2 Copyright (C) 1999-2013 Paul Davis
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 #include "libardour-config.h"
31 #include <cstdio> /* snprintf(3) ... grrr */
44 #include <sys/param.h>
45 #include <sys/mount.h>
48 #ifdef HAVE_SYS_STATVFS_H
49 #include <sys/statvfs.h>
53 #include <glib/gstdio.h>
56 #include <glibmm/threads.h>
58 #include <boost/algorithm/string.hpp>
60 #include "midi++/mmc.h"
61 #include "midi++/port.h"
63 #include "evoral/SMF.hpp"
65 #include "pbd/boost_debug.h"
66 #include "pbd/basename.h"
67 #include "pbd/controllable_descriptor.h"
68 #include "pbd/enumwriter.h"
69 #include "pbd/error.h"
70 #include "pbd/file_utils.h"
71 #include "pbd/pathexpand.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"
77 #include "pbd/localtime_r.h"
79 #include "ardour/amp.h"
80 #include "ardour/audio_diskstream.h"
81 #include "ardour/audio_track.h"
82 #include "ardour/audioengine.h"
83 #include "ardour/audiofilesource.h"
84 #include "ardour/audioregion.h"
85 #include "ardour/automation_control.h"
86 #include "ardour/butler.h"
87 #include "ardour/control_protocol_manager.h"
88 #include "ardour/directory_names.h"
89 #include "ardour/filename_extensions.h"
90 #include "ardour/graph.h"
91 #include "ardour/location.h"
92 #include "ardour/midi_model.h"
93 #include "ardour/midi_patch_manager.h"
94 #include "ardour/midi_region.h"
95 #include "ardour/midi_source.h"
96 #include "ardour/midi_track.h"
97 #include "ardour/pannable.h"
98 #include "ardour/playlist_factory.h"
99 #include "ardour/port.h"
100 #include "ardour/processor.h"
101 #include "ardour/proxy_controllable.h"
102 #include "ardour/recent_sessions.h"
103 #include "ardour/region_factory.h"
104 #include "ardour/route_group.h"
105 #include "ardour/send.h"
106 #include "ardour/session.h"
107 #include "ardour/session_directory.h"
108 #include "ardour/session_metadata.h"
109 #include "ardour/session_playlists.h"
110 #include "ardour/session_state_utils.h"
111 #include "ardour/silentfilesource.h"
112 #include "ardour/sndfilesource.h"
113 #include "ardour/source_factory.h"
114 #include "ardour/speakers.h"
115 #include "ardour/template_utils.h"
116 #include "ardour/tempo.h"
117 #include "ardour/ticker.h"
118 #include "ardour/user_bundle.h"
120 #include "control_protocol/control_protocol.h"
126 using namespace ARDOUR;
130 Session::pre_engine_init (string fullpath)
132 if (fullpath.empty()) {
134 throw failed_constructor();
137 /* discover canonical fullpath */
139 char buf[PATH_MAX+1];
140 if (!realpath (fullpath.c_str(), buf) && (errno != ENOENT)) {
141 error << string_compose(_("Could not use path %1 (%2)"), buf, strerror(errno)) << endmsg;
143 throw failed_constructor();
148 /* we require _path to end with a dir separator */
150 if (_path[_path.length()-1] != G_DIR_SEPARATOR) {
151 _path += G_DIR_SEPARATOR;
156 _is_new = !Glib::file_test (_path, Glib::FileTest (G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR));
158 /* finish initialization that can't be done in a normal C++ constructor
162 timerclear (&last_mmc_step);
163 g_atomic_int_set (&processing_prohibited, 0);
164 g_atomic_int_set (&_record_status, Disabled);
165 g_atomic_int_set (&_playback_load, 100);
166 g_atomic_int_set (&_capture_load, 100);
168 _all_route_group->set_active (true, this);
169 interpolation.add_channel_to (0, 0);
171 if (config.get_use_video_sync()) {
172 waiting_for_sync_offset = true;
174 waiting_for_sync_offset = false;
177 last_rr_session_dir = session_dirs.begin();
179 set_history_depth (Config->get_history_depth());
181 /* default: assume simple stereo speaker configuration */
183 _speakers->setup_default_speakers (2);
185 _solo_cut_control.reset (new ProxyControllable (_("solo cut control (dB)"), PBD::Controllable::GainLike,
186 boost::bind (&RCConfiguration::set_solo_mute_gain, Config, _1),
187 boost::bind (&RCConfiguration::get_solo_mute_gain, Config)));
188 add_controllable (_solo_cut_control);
190 /* These are all static "per-class" signals */
192 SourceFactory::SourceCreated.connect_same_thread (*this, boost::bind (&Session::add_source, this, _1));
193 PlaylistFactory::PlaylistCreated.connect_same_thread (*this, boost::bind (&Session::add_playlist, this, _1, _2));
194 AutomationList::AutomationListCreated.connect_same_thread (*this, boost::bind (&Session::add_automation_list, this, _1));
195 Controllable::Destroyed.connect_same_thread (*this, boost::bind (&Session::remove_controllable, this, _1));
196 IO::PortCountChanged.connect_same_thread (*this, boost::bind (&Session::ensure_buffers, this, _1));
198 /* stop IO objects from doing stuff until we're ready for them */
200 Delivery::disable_panners ();
201 IO::disable_connecting ();
203 AudioFileSource::set_peak_dir (_session_dir->peak_path());
207 Session::post_engine_init ()
209 BootMessage (_("Set block size and sample rate"));
211 set_block_size (_engine.samples_per_cycle());
212 set_frame_rate (_engine.sample_rate());
214 if (how_many_dsp_threads () > 1) {
215 /* For now, only create the graph if we are using >1 DSP threads, as
216 it is a bit slower than the old code with 1 thread.
218 _process_graph.reset (new Graph (*this));
221 n_physical_outputs = _engine.n_physical_outputs ();
222 n_physical_inputs = _engine.n_physical_inputs ();
224 BootMessage (_("Using configuration"));
226 _midi_ports = new MidiPortManager;
227 setup_midi_machine_control ();
229 if (_butler->start_thread()) {
233 if (start_midi_thread ()) {
237 setup_click_sounds (0);
238 setup_midi_control ();
240 _engine.Halted.connect_same_thread (*this, boost::bind (&Session::engine_halted, this));
241 _engine.Xrun.connect_same_thread (*this, boost::bind (&Session::xrun_recovery, this));
244 /* tempo map requires sample rate knowledge */
246 _tempo_map = new TempoMap (_current_frame_rate);
247 _tempo_map->PropertyChanged.connect_same_thread (*this, boost::bind (&Session::tempo_map_changed, this, _1));
249 /* MidiClock requires a tempo map */
251 midi_clock = new MidiClockTicker ();
252 midi_clock->set_session (this);
254 /* crossfades require sample rate knowledge */
256 SndFileSource::setup_standard_crossfades (*this, frame_rate());
257 _engine.GraphReordered.connect_same_thread (*this, boost::bind (&Session::graph_reordered, this));
259 AudioDiskstream::allocate_working_buffers();
260 refresh_disk_space ();
262 /* we're finally ready to call set_state() ... all objects have
263 * been created, the engine is running.
267 if (set_state (*state_tree->root(), Stateful::loading_state_version)) {
271 // set_state() will call setup_raid_path(), but if it's a new session we need
272 // to call setup_raid_path() here.
273 setup_raid_path (_path);
278 boost::function<void (std::string)> ff (boost::bind (&Session::config_changed, this, _1, false));
279 boost::function<void (std::string)> ft (boost::bind (&Session::config_changed, this, _1, true));
281 Config->map_parameters (ff);
282 config.map_parameters (ft);
284 when_engine_running ();
286 _locations->changed.connect_same_thread (*this, boost::bind (&Session::locations_changed, this));
287 _locations->added.connect_same_thread (*this, boost::bind (&Session::locations_added, this, _1));
289 } catch (AudioEngine::PortRegistrationFailure& err) {
290 /* handle this one in a different way than all others, so that its clear what happened */
291 error << err.what() << endmsg;
297 BootMessage (_("Reset Remote Controls"));
299 // send_full_time_code (0);
300 _engine.transport_locate (0);
302 _mmc->send (MIDI::MachineControlCommand (MIDI::MachineControl::cmdMmcReset));
303 _mmc->send (MIDI::MachineControlCommand (Timecode::Time ()));
305 MIDI::Name::MidiPatchManager::instance().set_session (this);
308 /* initial program change will be delivered later; see ::config_changed() */
310 _state_of_the_state = Clean;
312 Port::set_connecting_blocked (false);
314 DirtyChanged (); /* EMIT SIGNAL */
318 } else if (state_was_pending) {
320 remove_pending_capture_state ();
321 state_was_pending = false;
328 Session::raid_path () const
330 Searchpath raid_search_path;
332 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
333 raid_search_path += (*i).path;
336 return raid_search_path.to_string ();
340 Session::setup_raid_path (string path)
349 session_dirs.clear ();
351 Searchpath search_path(path);
352 Searchpath sound_search_path;
353 Searchpath midi_search_path;
355 for (Searchpath::const_iterator i = search_path.begin(); i != search_path.end(); ++i) {
357 sp.blocks = 0; // not needed
358 session_dirs.push_back (sp);
360 SessionDirectory sdir(sp.path);
362 sound_search_path += sdir.sound_path ();
363 midi_search_path += sdir.midi_path ();
366 // reset the round-robin soundfile path thingie
367 last_rr_session_dir = session_dirs.begin();
371 Session::path_is_within_session (const std::string& path)
373 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
374 if (PBD::path_is_within (i->path, path)) {
382 Session::ensure_subdirs ()
386 dir = session_directory().peak_path();
388 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
389 error << string_compose(_("Session: cannot create session peakfile folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
393 dir = session_directory().sound_path();
395 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
396 error << string_compose(_("Session: cannot create session sounds dir \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
400 dir = session_directory().midi_path();
402 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
403 error << string_compose(_("Session: cannot create session midi dir \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
407 dir = session_directory().dead_path();
409 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
410 error << string_compose(_("Session: cannot create session dead sounds folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
414 dir = session_directory().export_path();
416 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
417 error << string_compose(_("Session: cannot create session export folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
421 dir = analysis_dir ();
423 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
424 error << string_compose(_("Session: cannot create session analysis folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
428 dir = plugins_dir ();
430 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
431 error << string_compose(_("Session: cannot create session plugins folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
435 dir = externals_dir ();
437 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
438 error << string_compose(_("Session: cannot create session externals folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
445 /** @param session_template directory containing session template, or empty.
446 * Caller must not hold process lock.
449 Session::create (const string& session_template, BusProfile* bus_profile)
451 if (g_mkdir_with_parents (_path.c_str(), 0755) < 0) {
452 error << string_compose(_("Session: cannot create session folder \"%1\" (%2)"), _path, strerror (errno)) << endmsg;
456 if (ensure_subdirs ()) {
460 _writable = exists_and_writable (_path);
462 if (!session_template.empty()) {
463 std::string in_path = session_template_dir_to_file (session_template);
465 ifstream in(in_path.c_str());
468 string out_path = _path;
470 out_path += statefile_suffix;
472 ofstream out(out_path.c_str());
478 /* Copy plugin state files from template to new session */
479 std::string template_plugins = Glib::build_filename (session_template, X_("plugins"));
480 copy_files (template_plugins, plugins_dir ());
485 error << string_compose (_("Could not open %1 for writing session template"), out_path)
491 error << string_compose (_("Could not open session template %1 for reading"), in_path)
498 /* set initial start + end point */
500 _state_of_the_state = Clean;
502 /* set up Master Out and Control Out if necessary */
507 ChanCount count(DataType::AUDIO, bus_profile->master_out_channels);
509 if (bus_profile->master_out_channels) {
510 boost::shared_ptr<Route> r (new Route (*this, _("master"), Route::MasterOut, DataType::AUDIO));
514 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
515 // boost_debug_shared_ptr_mark_interesting (r.get(), "Route");
518 Glib::Threads::Mutex::Lock lm (AudioEngine::instance()->process_lock ());
519 r->input()->ensure_io (count, false, this);
520 r->output()->ensure_io (count, false, this);
526 /* prohibit auto-connect to master, because there isn't one */
527 bus_profile->output_ac = AutoConnectOption (bus_profile->output_ac & ~AutoConnectMaster);
531 add_routes (rl, false, false, false);
534 /* this allows the user to override settings with an environment variable.
537 if (no_auto_connect()) {
538 bus_profile->input_ac = AutoConnectOption (0);
539 bus_profile->output_ac = AutoConnectOption (0);
542 Config->set_input_auto_connect (bus_profile->input_ac);
543 Config->set_output_auto_connect (bus_profile->output_ac);
546 if (Config->get_use_monitor_bus() && bus_profile) {
547 add_monitor_section ();
554 Session::maybe_write_autosave()
556 if (dirty() && record_status() != Recording) {
557 save_state("", true);
562 Session::remove_pending_capture_state ()
564 std::string pending_state_file_path(_session_dir->root_path());
566 pending_state_file_path = Glib::build_filename (pending_state_file_path, legalize_for_path (_current_snapshot_name) + pending_suffix);
568 if (!Glib::file_test (pending_state_file_path, Glib::FILE_TEST_EXISTS)) return;
570 if (g_remove (pending_state_file_path.c_str()) != 0) {
571 error << string_compose(_("Could not remove pending capture state at path \"%1\" (%2)"),
572 pending_state_file_path, g_strerror (errno)) << endmsg;
576 /** Rename a state file.
577 * @param old_name Old snapshot name.
578 * @param new_name New snapshot name.
581 Session::rename_state (string old_name, string new_name)
583 if (old_name == _current_snapshot_name || old_name == _name) {
584 /* refuse to rename the current snapshot or the "main" one */
588 const string old_xml_filename = legalize_for_path (old_name) + statefile_suffix;
589 const string new_xml_filename = legalize_for_path (new_name) + statefile_suffix;
591 const std::string old_xml_path(Glib::build_filename (_session_dir->root_path(), old_xml_filename));
592 const std::string new_xml_path(Glib::build_filename (_session_dir->root_path(), new_xml_filename));
594 if (::g_rename (old_xml_path.c_str(), new_xml_path.c_str()) != 0) {
595 error << string_compose(_("could not rename snapshot %1 to %2 (%3)"),
596 old_name, new_name, g_strerror(errno)) << endmsg;
600 /** Remove a state file.
601 * @param snapshot_name Snapshot name.
604 Session::remove_state (string snapshot_name)
606 if (!_writable || snapshot_name == _current_snapshot_name || snapshot_name == _name) {
607 // refuse to remove the current snapshot or the "main" one
611 std::string xml_path(_session_dir->root_path());
613 xml_path = Glib::build_filename (xml_path, legalize_for_path (snapshot_name) + statefile_suffix);
615 if (!create_backup_file (xml_path)) {
616 // don't remove it if a backup can't be made
617 // create_backup_file will log the error.
622 if (g_remove (xml_path.c_str()) != 0) {
623 error << string_compose(_("Could not remove session file at path \"%1\" (%2)"),
624 xml_path, g_strerror (errno)) << endmsg;
628 /** @param snapshot_name Name to save under, without .ardour / .pending prefix */
630 Session::save_state (string snapshot_name, bool pending, bool switch_to_snapshot)
633 std::string xml_path(_session_dir->root_path());
635 if (!_writable || (_state_of_the_state & CannotSave)) {
639 if (!_engine.connected ()) {
640 error << string_compose (_("the %1 audio engine is not connected and state saving would lose all I/O connections. Session not saved"),
646 /* tell sources we're saving first, in case they write out to a new file
647 * which should be saved with the state rather than the old one */
648 for (SourceMap::const_iterator i = sources.begin(); i != sources.end(); ++i) {
650 i->second->session_saved();
651 } catch (Evoral::SMF::FileError& e) {
652 error << string_compose ("Could not write to MIDI file %1; MIDI data not saved.", e.file_name ()) << endmsg;
656 SaveSession (); /* EMIT SIGNAL */
658 tree.set_root (&get_state());
660 if (snapshot_name.empty()) {
661 snapshot_name = _current_snapshot_name;
662 } else if (switch_to_snapshot) {
663 _current_snapshot_name = snapshot_name;
668 /* proper save: use statefile_suffix (.ardour in English) */
670 xml_path = Glib::build_filename (xml_path, legalize_for_path (snapshot_name) + statefile_suffix);
672 /* make a backup copy of the old file */
674 if (Glib::file_test (xml_path, Glib::FILE_TEST_EXISTS) && !create_backup_file (xml_path)) {
675 // create_backup_file will log the error
681 /* pending save: use pending_suffix (.pending in English) */
682 xml_path = Glib::build_filename (xml_path, legalize_for_path (snapshot_name) + pending_suffix);
685 std::string tmp_path(_session_dir->root_path());
686 tmp_path = Glib::build_filename (tmp_path, legalize_for_path (snapshot_name) + temp_suffix);
688 // cerr << "actually writing state to " << xml_path << endl;
690 if (!tree.write (tmp_path)) {
691 error << string_compose (_("state could not be saved to %1"), tmp_path) << endmsg;
692 if (g_remove (tmp_path.c_str()) != 0) {
693 error << string_compose(_("Could not remove temporary session file at path \"%1\" (%2)"),
694 tmp_path, g_strerror (errno)) << endmsg;
700 if (::g_rename (tmp_path.c_str(), xml_path.c_str()) != 0) {
701 error << string_compose (_("could not rename temporary session file %1 to %2 (%3)"),
702 tmp_path, xml_path, g_strerror(errno)) << endmsg;
703 if (g_remove (tmp_path.c_str()) != 0) {
704 error << string_compose(_("Could not remove temporary session file at path \"%1\" (%2)"),
705 tmp_path, g_strerror (errno)) << endmsg;
713 save_history (snapshot_name);
715 bool was_dirty = dirty();
717 _state_of_the_state = StateOfTheState (_state_of_the_state & ~Dirty);
720 DirtyChanged (); /* EMIT SIGNAL */
723 StateSaved (snapshot_name); /* EMIT SIGNAL */
730 Session::restore_state (string snapshot_name)
732 if (load_state (snapshot_name) == 0) {
733 set_state (*state_tree->root(), Stateful::loading_state_version);
740 Session::load_state (string snapshot_name)
745 state_was_pending = false;
747 /* check for leftover pending state from a crashed capture attempt */
749 std::string xmlpath(_session_dir->root_path());
750 xmlpath = Glib::build_filename (xmlpath, legalize_for_path (snapshot_name) + pending_suffix);
752 if (Glib::file_test (xmlpath, Glib::FILE_TEST_EXISTS)) {
754 /* there is pending state from a crashed capture attempt */
756 boost::optional<int> r = AskAboutPendingState();
757 if (r.get_value_or (1)) {
758 state_was_pending = true;
762 if (!state_was_pending) {
763 xmlpath = Glib::build_filename (_session_dir->root_path(), snapshot_name);
766 if (!Glib::file_test (xmlpath, Glib::FILE_TEST_EXISTS)) {
767 xmlpath = Glib::build_filename (_session_dir->root_path(), legalize_for_path (snapshot_name) + statefile_suffix);
768 if (!Glib::file_test (xmlpath, Glib::FILE_TEST_EXISTS)) {
769 error << string_compose(_("%1: session file \"%2\" doesn't exist!"), _name, xmlpath) << endmsg;
774 state_tree = new XMLTree;
778 _writable = exists_and_writable (xmlpath);
780 if (!state_tree->read (xmlpath)) {
781 error << string_compose(_("Could not understand session file %1"), xmlpath) << endmsg;
787 XMLNode& root (*state_tree->root());
789 if (root.name() != X_("Session")) {
790 error << string_compose (_("Session file %1 is not a session"), xmlpath) << endmsg;
796 const XMLProperty* prop;
798 if ((prop = root.property ("version")) == 0) {
799 /* no version implies very old version of Ardour */
800 Stateful::loading_state_version = 1000;
802 if (prop->value().find ('.') != string::npos) {
803 /* old school version format */
804 if (prop->value()[0] == '2') {
805 Stateful::loading_state_version = 2000;
807 Stateful::loading_state_version = 3000;
810 Stateful::loading_state_version = atoi (prop->value());
814 if (Stateful::loading_state_version < CURRENT_SESSION_FILE_VERSION && _writable) {
816 std::string backup_path(_session_dir->root_path());
817 std::string backup_filename = string_compose ("%1-%2%3", legalize_for_path (snapshot_name), Stateful::loading_state_version, statefile_suffix);
818 backup_path = Glib::build_filename (backup_path, backup_filename);
820 // only create a backup for a given statefile version once
822 if (!Glib::file_test (backup_path, Glib::FILE_TEST_EXISTS)) {
824 VersionMismatch (xmlpath, backup_path);
826 if (!copy_file (xmlpath, backup_path)) {;
836 Session::load_options (const XMLNode& node)
838 LocaleGuard lg (X_("POSIX"));
839 config.set_variables (node);
850 Session::get_template()
852 /* if we don't disable rec-enable, diskstreams
853 will believe they need to store their capture
854 sources in their state node.
857 disable_record (false);
863 Session::state (bool full_state)
865 XMLNode* node = new XMLNode("Session");
869 snprintf(buf, sizeof(buf), "%d", CURRENT_SESSION_FILE_VERSION);
870 node->add_property("version", buf);
872 /* store configuration settings */
876 node->add_property ("name", _name);
877 snprintf (buf, sizeof (buf), "%" PRId64, _nominal_frame_rate);
878 node->add_property ("sample-rate", buf);
880 if (session_dirs.size() > 1) {
884 vector<space_and_path>::iterator i = session_dirs.begin();
885 vector<space_and_path>::iterator next;
887 ++i; /* skip the first one */
891 while (i != session_dirs.end()) {
895 if (next != session_dirs.end()) {
905 child = node->add_child ("Path");
906 child->add_content (p);
910 /* save the ID counter */
912 snprintf (buf, sizeof (buf), "%" PRIu64, ID::counter());
913 node->add_property ("id-counter", buf);
915 /* save the event ID counter */
917 snprintf (buf, sizeof (buf), "%d", Evoral::event_id_counter());
918 node->add_property ("event-counter", buf);
920 /* various options */
922 list<XMLNode*> midi_port_nodes = _midi_ports->get_midi_port_states();
923 if (!midi_port_nodes.empty()) {
924 XMLNode* midi_port_stuff = new XMLNode ("MIDIPorts");
925 for (list<XMLNode*>::const_iterator n = midi_port_nodes.begin(); n != midi_port_nodes.end(); ++n) {
926 midi_port_stuff->add_child_nocopy (**n);
928 node->add_child_nocopy (*midi_port_stuff);
931 node->add_child_nocopy (config.get_variables ());
933 node->add_child_nocopy (ARDOUR::SessionMetadata::Metadata()->get_state());
935 child = node->add_child ("Sources");
938 Glib::Threads::Mutex::Lock sl (source_lock);
940 for (SourceMap::iterator siter = sources.begin(); siter != sources.end(); ++siter) {
942 /* Don't save information about non-file Sources, or
943 * about non-destructive file sources that are empty
944 * and unused by any regions.
947 boost::shared_ptr<FileSource> fs;
949 if ((fs = boost::dynamic_pointer_cast<FileSource> (siter->second)) != 0) {
951 if (!fs->destructive()) {
952 if (fs->empty() && !fs->used()) {
957 child->add_child_nocopy (siter->second->get_state());
962 child = node->add_child ("Regions");
965 Glib::Threads::Mutex::Lock rl (region_lock);
966 const RegionFactory::RegionMap& region_map (RegionFactory::all_regions());
967 for (RegionFactory::RegionMap::const_iterator i = region_map.begin(); i != region_map.end(); ++i) {
968 boost::shared_ptr<Region> r = i->second;
969 /* only store regions not attached to playlists */
970 if (r->playlist() == 0) {
971 if (boost::dynamic_pointer_cast<AudioRegion>(r)) {
972 child->add_child_nocopy ((boost::dynamic_pointer_cast<AudioRegion>(r))->get_basic_state ());
974 child->add_child_nocopy (r->get_state ());
979 RegionFactory::CompoundAssociations& cassocs (RegionFactory::compound_associations());
981 if (!cassocs.empty()) {
982 XMLNode* ca = node->add_child (X_("CompoundAssociations"));
984 for (RegionFactory::CompoundAssociations::iterator i = cassocs.begin(); i != cassocs.end(); ++i) {
986 XMLNode* can = new XMLNode (X_("CompoundAssociation"));
987 i->first->id().print (buf, sizeof (buf));
988 can->add_property (X_("copy"), buf);
989 i->second->id().print (buf, sizeof (buf));
990 can->add_property (X_("original"), buf);
991 ca->add_child_nocopy (*can);
997 node->add_child_nocopy (_locations->get_state());
999 // for a template, just create a new Locations, populate it
1000 // with the default start and end, and get the state for that.
1001 Locations loc (*this);
1002 Location* range = new Location (*this, 0, 0, _("session"), Location::IsSessionRange);
1003 range->set (max_framepos, 0);
1005 node->add_child_nocopy (loc.get_state());
1008 child = node->add_child ("Bundles");
1010 boost::shared_ptr<BundleList> bundles = _bundles.reader ();
1011 for (BundleList::iterator i = bundles->begin(); i != bundles->end(); ++i) {
1012 boost::shared_ptr<UserBundle> b = boost::dynamic_pointer_cast<UserBundle> (*i);
1014 child->add_child_nocopy (b->get_state());
1019 child = node->add_child ("Routes");
1021 boost::shared_ptr<RouteList> r = routes.reader ();
1023 RoutePublicOrderSorter cmp;
1024 RouteList public_order (*r);
1025 public_order.sort (cmp);
1027 /* the sort should have put control outs first */
1030 assert (_monitor_out == public_order.front());
1033 for (RouteList::iterator i = public_order.begin(); i != public_order.end(); ++i) {
1034 if (!(*i)->is_auditioner()) {
1036 child->add_child_nocopy ((*i)->get_state());
1038 child->add_child_nocopy ((*i)->get_template());
1044 playlists->add_state (node, full_state);
1046 child = node->add_child ("RouteGroups");
1047 for (list<RouteGroup *>::iterator i = _route_groups.begin(); i != _route_groups.end(); ++i) {
1048 child->add_child_nocopy ((*i)->get_state());
1052 XMLNode* gain_child = node->add_child ("Click");
1053 gain_child->add_child_nocopy (_click_io->state (full_state));
1054 gain_child->add_child_nocopy (_click_gain->state (full_state));
1058 XMLNode* ltc_input_child = node->add_child ("LTC-In");
1059 ltc_input_child->add_child_nocopy (_ltc_input->state (full_state));
1063 XMLNode* ltc_output_child = node->add_child ("LTC-Out");
1064 ltc_output_child->add_child_nocopy (_ltc_output->state (full_state));
1067 node->add_child_nocopy (_speakers->get_state());
1068 node->add_child_nocopy (_tempo_map->get_state());
1069 node->add_child_nocopy (get_control_protocol_state());
1072 node->add_child_copy (*_extra_xml);
1079 Session::get_control_protocol_state ()
1081 ControlProtocolManager& cpm (ControlProtocolManager::instance());
1082 return cpm.get_state();
1086 Session::set_state (const XMLNode& node, int version)
1090 const XMLProperty* prop;
1093 _state_of_the_state = StateOfTheState (_state_of_the_state|CannotSave);
1095 if (node.name() != X_("Session")) {
1096 fatal << _("programming error: Session: incorrect XML node sent to set_state()") << endmsg;
1100 if ((prop = node.property ("name")) != 0) {
1101 _name = prop->value ();
1104 if ((prop = node.property (X_("sample-rate"))) != 0) {
1106 _nominal_frame_rate = atoi (prop->value());
1108 if (_nominal_frame_rate != _current_frame_rate) {
1109 boost::optional<int> r = AskAboutSampleRateMismatch (_nominal_frame_rate, _current_frame_rate);
1110 if (r.get_value_or (0)) {
1116 setup_raid_path(_session_dir->root_path());
1118 if ((prop = node.property (X_("id-counter"))) != 0) {
1120 sscanf (prop->value().c_str(), "%" PRIu64, &x);
1121 ID::init_counter (x);
1123 /* old sessions used a timebased counter, so fake
1124 the startup ID counter based on a standard
1129 ID::init_counter (now);
1132 if ((prop = node.property (X_("event-counter"))) != 0) {
1133 Evoral::init_event_id_counter (atoi (prop->value()));
1137 if ((child = find_named_node (node, "MIDIPorts")) != 0) {
1138 _midi_ports->set_midi_port_states (child->children());
1141 IO::disable_connecting ();
1143 Stateful::save_extra_xml (node);
1145 if (((child = find_named_node (node, "Options")) != 0)) { /* old style */
1146 load_options (*child);
1147 } else if ((child = find_named_node (node, "Config")) != 0) { /* new style */
1148 load_options (*child);
1150 error << _("Session: XML state has no options section") << endmsg;
1153 if (version >= 3000) {
1154 if ((child = find_named_node (node, "Metadata")) == 0) {
1155 warning << _("Session: XML state has no metadata section") << endmsg;
1156 } else if ( ARDOUR::SessionMetadata::Metadata()->set_state (*child, version) ) {
1161 if ((child = find_named_node (node, X_("Speakers"))) != 0) {
1162 _speakers->set_state (*child, version);
1165 if ((child = find_named_node (node, "Sources")) == 0) {
1166 error << _("Session: XML state has no sources section") << endmsg;
1168 } else if (load_sources (*child)) {
1172 if ((child = find_named_node (node, "TempoMap")) == 0) {
1173 error << _("Session: XML state has no Tempo Map section") << endmsg;
1175 } else if (_tempo_map->set_state (*child, version)) {
1179 if ((child = find_named_node (node, "Locations")) == 0) {
1180 error << _("Session: XML state has no locations section") << endmsg;
1182 } else if (_locations->set_state (*child, version)) {
1188 if ((location = _locations->auto_loop_location()) != 0) {
1189 set_auto_loop_location (location);
1192 if ((location = _locations->auto_punch_location()) != 0) {
1193 set_auto_punch_location (location);
1196 if ((location = _locations->session_range_location()) != 0) {
1197 delete _session_range_location;
1198 _session_range_location = location;
1201 if (_session_range_location) {
1202 AudioFileSource::set_header_position_offset (_session_range_location->start());
1205 if ((child = find_named_node (node, "Regions")) == 0) {
1206 error << _("Session: XML state has no Regions section") << endmsg;
1208 } else if (load_regions (*child)) {
1212 if ((child = find_named_node (node, "Playlists")) == 0) {
1213 error << _("Session: XML state has no playlists section") << endmsg;
1215 } else if (playlists->load (*this, *child)) {
1219 if ((child = find_named_node (node, "UnusedPlaylists")) == 0) {
1221 } else if (playlists->load_unused (*this, *child)) {
1225 if ((child = find_named_node (node, "CompoundAssociations")) != 0) {
1226 if (load_compounds (*child)) {
1231 if (version >= 3000) {
1232 if ((child = find_named_node (node, "Bundles")) == 0) {
1233 warning << _("Session: XML state has no bundles section") << endmsg;
1236 /* We can't load Bundles yet as they need to be able
1237 to convert from port names to Port objects, which can't happen until
1239 _bundle_xml_node = new XMLNode (*child);
1243 if (version < 3000) {
1244 if ((child = find_named_node (node, X_("DiskStreams"))) == 0) {
1245 error << _("Session: XML state has no diskstreams section") << endmsg;
1247 } else if (load_diskstreams_2X (*child, version)) {
1252 if ((child = find_named_node (node, "Routes")) == 0) {
1253 error << _("Session: XML state has no routes section") << endmsg;
1255 } else if (load_routes (*child, version)) {
1259 /* our diskstreams list is no longer needed as they are now all owned by their Route */
1260 _diskstreams_2X.clear ();
1262 if (version >= 3000) {
1264 if ((child = find_named_node (node, "RouteGroups")) == 0) {
1265 error << _("Session: XML state has no route groups section") << endmsg;
1267 } else if (load_route_groups (*child, version)) {
1271 } else if (version < 3000) {
1273 if ((child = find_named_node (node, "EditGroups")) == 0) {
1274 error << _("Session: XML state has no edit groups section") << endmsg;
1276 } else if (load_route_groups (*child, version)) {
1280 if ((child = find_named_node (node, "MixGroups")) == 0) {
1281 error << _("Session: XML state has no mix groups section") << endmsg;
1283 } else if (load_route_groups (*child, version)) {
1288 if ((child = find_named_node (node, "Click")) == 0) {
1289 warning << _("Session: XML state has no click section") << endmsg;
1290 } else if (_click_io) {
1291 const XMLNodeList& children (child->children());
1292 XMLNodeList::const_iterator i = children.begin();
1293 _click_io->set_state (**i, version);
1295 if (i != children.end()) {
1296 _click_gain->set_state (**i, version);
1300 if ((child = find_named_node (node, ControlProtocolManager::state_node_name)) != 0) {
1301 ControlProtocolManager::instance().set_state (*child, version);
1304 update_have_rec_enabled_track ();
1306 /* here beginneth the second phase ... */
1308 StateReady (); /* EMIT SIGNAL */
1317 Session::load_routes (const XMLNode& node, int version)
1320 XMLNodeConstIterator niter;
1321 RouteList new_routes;
1323 nlist = node.children();
1327 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1329 boost::shared_ptr<Route> route;
1330 if (version < 3000) {
1331 route = XMLRouteFactory_2X (**niter, version);
1333 route = XMLRouteFactory (**niter, version);
1337 error << _("Session: cannot create Route from XML description.") << endmsg;
1341 BootMessage (string_compose (_("Loaded track/bus %1"), route->name()));
1343 new_routes.push_back (route);
1346 add_routes (new_routes, false, false, false);
1351 boost::shared_ptr<Route>
1352 Session::XMLRouteFactory (const XMLNode& node, int version)
1354 boost::shared_ptr<Route> ret;
1356 if (node.name() != "Route") {
1360 XMLNode* ds_child = find_named_node (node, X_("Diskstream"));
1362 DataType type = DataType::AUDIO;
1363 const XMLProperty* prop = node.property("default-type");
1366 type = DataType (prop->value());
1369 assert (type != DataType::NIL);
1373 boost::shared_ptr<Track> track;
1375 if (type == DataType::AUDIO) {
1376 track.reset (new AudioTrack (*this, X_("toBeResetFroXML")));
1378 track.reset (new MidiTrack (*this, X_("toBeResetFroXML")));
1381 if (track->init()) {
1385 if (track->set_state (node, version)) {
1389 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
1390 // boost_debug_shared_ptr_mark_interesting (track.get(), "Track");
1395 boost::shared_ptr<Route> r (new Route (*this, X_("toBeResetFroXML")));
1397 if (r->init () == 0 && r->set_state (node, version) == 0) {
1398 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
1399 // boost_debug_shared_ptr_mark_interesting (r.get(), "Route");
1408 boost::shared_ptr<Route>
1409 Session::XMLRouteFactory_2X (const XMLNode& node, int version)
1411 boost::shared_ptr<Route> ret;
1413 if (node.name() != "Route") {
1417 XMLProperty const * ds_prop = node.property (X_("diskstream-id"));
1419 ds_prop = node.property (X_("diskstream"));
1422 DataType type = DataType::AUDIO;
1423 const XMLProperty* prop = node.property("default-type");
1426 type = DataType (prop->value());
1429 assert (type != DataType::NIL);
1433 list<boost::shared_ptr<Diskstream> >::iterator i = _diskstreams_2X.begin ();
1434 while (i != _diskstreams_2X.end() && (*i)->id() != ds_prop->value()) {
1438 if (i == _diskstreams_2X.end()) {
1439 error << _("Could not find diskstream for route") << endmsg;
1440 return boost::shared_ptr<Route> ();
1443 boost::shared_ptr<Track> track;
1445 if (type == DataType::AUDIO) {
1446 track.reset (new AudioTrack (*this, X_("toBeResetFroXML")));
1448 track.reset (new MidiTrack (*this, X_("toBeResetFroXML")));
1451 if (track->init()) {
1455 if (track->set_state (node, version)) {
1459 track->set_diskstream (*i);
1461 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
1462 // boost_debug_shared_ptr_mark_interesting (track.get(), "Track");
1467 boost::shared_ptr<Route> r (new Route (*this, X_("toBeResetFroXML")));
1469 if (r->init () == 0 && r->set_state (node, version) == 0) {
1470 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
1471 // boost_debug_shared_ptr_mark_interesting (r.get(), "Route");
1481 Session::load_regions (const XMLNode& node)
1484 XMLNodeConstIterator niter;
1485 boost::shared_ptr<Region> region;
1487 nlist = node.children();
1491 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1492 if ((region = XMLRegionFactory (**niter, false)) == 0) {
1493 error << _("Session: cannot create Region from XML description.");
1494 const XMLProperty *name = (**niter).property("name");
1497 error << " " << string_compose (_("Can not load state for region '%1'"), name->value());
1508 Session::load_compounds (const XMLNode& node)
1510 XMLNodeList calist = node.children();
1511 XMLNodeConstIterator caiter;
1512 XMLProperty *caprop;
1514 for (caiter = calist.begin(); caiter != calist.end(); ++caiter) {
1515 XMLNode* ca = *caiter;
1519 if ((caprop = ca->property (X_("original"))) == 0) {
1522 orig_id = caprop->value();
1524 if ((caprop = ca->property (X_("copy"))) == 0) {
1527 copy_id = caprop->value();
1529 boost::shared_ptr<Region> orig = RegionFactory::region_by_id (orig_id);
1530 boost::shared_ptr<Region> copy = RegionFactory::region_by_id (copy_id);
1532 if (!orig || !copy) {
1533 warning << string_compose (_("Regions in compound description not found (ID's %1 and %2): ignored"),
1539 RegionFactory::add_compound_association (orig, copy);
1546 Session::load_nested_sources (const XMLNode& node)
1549 XMLNodeConstIterator niter;
1551 nlist = node.children();
1553 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1554 if ((*niter)->name() == "Source") {
1556 /* it may already exist, so don't recreate it unnecessarily
1559 XMLProperty* prop = (*niter)->property (X_("id"));
1561 error << _("Nested source has no ID info in session file! (ignored)") << endmsg;
1565 ID source_id (prop->value());
1567 if (!source_by_id (source_id)) {
1570 SourceFactory::create (*this, **niter, true);
1572 catch (failed_constructor& err) {
1573 error << string_compose (_("Cannot reconstruct nested source for region %1"), name()) << endmsg;
1580 boost::shared_ptr<Region>
1581 Session::XMLRegionFactory (const XMLNode& node, bool full)
1583 const XMLProperty* type = node.property("type");
1587 const XMLNodeList& nlist = node.children();
1589 for (XMLNodeConstIterator niter = nlist.begin(); niter != nlist.end(); ++niter) {
1590 XMLNode *child = (*niter);
1591 if (child->name() == "NestedSource") {
1592 load_nested_sources (*child);
1596 if (!type || type->value() == "audio") {
1597 return boost::shared_ptr<Region>(XMLAudioRegionFactory (node, full));
1598 } else if (type->value() == "midi") {
1599 return boost::shared_ptr<Region>(XMLMidiRegionFactory (node, full));
1602 } catch (failed_constructor& err) {
1603 return boost::shared_ptr<Region> ();
1606 return boost::shared_ptr<Region> ();
1609 boost::shared_ptr<AudioRegion>
1610 Session::XMLAudioRegionFactory (const XMLNode& node, bool /*full*/)
1612 const XMLProperty* prop;
1613 boost::shared_ptr<Source> source;
1614 boost::shared_ptr<AudioSource> as;
1616 SourceList master_sources;
1617 uint32_t nchans = 1;
1620 if (node.name() != X_("Region")) {
1621 return boost::shared_ptr<AudioRegion>();
1624 if ((prop = node.property (X_("channels"))) != 0) {
1625 nchans = atoi (prop->value().c_str());
1628 if ((prop = node.property ("name")) == 0) {
1629 cerr << "no name for this region\n";
1633 if ((prop = node.property (X_("source-0"))) == 0) {
1634 if ((prop = node.property ("source")) == 0) {
1635 error << _("Session: XMLNode describing a AudioRegion is incomplete (no source)") << endmsg;
1636 return boost::shared_ptr<AudioRegion>();
1640 PBD::ID s_id (prop->value());
1642 if ((source = source_by_id (s_id)) == 0) {
1643 error << string_compose(_("Session: XMLNode describing a AudioRegion references an unknown source id =%1"), s_id) << endmsg;
1644 return boost::shared_ptr<AudioRegion>();
1647 as = boost::dynamic_pointer_cast<AudioSource>(source);
1649 error << string_compose(_("Session: XMLNode describing a AudioRegion references a non-audio source id =%1"), s_id) << endmsg;
1650 return boost::shared_ptr<AudioRegion>();
1653 sources.push_back (as);
1655 /* pickup other channels */
1657 for (uint32_t n=1; n < nchans; ++n) {
1658 snprintf (buf, sizeof(buf), X_("source-%d"), n);
1659 if ((prop = node.property (buf)) != 0) {
1661 PBD::ID id2 (prop->value());
1663 if ((source = source_by_id (id2)) == 0) {
1664 error << string_compose(_("Session: XMLNode describing a AudioRegion references an unknown source id =%1"), id2) << endmsg;
1665 return boost::shared_ptr<AudioRegion>();
1668 as = boost::dynamic_pointer_cast<AudioSource>(source);
1670 error << string_compose(_("Session: XMLNode describing a AudioRegion references a non-audio source id =%1"), id2) << endmsg;
1671 return boost::shared_ptr<AudioRegion>();
1673 sources.push_back (as);
1677 for (uint32_t n = 0; n < nchans; ++n) {
1678 snprintf (buf, sizeof(buf), X_("master-source-%d"), n);
1679 if ((prop = node.property (buf)) != 0) {
1681 PBD::ID id2 (prop->value());
1683 if ((source = source_by_id (id2)) == 0) {
1684 error << string_compose(_("Session: XMLNode describing a AudioRegion references an unknown source id =%1"), id2) << endmsg;
1685 return boost::shared_ptr<AudioRegion>();
1688 as = boost::dynamic_pointer_cast<AudioSource>(source);
1690 error << string_compose(_("Session: XMLNode describing a AudioRegion references a non-audio source id =%1"), id2) << endmsg;
1691 return boost::shared_ptr<AudioRegion>();
1693 master_sources.push_back (as);
1698 boost::shared_ptr<AudioRegion> region (boost::dynamic_pointer_cast<AudioRegion> (RegionFactory::create (sources, node)));
1700 /* a final detail: this is the one and only place that we know how long missing files are */
1702 if (region->whole_file()) {
1703 for (SourceList::iterator sx = sources.begin(); sx != sources.end(); ++sx) {
1704 boost::shared_ptr<SilentFileSource> sfp = boost::dynamic_pointer_cast<SilentFileSource> (*sx);
1706 sfp->set_length (region->length());
1711 if (!master_sources.empty()) {
1712 if (master_sources.size() != nchans) {
1713 error << _("Session: XMLNode describing an AudioRegion is missing some master sources; ignored") << endmsg;
1715 region->set_master_sources (master_sources);
1723 catch (failed_constructor& err) {
1724 return boost::shared_ptr<AudioRegion>();
1728 boost::shared_ptr<MidiRegion>
1729 Session::XMLMidiRegionFactory (const XMLNode& node, bool /*full*/)
1731 const XMLProperty* prop;
1732 boost::shared_ptr<Source> source;
1733 boost::shared_ptr<MidiSource> ms;
1736 if (node.name() != X_("Region")) {
1737 return boost::shared_ptr<MidiRegion>();
1740 if ((prop = node.property ("name")) == 0) {
1741 cerr << "no name for this region\n";
1745 if ((prop = node.property (X_("source-0"))) == 0) {
1746 if ((prop = node.property ("source")) == 0) {
1747 error << _("Session: XMLNode describing a MidiRegion is incomplete (no source)") << endmsg;
1748 return boost::shared_ptr<MidiRegion>();
1752 PBD::ID s_id (prop->value());
1754 if ((source = source_by_id (s_id)) == 0) {
1755 error << string_compose(_("Session: XMLNode describing a MidiRegion references an unknown source id =%1"), s_id) << endmsg;
1756 return boost::shared_ptr<MidiRegion>();
1759 ms = boost::dynamic_pointer_cast<MidiSource>(source);
1761 error << string_compose(_("Session: XMLNode describing a MidiRegion references a non-midi source id =%1"), s_id) << endmsg;
1762 return boost::shared_ptr<MidiRegion>();
1765 sources.push_back (ms);
1768 boost::shared_ptr<MidiRegion> region (boost::dynamic_pointer_cast<MidiRegion> (RegionFactory::create (sources, node)));
1769 /* a final detail: this is the one and only place that we know how long missing files are */
1771 if (region->whole_file()) {
1772 for (SourceList::iterator sx = sources.begin(); sx != sources.end(); ++sx) {
1773 boost::shared_ptr<SilentFileSource> sfp = boost::dynamic_pointer_cast<SilentFileSource> (*sx);
1775 sfp->set_length (region->length());
1783 catch (failed_constructor& err) {
1784 return boost::shared_ptr<MidiRegion>();
1789 Session::get_sources_as_xml ()
1792 XMLNode* node = new XMLNode (X_("Sources"));
1793 Glib::Threads::Mutex::Lock lm (source_lock);
1795 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ++i) {
1796 node->add_child_nocopy (i->second->get_state());
1803 Session::path_from_region_name (DataType type, string name, string identifier)
1805 char buf[PATH_MAX+1];
1807 SessionDirectory sdir(get_best_session_directory_for_new_source());
1808 std::string source_dir = ((type == DataType::AUDIO)
1809 ? sdir.sound_path() : sdir.midi_path());
1811 string ext = native_header_format_extension (config.get_native_file_header_format(), type);
1813 for (n = 0; n < 999999; ++n) {
1814 if (identifier.length()) {
1815 snprintf (buf, sizeof(buf), "%s%s%" PRIu32 "%s", name.c_str(),
1816 identifier.c_str(), n, ext.c_str());
1818 snprintf (buf, sizeof(buf), "%s-%" PRIu32 "%s", name.c_str(),
1822 std::string source_path = Glib::build_filename (source_dir, buf);
1824 if (!Glib::file_test (source_path, Glib::FILE_TEST_EXISTS)) {
1829 error << string_compose (_("cannot create new file from region name \"%1\" with ident = \"%2\": too many existing files with similar names"),
1838 Session::load_sources (const XMLNode& node)
1841 XMLNodeConstIterator niter;
1842 boost::shared_ptr<Source> source;
1844 nlist = node.children();
1848 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1851 if ((source = XMLSourceFactory (**niter)) == 0) {
1852 error << _("Session: cannot create Source from XML description.") << endmsg;
1855 } catch (MissingSource& err) {
1859 if (!no_questions_about_missing_files) {
1860 user_choice = MissingFile (this, err.path, err.type).get_value_or (-1);
1865 switch (user_choice) {
1867 /* user added a new search location, so try again */
1872 /* user asked to quit the entire session load
1877 no_questions_about_missing_files = true;
1881 no_questions_about_missing_files = true;
1886 warning << _("A sound file is missing. It will be replaced by silence.") << endmsg;
1887 source = SourceFactory::createSilent (*this, **niter, max_framecnt, _current_frame_rate);
1896 boost::shared_ptr<Source>
1897 Session::XMLSourceFactory (const XMLNode& node)
1899 if (node.name() != "Source") {
1900 return boost::shared_ptr<Source>();
1904 /* note: do peak building in another thread when loading session state */
1905 return SourceFactory::create (*this, node, true);
1908 catch (failed_constructor& err) {
1909 error << string_compose (_("Found a sound file that cannot be used by %1. Talk to the progammers."), PROGRAM_NAME) << endmsg;
1910 return boost::shared_ptr<Source>();
1915 Session::save_template (string template_name)
1919 if (_state_of_the_state & CannotSave) {
1923 std::string user_template_dir(user_template_directory());
1925 if (g_mkdir_with_parents (user_template_dir.c_str(), 0755) != 0) {
1926 error << string_compose(_("Could not create templates directory \"%1\" (%2)"),
1927 user_template_dir, g_strerror (errno)) << endmsg;
1931 tree.set_root (&get_template());
1933 std::string template_dir_path(user_template_dir);
1935 /* directory to put the template in */
1936 template_dir_path = Glib::build_filename (template_dir_path, template_name);
1938 if (Glib::file_test (template_dir_path, Glib::FILE_TEST_EXISTS)) {
1939 warning << string_compose(_("Template \"%1\" already exists - new version not created"),
1940 template_dir_path) << endmsg;
1944 if (g_mkdir_with_parents (template_dir_path.c_str(), 0755) != 0) {
1945 error << string_compose(_("Could not create directory for Session template\"%1\" (%2)"),
1946 template_dir_path, g_strerror (errno)) << endmsg;
1951 std::string template_file_path(template_dir_path);
1952 template_file_path = Glib::build_filename (template_file_path, template_name + template_suffix);
1954 if (!tree.write (template_file_path)) {
1955 error << _("template not saved") << endmsg;
1959 /* copy plugin state directory */
1961 std::string template_plugin_state_path(template_dir_path);
1962 template_plugin_state_path = Glib::build_filename (template_plugin_state_path, X_("plugins"));
1964 if (g_mkdir_with_parents (template_plugin_state_path.c_str(), 0755) != 0) {
1965 error << string_compose(_("Could not create directory for Session template plugin state\"%1\" (%2)"),
1966 template_plugin_state_path, g_strerror (errno)) << endmsg;
1970 copy_files (plugins_dir(), template_plugin_state_path);
1976 Session::refresh_disk_space ()
1978 #if __APPLE__ || (HAVE_SYS_VFS_H && HAVE_SYS_STATVFS_H)
1980 Glib::Threads::Mutex::Lock lm (space_lock);
1982 /* get freespace on every FS that is part of the session path */
1984 _total_free_4k_blocks = 0;
1985 _total_free_4k_blocks_uncertain = false;
1987 for (vector<space_and_path>::iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
1989 struct statfs statfsbuf;
1990 statfs (i->path.c_str(), &statfsbuf);
1992 double const scale = statfsbuf.f_bsize / 4096.0;
1994 /* See if this filesystem is read-only */
1995 struct statvfs statvfsbuf;
1996 statvfs (i->path.c_str(), &statvfsbuf);
1998 /* f_bavail can be 0 if it is undefined for whatever
1999 filesystem we are looking at; Samba shares mounted
2000 via GVFS are an example of this.
2002 if (statfsbuf.f_bavail == 0) {
2003 /* block count unknown */
2005 i->blocks_unknown = true;
2006 } else if (statvfsbuf.f_flag & ST_RDONLY) {
2007 /* read-only filesystem */
2009 i->blocks_unknown = false;
2011 /* read/write filesystem with known space */
2012 i->blocks = (uint32_t) floor (statfsbuf.f_bavail * scale);
2013 i->blocks_unknown = false;
2016 _total_free_4k_blocks += i->blocks;
2017 if (i->blocks_unknown) {
2018 _total_free_4k_blocks_uncertain = true;
2021 #elif defined (COMPILER_MSVC)
2022 vector<string> scanned_volumes;
2023 vector<string>::iterator j;
2024 vector<space_and_path>::iterator i;
2025 DWORD nSectorsPerCluster, nBytesPerSector,
2026 nFreeClusters, nTotalClusters;
2030 _total_free_4k_blocks = 0;
2032 for (i = session_dirs.begin(); i != session_dirs.end(); i++) {
2033 strncpy (disk_drive, (*i).path.c_str(), 3);
2037 volume_found = false;
2038 if (0 != (GetDiskFreeSpace(disk_drive, &nSectorsPerCluster, &nBytesPerSector, &nFreeClusters, &nTotalClusters)))
2040 int64_t nBytesPerCluster = nBytesPerSector * nSectorsPerCluster;
2041 int64_t nFreeBytes = nBytesPerCluster * (int64_t)nFreeClusters;
2042 i->blocks = (uint32_t)(nFreeBytes / 4096);
2044 for (j = scanned_volumes.begin(); j != scanned_volumes.end(); j++) {
2045 if (0 == j->compare(disk_drive)) {
2046 volume_found = true;
2051 if (!volume_found) {
2052 scanned_volumes.push_back(disk_drive);
2053 _total_free_4k_blocks += i->blocks;
2058 if (0 == _total_free_4k_blocks) {
2059 strncpy (disk_drive, path().c_str(), 3);
2062 if (0 != (GetDiskFreeSpace(disk_drive, &nSectorsPerCluster, &nBytesPerSector, &nFreeClusters, &nTotalClusters)))
2064 int64_t nBytesPerCluster = nBytesPerSector * nSectorsPerCluster;
2065 int64_t nFreeBytes = nBytesPerCluster * (int64_t)nFreeClusters;
2066 _total_free_4k_blocks = (uint32_t)(nFreeBytes / 4096);
2073 Session::get_best_session_directory_for_new_source ()
2075 vector<space_and_path>::iterator i;
2076 string result = _session_dir->root_path();
2078 /* handle common case without system calls */
2080 if (session_dirs.size() == 1) {
2084 /* OK, here's the algorithm we're following here:
2086 We want to select which directory to use for
2087 the next file source to be created. Ideally,
2088 we'd like to use a round-robin process so as to
2089 get maximum performance benefits from splitting
2090 the files across multiple disks.
2092 However, in situations without much diskspace, an
2093 RR approach may end up filling up a filesystem
2094 with new files while others still have space.
2095 Its therefore important to pay some attention to
2096 the freespace in the filesystem holding each
2097 directory as well. However, if we did that by
2098 itself, we'd keep creating new files in the file
2099 system with the most space until it was as full
2100 as all others, thus negating any performance
2101 benefits of this RAID-1 like approach.
2103 So, we use a user-configurable space threshold. If
2104 there are at least 2 filesystems with more than this
2105 much space available, we use RR selection between them.
2106 If not, then we pick the filesystem with the most space.
2108 This gets a good balance between the two
2112 refresh_disk_space ();
2114 int free_enough = 0;
2116 for (i = session_dirs.begin(); i != session_dirs.end(); ++i) {
2117 if ((*i).blocks * 4096 >= Config->get_disk_choice_space_threshold()) {
2122 if (free_enough >= 2) {
2123 /* use RR selection process, ensuring that the one
2127 i = last_rr_session_dir;
2130 if (++i == session_dirs.end()) {
2131 i = session_dirs.begin();
2134 if ((*i).blocks * 4096 >= Config->get_disk_choice_space_threshold()) {
2135 SessionDirectory sdir(i->path);
2136 if (sdir.create ()) {
2138 last_rr_session_dir = i;
2143 } while (i != last_rr_session_dir);
2147 /* pick FS with the most freespace (and that
2148 seems to actually work ...)
2151 vector<space_and_path> sorted;
2152 space_and_path_ascending_cmp cmp;
2154 sorted = session_dirs;
2155 sort (sorted.begin(), sorted.end(), cmp);
2157 for (i = sorted.begin(); i != sorted.end(); ++i) {
2158 SessionDirectory sdir(i->path);
2159 if (sdir.create ()) {
2161 last_rr_session_dir = i;
2171 Session::automation_dir () const
2173 return Glib::build_filename (_path, "automation");
2177 Session::analysis_dir () const
2179 return Glib::build_filename (_path, "analysis");
2183 Session::plugins_dir () const
2185 return Glib::build_filename (_path, "plugins");
2189 Session::externals_dir () const
2191 return Glib::build_filename (_path, "externals");
2195 Session::load_bundles (XMLNode const & node)
2197 XMLNodeList nlist = node.children();
2198 XMLNodeConstIterator niter;
2202 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2203 if ((*niter)->name() == "InputBundle") {
2204 add_bundle (boost::shared_ptr<UserBundle> (new UserBundle (**niter, true)));
2205 } else if ((*niter)->name() == "OutputBundle") {
2206 add_bundle (boost::shared_ptr<UserBundle> (new UserBundle (**niter, false)));
2208 error << string_compose(_("Unknown node \"%1\" found in Bundles list from session file"), (*niter)->name()) << endmsg;
2217 Session::load_route_groups (const XMLNode& node, int version)
2219 XMLNodeList nlist = node.children();
2220 XMLNodeConstIterator niter;
2224 if (version >= 3000) {
2226 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2227 if ((*niter)->name() == "RouteGroup") {
2228 RouteGroup* rg = new RouteGroup (*this, "");
2229 add_route_group (rg);
2230 rg->set_state (**niter, version);
2234 } else if (version < 3000) {
2236 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2237 if ((*niter)->name() == "EditGroup" || (*niter)->name() == "MixGroup") {
2238 RouteGroup* rg = new RouteGroup (*this, "");
2239 add_route_group (rg);
2240 rg->set_state (**niter, version);
2249 Session::auto_save()
2251 save_state (_current_snapshot_name);
2255 state_file_filter (const string &str, void* /*arg*/)
2257 return (str.length() > strlen(statefile_suffix) &&
2258 str.find (statefile_suffix) == (str.length() - strlen (statefile_suffix)));
2262 bool operator()(const string* a, const string* b) {
2268 remove_end(string* state)
2270 string statename(*state);
2272 string::size_type start,end;
2273 if ((start = statename.find_last_of (G_DIR_SEPARATOR)) != string::npos) {
2274 statename = statename.substr (start+1);
2277 if ((end = statename.rfind(".ardour")) == string::npos) {
2278 end = statename.length();
2281 return new string(statename.substr (0, end));
2285 Session::possible_states (string path)
2287 PathScanner scanner;
2288 vector<string*>* states = scanner (path, state_file_filter, 0, false, false);
2290 transform(states->begin(), states->end(), states->begin(), remove_end);
2293 sort (states->begin(), states->end(), cmp);
2299 Session::possible_states () const
2301 return possible_states(_path);
2305 Session::add_route_group (RouteGroup* g)
2307 _route_groups.push_back (g);
2308 route_group_added (g); /* EMIT SIGNAL */
2310 g->RouteAdded.connect_same_thread (*this, boost::bind (&Session::route_added_to_route_group, this, _1, _2));
2311 g->RouteRemoved.connect_same_thread (*this, boost::bind (&Session::route_removed_from_route_group, this, _1, _2));
2312 g->PropertyChanged.connect_same_thread (*this, boost::bind (&Session::route_group_property_changed, this, g));
2318 Session::remove_route_group (RouteGroup& rg)
2320 list<RouteGroup*>::iterator i;
2322 if ((i = find (_route_groups.begin(), _route_groups.end(), &rg)) != _route_groups.end()) {
2323 _route_groups.erase (i);
2326 route_group_removed (); /* EMIT SIGNAL */
2330 /** Set a new order for our route groups, without adding or removing any.
2331 * @param groups Route group list in the new order.
2334 Session::reorder_route_groups (list<RouteGroup*> groups)
2336 _route_groups = groups;
2338 route_groups_reordered (); /* EMIT SIGNAL */
2344 Session::route_group_by_name (string name)
2346 list<RouteGroup *>::iterator i;
2348 for (i = _route_groups.begin(); i != _route_groups.end(); ++i) {
2349 if ((*i)->name() == name) {
2357 Session::all_route_group() const
2359 return *_all_route_group;
2363 Session::add_commands (vector<Command*> const & cmds)
2365 for (vector<Command*>::const_iterator i = cmds.begin(); i != cmds.end(); ++i) {
2371 Session::begin_reversible_command (const string& name)
2373 begin_reversible_command (g_quark_from_string (name.c_str ()));
2376 /** Begin a reversible command using a GQuark to identify it.
2377 * begin_reversible_command() and commit_reversible_command() calls may be nested,
2378 * but there must be as many begin...()s as there are commit...()s.
2381 Session::begin_reversible_command (GQuark q)
2383 /* If nested begin/commit pairs are used, we create just one UndoTransaction
2384 to hold all the commands that are committed. This keeps the order of
2385 commands correct in the history.
2388 if (_current_trans == 0) {
2389 /* start a new transaction */
2390 assert (_current_trans_quarks.empty ());
2391 _current_trans = new UndoTransaction();
2392 _current_trans->set_name (g_quark_to_string (q));
2395 _current_trans_quarks.push_front (q);
2399 Session::commit_reversible_command (Command *cmd)
2401 assert (_current_trans);
2402 assert (!_current_trans_quarks.empty ());
2407 _current_trans->add_command (cmd);
2410 _current_trans_quarks.pop_front ();
2412 if (!_current_trans_quarks.empty ()) {
2413 /* the transaction we're committing is not the top-level one */
2417 if (_current_trans->empty()) {
2418 /* no commands were added to the transaction, so just get rid of it */
2419 delete _current_trans;
2424 gettimeofday (&now, 0);
2425 _current_trans->set_timestamp (now);
2427 _history.add (_current_trans);
2432 accept_all_audio_files (const string& path, void* /*arg*/)
2434 if (!Glib::file_test (path, Glib::FILE_TEST_IS_REGULAR)) {
2438 if (!AudioFileSource::safe_audio_file_extension (path)) {
2446 accept_all_midi_files (const string& path, void* /*arg*/)
2448 if (!Glib::file_test (path, Glib::FILE_TEST_IS_REGULAR)) {
2452 return ((path.length() > 4 && path.find (".mid") != (path.length() - 4)) ||
2453 (path.length() > 4 && path.find (".smf") != (path.length() - 4)) ||
2454 (path.length() > 5 && path.find (".midi") != (path.length() - 5)));
2458 accept_all_state_files (const string& path, void* /*arg*/)
2460 if (!Glib::file_test (path, Glib::FILE_TEST_IS_REGULAR)) {
2464 return (path.length() > 7 && path.find (".ardour") == (path.length() - 7));
2468 Session::find_all_sources (string path, set<string>& result)
2473 if (!tree.read (path)) {
2477 if ((node = find_named_node (*tree.root(), "Sources")) == 0) {
2482 XMLNodeConstIterator niter;
2484 nlist = node->children();
2488 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2492 if ((prop = (*niter)->property (X_("type"))) == 0) {
2496 DataType type (prop->value());
2498 if ((prop = (*niter)->property (X_("name"))) == 0) {
2502 if (Glib::path_is_absolute (prop->value())) {
2503 /* external file, ignore */
2511 if (FileSource::find (*this, type, prop->value(), true, is_new, chan, found_path)) {
2512 result.insert (found_path);
2520 Session::find_all_sources_across_snapshots (set<string>& result, bool exclude_this_snapshot)
2522 PathScanner scanner;
2523 vector<string*>* state_files;
2525 string this_snapshot_path;
2531 if (ripped[ripped.length()-1] == G_DIR_SEPARATOR) {
2532 ripped = ripped.substr (0, ripped.length() - 1);
2535 state_files = scanner (ripped, accept_all_state_files, (void *) 0, true, true);
2537 if (state_files == 0) {
2542 this_snapshot_path = _path;
2543 this_snapshot_path += legalize_for_path (_current_snapshot_name);
2544 this_snapshot_path += statefile_suffix;
2546 for (vector<string*>::iterator i = state_files->begin(); i != state_files->end(); ++i) {
2548 if (exclude_this_snapshot && **i == this_snapshot_path) {
2552 if (find_all_sources (**i, result) < 0) {
2560 struct RegionCounter {
2561 typedef std::map<PBD::ID,boost::shared_ptr<AudioSource> > AudioSourceList;
2562 AudioSourceList::iterator iter;
2563 boost::shared_ptr<Region> region;
2566 RegionCounter() : count (0) {}
2570 Session::ask_about_playlist_deletion (boost::shared_ptr<Playlist> p)
2572 boost::optional<int> r = AskAboutPlaylistDeletion (p);
2573 return r.get_value_or (1);
2577 Session::cleanup_regions ()
2579 const RegionFactory::RegionMap& regions (RegionFactory::regions());
2581 for (RegionFactory::RegionMap::const_iterator i = regions.begin(); i != regions.end(); ++i) {
2583 uint32_t used = playlists->region_use_count (i->second);
2585 if (used == 0 && !i->second->automatic ()) {
2586 RegionFactory::map_remove (i->second);
2590 /* dump the history list */
2597 Session::cleanup_sources (CleanupReport& rep)
2599 // FIXME: needs adaptation to midi
2601 vector<boost::shared_ptr<Source> > dead_sources;
2602 PathScanner scanner;
2605 vector<space_and_path>::iterator i;
2606 vector<space_and_path>::iterator nexti;
2607 vector<string*>* candidates;
2608 vector<string*>* candidates2;
2609 vector<string> unused;
2610 set<string> all_sources;
2617 _state_of_the_state = (StateOfTheState) (_state_of_the_state | InCleanup);
2619 /* consider deleting all unused playlists */
2621 if (playlists->maybe_delete_unused (boost::bind (Session::ask_about_playlist_deletion, _1))) {
2626 /* sync the "all regions" property of each playlist with its current state
2629 playlists->sync_all_regions_with_regions ();
2631 /* find all un-used sources */
2636 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ) {
2638 SourceMap::iterator tmp;
2643 /* do not bother with files that are zero size, otherwise we remove the current "nascent"
2647 if (!i->second->used() && (i->second->length(i->second->timeline_position() > 0))) {
2648 dead_sources.push_back (i->second);
2649 i->second->drop_references ();
2655 /* build a list of all the possible audio directories for the session */
2657 for (i = session_dirs.begin(); i != session_dirs.end(); ) {
2662 SessionDirectory sdir ((*i).path);
2663 audio_path += sdir.sound_path();
2665 if (nexti != session_dirs.end()) {
2673 /* build a list of all the possible midi directories for the session */
2675 for (i = session_dirs.begin(); i != session_dirs.end(); ) {
2680 SessionDirectory sdir ((*i).path);
2681 midi_path += sdir.midi_path();
2683 if (nexti != session_dirs.end()) {
2690 candidates = scanner (audio_path, accept_all_audio_files, (void *) 0, true, true);
2691 candidates2 = scanner (midi_path, accept_all_midi_files, (void *) 0, true, true);
2697 for (vector<string*>::iterator i = candidates2->begin(); i != candidates2->end(); ++i) {
2698 candidates->push_back (*i);
2703 candidates = candidates2; // might still be null
2706 /* find all sources, but don't use this snapshot because the
2707 state file on disk still references sources we may have already
2711 find_all_sources_across_snapshots (all_sources, true);
2713 /* add our current source list
2716 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ) {
2717 boost::shared_ptr<FileSource> fs;
2718 SourceMap::iterator tmp = i;
2721 if ((fs = boost::dynamic_pointer_cast<FileSource> (i->second)) != 0) {
2722 if (playlists->source_use_count (fs) != 0) {
2723 all_sources.insert (fs->path());
2726 /* we might not remove this source from disk, because it may be used
2727 by other snapshots, but its not being used in this version
2728 so lets get rid of it now, along with any representative regions
2732 RegionFactory::remove_regions_using_source (i->second);
2741 for (vector<string*>::iterator x = candidates->begin(); x != candidates->end(); ++x) {
2746 for (set<string>::iterator i = all_sources.begin(); i != all_sources.end(); ++i) {
2748 tmppath1 = canonical_path (spath);
2749 tmppath2 = canonical_path ((*i));
2751 if (tmppath1 == tmppath2) {
2758 unused.push_back (spath);
2767 /* now try to move all unused files into the "dead" directory(ies) */
2769 for (vector<string>::iterator x = unused.begin(); x != unused.end(); ++x) {
2770 struct stat statbuf;
2774 /* don't move the file across filesystems, just
2775 stick it in the `dead_dir_name' directory
2776 on whichever filesystem it was already on.
2779 if ((*x).find ("/sounds/") != string::npos) {
2781 /* old school, go up 1 level */
2783 newpath = Glib::path_get_dirname (*x); // "sounds"
2784 newpath = Glib::path_get_dirname (newpath); // "session-name"
2788 /* new school, go up 4 levels */
2790 newpath = Glib::path_get_dirname (*x); // "audiofiles" or "midifiles"
2791 newpath = Glib::path_get_dirname (newpath); // "session-name"
2792 newpath = Glib::path_get_dirname (newpath); // "interchange"
2793 newpath = Glib::path_get_dirname (newpath); // "session-dir"
2796 newpath = Glib::build_filename (newpath, dead_dir_name);
2798 if (g_mkdir_with_parents (newpath.c_str(), 0755) < 0) {
2799 error << string_compose(_("Session: cannot create dead file folder \"%1\" (%2)"), newpath, strerror (errno)) << endmsg;
2803 newpath = Glib::build_filename (newpath, Glib::path_get_basename ((*x)));
2805 if (Glib::file_test (newpath, Glib::FILE_TEST_EXISTS)) {
2807 /* the new path already exists, try versioning */
2809 char buf[PATH_MAX+1];
2813 snprintf (buf, sizeof (buf), "%s.%d", newpath.c_str(), version);
2816 while (Glib::file_test (newpath_v.c_str(), Glib::FILE_TEST_EXISTS) && version < 999) {
2817 snprintf (buf, sizeof (buf), "%s.%d", newpath.c_str(), ++version);
2821 if (version == 999) {
2822 error << string_compose (_("there are already 1000 files with names like %1; versioning discontinued"),
2826 newpath = newpath_v;
2831 /* it doesn't exist, or we can't read it or something */
2835 stat ((*x).c_str(), &statbuf);
2837 if (::rename ((*x).c_str(), newpath.c_str()) != 0) {
2838 error << string_compose (_("cannot rename unused file source from %1 to %2 (%3)"),
2839 (*x), newpath, strerror (errno))
2844 /* see if there an easy to find peakfile for this file, and remove it.
2847 string base = basename_nosuffix (*x);
2848 base += "%A"; /* this is what we add for the channel suffix of all native files,
2849 or for the first channel of embedded files. it will miss
2850 some peakfiles for other channels
2852 string peakpath = peak_path (base);
2854 if (Glib::file_test (peakpath.c_str(), Glib::FILE_TEST_EXISTS)) {
2855 if (::g_unlink (peakpath.c_str()) != 0) {
2856 error << string_compose (_("cannot remove peakfile %1 for %2 (%3)"),
2857 peakpath, _path, strerror (errno))
2859 /* try to back out */
2860 ::rename (newpath.c_str(), _path.c_str());
2865 rep.paths.push_back (*x);
2866 rep.space += statbuf.st_size;
2869 /* dump the history list */
2873 /* save state so we don't end up a session file
2874 referring to non-existent sources.
2881 _state_of_the_state = (StateOfTheState) (_state_of_the_state & ~InCleanup);
2887 Session::cleanup_trash_sources (CleanupReport& rep)
2889 // FIXME: needs adaptation for MIDI
2891 vector<space_and_path>::iterator i;
2897 for (i = session_dirs.begin(); i != session_dirs.end(); ++i) {
2899 dead_dir = Glib::build_filename ((*i).path, dead_dir_name);
2901 clear_directory (dead_dir, &rep.space, &rep.paths);
2908 Session::set_dirty ()
2910 bool was_dirty = dirty();
2912 _state_of_the_state = StateOfTheState (_state_of_the_state | Dirty);
2916 DirtyChanged(); /* EMIT SIGNAL */
2922 Session::set_clean ()
2924 bool was_dirty = dirty();
2926 _state_of_the_state = Clean;
2930 DirtyChanged(); /* EMIT SIGNAL */
2935 Session::set_deletion_in_progress ()
2937 _state_of_the_state = StateOfTheState (_state_of_the_state | Deletion);
2941 Session::clear_deletion_in_progress ()
2943 _state_of_the_state = StateOfTheState (_state_of_the_state & (~Deletion));
2947 Session::add_controllable (boost::shared_ptr<Controllable> c)
2949 /* this adds a controllable to the list managed by the Session.
2950 this is a subset of those managed by the Controllable class
2951 itself, and represents the only ones whose state will be saved
2952 as part of the session.
2955 Glib::Threads::Mutex::Lock lm (controllables_lock);
2956 controllables.insert (c);
2959 struct null_deleter { void operator()(void const *) const {} };
2962 Session::remove_controllable (Controllable* c)
2964 if (_state_of_the_state & Deletion) {
2968 Glib::Threads::Mutex::Lock lm (controllables_lock);
2970 Controllables::iterator x = controllables.find (boost::shared_ptr<Controllable>(c, null_deleter()));
2972 if (x != controllables.end()) {
2973 controllables.erase (x);
2977 boost::shared_ptr<Controllable>
2978 Session::controllable_by_id (const PBD::ID& id)
2980 Glib::Threads::Mutex::Lock lm (controllables_lock);
2982 for (Controllables::iterator i = controllables.begin(); i != controllables.end(); ++i) {
2983 if ((*i)->id() == id) {
2988 return boost::shared_ptr<Controllable>();
2991 boost::shared_ptr<Controllable>
2992 Session::controllable_by_descriptor (const ControllableDescriptor& desc)
2994 boost::shared_ptr<Controllable> c;
2995 boost::shared_ptr<Route> r;
2997 switch (desc.top_level_type()) {
2998 case ControllableDescriptor::NamedRoute:
3000 std::string str = desc.top_level_name();
3001 if (str == "master") {
3003 } else if (str == "control" || str == "listen") {
3006 r = route_by_name (desc.top_level_name());
3011 case ControllableDescriptor::RemoteControlID:
3012 r = route_by_remote_id (desc.rid());
3020 switch (desc.subtype()) {
3021 case ControllableDescriptor::Gain:
3022 c = r->gain_control ();
3025 case ControllableDescriptor::Solo:
3026 c = r->solo_control();
3029 case ControllableDescriptor::Mute:
3030 c = r->mute_control();
3033 case ControllableDescriptor::Recenable:
3035 boost::shared_ptr<Track> t = boost::dynamic_pointer_cast<Track>(r);
3038 c = t->rec_enable_control ();
3043 case ControllableDescriptor::PanDirection:
3045 c = r->pannable()->pan_azimuth_control;
3049 case ControllableDescriptor::PanWidth:
3051 c = r->pannable()->pan_width_control;
3055 case ControllableDescriptor::PanElevation:
3057 c = r->pannable()->pan_elevation_control;
3061 case ControllableDescriptor::Balance:
3062 /* XXX simple pan control */
3065 case ControllableDescriptor::PluginParameter:
3067 uint32_t plugin = desc.target (0);
3068 uint32_t parameter_index = desc.target (1);
3070 /* revert to zero based counting */
3076 if (parameter_index > 0) {
3080 boost::shared_ptr<Processor> p = r->nth_plugin (plugin);
3083 c = boost::dynamic_pointer_cast<ARDOUR::AutomationControl>(
3084 p->control(Evoral::Parameter(PluginAutomation, 0, parameter_index)));
3089 case ControllableDescriptor::SendGain:
3091 uint32_t send = desc.target (0);
3093 /* revert to zero-based counting */
3099 boost::shared_ptr<Processor> p = r->nth_send (send);
3102 boost::shared_ptr<Send> s = boost::dynamic_pointer_cast<Send>(p);
3103 boost::shared_ptr<Amp> a = s->amp();
3106 c = s->amp()->gain_control();
3113 /* relax and return a null pointer */
3121 Session::add_instant_xml (XMLNode& node, bool write_to_config)
3124 Stateful::add_instant_xml (node, _path);
3127 if (write_to_config) {
3128 Config->add_instant_xml (node);
3133 Session::instant_xml (const string& node_name)
3135 return Stateful::instant_xml (node_name, _path);
3139 Session::save_history (string snapshot_name)
3147 if (snapshot_name.empty()) {
3148 snapshot_name = _current_snapshot_name;
3151 const string history_filename = legalize_for_path (snapshot_name) + history_suffix;
3152 const string backup_filename = history_filename + backup_suffix;
3153 const std::string xml_path(Glib::build_filename (_session_dir->root_path(), history_filename));
3154 const std::string backup_path(Glib::build_filename (_session_dir->root_path(), backup_filename));
3156 if (Glib::file_test (xml_path, Glib::FILE_TEST_EXISTS)) {
3157 if (::g_rename (xml_path.c_str(), backup_path.c_str()) != 0) {
3158 error << _("could not backup old history file, current history not saved") << endmsg;
3163 if (!Config->get_save_history() || Config->get_saved_history_depth() < 0) {
3167 tree.set_root (&_history.get_state (Config->get_saved_history_depth()));
3169 if (!tree.write (xml_path))
3171 error << string_compose (_("history could not be saved to %1"), xml_path) << endmsg;
3173 if (g_remove (xml_path.c_str()) != 0) {
3174 error << string_compose(_("Could not remove history file at path \"%1\" (%2)"),
3175 xml_path, g_strerror (errno)) << endmsg;
3177 if (::g_rename (backup_path.c_str(), xml_path.c_str()) != 0) {
3178 error << string_compose (_("could not restore history file from backup %1 (%2)"),
3179 backup_path, g_strerror (errno)) << endmsg;
3189 Session::restore_history (string snapshot_name)
3193 if (snapshot_name.empty()) {
3194 snapshot_name = _current_snapshot_name;
3197 const std::string xml_filename = legalize_for_path (snapshot_name) + history_suffix;
3198 const std::string xml_path(Glib::build_filename (_session_dir->root_path(), xml_filename));
3200 info << "Loading history from " << xml_path << endmsg;
3202 if (!Glib::file_test (xml_path, Glib::FILE_TEST_EXISTS)) {
3203 info << string_compose (_("%1: no history file \"%2\" for this session."),
3204 _name, xml_path) << endmsg;
3208 if (!tree.read (xml_path)) {
3209 error << string_compose (_("Could not understand session history file \"%1\""),
3210 xml_path) << endmsg;
3217 for (XMLNodeConstIterator it = tree.root()->children().begin(); it != tree.root()->children().end(); it++) {
3220 UndoTransaction* ut = new UndoTransaction ();
3223 ut->set_name(t->property("name")->value());
3224 stringstream ss(t->property("tv-sec")->value());
3226 ss.str(t->property("tv-usec")->value());
3228 ut->set_timestamp(tv);
3230 for (XMLNodeConstIterator child_it = t->children().begin();
3231 child_it != t->children().end(); child_it++)
3233 XMLNode *n = *child_it;
3236 if (n->name() == "MementoCommand" ||
3237 n->name() == "MementoUndoCommand" ||
3238 n->name() == "MementoRedoCommand") {
3240 if ((c = memento_command_factory(n))) {
3244 } else if (n->name() == "NoteDiffCommand") {
3245 PBD::ID id (n->property("midi-source")->value());
3246 boost::shared_ptr<MidiSource> midi_source =
3247 boost::dynamic_pointer_cast<MidiSource, Source>(source_by_id(id));
3249 ut->add_command (new MidiModel::NoteDiffCommand(midi_source->model(), *n));
3251 error << _("Failed to downcast MidiSource for NoteDiffCommand") << endmsg;
3254 } else if (n->name() == "SysExDiffCommand") {
3256 PBD::ID id (n->property("midi-source")->value());
3257 boost::shared_ptr<MidiSource> midi_source =
3258 boost::dynamic_pointer_cast<MidiSource, Source>(source_by_id(id));
3260 ut->add_command (new MidiModel::SysExDiffCommand (midi_source->model(), *n));
3262 error << _("Failed to downcast MidiSource for SysExDiffCommand") << endmsg;
3265 } else if (n->name() == "PatchChangeDiffCommand") {
3267 PBD::ID id (n->property("midi-source")->value());
3268 boost::shared_ptr<MidiSource> midi_source =
3269 boost::dynamic_pointer_cast<MidiSource, Source>(source_by_id(id));
3271 ut->add_command (new MidiModel::PatchChangeDiffCommand (midi_source->model(), *n));
3273 error << _("Failed to downcast MidiSource for PatchChangeDiffCommand") << endmsg;
3276 } else if (n->name() == "StatefulDiffCommand") {
3277 if ((c = stateful_diff_command_factory (n))) {
3278 ut->add_command (c);
3281 error << string_compose(_("Couldn't figure out how to make a Command out of a %1 XMLNode."), n->name()) << endmsg;
3292 Session::config_changed (std::string p, bool ours)
3298 if (p == "seamless-loop") {
3300 } else if (p == "rf-speed") {
3302 } else if (p == "auto-loop") {
3304 } else if (p == "auto-input") {
3306 if (Config->get_monitoring_model() == HardwareMonitoring && transport_rolling()) {
3307 /* auto-input only makes a difference if we're rolling */
3308 set_track_monitor_input_status (!config.get_auto_input());
3311 } else if (p == "punch-in") {
3315 if ((location = _locations->auto_punch_location()) != 0) {
3317 if (config.get_punch_in ()) {
3318 replace_event (SessionEvent::PunchIn, location->start());
3320 remove_event (location->start(), SessionEvent::PunchIn);
3324 } else if (p == "punch-out") {
3328 if ((location = _locations->auto_punch_location()) != 0) {
3330 if (config.get_punch_out()) {
3331 replace_event (SessionEvent::PunchOut, location->end());
3333 clear_events (SessionEvent::PunchOut);
3337 } else if (p == "edit-mode") {
3339 Glib::Threads::Mutex::Lock lm (playlists->lock);
3341 for (SessionPlaylists::List::iterator i = playlists->playlists.begin(); i != playlists->playlists.end(); ++i) {
3342 (*i)->set_edit_mode (Config->get_edit_mode ());
3345 } else if (p == "use-video-sync") {
3347 waiting_for_sync_offset = config.get_use_video_sync();
3349 } else if (p == "mmc-control") {
3351 //poke_midi_thread ();
3353 } else if (p == "mmc-device-id" || p == "mmc-receive-id" || p == "mmc-receive-device-id") {
3355 _mmc->set_receive_device_id (Config->get_mmc_receive_device_id());
3357 } else if (p == "mmc-send-id" || p == "mmc-send-device-id") {
3359 _mmc->set_send_device_id (Config->get_mmc_send_device_id());
3361 } else if (p == "midi-control") {
3363 //poke_midi_thread ();
3365 } else if (p == "raid-path") {
3367 setup_raid_path (config.get_raid_path());
3369 } else if (p == "timecode-format") {
3373 } else if (p == "video-pullup") {
3377 } else if (p == "seamless-loop") {
3379 if (play_loop && transport_rolling()) {
3380 // to reset diskstreams etc
3381 request_play_loop (true);
3384 } else if (p == "rf-speed") {
3386 cumulative_rf_motion = 0;
3389 } else if (p == "click-sound") {
3391 setup_click_sounds (1);
3393 } else if (p == "click-emphasis-sound") {
3395 setup_click_sounds (-1);
3397 } else if (p == "clicking") {
3399 if (Config->get_clicking()) {
3400 if (_click_io && click_data) { // don't require emphasis data
3407 } else if (p == "click-gain") {
3410 _click_gain->set_gain (Config->get_click_gain(), this);
3413 } else if (p == "send-mtc") {
3415 if (Config->get_send_mtc ()) {
3416 /* mark us ready to send */
3417 next_quarter_frame_to_send = 0;
3420 } else if (p == "send-mmc") {
3422 _mmc->enable_send (Config->get_send_mmc ());
3424 } else if (p == "midi-feedback") {
3426 session_midi_feedback = Config->get_midi_feedback();
3428 } else if (p == "jack-time-master") {
3430 engine().reset_timebase ();
3432 } else if (p == "native-file-header-format") {
3434 if (!first_file_header_format_reset) {
3435 reset_native_file_format ();
3438 first_file_header_format_reset = false;
3440 } else if (p == "native-file-data-format") {
3442 if (!first_file_data_format_reset) {
3443 reset_native_file_format ();
3446 first_file_data_format_reset = false;
3448 } else if (p == "external-sync") {
3449 if (!config.get_external_sync()) {
3450 drop_sync_source ();
3452 switch_to_sync_source (Config->get_sync_source());
3454 } else if (p == "denormal-model") {
3456 } else if (p == "history-depth") {
3457 set_history_depth (Config->get_history_depth());
3458 } else if (p == "remote-model") {
3459 /* XXX DO SOMETHING HERE TO TELL THE GUI THAT WE NEED
3462 } else if (p == "sync-all-route-ordering") {
3464 /* sync to editor order unless mixer is used for remote IDs
3467 switch (Config->get_remote_model()) {
3469 sync_order_keys (EditorSort);
3472 sync_order_keys (EditorSort);
3475 sync_order_keys (MixerSort);
3478 } else if (p == "initial-program-change") {
3480 if (_mmc->output_port() && Config->get_initial_program_change() >= 0) {
3483 buf[0] = MIDI::program; // channel zero by default
3484 buf[1] = (Config->get_initial_program_change() & 0x7f);
3486 _mmc->output_port()->midimsg (buf, sizeof (buf), 0);
3488 } else if (p == "solo-mute-override") {
3489 // catch_up_on_solo_mute_override ();
3490 } else if (p == "listen-position" || p == "pfl-position") {
3491 listen_position_changed ();
3492 } else if (p == "solo-control-is-listen-control") {
3493 solo_control_mode_changed ();
3494 } else if (p == "timecode-offset" || p == "timecode-offset-negative") {
3495 last_timecode_valid = false;
3496 } else if (p == "playback-buffer-seconds") {
3497 AudioSource::allocate_working_buffers (frame_rate());
3498 } else if (p == "automation-thinning-factor") {
3499 Evoral::ControlList::set_thinning_factor (Config->get_automation_thinning_factor());
3500 } else if (p == "ltc-source-port") {
3501 reconnect_ltc_input ();
3502 } else if (p == "ltc-sink-port") {
3503 reconnect_ltc_output ();
3504 } else if (p == "timecode-generator-offset") {
3505 ltc_tx_parse_offset();
3512 Session::set_history_depth (uint32_t d)
3514 _history.set_depth (d);
3518 Session::load_diskstreams_2X (XMLNode const & node, int)
3521 XMLNodeConstIterator citer;
3523 clist = node.children();
3525 for (citer = clist.begin(); citer != clist.end(); ++citer) {
3528 /* diskstreams added automatically by DiskstreamCreated handler */
3529 if ((*citer)->name() == "AudioDiskstream" || (*citer)->name() == "DiskStream") {
3530 boost::shared_ptr<AudioDiskstream> dsp (new AudioDiskstream (*this, **citer));
3531 _diskstreams_2X.push_back (dsp);
3533 error << _("Session: unknown diskstream type in XML") << endmsg;
3537 catch (failed_constructor& err) {
3538 error << _("Session: could not load diskstream via XML state") << endmsg;
3546 /** Connect things to the MMC object */
3548 Session::setup_midi_machine_control ()
3550 _mmc = new MIDI::MachineControl;
3551 _mmc->set_ports (_midi_ports->mmc_input_port(), _midi_ports->mmc_output_port());
3553 _mmc->Play.connect_same_thread (*this, boost::bind (&Session::mmc_deferred_play, this, _1));
3554 _mmc->DeferredPlay.connect_same_thread (*this, boost::bind (&Session::mmc_deferred_play, this, _1));
3555 _mmc->Stop.connect_same_thread (*this, boost::bind (&Session::mmc_stop, this, _1));
3556 _mmc->FastForward.connect_same_thread (*this, boost::bind (&Session::mmc_fast_forward, this, _1));
3557 _mmc->Rewind.connect_same_thread (*this, boost::bind (&Session::mmc_rewind, this, _1));
3558 _mmc->Pause.connect_same_thread (*this, boost::bind (&Session::mmc_pause, this, _1));
3559 _mmc->RecordPause.connect_same_thread (*this, boost::bind (&Session::mmc_record_pause, this, _1));
3560 _mmc->RecordStrobe.connect_same_thread (*this, boost::bind (&Session::mmc_record_strobe, this, _1));
3561 _mmc->RecordExit.connect_same_thread (*this, boost::bind (&Session::mmc_record_exit, this, _1));
3562 _mmc->Locate.connect_same_thread (*this, boost::bind (&Session::mmc_locate, this, _1, _2));
3563 _mmc->Step.connect_same_thread (*this, boost::bind (&Session::mmc_step, this, _1, _2));
3564 _mmc->Shuttle.connect_same_thread (*this, boost::bind (&Session::mmc_shuttle, this, _1, _2, _3));
3565 _mmc->TrackRecordStatusChange.connect_same_thread (*this, boost::bind (&Session::mmc_record_enable, this, _1, _2, _3));
3567 /* also handle MIDI SPP because its so common */
3569 _mmc->SPPStart.connect_same_thread (*this, boost::bind (&Session::spp_start, this));
3570 _mmc->SPPContinue.connect_same_thread (*this, boost::bind (&Session::spp_continue, this));
3571 _mmc->SPPStop.connect_same_thread (*this, boost::bind (&Session::spp_stop, this));
3574 boost::shared_ptr<Controllable>
3575 Session::solo_cut_control() const
3577 /* the solo cut control is a bit of an anomaly, at least as of Febrary 2011. There are no other
3578 controls in Ardour that currently get presented to the user in the GUI that require
3579 access as a Controllable and are also NOT owned by some SessionObject (e.g. Route, or MonitorProcessor).
3581 its actually an RCConfiguration parameter, so we use a ProxyControllable to wrap
3582 it up as a Controllable. Changes to the Controllable will just map back to the RCConfiguration
3586 return _solo_cut_control;
3590 Session::rename (const std::string& new_name)
3592 string legal_name = legalize_for_path (new_name);
3598 string const old_sources_root = _session_dir->sources_root();
3600 #define RENAME ::rename
3605 * interchange subdirectory
3609 * Backup files are left unchanged and not renamed.
3612 /* pass one: not 100% safe check that the new directory names don't
3616 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
3621 /* this is a stupid hack because Glib::path_get_dirname() is
3622 * lexical-only, and so passing it /a/b/c/ gives a different
3623 * result than passing it /a/b/c ...
3626 if (oldstr[oldstr.length()-1] == G_DIR_SEPARATOR) {
3627 oldstr = oldstr.substr (0, oldstr.length() - 1);
3630 string base = Glib::path_get_dirname (oldstr);
3631 string p = Glib::path_get_basename (oldstr);
3633 newstr = Glib::build_filename (base, legal_name);
3635 if (Glib::file_test (newstr, Glib::FILE_TEST_EXISTS)) {
3642 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
3647 /* this is a stupid hack because Glib::path_get_dirname() is
3648 * lexical-only, and so passing it /a/b/c/ gives a different
3649 * result than passing it /a/b/c ...
3652 if (oldstr[oldstr.length()-1] == G_DIR_SEPARATOR) {
3653 oldstr = oldstr.substr (0, oldstr.length() - 1);
3656 string base = Glib::path_get_dirname (oldstr);
3657 string p = Glib::path_get_basename (oldstr);
3659 newstr = Glib::build_filename (base, legal_name);
3661 cerr << "Rename " << oldstr << " => " << newstr << endl;
3663 if (RENAME (oldstr.c_str(), newstr.c_str()) != 0) {
3668 (*_session_dir) = newstr;
3673 /* directory below interchange */
3675 v.push_back (newstr);
3676 v.push_back (interchange_dir_name);
3679 oldstr = Glib::build_filename (v);
3682 v.push_back (newstr);
3683 v.push_back (interchange_dir_name);
3684 v.push_back (legal_name);
3686 newstr = Glib::build_filename (v);
3688 cerr << "Rename " << oldstr << " => " << newstr << endl;
3690 if (RENAME (oldstr.c_str(), newstr.c_str()) != 0) {
3697 oldstr = Glib::build_filename (newpath, _current_snapshot_name) + statefile_suffix;
3698 newstr= Glib::build_filename (newpath, legal_name) + statefile_suffix;
3700 cerr << "Rename " << oldstr << " => " << newstr << endl;
3702 if (RENAME (oldstr.c_str(), newstr.c_str()) != 0) {
3709 oldstr = Glib::build_filename (newpath, _current_snapshot_name) + history_suffix;
3711 if (Glib::file_test (oldstr, Glib::FILE_TEST_EXISTS)) {
3712 newstr = Glib::build_filename (newpath, legal_name) + history_suffix;
3714 cerr << "Rename " << oldstr << " => " << newstr << endl;
3716 if (RENAME (oldstr.c_str(), newstr.c_str()) != 0) {
3721 /* update file source paths */
3723 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ++i) {
3724 boost::shared_ptr<FileSource> fs = boost::dynamic_pointer_cast<FileSource> (i->second);
3726 string p = fs->path ();
3727 boost::replace_all (p, old_sources_root, _session_dir->sources_root());
3732 /* remove old name from recent sessions */
3734 remove_recent_sessions (_path);
3737 _current_snapshot_name = new_name;
3742 /* save state again to get everything just right */
3744 save_state (_current_snapshot_name);
3747 /* add to recent sessions */
3749 store_recent_sessions (new_name, _path);