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;
129 Session::pre_engine_init (string fullpath)
131 if (fullpath.empty()) {
133 throw failed_constructor();
136 /* discover canonical fullpath */
138 char buf[PATH_MAX+1];
139 if (!realpath (fullpath.c_str(), buf) && (errno != ENOENT)) {
140 error << string_compose(_("Could not use path %1 (%2)"), buf, strerror(errno)) << endmsg;
142 throw failed_constructor();
147 /* we require _path to end with a dir separator */
149 if (_path[_path.length()-1] != G_DIR_SEPARATOR) {
150 _path += G_DIR_SEPARATOR;
155 _is_new = !Glib::file_test (_path, Glib::FileTest (G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR));
157 /* finish initialization that can't be done in a normal C++ constructor
161 timerclear (&last_mmc_step);
162 g_atomic_int_set (&processing_prohibited, 0);
163 g_atomic_int_set (&_record_status, Disabled);
164 g_atomic_int_set (&_playback_load, 100);
165 g_atomic_int_set (&_capture_load, 100);
167 _all_route_group->set_active (true, this);
168 interpolation.add_channel_to (0, 0);
170 if (config.get_use_video_sync()) {
171 waiting_for_sync_offset = true;
173 waiting_for_sync_offset = false;
176 last_rr_session_dir = session_dirs.begin();
178 set_history_depth (Config->get_history_depth());
180 if (how_many_dsp_threads () > 1) {
181 /* For now, only create the graph if we are using >1 DSP threads, as
182 it is a bit slower than the old code with 1 thread.
184 _process_graph.reset (new Graph (*this));
187 /* default: assume simple stereo speaker configuration */
189 _speakers->setup_default_speakers (2);
191 _solo_cut_control.reset (new ProxyControllable (_("solo cut control (dB)"), PBD::Controllable::GainLike,
192 boost::bind (&RCConfiguration::set_solo_mute_gain, Config, _1),
193 boost::bind (&RCConfiguration::get_solo_mute_gain, Config)));
194 add_controllable (_solo_cut_control);
196 /* These are all static "per-class" signals */
198 SourceFactory::SourceCreated.connect_same_thread (*this, boost::bind (&Session::add_source, this, _1));
199 PlaylistFactory::PlaylistCreated.connect_same_thread (*this, boost::bind (&Session::add_playlist, this, _1, _2));
200 AutomationList::AutomationListCreated.connect_same_thread (*this, boost::bind (&Session::add_automation_list, this, _1));
201 Controllable::Destroyed.connect_same_thread (*this, boost::bind (&Session::remove_controllable, this, _1));
202 IO::PortCountChanged.connect_same_thread (*this, boost::bind (&Session::ensure_buffers, this, _1));
204 /* stop IO objects from doing stuff until we're ready for them */
206 Delivery::disable_panners ();
207 IO::disable_connecting ();
209 AudioFileSource::set_peak_dir (_session_dir->peak_path());
213 Session::post_engine_init ()
215 BootMessage (_("Set block size and sample rate"));
217 set_block_size (_engine.samples_per_cycle());
218 set_frame_rate (_engine.sample_rate());
220 n_physical_outputs = _engine.n_physical_outputs ();
221 n_physical_inputs = _engine.n_physical_inputs ();
223 BootMessage (_("Using configuration"));
225 _midi_ports = new MidiPortManager;
226 setup_midi_machine_control ();
228 if (_butler->start_thread()) {
232 if (start_midi_thread ()) {
236 setup_click_sounds (0);
237 setup_midi_control ();
239 _engine.Halted.connect_same_thread (*this, boost::bind (&Session::engine_halted, this));
240 _engine.Xrun.connect_same_thread (*this, boost::bind (&Session::xrun_recovery, this));
243 /* tempo map requires sample rate knowledge */
245 _tempo_map = new TempoMap (_current_frame_rate);
246 _tempo_map->PropertyChanged.connect_same_thread (*this, boost::bind (&Session::tempo_map_changed, this, _1));
248 /* MidiClock requires a tempo map */
250 midi_clock = new MidiClockTicker ();
251 midi_clock->set_session (this);
253 /* crossfades require sample rate knowledge */
255 SndFileSource::setup_standard_crossfades (*this, frame_rate());
256 _engine.GraphReordered.connect_same_thread (*this, boost::bind (&Session::graph_reordered, this));
258 AudioDiskstream::allocate_working_buffers();
259 refresh_disk_space ();
261 /* we're finally ready to call set_state() ... all objects have
262 * been created, the engine is running.
266 if (set_state (*state_tree->root(), Stateful::loading_state_version)) {
270 // set_state() will call setup_raid_path(), but if it's a new session we need
271 // to call setup_raid_path() here.
272 setup_raid_path (_path);
277 boost::function<void (std::string)> ff (boost::bind (&Session::config_changed, this, _1, false));
278 boost::function<void (std::string)> ft (boost::bind (&Session::config_changed, this, _1, true));
280 Config->map_parameters (ff);
281 config.map_parameters (ft);
283 when_engine_running ();
285 _locations->changed.connect_same_thread (*this, boost::bind (&Session::locations_changed, this));
286 _locations->added.connect_same_thread (*this, boost::bind (&Session::locations_added, this, _1));
288 } catch (AudioEngine::PortRegistrationFailure& err) {
289 /* handle this one in a different way than all others, so that its clear what happened */
290 error << err.what() << endmsg;
296 BootMessage (_("Reset Remote Controls"));
298 // send_full_time_code (0);
299 _engine.transport_locate (0);
301 _mmc->send (MIDI::MachineControlCommand (MIDI::MachineControl::cmdMmcReset));
302 _mmc->send (MIDI::MachineControlCommand (Timecode::Time ()));
304 MIDI::Name::MidiPatchManager::instance().set_session (this);
307 /* initial program change will be delivered later; see ::config_changed() */
309 _state_of_the_state = Clean;
311 DirtyChanged (); /* EMIT SIGNAL */
315 } else if (state_was_pending) {
317 remove_pending_capture_state ();
318 state_was_pending = false;
325 Session::raid_path () const
327 SearchPath raid_search_path;
329 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
330 raid_search_path += (*i).path;
333 return raid_search_path.to_string ();
337 Session::setup_raid_path (string path)
346 session_dirs.clear ();
348 SearchPath search_path(path);
349 SearchPath sound_search_path;
350 SearchPath midi_search_path;
352 for (SearchPath::const_iterator i = search_path.begin(); i != search_path.end(); ++i) {
354 sp.blocks = 0; // not needed
355 session_dirs.push_back (sp);
357 SessionDirectory sdir(sp.path);
359 sound_search_path += sdir.sound_path ();
360 midi_search_path += sdir.midi_path ();
363 // reset the round-robin soundfile path thingie
364 last_rr_session_dir = session_dirs.begin();
368 Session::path_is_within_session (const std::string& path)
370 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
371 if (PBD::path_is_within (i->path, path)) {
379 Session::ensure_subdirs ()
383 dir = session_directory().peak_path();
385 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
386 error << string_compose(_("Session: cannot create session peakfile folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
390 dir = session_directory().sound_path();
392 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
393 error << string_compose(_("Session: cannot create session sounds dir \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
397 dir = session_directory().midi_path();
399 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
400 error << string_compose(_("Session: cannot create session midi dir \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
404 dir = session_directory().dead_path();
406 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
407 error << string_compose(_("Session: cannot create session dead sounds folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
411 dir = session_directory().export_path();
413 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
414 error << string_compose(_("Session: cannot create session export folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
418 dir = analysis_dir ();
420 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
421 error << string_compose(_("Session: cannot create session analysis folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
425 dir = plugins_dir ();
427 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
428 error << string_compose(_("Session: cannot create session plugins folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
432 dir = externals_dir ();
434 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
435 error << string_compose(_("Session: cannot create session externals folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
442 /** @param session_template directory containing session template, or empty.
443 * Caller must not hold process lock.
446 Session::create (const string& session_template, BusProfile* bus_profile)
448 if (g_mkdir_with_parents (_path.c_str(), 0755) < 0) {
449 error << string_compose(_("Session: cannot create session folder \"%1\" (%2)"), _path, strerror (errno)) << endmsg;
453 if (ensure_subdirs ()) {
457 _writable = exists_and_writable (_path);
459 if (!session_template.empty()) {
460 std::string in_path = session_template_dir_to_file (session_template);
462 ifstream in(in_path.c_str());
465 string out_path = _path;
467 out_path += statefile_suffix;
469 ofstream out(out_path.c_str());
475 /* Copy plugin state files from template to new session */
476 std::string template_plugins = Glib::build_filename (session_template, X_("plugins"));
477 copy_files (template_plugins, plugins_dir ());
482 error << string_compose (_("Could not open %1 for writing session template"), out_path)
488 error << string_compose (_("Could not open session template %1 for reading"), in_path)
495 /* set initial start + end point */
497 _state_of_the_state = Clean;
499 /* set up Master Out and Control Out if necessary */
504 ChanCount count(DataType::AUDIO, bus_profile->master_out_channels);
506 if (bus_profile->master_out_channels) {
507 boost::shared_ptr<Route> r (new Route (*this, _("master"), Route::MasterOut, DataType::AUDIO));
511 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
512 // boost_debug_shared_ptr_mark_interesting (r.get(), "Route");
515 Glib::Threads::Mutex::Lock lm (AudioEngine::instance()->process_lock ());
516 r->input()->ensure_io (count, false, this);
517 r->output()->ensure_io (count, false, this);
523 /* prohibit auto-connect to master, because there isn't one */
524 bus_profile->output_ac = AutoConnectOption (bus_profile->output_ac & ~AutoConnectMaster);
528 add_routes (rl, false, false, false);
531 /* this allows the user to override settings with an environment variable.
534 if (no_auto_connect()) {
535 bus_profile->input_ac = AutoConnectOption (0);
536 bus_profile->output_ac = AutoConnectOption (0);
539 Config->set_input_auto_connect (bus_profile->input_ac);
540 Config->set_output_auto_connect (bus_profile->output_ac);
543 if (Config->get_use_monitor_bus() && bus_profile) {
544 add_monitor_section ();
551 Session::maybe_write_autosave()
553 if (dirty() && record_status() != Recording) {
554 save_state("", true);
559 Session::remove_pending_capture_state ()
561 std::string pending_state_file_path(_session_dir->root_path());
563 pending_state_file_path = Glib::build_filename (pending_state_file_path, legalize_for_path (_current_snapshot_name) + pending_suffix);
565 if (!Glib::file_test (pending_state_file_path, Glib::FILE_TEST_EXISTS)) return;
567 if (g_remove (pending_state_file_path.c_str()) != 0) {
568 error << string_compose(_("Could not remove pending capture state at path \"%1\" (%2)"),
569 pending_state_file_path, g_strerror (errno)) << endmsg;
573 /** Rename a state file.
574 * @param old_name Old snapshot name.
575 * @param new_name New snapshot name.
578 Session::rename_state (string old_name, string new_name)
580 if (old_name == _current_snapshot_name || old_name == _name) {
581 /* refuse to rename the current snapshot or the "main" one */
585 const string old_xml_filename = legalize_for_path (old_name) + statefile_suffix;
586 const string new_xml_filename = legalize_for_path (new_name) + statefile_suffix;
588 const std::string old_xml_path(Glib::build_filename (_session_dir->root_path(), old_xml_filename));
589 const std::string new_xml_path(Glib::build_filename (_session_dir->root_path(), new_xml_filename));
591 if (::g_rename (old_xml_path.c_str(), new_xml_path.c_str()) != 0) {
592 error << string_compose(_("could not rename snapshot %1 to %2 (%3)"),
593 old_name, new_name, g_strerror(errno)) << endmsg;
597 /** Remove a state file.
598 * @param snapshot_name Snapshot name.
601 Session::remove_state (string snapshot_name)
603 if (!_writable || snapshot_name == _current_snapshot_name || snapshot_name == _name) {
604 // refuse to remove the current snapshot or the "main" one
608 std::string xml_path(_session_dir->root_path());
610 xml_path = Glib::build_filename (xml_path, legalize_for_path (snapshot_name) + statefile_suffix);
612 if (!create_backup_file (xml_path)) {
613 // don't remove it if a backup can't be made
614 // create_backup_file will log the error.
619 if (g_remove (xml_path.c_str()) != 0) {
620 error << string_compose(_("Could not remove session file at path \"%1\" (%2)"),
621 xml_path, g_strerror (errno)) << endmsg;
625 /** @param snapshot_name Name to save under, without .ardour / .pending prefix */
627 Session::save_state (string snapshot_name, bool pending, bool switch_to_snapshot)
630 std::string xml_path(_session_dir->root_path());
632 if (!_writable || (_state_of_the_state & CannotSave)) {
636 if (!_engine.connected ()) {
637 error << string_compose (_("the %1 audio engine is not connected and state saving would lose all I/O connections. Session not saved"),
643 /* tell sources we're saving first, in case they write out to a new file
644 * which should be saved with the state rather than the old one */
645 for (SourceMap::const_iterator i = sources.begin(); i != sources.end(); ++i) {
647 i->second->session_saved();
648 } catch (Evoral::SMF::FileError& e) {
649 error << string_compose ("Could not write to MIDI file %1; MIDI data not saved.", e.file_name ()) << endmsg;
653 SaveSession (); /* EMIT SIGNAL */
655 tree.set_root (&get_state());
657 if (snapshot_name.empty()) {
658 snapshot_name = _current_snapshot_name;
659 } else if (switch_to_snapshot) {
660 _current_snapshot_name = snapshot_name;
665 /* proper save: use statefile_suffix (.ardour in English) */
667 xml_path = Glib::build_filename (xml_path, legalize_for_path (snapshot_name) + statefile_suffix);
669 /* make a backup copy of the old file */
671 if (Glib::file_test (xml_path, Glib::FILE_TEST_EXISTS) && !create_backup_file (xml_path)) {
672 // create_backup_file will log the error
678 /* pending save: use pending_suffix (.pending in English) */
679 xml_path = Glib::build_filename (xml_path, legalize_for_path (snapshot_name) + pending_suffix);
682 std::string tmp_path(_session_dir->root_path());
683 tmp_path = Glib::build_filename (tmp_path, legalize_for_path (snapshot_name) + temp_suffix);
685 // cerr << "actually writing state to " << xml_path << endl;
687 if (!tree.write (tmp_path)) {
688 error << string_compose (_("state could not be saved to %1"), tmp_path) << endmsg;
689 if (g_remove (tmp_path.c_str()) != 0) {
690 error << string_compose(_("Could not remove temporary session file at path \"%1\" (%2)"),
691 tmp_path, g_strerror (errno)) << endmsg;
697 if (::rename (tmp_path.c_str(), xml_path.c_str()) != 0) {
698 error << string_compose (_("could not rename temporary session file %1 to %2"),
699 tmp_path, xml_path) << endmsg;
700 if (g_remove (tmp_path.c_str()) != 0) {
701 error << string_compose(_("Could not remove temporary session file at path \"%1\" (%2)"),
702 tmp_path, g_strerror (errno)) << endmsg;
710 save_history (snapshot_name);
712 bool was_dirty = dirty();
714 _state_of_the_state = StateOfTheState (_state_of_the_state & ~Dirty);
717 DirtyChanged (); /* EMIT SIGNAL */
720 StateSaved (snapshot_name); /* EMIT SIGNAL */
727 Session::restore_state (string snapshot_name)
729 if (load_state (snapshot_name) == 0) {
730 set_state (*state_tree->root(), Stateful::loading_state_version);
737 Session::load_state (string snapshot_name)
742 state_was_pending = false;
744 /* check for leftover pending state from a crashed capture attempt */
746 std::string xmlpath(_session_dir->root_path());
747 xmlpath = Glib::build_filename (xmlpath, legalize_for_path (snapshot_name) + pending_suffix);
749 if (Glib::file_test (xmlpath, Glib::FILE_TEST_EXISTS)) {
751 /* there is pending state from a crashed capture attempt */
753 boost::optional<int> r = AskAboutPendingState();
754 if (r.get_value_or (1)) {
755 state_was_pending = true;
759 if (!state_was_pending) {
760 xmlpath = Glib::build_filename (_session_dir->root_path(), snapshot_name);
763 if (!Glib::file_test (xmlpath, Glib::FILE_TEST_EXISTS)) {
764 xmlpath = Glib::build_filename (_session_dir->root_path(), legalize_for_path (snapshot_name) + statefile_suffix);
765 if (!Glib::file_test (xmlpath, Glib::FILE_TEST_EXISTS)) {
766 error << string_compose(_("%1: session file \"%2\" doesn't exist!"), _name, xmlpath) << endmsg;
771 state_tree = new XMLTree;
775 _writable = exists_and_writable (xmlpath);
777 if (!state_tree->read (xmlpath)) {
778 error << string_compose(_("Could not understand session file %1"), xmlpath) << endmsg;
784 XMLNode& root (*state_tree->root());
786 if (root.name() != X_("Session")) {
787 error << string_compose (_("Session file %1 is not a session"), xmlpath) << endmsg;
793 const XMLProperty* prop;
795 if ((prop = root.property ("version")) == 0) {
796 /* no version implies very old version of Ardour */
797 Stateful::loading_state_version = 1000;
799 if (prop->value().find ('.') != string::npos) {
800 /* old school version format */
801 if (prop->value()[0] == '2') {
802 Stateful::loading_state_version = 2000;
804 Stateful::loading_state_version = 3000;
807 Stateful::loading_state_version = atoi (prop->value());
811 if (Stateful::loading_state_version < CURRENT_SESSION_FILE_VERSION && _writable) {
813 std::string backup_path(_session_dir->root_path());
814 std::string backup_filename = string_compose ("%1-%2%3", legalize_for_path (snapshot_name), Stateful::loading_state_version, statefile_suffix);
815 backup_path = Glib::build_filename (backup_path, backup_filename);
817 // only create a backup for a given statefile version once
819 if (!Glib::file_test (backup_path, Glib::FILE_TEST_EXISTS)) {
821 VersionMismatch (xmlpath, backup_path);
823 if (!copy_file (xmlpath, backup_path)) {;
833 Session::load_options (const XMLNode& node)
835 LocaleGuard lg (X_("POSIX"));
836 config.set_variables (node);
847 Session::get_template()
849 /* if we don't disable rec-enable, diskstreams
850 will believe they need to store their capture
851 sources in their state node.
854 disable_record (false);
860 Session::state (bool full_state)
862 XMLNode* node = new XMLNode("Session");
866 snprintf(buf, sizeof(buf), "%d", CURRENT_SESSION_FILE_VERSION);
867 node->add_property("version", buf);
869 /* store configuration settings */
873 node->add_property ("name", _name);
874 snprintf (buf, sizeof (buf), "%" PRId64, _nominal_frame_rate);
875 node->add_property ("sample-rate", buf);
877 if (session_dirs.size() > 1) {
881 vector<space_and_path>::iterator i = session_dirs.begin();
882 vector<space_and_path>::iterator next;
884 ++i; /* skip the first one */
888 while (i != session_dirs.end()) {
892 if (next != session_dirs.end()) {
902 child = node->add_child ("Path");
903 child->add_content (p);
907 /* save the ID counter */
909 snprintf (buf, sizeof (buf), "%" PRIu64, ID::counter());
910 node->add_property ("id-counter", buf);
912 /* save the event ID counter */
914 snprintf (buf, sizeof (buf), "%d", Evoral::event_id_counter());
915 node->add_property ("event-counter", buf);
917 /* various options */
919 list<XMLNode*> midi_port_nodes = _midi_ports->get_midi_port_states();
920 if (!midi_port_nodes.empty()) {
921 XMLNode* midi_port_stuff = new XMLNode ("MIDIPorts");
922 for (list<XMLNode*>::const_iterator n = midi_port_nodes.begin(); n != midi_port_nodes.end(); ++n) {
923 midi_port_stuff->add_child_nocopy (**n);
925 node->add_child_nocopy (*midi_port_stuff);
928 node->add_child_nocopy (config.get_variables ());
930 node->add_child_nocopy (ARDOUR::SessionMetadata::Metadata()->get_state());
932 child = node->add_child ("Sources");
935 Glib::Threads::Mutex::Lock sl (source_lock);
937 for (SourceMap::iterator siter = sources.begin(); siter != sources.end(); ++siter) {
939 /* Don't save information about non-file Sources, or
940 * about non-destructive file sources that are empty
941 * and unused by any regions.
944 boost::shared_ptr<FileSource> fs;
946 if ((fs = boost::dynamic_pointer_cast<FileSource> (siter->second)) != 0) {
948 if (!fs->destructive()) {
949 if (fs->empty() && !fs->used()) {
954 child->add_child_nocopy (siter->second->get_state());
959 child = node->add_child ("Regions");
962 Glib::Threads::Mutex::Lock rl (region_lock);
963 const RegionFactory::RegionMap& region_map (RegionFactory::all_regions());
964 for (RegionFactory::RegionMap::const_iterator i = region_map.begin(); i != region_map.end(); ++i) {
965 boost::shared_ptr<Region> r = i->second;
966 /* only store regions not attached to playlists */
967 if (r->playlist() == 0) {
968 if (boost::dynamic_pointer_cast<AudioRegion>(r)) {
969 child->add_child_nocopy ((boost::dynamic_pointer_cast<AudioRegion>(r))->get_basic_state ());
971 child->add_child_nocopy (r->get_state ());
976 RegionFactory::CompoundAssociations& cassocs (RegionFactory::compound_associations());
978 if (!cassocs.empty()) {
979 XMLNode* ca = node->add_child (X_("CompoundAssociations"));
981 for (RegionFactory::CompoundAssociations::iterator i = cassocs.begin(); i != cassocs.end(); ++i) {
983 XMLNode* can = new XMLNode (X_("CompoundAssociation"));
984 i->first->id().print (buf, sizeof (buf));
985 can->add_property (X_("copy"), buf);
986 i->second->id().print (buf, sizeof (buf));
987 can->add_property (X_("original"), buf);
988 ca->add_child_nocopy (*can);
994 node->add_child_nocopy (_locations->get_state());
996 // for a template, just create a new Locations, populate it
997 // with the default start and end, and get the state for that.
998 Locations loc (*this);
999 Location* range = new Location (*this, 0, 0, _("session"), Location::IsSessionRange);
1000 range->set (max_framepos, 0);
1002 node->add_child_nocopy (loc.get_state());
1005 child = node->add_child ("Bundles");
1007 boost::shared_ptr<BundleList> bundles = _bundles.reader ();
1008 for (BundleList::iterator i = bundles->begin(); i != bundles->end(); ++i) {
1009 boost::shared_ptr<UserBundle> b = boost::dynamic_pointer_cast<UserBundle> (*i);
1011 child->add_child_nocopy (b->get_state());
1016 child = node->add_child ("Routes");
1018 boost::shared_ptr<RouteList> r = routes.reader ();
1020 RoutePublicOrderSorter cmp;
1021 RouteList public_order (*r);
1022 public_order.sort (cmp);
1024 /* the sort should have put control outs first */
1027 assert (_monitor_out == public_order.front());
1030 for (RouteList::iterator i = public_order.begin(); i != public_order.end(); ++i) {
1031 if (!(*i)->is_auditioner()) {
1033 child->add_child_nocopy ((*i)->get_state());
1035 child->add_child_nocopy ((*i)->get_template());
1041 playlists->add_state (node, full_state);
1043 child = node->add_child ("RouteGroups");
1044 for (list<RouteGroup *>::iterator i = _route_groups.begin(); i != _route_groups.end(); ++i) {
1045 child->add_child_nocopy ((*i)->get_state());
1049 XMLNode* gain_child = node->add_child ("Click");
1050 gain_child->add_child_nocopy (_click_io->state (full_state));
1051 gain_child->add_child_nocopy (_click_gain->state (full_state));
1055 XMLNode* ltc_input_child = node->add_child ("LTC-In");
1056 ltc_input_child->add_child_nocopy (_ltc_input->state (full_state));
1060 XMLNode* ltc_output_child = node->add_child ("LTC-Out");
1061 ltc_output_child->add_child_nocopy (_ltc_output->state (full_state));
1064 node->add_child_nocopy (_speakers->get_state());
1065 node->add_child_nocopy (_tempo_map->get_state());
1066 node->add_child_nocopy (get_control_protocol_state());
1069 node->add_child_copy (*_extra_xml);
1076 Session::get_control_protocol_state ()
1078 ControlProtocolManager& cpm (ControlProtocolManager::instance());
1079 return cpm.get_state();
1083 Session::set_state (const XMLNode& node, int version)
1087 const XMLProperty* prop;
1090 _state_of_the_state = StateOfTheState (_state_of_the_state|CannotSave);
1092 if (node.name() != X_("Session")) {
1093 fatal << _("programming error: Session: incorrect XML node sent to set_state()") << endmsg;
1097 if ((prop = node.property ("name")) != 0) {
1098 _name = prop->value ();
1101 if ((prop = node.property (X_("sample-rate"))) != 0) {
1103 _nominal_frame_rate = atoi (prop->value());
1105 if (_nominal_frame_rate != _current_frame_rate) {
1106 boost::optional<int> r = AskAboutSampleRateMismatch (_nominal_frame_rate, _current_frame_rate);
1107 if (r.get_value_or (0)) {
1113 setup_raid_path(_session_dir->root_path());
1115 if ((prop = node.property (X_("id-counter"))) != 0) {
1117 sscanf (prop->value().c_str(), "%" PRIu64, &x);
1118 ID::init_counter (x);
1120 /* old sessions used a timebased counter, so fake
1121 the startup ID counter based on a standard
1126 ID::init_counter (now);
1129 if ((prop = node.property (X_("event-counter"))) != 0) {
1130 Evoral::init_event_id_counter (atoi (prop->value()));
1134 if ((child = find_named_node (node, "MIDIPorts")) != 0) {
1135 _midi_ports->set_midi_port_states (child->children());
1138 IO::disable_connecting ();
1140 Stateful::save_extra_xml (node);
1142 if (((child = find_named_node (node, "Options")) != 0)) { /* old style */
1143 load_options (*child);
1144 } else if ((child = find_named_node (node, "Config")) != 0) { /* new style */
1145 load_options (*child);
1147 error << _("Session: XML state has no options section") << endmsg;
1150 if (version >= 3000) {
1151 if ((child = find_named_node (node, "Metadata")) == 0) {
1152 warning << _("Session: XML state has no metadata section") << endmsg;
1153 } else if ( ARDOUR::SessionMetadata::Metadata()->set_state (*child, version) ) {
1158 if ((child = find_named_node (node, X_("Speakers"))) != 0) {
1159 _speakers->set_state (*child, version);
1162 if ((child = find_named_node (node, "Sources")) == 0) {
1163 error << _("Session: XML state has no sources section") << endmsg;
1165 } else if (load_sources (*child)) {
1169 if ((child = find_named_node (node, "TempoMap")) == 0) {
1170 error << _("Session: XML state has no Tempo Map section") << endmsg;
1172 } else if (_tempo_map->set_state (*child, version)) {
1176 if ((child = find_named_node (node, "Locations")) == 0) {
1177 error << _("Session: XML state has no locations section") << endmsg;
1179 } else if (_locations->set_state (*child, version)) {
1185 if ((location = _locations->auto_loop_location()) != 0) {
1186 set_auto_loop_location (location);
1189 if ((location = _locations->auto_punch_location()) != 0) {
1190 set_auto_punch_location (location);
1193 if ((location = _locations->session_range_location()) != 0) {
1194 delete _session_range_location;
1195 _session_range_location = location;
1198 if (_session_range_location) {
1199 AudioFileSource::set_header_position_offset (_session_range_location->start());
1202 if ((child = find_named_node (node, "Regions")) == 0) {
1203 error << _("Session: XML state has no Regions section") << endmsg;
1205 } else if (load_regions (*child)) {
1209 if ((child = find_named_node (node, "Playlists")) == 0) {
1210 error << _("Session: XML state has no playlists section") << endmsg;
1212 } else if (playlists->load (*this, *child)) {
1216 if ((child = find_named_node (node, "UnusedPlaylists")) == 0) {
1218 } else if (playlists->load_unused (*this, *child)) {
1222 if ((child = find_named_node (node, "CompoundAssociations")) != 0) {
1223 if (load_compounds (*child)) {
1228 if (version >= 3000) {
1229 if ((child = find_named_node (node, "Bundles")) == 0) {
1230 warning << _("Session: XML state has no bundles section") << endmsg;
1233 /* We can't load Bundles yet as they need to be able
1234 to convert from port names to Port objects, which can't happen until
1236 _bundle_xml_node = new XMLNode (*child);
1240 if (version < 3000) {
1241 if ((child = find_named_node (node, X_("DiskStreams"))) == 0) {
1242 error << _("Session: XML state has no diskstreams section") << endmsg;
1244 } else if (load_diskstreams_2X (*child, version)) {
1249 if ((child = find_named_node (node, "Routes")) == 0) {
1250 error << _("Session: XML state has no routes section") << endmsg;
1252 } else if (load_routes (*child, version)) {
1256 /* our diskstreams list is no longer needed as they are now all owned by their Route */
1257 _diskstreams_2X.clear ();
1259 if (version >= 3000) {
1261 if ((child = find_named_node (node, "RouteGroups")) == 0) {
1262 error << _("Session: XML state has no route groups section") << endmsg;
1264 } else if (load_route_groups (*child, version)) {
1268 } else if (version < 3000) {
1270 if ((child = find_named_node (node, "EditGroups")) == 0) {
1271 error << _("Session: XML state has no edit groups section") << endmsg;
1273 } else if (load_route_groups (*child, version)) {
1277 if ((child = find_named_node (node, "MixGroups")) == 0) {
1278 error << _("Session: XML state has no mix groups section") << endmsg;
1280 } else if (load_route_groups (*child, version)) {
1285 if ((child = find_named_node (node, "Click")) == 0) {
1286 warning << _("Session: XML state has no click section") << endmsg;
1287 } else if (_click_io) {
1288 const XMLNodeList& children (child->children());
1289 XMLNodeList::const_iterator i = children.begin();
1290 _click_io->set_state (**i, version);
1292 if (i != children.end()) {
1293 _click_gain->set_state (**i, version);
1297 if ((child = find_named_node (node, ControlProtocolManager::state_node_name)) != 0) {
1298 ControlProtocolManager::instance().set_state (*child, version);
1301 update_have_rec_enabled_track ();
1303 /* here beginneth the second phase ... */
1305 StateReady (); /* EMIT SIGNAL */
1314 Session::load_routes (const XMLNode& node, int version)
1317 XMLNodeConstIterator niter;
1318 RouteList new_routes;
1320 nlist = node.children();
1324 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1326 boost::shared_ptr<Route> route;
1327 if (version < 3000) {
1328 route = XMLRouteFactory_2X (**niter, version);
1330 route = XMLRouteFactory (**niter, version);
1334 error << _("Session: cannot create Route from XML description.") << endmsg;
1338 BootMessage (string_compose (_("Loaded track/bus %1"), route->name()));
1340 new_routes.push_back (route);
1343 add_routes (new_routes, false, false, false);
1348 boost::shared_ptr<Route>
1349 Session::XMLRouteFactory (const XMLNode& node, int version)
1351 boost::shared_ptr<Route> ret;
1353 if (node.name() != "Route") {
1357 XMLNode* ds_child = find_named_node (node, X_("Diskstream"));
1359 DataType type = DataType::AUDIO;
1360 const XMLProperty* prop = node.property("default-type");
1363 type = DataType (prop->value());
1366 assert (type != DataType::NIL);
1370 boost::shared_ptr<Track> track;
1372 if (type == DataType::AUDIO) {
1373 track.reset (new AudioTrack (*this, X_("toBeResetFroXML")));
1375 track.reset (new MidiTrack (*this, X_("toBeResetFroXML")));
1378 if (track->init()) {
1382 if (track->set_state (node, version)) {
1386 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
1387 // boost_debug_shared_ptr_mark_interesting (track.get(), "Track");
1392 boost::shared_ptr<Route> r (new Route (*this, X_("toBeResetFroXML")));
1394 if (r->init () == 0 && r->set_state (node, version) == 0) {
1395 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
1396 // boost_debug_shared_ptr_mark_interesting (r.get(), "Route");
1405 boost::shared_ptr<Route>
1406 Session::XMLRouteFactory_2X (const XMLNode& node, int version)
1408 boost::shared_ptr<Route> ret;
1410 if (node.name() != "Route") {
1414 XMLProperty const * ds_prop = node.property (X_("diskstream-id"));
1416 ds_prop = node.property (X_("diskstream"));
1419 DataType type = DataType::AUDIO;
1420 const XMLProperty* prop = node.property("default-type");
1423 type = DataType (prop->value());
1426 assert (type != DataType::NIL);
1430 list<boost::shared_ptr<Diskstream> >::iterator i = _diskstreams_2X.begin ();
1431 while (i != _diskstreams_2X.end() && (*i)->id() != ds_prop->value()) {
1435 if (i == _diskstreams_2X.end()) {
1436 error << _("Could not find diskstream for route") << endmsg;
1437 return boost::shared_ptr<Route> ();
1440 boost::shared_ptr<Track> track;
1442 if (type == DataType::AUDIO) {
1443 track.reset (new AudioTrack (*this, X_("toBeResetFroXML")));
1445 track.reset (new MidiTrack (*this, X_("toBeResetFroXML")));
1448 if (track->init()) {
1452 if (track->set_state (node, version)) {
1456 track->set_diskstream (*i);
1458 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
1459 // boost_debug_shared_ptr_mark_interesting (track.get(), "Track");
1464 boost::shared_ptr<Route> r (new Route (*this, X_("toBeResetFroXML")));
1466 if (r->init () == 0 && r->set_state (node, version) == 0) {
1467 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
1468 // boost_debug_shared_ptr_mark_interesting (r.get(), "Route");
1478 Session::load_regions (const XMLNode& node)
1481 XMLNodeConstIterator niter;
1482 boost::shared_ptr<Region> region;
1484 nlist = node.children();
1488 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1489 if ((region = XMLRegionFactory (**niter, false)) == 0) {
1490 error << _("Session: cannot create Region from XML description.");
1491 const XMLProperty *name = (**niter).property("name");
1494 error << " " << string_compose (_("Can not load state for region '%1'"), name->value());
1505 Session::load_compounds (const XMLNode& node)
1507 XMLNodeList calist = node.children();
1508 XMLNodeConstIterator caiter;
1509 XMLProperty *caprop;
1511 for (caiter = calist.begin(); caiter != calist.end(); ++caiter) {
1512 XMLNode* ca = *caiter;
1516 if ((caprop = ca->property (X_("original"))) == 0) {
1519 orig_id = caprop->value();
1521 if ((caprop = ca->property (X_("copy"))) == 0) {
1524 copy_id = caprop->value();
1526 boost::shared_ptr<Region> orig = RegionFactory::region_by_id (orig_id);
1527 boost::shared_ptr<Region> copy = RegionFactory::region_by_id (copy_id);
1529 if (!orig || !copy) {
1530 warning << string_compose (_("Regions in compound description not found (ID's %1 and %2): ignored"),
1536 RegionFactory::add_compound_association (orig, copy);
1543 Session::load_nested_sources (const XMLNode& node)
1546 XMLNodeConstIterator niter;
1548 nlist = node.children();
1550 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1551 if ((*niter)->name() == "Source") {
1553 /* it may already exist, so don't recreate it unnecessarily
1556 XMLProperty* prop = (*niter)->property (X_("id"));
1558 error << _("Nested source has no ID info in session file! (ignored)") << endmsg;
1562 ID source_id (prop->value());
1564 if (!source_by_id (source_id)) {
1567 SourceFactory::create (*this, **niter, true);
1569 catch (failed_constructor& err) {
1570 error << string_compose (_("Cannot reconstruct nested source for region %1"), name()) << endmsg;
1577 boost::shared_ptr<Region>
1578 Session::XMLRegionFactory (const XMLNode& node, bool full)
1580 const XMLProperty* type = node.property("type");
1584 const XMLNodeList& nlist = node.children();
1586 for (XMLNodeConstIterator niter = nlist.begin(); niter != nlist.end(); ++niter) {
1587 XMLNode *child = (*niter);
1588 if (child->name() == "NestedSource") {
1589 load_nested_sources (*child);
1593 if (!type || type->value() == "audio") {
1594 return boost::shared_ptr<Region>(XMLAudioRegionFactory (node, full));
1595 } else if (type->value() == "midi") {
1596 return boost::shared_ptr<Region>(XMLMidiRegionFactory (node, full));
1599 } catch (failed_constructor& err) {
1600 return boost::shared_ptr<Region> ();
1603 return boost::shared_ptr<Region> ();
1606 boost::shared_ptr<AudioRegion>
1607 Session::XMLAudioRegionFactory (const XMLNode& node, bool /*full*/)
1609 const XMLProperty* prop;
1610 boost::shared_ptr<Source> source;
1611 boost::shared_ptr<AudioSource> as;
1613 SourceList master_sources;
1614 uint32_t nchans = 1;
1617 if (node.name() != X_("Region")) {
1618 return boost::shared_ptr<AudioRegion>();
1621 if ((prop = node.property (X_("channels"))) != 0) {
1622 nchans = atoi (prop->value().c_str());
1625 if ((prop = node.property ("name")) == 0) {
1626 cerr << "no name for this region\n";
1630 if ((prop = node.property (X_("source-0"))) == 0) {
1631 if ((prop = node.property ("source")) == 0) {
1632 error << _("Session: XMLNode describing a AudioRegion is incomplete (no source)") << endmsg;
1633 return boost::shared_ptr<AudioRegion>();
1637 PBD::ID s_id (prop->value());
1639 if ((source = source_by_id (s_id)) == 0) {
1640 error << string_compose(_("Session: XMLNode describing a AudioRegion references an unknown source id =%1"), s_id) << endmsg;
1641 return boost::shared_ptr<AudioRegion>();
1644 as = boost::dynamic_pointer_cast<AudioSource>(source);
1646 error << string_compose(_("Session: XMLNode describing a AudioRegion references a non-audio source id =%1"), s_id) << endmsg;
1647 return boost::shared_ptr<AudioRegion>();
1650 sources.push_back (as);
1652 /* pickup other channels */
1654 for (uint32_t n=1; n < nchans; ++n) {
1655 snprintf (buf, sizeof(buf), X_("source-%d"), n);
1656 if ((prop = node.property (buf)) != 0) {
1658 PBD::ID id2 (prop->value());
1660 if ((source = source_by_id (id2)) == 0) {
1661 error << string_compose(_("Session: XMLNode describing a AudioRegion references an unknown source id =%1"), id2) << endmsg;
1662 return boost::shared_ptr<AudioRegion>();
1665 as = boost::dynamic_pointer_cast<AudioSource>(source);
1667 error << string_compose(_("Session: XMLNode describing a AudioRegion references a non-audio source id =%1"), id2) << endmsg;
1668 return boost::shared_ptr<AudioRegion>();
1670 sources.push_back (as);
1674 for (uint32_t n = 0; n < nchans; ++n) {
1675 snprintf (buf, sizeof(buf), X_("master-source-%d"), n);
1676 if ((prop = node.property (buf)) != 0) {
1678 PBD::ID id2 (prop->value());
1680 if ((source = source_by_id (id2)) == 0) {
1681 error << string_compose(_("Session: XMLNode describing a AudioRegion references an unknown source id =%1"), id2) << endmsg;
1682 return boost::shared_ptr<AudioRegion>();
1685 as = boost::dynamic_pointer_cast<AudioSource>(source);
1687 error << string_compose(_("Session: XMLNode describing a AudioRegion references a non-audio source id =%1"), id2) << endmsg;
1688 return boost::shared_ptr<AudioRegion>();
1690 master_sources.push_back (as);
1695 boost::shared_ptr<AudioRegion> region (boost::dynamic_pointer_cast<AudioRegion> (RegionFactory::create (sources, node)));
1697 /* a final detail: this is the one and only place that we know how long missing files are */
1699 if (region->whole_file()) {
1700 for (SourceList::iterator sx = sources.begin(); sx != sources.end(); ++sx) {
1701 boost::shared_ptr<SilentFileSource> sfp = boost::dynamic_pointer_cast<SilentFileSource> (*sx);
1703 sfp->set_length (region->length());
1708 if (!master_sources.empty()) {
1709 if (master_sources.size() != nchans) {
1710 error << _("Session: XMLNode describing an AudioRegion is missing some master sources; ignored") << endmsg;
1712 region->set_master_sources (master_sources);
1720 catch (failed_constructor& err) {
1721 return boost::shared_ptr<AudioRegion>();
1725 boost::shared_ptr<MidiRegion>
1726 Session::XMLMidiRegionFactory (const XMLNode& node, bool /*full*/)
1728 const XMLProperty* prop;
1729 boost::shared_ptr<Source> source;
1730 boost::shared_ptr<MidiSource> ms;
1733 if (node.name() != X_("Region")) {
1734 return boost::shared_ptr<MidiRegion>();
1737 if ((prop = node.property ("name")) == 0) {
1738 cerr << "no name for this region\n";
1742 if ((prop = node.property (X_("source-0"))) == 0) {
1743 if ((prop = node.property ("source")) == 0) {
1744 error << _("Session: XMLNode describing a MidiRegion is incomplete (no source)") << endmsg;
1745 return boost::shared_ptr<MidiRegion>();
1749 PBD::ID s_id (prop->value());
1751 if ((source = source_by_id (s_id)) == 0) {
1752 error << string_compose(_("Session: XMLNode describing a MidiRegion references an unknown source id =%1"), s_id) << endmsg;
1753 return boost::shared_ptr<MidiRegion>();
1756 ms = boost::dynamic_pointer_cast<MidiSource>(source);
1758 error << string_compose(_("Session: XMLNode describing a MidiRegion references a non-midi source id =%1"), s_id) << endmsg;
1759 return boost::shared_ptr<MidiRegion>();
1762 sources.push_back (ms);
1765 boost::shared_ptr<MidiRegion> region (boost::dynamic_pointer_cast<MidiRegion> (RegionFactory::create (sources, node)));
1766 /* a final detail: this is the one and only place that we know how long missing files are */
1768 if (region->whole_file()) {
1769 for (SourceList::iterator sx = sources.begin(); sx != sources.end(); ++sx) {
1770 boost::shared_ptr<SilentFileSource> sfp = boost::dynamic_pointer_cast<SilentFileSource> (*sx);
1772 sfp->set_length (region->length());
1780 catch (failed_constructor& err) {
1781 return boost::shared_ptr<MidiRegion>();
1786 Session::get_sources_as_xml ()
1789 XMLNode* node = new XMLNode (X_("Sources"));
1790 Glib::Threads::Mutex::Lock lm (source_lock);
1792 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ++i) {
1793 node->add_child_nocopy (i->second->get_state());
1800 Session::path_from_region_name (DataType type, string name, string identifier)
1802 char buf[PATH_MAX+1];
1804 SessionDirectory sdir(get_best_session_directory_for_new_source());
1805 std::string source_dir = ((type == DataType::AUDIO)
1806 ? sdir.sound_path() : sdir.midi_path());
1808 string ext = native_header_format_extension (config.get_native_file_header_format(), type);
1810 for (n = 0; n < 999999; ++n) {
1811 if (identifier.length()) {
1812 snprintf (buf, sizeof(buf), "%s%s%" PRIu32 "%s", name.c_str(),
1813 identifier.c_str(), n, ext.c_str());
1815 snprintf (buf, sizeof(buf), "%s-%" PRIu32 "%s", name.c_str(),
1819 std::string source_path = Glib::build_filename (source_dir, buf);
1821 if (!Glib::file_test (source_path, Glib::FILE_TEST_EXISTS)) {
1826 error << string_compose (_("cannot create new file from region name \"%1\" with ident = \"%2\": too many existing files with similar names"),
1835 Session::load_sources (const XMLNode& node)
1838 XMLNodeConstIterator niter;
1839 boost::shared_ptr<Source> source;
1841 nlist = node.children();
1845 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1848 if ((source = XMLSourceFactory (**niter)) == 0) {
1849 error << _("Session: cannot create Source from XML description.") << endmsg;
1852 } catch (MissingSource& err) {
1856 if (!no_questions_about_missing_files) {
1857 user_choice = MissingFile (this, err.path, err.type).get_value_or (-1);
1862 switch (user_choice) {
1864 /* user added a new search location, so try again */
1869 /* user asked to quit the entire session load
1874 no_questions_about_missing_files = true;
1878 no_questions_about_missing_files = true;
1883 warning << _("A sound file is missing. It will be replaced by silence.") << endmsg;
1884 source = SourceFactory::createSilent (*this, **niter, max_framecnt, _current_frame_rate);
1893 boost::shared_ptr<Source>
1894 Session::XMLSourceFactory (const XMLNode& node)
1896 if (node.name() != "Source") {
1897 return boost::shared_ptr<Source>();
1901 /* note: do peak building in another thread when loading session state */
1902 return SourceFactory::create (*this, node, true);
1905 catch (failed_constructor& err) {
1906 error << string_compose (_("Found a sound file that cannot be used by %1. Talk to the progammers."), PROGRAM_NAME) << endmsg;
1907 return boost::shared_ptr<Source>();
1912 Session::save_template (string template_name)
1916 if (_state_of_the_state & CannotSave) {
1920 std::string user_template_dir(user_template_directory());
1922 if (g_mkdir_with_parents (user_template_dir.c_str(), 0755) != 0) {
1923 error << string_compose(_("Could not create templates directory \"%1\" (%2)"),
1924 user_template_dir, g_strerror (errno)) << endmsg;
1928 tree.set_root (&get_template());
1930 std::string template_dir_path(user_template_dir);
1932 /* directory to put the template in */
1933 template_dir_path = Glib::build_filename (template_dir_path, template_name);
1935 if (Glib::file_test (template_dir_path, Glib::FILE_TEST_EXISTS)) {
1936 warning << string_compose(_("Template \"%1\" already exists - new version not created"),
1937 template_dir_path) << endmsg;
1941 if (g_mkdir_with_parents (template_dir_path.c_str(), 0755) != 0) {
1942 error << string_compose(_("Could not create directory for Session template\"%1\" (%2)"),
1943 template_dir_path, g_strerror (errno)) << endmsg;
1948 std::string template_file_path(template_dir_path);
1949 template_file_path = Glib::build_filename (template_file_path, template_name + template_suffix);
1951 if (!tree.write (template_file_path)) {
1952 error << _("template not saved") << endmsg;
1956 /* copy plugin state directory */
1958 std::string template_plugin_state_path(template_dir_path);
1959 template_plugin_state_path = Glib::build_filename (template_plugin_state_path, X_("plugins"));
1961 if (g_mkdir_with_parents (template_plugin_state_path.c_str(), 0755) != 0) {
1962 error << string_compose(_("Could not create directory for Session template plugin state\"%1\" (%2)"),
1963 template_plugin_state_path, g_strerror (errno)) << endmsg;
1967 copy_files (plugins_dir(), template_plugin_state_path);
1973 Session::refresh_disk_space ()
1975 #if __APPLE__ || (HAVE_SYS_VFS_H && HAVE_SYS_STATVFS_H)
1977 Glib::Threads::Mutex::Lock lm (space_lock);
1979 /* get freespace on every FS that is part of the session path */
1981 _total_free_4k_blocks = 0;
1982 _total_free_4k_blocks_uncertain = false;
1984 for (vector<space_and_path>::iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
1986 struct statfs statfsbuf;
1987 statfs (i->path.c_str(), &statfsbuf);
1989 double const scale = statfsbuf.f_bsize / 4096.0;
1991 /* See if this filesystem is read-only */
1992 struct statvfs statvfsbuf;
1993 statvfs (i->path.c_str(), &statvfsbuf);
1995 /* f_bavail can be 0 if it is undefined for whatever
1996 filesystem we are looking at; Samba shares mounted
1997 via GVFS are an example of this.
1999 if (statfsbuf.f_bavail == 0) {
2000 /* block count unknown */
2002 i->blocks_unknown = true;
2003 } else if (statvfsbuf.f_flag & ST_RDONLY) {
2004 /* read-only filesystem */
2006 i->blocks_unknown = false;
2008 /* read/write filesystem with known space */
2009 i->blocks = (uint32_t) floor (statfsbuf.f_bavail * scale);
2010 i->blocks_unknown = false;
2013 _total_free_4k_blocks += i->blocks;
2014 if (i->blocks_unknown) {
2015 _total_free_4k_blocks_uncertain = true;
2022 Session::get_best_session_directory_for_new_source ()
2024 vector<space_and_path>::iterator i;
2025 string result = _session_dir->root_path();
2027 /* handle common case without system calls */
2029 if (session_dirs.size() == 1) {
2033 /* OK, here's the algorithm we're following here:
2035 We want to select which directory to use for
2036 the next file source to be created. Ideally,
2037 we'd like to use a round-robin process so as to
2038 get maximum performance benefits from splitting
2039 the files across multiple disks.
2041 However, in situations without much diskspace, an
2042 RR approach may end up filling up a filesystem
2043 with new files while others still have space.
2044 Its therefore important to pay some attention to
2045 the freespace in the filesystem holding each
2046 directory as well. However, if we did that by
2047 itself, we'd keep creating new files in the file
2048 system with the most space until it was as full
2049 as all others, thus negating any performance
2050 benefits of this RAID-1 like approach.
2052 So, we use a user-configurable space threshold. If
2053 there are at least 2 filesystems with more than this
2054 much space available, we use RR selection between them.
2055 If not, then we pick the filesystem with the most space.
2057 This gets a good balance between the two
2061 refresh_disk_space ();
2063 int free_enough = 0;
2065 for (i = session_dirs.begin(); i != session_dirs.end(); ++i) {
2066 if ((*i).blocks * 4096 >= Config->get_disk_choice_space_threshold()) {
2071 if (free_enough >= 2) {
2072 /* use RR selection process, ensuring that the one
2076 i = last_rr_session_dir;
2079 if (++i == session_dirs.end()) {
2080 i = session_dirs.begin();
2083 if ((*i).blocks * 4096 >= Config->get_disk_choice_space_threshold()) {
2084 SessionDirectory sdir(i->path);
2085 if (sdir.create ()) {
2087 last_rr_session_dir = i;
2092 } while (i != last_rr_session_dir);
2096 /* pick FS with the most freespace (and that
2097 seems to actually work ...)
2100 vector<space_and_path> sorted;
2101 space_and_path_ascending_cmp cmp;
2103 sorted = session_dirs;
2104 sort (sorted.begin(), sorted.end(), cmp);
2106 for (i = sorted.begin(); i != sorted.end(); ++i) {
2107 SessionDirectory sdir(i->path);
2108 if (sdir.create ()) {
2110 last_rr_session_dir = i;
2120 Session::automation_dir () const
2122 return Glib::build_filename (_path, "automation");
2126 Session::analysis_dir () const
2128 return Glib::build_filename (_path, "analysis");
2132 Session::plugins_dir () const
2134 return Glib::build_filename (_path, "plugins");
2138 Session::externals_dir () const
2140 return Glib::build_filename (_path, "externals");
2144 Session::load_bundles (XMLNode const & node)
2146 XMLNodeList nlist = node.children();
2147 XMLNodeConstIterator niter;
2151 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2152 if ((*niter)->name() == "InputBundle") {
2153 add_bundle (boost::shared_ptr<UserBundle> (new UserBundle (**niter, true)));
2154 } else if ((*niter)->name() == "OutputBundle") {
2155 add_bundle (boost::shared_ptr<UserBundle> (new UserBundle (**niter, false)));
2157 error << string_compose(_("Unknown node \"%1\" found in Bundles list from session file"), (*niter)->name()) << endmsg;
2166 Session::load_route_groups (const XMLNode& node, int version)
2168 XMLNodeList nlist = node.children();
2169 XMLNodeConstIterator niter;
2173 if (version >= 3000) {
2175 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2176 if ((*niter)->name() == "RouteGroup") {
2177 RouteGroup* rg = new RouteGroup (*this, "");
2178 add_route_group (rg);
2179 rg->set_state (**niter, version);
2183 } else if (version < 3000) {
2185 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2186 if ((*niter)->name() == "EditGroup" || (*niter)->name() == "MixGroup") {
2187 RouteGroup* rg = new RouteGroup (*this, "");
2188 add_route_group (rg);
2189 rg->set_state (**niter, version);
2198 Session::auto_save()
2200 save_state (_current_snapshot_name);
2204 state_file_filter (const string &str, void */*arg*/)
2206 return (str.length() > strlen(statefile_suffix) &&
2207 str.find (statefile_suffix) == (str.length() - strlen (statefile_suffix)));
2211 bool operator()(const string* a, const string* b) {
2217 remove_end(string* state)
2219 string statename(*state);
2221 string::size_type start,end;
2222 if ((start = statename.find_last_of (G_DIR_SEPARATOR)) != string::npos) {
2223 statename = statename.substr (start+1);
2226 if ((end = statename.rfind(".ardour")) == string::npos) {
2227 end = statename.length();
2230 return new string(statename.substr (0, end));
2234 Session::possible_states (string path)
2236 PathScanner scanner;
2237 vector<string*>* states = scanner (path, state_file_filter, 0, false, false);
2239 transform(states->begin(), states->end(), states->begin(), remove_end);
2242 sort (states->begin(), states->end(), cmp);
2248 Session::possible_states () const
2250 return possible_states(_path);
2254 Session::add_route_group (RouteGroup* g)
2256 _route_groups.push_back (g);
2257 route_group_added (g); /* EMIT SIGNAL */
2259 g->RouteAdded.connect_same_thread (*this, boost::bind (&Session::route_added_to_route_group, this, _1, _2));
2260 g->RouteRemoved.connect_same_thread (*this, boost::bind (&Session::route_removed_from_route_group, this, _1, _2));
2261 g->PropertyChanged.connect_same_thread (*this, boost::bind (&Session::route_group_property_changed, this, g));
2267 Session::remove_route_group (RouteGroup& rg)
2269 list<RouteGroup*>::iterator i;
2271 if ((i = find (_route_groups.begin(), _route_groups.end(), &rg)) != _route_groups.end()) {
2272 _route_groups.erase (i);
2275 route_group_removed (); /* EMIT SIGNAL */
2279 /** Set a new order for our route groups, without adding or removing any.
2280 * @param groups Route group list in the new order.
2283 Session::reorder_route_groups (list<RouteGroup*> groups)
2285 _route_groups = groups;
2287 route_groups_reordered (); /* EMIT SIGNAL */
2293 Session::route_group_by_name (string name)
2295 list<RouteGroup *>::iterator i;
2297 for (i = _route_groups.begin(); i != _route_groups.end(); ++i) {
2298 if ((*i)->name() == name) {
2306 Session::all_route_group() const
2308 return *_all_route_group;
2312 Session::add_commands (vector<Command*> const & cmds)
2314 for (vector<Command*>::const_iterator i = cmds.begin(); i != cmds.end(); ++i) {
2320 Session::begin_reversible_command (const string& name)
2322 begin_reversible_command (g_quark_from_string (name.c_str ()));
2325 /** Begin a reversible command using a GQuark to identify it.
2326 * begin_reversible_command() and commit_reversible_command() calls may be nested,
2327 * but there must be as many begin...()s as there are commit...()s.
2330 Session::begin_reversible_command (GQuark q)
2332 /* If nested begin/commit pairs are used, we create just one UndoTransaction
2333 to hold all the commands that are committed. This keeps the order of
2334 commands correct in the history.
2337 if (_current_trans == 0) {
2338 /* start a new transaction */
2339 assert (_current_trans_quarks.empty ());
2340 _current_trans = new UndoTransaction();
2341 _current_trans->set_name (g_quark_to_string (q));
2344 _current_trans_quarks.push_front (q);
2348 Session::commit_reversible_command (Command *cmd)
2350 assert (_current_trans);
2351 assert (!_current_trans_quarks.empty ());
2356 _current_trans->add_command (cmd);
2359 _current_trans_quarks.pop_front ();
2361 if (!_current_trans_quarks.empty ()) {
2362 /* the transaction we're committing is not the top-level one */
2366 if (_current_trans->empty()) {
2367 /* no commands were added to the transaction, so just get rid of it */
2368 delete _current_trans;
2373 gettimeofday (&now, 0);
2374 _current_trans->set_timestamp (now);
2376 _history.add (_current_trans);
2381 accept_all_audio_files (const string& path, void */*arg*/)
2383 if (!Glib::file_test (path, Glib::FILE_TEST_IS_REGULAR)) {
2387 if (!AudioFileSource::safe_audio_file_extension (path)) {
2395 accept_all_midi_files (const string& path, void */*arg*/)
2397 if (!Glib::file_test (path, Glib::FILE_TEST_IS_REGULAR)) {
2401 return ((path.length() > 4 && path.find (".mid") != (path.length() - 4)) ||
2402 (path.length() > 4 && path.find (".smf") != (path.length() - 4)) ||
2403 (path.length() > 5 && path.find (".midi") != (path.length() - 5)));
2407 accept_all_state_files (const string& path, void */*arg*/)
2409 if (!Glib::file_test (path, Glib::FILE_TEST_IS_REGULAR)) {
2413 return (path.length() > 7 && path.find (".ardour") == (path.length() - 7));
2417 Session::find_all_sources (string path, set<string>& result)
2422 if (!tree.read (path)) {
2426 if ((node = find_named_node (*tree.root(), "Sources")) == 0) {
2431 XMLNodeConstIterator niter;
2433 nlist = node->children();
2437 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2441 if ((prop = (*niter)->property (X_("type"))) == 0) {
2445 DataType type (prop->value());
2447 if ((prop = (*niter)->property (X_("name"))) == 0) {
2451 if (Glib::path_is_absolute (prop->value())) {
2452 /* external file, ignore */
2460 if (FileSource::find (*this, type, prop->value(), true, is_new, chan, found_path)) {
2461 result.insert (found_path);
2469 Session::find_all_sources_across_snapshots (set<string>& result, bool exclude_this_snapshot)
2471 PathScanner scanner;
2472 vector<string*>* state_files;
2474 string this_snapshot_path;
2480 if (ripped[ripped.length()-1] == G_DIR_SEPARATOR) {
2481 ripped = ripped.substr (0, ripped.length() - 1);
2484 state_files = scanner (ripped, accept_all_state_files, (void *) 0, true, true);
2486 if (state_files == 0) {
2491 this_snapshot_path = _path;
2492 this_snapshot_path += legalize_for_path (_current_snapshot_name);
2493 this_snapshot_path += statefile_suffix;
2495 for (vector<string*>::iterator i = state_files->begin(); i != state_files->end(); ++i) {
2497 if (exclude_this_snapshot && **i == this_snapshot_path) {
2501 if (find_all_sources (**i, result) < 0) {
2509 struct RegionCounter {
2510 typedef std::map<PBD::ID,boost::shared_ptr<AudioSource> > AudioSourceList;
2511 AudioSourceList::iterator iter;
2512 boost::shared_ptr<Region> region;
2515 RegionCounter() : count (0) {}
2519 Session::ask_about_playlist_deletion (boost::shared_ptr<Playlist> p)
2521 boost::optional<int> r = AskAboutPlaylistDeletion (p);
2522 return r.get_value_or (1);
2526 Session::cleanup_regions ()
2528 const RegionFactory::RegionMap& regions (RegionFactory::regions());
2530 for (RegionFactory::RegionMap::const_iterator i = regions.begin(); i != regions.end(); ++i) {
2532 uint32_t used = playlists->region_use_count (i->second);
2534 if (used == 0 && !i->second->automatic ()) {
2535 RegionFactory::map_remove (i->second);
2539 /* dump the history list */
2546 Session::cleanup_sources (CleanupReport& rep)
2548 // FIXME: needs adaptation to midi
2550 vector<boost::shared_ptr<Source> > dead_sources;
2551 PathScanner scanner;
2554 vector<space_and_path>::iterator i;
2555 vector<space_and_path>::iterator nexti;
2556 vector<string*>* candidates;
2557 vector<string*>* candidates2;
2558 vector<string> unused;
2559 set<string> all_sources;
2564 _state_of_the_state = (StateOfTheState) (_state_of_the_state | InCleanup);
2566 /* consider deleting all unused playlists */
2568 if (playlists->maybe_delete_unused (boost::bind (Session::ask_about_playlist_deletion, _1))) {
2573 /* sync the "all regions" property of each playlist with its current state
2576 playlists->sync_all_regions_with_regions ();
2578 /* find all un-used sources */
2583 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ) {
2585 SourceMap::iterator tmp;
2590 /* do not bother with files that are zero size, otherwise we remove the current "nascent"
2594 if (!i->second->used() && (i->second->length(i->second->timeline_position() > 0))) {
2595 dead_sources.push_back (i->second);
2596 i->second->drop_references ();
2602 /* build a list of all the possible audio directories for the session */
2604 for (i = session_dirs.begin(); i != session_dirs.end(); ) {
2609 SessionDirectory sdir ((*i).path);
2610 audio_path += sdir.sound_path();
2612 if (nexti != session_dirs.end()) {
2620 /* build a list of all the possible midi directories for the session */
2622 for (i = session_dirs.begin(); i != session_dirs.end(); ) {
2627 SessionDirectory sdir ((*i).path);
2628 midi_path += sdir.midi_path();
2630 if (nexti != session_dirs.end()) {
2637 candidates = scanner (audio_path, accept_all_audio_files, (void *) 0, true, true);
2638 candidates2 = scanner (midi_path, accept_all_midi_files, (void *) 0, true, true);
2644 for (vector<string*>::iterator i = candidates2->begin(); i != candidates2->end(); ++i) {
2645 candidates->push_back (*i);
2650 candidates = candidates2; // might still be null
2653 /* find all sources, but don't use this snapshot because the
2654 state file on disk still references sources we may have already
2658 find_all_sources_across_snapshots (all_sources, true);
2660 /* add our current source list
2663 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ) {
2664 boost::shared_ptr<FileSource> fs;
2665 SourceMap::iterator tmp = i;
2668 if ((fs = boost::dynamic_pointer_cast<FileSource> (i->second)) != 0) {
2669 if (playlists->source_use_count (fs) != 0) {
2670 all_sources.insert (fs->path());
2673 /* we might not remove this source from disk, because it may be used
2674 by other snapshots, but its not being used in this version
2675 so lets get rid of it now, along with any representative regions
2679 RegionFactory::remove_regions_using_source (i->second);
2687 char tmppath1[PATH_MAX+1];
2688 char tmppath2[PATH_MAX+1];
2691 for (vector<string*>::iterator x = candidates->begin(); x != candidates->end(); ++x) {
2696 for (set<string>::iterator i = all_sources.begin(); i != all_sources.end(); ++i) {
2698 if (realpath(spath.c_str(), tmppath1) == 0) {
2699 error << string_compose (_("Cannot expand path %1 (%2)"),
2700 spath, strerror (errno)) << endmsg;
2704 if (realpath((*i).c_str(), tmppath2) == 0) {
2705 error << string_compose (_("Cannot expand path %1 (%2)"),
2706 (*i), strerror (errno)) << endmsg;
2710 if (strcmp(tmppath1, tmppath2) == 0) {
2717 unused.push_back (spath);
2726 /* now try to move all unused files into the "dead" directory(ies) */
2728 for (vector<string>::iterator x = unused.begin(); x != unused.end(); ++x) {
2729 struct stat statbuf;
2733 /* don't move the file across filesystems, just
2734 stick it in the `dead_dir_name' directory
2735 on whichever filesystem it was already on.
2738 if ((*x).find ("/sounds/") != string::npos) {
2740 /* old school, go up 1 level */
2742 newpath = Glib::path_get_dirname (*x); // "sounds"
2743 newpath = Glib::path_get_dirname (newpath); // "session-name"
2747 /* new school, go up 4 levels */
2749 newpath = Glib::path_get_dirname (*x); // "audiofiles" or "midifiles"
2750 newpath = Glib::path_get_dirname (newpath); // "session-name"
2751 newpath = Glib::path_get_dirname (newpath); // "interchange"
2752 newpath = Glib::path_get_dirname (newpath); // "session-dir"
2755 newpath = Glib::build_filename (newpath, dead_dir_name);
2757 if (g_mkdir_with_parents (newpath.c_str(), 0755) < 0) {
2758 error << string_compose(_("Session: cannot create dead file folder \"%1\" (%2)"), newpath, strerror (errno)) << endmsg;
2762 newpath = Glib::build_filename (newpath, Glib::path_get_basename ((*x)));
2764 if (Glib::file_test (newpath, Glib::FILE_TEST_EXISTS)) {
2766 /* the new path already exists, try versioning */
2768 char buf[PATH_MAX+1];
2772 snprintf (buf, sizeof (buf), "%s.%d", newpath.c_str(), version);
2775 while (Glib::file_test (newpath_v.c_str(), Glib::FILE_TEST_EXISTS) && version < 999) {
2776 snprintf (buf, sizeof (buf), "%s.%d", newpath.c_str(), ++version);
2780 if (version == 999) {
2781 error << string_compose (_("there are already 1000 files with names like %1; versioning discontinued"),
2785 newpath = newpath_v;
2790 /* it doesn't exist, or we can't read it or something */
2794 stat ((*x).c_str(), &statbuf);
2796 if (::rename ((*x).c_str(), newpath.c_str()) != 0) {
2797 error << string_compose (_("cannot rename unused file source from %1 to %2 (%3)"),
2798 (*x), newpath, strerror (errno))
2803 /* see if there an easy to find peakfile for this file, and remove it.
2806 string base = basename_nosuffix (*x);
2807 base += "%A"; /* this is what we add for the channel suffix of all native files,
2808 or for the first channel of embedded files. it will miss
2809 some peakfiles for other channels
2811 string peakpath = peak_path (base);
2813 if (Glib::file_test (peakpath.c_str(), Glib::FILE_TEST_EXISTS)) {
2814 if (::unlink (peakpath.c_str()) != 0) {
2815 error << string_compose (_("cannot remove peakfile %1 for %2 (%3)"),
2816 peakpath, _path, strerror (errno))
2818 /* try to back out */
2819 ::rename (newpath.c_str(), _path.c_str());
2824 rep.paths.push_back (*x);
2825 rep.space += statbuf.st_size;
2828 /* dump the history list */
2832 /* save state so we don't end up a session file
2833 referring to non-existent sources.
2840 _state_of_the_state = (StateOfTheState) (_state_of_the_state & ~InCleanup);
2846 Session::cleanup_trash_sources (CleanupReport& rep)
2848 // FIXME: needs adaptation for MIDI
2850 vector<space_and_path>::iterator i;
2856 for (i = session_dirs.begin(); i != session_dirs.end(); ++i) {
2858 dead_dir = Glib::build_filename ((*i).path, dead_dir_name);
2860 clear_directory (dead_dir, &rep.space, &rep.paths);
2867 Session::set_dirty ()
2869 bool was_dirty = dirty();
2871 _state_of_the_state = StateOfTheState (_state_of_the_state | Dirty);
2875 DirtyChanged(); /* EMIT SIGNAL */
2881 Session::set_clean ()
2883 bool was_dirty = dirty();
2885 _state_of_the_state = Clean;
2889 DirtyChanged(); /* EMIT SIGNAL */
2894 Session::set_deletion_in_progress ()
2896 _state_of_the_state = StateOfTheState (_state_of_the_state | Deletion);
2900 Session::clear_deletion_in_progress ()
2902 _state_of_the_state = StateOfTheState (_state_of_the_state & (~Deletion));
2906 Session::add_controllable (boost::shared_ptr<Controllable> c)
2908 /* this adds a controllable to the list managed by the Session.
2909 this is a subset of those managed by the Controllable class
2910 itself, and represents the only ones whose state will be saved
2911 as part of the session.
2914 Glib::Threads::Mutex::Lock lm (controllables_lock);
2915 controllables.insert (c);
2918 struct null_deleter { void operator()(void const *) const {} };
2921 Session::remove_controllable (Controllable* c)
2923 if (_state_of_the_state & Deletion) {
2927 Glib::Threads::Mutex::Lock lm (controllables_lock);
2929 Controllables::iterator x = controllables.find (boost::shared_ptr<Controllable>(c, null_deleter()));
2931 if (x != controllables.end()) {
2932 controllables.erase (x);
2936 boost::shared_ptr<Controllable>
2937 Session::controllable_by_id (const PBD::ID& id)
2939 Glib::Threads::Mutex::Lock lm (controllables_lock);
2941 for (Controllables::iterator i = controllables.begin(); i != controllables.end(); ++i) {
2942 if ((*i)->id() == id) {
2947 return boost::shared_ptr<Controllable>();
2950 boost::shared_ptr<Controllable>
2951 Session::controllable_by_descriptor (const ControllableDescriptor& desc)
2953 boost::shared_ptr<Controllable> c;
2954 boost::shared_ptr<Route> r;
2956 switch (desc.top_level_type()) {
2957 case ControllableDescriptor::NamedRoute:
2959 std::string str = desc.top_level_name();
2960 if (str == "master") {
2962 } else if (str == "control" || str == "listen") {
2965 r = route_by_name (desc.top_level_name());
2970 case ControllableDescriptor::RemoteControlID:
2971 r = route_by_remote_id (desc.rid());
2979 switch (desc.subtype()) {
2980 case ControllableDescriptor::Gain:
2981 c = r->gain_control ();
2984 case ControllableDescriptor::Solo:
2985 c = r->solo_control();
2988 case ControllableDescriptor::Mute:
2989 c = r->mute_control();
2992 case ControllableDescriptor::Recenable:
2994 boost::shared_ptr<Track> t = boost::dynamic_pointer_cast<Track>(r);
2997 c = t->rec_enable_control ();
3002 case ControllableDescriptor::PanDirection:
3004 c = r->pannable()->pan_azimuth_control;
3008 case ControllableDescriptor::PanWidth:
3010 c = r->pannable()->pan_width_control;
3014 case ControllableDescriptor::PanElevation:
3016 c = r->pannable()->pan_elevation_control;
3020 case ControllableDescriptor::Balance:
3021 /* XXX simple pan control */
3024 case ControllableDescriptor::PluginParameter:
3026 uint32_t plugin = desc.target (0);
3027 uint32_t parameter_index = desc.target (1);
3029 /* revert to zero based counting */
3035 if (parameter_index > 0) {
3039 boost::shared_ptr<Processor> p = r->nth_plugin (plugin);
3042 c = boost::dynamic_pointer_cast<ARDOUR::AutomationControl>(
3043 p->control(Evoral::Parameter(PluginAutomation, 0, parameter_index)));
3048 case ControllableDescriptor::SendGain:
3050 uint32_t send = desc.target (0);
3052 /* revert to zero-based counting */
3058 boost::shared_ptr<Processor> p = r->nth_send (send);
3061 boost::shared_ptr<Send> s = boost::dynamic_pointer_cast<Send>(p);
3062 boost::shared_ptr<Amp> a = s->amp();
3065 c = s->amp()->gain_control();
3072 /* relax and return a null pointer */
3080 Session::add_instant_xml (XMLNode& node, bool write_to_config)
3083 Stateful::add_instant_xml (node, _path);
3086 if (write_to_config) {
3087 Config->add_instant_xml (node);
3092 Session::instant_xml (const string& node_name)
3094 return Stateful::instant_xml (node_name, _path);
3098 Session::save_history (string snapshot_name)
3106 if (snapshot_name.empty()) {
3107 snapshot_name = _current_snapshot_name;
3110 const string history_filename = legalize_for_path (snapshot_name) + history_suffix;
3111 const string backup_filename = history_filename + backup_suffix;
3112 const std::string xml_path(Glib::build_filename (_session_dir->root_path(), history_filename));
3113 const std::string backup_path(Glib::build_filename (_session_dir->root_path(), backup_filename));
3115 if (Glib::file_test (xml_path, Glib::FILE_TEST_EXISTS)) {
3116 if (::g_rename (xml_path.c_str(), backup_path.c_str()) != 0) {
3117 error << _("could not backup old history file, current history not saved") << endmsg;
3122 if (!Config->get_save_history() || Config->get_saved_history_depth() < 0) {
3126 tree.set_root (&_history.get_state (Config->get_saved_history_depth()));
3128 if (!tree.write (xml_path))
3130 error << string_compose (_("history could not be saved to %1"), xml_path) << endmsg;
3132 if (g_remove (xml_path.c_str()) != 0) {
3133 error << string_compose(_("Could not remove history file at path \"%1\" (%2)"),
3134 xml_path, g_strerror (errno)) << endmsg;
3136 if (::g_rename (backup_path.c_str(), xml_path.c_str()) != 0) {
3137 error << string_compose (_("could not restore history file from backup %1 (%2)"),
3138 backup_path, g_strerror (errno)) << endmsg;
3148 Session::restore_history (string snapshot_name)
3152 if (snapshot_name.empty()) {
3153 snapshot_name = _current_snapshot_name;
3156 const std::string xml_filename = legalize_for_path (snapshot_name) + history_suffix;
3157 const std::string xml_path(Glib::build_filename (_session_dir->root_path(), xml_filename));
3159 info << "Loading history from " << xml_path << endmsg;
3161 if (!Glib::file_test (xml_path, Glib::FILE_TEST_EXISTS)) {
3162 info << string_compose (_("%1: no history file \"%2\" for this session."),
3163 _name, xml_path) << endmsg;
3167 if (!tree.read (xml_path)) {
3168 error << string_compose (_("Could not understand session history file \"%1\""),
3169 xml_path) << endmsg;
3176 for (XMLNodeConstIterator it = tree.root()->children().begin(); it != tree.root()->children().end(); it++) {
3179 UndoTransaction* ut = new UndoTransaction ();
3182 ut->set_name(t->property("name")->value());
3183 stringstream ss(t->property("tv-sec")->value());
3185 ss.str(t->property("tv-usec")->value());
3187 ut->set_timestamp(tv);
3189 for (XMLNodeConstIterator child_it = t->children().begin();
3190 child_it != t->children().end(); child_it++)
3192 XMLNode *n = *child_it;
3195 if (n->name() == "MementoCommand" ||
3196 n->name() == "MementoUndoCommand" ||
3197 n->name() == "MementoRedoCommand") {
3199 if ((c = memento_command_factory(n))) {
3203 } else if (n->name() == "NoteDiffCommand") {
3204 PBD::ID id (n->property("midi-source")->value());
3205 boost::shared_ptr<MidiSource> midi_source =
3206 boost::dynamic_pointer_cast<MidiSource, Source>(source_by_id(id));
3208 ut->add_command (new MidiModel::NoteDiffCommand(midi_source->model(), *n));
3210 error << _("Failed to downcast MidiSource for NoteDiffCommand") << endmsg;
3213 } else if (n->name() == "SysExDiffCommand") {
3215 PBD::ID id (n->property("midi-source")->value());
3216 boost::shared_ptr<MidiSource> midi_source =
3217 boost::dynamic_pointer_cast<MidiSource, Source>(source_by_id(id));
3219 ut->add_command (new MidiModel::SysExDiffCommand (midi_source->model(), *n));
3221 error << _("Failed to downcast MidiSource for SysExDiffCommand") << endmsg;
3224 } else if (n->name() == "PatchChangeDiffCommand") {
3226 PBD::ID id (n->property("midi-source")->value());
3227 boost::shared_ptr<MidiSource> midi_source =
3228 boost::dynamic_pointer_cast<MidiSource, Source>(source_by_id(id));
3230 ut->add_command (new MidiModel::PatchChangeDiffCommand (midi_source->model(), *n));
3232 error << _("Failed to downcast MidiSource for PatchChangeDiffCommand") << endmsg;
3235 } else if (n->name() == "StatefulDiffCommand") {
3236 if ((c = stateful_diff_command_factory (n))) {
3237 ut->add_command (c);
3240 error << string_compose(_("Couldn't figure out how to make a Command out of a %1 XMLNode."), n->name()) << endmsg;
3251 Session::config_changed (std::string p, bool ours)
3257 if (p == "seamless-loop") {
3259 } else if (p == "rf-speed") {
3261 } else if (p == "auto-loop") {
3263 } else if (p == "auto-input") {
3265 if (Config->get_monitoring_model() == HardwareMonitoring && transport_rolling()) {
3266 /* auto-input only makes a difference if we're rolling */
3267 set_track_monitor_input_status (!config.get_auto_input());
3270 } else if (p == "punch-in") {
3274 if ((location = _locations->auto_punch_location()) != 0) {
3276 if (config.get_punch_in ()) {
3277 replace_event (SessionEvent::PunchIn, location->start());
3279 remove_event (location->start(), SessionEvent::PunchIn);
3283 } else if (p == "punch-out") {
3287 if ((location = _locations->auto_punch_location()) != 0) {
3289 if (config.get_punch_out()) {
3290 replace_event (SessionEvent::PunchOut, location->end());
3292 clear_events (SessionEvent::PunchOut);
3296 } else if (p == "edit-mode") {
3298 Glib::Threads::Mutex::Lock lm (playlists->lock);
3300 for (SessionPlaylists::List::iterator i = playlists->playlists.begin(); i != playlists->playlists.end(); ++i) {
3301 (*i)->set_edit_mode (Config->get_edit_mode ());
3304 } else if (p == "use-video-sync") {
3306 waiting_for_sync_offset = config.get_use_video_sync();
3308 } else if (p == "mmc-control") {
3310 //poke_midi_thread ();
3312 } else if (p == "mmc-device-id" || p == "mmc-receive-id" || p == "mmc-receive-device-id") {
3314 _mmc->set_receive_device_id (Config->get_mmc_receive_device_id());
3316 } else if (p == "mmc-send-id" || p == "mmc-send-device-id") {
3318 _mmc->set_send_device_id (Config->get_mmc_send_device_id());
3320 } else if (p == "midi-control") {
3322 //poke_midi_thread ();
3324 } else if (p == "raid-path") {
3326 setup_raid_path (config.get_raid_path());
3328 } else if (p == "timecode-format") {
3332 } else if (p == "video-pullup") {
3336 } else if (p == "seamless-loop") {
3338 if (play_loop && transport_rolling()) {
3339 // to reset diskstreams etc
3340 request_play_loop (true);
3343 } else if (p == "rf-speed") {
3345 cumulative_rf_motion = 0;
3348 } else if (p == "click-sound") {
3350 setup_click_sounds (1);
3352 } else if (p == "click-emphasis-sound") {
3354 setup_click_sounds (-1);
3356 } else if (p == "clicking") {
3358 if (Config->get_clicking()) {
3359 if (_click_io && click_data) { // don't require emphasis data
3366 } else if (p == "click-gain") {
3369 _click_gain->set_gain (Config->get_click_gain(), this);
3372 } else if (p == "send-mtc") {
3374 if (Config->get_send_mtc ()) {
3375 /* mark us ready to send */
3376 next_quarter_frame_to_send = 0;
3379 } else if (p == "send-mmc") {
3381 _mmc->enable_send (Config->get_send_mmc ());
3383 } else if (p == "midi-feedback") {
3385 session_midi_feedback = Config->get_midi_feedback();
3387 } else if (p == "jack-time-master") {
3389 engine().reset_timebase ();
3391 } else if (p == "native-file-header-format") {
3393 if (!first_file_header_format_reset) {
3394 reset_native_file_format ();
3397 first_file_header_format_reset = false;
3399 } else if (p == "native-file-data-format") {
3401 if (!first_file_data_format_reset) {
3402 reset_native_file_format ();
3405 first_file_data_format_reset = false;
3407 } else if (p == "external-sync") {
3408 if (!config.get_external_sync()) {
3409 drop_sync_source ();
3411 switch_to_sync_source (Config->get_sync_source());
3413 } else if (p == "denormal-model") {
3415 } else if (p == "history-depth") {
3416 set_history_depth (Config->get_history_depth());
3417 } else if (p == "remote-model") {
3418 /* XXX DO SOMETHING HERE TO TELL THE GUI THAT WE NEED
3421 } else if (p == "sync-all-route-ordering") {
3423 /* sync to editor order unless mixer is used for remote IDs
3426 switch (Config->get_remote_model()) {
3428 sync_order_keys (EditorSort);
3431 sync_order_keys (EditorSort);
3434 sync_order_keys (MixerSort);
3437 } else if (p == "initial-program-change") {
3439 if (_mmc->output_port() && Config->get_initial_program_change() >= 0) {
3442 buf[0] = MIDI::program; // channel zero by default
3443 buf[1] = (Config->get_initial_program_change() & 0x7f);
3445 _mmc->output_port()->midimsg (buf, sizeof (buf), 0);
3447 } else if (p == "solo-mute-override") {
3448 // catch_up_on_solo_mute_override ();
3449 } else if (p == "listen-position" || p == "pfl-position") {
3450 listen_position_changed ();
3451 } else if (p == "solo-control-is-listen-control") {
3452 solo_control_mode_changed ();
3453 } else if (p == "timecode-offset" || p == "timecode-offset-negative") {
3454 last_timecode_valid = false;
3455 } else if (p == "playback-buffer-seconds") {
3456 AudioSource::allocate_working_buffers (frame_rate());
3457 } else if (p == "automation-thinning-factor") {
3458 Evoral::ControlList::set_thinning_factor (Config->get_automation_thinning_factor());
3459 } else if (p == "ltc-source-port") {
3460 reconnect_ltc_input ();
3461 } else if (p == "ltc-sink-port") {
3462 reconnect_ltc_output ();
3463 } else if (p == "timecode-generator-offset") {
3464 ltc_tx_parse_offset();
3471 Session::set_history_depth (uint32_t d)
3473 _history.set_depth (d);
3477 Session::load_diskstreams_2X (XMLNode const & node, int)
3480 XMLNodeConstIterator citer;
3482 clist = node.children();
3484 for (citer = clist.begin(); citer != clist.end(); ++citer) {
3487 /* diskstreams added automatically by DiskstreamCreated handler */
3488 if ((*citer)->name() == "AudioDiskstream" || (*citer)->name() == "DiskStream") {
3489 boost::shared_ptr<AudioDiskstream> dsp (new AudioDiskstream (*this, **citer));
3490 _diskstreams_2X.push_back (dsp);
3492 error << _("Session: unknown diskstream type in XML") << endmsg;
3496 catch (failed_constructor& err) {
3497 error << _("Session: could not load diskstream via XML state") << endmsg;
3505 /** Connect things to the MMC object */
3507 Session::setup_midi_machine_control ()
3509 _mmc = new MIDI::MachineControl;
3510 _mmc->set_ports (_midi_ports->mmc_input_port(), _midi_ports->mmc_output_port());
3512 _mmc->Play.connect_same_thread (*this, boost::bind (&Session::mmc_deferred_play, this, _1));
3513 _mmc->DeferredPlay.connect_same_thread (*this, boost::bind (&Session::mmc_deferred_play, this, _1));
3514 _mmc->Stop.connect_same_thread (*this, boost::bind (&Session::mmc_stop, this, _1));
3515 _mmc->FastForward.connect_same_thread (*this, boost::bind (&Session::mmc_fast_forward, this, _1));
3516 _mmc->Rewind.connect_same_thread (*this, boost::bind (&Session::mmc_rewind, this, _1));
3517 _mmc->Pause.connect_same_thread (*this, boost::bind (&Session::mmc_pause, this, _1));
3518 _mmc->RecordPause.connect_same_thread (*this, boost::bind (&Session::mmc_record_pause, this, _1));
3519 _mmc->RecordStrobe.connect_same_thread (*this, boost::bind (&Session::mmc_record_strobe, this, _1));
3520 _mmc->RecordExit.connect_same_thread (*this, boost::bind (&Session::mmc_record_exit, this, _1));
3521 _mmc->Locate.connect_same_thread (*this, boost::bind (&Session::mmc_locate, this, _1, _2));
3522 _mmc->Step.connect_same_thread (*this, boost::bind (&Session::mmc_step, this, _1, _2));
3523 _mmc->Shuttle.connect_same_thread (*this, boost::bind (&Session::mmc_shuttle, this, _1, _2, _3));
3524 _mmc->TrackRecordStatusChange.connect_same_thread (*this, boost::bind (&Session::mmc_record_enable, this, _1, _2, _3));
3526 /* also handle MIDI SPP because its so common */
3528 _mmc->SPPStart.connect_same_thread (*this, boost::bind (&Session::spp_start, this));
3529 _mmc->SPPContinue.connect_same_thread (*this, boost::bind (&Session::spp_continue, this));
3530 _mmc->SPPStop.connect_same_thread (*this, boost::bind (&Session::spp_stop, this));
3533 boost::shared_ptr<Controllable>
3534 Session::solo_cut_control() const
3536 /* the solo cut control is a bit of an anomaly, at least as of Febrary 2011. There are no other
3537 controls in Ardour that currently get presented to the user in the GUI that require
3538 access as a Controllable and are also NOT owned by some SessionObject (e.g. Route, or MonitorProcessor).
3540 its actually an RCConfiguration parameter, so we use a ProxyControllable to wrap
3541 it up as a Controllable. Changes to the Controllable will just map back to the RCConfiguration
3545 return _solo_cut_control;
3549 Session::rename (const std::string& new_name)
3551 string legal_name = legalize_for_path (new_name);
3557 string const old_sources_root = _session_dir->sources_root();
3559 #define RENAME ::rename
3564 * interchange subdirectory
3568 * Backup files are left unchanged and not renamed.
3571 /* pass one: not 100% safe check that the new directory names don't
3575 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
3580 /* this is a stupid hack because Glib::path_get_dirname() is
3581 * lexical-only, and so passing it /a/b/c/ gives a different
3582 * result than passing it /a/b/c ...
3585 if (oldstr[oldstr.length()-1] == G_DIR_SEPARATOR) {
3586 oldstr = oldstr.substr (0, oldstr.length() - 1);
3589 string base = Glib::path_get_dirname (oldstr);
3590 string p = Glib::path_get_basename (oldstr);
3592 newstr = Glib::build_filename (base, legal_name);
3594 if (Glib::file_test (newstr, Glib::FILE_TEST_EXISTS)) {
3601 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
3606 /* this is a stupid hack because Glib::path_get_dirname() is
3607 * lexical-only, and so passing it /a/b/c/ gives a different
3608 * result than passing it /a/b/c ...
3611 if (oldstr[oldstr.length()-1] == G_DIR_SEPARATOR) {
3612 oldstr = oldstr.substr (0, oldstr.length() - 1);
3615 string base = Glib::path_get_dirname (oldstr);
3616 string p = Glib::path_get_basename (oldstr);
3618 newstr = Glib::build_filename (base, legal_name);
3620 cerr << "Rename " << oldstr << " => " << newstr << endl;
3622 if (RENAME (oldstr.c_str(), newstr.c_str()) != 0) {
3627 (*_session_dir) = newstr;
3632 /* directory below interchange */
3634 v.push_back (newstr);
3635 v.push_back (interchange_dir_name);
3638 oldstr = Glib::build_filename (v);
3641 v.push_back (newstr);
3642 v.push_back (interchange_dir_name);
3643 v.push_back (legal_name);
3645 newstr = Glib::build_filename (v);
3647 cerr << "Rename " << oldstr << " => " << newstr << endl;
3649 if (RENAME (oldstr.c_str(), newstr.c_str()) != 0) {
3656 oldstr = Glib::build_filename (newpath, _current_snapshot_name) + statefile_suffix;
3657 newstr= Glib::build_filename (newpath, legal_name) + statefile_suffix;
3659 cerr << "Rename " << oldstr << " => " << newstr << endl;
3661 if (RENAME (oldstr.c_str(), newstr.c_str()) != 0) {
3668 oldstr = Glib::build_filename (newpath, _current_snapshot_name) + history_suffix;
3670 if (Glib::file_test (oldstr, Glib::FILE_TEST_EXISTS)) {
3671 newstr = Glib::build_filename (newpath, legal_name) + history_suffix;
3673 cerr << "Rename " << oldstr << " => " << newstr << endl;
3675 if (RENAME (oldstr.c_str(), newstr.c_str()) != 0) {
3680 /* update file source paths */
3682 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ++i) {
3683 boost::shared_ptr<FileSource> fs = boost::dynamic_pointer_cast<FileSource> (i->second);
3685 string p = fs->path ();
3686 boost::replace_all (p, old_sources_root, _session_dir->sources_root());
3691 /* remove old name from recent sessions */
3693 remove_recent_sessions (_path);
3696 _current_snapshot_name = new_name;
3701 /* save state again to get everything just right */
3703 save_state (_current_snapshot_name);
3706 /* add to recent sessions */
3708 store_recent_sessions (new_name, _path);