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 */
45 #include <sys/param.h>
46 #include <sys/mount.h>
49 #ifdef HAVE_SYS_STATVFS_H
50 #include <sys/statvfs.h>
54 #include <glib/gstdio.h>
57 #include <glibmm/threads.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/pathscanner.h"
73 #include "pbd/pthread_utils.h"
74 #include "pbd/stacktrace.h"
75 #include "pbd/convert.h"
76 #include "pbd/clear_dir.h"
78 #include "ardour/amp.h"
79 #include "ardour/audio_diskstream.h"
80 #include "ardour/audio_track.h"
81 #include "ardour/audioengine.h"
82 #include "ardour/audiofilesource.h"
83 #include "ardour/audioregion.h"
84 #include "ardour/automation_control.h"
85 #include "ardour/butler.h"
86 #include "ardour/control_protocol_manager.h"
87 #include "ardour/directory_names.h"
88 #include "ardour/filename_extensions.h"
89 #include "ardour/graph.h"
90 #include "ardour/location.h"
91 #include "ardour/midi_model.h"
92 #include "ardour/midi_patch_manager.h"
93 #include "ardour/midi_region.h"
94 #include "ardour/midi_source.h"
95 #include "ardour/midi_track.h"
96 #include "ardour/pannable.h"
97 #include "ardour/playlist_factory.h"
98 #include "ardour/port.h"
99 #include "ardour/processor.h"
100 #include "ardour/proxy_controllable.h"
101 #include "ardour/recent_sessions.h"
102 #include "ardour/region_factory.h"
103 #include "ardour/route_group.h"
104 #include "ardour/send.h"
105 #include "ardour/session.h"
106 #include "ardour/session_directory.h"
107 #include "ardour/session_metadata.h"
108 #include "ardour/session_playlists.h"
109 #include "ardour/session_state_utils.h"
110 #include "ardour/silentfilesource.h"
111 #include "ardour/sndfilesource.h"
112 #include "ardour/source_factory.h"
113 #include "ardour/speakers.h"
114 #include "ardour/template_utils.h"
115 #include "ardour/tempo.h"
116 #include "ardour/ticker.h"
117 #include "ardour/user_bundle.h"
119 #include "control_protocol/control_protocol.h"
125 using namespace ARDOUR;
128 /** @param snapshot_name Snapshot name, without the .ardour prefix */
130 Session::first_stage_init (string fullpath, string /*snapshot_name*/)
132 /* finish initialization that can't be done in a normal C++ constructor
136 timerclear (&last_mmc_step);
137 g_atomic_int_set (&processing_prohibited, 0);
138 g_atomic_int_set (&_record_status, Disabled);
139 g_atomic_int_set (&_playback_load, 100);
140 g_atomic_int_set (&_capture_load, 100);
142 _all_route_group->set_active (true, this);
143 interpolation.add_channel_to (0, 0);
145 if (config.get_use_video_sync()) {
146 waiting_for_sync_offset = true;
148 waiting_for_sync_offset = false;
151 last_rr_session_dir = session_dirs.begin();
153 set_history_depth (Config->get_history_depth());
155 if (how_many_dsp_threads () > 1) {
156 /* For now, only create the graph if we are using >1 DSP threads, as
157 it is a bit slower than the old code with 1 thread.
159 _process_graph.reset (new Graph (*this));
162 /* default: assume simple stereo speaker configuration */
164 _speakers->setup_default_speakers (2);
166 _solo_cut_control.reset (new ProxyControllable (_("solo cut control (dB)"), PBD::Controllable::GainLike,
167 boost::bind (&RCConfiguration::set_solo_mute_gain, Config, _1),
168 boost::bind (&RCConfiguration::get_solo_mute_gain, Config)));
169 add_controllable (_solo_cut_control);
171 /* discover canonical fullpath */
173 if (fullpath.length() == 0) {
175 throw failed_constructor();
178 char buf[PATH_MAX+1];
179 if (!realpath (fullpath.c_str(), buf) && (errno != ENOENT)) {
180 error << string_compose(_("Could not use path %1 (%2)"), buf, strerror(errno)) << endmsg;
182 throw failed_constructor();
187 /* we require _path to end with a dir separator */
189 if (_path[_path.length()-1] != G_DIR_SEPARATOR) {
190 _path += G_DIR_SEPARATOR;
195 _is_new = !Glib::file_test (_path, Glib::FileTest (G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR));
197 /* These are all static "per-class" signals */
199 SourceFactory::SourceCreated.connect_same_thread (*this, boost::bind (&Session::add_source, this, _1));
200 PlaylistFactory::PlaylistCreated.connect_same_thread (*this, boost::bind (&Session::add_playlist, this, _1, _2));
201 AutomationList::AutomationListCreated.connect_same_thread (*this, boost::bind (&Session::add_automation_list, this, _1));
202 Controllable::Destroyed.connect_same_thread (*this, boost::bind (&Session::remove_controllable, this, _1));
203 IO::PortCountChanged.connect_same_thread (*this, boost::bind (&Session::ensure_buffers, this, _1));
205 /* stop IO objects from doing stuff until we're ready for them */
207 Delivery::disable_panners ();
208 IO::disable_connecting ();
212 n_physical_outputs = _engine.n_physical_outputs ();
213 n_physical_inputs = _engine.n_physical_inputs ();
215 _current_frame_rate = _engine.sample_rate ();
216 _nominal_frame_rate = _current_frame_rate;
217 _base_frame_rate = _current_frame_rate;
219 _midi_ports = new MidiPortManager;
220 _mmc = new MIDI::MachineControl;
222 _mmc->set_ports (_midi_ports->mmc_input_port(), _midi_ports->mmc_output_port());
224 _tempo_map = new TempoMap (_current_frame_rate);
225 _tempo_map->PropertyChanged.connect_same_thread (*this, boost::bind (&Session::tempo_map_changed, this, _1));
227 AudioDiskstream::allocate_working_buffers();
229 SndFileSource::setup_standard_crossfades (*this, frame_rate());
230 _engine.GraphReordered.connect_same_thread (*this, boost::bind (&Session::graph_reordered, this));
232 refresh_disk_space ();
237 Session::second_stage_init ()
239 AudioFileSource::set_peak_dir (_session_dir->peak_path());
241 if (_butler->start_thread()) {
245 if (start_midi_thread ()) {
249 setup_midi_machine_control ();
251 // set_state() will call setup_raid_path(), but if it's a new session we need
252 // to call setup_raid_path() here.
255 if (set_state (*state_tree->root(), Stateful::loading_state_version)) {
259 setup_raid_path(_path);
262 /* we can't save till after ::when_engine_running() is called,
263 because otherwise we save state with no connections made.
264 therefore, we reset _state_of_the_state because ::set_state()
265 will have cleared it.
267 we also have to include Loading so that any events that get
268 generated between here and the end of ::when_engine_running()
269 will be processed directly rather than queued.
272 _state_of_the_state = StateOfTheState (_state_of_the_state|CannotSave|Loading);
274 _locations->changed.connect_same_thread (*this, boost::bind (&Session::locations_changed, this));
275 _locations->added.connect_same_thread (*this, boost::bind (&Session::locations_added, this, _1));
276 setup_click_sounds (0);
277 setup_midi_control ();
279 /* Pay attention ... */
281 _engine.Halted.connect_same_thread (*this, boost::bind (&Session::engine_halted, this));
282 _engine.Xrun.connect_same_thread (*this, boost::bind (&Session::xrun_recovery, this));
284 midi_clock = new MidiClockTicker ();
285 midi_clock->set_session (this);
288 when_engine_running ();
291 /* handle this one in a different way than all others, so that its clear what happened */
293 catch (AudioEngine::PortRegistrationFailure& err) {
294 error << err.what() << endmsg;
302 BootMessage (_("Reset Remote Controls"));
304 // send_full_time_code (0);
305 _engine.transport_locate (0);
307 _mmc->send (MIDI::MachineControlCommand (MIDI::MachineControl::cmdMmcReset));
308 _mmc->send (MIDI::MachineControlCommand (Timecode::Time ()));
310 MIDI::Name::MidiPatchManager::instance().set_session (this);
313 /* initial program change will be delivered later; see ::config_changed() */
315 _state_of_the_state = Clean;
317 Port::set_connecting_blocked (false);
319 DirtyChanged (); /* EMIT SIGNAL */
321 if (state_was_pending) {
322 save_state (_current_snapshot_name);
323 remove_pending_capture_state ();
324 state_was_pending = false;
327 BootMessage (_("Session loading complete"));
333 Session::raid_path () const
335 SearchPath raid_search_path;
337 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
338 raid_search_path += (*i).path;
341 return raid_search_path.to_string ();
345 Session::setup_raid_path (string path)
354 session_dirs.clear ();
356 SearchPath search_path(path);
357 SearchPath sound_search_path;
358 SearchPath midi_search_path;
360 for (SearchPath::const_iterator i = search_path.begin(); i != search_path.end(); ++i) {
362 sp.blocks = 0; // not needed
363 session_dirs.push_back (sp);
365 SessionDirectory sdir(sp.path);
367 sound_search_path += sdir.sound_path ();
368 midi_search_path += sdir.midi_path ();
371 // reset the round-robin soundfile path thingie
372 last_rr_session_dir = session_dirs.begin();
376 Session::path_is_within_session (const std::string& path)
378 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
379 if (PBD::path_is_within (i->path, path)) {
387 Session::ensure_subdirs ()
391 dir = session_directory().peak_path();
393 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
394 error << string_compose(_("Session: cannot create session peakfile folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
398 dir = session_directory().sound_path();
400 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
401 error << string_compose(_("Session: cannot create session sounds dir \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
405 dir = session_directory().midi_path();
407 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
408 error << string_compose(_("Session: cannot create session midi dir \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
412 dir = session_directory().dead_path();
414 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
415 error << string_compose(_("Session: cannot create session dead sounds folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
419 dir = session_directory().export_path();
421 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
422 error << string_compose(_("Session: cannot create session export folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
426 dir = analysis_dir ();
428 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
429 error << string_compose(_("Session: cannot create session analysis folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
433 dir = plugins_dir ();
435 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
436 error << string_compose(_("Session: cannot create session plugins folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
440 dir = externals_dir ();
442 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
443 error << string_compose(_("Session: cannot create session externals folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
450 /** @param session_template directory containing session template, or empty.
451 * Caller must not hold process lock.
454 Session::create (const string& session_template, BusProfile* bus_profile)
456 if (g_mkdir_with_parents (_path.c_str(), 0755) < 0) {
457 error << string_compose(_("Session: cannot create session folder \"%1\" (%2)"), _path, strerror (errno)) << endmsg;
461 if (ensure_subdirs ()) {
465 _writable = exists_and_writable (_path);
467 if (!session_template.empty()) {
468 std::string in_path = session_template_dir_to_file (session_template);
470 ifstream in(in_path.c_str());
473 string out_path = _path;
475 out_path += statefile_suffix;
477 ofstream out(out_path.c_str());
483 /* Copy plugin state files from template to new session */
484 std::string template_plugins = Glib::build_filename (session_template, X_("plugins"));
485 copy_files (template_plugins, plugins_dir ());
490 error << string_compose (_("Could not open %1 for writing session template"), out_path)
496 error << string_compose (_("Could not open session template %1 for reading"), in_path)
503 /* set initial start + end point */
505 _state_of_the_state = Clean;
507 /* set up Master Out and Control Out if necessary */
512 ChanCount count(DataType::AUDIO, bus_profile->master_out_channels);
514 if (bus_profile->master_out_channels) {
515 boost::shared_ptr<Route> r (new Route (*this, _("master"), Route::MasterOut, DataType::AUDIO));
519 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
520 // boost_debug_shared_ptr_mark_interesting (r.get(), "Route");
523 Glib::Threads::Mutex::Lock lm (AudioEngine::instance()->process_lock ());
524 r->input()->ensure_io (count, false, this);
525 r->output()->ensure_io (count, false, this);
531 /* prohibit auto-connect to master, because there isn't one */
532 bus_profile->output_ac = AutoConnectOption (bus_profile->output_ac & ~AutoConnectMaster);
536 add_routes (rl, false, false, false);
539 /* this allows the user to override settings with an environment variable.
542 if (no_auto_connect()) {
543 bus_profile->input_ac = AutoConnectOption (0);
544 bus_profile->output_ac = AutoConnectOption (0);
547 Config->set_input_auto_connect (bus_profile->input_ac);
548 Config->set_output_auto_connect (bus_profile->output_ac);
551 if (Config->get_use_monitor_bus() && bus_profile) {
552 add_monitor_section ();
561 Session::maybe_write_autosave()
563 if (dirty() && record_status() != Recording) {
564 save_state("", true);
569 Session::remove_pending_capture_state ()
571 std::string pending_state_file_path(_session_dir->root_path());
573 pending_state_file_path = Glib::build_filename (pending_state_file_path, legalize_for_path (_current_snapshot_name) + pending_suffix);
575 if (!Glib::file_test (pending_state_file_path, Glib::FILE_TEST_EXISTS)) return;
577 if (g_remove (pending_state_file_path.c_str()) != 0) {
578 error << string_compose(_("Could not remove pending capture state at path \"%1\" (%2)"),
579 pending_state_file_path, g_strerror (errno)) << endmsg;
583 /** Rename a state file.
584 * @param old_name Old snapshot name.
585 * @param new_name New snapshot name.
588 Session::rename_state (string old_name, string new_name)
590 if (old_name == _current_snapshot_name || old_name == _name) {
591 /* refuse to rename the current snapshot or the "main" one */
595 const string old_xml_filename = legalize_for_path (old_name) + statefile_suffix;
596 const string new_xml_filename = legalize_for_path (new_name) + statefile_suffix;
598 const std::string old_xml_path(Glib::build_filename (_session_dir->root_path(), old_xml_filename));
599 const std::string new_xml_path(Glib::build_filename (_session_dir->root_path(), new_xml_filename));
601 if (::g_rename (old_xml_path.c_str(), new_xml_path.c_str()) != 0) {
602 error << string_compose(_("could not rename snapshot %1 to %2 (%3)"),
603 old_name, new_name, g_strerror(errno)) << endmsg;
607 /** Remove a state file.
608 * @param snapshot_name Snapshot name.
611 Session::remove_state (string snapshot_name)
613 if (!_writable || snapshot_name == _current_snapshot_name || snapshot_name == _name) {
614 // refuse to remove the current snapshot or the "main" one
618 std::string xml_path(_session_dir->root_path());
620 xml_path = Glib::build_filename (xml_path, legalize_for_path (snapshot_name) + statefile_suffix);
622 if (!create_backup_file (xml_path)) {
623 // don't remove it if a backup can't be made
624 // create_backup_file will log the error.
629 if (g_remove (xml_path.c_str()) != 0) {
630 error << string_compose(_("Could not remove session file at path \"%1\" (%2)"),
631 xml_path, g_strerror (errno)) << endmsg;
635 /** @param snapshot_name Name to save under, without .ardour / .pending prefix */
637 Session::save_state (string snapshot_name, bool pending, bool switch_to_snapshot)
640 std::string xml_path(_session_dir->root_path());
642 if (!_writable || (_state_of_the_state & CannotSave)) {
646 if (!_engine.connected ()) {
647 error << string_compose (_("the %1 audio engine is not connected and state saving would lose all I/O connections. Session not saved"),
653 /* tell sources we're saving first, in case they write out to a new file
654 * which should be saved with the state rather than the old one */
655 for (SourceMap::const_iterator i = sources.begin(); i != sources.end(); ++i) {
657 i->second->session_saved();
658 } catch (Evoral::SMF::FileError& e) {
659 error << string_compose ("Could not write to MIDI file %1; MIDI data not saved.", e.file_name ()) << endmsg;
663 SaveSession (); /* EMIT SIGNAL */
665 tree.set_root (&get_state());
667 if (snapshot_name.empty()) {
668 snapshot_name = _current_snapshot_name;
669 } else if (switch_to_snapshot) {
670 _current_snapshot_name = snapshot_name;
675 /* proper save: use statefile_suffix (.ardour in English) */
677 xml_path = Glib::build_filename (xml_path, legalize_for_path (snapshot_name) + statefile_suffix);
679 /* make a backup copy of the old file */
681 if (Glib::file_test (xml_path, Glib::FILE_TEST_EXISTS) && !create_backup_file (xml_path)) {
682 // create_backup_file will log the error
688 /* pending save: use pending_suffix (.pending in English) */
689 xml_path = Glib::build_filename (xml_path, legalize_for_path (snapshot_name) + pending_suffix);
692 std::string tmp_path(_session_dir->root_path());
693 tmp_path = Glib::build_filename (tmp_path, legalize_for_path (snapshot_name) + temp_suffix);
695 // cerr << "actually writing state to " << xml_path << endl;
697 if (!tree.write (tmp_path)) {
698 error << string_compose (_("state could not be saved to %1"), tmp_path) << endmsg;
699 if (g_remove (tmp_path.c_str()) != 0) {
700 error << string_compose(_("Could not remove temporary session file at path \"%1\" (%2)"),
701 tmp_path, g_strerror (errno)) << endmsg;
707 if (::rename (tmp_path.c_str(), xml_path.c_str()) != 0) {
708 error << string_compose (_("could not rename temporary session file %1 to %2"),
709 tmp_path, xml_path) << endmsg;
710 if (g_remove (tmp_path.c_str()) != 0) {
711 error << string_compose(_("Could not remove temporary session file at path \"%1\" (%2)"),
712 tmp_path, g_strerror (errno)) << endmsg;
720 save_history (snapshot_name);
722 bool was_dirty = dirty();
724 _state_of_the_state = StateOfTheState (_state_of_the_state & ~Dirty);
727 DirtyChanged (); /* EMIT SIGNAL */
730 StateSaved (snapshot_name); /* EMIT SIGNAL */
737 Session::restore_state (string snapshot_name)
739 if (load_state (snapshot_name) == 0) {
740 set_state (*state_tree->root(), Stateful::loading_state_version);
747 Session::load_state (string snapshot_name)
752 state_was_pending = false;
754 /* check for leftover pending state from a crashed capture attempt */
756 std::string xmlpath(_session_dir->root_path());
757 xmlpath = Glib::build_filename (xmlpath, legalize_for_path (snapshot_name) + pending_suffix);
759 if (Glib::file_test (xmlpath, Glib::FILE_TEST_EXISTS)) {
761 /* there is pending state from a crashed capture attempt */
763 boost::optional<int> r = AskAboutPendingState();
764 if (r.get_value_or (1)) {
765 state_was_pending = true;
769 if (!state_was_pending) {
770 xmlpath = Glib::build_filename (_session_dir->root_path(), snapshot_name);
773 if (!Glib::file_test (xmlpath, Glib::FILE_TEST_EXISTS)) {
774 xmlpath = Glib::build_filename (_session_dir->root_path(), legalize_for_path (snapshot_name) + statefile_suffix);
775 if (!Glib::file_test (xmlpath, Glib::FILE_TEST_EXISTS)) {
776 error << string_compose(_("%1: session file \"%2\" doesn't exist!"), _name, xmlpath) << endmsg;
781 state_tree = new XMLTree;
785 _writable = exists_and_writable (xmlpath);
787 if (!state_tree->read (xmlpath)) {
788 error << string_compose(_("Could not understand session file %1"), xmlpath) << endmsg;
794 XMLNode& root (*state_tree->root());
796 if (root.name() != X_("Session")) {
797 error << string_compose (_("Session file %1 is not a session"), xmlpath) << endmsg;
803 const XMLProperty* prop;
805 if ((prop = root.property ("version")) == 0) {
806 /* no version implies very old version of Ardour */
807 Stateful::loading_state_version = 1000;
809 if (prop->value().find ('.') != string::npos) {
810 /* old school version format */
811 if (prop->value()[0] == '2') {
812 Stateful::loading_state_version = 2000;
814 Stateful::loading_state_version = 3000;
817 Stateful::loading_state_version = atoi (prop->value());
821 if (Stateful::loading_state_version < CURRENT_SESSION_FILE_VERSION && _writable) {
823 std::string backup_path(_session_dir->root_path());
824 std::string backup_filename = string_compose ("%1-%2%3", legalize_for_path (snapshot_name), Stateful::loading_state_version, statefile_suffix);
825 backup_path = Glib::build_filename (backup_path, backup_filename);
827 // only create a backup for a given statefile version once
829 if (!Glib::file_test (backup_path, Glib::FILE_TEST_EXISTS)) {
831 VersionMismatch (xmlpath, backup_path);
833 if (!copy_file (xmlpath, backup_path)) {;
843 Session::load_options (const XMLNode& node)
845 LocaleGuard lg (X_("POSIX"));
846 config.set_variables (node);
857 Session::get_template()
859 /* if we don't disable rec-enable, diskstreams
860 will believe they need to store their capture
861 sources in their state node.
864 disable_record (false);
870 Session::state (bool full_state)
872 XMLNode* node = new XMLNode("Session");
876 snprintf(buf, sizeof(buf), "%d", CURRENT_SESSION_FILE_VERSION);
877 node->add_property("version", buf);
879 /* store configuration settings */
883 node->add_property ("name", _name);
884 snprintf (buf, sizeof (buf), "%" PRId64, _nominal_frame_rate);
885 node->add_property ("sample-rate", buf);
887 if (session_dirs.size() > 1) {
891 vector<space_and_path>::iterator i = session_dirs.begin();
892 vector<space_and_path>::iterator next;
894 ++i; /* skip the first one */
898 while (i != session_dirs.end()) {
902 if (next != session_dirs.end()) {
912 child = node->add_child ("Path");
913 child->add_content (p);
917 /* save the ID counter */
919 snprintf (buf, sizeof (buf), "%" PRIu64, ID::counter());
920 node->add_property ("id-counter", buf);
922 /* save the event ID counter */
924 snprintf (buf, sizeof (buf), "%d", Evoral::event_id_counter());
925 node->add_property ("event-counter", buf);
927 /* various options */
929 list<XMLNode*> midi_port_nodes = _midi_ports->get_midi_port_states();
930 if (!midi_port_nodes.empty()) {
931 XMLNode* midi_port_stuff = new XMLNode ("MIDIPorts");
932 for (list<XMLNode*>::const_iterator n = midi_port_nodes.begin(); n != midi_port_nodes.end(); ++n) {
933 midi_port_stuff->add_child_nocopy (**n);
935 node->add_child_nocopy (*midi_port_stuff);
938 node->add_child_nocopy (config.get_variables ());
940 node->add_child_nocopy (ARDOUR::SessionMetadata::Metadata()->get_state());
942 child = node->add_child ("Sources");
945 Glib::Threads::Mutex::Lock sl (source_lock);
947 for (SourceMap::iterator siter = sources.begin(); siter != sources.end(); ++siter) {
949 /* Don't save information about non-file Sources, or
950 * about non-destructive file sources that are empty
951 * and unused by any regions.
954 boost::shared_ptr<FileSource> fs;
956 if ((fs = boost::dynamic_pointer_cast<FileSource> (siter->second)) != 0) {
958 if (!fs->destructive()) {
959 if (fs->empty() && !fs->used()) {
964 child->add_child_nocopy (siter->second->get_state());
969 child = node->add_child ("Regions");
972 Glib::Threads::Mutex::Lock rl (region_lock);
973 const RegionFactory::RegionMap& region_map (RegionFactory::all_regions());
974 for (RegionFactory::RegionMap::const_iterator i = region_map.begin(); i != region_map.end(); ++i) {
975 boost::shared_ptr<Region> r = i->second;
976 /* only store regions not attached to playlists */
977 if (r->playlist() == 0) {
978 if (boost::dynamic_pointer_cast<AudioRegion>(r)) {
979 child->add_child_nocopy ((boost::dynamic_pointer_cast<AudioRegion>(r))->get_basic_state ());
981 child->add_child_nocopy (r->get_state ());
986 RegionFactory::CompoundAssociations& cassocs (RegionFactory::compound_associations());
988 if (!cassocs.empty()) {
989 XMLNode* ca = node->add_child (X_("CompoundAssociations"));
991 for (RegionFactory::CompoundAssociations::iterator i = cassocs.begin(); i != cassocs.end(); ++i) {
993 XMLNode* can = new XMLNode (X_("CompoundAssociation"));
994 i->first->id().print (buf, sizeof (buf));
995 can->add_property (X_("copy"), buf);
996 i->second->id().print (buf, sizeof (buf));
997 can->add_property (X_("original"), buf);
998 ca->add_child_nocopy (*can);
1004 node->add_child_nocopy (_locations->get_state());
1006 // for a template, just create a new Locations, populate it
1007 // with the default start and end, and get the state for that.
1008 Locations loc (*this);
1009 Location* range = new Location (*this, 0, 0, _("session"), Location::IsSessionRange);
1010 range->set (max_framepos, 0);
1012 node->add_child_nocopy (loc.get_state());
1015 child = node->add_child ("Bundles");
1017 boost::shared_ptr<BundleList> bundles = _bundles.reader ();
1018 for (BundleList::iterator i = bundles->begin(); i != bundles->end(); ++i) {
1019 boost::shared_ptr<UserBundle> b = boost::dynamic_pointer_cast<UserBundle> (*i);
1021 child->add_child_nocopy (b->get_state());
1026 child = node->add_child ("Routes");
1028 boost::shared_ptr<RouteList> r = routes.reader ();
1030 RoutePublicOrderSorter cmp;
1031 RouteList public_order (*r);
1032 public_order.sort (cmp);
1034 /* the sort should have put control outs first */
1037 assert (_monitor_out == public_order.front());
1040 for (RouteList::iterator i = public_order.begin(); i != public_order.end(); ++i) {
1041 if (!(*i)->is_auditioner()) {
1043 child->add_child_nocopy ((*i)->get_state());
1045 child->add_child_nocopy ((*i)->get_template());
1051 playlists->add_state (node, full_state);
1053 child = node->add_child ("RouteGroups");
1054 for (list<RouteGroup *>::iterator i = _route_groups.begin(); i != _route_groups.end(); ++i) {
1055 child->add_child_nocopy ((*i)->get_state());
1059 XMLNode* gain_child = node->add_child ("Click");
1060 gain_child->add_child_nocopy (_click_io->state (full_state));
1061 gain_child->add_child_nocopy (_click_gain->state (full_state));
1065 XMLNode* ltc_input_child = node->add_child ("LTC-In");
1066 ltc_input_child->add_child_nocopy (_ltc_input->state (full_state));
1070 XMLNode* ltc_output_child = node->add_child ("LTC-Out");
1071 ltc_output_child->add_child_nocopy (_ltc_output->state (full_state));
1074 node->add_child_nocopy (_speakers->get_state());
1075 node->add_child_nocopy (_tempo_map->get_state());
1076 node->add_child_nocopy (get_control_protocol_state());
1079 node->add_child_copy (*_extra_xml);
1086 Session::get_control_protocol_state ()
1088 ControlProtocolManager& cpm (ControlProtocolManager::instance());
1089 return cpm.get_state();
1093 Session::set_state (const XMLNode& node, int version)
1097 const XMLProperty* prop;
1100 _state_of_the_state = StateOfTheState (_state_of_the_state|CannotSave);
1102 if (node.name() != X_("Session")) {
1103 fatal << _("programming error: Session: incorrect XML node sent to set_state()") << endmsg;
1107 if ((prop = node.property ("name")) != 0) {
1108 _name = prop->value ();
1111 if ((prop = node.property (X_("sample-rate"))) != 0) {
1113 _nominal_frame_rate = atoi (prop->value());
1115 if (_nominal_frame_rate != _current_frame_rate) {
1116 boost::optional<int> r = AskAboutSampleRateMismatch (_nominal_frame_rate, _current_frame_rate);
1117 if (r.get_value_or (0)) {
1123 setup_raid_path(_session_dir->root_path());
1125 if ((prop = node.property (X_("id-counter"))) != 0) {
1127 sscanf (prop->value().c_str(), "%" PRIu64, &x);
1128 ID::init_counter (x);
1130 /* old sessions used a timebased counter, so fake
1131 the startup ID counter based on a standard
1136 ID::init_counter (now);
1139 if ((prop = node.property (X_("event-counter"))) != 0) {
1140 Evoral::init_event_id_counter (atoi (prop->value()));
1144 if ((child = find_named_node (node, "MIDIPorts")) != 0) {
1145 _midi_ports->set_midi_port_states (child->children());
1148 IO::disable_connecting ();
1150 Stateful::save_extra_xml (node);
1152 if (((child = find_named_node (node, "Options")) != 0)) { /* old style */
1153 load_options (*child);
1154 } else if ((child = find_named_node (node, "Config")) != 0) { /* new style */
1155 load_options (*child);
1157 error << _("Session: XML state has no options section") << endmsg;
1160 if (version >= 3000) {
1161 if ((child = find_named_node (node, "Metadata")) == 0) {
1162 warning << _("Session: XML state has no metadata section") << endmsg;
1163 } else if ( ARDOUR::SessionMetadata::Metadata()->set_state (*child, version) ) {
1168 if ((child = find_named_node (node, X_("Speakers"))) != 0) {
1169 _speakers->set_state (*child, version);
1172 if ((child = find_named_node (node, "Sources")) == 0) {
1173 error << _("Session: XML state has no sources section") << endmsg;
1175 } else if (load_sources (*child)) {
1179 if ((child = find_named_node (node, "TempoMap")) == 0) {
1180 error << _("Session: XML state has no Tempo Map section") << endmsg;
1182 } else if (_tempo_map->set_state (*child, version)) {
1186 if ((child = find_named_node (node, "Locations")) == 0) {
1187 error << _("Session: XML state has no locations section") << endmsg;
1189 } else if (_locations->set_state (*child, version)) {
1195 if ((location = _locations->auto_loop_location()) != 0) {
1196 set_auto_loop_location (location);
1199 if ((location = _locations->auto_punch_location()) != 0) {
1200 set_auto_punch_location (location);
1203 if ((location = _locations->session_range_location()) != 0) {
1204 delete _session_range_location;
1205 _session_range_location = location;
1208 if (_session_range_location) {
1209 AudioFileSource::set_header_position_offset (_session_range_location->start());
1212 if ((child = find_named_node (node, "Regions")) == 0) {
1213 error << _("Session: XML state has no Regions section") << endmsg;
1215 } else if (load_regions (*child)) {
1219 if ((child = find_named_node (node, "Playlists")) == 0) {
1220 error << _("Session: XML state has no playlists section") << endmsg;
1222 } else if (playlists->load (*this, *child)) {
1226 if ((child = find_named_node (node, "UnusedPlaylists")) == 0) {
1228 } else if (playlists->load_unused (*this, *child)) {
1232 if ((child = find_named_node (node, "CompoundAssociations")) != 0) {
1233 if (load_compounds (*child)) {
1238 if (version >= 3000) {
1239 if ((child = find_named_node (node, "Bundles")) == 0) {
1240 warning << _("Session: XML state has no bundles section") << endmsg;
1243 /* We can't load Bundles yet as they need to be able
1244 to convert from port names to Port objects, which can't happen until
1246 _bundle_xml_node = new XMLNode (*child);
1250 if (version < 3000) {
1251 if ((child = find_named_node (node, X_("DiskStreams"))) == 0) {
1252 error << _("Session: XML state has no diskstreams section") << endmsg;
1254 } else if (load_diskstreams_2X (*child, version)) {
1259 if ((child = find_named_node (node, "Routes")) == 0) {
1260 error << _("Session: XML state has no routes section") << endmsg;
1262 } else if (load_routes (*child, version)) {
1266 /* our diskstreams list is no longer needed as they are now all owned by their Route */
1267 _diskstreams_2X.clear ();
1269 if (version >= 3000) {
1271 if ((child = find_named_node (node, "RouteGroups")) == 0) {
1272 error << _("Session: XML state has no route groups section") << endmsg;
1274 } else if (load_route_groups (*child, version)) {
1278 } else if (version < 3000) {
1280 if ((child = find_named_node (node, "EditGroups")) == 0) {
1281 error << _("Session: XML state has no edit groups section") << endmsg;
1283 } else if (load_route_groups (*child, version)) {
1287 if ((child = find_named_node (node, "MixGroups")) == 0) {
1288 error << _("Session: XML state has no mix groups section") << endmsg;
1290 } else if (load_route_groups (*child, version)) {
1295 if ((child = find_named_node (node, "Click")) == 0) {
1296 warning << _("Session: XML state has no click section") << endmsg;
1297 } else if (_click_io) {
1298 const XMLNodeList& children (child->children());
1299 XMLNodeList::const_iterator i = children.begin();
1300 _click_io->set_state (**i, version);
1302 if (i != children.end()) {
1303 _click_gain->set_state (**i, version);
1307 if ((child = find_named_node (node, ControlProtocolManager::state_node_name)) != 0) {
1308 ControlProtocolManager::instance().set_state (*child, version);
1311 update_have_rec_enabled_track ();
1313 /* here beginneth the second phase ... */
1315 StateReady (); /* EMIT SIGNAL */
1324 Session::load_routes (const XMLNode& node, int version)
1327 XMLNodeConstIterator niter;
1328 RouteList new_routes;
1330 nlist = node.children();
1334 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1336 boost::shared_ptr<Route> route;
1337 if (version < 3000) {
1338 route = XMLRouteFactory_2X (**niter, version);
1340 route = XMLRouteFactory (**niter, version);
1344 error << _("Session: cannot create Route from XML description.") << endmsg;
1348 BootMessage (string_compose (_("Loaded track/bus %1"), route->name()));
1350 new_routes.push_back (route);
1353 add_routes (new_routes, false, false, false);
1358 boost::shared_ptr<Route>
1359 Session::XMLRouteFactory (const XMLNode& node, int version)
1361 boost::shared_ptr<Route> ret;
1363 if (node.name() != "Route") {
1367 XMLNode* ds_child = find_named_node (node, X_("Diskstream"));
1369 DataType type = DataType::AUDIO;
1370 const XMLProperty* prop = node.property("default-type");
1373 type = DataType (prop->value());
1376 assert (type != DataType::NIL);
1380 boost::shared_ptr<Track> track;
1382 if (type == DataType::AUDIO) {
1383 track.reset (new AudioTrack (*this, X_("toBeResetFroXML")));
1385 track.reset (new MidiTrack (*this, X_("toBeResetFroXML")));
1388 if (track->init()) {
1392 if (track->set_state (node, version)) {
1396 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
1397 // boost_debug_shared_ptr_mark_interesting (track.get(), "Track");
1402 boost::shared_ptr<Route> r (new Route (*this, X_("toBeResetFroXML")));
1404 if (r->init () == 0 && r->set_state (node, version) == 0) {
1405 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
1406 // boost_debug_shared_ptr_mark_interesting (r.get(), "Route");
1415 boost::shared_ptr<Route>
1416 Session::XMLRouteFactory_2X (const XMLNode& node, int version)
1418 boost::shared_ptr<Route> ret;
1420 if (node.name() != "Route") {
1424 XMLProperty const * ds_prop = node.property (X_("diskstream-id"));
1426 ds_prop = node.property (X_("diskstream"));
1429 DataType type = DataType::AUDIO;
1430 const XMLProperty* prop = node.property("default-type");
1433 type = DataType (prop->value());
1436 assert (type != DataType::NIL);
1440 list<boost::shared_ptr<Diskstream> >::iterator i = _diskstreams_2X.begin ();
1441 while (i != _diskstreams_2X.end() && (*i)->id() != ds_prop->value()) {
1445 if (i == _diskstreams_2X.end()) {
1446 error << _("Could not find diskstream for route") << endmsg;
1447 return boost::shared_ptr<Route> ();
1450 boost::shared_ptr<Track> track;
1452 if (type == DataType::AUDIO) {
1453 track.reset (new AudioTrack (*this, X_("toBeResetFroXML")));
1455 track.reset (new MidiTrack (*this, X_("toBeResetFroXML")));
1458 if (track->init()) {
1462 if (track->set_state (node, version)) {
1466 track->set_diskstream (*i);
1468 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
1469 // boost_debug_shared_ptr_mark_interesting (track.get(), "Track");
1474 boost::shared_ptr<Route> r (new Route (*this, X_("toBeResetFroXML")));
1476 if (r->init () == 0 && r->set_state (node, version) == 0) {
1477 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
1478 // boost_debug_shared_ptr_mark_interesting (r.get(), "Route");
1488 Session::load_regions (const XMLNode& node)
1491 XMLNodeConstIterator niter;
1492 boost::shared_ptr<Region> region;
1494 nlist = node.children();
1498 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1499 if ((region = XMLRegionFactory (**niter, false)) == 0) {
1500 error << _("Session: cannot create Region from XML description.");
1501 const XMLProperty *name = (**niter).property("name");
1504 error << " " << string_compose (_("Can not load state for region '%1'"), name->value());
1515 Session::load_compounds (const XMLNode& node)
1517 XMLNodeList calist = node.children();
1518 XMLNodeConstIterator caiter;
1519 XMLProperty *caprop;
1521 for (caiter = calist.begin(); caiter != calist.end(); ++caiter) {
1522 XMLNode* ca = *caiter;
1526 if ((caprop = ca->property (X_("original"))) == 0) {
1529 orig_id = caprop->value();
1531 if ((caprop = ca->property (X_("copy"))) == 0) {
1534 copy_id = caprop->value();
1536 boost::shared_ptr<Region> orig = RegionFactory::region_by_id (orig_id);
1537 boost::shared_ptr<Region> copy = RegionFactory::region_by_id (copy_id);
1539 if (!orig || !copy) {
1540 warning << string_compose (_("Regions in compound description not found (ID's %1 and %2): ignored"),
1546 RegionFactory::add_compound_association (orig, copy);
1553 Session::load_nested_sources (const XMLNode& node)
1556 XMLNodeConstIterator niter;
1558 nlist = node.children();
1560 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1561 if ((*niter)->name() == "Source") {
1563 /* it may already exist, so don't recreate it unnecessarily
1566 XMLProperty* prop = (*niter)->property (X_("id"));
1568 error << _("Nested source has no ID info in session file! (ignored)") << endmsg;
1572 ID source_id (prop->value());
1574 if (!source_by_id (source_id)) {
1577 SourceFactory::create (*this, **niter, true);
1579 catch (failed_constructor& err) {
1580 error << string_compose (_("Cannot reconstruct nested source for region %1"), name()) << endmsg;
1587 boost::shared_ptr<Region>
1588 Session::XMLRegionFactory (const XMLNode& node, bool full)
1590 const XMLProperty* type = node.property("type");
1594 const XMLNodeList& nlist = node.children();
1596 for (XMLNodeConstIterator niter = nlist.begin(); niter != nlist.end(); ++niter) {
1597 XMLNode *child = (*niter);
1598 if (child->name() == "NestedSource") {
1599 load_nested_sources (*child);
1603 if (!type || type->value() == "audio") {
1604 return boost::shared_ptr<Region>(XMLAudioRegionFactory (node, full));
1605 } else if (type->value() == "midi") {
1606 return boost::shared_ptr<Region>(XMLMidiRegionFactory (node, full));
1609 } catch (failed_constructor& err) {
1610 return boost::shared_ptr<Region> ();
1613 return boost::shared_ptr<Region> ();
1616 boost::shared_ptr<AudioRegion>
1617 Session::XMLAudioRegionFactory (const XMLNode& node, bool /*full*/)
1619 const XMLProperty* prop;
1620 boost::shared_ptr<Source> source;
1621 boost::shared_ptr<AudioSource> as;
1623 SourceList master_sources;
1624 uint32_t nchans = 1;
1627 if (node.name() != X_("Region")) {
1628 return boost::shared_ptr<AudioRegion>();
1631 if ((prop = node.property (X_("channels"))) != 0) {
1632 nchans = atoi (prop->value().c_str());
1635 if ((prop = node.property ("name")) == 0) {
1636 cerr << "no name for this region\n";
1640 if ((prop = node.property (X_("source-0"))) == 0) {
1641 if ((prop = node.property ("source")) == 0) {
1642 error << _("Session: XMLNode describing a AudioRegion is incomplete (no source)") << endmsg;
1643 return boost::shared_ptr<AudioRegion>();
1647 PBD::ID s_id (prop->value());
1649 if ((source = source_by_id (s_id)) == 0) {
1650 error << string_compose(_("Session: XMLNode describing a AudioRegion references an unknown source id =%1"), s_id) << endmsg;
1651 return boost::shared_ptr<AudioRegion>();
1654 as = boost::dynamic_pointer_cast<AudioSource>(source);
1656 error << string_compose(_("Session: XMLNode describing a AudioRegion references a non-audio source id =%1"), s_id) << endmsg;
1657 return boost::shared_ptr<AudioRegion>();
1660 sources.push_back (as);
1662 /* pickup other channels */
1664 for (uint32_t n=1; n < nchans; ++n) {
1665 snprintf (buf, sizeof(buf), X_("source-%d"), n);
1666 if ((prop = node.property (buf)) != 0) {
1668 PBD::ID id2 (prop->value());
1670 if ((source = source_by_id (id2)) == 0) {
1671 error << string_compose(_("Session: XMLNode describing a AudioRegion references an unknown source id =%1"), id2) << endmsg;
1672 return boost::shared_ptr<AudioRegion>();
1675 as = boost::dynamic_pointer_cast<AudioSource>(source);
1677 error << string_compose(_("Session: XMLNode describing a AudioRegion references a non-audio source id =%1"), id2) << endmsg;
1678 return boost::shared_ptr<AudioRegion>();
1680 sources.push_back (as);
1684 for (uint32_t n = 0; n < nchans; ++n) {
1685 snprintf (buf, sizeof(buf), X_("master-source-%d"), n);
1686 if ((prop = node.property (buf)) != 0) {
1688 PBD::ID id2 (prop->value());
1690 if ((source = source_by_id (id2)) == 0) {
1691 error << string_compose(_("Session: XMLNode describing a AudioRegion references an unknown source id =%1"), id2) << endmsg;
1692 return boost::shared_ptr<AudioRegion>();
1695 as = boost::dynamic_pointer_cast<AudioSource>(source);
1697 error << string_compose(_("Session: XMLNode describing a AudioRegion references a non-audio source id =%1"), id2) << endmsg;
1698 return boost::shared_ptr<AudioRegion>();
1700 master_sources.push_back (as);
1705 boost::shared_ptr<AudioRegion> region (boost::dynamic_pointer_cast<AudioRegion> (RegionFactory::create (sources, node)));
1707 /* a final detail: this is the one and only place that we know how long missing files are */
1709 if (region->whole_file()) {
1710 for (SourceList::iterator sx = sources.begin(); sx != sources.end(); ++sx) {
1711 boost::shared_ptr<SilentFileSource> sfp = boost::dynamic_pointer_cast<SilentFileSource> (*sx);
1713 sfp->set_length (region->length());
1718 if (!master_sources.empty()) {
1719 if (master_sources.size() != nchans) {
1720 error << _("Session: XMLNode describing an AudioRegion is missing some master sources; ignored") << endmsg;
1722 region->set_master_sources (master_sources);
1730 catch (failed_constructor& err) {
1731 return boost::shared_ptr<AudioRegion>();
1735 boost::shared_ptr<MidiRegion>
1736 Session::XMLMidiRegionFactory (const XMLNode& node, bool /*full*/)
1738 const XMLProperty* prop;
1739 boost::shared_ptr<Source> source;
1740 boost::shared_ptr<MidiSource> ms;
1743 if (node.name() != X_("Region")) {
1744 return boost::shared_ptr<MidiRegion>();
1747 if ((prop = node.property ("name")) == 0) {
1748 cerr << "no name for this region\n";
1752 if ((prop = node.property (X_("source-0"))) == 0) {
1753 if ((prop = node.property ("source")) == 0) {
1754 error << _("Session: XMLNode describing a MidiRegion is incomplete (no source)") << endmsg;
1755 return boost::shared_ptr<MidiRegion>();
1759 PBD::ID s_id (prop->value());
1761 if ((source = source_by_id (s_id)) == 0) {
1762 error << string_compose(_("Session: XMLNode describing a MidiRegion references an unknown source id =%1"), s_id) << endmsg;
1763 return boost::shared_ptr<MidiRegion>();
1766 ms = boost::dynamic_pointer_cast<MidiSource>(source);
1768 error << string_compose(_("Session: XMLNode describing a MidiRegion references a non-midi source id =%1"), s_id) << endmsg;
1769 return boost::shared_ptr<MidiRegion>();
1772 sources.push_back (ms);
1775 boost::shared_ptr<MidiRegion> region (boost::dynamic_pointer_cast<MidiRegion> (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());
1790 catch (failed_constructor& err) {
1791 return boost::shared_ptr<MidiRegion>();
1796 Session::get_sources_as_xml ()
1799 XMLNode* node = new XMLNode (X_("Sources"));
1800 Glib::Threads::Mutex::Lock lm (source_lock);
1802 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ++i) {
1803 node->add_child_nocopy (i->second->get_state());
1810 Session::path_from_region_name (DataType type, string name, string identifier)
1812 char buf[PATH_MAX+1];
1814 SessionDirectory sdir(get_best_session_directory_for_new_source());
1815 std::string source_dir = ((type == DataType::AUDIO)
1816 ? sdir.sound_path() : sdir.midi_path());
1818 string ext = native_header_format_extension (config.get_native_file_header_format(), type);
1820 for (n = 0; n < 999999; ++n) {
1821 if (identifier.length()) {
1822 snprintf (buf, sizeof(buf), "%s%s%" PRIu32 "%s", name.c_str(),
1823 identifier.c_str(), n, ext.c_str());
1825 snprintf (buf, sizeof(buf), "%s-%" PRIu32 "%s", name.c_str(),
1829 std::string source_path = Glib::build_filename (source_dir, buf);
1831 if (!Glib::file_test (source_path, Glib::FILE_TEST_EXISTS)) {
1836 error << string_compose (_("cannot create new file from region name \"%1\" with ident = \"%2\": too many existing files with similar names"),
1845 Session::load_sources (const XMLNode& node)
1848 XMLNodeConstIterator niter;
1849 boost::shared_ptr<Source> source;
1851 nlist = node.children();
1855 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1858 if ((source = XMLSourceFactory (**niter)) == 0) {
1859 error << _("Session: cannot create Source from XML description.") << endmsg;
1862 } catch (MissingSource& err) {
1866 if (!no_questions_about_missing_files) {
1867 user_choice = MissingFile (this, err.path, err.type).get_value_or (-1);
1872 switch (user_choice) {
1874 /* user added a new search location, so try again */
1879 /* user asked to quit the entire session load
1884 no_questions_about_missing_files = true;
1888 no_questions_about_missing_files = true;
1893 warning << _("A sound file is missing. It will be replaced by silence.") << endmsg;
1894 source = SourceFactory::createSilent (*this, **niter, max_framecnt, _current_frame_rate);
1903 boost::shared_ptr<Source>
1904 Session::XMLSourceFactory (const XMLNode& node)
1906 if (node.name() != "Source") {
1907 return boost::shared_ptr<Source>();
1911 /* note: do peak building in another thread when loading session state */
1912 return SourceFactory::create (*this, node, true);
1915 catch (failed_constructor& err) {
1916 error << string_compose (_("Found a sound file that cannot be used by %1. Talk to the progammers."), PROGRAM_NAME) << endmsg;
1917 return boost::shared_ptr<Source>();
1922 Session::save_template (string template_name)
1926 if (_state_of_the_state & CannotSave) {
1930 std::string user_template_dir(user_template_directory());
1932 if (g_mkdir_with_parents (user_template_dir.c_str(), 0755) != 0) {
1933 error << string_compose(_("Could not create templates directory \"%1\" (%2)"),
1934 user_template_dir, g_strerror (errno)) << endmsg;
1938 tree.set_root (&get_template());
1940 std::string template_dir_path(user_template_dir);
1942 /* directory to put the template in */
1943 template_dir_path = Glib::build_filename (template_dir_path, template_name);
1945 if (Glib::file_test (template_dir_path, Glib::FILE_TEST_EXISTS)) {
1946 warning << string_compose(_("Template \"%1\" already exists - new version not created"),
1947 template_dir_path) << endmsg;
1951 if (g_mkdir_with_parents (template_dir_path.c_str(), 0755) != 0) {
1952 error << string_compose(_("Could not create directory for Session template\"%1\" (%2)"),
1953 template_dir_path, g_strerror (errno)) << endmsg;
1958 std::string template_file_path(template_dir_path);
1959 template_file_path = Glib::build_filename (template_file_path, template_name + template_suffix);
1961 if (!tree.write (template_file_path)) {
1962 error << _("template not saved") << endmsg;
1966 /* copy plugin state directory */
1968 std::string template_plugin_state_path(template_dir_path);
1969 template_plugin_state_path = Glib::build_filename (template_plugin_state_path, X_("plugins"));
1971 if (g_mkdir_with_parents (template_plugin_state_path.c_str(), 0755) != 0) {
1972 error << string_compose(_("Could not create directory for Session template plugin state\"%1\" (%2)"),
1973 template_plugin_state_path, g_strerror (errno)) << endmsg;
1977 copy_files (plugins_dir(), template_plugin_state_path);
1983 Session::refresh_disk_space ()
1985 #if __APPLE__ || (HAVE_SYS_VFS_H && HAVE_SYS_STATVFS_H)
1987 Glib::Threads::Mutex::Lock lm (space_lock);
1989 /* get freespace on every FS that is part of the session path */
1991 _total_free_4k_blocks = 0;
1992 _total_free_4k_blocks_uncertain = false;
1994 for (vector<space_and_path>::iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
1996 struct statfs statfsbuf;
1997 statfs (i->path.c_str(), &statfsbuf);
1999 double const scale = statfsbuf.f_bsize / 4096.0;
2001 /* See if this filesystem is read-only */
2002 struct statvfs statvfsbuf;
2003 statvfs (i->path.c_str(), &statvfsbuf);
2005 /* f_bavail can be 0 if it is undefined for whatever
2006 filesystem we are looking at; Samba shares mounted
2007 via GVFS are an example of this.
2009 if (statfsbuf.f_bavail == 0) {
2010 /* block count unknown */
2012 i->blocks_unknown = true;
2013 } else if (statvfsbuf.f_flag & ST_RDONLY) {
2014 /* read-only filesystem */
2016 i->blocks_unknown = false;
2018 /* read/write filesystem with known space */
2019 i->blocks = (uint32_t) floor (statfsbuf.f_bavail * scale);
2020 i->blocks_unknown = false;
2023 _total_free_4k_blocks += i->blocks;
2024 if (i->blocks_unknown) {
2025 _total_free_4k_blocks_uncertain = true;
2032 Session::get_best_session_directory_for_new_source ()
2034 vector<space_and_path>::iterator i;
2035 string result = _session_dir->root_path();
2037 /* handle common case without system calls */
2039 if (session_dirs.size() == 1) {
2043 /* OK, here's the algorithm we're following here:
2045 We want to select which directory to use for
2046 the next file source to be created. Ideally,
2047 we'd like to use a round-robin process so as to
2048 get maximum performance benefits from splitting
2049 the files across multiple disks.
2051 However, in situations without much diskspace, an
2052 RR approach may end up filling up a filesystem
2053 with new files while others still have space.
2054 Its therefore important to pay some attention to
2055 the freespace in the filesystem holding each
2056 directory as well. However, if we did that by
2057 itself, we'd keep creating new files in the file
2058 system with the most space until it was as full
2059 as all others, thus negating any performance
2060 benefits of this RAID-1 like approach.
2062 So, we use a user-configurable space threshold. If
2063 there are at least 2 filesystems with more than this
2064 much space available, we use RR selection between them.
2065 If not, then we pick the filesystem with the most space.
2067 This gets a good balance between the two
2071 refresh_disk_space ();
2073 int free_enough = 0;
2075 for (i = session_dirs.begin(); i != session_dirs.end(); ++i) {
2076 if ((*i).blocks * 4096 >= Config->get_disk_choice_space_threshold()) {
2081 if (free_enough >= 2) {
2082 /* use RR selection process, ensuring that the one
2086 i = last_rr_session_dir;
2089 if (++i == session_dirs.end()) {
2090 i = session_dirs.begin();
2093 if ((*i).blocks * 4096 >= Config->get_disk_choice_space_threshold()) {
2094 SessionDirectory sdir(i->path);
2095 if (sdir.create ()) {
2097 last_rr_session_dir = i;
2102 } while (i != last_rr_session_dir);
2106 /* pick FS with the most freespace (and that
2107 seems to actually work ...)
2110 vector<space_and_path> sorted;
2111 space_and_path_ascending_cmp cmp;
2113 sorted = session_dirs;
2114 sort (sorted.begin(), sorted.end(), cmp);
2116 for (i = sorted.begin(); i != sorted.end(); ++i) {
2117 SessionDirectory sdir(i->path);
2118 if (sdir.create ()) {
2120 last_rr_session_dir = i;
2130 Session::automation_dir () const
2132 return Glib::build_filename (_path, "automation");
2136 Session::analysis_dir () const
2138 return Glib::build_filename (_path, "analysis");
2142 Session::plugins_dir () const
2144 return Glib::build_filename (_path, "plugins");
2148 Session::externals_dir () const
2150 return Glib::build_filename (_path, "externals");
2154 Session::load_bundles (XMLNode const & node)
2156 XMLNodeList nlist = node.children();
2157 XMLNodeConstIterator niter;
2161 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2162 if ((*niter)->name() == "InputBundle") {
2163 add_bundle (boost::shared_ptr<UserBundle> (new UserBundle (**niter, true)));
2164 } else if ((*niter)->name() == "OutputBundle") {
2165 add_bundle (boost::shared_ptr<UserBundle> (new UserBundle (**niter, false)));
2167 error << string_compose(_("Unknown node \"%1\" found in Bundles list from session file"), (*niter)->name()) << endmsg;
2176 Session::load_route_groups (const XMLNode& node, int version)
2178 XMLNodeList nlist = node.children();
2179 XMLNodeConstIterator niter;
2183 if (version >= 3000) {
2185 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2186 if ((*niter)->name() == "RouteGroup") {
2187 RouteGroup* rg = new RouteGroup (*this, "");
2188 add_route_group (rg);
2189 rg->set_state (**niter, version);
2193 } else if (version < 3000) {
2195 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2196 if ((*niter)->name() == "EditGroup" || (*niter)->name() == "MixGroup") {
2197 RouteGroup* rg = new RouteGroup (*this, "");
2198 add_route_group (rg);
2199 rg->set_state (**niter, version);
2208 Session::auto_save()
2210 save_state (_current_snapshot_name);
2214 state_file_filter (const string &str, void */*arg*/)
2216 return (str.length() > strlen(statefile_suffix) &&
2217 str.find (statefile_suffix) == (str.length() - strlen (statefile_suffix)));
2221 bool operator()(const string* a, const string* b) {
2227 remove_end(string* state)
2229 string statename(*state);
2231 string::size_type start,end;
2232 if ((start = statename.find_last_of (G_DIR_SEPARATOR)) != string::npos) {
2233 statename = statename.substr (start+1);
2236 if ((end = statename.rfind(".ardour")) == string::npos) {
2237 end = statename.length();
2240 return new string(statename.substr (0, end));
2244 Session::possible_states (string path)
2246 PathScanner scanner;
2247 vector<string*>* states = scanner (path, state_file_filter, 0, false, false);
2249 transform(states->begin(), states->end(), states->begin(), remove_end);
2252 sort (states->begin(), states->end(), cmp);
2258 Session::possible_states () const
2260 return possible_states(_path);
2264 Session::add_route_group (RouteGroup* g)
2266 _route_groups.push_back (g);
2267 route_group_added (g); /* EMIT SIGNAL */
2269 g->RouteAdded.connect_same_thread (*this, boost::bind (&Session::route_added_to_route_group, this, _1, _2));
2270 g->RouteRemoved.connect_same_thread (*this, boost::bind (&Session::route_removed_from_route_group, this, _1, _2));
2271 g->PropertyChanged.connect_same_thread (*this, boost::bind (&Session::route_group_property_changed, this, g));
2277 Session::remove_route_group (RouteGroup& rg)
2279 list<RouteGroup*>::iterator i;
2281 if ((i = find (_route_groups.begin(), _route_groups.end(), &rg)) != _route_groups.end()) {
2282 _route_groups.erase (i);
2285 route_group_removed (); /* EMIT SIGNAL */
2289 /** Set a new order for our route groups, without adding or removing any.
2290 * @param groups Route group list in the new order.
2293 Session::reorder_route_groups (list<RouteGroup*> groups)
2295 _route_groups = groups;
2297 route_groups_reordered (); /* EMIT SIGNAL */
2303 Session::route_group_by_name (string name)
2305 list<RouteGroup *>::iterator i;
2307 for (i = _route_groups.begin(); i != _route_groups.end(); ++i) {
2308 if ((*i)->name() == name) {
2316 Session::all_route_group() const
2318 return *_all_route_group;
2322 Session::add_commands (vector<Command*> const & cmds)
2324 for (vector<Command*>::const_iterator i = cmds.begin(); i != cmds.end(); ++i) {
2330 Session::begin_reversible_command (const string& name)
2332 begin_reversible_command (g_quark_from_string (name.c_str ()));
2335 /** Begin a reversible command using a GQuark to identify it.
2336 * begin_reversible_command() and commit_reversible_command() calls may be nested,
2337 * but there must be as many begin...()s as there are commit...()s.
2340 Session::begin_reversible_command (GQuark q)
2342 /* If nested begin/commit pairs are used, we create just one UndoTransaction
2343 to hold all the commands that are committed. This keeps the order of
2344 commands correct in the history.
2347 if (_current_trans == 0) {
2348 /* start a new transaction */
2349 assert (_current_trans_quarks.empty ());
2350 _current_trans = new UndoTransaction();
2351 _current_trans->set_name (g_quark_to_string (q));
2354 _current_trans_quarks.push_front (q);
2358 Session::commit_reversible_command (Command *cmd)
2360 assert (_current_trans);
2361 assert (!_current_trans_quarks.empty ());
2366 _current_trans->add_command (cmd);
2369 _current_trans_quarks.pop_front ();
2371 if (!_current_trans_quarks.empty ()) {
2372 /* the transaction we're committing is not the top-level one */
2376 if (_current_trans->empty()) {
2377 /* no commands were added to the transaction, so just get rid of it */
2378 delete _current_trans;
2383 gettimeofday (&now, 0);
2384 _current_trans->set_timestamp (now);
2386 _history.add (_current_trans);
2391 accept_all_audio_files (const string& path, void */*arg*/)
2393 if (!Glib::file_test (path, Glib::FILE_TEST_IS_REGULAR)) {
2397 if (!AudioFileSource::safe_audio_file_extension (path)) {
2405 accept_all_midi_files (const string& path, void */*arg*/)
2407 if (!Glib::file_test (path, Glib::FILE_TEST_IS_REGULAR)) {
2411 return ((path.length() > 4 && path.find (".mid") != (path.length() - 4)) ||
2412 (path.length() > 4 && path.find (".smf") != (path.length() - 4)) ||
2413 (path.length() > 5 && path.find (".midi") != (path.length() - 5)));
2417 accept_all_state_files (const string& path, void */*arg*/)
2419 if (!Glib::file_test (path, Glib::FILE_TEST_IS_REGULAR)) {
2423 return (path.length() > 7 && path.find (".ardour") == (path.length() - 7));
2427 Session::find_all_sources (string path, set<string>& result)
2432 if (!tree.read (path)) {
2436 if ((node = find_named_node (*tree.root(), "Sources")) == 0) {
2441 XMLNodeConstIterator niter;
2443 nlist = node->children();
2447 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2451 if ((prop = (*niter)->property (X_("type"))) == 0) {
2455 DataType type (prop->value());
2457 if ((prop = (*niter)->property (X_("name"))) == 0) {
2461 if (Glib::path_is_absolute (prop->value())) {
2462 /* external file, ignore */
2470 if (FileSource::find (*this, type, prop->value(), true, is_new, chan, found_path)) {
2471 result.insert (found_path);
2479 Session::find_all_sources_across_snapshots (set<string>& result, bool exclude_this_snapshot)
2481 PathScanner scanner;
2482 vector<string*>* state_files;
2484 string this_snapshot_path;
2490 if (ripped[ripped.length()-1] == G_DIR_SEPARATOR) {
2491 ripped = ripped.substr (0, ripped.length() - 1);
2494 state_files = scanner (ripped, accept_all_state_files, (void *) 0, true, true);
2496 if (state_files == 0) {
2501 this_snapshot_path = _path;
2502 this_snapshot_path += legalize_for_path (_current_snapshot_name);
2503 this_snapshot_path += statefile_suffix;
2505 for (vector<string*>::iterator i = state_files->begin(); i != state_files->end(); ++i) {
2507 if (exclude_this_snapshot && **i == this_snapshot_path) {
2511 if (find_all_sources (**i, result) < 0) {
2519 struct RegionCounter {
2520 typedef std::map<PBD::ID,boost::shared_ptr<AudioSource> > AudioSourceList;
2521 AudioSourceList::iterator iter;
2522 boost::shared_ptr<Region> region;
2525 RegionCounter() : count (0) {}
2529 Session::ask_about_playlist_deletion (boost::shared_ptr<Playlist> p)
2531 boost::optional<int> r = AskAboutPlaylistDeletion (p);
2532 return r.get_value_or (1);
2536 Session::cleanup_regions ()
2538 const RegionFactory::RegionMap& regions (RegionFactory::regions());
2540 for (RegionFactory::RegionMap::const_iterator i = regions.begin(); i != regions.end(); ++i) {
2542 uint32_t used = playlists->region_use_count (i->second);
2544 if (used == 0 && !i->second->automatic ()) {
2545 RegionFactory::map_remove (i->second);
2549 /* dump the history list */
2556 Session::cleanup_sources (CleanupReport& rep)
2558 // FIXME: needs adaptation to midi
2560 vector<boost::shared_ptr<Source> > dead_sources;
2561 PathScanner scanner;
2564 vector<space_and_path>::iterator i;
2565 vector<space_and_path>::iterator nexti;
2566 vector<string*>* candidates;
2567 vector<string*>* candidates2;
2568 vector<string> unused;
2569 set<string> all_sources;
2574 _state_of_the_state = (StateOfTheState) (_state_of_the_state | InCleanup);
2576 /* consider deleting all unused playlists */
2578 if (playlists->maybe_delete_unused (boost::bind (Session::ask_about_playlist_deletion, _1))) {
2583 /* sync the "all regions" property of each playlist with its current state
2586 playlists->sync_all_regions_with_regions ();
2588 /* find all un-used sources */
2593 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ) {
2595 SourceMap::iterator tmp;
2600 /* do not bother with files that are zero size, otherwise we remove the current "nascent"
2604 if (!i->second->used() && (i->second->length(i->second->timeline_position() > 0))) {
2605 dead_sources.push_back (i->second);
2606 i->second->drop_references ();
2612 /* build a list of all the possible audio directories for the session */
2614 for (i = session_dirs.begin(); i != session_dirs.end(); ) {
2619 SessionDirectory sdir ((*i).path);
2620 audio_path += sdir.sound_path();
2622 if (nexti != session_dirs.end()) {
2630 /* build a list of all the possible midi directories for the session */
2632 for (i = session_dirs.begin(); i != session_dirs.end(); ) {
2637 SessionDirectory sdir ((*i).path);
2638 midi_path += sdir.midi_path();
2640 if (nexti != session_dirs.end()) {
2647 candidates = scanner (audio_path, accept_all_audio_files, (void *) 0, true, true);
2648 candidates2 = scanner (midi_path, accept_all_midi_files, (void *) 0, true, true);
2654 for (vector<string*>::iterator i = candidates2->begin(); i != candidates2->end(); ++i) {
2655 candidates->push_back (*i);
2660 candidates = candidates2; // might still be null
2663 /* find all sources, but don't use this snapshot because the
2664 state file on disk still references sources we may have already
2668 find_all_sources_across_snapshots (all_sources, true);
2670 /* add our current source list
2673 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ) {
2674 boost::shared_ptr<FileSource> fs;
2675 SourceMap::iterator tmp = i;
2678 if ((fs = boost::dynamic_pointer_cast<FileSource> (i->second)) != 0) {
2679 if (playlists->source_use_count (fs) != 0) {
2680 all_sources.insert (fs->path());
2683 /* we might not remove this source from disk, because it may be used
2684 by other snapshots, but its not being used in this version
2685 so lets get rid of it now, along with any representative regions
2689 RegionFactory::remove_regions_using_source (i->second);
2697 char tmppath1[PATH_MAX+1];
2698 char tmppath2[PATH_MAX+1];
2701 for (vector<string*>::iterator x = candidates->begin(); x != candidates->end(); ++x) {
2706 for (set<string>::iterator i = all_sources.begin(); i != all_sources.end(); ++i) {
2708 if (realpath(spath.c_str(), tmppath1) == 0) {
2709 error << string_compose (_("Cannot expand path %1 (%2)"),
2710 spath, strerror (errno)) << endmsg;
2714 if (realpath((*i).c_str(), tmppath2) == 0) {
2715 error << string_compose (_("Cannot expand path %1 (%2)"),
2716 (*i), strerror (errno)) << endmsg;
2720 if (strcmp(tmppath1, tmppath2) == 0) {
2727 unused.push_back (spath);
2736 /* now try to move all unused files into the "dead" directory(ies) */
2738 for (vector<string>::iterator x = unused.begin(); x != unused.end(); ++x) {
2739 struct stat statbuf;
2743 /* don't move the file across filesystems, just
2744 stick it in the `dead_dir_name' directory
2745 on whichever filesystem it was already on.
2748 if ((*x).find ("/sounds/") != string::npos) {
2750 /* old school, go up 1 level */
2752 newpath = Glib::path_get_dirname (*x); // "sounds"
2753 newpath = Glib::path_get_dirname (newpath); // "session-name"
2757 /* new school, go up 4 levels */
2759 newpath = Glib::path_get_dirname (*x); // "audiofiles" or "midifiles"
2760 newpath = Glib::path_get_dirname (newpath); // "session-name"
2761 newpath = Glib::path_get_dirname (newpath); // "interchange"
2762 newpath = Glib::path_get_dirname (newpath); // "session-dir"
2765 newpath = Glib::build_filename (newpath, dead_dir_name);
2767 if (g_mkdir_with_parents (newpath.c_str(), 0755) < 0) {
2768 error << string_compose(_("Session: cannot create dead file folder \"%1\" (%2)"), newpath, strerror (errno)) << endmsg;
2772 newpath = Glib::build_filename (newpath, Glib::path_get_basename ((*x)));
2774 if (Glib::file_test (newpath, Glib::FILE_TEST_EXISTS)) {
2776 /* the new path already exists, try versioning */
2778 char buf[PATH_MAX+1];
2782 snprintf (buf, sizeof (buf), "%s.%d", newpath.c_str(), version);
2785 while (Glib::file_test (newpath_v.c_str(), Glib::FILE_TEST_EXISTS) && version < 999) {
2786 snprintf (buf, sizeof (buf), "%s.%d", newpath.c_str(), ++version);
2790 if (version == 999) {
2791 error << string_compose (_("there are already 1000 files with names like %1; versioning discontinued"),
2795 newpath = newpath_v;
2800 /* it doesn't exist, or we can't read it or something */
2804 stat ((*x).c_str(), &statbuf);
2806 if (::rename ((*x).c_str(), newpath.c_str()) != 0) {
2807 error << string_compose (_("cannot rename unused file source from %1 to %2 (%3)"),
2808 (*x), newpath, strerror (errno))
2813 /* see if there an easy to find peakfile for this file, and remove it.
2816 string base = basename_nosuffix (*x);
2817 base += "%A"; /* this is what we add for the channel suffix of all native files,
2818 or for the first channel of embedded files. it will miss
2819 some peakfiles for other channels
2821 string peakpath = peak_path (base);
2823 if (Glib::file_test (peakpath.c_str(), Glib::FILE_TEST_EXISTS)) {
2824 if (::unlink (peakpath.c_str()) != 0) {
2825 error << string_compose (_("cannot remove peakfile %1 for %2 (%3)"),
2826 peakpath, _path, strerror (errno))
2828 /* try to back out */
2829 ::rename (newpath.c_str(), _path.c_str());
2834 rep.paths.push_back (*x);
2835 rep.space += statbuf.st_size;
2838 /* dump the history list */
2842 /* save state so we don't end up a session file
2843 referring to non-existent sources.
2850 _state_of_the_state = (StateOfTheState) (_state_of_the_state & ~InCleanup);
2856 Session::cleanup_trash_sources (CleanupReport& rep)
2858 // FIXME: needs adaptation for MIDI
2860 vector<space_and_path>::iterator i;
2866 for (i = session_dirs.begin(); i != session_dirs.end(); ++i) {
2868 dead_dir = Glib::build_filename ((*i).path, dead_dir_name);
2870 clear_directory (dead_dir, &rep.space, &rep.paths);
2877 Session::set_dirty ()
2879 bool was_dirty = dirty();
2881 _state_of_the_state = StateOfTheState (_state_of_the_state | Dirty);
2885 DirtyChanged(); /* EMIT SIGNAL */
2891 Session::set_clean ()
2893 bool was_dirty = dirty();
2895 _state_of_the_state = Clean;
2899 DirtyChanged(); /* EMIT SIGNAL */
2904 Session::set_deletion_in_progress ()
2906 _state_of_the_state = StateOfTheState (_state_of_the_state | Deletion);
2910 Session::clear_deletion_in_progress ()
2912 _state_of_the_state = StateOfTheState (_state_of_the_state & (~Deletion));
2916 Session::add_controllable (boost::shared_ptr<Controllable> c)
2918 /* this adds a controllable to the list managed by the Session.
2919 this is a subset of those managed by the Controllable class
2920 itself, and represents the only ones whose state will be saved
2921 as part of the session.
2924 Glib::Threads::Mutex::Lock lm (controllables_lock);
2925 controllables.insert (c);
2928 struct null_deleter { void operator()(void const *) const {} };
2931 Session::remove_controllable (Controllable* c)
2933 if (_state_of_the_state & Deletion) {
2937 Glib::Threads::Mutex::Lock lm (controllables_lock);
2939 Controllables::iterator x = controllables.find (boost::shared_ptr<Controllable>(c, null_deleter()));
2941 if (x != controllables.end()) {
2942 controllables.erase (x);
2946 boost::shared_ptr<Controllable>
2947 Session::controllable_by_id (const PBD::ID& id)
2949 Glib::Threads::Mutex::Lock lm (controllables_lock);
2951 for (Controllables::iterator i = controllables.begin(); i != controllables.end(); ++i) {
2952 if ((*i)->id() == id) {
2957 return boost::shared_ptr<Controllable>();
2960 boost::shared_ptr<Controllable>
2961 Session::controllable_by_descriptor (const ControllableDescriptor& desc)
2963 boost::shared_ptr<Controllable> c;
2964 boost::shared_ptr<Route> r;
2966 switch (desc.top_level_type()) {
2967 case ControllableDescriptor::NamedRoute:
2969 std::string str = desc.top_level_name();
2970 if (str == "master") {
2972 } else if (str == "control" || str == "listen") {
2975 r = route_by_name (desc.top_level_name());
2980 case ControllableDescriptor::RemoteControlID:
2981 r = route_by_remote_id (desc.rid());
2989 switch (desc.subtype()) {
2990 case ControllableDescriptor::Gain:
2991 c = r->gain_control ();
2994 case ControllableDescriptor::Solo:
2995 c = r->solo_control();
2998 case ControllableDescriptor::Mute:
2999 c = r->mute_control();
3002 case ControllableDescriptor::Recenable:
3004 boost::shared_ptr<Track> t = boost::dynamic_pointer_cast<Track>(r);
3007 c = t->rec_enable_control ();
3012 case ControllableDescriptor::PanDirection:
3014 c = r->pannable()->pan_azimuth_control;
3018 case ControllableDescriptor::PanWidth:
3020 c = r->pannable()->pan_width_control;
3024 case ControllableDescriptor::PanElevation:
3026 c = r->pannable()->pan_elevation_control;
3030 case ControllableDescriptor::Balance:
3031 /* XXX simple pan control */
3034 case ControllableDescriptor::PluginParameter:
3036 uint32_t plugin = desc.target (0);
3037 uint32_t parameter_index = desc.target (1);
3039 /* revert to zero based counting */
3045 if (parameter_index > 0) {
3049 boost::shared_ptr<Processor> p = r->nth_plugin (plugin);
3052 c = boost::dynamic_pointer_cast<ARDOUR::AutomationControl>(
3053 p->control(Evoral::Parameter(PluginAutomation, 0, parameter_index)));
3058 case ControllableDescriptor::SendGain:
3060 uint32_t send = desc.target (0);
3062 /* revert to zero-based counting */
3068 boost::shared_ptr<Processor> p = r->nth_send (send);
3071 boost::shared_ptr<Send> s = boost::dynamic_pointer_cast<Send>(p);
3072 boost::shared_ptr<Amp> a = s->amp();
3075 c = s->amp()->gain_control();
3082 /* relax and return a null pointer */
3090 Session::add_instant_xml (XMLNode& node, bool write_to_config)
3093 Stateful::add_instant_xml (node, _path);
3096 if (write_to_config) {
3097 Config->add_instant_xml (node);
3102 Session::instant_xml (const string& node_name)
3104 return Stateful::instant_xml (node_name, _path);
3108 Session::save_history (string snapshot_name)
3116 if (snapshot_name.empty()) {
3117 snapshot_name = _current_snapshot_name;
3120 const string history_filename = legalize_for_path (snapshot_name) + history_suffix;
3121 const string backup_filename = history_filename + backup_suffix;
3122 const std::string xml_path(Glib::build_filename (_session_dir->root_path(), history_filename));
3123 const std::string backup_path(Glib::build_filename (_session_dir->root_path(), backup_filename));
3125 if (Glib::file_test (xml_path, Glib::FILE_TEST_EXISTS)) {
3126 if (::g_rename (xml_path.c_str(), backup_path.c_str()) != 0) {
3127 error << _("could not backup old history file, current history not saved") << endmsg;
3132 if (!Config->get_save_history() || Config->get_saved_history_depth() < 0) {
3136 tree.set_root (&_history.get_state (Config->get_saved_history_depth()));
3138 if (!tree.write (xml_path))
3140 error << string_compose (_("history could not be saved to %1"), xml_path) << endmsg;
3142 if (g_remove (xml_path.c_str()) != 0) {
3143 error << string_compose(_("Could not remove history file at path \"%1\" (%2)"),
3144 xml_path, g_strerror (errno)) << endmsg;
3146 if (::g_rename (backup_path.c_str(), xml_path.c_str()) != 0) {
3147 error << string_compose (_("could not restore history file from backup %1 (%2)"),
3148 backup_path, g_strerror (errno)) << endmsg;
3158 Session::restore_history (string snapshot_name)
3162 if (snapshot_name.empty()) {
3163 snapshot_name = _current_snapshot_name;
3166 const std::string xml_filename = legalize_for_path (snapshot_name) + history_suffix;
3167 const std::string xml_path(Glib::build_filename (_session_dir->root_path(), xml_filename));
3169 info << "Loading history from " << xml_path << endmsg;
3171 if (!Glib::file_test (xml_path, Glib::FILE_TEST_EXISTS)) {
3172 info << string_compose (_("%1: no history file \"%2\" for this session."),
3173 _name, xml_path) << endmsg;
3177 if (!tree.read (xml_path)) {
3178 error << string_compose (_("Could not understand session history file \"%1\""),
3179 xml_path) << endmsg;
3186 for (XMLNodeConstIterator it = tree.root()->children().begin(); it != tree.root()->children().end(); it++) {
3189 UndoTransaction* ut = new UndoTransaction ();
3192 ut->set_name(t->property("name")->value());
3193 stringstream ss(t->property("tv-sec")->value());
3195 ss.str(t->property("tv-usec")->value());
3197 ut->set_timestamp(tv);
3199 for (XMLNodeConstIterator child_it = t->children().begin();
3200 child_it != t->children().end(); child_it++)
3202 XMLNode *n = *child_it;
3205 if (n->name() == "MementoCommand" ||
3206 n->name() == "MementoUndoCommand" ||
3207 n->name() == "MementoRedoCommand") {
3209 if ((c = memento_command_factory(n))) {
3213 } else if (n->name() == "NoteDiffCommand") {
3214 PBD::ID id (n->property("midi-source")->value());
3215 boost::shared_ptr<MidiSource> midi_source =
3216 boost::dynamic_pointer_cast<MidiSource, Source>(source_by_id(id));
3218 ut->add_command (new MidiModel::NoteDiffCommand(midi_source->model(), *n));
3220 error << _("Failed to downcast MidiSource for NoteDiffCommand") << endmsg;
3223 } else if (n->name() == "SysExDiffCommand") {
3225 PBD::ID id (n->property("midi-source")->value());
3226 boost::shared_ptr<MidiSource> midi_source =
3227 boost::dynamic_pointer_cast<MidiSource, Source>(source_by_id(id));
3229 ut->add_command (new MidiModel::SysExDiffCommand (midi_source->model(), *n));
3231 error << _("Failed to downcast MidiSource for SysExDiffCommand") << endmsg;
3234 } else if (n->name() == "PatchChangeDiffCommand") {
3236 PBD::ID id (n->property("midi-source")->value());
3237 boost::shared_ptr<MidiSource> midi_source =
3238 boost::dynamic_pointer_cast<MidiSource, Source>(source_by_id(id));
3240 ut->add_command (new MidiModel::PatchChangeDiffCommand (midi_source->model(), *n));
3242 error << _("Failed to downcast MidiSource for PatchChangeDiffCommand") << endmsg;
3245 } else if (n->name() == "StatefulDiffCommand") {
3246 if ((c = stateful_diff_command_factory (n))) {
3247 ut->add_command (c);
3250 error << string_compose(_("Couldn't figure out how to make a Command out of a %1 XMLNode."), n->name()) << endmsg;
3261 Session::config_changed (std::string p, bool ours)
3267 if (p == "seamless-loop") {
3269 } else if (p == "rf-speed") {
3271 } else if (p == "auto-loop") {
3273 } else if (p == "auto-input") {
3275 if (Config->get_monitoring_model() == HardwareMonitoring && transport_rolling()) {
3276 /* auto-input only makes a difference if we're rolling */
3277 set_track_monitor_input_status (!config.get_auto_input());
3280 } else if (p == "punch-in") {
3284 if ((location = _locations->auto_punch_location()) != 0) {
3286 if (config.get_punch_in ()) {
3287 replace_event (SessionEvent::PunchIn, location->start());
3289 remove_event (location->start(), SessionEvent::PunchIn);
3293 } else if (p == "punch-out") {
3297 if ((location = _locations->auto_punch_location()) != 0) {
3299 if (config.get_punch_out()) {
3300 replace_event (SessionEvent::PunchOut, location->end());
3302 clear_events (SessionEvent::PunchOut);
3306 } else if (p == "edit-mode") {
3308 Glib::Threads::Mutex::Lock lm (playlists->lock);
3310 for (SessionPlaylists::List::iterator i = playlists->playlists.begin(); i != playlists->playlists.end(); ++i) {
3311 (*i)->set_edit_mode (Config->get_edit_mode ());
3314 } else if (p == "use-video-sync") {
3316 waiting_for_sync_offset = config.get_use_video_sync();
3318 } else if (p == "mmc-control") {
3320 //poke_midi_thread ();
3322 } else if (p == "mmc-device-id" || p == "mmc-receive-id" || p == "mmc-receive-device-id") {
3324 _mmc->set_receive_device_id (Config->get_mmc_receive_device_id());
3326 } else if (p == "mmc-send-id" || p == "mmc-send-device-id") {
3328 _mmc->set_send_device_id (Config->get_mmc_send_device_id());
3330 } else if (p == "midi-control") {
3332 //poke_midi_thread ();
3334 } else if (p == "raid-path") {
3336 setup_raid_path (config.get_raid_path());
3338 } else if (p == "timecode-format") {
3342 } else if (p == "video-pullup") {
3346 } else if (p == "seamless-loop") {
3348 if (play_loop && transport_rolling()) {
3349 // to reset diskstreams etc
3350 request_play_loop (true);
3353 } else if (p == "rf-speed") {
3355 cumulative_rf_motion = 0;
3358 } else if (p == "click-sound") {
3360 setup_click_sounds (1);
3362 } else if (p == "click-emphasis-sound") {
3364 setup_click_sounds (-1);
3366 } else if (p == "clicking") {
3368 if (Config->get_clicking()) {
3369 if (_click_io && click_data) { // don't require emphasis data
3376 } else if (p == "click-gain") {
3379 _click_gain->set_gain (Config->get_click_gain(), this);
3382 } else if (p == "send-mtc") {
3384 if (Config->get_send_mtc ()) {
3385 /* mark us ready to send */
3386 next_quarter_frame_to_send = 0;
3389 } else if (p == "send-mmc") {
3391 _mmc->enable_send (Config->get_send_mmc ());
3393 } else if (p == "midi-feedback") {
3395 session_midi_feedback = Config->get_midi_feedback();
3397 } else if (p == "jack-time-master") {
3399 engine().reset_timebase ();
3401 } else if (p == "native-file-header-format") {
3403 if (!first_file_header_format_reset) {
3404 reset_native_file_format ();
3407 first_file_header_format_reset = false;
3409 } else if (p == "native-file-data-format") {
3411 if (!first_file_data_format_reset) {
3412 reset_native_file_format ();
3415 first_file_data_format_reset = false;
3417 } else if (p == "external-sync") {
3418 if (!config.get_external_sync()) {
3419 drop_sync_source ();
3421 switch_to_sync_source (Config->get_sync_source());
3423 } else if (p == "denormal-model") {
3425 } else if (p == "history-depth") {
3426 set_history_depth (Config->get_history_depth());
3427 } else if (p == "remote-model") {
3428 /* XXX DO SOMETHING HERE TO TELL THE GUI THAT WE NEED
3431 } else if (p == "sync-all-route-ordering") {
3433 /* sync to editor order unless mixer is used for remote IDs
3436 switch (Config->get_remote_model()) {
3438 sync_order_keys (EditorSort);
3441 sync_order_keys (EditorSort);
3444 sync_order_keys (MixerSort);
3447 } else if (p == "initial-program-change") {
3449 if (_mmc->output_port() && Config->get_initial_program_change() >= 0) {
3452 buf[0] = MIDI::program; // channel zero by default
3453 buf[1] = (Config->get_initial_program_change() & 0x7f);
3455 _mmc->output_port()->midimsg (buf, sizeof (buf), 0);
3457 } else if (p == "solo-mute-override") {
3458 // catch_up_on_solo_mute_override ();
3459 } else if (p == "listen-position" || p == "pfl-position") {
3460 listen_position_changed ();
3461 } else if (p == "solo-control-is-listen-control") {
3462 solo_control_mode_changed ();
3463 } else if (p == "timecode-offset" || p == "timecode-offset-negative") {
3464 last_timecode_valid = false;
3465 } else if (p == "playback-buffer-seconds") {
3466 AudioSource::allocate_working_buffers (frame_rate());
3467 } else if (p == "automation-thinning-factor") {
3468 Evoral::ControlList::set_thinning_factor (Config->get_automation_thinning_factor());
3469 } else if (p == "ltc-source-port") {
3470 reconnect_ltc_input ();
3471 } else if (p == "ltc-sink-port") {
3472 reconnect_ltc_output ();
3473 } else if (p == "timecode-generator-offset") {
3474 ltc_tx_parse_offset();
3481 Session::set_history_depth (uint32_t d)
3483 _history.set_depth (d);
3487 Session::load_diskstreams_2X (XMLNode const & node, int)
3490 XMLNodeConstIterator citer;
3492 clist = node.children();
3494 for (citer = clist.begin(); citer != clist.end(); ++citer) {
3497 /* diskstreams added automatically by DiskstreamCreated handler */
3498 if ((*citer)->name() == "AudioDiskstream" || (*citer)->name() == "DiskStream") {
3499 boost::shared_ptr<AudioDiskstream> dsp (new AudioDiskstream (*this, **citer));
3500 _diskstreams_2X.push_back (dsp);
3502 error << _("Session: unknown diskstream type in XML") << endmsg;
3506 catch (failed_constructor& err) {
3507 error << _("Session: could not load diskstream via XML state") << endmsg;
3515 /** Connect things to the MMC object */
3517 Session::setup_midi_machine_control ()
3519 _mmc->Play.connect_same_thread (*this, boost::bind (&Session::mmc_deferred_play, this, _1));
3520 _mmc->DeferredPlay.connect_same_thread (*this, boost::bind (&Session::mmc_deferred_play, this, _1));
3521 _mmc->Stop.connect_same_thread (*this, boost::bind (&Session::mmc_stop, this, _1));
3522 _mmc->FastForward.connect_same_thread (*this, boost::bind (&Session::mmc_fast_forward, this, _1));
3523 _mmc->Rewind.connect_same_thread (*this, boost::bind (&Session::mmc_rewind, this, _1));
3524 _mmc->Pause.connect_same_thread (*this, boost::bind (&Session::mmc_pause, this, _1));
3525 _mmc->RecordPause.connect_same_thread (*this, boost::bind (&Session::mmc_record_pause, this, _1));
3526 _mmc->RecordStrobe.connect_same_thread (*this, boost::bind (&Session::mmc_record_strobe, this, _1));
3527 _mmc->RecordExit.connect_same_thread (*this, boost::bind (&Session::mmc_record_exit, this, _1));
3528 _mmc->Locate.connect_same_thread (*this, boost::bind (&Session::mmc_locate, this, _1, _2));
3529 _mmc->Step.connect_same_thread (*this, boost::bind (&Session::mmc_step, this, _1, _2));
3530 _mmc->Shuttle.connect_same_thread (*this, boost::bind (&Session::mmc_shuttle, this, _1, _2, _3));
3531 _mmc->TrackRecordStatusChange.connect_same_thread (*this, boost::bind (&Session::mmc_record_enable, this, _1, _2, _3));
3533 /* also handle MIDI SPP because its so common */
3535 _mmc->SPPStart.connect_same_thread (*this, boost::bind (&Session::spp_start, this));
3536 _mmc->SPPContinue.connect_same_thread (*this, boost::bind (&Session::spp_continue, this));
3537 _mmc->SPPStop.connect_same_thread (*this, boost::bind (&Session::spp_stop, this));
3540 boost::shared_ptr<Controllable>
3541 Session::solo_cut_control() const
3543 /* the solo cut control is a bit of an anomaly, at least as of Febrary 2011. There are no other
3544 controls in Ardour that currently get presented to the user in the GUI that require
3545 access as a Controllable and are also NOT owned by some SessionObject (e.g. Route, or MonitorProcessor).
3547 its actually an RCConfiguration parameter, so we use a ProxyControllable to wrap
3548 it up as a Controllable. Changes to the Controllable will just map back to the RCConfiguration
3552 return _solo_cut_control;
3556 Session::rename (const std::string& new_name)
3558 string legal_name = legalize_for_path (new_name);
3564 string const old_sources_root = _session_dir->sources_root();
3566 #define RENAME ::rename
3571 * interchange subdirectory
3575 * Backup files are left unchanged and not renamed.
3578 /* pass one: not 100% safe check that the new directory names don't
3582 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
3587 /* this is a stupid hack because Glib::path_get_dirname() is
3588 * lexical-only, and so passing it /a/b/c/ gives a different
3589 * result than passing it /a/b/c ...
3592 if (oldstr[oldstr.length()-1] == G_DIR_SEPARATOR) {
3593 oldstr = oldstr.substr (0, oldstr.length() - 1);
3596 string base = Glib::path_get_dirname (oldstr);
3597 string p = Glib::path_get_basename (oldstr);
3599 newstr = Glib::build_filename (base, legal_name);
3601 if (Glib::file_test (newstr, Glib::FILE_TEST_EXISTS)) {
3608 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
3613 /* this is a stupid hack because Glib::path_get_dirname() is
3614 * lexical-only, and so passing it /a/b/c/ gives a different
3615 * result than passing it /a/b/c ...
3618 if (oldstr[oldstr.length()-1] == G_DIR_SEPARATOR) {
3619 oldstr = oldstr.substr (0, oldstr.length() - 1);
3622 string base = Glib::path_get_dirname (oldstr);
3623 string p = Glib::path_get_basename (oldstr);
3625 newstr = Glib::build_filename (base, legal_name);
3627 cerr << "Rename " << oldstr << " => " << newstr << endl;
3629 if (RENAME (oldstr.c_str(), newstr.c_str()) != 0) {
3634 (*_session_dir) = newstr;
3639 /* directory below interchange */
3641 v.push_back (newstr);
3642 v.push_back (interchange_dir_name);
3645 oldstr = Glib::build_filename (v);
3648 v.push_back (newstr);
3649 v.push_back (interchange_dir_name);
3650 v.push_back (legal_name);
3652 newstr = Glib::build_filename (v);
3654 cerr << "Rename " << oldstr << " => " << newstr << endl;
3656 if (RENAME (oldstr.c_str(), newstr.c_str()) != 0) {
3663 oldstr = Glib::build_filename (newpath, _current_snapshot_name) + statefile_suffix;
3664 newstr= Glib::build_filename (newpath, legal_name) + statefile_suffix;
3666 cerr << "Rename " << oldstr << " => " << newstr << endl;
3668 if (RENAME (oldstr.c_str(), newstr.c_str()) != 0) {
3675 oldstr = Glib::build_filename (newpath, _current_snapshot_name) + history_suffix;
3677 if (Glib::file_test (oldstr, Glib::FILE_TEST_EXISTS)) {
3678 newstr = Glib::build_filename (newpath, legal_name) + history_suffix;
3680 cerr << "Rename " << oldstr << " => " << newstr << endl;
3682 if (RENAME (oldstr.c_str(), newstr.c_str()) != 0) {
3687 /* update file source paths */
3689 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ++i) {
3690 boost::shared_ptr<FileSource> fs = boost::dynamic_pointer_cast<FileSource> (i->second);
3692 string p = fs->path ();
3693 boost::replace_all (p, old_sources_root, _session_dir->sources_root());
3698 /* remove old name from recent sessions */
3700 remove_recent_sessions (_path);
3703 _current_snapshot_name = new_name;
3708 /* save state again to get everything just right */
3710 save_state (_current_snapshot_name);
3713 /* add to recent sessions */
3715 store_recent_sessions (new_name, _path);