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 Port::set_connecting_blocked (false);
313 DirtyChanged (); /* EMIT SIGNAL */
317 } else if (state_was_pending) {
319 remove_pending_capture_state ();
320 state_was_pending = false;
323 BootMessage (_("Session loading complete"));
329 Session::raid_path () const
331 SearchPath raid_search_path;
333 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
334 raid_search_path += (*i).path;
337 return raid_search_path.to_string ();
341 Session::setup_raid_path (string path)
350 session_dirs.clear ();
352 SearchPath search_path(path);
353 SearchPath sound_search_path;
354 SearchPath midi_search_path;
356 for (SearchPath::const_iterator i = search_path.begin(); i != search_path.end(); ++i) {
358 sp.blocks = 0; // not needed
359 session_dirs.push_back (sp);
361 SessionDirectory sdir(sp.path);
363 sound_search_path += sdir.sound_path ();
364 midi_search_path += sdir.midi_path ();
367 // reset the round-robin soundfile path thingie
368 last_rr_session_dir = session_dirs.begin();
372 Session::path_is_within_session (const std::string& path)
374 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
375 if (PBD::path_is_within (i->path, path)) {
383 Session::ensure_subdirs ()
387 dir = session_directory().peak_path();
389 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
390 error << string_compose(_("Session: cannot create session peakfile folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
394 dir = session_directory().sound_path();
396 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
397 error << string_compose(_("Session: cannot create session sounds dir \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
401 dir = session_directory().midi_path();
403 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
404 error << string_compose(_("Session: cannot create session midi dir \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
408 dir = session_directory().dead_path();
410 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
411 error << string_compose(_("Session: cannot create session dead sounds folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
415 dir = session_directory().export_path();
417 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
418 error << string_compose(_("Session: cannot create session export folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
422 dir = analysis_dir ();
424 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
425 error << string_compose(_("Session: cannot create session analysis folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
429 dir = plugins_dir ();
431 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
432 error << string_compose(_("Session: cannot create session plugins folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
436 dir = externals_dir ();
438 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
439 error << string_compose(_("Session: cannot create session externals folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
446 /** @param session_template directory containing session template, or empty.
447 * Caller must not hold process lock.
450 Session::create (const string& session_template, BusProfile* bus_profile)
452 if (g_mkdir_with_parents (_path.c_str(), 0755) < 0) {
453 error << string_compose(_("Session: cannot create session folder \"%1\" (%2)"), _path, strerror (errno)) << endmsg;
457 if (ensure_subdirs ()) {
461 _writable = exists_and_writable (_path);
463 if (!session_template.empty()) {
464 std::string in_path = session_template_dir_to_file (session_template);
466 ifstream in(in_path.c_str());
469 string out_path = _path;
471 out_path += statefile_suffix;
473 ofstream out(out_path.c_str());
479 /* Copy plugin state files from template to new session */
480 std::string template_plugins = Glib::build_filename (session_template, X_("plugins"));
481 copy_files (template_plugins, plugins_dir ());
486 error << string_compose (_("Could not open %1 for writing session template"), out_path)
492 error << string_compose (_("Could not open session template %1 for reading"), in_path)
499 /* set initial start + end point */
501 _state_of_the_state = Clean;
503 /* set up Master Out and Control Out if necessary */
508 ChanCount count(DataType::AUDIO, bus_profile->master_out_channels);
510 if (bus_profile->master_out_channels) {
511 boost::shared_ptr<Route> r (new Route (*this, _("master"), Route::MasterOut, DataType::AUDIO));
515 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
516 // boost_debug_shared_ptr_mark_interesting (r.get(), "Route");
519 Glib::Threads::Mutex::Lock lm (AudioEngine::instance()->process_lock ());
520 r->input()->ensure_io (count, false, this);
521 r->output()->ensure_io (count, false, this);
527 /* prohibit auto-connect to master, because there isn't one */
528 bus_profile->output_ac = AutoConnectOption (bus_profile->output_ac & ~AutoConnectMaster);
532 add_routes (rl, false, false, false);
535 /* this allows the user to override settings with an environment variable.
538 if (no_auto_connect()) {
539 bus_profile->input_ac = AutoConnectOption (0);
540 bus_profile->output_ac = AutoConnectOption (0);
543 Config->set_input_auto_connect (bus_profile->input_ac);
544 Config->set_output_auto_connect (bus_profile->output_ac);
547 if (Config->get_use_monitor_bus() && bus_profile) {
548 add_monitor_section ();
555 Session::maybe_write_autosave()
557 if (dirty() && record_status() != Recording) {
558 save_state("", true);
563 Session::remove_pending_capture_state ()
565 std::string pending_state_file_path(_session_dir->root_path());
567 pending_state_file_path = Glib::build_filename (pending_state_file_path, legalize_for_path (_current_snapshot_name) + pending_suffix);
569 if (!Glib::file_test (pending_state_file_path, Glib::FILE_TEST_EXISTS)) return;
571 if (g_remove (pending_state_file_path.c_str()) != 0) {
572 error << string_compose(_("Could not remove pending capture state at path \"%1\" (%2)"),
573 pending_state_file_path, g_strerror (errno)) << endmsg;
577 /** Rename a state file.
578 * @param old_name Old snapshot name.
579 * @param new_name New snapshot name.
582 Session::rename_state (string old_name, string new_name)
584 if (old_name == _current_snapshot_name || old_name == _name) {
585 /* refuse to rename the current snapshot or the "main" one */
589 const string old_xml_filename = legalize_for_path (old_name) + statefile_suffix;
590 const string new_xml_filename = legalize_for_path (new_name) + statefile_suffix;
592 const std::string old_xml_path(Glib::build_filename (_session_dir->root_path(), old_xml_filename));
593 const std::string new_xml_path(Glib::build_filename (_session_dir->root_path(), new_xml_filename));
595 if (::g_rename (old_xml_path.c_str(), new_xml_path.c_str()) != 0) {
596 error << string_compose(_("could not rename snapshot %1 to %2 (%3)"),
597 old_name, new_name, g_strerror(errno)) << endmsg;
601 /** Remove a state file.
602 * @param snapshot_name Snapshot name.
605 Session::remove_state (string snapshot_name)
607 if (!_writable || snapshot_name == _current_snapshot_name || snapshot_name == _name) {
608 // refuse to remove the current snapshot or the "main" one
612 std::string xml_path(_session_dir->root_path());
614 xml_path = Glib::build_filename (xml_path, legalize_for_path (snapshot_name) + statefile_suffix);
616 if (!create_backup_file (xml_path)) {
617 // don't remove it if a backup can't be made
618 // create_backup_file will log the error.
623 if (g_remove (xml_path.c_str()) != 0) {
624 error << string_compose(_("Could not remove session file at path \"%1\" (%2)"),
625 xml_path, g_strerror (errno)) << endmsg;
629 /** @param snapshot_name Name to save under, without .ardour / .pending prefix */
631 Session::save_state (string snapshot_name, bool pending, bool switch_to_snapshot)
634 std::string xml_path(_session_dir->root_path());
636 if (!_writable || (_state_of_the_state & CannotSave)) {
640 if (!_engine.connected ()) {
641 error << string_compose (_("the %1 audio engine is not connected and state saving would lose all I/O connections. Session not saved"),
647 /* tell sources we're saving first, in case they write out to a new file
648 * which should be saved with the state rather than the old one */
649 for (SourceMap::const_iterator i = sources.begin(); i != sources.end(); ++i) {
651 i->second->session_saved();
652 } catch (Evoral::SMF::FileError& e) {
653 error << string_compose ("Could not write to MIDI file %1; MIDI data not saved.", e.file_name ()) << endmsg;
657 SaveSession (); /* EMIT SIGNAL */
659 tree.set_root (&get_state());
661 if (snapshot_name.empty()) {
662 snapshot_name = _current_snapshot_name;
663 } else if (switch_to_snapshot) {
664 _current_snapshot_name = snapshot_name;
669 /* proper save: use statefile_suffix (.ardour in English) */
671 xml_path = Glib::build_filename (xml_path, legalize_for_path (snapshot_name) + statefile_suffix);
673 /* make a backup copy of the old file */
675 if (Glib::file_test (xml_path, Glib::FILE_TEST_EXISTS) && !create_backup_file (xml_path)) {
676 // create_backup_file will log the error
682 /* pending save: use pending_suffix (.pending in English) */
683 xml_path = Glib::build_filename (xml_path, legalize_for_path (snapshot_name) + pending_suffix);
686 std::string tmp_path(_session_dir->root_path());
687 tmp_path = Glib::build_filename (tmp_path, legalize_for_path (snapshot_name) + temp_suffix);
689 // cerr << "actually writing state to " << xml_path << endl;
691 if (!tree.write (tmp_path)) {
692 error << string_compose (_("state could not be saved to %1"), tmp_path) << endmsg;
693 if (g_remove (tmp_path.c_str()) != 0) {
694 error << string_compose(_("Could not remove temporary session file at path \"%1\" (%2)"),
695 tmp_path, g_strerror (errno)) << endmsg;
701 if (::rename (tmp_path.c_str(), xml_path.c_str()) != 0) {
702 error << string_compose (_("could not rename temporary session file %1 to %2"),
703 tmp_path, xml_path) << endmsg;
704 if (g_remove (tmp_path.c_str()) != 0) {
705 error << string_compose(_("Could not remove temporary session file at path \"%1\" (%2)"),
706 tmp_path, g_strerror (errno)) << endmsg;
714 save_history (snapshot_name);
716 bool was_dirty = dirty();
718 _state_of_the_state = StateOfTheState (_state_of_the_state & ~Dirty);
721 DirtyChanged (); /* EMIT SIGNAL */
724 StateSaved (snapshot_name); /* EMIT SIGNAL */
731 Session::restore_state (string snapshot_name)
733 if (load_state (snapshot_name) == 0) {
734 set_state (*state_tree->root(), Stateful::loading_state_version);
741 Session::load_state (string snapshot_name)
746 state_was_pending = false;
748 /* check for leftover pending state from a crashed capture attempt */
750 std::string xmlpath(_session_dir->root_path());
751 xmlpath = Glib::build_filename (xmlpath, legalize_for_path (snapshot_name) + pending_suffix);
753 if (Glib::file_test (xmlpath, Glib::FILE_TEST_EXISTS)) {
755 /* there is pending state from a crashed capture attempt */
757 boost::optional<int> r = AskAboutPendingState();
758 if (r.get_value_or (1)) {
759 state_was_pending = true;
763 if (!state_was_pending) {
764 xmlpath = Glib::build_filename (_session_dir->root_path(), snapshot_name);
767 if (!Glib::file_test (xmlpath, Glib::FILE_TEST_EXISTS)) {
768 xmlpath = Glib::build_filename (_session_dir->root_path(), legalize_for_path (snapshot_name) + statefile_suffix);
769 if (!Glib::file_test (xmlpath, Glib::FILE_TEST_EXISTS)) {
770 error << string_compose(_("%1: session file \"%2\" doesn't exist!"), _name, xmlpath) << endmsg;
775 state_tree = new XMLTree;
779 _writable = exists_and_writable (xmlpath);
781 if (!state_tree->read (xmlpath)) {
782 error << string_compose(_("Could not understand session file %1"), xmlpath) << endmsg;
788 XMLNode& root (*state_tree->root());
790 if (root.name() != X_("Session")) {
791 error << string_compose (_("Session file %1 is not a session"), xmlpath) << endmsg;
797 const XMLProperty* prop;
799 if ((prop = root.property ("version")) == 0) {
800 /* no version implies very old version of Ardour */
801 Stateful::loading_state_version = 1000;
803 if (prop->value().find ('.') != string::npos) {
804 /* old school version format */
805 if (prop->value()[0] == '2') {
806 Stateful::loading_state_version = 2000;
808 Stateful::loading_state_version = 3000;
811 Stateful::loading_state_version = atoi (prop->value());
815 if (Stateful::loading_state_version < CURRENT_SESSION_FILE_VERSION && _writable) {
817 std::string backup_path(_session_dir->root_path());
818 std::string backup_filename = string_compose ("%1-%2%3", legalize_for_path (snapshot_name), Stateful::loading_state_version, statefile_suffix);
819 backup_path = Glib::build_filename (backup_path, backup_filename);
821 // only create a backup for a given statefile version once
823 if (!Glib::file_test (backup_path, Glib::FILE_TEST_EXISTS)) {
825 VersionMismatch (xmlpath, backup_path);
827 if (!copy_file (xmlpath, backup_path)) {;
837 Session::load_options (const XMLNode& node)
839 LocaleGuard lg (X_("POSIX"));
840 config.set_variables (node);
851 Session::get_template()
853 /* if we don't disable rec-enable, diskstreams
854 will believe they need to store their capture
855 sources in their state node.
858 disable_record (false);
864 Session::state (bool full_state)
866 XMLNode* node = new XMLNode("Session");
870 snprintf(buf, sizeof(buf), "%d", CURRENT_SESSION_FILE_VERSION);
871 node->add_property("version", buf);
873 /* store configuration settings */
877 node->add_property ("name", _name);
878 snprintf (buf, sizeof (buf), "%" PRId64, _nominal_frame_rate);
879 node->add_property ("sample-rate", buf);
881 if (session_dirs.size() > 1) {
885 vector<space_and_path>::iterator i = session_dirs.begin();
886 vector<space_and_path>::iterator next;
888 ++i; /* skip the first one */
892 while (i != session_dirs.end()) {
896 if (next != session_dirs.end()) {
906 child = node->add_child ("Path");
907 child->add_content (p);
911 /* save the ID counter */
913 snprintf (buf, sizeof (buf), "%" PRIu64, ID::counter());
914 node->add_property ("id-counter", buf);
916 /* save the event ID counter */
918 snprintf (buf, sizeof (buf), "%d", Evoral::event_id_counter());
919 node->add_property ("event-counter", buf);
921 /* various options */
923 list<XMLNode*> midi_port_nodes = _midi_ports->get_midi_port_states();
924 if (!midi_port_nodes.empty()) {
925 XMLNode* midi_port_stuff = new XMLNode ("MIDIPorts");
926 for (list<XMLNode*>::const_iterator n = midi_port_nodes.begin(); n != midi_port_nodes.end(); ++n) {
927 midi_port_stuff->add_child_nocopy (**n);
929 node->add_child_nocopy (*midi_port_stuff);
932 node->add_child_nocopy (config.get_variables ());
934 node->add_child_nocopy (ARDOUR::SessionMetadata::Metadata()->get_state());
936 child = node->add_child ("Sources");
939 Glib::Threads::Mutex::Lock sl (source_lock);
941 for (SourceMap::iterator siter = sources.begin(); siter != sources.end(); ++siter) {
943 /* Don't save information about non-file Sources, or
944 * about non-destructive file sources that are empty
945 * and unused by any regions.
948 boost::shared_ptr<FileSource> fs;
950 if ((fs = boost::dynamic_pointer_cast<FileSource> (siter->second)) != 0) {
952 if (!fs->destructive()) {
953 if (fs->empty() && !fs->used()) {
958 child->add_child_nocopy (siter->second->get_state());
963 child = node->add_child ("Regions");
966 Glib::Threads::Mutex::Lock rl (region_lock);
967 const RegionFactory::RegionMap& region_map (RegionFactory::all_regions());
968 for (RegionFactory::RegionMap::const_iterator i = region_map.begin(); i != region_map.end(); ++i) {
969 boost::shared_ptr<Region> r = i->second;
970 /* only store regions not attached to playlists */
971 if (r->playlist() == 0) {
972 if (boost::dynamic_pointer_cast<AudioRegion>(r)) {
973 child->add_child_nocopy ((boost::dynamic_pointer_cast<AudioRegion>(r))->get_basic_state ());
975 child->add_child_nocopy (r->get_state ());
980 RegionFactory::CompoundAssociations& cassocs (RegionFactory::compound_associations());
982 if (!cassocs.empty()) {
983 XMLNode* ca = node->add_child (X_("CompoundAssociations"));
985 for (RegionFactory::CompoundAssociations::iterator i = cassocs.begin(); i != cassocs.end(); ++i) {
987 XMLNode* can = new XMLNode (X_("CompoundAssociation"));
988 i->first->id().print (buf, sizeof (buf));
989 can->add_property (X_("copy"), buf);
990 i->second->id().print (buf, sizeof (buf));
991 can->add_property (X_("original"), buf);
992 ca->add_child_nocopy (*can);
998 node->add_child_nocopy (_locations->get_state());
1000 // for a template, just create a new Locations, populate it
1001 // with the default start and end, and get the state for that.
1002 Locations loc (*this);
1003 Location* range = new Location (*this, 0, 0, _("session"), Location::IsSessionRange);
1004 range->set (max_framepos, 0);
1006 node->add_child_nocopy (loc.get_state());
1009 child = node->add_child ("Bundles");
1011 boost::shared_ptr<BundleList> bundles = _bundles.reader ();
1012 for (BundleList::iterator i = bundles->begin(); i != bundles->end(); ++i) {
1013 boost::shared_ptr<UserBundle> b = boost::dynamic_pointer_cast<UserBundle> (*i);
1015 child->add_child_nocopy (b->get_state());
1020 child = node->add_child ("Routes");
1022 boost::shared_ptr<RouteList> r = routes.reader ();
1024 RoutePublicOrderSorter cmp;
1025 RouteList public_order (*r);
1026 public_order.sort (cmp);
1028 /* the sort should have put control outs first */
1031 assert (_monitor_out == public_order.front());
1034 for (RouteList::iterator i = public_order.begin(); i != public_order.end(); ++i) {
1035 if (!(*i)->is_auditioner()) {
1037 child->add_child_nocopy ((*i)->get_state());
1039 child->add_child_nocopy ((*i)->get_template());
1045 playlists->add_state (node, full_state);
1047 child = node->add_child ("RouteGroups");
1048 for (list<RouteGroup *>::iterator i = _route_groups.begin(); i != _route_groups.end(); ++i) {
1049 child->add_child_nocopy ((*i)->get_state());
1053 XMLNode* gain_child = node->add_child ("Click");
1054 gain_child->add_child_nocopy (_click_io->state (full_state));
1055 gain_child->add_child_nocopy (_click_gain->state (full_state));
1059 XMLNode* ltc_input_child = node->add_child ("LTC-In");
1060 ltc_input_child->add_child_nocopy (_ltc_input->state (full_state));
1064 XMLNode* ltc_output_child = node->add_child ("LTC-Out");
1065 ltc_output_child->add_child_nocopy (_ltc_output->state (full_state));
1068 node->add_child_nocopy (_speakers->get_state());
1069 node->add_child_nocopy (_tempo_map->get_state());
1070 node->add_child_nocopy (get_control_protocol_state());
1073 node->add_child_copy (*_extra_xml);
1080 Session::get_control_protocol_state ()
1082 ControlProtocolManager& cpm (ControlProtocolManager::instance());
1083 return cpm.get_state();
1087 Session::set_state (const XMLNode& node, int version)
1091 const XMLProperty* prop;
1094 _state_of_the_state = StateOfTheState (_state_of_the_state|CannotSave);
1096 if (node.name() != X_("Session")) {
1097 fatal << _("programming error: Session: incorrect XML node sent to set_state()") << endmsg;
1101 if ((prop = node.property ("name")) != 0) {
1102 _name = prop->value ();
1105 if ((prop = node.property (X_("sample-rate"))) != 0) {
1107 _nominal_frame_rate = atoi (prop->value());
1109 if (_nominal_frame_rate != _current_frame_rate) {
1110 boost::optional<int> r = AskAboutSampleRateMismatch (_nominal_frame_rate, _current_frame_rate);
1111 if (r.get_value_or (0)) {
1117 setup_raid_path(_session_dir->root_path());
1119 if ((prop = node.property (X_("id-counter"))) != 0) {
1121 sscanf (prop->value().c_str(), "%" PRIu64, &x);
1122 ID::init_counter (x);
1124 /* old sessions used a timebased counter, so fake
1125 the startup ID counter based on a standard
1130 ID::init_counter (now);
1133 if ((prop = node.property (X_("event-counter"))) != 0) {
1134 Evoral::init_event_id_counter (atoi (prop->value()));
1138 if ((child = find_named_node (node, "MIDIPorts")) != 0) {
1139 _midi_ports->set_midi_port_states (child->children());
1142 IO::disable_connecting ();
1144 Stateful::save_extra_xml (node);
1146 if (((child = find_named_node (node, "Options")) != 0)) { /* old style */
1147 load_options (*child);
1148 } else if ((child = find_named_node (node, "Config")) != 0) { /* new style */
1149 load_options (*child);
1151 error << _("Session: XML state has no options section") << endmsg;
1154 if (version >= 3000) {
1155 if ((child = find_named_node (node, "Metadata")) == 0) {
1156 warning << _("Session: XML state has no metadata section") << endmsg;
1157 } else if ( ARDOUR::SessionMetadata::Metadata()->set_state (*child, version) ) {
1162 if ((child = find_named_node (node, X_("Speakers"))) != 0) {
1163 _speakers->set_state (*child, version);
1166 if ((child = find_named_node (node, "Sources")) == 0) {
1167 error << _("Session: XML state has no sources section") << endmsg;
1169 } else if (load_sources (*child)) {
1173 if ((child = find_named_node (node, "TempoMap")) == 0) {
1174 error << _("Session: XML state has no Tempo Map section") << endmsg;
1176 } else if (_tempo_map->set_state (*child, version)) {
1180 if ((child = find_named_node (node, "Locations")) == 0) {
1181 error << _("Session: XML state has no locations section") << endmsg;
1183 } else if (_locations->set_state (*child, version)) {
1189 if ((location = _locations->auto_loop_location()) != 0) {
1190 set_auto_loop_location (location);
1193 if ((location = _locations->auto_punch_location()) != 0) {
1194 set_auto_punch_location (location);
1197 if ((location = _locations->session_range_location()) != 0) {
1198 delete _session_range_location;
1199 _session_range_location = location;
1202 if (_session_range_location) {
1203 AudioFileSource::set_header_position_offset (_session_range_location->start());
1206 if ((child = find_named_node (node, "Regions")) == 0) {
1207 error << _("Session: XML state has no Regions section") << endmsg;
1209 } else if (load_regions (*child)) {
1213 if ((child = find_named_node (node, "Playlists")) == 0) {
1214 error << _("Session: XML state has no playlists section") << endmsg;
1216 } else if (playlists->load (*this, *child)) {
1220 if ((child = find_named_node (node, "UnusedPlaylists")) == 0) {
1222 } else if (playlists->load_unused (*this, *child)) {
1226 if ((child = find_named_node (node, "CompoundAssociations")) != 0) {
1227 if (load_compounds (*child)) {
1232 if (version >= 3000) {
1233 if ((child = find_named_node (node, "Bundles")) == 0) {
1234 warning << _("Session: XML state has no bundles section") << endmsg;
1237 /* We can't load Bundles yet as they need to be able
1238 to convert from port names to Port objects, which can't happen until
1240 _bundle_xml_node = new XMLNode (*child);
1244 if (version < 3000) {
1245 if ((child = find_named_node (node, X_("DiskStreams"))) == 0) {
1246 error << _("Session: XML state has no diskstreams section") << endmsg;
1248 } else if (load_diskstreams_2X (*child, version)) {
1253 if ((child = find_named_node (node, "Routes")) == 0) {
1254 error << _("Session: XML state has no routes section") << endmsg;
1256 } else if (load_routes (*child, version)) {
1260 /* our diskstreams list is no longer needed as they are now all owned by their Route */
1261 _diskstreams_2X.clear ();
1263 if (version >= 3000) {
1265 if ((child = find_named_node (node, "RouteGroups")) == 0) {
1266 error << _("Session: XML state has no route groups section") << endmsg;
1268 } else if (load_route_groups (*child, version)) {
1272 } else if (version < 3000) {
1274 if ((child = find_named_node (node, "EditGroups")) == 0) {
1275 error << _("Session: XML state has no edit groups section") << endmsg;
1277 } else if (load_route_groups (*child, version)) {
1281 if ((child = find_named_node (node, "MixGroups")) == 0) {
1282 error << _("Session: XML state has no mix groups section") << endmsg;
1284 } else if (load_route_groups (*child, version)) {
1289 if ((child = find_named_node (node, "Click")) == 0) {
1290 warning << _("Session: XML state has no click section") << endmsg;
1291 } else if (_click_io) {
1292 const XMLNodeList& children (child->children());
1293 XMLNodeList::const_iterator i = children.begin();
1294 _click_io->set_state (**i, version);
1296 if (i != children.end()) {
1297 _click_gain->set_state (**i, version);
1301 if ((child = find_named_node (node, ControlProtocolManager::state_node_name)) != 0) {
1302 ControlProtocolManager::instance().set_state (*child, version);
1305 update_have_rec_enabled_track ();
1307 /* here beginneth the second phase ... */
1309 StateReady (); /* EMIT SIGNAL */
1318 Session::load_routes (const XMLNode& node, int version)
1321 XMLNodeConstIterator niter;
1322 RouteList new_routes;
1324 nlist = node.children();
1328 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1330 boost::shared_ptr<Route> route;
1331 if (version < 3000) {
1332 route = XMLRouteFactory_2X (**niter, version);
1334 route = XMLRouteFactory (**niter, version);
1338 error << _("Session: cannot create Route from XML description.") << endmsg;
1342 BootMessage (string_compose (_("Loaded track/bus %1"), route->name()));
1344 new_routes.push_back (route);
1347 add_routes (new_routes, false, false, false);
1352 boost::shared_ptr<Route>
1353 Session::XMLRouteFactory (const XMLNode& node, int version)
1355 boost::shared_ptr<Route> ret;
1357 if (node.name() != "Route") {
1361 XMLNode* ds_child = find_named_node (node, X_("Diskstream"));
1363 DataType type = DataType::AUDIO;
1364 const XMLProperty* prop = node.property("default-type");
1367 type = DataType (prop->value());
1370 assert (type != DataType::NIL);
1374 boost::shared_ptr<Track> track;
1376 if (type == DataType::AUDIO) {
1377 track.reset (new AudioTrack (*this, X_("toBeResetFroXML")));
1379 track.reset (new MidiTrack (*this, X_("toBeResetFroXML")));
1382 if (track->init()) {
1386 if (track->set_state (node, version)) {
1390 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
1391 // boost_debug_shared_ptr_mark_interesting (track.get(), "Track");
1396 boost::shared_ptr<Route> r (new Route (*this, X_("toBeResetFroXML")));
1398 if (r->init () == 0 && r->set_state (node, version) == 0) {
1399 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
1400 // boost_debug_shared_ptr_mark_interesting (r.get(), "Route");
1409 boost::shared_ptr<Route>
1410 Session::XMLRouteFactory_2X (const XMLNode& node, int version)
1412 boost::shared_ptr<Route> ret;
1414 if (node.name() != "Route") {
1418 XMLProperty const * ds_prop = node.property (X_("diskstream-id"));
1420 ds_prop = node.property (X_("diskstream"));
1423 DataType type = DataType::AUDIO;
1424 const XMLProperty* prop = node.property("default-type");
1427 type = DataType (prop->value());
1430 assert (type != DataType::NIL);
1434 list<boost::shared_ptr<Diskstream> >::iterator i = _diskstreams_2X.begin ();
1435 while (i != _diskstreams_2X.end() && (*i)->id() != ds_prop->value()) {
1439 if (i == _diskstreams_2X.end()) {
1440 error << _("Could not find diskstream for route") << endmsg;
1441 return boost::shared_ptr<Route> ();
1444 boost::shared_ptr<Track> track;
1446 if (type == DataType::AUDIO) {
1447 track.reset (new AudioTrack (*this, X_("toBeResetFroXML")));
1449 track.reset (new MidiTrack (*this, X_("toBeResetFroXML")));
1452 if (track->init()) {
1456 if (track->set_state (node, version)) {
1460 track->set_diskstream (*i);
1462 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
1463 // boost_debug_shared_ptr_mark_interesting (track.get(), "Track");
1468 boost::shared_ptr<Route> r (new Route (*this, X_("toBeResetFroXML")));
1470 if (r->init () == 0 && r->set_state (node, version) == 0) {
1471 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
1472 // boost_debug_shared_ptr_mark_interesting (r.get(), "Route");
1482 Session::load_regions (const XMLNode& node)
1485 XMLNodeConstIterator niter;
1486 boost::shared_ptr<Region> region;
1488 nlist = node.children();
1492 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1493 if ((region = XMLRegionFactory (**niter, false)) == 0) {
1494 error << _("Session: cannot create Region from XML description.");
1495 const XMLProperty *name = (**niter).property("name");
1498 error << " " << string_compose (_("Can not load state for region '%1'"), name->value());
1509 Session::load_compounds (const XMLNode& node)
1511 XMLNodeList calist = node.children();
1512 XMLNodeConstIterator caiter;
1513 XMLProperty *caprop;
1515 for (caiter = calist.begin(); caiter != calist.end(); ++caiter) {
1516 XMLNode* ca = *caiter;
1520 if ((caprop = ca->property (X_("original"))) == 0) {
1523 orig_id = caprop->value();
1525 if ((caprop = ca->property (X_("copy"))) == 0) {
1528 copy_id = caprop->value();
1530 boost::shared_ptr<Region> orig = RegionFactory::region_by_id (orig_id);
1531 boost::shared_ptr<Region> copy = RegionFactory::region_by_id (copy_id);
1533 if (!orig || !copy) {
1534 warning << string_compose (_("Regions in compound description not found (ID's %1 and %2): ignored"),
1540 RegionFactory::add_compound_association (orig, copy);
1547 Session::load_nested_sources (const XMLNode& node)
1550 XMLNodeConstIterator niter;
1552 nlist = node.children();
1554 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1555 if ((*niter)->name() == "Source") {
1557 /* it may already exist, so don't recreate it unnecessarily
1560 XMLProperty* prop = (*niter)->property (X_("id"));
1562 error << _("Nested source has no ID info in session file! (ignored)") << endmsg;
1566 ID source_id (prop->value());
1568 if (!source_by_id (source_id)) {
1571 SourceFactory::create (*this, **niter, true);
1573 catch (failed_constructor& err) {
1574 error << string_compose (_("Cannot reconstruct nested source for region %1"), name()) << endmsg;
1581 boost::shared_ptr<Region>
1582 Session::XMLRegionFactory (const XMLNode& node, bool full)
1584 const XMLProperty* type = node.property("type");
1588 const XMLNodeList& nlist = node.children();
1590 for (XMLNodeConstIterator niter = nlist.begin(); niter != nlist.end(); ++niter) {
1591 XMLNode *child = (*niter);
1592 if (child->name() == "NestedSource") {
1593 load_nested_sources (*child);
1597 if (!type || type->value() == "audio") {
1598 return boost::shared_ptr<Region>(XMLAudioRegionFactory (node, full));
1599 } else if (type->value() == "midi") {
1600 return boost::shared_ptr<Region>(XMLMidiRegionFactory (node, full));
1603 } catch (failed_constructor& err) {
1604 return boost::shared_ptr<Region> ();
1607 return boost::shared_ptr<Region> ();
1610 boost::shared_ptr<AudioRegion>
1611 Session::XMLAudioRegionFactory (const XMLNode& node, bool /*full*/)
1613 const XMLProperty* prop;
1614 boost::shared_ptr<Source> source;
1615 boost::shared_ptr<AudioSource> as;
1617 SourceList master_sources;
1618 uint32_t nchans = 1;
1621 if (node.name() != X_("Region")) {
1622 return boost::shared_ptr<AudioRegion>();
1625 if ((prop = node.property (X_("channels"))) != 0) {
1626 nchans = atoi (prop->value().c_str());
1629 if ((prop = node.property ("name")) == 0) {
1630 cerr << "no name for this region\n";
1634 if ((prop = node.property (X_("source-0"))) == 0) {
1635 if ((prop = node.property ("source")) == 0) {
1636 error << _("Session: XMLNode describing a AudioRegion is incomplete (no source)") << endmsg;
1637 return boost::shared_ptr<AudioRegion>();
1641 PBD::ID s_id (prop->value());
1643 if ((source = source_by_id (s_id)) == 0) {
1644 error << string_compose(_("Session: XMLNode describing a AudioRegion references an unknown source id =%1"), s_id) << endmsg;
1645 return boost::shared_ptr<AudioRegion>();
1648 as = boost::dynamic_pointer_cast<AudioSource>(source);
1650 error << string_compose(_("Session: XMLNode describing a AudioRegion references a non-audio source id =%1"), s_id) << endmsg;
1651 return boost::shared_ptr<AudioRegion>();
1654 sources.push_back (as);
1656 /* pickup other channels */
1658 for (uint32_t n=1; n < nchans; ++n) {
1659 snprintf (buf, sizeof(buf), X_("source-%d"), n);
1660 if ((prop = node.property (buf)) != 0) {
1662 PBD::ID id2 (prop->value());
1664 if ((source = source_by_id (id2)) == 0) {
1665 error << string_compose(_("Session: XMLNode describing a AudioRegion references an unknown source id =%1"), id2) << endmsg;
1666 return boost::shared_ptr<AudioRegion>();
1669 as = boost::dynamic_pointer_cast<AudioSource>(source);
1671 error << string_compose(_("Session: XMLNode describing a AudioRegion references a non-audio source id =%1"), id2) << endmsg;
1672 return boost::shared_ptr<AudioRegion>();
1674 sources.push_back (as);
1678 for (uint32_t n = 0; n < nchans; ++n) {
1679 snprintf (buf, sizeof(buf), X_("master-source-%d"), n);
1680 if ((prop = node.property (buf)) != 0) {
1682 PBD::ID id2 (prop->value());
1684 if ((source = source_by_id (id2)) == 0) {
1685 error << string_compose(_("Session: XMLNode describing a AudioRegion references an unknown source id =%1"), id2) << endmsg;
1686 return boost::shared_ptr<AudioRegion>();
1689 as = boost::dynamic_pointer_cast<AudioSource>(source);
1691 error << string_compose(_("Session: XMLNode describing a AudioRegion references a non-audio source id =%1"), id2) << endmsg;
1692 return boost::shared_ptr<AudioRegion>();
1694 master_sources.push_back (as);
1699 boost::shared_ptr<AudioRegion> region (boost::dynamic_pointer_cast<AudioRegion> (RegionFactory::create (sources, node)));
1701 /* a final detail: this is the one and only place that we know how long missing files are */
1703 if (region->whole_file()) {
1704 for (SourceList::iterator sx = sources.begin(); sx != sources.end(); ++sx) {
1705 boost::shared_ptr<SilentFileSource> sfp = boost::dynamic_pointer_cast<SilentFileSource> (*sx);
1707 sfp->set_length (region->length());
1712 if (!master_sources.empty()) {
1713 if (master_sources.size() != nchans) {
1714 error << _("Session: XMLNode describing an AudioRegion is missing some master sources; ignored") << endmsg;
1716 region->set_master_sources (master_sources);
1724 catch (failed_constructor& err) {
1725 return boost::shared_ptr<AudioRegion>();
1729 boost::shared_ptr<MidiRegion>
1730 Session::XMLMidiRegionFactory (const XMLNode& node, bool /*full*/)
1732 const XMLProperty* prop;
1733 boost::shared_ptr<Source> source;
1734 boost::shared_ptr<MidiSource> ms;
1737 if (node.name() != X_("Region")) {
1738 return boost::shared_ptr<MidiRegion>();
1741 if ((prop = node.property ("name")) == 0) {
1742 cerr << "no name for this region\n";
1746 if ((prop = node.property (X_("source-0"))) == 0) {
1747 if ((prop = node.property ("source")) == 0) {
1748 error << _("Session: XMLNode describing a MidiRegion is incomplete (no source)") << endmsg;
1749 return boost::shared_ptr<MidiRegion>();
1753 PBD::ID s_id (prop->value());
1755 if ((source = source_by_id (s_id)) == 0) {
1756 error << string_compose(_("Session: XMLNode describing a MidiRegion references an unknown source id =%1"), s_id) << endmsg;
1757 return boost::shared_ptr<MidiRegion>();
1760 ms = boost::dynamic_pointer_cast<MidiSource>(source);
1762 error << string_compose(_("Session: XMLNode describing a MidiRegion references a non-midi source id =%1"), s_id) << endmsg;
1763 return boost::shared_ptr<MidiRegion>();
1766 sources.push_back (ms);
1769 boost::shared_ptr<MidiRegion> region (boost::dynamic_pointer_cast<MidiRegion> (RegionFactory::create (sources, node)));
1770 /* a final detail: this is the one and only place that we know how long missing files are */
1772 if (region->whole_file()) {
1773 for (SourceList::iterator sx = sources.begin(); sx != sources.end(); ++sx) {
1774 boost::shared_ptr<SilentFileSource> sfp = boost::dynamic_pointer_cast<SilentFileSource> (*sx);
1776 sfp->set_length (region->length());
1784 catch (failed_constructor& err) {
1785 return boost::shared_ptr<MidiRegion>();
1790 Session::get_sources_as_xml ()
1793 XMLNode* node = new XMLNode (X_("Sources"));
1794 Glib::Threads::Mutex::Lock lm (source_lock);
1796 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ++i) {
1797 node->add_child_nocopy (i->second->get_state());
1804 Session::path_from_region_name (DataType type, string name, string identifier)
1806 char buf[PATH_MAX+1];
1808 SessionDirectory sdir(get_best_session_directory_for_new_source());
1809 std::string source_dir = ((type == DataType::AUDIO)
1810 ? sdir.sound_path() : sdir.midi_path());
1812 string ext = native_header_format_extension (config.get_native_file_header_format(), type);
1814 for (n = 0; n < 999999; ++n) {
1815 if (identifier.length()) {
1816 snprintf (buf, sizeof(buf), "%s%s%" PRIu32 "%s", name.c_str(),
1817 identifier.c_str(), n, ext.c_str());
1819 snprintf (buf, sizeof(buf), "%s-%" PRIu32 "%s", name.c_str(),
1823 std::string source_path = Glib::build_filename (source_dir, buf);
1825 if (!Glib::file_test (source_path, Glib::FILE_TEST_EXISTS)) {
1830 error << string_compose (_("cannot create new file from region name \"%1\" with ident = \"%2\": too many existing files with similar names"),
1839 Session::load_sources (const XMLNode& node)
1842 XMLNodeConstIterator niter;
1843 boost::shared_ptr<Source> source;
1845 nlist = node.children();
1849 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1852 if ((source = XMLSourceFactory (**niter)) == 0) {
1853 error << _("Session: cannot create Source from XML description.") << endmsg;
1856 } catch (MissingSource& err) {
1860 if (!no_questions_about_missing_files) {
1861 user_choice = MissingFile (this, err.path, err.type).get_value_or (-1);
1866 switch (user_choice) {
1868 /* user added a new search location, so try again */
1873 /* user asked to quit the entire session load
1878 no_questions_about_missing_files = true;
1882 no_questions_about_missing_files = true;
1887 warning << _("A sound file is missing. It will be replaced by silence.") << endmsg;
1888 source = SourceFactory::createSilent (*this, **niter, max_framecnt, _current_frame_rate);
1897 boost::shared_ptr<Source>
1898 Session::XMLSourceFactory (const XMLNode& node)
1900 if (node.name() != "Source") {
1901 return boost::shared_ptr<Source>();
1905 /* note: do peak building in another thread when loading session state */
1906 return SourceFactory::create (*this, node, true);
1909 catch (failed_constructor& err) {
1910 error << string_compose (_("Found a sound file that cannot be used by %1. Talk to the progammers."), PROGRAM_NAME) << endmsg;
1911 return boost::shared_ptr<Source>();
1916 Session::save_template (string template_name)
1920 if (_state_of_the_state & CannotSave) {
1924 std::string user_template_dir(user_template_directory());
1926 if (g_mkdir_with_parents (user_template_dir.c_str(), 0755) != 0) {
1927 error << string_compose(_("Could not create templates directory \"%1\" (%2)"),
1928 user_template_dir, g_strerror (errno)) << endmsg;
1932 tree.set_root (&get_template());
1934 std::string template_dir_path(user_template_dir);
1936 /* directory to put the template in */
1937 template_dir_path = Glib::build_filename (template_dir_path, template_name);
1939 if (Glib::file_test (template_dir_path, Glib::FILE_TEST_EXISTS)) {
1940 warning << string_compose(_("Template \"%1\" already exists - new version not created"),
1941 template_dir_path) << endmsg;
1945 if (g_mkdir_with_parents (template_dir_path.c_str(), 0755) != 0) {
1946 error << string_compose(_("Could not create directory for Session template\"%1\" (%2)"),
1947 template_dir_path, g_strerror (errno)) << endmsg;
1952 std::string template_file_path(template_dir_path);
1953 template_file_path = Glib::build_filename (template_file_path, template_name + template_suffix);
1955 if (!tree.write (template_file_path)) {
1956 error << _("template not saved") << endmsg;
1960 /* copy plugin state directory */
1962 std::string template_plugin_state_path(template_dir_path);
1963 template_plugin_state_path = Glib::build_filename (template_plugin_state_path, X_("plugins"));
1965 if (g_mkdir_with_parents (template_plugin_state_path.c_str(), 0755) != 0) {
1966 error << string_compose(_("Could not create directory for Session template plugin state\"%1\" (%2)"),
1967 template_plugin_state_path, g_strerror (errno)) << endmsg;
1971 copy_files (plugins_dir(), template_plugin_state_path);
1977 Session::refresh_disk_space ()
1979 #if __APPLE__ || (HAVE_SYS_VFS_H && HAVE_SYS_STATVFS_H)
1981 Glib::Threads::Mutex::Lock lm (space_lock);
1983 /* get freespace on every FS that is part of the session path */
1985 _total_free_4k_blocks = 0;
1986 _total_free_4k_blocks_uncertain = false;
1988 for (vector<space_and_path>::iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
1990 struct statfs statfsbuf;
1991 statfs (i->path.c_str(), &statfsbuf);
1993 double const scale = statfsbuf.f_bsize / 4096.0;
1995 /* See if this filesystem is read-only */
1996 struct statvfs statvfsbuf;
1997 statvfs (i->path.c_str(), &statvfsbuf);
1999 /* f_bavail can be 0 if it is undefined for whatever
2000 filesystem we are looking at; Samba shares mounted
2001 via GVFS are an example of this.
2003 if (statfsbuf.f_bavail == 0) {
2004 /* block count unknown */
2006 i->blocks_unknown = true;
2007 } else if (statvfsbuf.f_flag & ST_RDONLY) {
2008 /* read-only filesystem */
2010 i->blocks_unknown = false;
2012 /* read/write filesystem with known space */
2013 i->blocks = (uint32_t) floor (statfsbuf.f_bavail * scale);
2014 i->blocks_unknown = false;
2017 _total_free_4k_blocks += i->blocks;
2018 if (i->blocks_unknown) {
2019 _total_free_4k_blocks_uncertain = true;
2026 Session::get_best_session_directory_for_new_source ()
2028 vector<space_and_path>::iterator i;
2029 string result = _session_dir->root_path();
2031 /* handle common case without system calls */
2033 if (session_dirs.size() == 1) {
2037 /* OK, here's the algorithm we're following here:
2039 We want to select which directory to use for
2040 the next file source to be created. Ideally,
2041 we'd like to use a round-robin process so as to
2042 get maximum performance benefits from splitting
2043 the files across multiple disks.
2045 However, in situations without much diskspace, an
2046 RR approach may end up filling up a filesystem
2047 with new files while others still have space.
2048 Its therefore important to pay some attention to
2049 the freespace in the filesystem holding each
2050 directory as well. However, if we did that by
2051 itself, we'd keep creating new files in the file
2052 system with the most space until it was as full
2053 as all others, thus negating any performance
2054 benefits of this RAID-1 like approach.
2056 So, we use a user-configurable space threshold. If
2057 there are at least 2 filesystems with more than this
2058 much space available, we use RR selection between them.
2059 If not, then we pick the filesystem with the most space.
2061 This gets a good balance between the two
2065 refresh_disk_space ();
2067 int free_enough = 0;
2069 for (i = session_dirs.begin(); i != session_dirs.end(); ++i) {
2070 if ((*i).blocks * 4096 >= Config->get_disk_choice_space_threshold()) {
2075 if (free_enough >= 2) {
2076 /* use RR selection process, ensuring that the one
2080 i = last_rr_session_dir;
2083 if (++i == session_dirs.end()) {
2084 i = session_dirs.begin();
2087 if ((*i).blocks * 4096 >= Config->get_disk_choice_space_threshold()) {
2088 SessionDirectory sdir(i->path);
2089 if (sdir.create ()) {
2091 last_rr_session_dir = i;
2096 } while (i != last_rr_session_dir);
2100 /* pick FS with the most freespace (and that
2101 seems to actually work ...)
2104 vector<space_and_path> sorted;
2105 space_and_path_ascending_cmp cmp;
2107 sorted = session_dirs;
2108 sort (sorted.begin(), sorted.end(), cmp);
2110 for (i = sorted.begin(); i != sorted.end(); ++i) {
2111 SessionDirectory sdir(i->path);
2112 if (sdir.create ()) {
2114 last_rr_session_dir = i;
2124 Session::automation_dir () const
2126 return Glib::build_filename (_path, "automation");
2130 Session::analysis_dir () const
2132 return Glib::build_filename (_path, "analysis");
2136 Session::plugins_dir () const
2138 return Glib::build_filename (_path, "plugins");
2142 Session::externals_dir () const
2144 return Glib::build_filename (_path, "externals");
2148 Session::load_bundles (XMLNode const & node)
2150 XMLNodeList nlist = node.children();
2151 XMLNodeConstIterator niter;
2155 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2156 if ((*niter)->name() == "InputBundle") {
2157 add_bundle (boost::shared_ptr<UserBundle> (new UserBundle (**niter, true)));
2158 } else if ((*niter)->name() == "OutputBundle") {
2159 add_bundle (boost::shared_ptr<UserBundle> (new UserBundle (**niter, false)));
2161 error << string_compose(_("Unknown node \"%1\" found in Bundles list from session file"), (*niter)->name()) << endmsg;
2170 Session::load_route_groups (const XMLNode& node, int version)
2172 XMLNodeList nlist = node.children();
2173 XMLNodeConstIterator niter;
2177 if (version >= 3000) {
2179 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2180 if ((*niter)->name() == "RouteGroup") {
2181 RouteGroup* rg = new RouteGroup (*this, "");
2182 add_route_group (rg);
2183 rg->set_state (**niter, version);
2187 } else if (version < 3000) {
2189 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2190 if ((*niter)->name() == "EditGroup" || (*niter)->name() == "MixGroup") {
2191 RouteGroup* rg = new RouteGroup (*this, "");
2192 add_route_group (rg);
2193 rg->set_state (**niter, version);
2202 Session::auto_save()
2204 save_state (_current_snapshot_name);
2208 state_file_filter (const string &str, void */*arg*/)
2210 return (str.length() > strlen(statefile_suffix) &&
2211 str.find (statefile_suffix) == (str.length() - strlen (statefile_suffix)));
2215 bool operator()(const string* a, const string* b) {
2221 remove_end(string* state)
2223 string statename(*state);
2225 string::size_type start,end;
2226 if ((start = statename.find_last_of (G_DIR_SEPARATOR)) != string::npos) {
2227 statename = statename.substr (start+1);
2230 if ((end = statename.rfind(".ardour")) == string::npos) {
2231 end = statename.length();
2234 return new string(statename.substr (0, end));
2238 Session::possible_states (string path)
2240 PathScanner scanner;
2241 vector<string*>* states = scanner (path, state_file_filter, 0, false, false);
2243 transform(states->begin(), states->end(), states->begin(), remove_end);
2246 sort (states->begin(), states->end(), cmp);
2252 Session::possible_states () const
2254 return possible_states(_path);
2258 Session::add_route_group (RouteGroup* g)
2260 _route_groups.push_back (g);
2261 route_group_added (g); /* EMIT SIGNAL */
2263 g->RouteAdded.connect_same_thread (*this, boost::bind (&Session::route_added_to_route_group, this, _1, _2));
2264 g->RouteRemoved.connect_same_thread (*this, boost::bind (&Session::route_removed_from_route_group, this, _1, _2));
2265 g->PropertyChanged.connect_same_thread (*this, boost::bind (&Session::route_group_property_changed, this, g));
2271 Session::remove_route_group (RouteGroup& rg)
2273 list<RouteGroup*>::iterator i;
2275 if ((i = find (_route_groups.begin(), _route_groups.end(), &rg)) != _route_groups.end()) {
2276 _route_groups.erase (i);
2279 route_group_removed (); /* EMIT SIGNAL */
2283 /** Set a new order for our route groups, without adding or removing any.
2284 * @param groups Route group list in the new order.
2287 Session::reorder_route_groups (list<RouteGroup*> groups)
2289 _route_groups = groups;
2291 route_groups_reordered (); /* EMIT SIGNAL */
2297 Session::route_group_by_name (string name)
2299 list<RouteGroup *>::iterator i;
2301 for (i = _route_groups.begin(); i != _route_groups.end(); ++i) {
2302 if ((*i)->name() == name) {
2310 Session::all_route_group() const
2312 return *_all_route_group;
2316 Session::add_commands (vector<Command*> const & cmds)
2318 for (vector<Command*>::const_iterator i = cmds.begin(); i != cmds.end(); ++i) {
2324 Session::begin_reversible_command (const string& name)
2326 begin_reversible_command (g_quark_from_string (name.c_str ()));
2329 /** Begin a reversible command using a GQuark to identify it.
2330 * begin_reversible_command() and commit_reversible_command() calls may be nested,
2331 * but there must be as many begin...()s as there are commit...()s.
2334 Session::begin_reversible_command (GQuark q)
2336 /* If nested begin/commit pairs are used, we create just one UndoTransaction
2337 to hold all the commands that are committed. This keeps the order of
2338 commands correct in the history.
2341 if (_current_trans == 0) {
2342 /* start a new transaction */
2343 assert (_current_trans_quarks.empty ());
2344 _current_trans = new UndoTransaction();
2345 _current_trans->set_name (g_quark_to_string (q));
2348 _current_trans_quarks.push_front (q);
2352 Session::commit_reversible_command (Command *cmd)
2354 assert (_current_trans);
2355 assert (!_current_trans_quarks.empty ());
2360 _current_trans->add_command (cmd);
2363 _current_trans_quarks.pop_front ();
2365 if (!_current_trans_quarks.empty ()) {
2366 /* the transaction we're committing is not the top-level one */
2370 if (_current_trans->empty()) {
2371 /* no commands were added to the transaction, so just get rid of it */
2372 delete _current_trans;
2377 gettimeofday (&now, 0);
2378 _current_trans->set_timestamp (now);
2380 _history.add (_current_trans);
2385 accept_all_audio_files (const string& path, void */*arg*/)
2387 if (!Glib::file_test (path, Glib::FILE_TEST_IS_REGULAR)) {
2391 if (!AudioFileSource::safe_audio_file_extension (path)) {
2399 accept_all_midi_files (const string& path, void */*arg*/)
2401 if (!Glib::file_test (path, Glib::FILE_TEST_IS_REGULAR)) {
2405 return ((path.length() > 4 && path.find (".mid") != (path.length() - 4)) ||
2406 (path.length() > 4 && path.find (".smf") != (path.length() - 4)) ||
2407 (path.length() > 5 && path.find (".midi") != (path.length() - 5)));
2411 accept_all_state_files (const string& path, void */*arg*/)
2413 if (!Glib::file_test (path, Glib::FILE_TEST_IS_REGULAR)) {
2417 return (path.length() > 7 && path.find (".ardour") == (path.length() - 7));
2421 Session::find_all_sources (string path, set<string>& result)
2426 if (!tree.read (path)) {
2430 if ((node = find_named_node (*tree.root(), "Sources")) == 0) {
2435 XMLNodeConstIterator niter;
2437 nlist = node->children();
2441 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2445 if ((prop = (*niter)->property (X_("type"))) == 0) {
2449 DataType type (prop->value());
2451 if ((prop = (*niter)->property (X_("name"))) == 0) {
2455 if (Glib::path_is_absolute (prop->value())) {
2456 /* external file, ignore */
2464 if (FileSource::find (*this, type, prop->value(), true, is_new, chan, found_path)) {
2465 result.insert (found_path);
2473 Session::find_all_sources_across_snapshots (set<string>& result, bool exclude_this_snapshot)
2475 PathScanner scanner;
2476 vector<string*>* state_files;
2478 string this_snapshot_path;
2484 if (ripped[ripped.length()-1] == G_DIR_SEPARATOR) {
2485 ripped = ripped.substr (0, ripped.length() - 1);
2488 state_files = scanner (ripped, accept_all_state_files, (void *) 0, true, true);
2490 if (state_files == 0) {
2495 this_snapshot_path = _path;
2496 this_snapshot_path += legalize_for_path (_current_snapshot_name);
2497 this_snapshot_path += statefile_suffix;
2499 for (vector<string*>::iterator i = state_files->begin(); i != state_files->end(); ++i) {
2501 if (exclude_this_snapshot && **i == this_snapshot_path) {
2505 if (find_all_sources (**i, result) < 0) {
2513 struct RegionCounter {
2514 typedef std::map<PBD::ID,boost::shared_ptr<AudioSource> > AudioSourceList;
2515 AudioSourceList::iterator iter;
2516 boost::shared_ptr<Region> region;
2519 RegionCounter() : count (0) {}
2523 Session::ask_about_playlist_deletion (boost::shared_ptr<Playlist> p)
2525 boost::optional<int> r = AskAboutPlaylistDeletion (p);
2526 return r.get_value_or (1);
2530 Session::cleanup_regions ()
2532 const RegionFactory::RegionMap& regions (RegionFactory::regions());
2534 for (RegionFactory::RegionMap::const_iterator i = regions.begin(); i != regions.end(); ++i) {
2536 uint32_t used = playlists->region_use_count (i->second);
2538 if (used == 0 && !i->second->automatic ()) {
2539 RegionFactory::map_remove (i->second);
2543 /* dump the history list */
2550 Session::cleanup_sources (CleanupReport& rep)
2552 // FIXME: needs adaptation to midi
2554 vector<boost::shared_ptr<Source> > dead_sources;
2555 PathScanner scanner;
2558 vector<space_and_path>::iterator i;
2559 vector<space_and_path>::iterator nexti;
2560 vector<string*>* candidates;
2561 vector<string*>* candidates2;
2562 vector<string> unused;
2563 set<string> all_sources;
2568 _state_of_the_state = (StateOfTheState) (_state_of_the_state | InCleanup);
2570 /* consider deleting all unused playlists */
2572 if (playlists->maybe_delete_unused (boost::bind (Session::ask_about_playlist_deletion, _1))) {
2577 /* sync the "all regions" property of each playlist with its current state
2580 playlists->sync_all_regions_with_regions ();
2582 /* find all un-used sources */
2587 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ) {
2589 SourceMap::iterator tmp;
2594 /* do not bother with files that are zero size, otherwise we remove the current "nascent"
2598 if (!i->second->used() && (i->second->length(i->second->timeline_position() > 0))) {
2599 dead_sources.push_back (i->second);
2600 i->second->drop_references ();
2606 /* build a list of all the possible audio directories for the session */
2608 for (i = session_dirs.begin(); i != session_dirs.end(); ) {
2613 SessionDirectory sdir ((*i).path);
2614 audio_path += sdir.sound_path();
2616 if (nexti != session_dirs.end()) {
2624 /* build a list of all the possible midi directories for the session */
2626 for (i = session_dirs.begin(); i != session_dirs.end(); ) {
2631 SessionDirectory sdir ((*i).path);
2632 midi_path += sdir.midi_path();
2634 if (nexti != session_dirs.end()) {
2641 candidates = scanner (audio_path, accept_all_audio_files, (void *) 0, true, true);
2642 candidates2 = scanner (midi_path, accept_all_midi_files, (void *) 0, true, true);
2648 for (vector<string*>::iterator i = candidates2->begin(); i != candidates2->end(); ++i) {
2649 candidates->push_back (*i);
2654 candidates = candidates2; // might still be null
2657 /* find all sources, but don't use this snapshot because the
2658 state file on disk still references sources we may have already
2662 find_all_sources_across_snapshots (all_sources, true);
2664 /* add our current source list
2667 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ) {
2668 boost::shared_ptr<FileSource> fs;
2669 SourceMap::iterator tmp = i;
2672 if ((fs = boost::dynamic_pointer_cast<FileSource> (i->second)) != 0) {
2673 if (playlists->source_use_count (fs) != 0) {
2674 all_sources.insert (fs->path());
2677 /* we might not remove this source from disk, because it may be used
2678 by other snapshots, but its not being used in this version
2679 so lets get rid of it now, along with any representative regions
2683 RegionFactory::remove_regions_using_source (i->second);
2691 char tmppath1[PATH_MAX+1];
2692 char tmppath2[PATH_MAX+1];
2695 for (vector<string*>::iterator x = candidates->begin(); x != candidates->end(); ++x) {
2700 for (set<string>::iterator i = all_sources.begin(); i != all_sources.end(); ++i) {
2702 if (realpath(spath.c_str(), tmppath1) == 0) {
2703 error << string_compose (_("Cannot expand path %1 (%2)"),
2704 spath, strerror (errno)) << endmsg;
2708 if (realpath((*i).c_str(), tmppath2) == 0) {
2709 error << string_compose (_("Cannot expand path %1 (%2)"),
2710 (*i), strerror (errno)) << endmsg;
2714 if (strcmp(tmppath1, tmppath2) == 0) {
2721 unused.push_back (spath);
2730 /* now try to move all unused files into the "dead" directory(ies) */
2732 for (vector<string>::iterator x = unused.begin(); x != unused.end(); ++x) {
2733 struct stat statbuf;
2737 /* don't move the file across filesystems, just
2738 stick it in the `dead_dir_name' directory
2739 on whichever filesystem it was already on.
2742 if ((*x).find ("/sounds/") != string::npos) {
2744 /* old school, go up 1 level */
2746 newpath = Glib::path_get_dirname (*x); // "sounds"
2747 newpath = Glib::path_get_dirname (newpath); // "session-name"
2751 /* new school, go up 4 levels */
2753 newpath = Glib::path_get_dirname (*x); // "audiofiles" or "midifiles"
2754 newpath = Glib::path_get_dirname (newpath); // "session-name"
2755 newpath = Glib::path_get_dirname (newpath); // "interchange"
2756 newpath = Glib::path_get_dirname (newpath); // "session-dir"
2759 newpath = Glib::build_filename (newpath, dead_dir_name);
2761 if (g_mkdir_with_parents (newpath.c_str(), 0755) < 0) {
2762 error << string_compose(_("Session: cannot create dead file folder \"%1\" (%2)"), newpath, strerror (errno)) << endmsg;
2766 newpath = Glib::build_filename (newpath, Glib::path_get_basename ((*x)));
2768 if (Glib::file_test (newpath, Glib::FILE_TEST_EXISTS)) {
2770 /* the new path already exists, try versioning */
2772 char buf[PATH_MAX+1];
2776 snprintf (buf, sizeof (buf), "%s.%d", newpath.c_str(), version);
2779 while (Glib::file_test (newpath_v.c_str(), Glib::FILE_TEST_EXISTS) && version < 999) {
2780 snprintf (buf, sizeof (buf), "%s.%d", newpath.c_str(), ++version);
2784 if (version == 999) {
2785 error << string_compose (_("there are already 1000 files with names like %1; versioning discontinued"),
2789 newpath = newpath_v;
2794 /* it doesn't exist, or we can't read it or something */
2798 stat ((*x).c_str(), &statbuf);
2800 if (::rename ((*x).c_str(), newpath.c_str()) != 0) {
2801 error << string_compose (_("cannot rename unused file source from %1 to %2 (%3)"),
2802 (*x), newpath, strerror (errno))
2807 /* see if there an easy to find peakfile for this file, and remove it.
2810 string base = basename_nosuffix (*x);
2811 base += "%A"; /* this is what we add for the channel suffix of all native files,
2812 or for the first channel of embedded files. it will miss
2813 some peakfiles for other channels
2815 string peakpath = peak_path (base);
2817 if (Glib::file_test (peakpath.c_str(), Glib::FILE_TEST_EXISTS)) {
2818 if (::unlink (peakpath.c_str()) != 0) {
2819 error << string_compose (_("cannot remove peakfile %1 for %2 (%3)"),
2820 peakpath, _path, strerror (errno))
2822 /* try to back out */
2823 ::rename (newpath.c_str(), _path.c_str());
2828 rep.paths.push_back (*x);
2829 rep.space += statbuf.st_size;
2832 /* dump the history list */
2836 /* save state so we don't end up a session file
2837 referring to non-existent sources.
2844 _state_of_the_state = (StateOfTheState) (_state_of_the_state & ~InCleanup);
2850 Session::cleanup_trash_sources (CleanupReport& rep)
2852 // FIXME: needs adaptation for MIDI
2854 vector<space_and_path>::iterator i;
2860 for (i = session_dirs.begin(); i != session_dirs.end(); ++i) {
2862 dead_dir = Glib::build_filename ((*i).path, dead_dir_name);
2864 clear_directory (dead_dir, &rep.space, &rep.paths);
2871 Session::set_dirty ()
2873 bool was_dirty = dirty();
2875 _state_of_the_state = StateOfTheState (_state_of_the_state | Dirty);
2879 DirtyChanged(); /* EMIT SIGNAL */
2885 Session::set_clean ()
2887 bool was_dirty = dirty();
2889 _state_of_the_state = Clean;
2893 DirtyChanged(); /* EMIT SIGNAL */
2898 Session::set_deletion_in_progress ()
2900 _state_of_the_state = StateOfTheState (_state_of_the_state | Deletion);
2904 Session::clear_deletion_in_progress ()
2906 _state_of_the_state = StateOfTheState (_state_of_the_state & (~Deletion));
2910 Session::add_controllable (boost::shared_ptr<Controllable> c)
2912 /* this adds a controllable to the list managed by the Session.
2913 this is a subset of those managed by the Controllable class
2914 itself, and represents the only ones whose state will be saved
2915 as part of the session.
2918 Glib::Threads::Mutex::Lock lm (controllables_lock);
2919 controllables.insert (c);
2922 struct null_deleter { void operator()(void const *) const {} };
2925 Session::remove_controllable (Controllable* c)
2927 if (_state_of_the_state & Deletion) {
2931 Glib::Threads::Mutex::Lock lm (controllables_lock);
2933 Controllables::iterator x = controllables.find (boost::shared_ptr<Controllable>(c, null_deleter()));
2935 if (x != controllables.end()) {
2936 controllables.erase (x);
2940 boost::shared_ptr<Controllable>
2941 Session::controllable_by_id (const PBD::ID& id)
2943 Glib::Threads::Mutex::Lock lm (controllables_lock);
2945 for (Controllables::iterator i = controllables.begin(); i != controllables.end(); ++i) {
2946 if ((*i)->id() == id) {
2951 return boost::shared_ptr<Controllable>();
2954 boost::shared_ptr<Controllable>
2955 Session::controllable_by_descriptor (const ControllableDescriptor& desc)
2957 boost::shared_ptr<Controllable> c;
2958 boost::shared_ptr<Route> r;
2960 switch (desc.top_level_type()) {
2961 case ControllableDescriptor::NamedRoute:
2963 std::string str = desc.top_level_name();
2964 if (str == "master") {
2966 } else if (str == "control" || str == "listen") {
2969 r = route_by_name (desc.top_level_name());
2974 case ControllableDescriptor::RemoteControlID:
2975 r = route_by_remote_id (desc.rid());
2983 switch (desc.subtype()) {
2984 case ControllableDescriptor::Gain:
2985 c = r->gain_control ();
2988 case ControllableDescriptor::Solo:
2989 c = r->solo_control();
2992 case ControllableDescriptor::Mute:
2993 c = r->mute_control();
2996 case ControllableDescriptor::Recenable:
2998 boost::shared_ptr<Track> t = boost::dynamic_pointer_cast<Track>(r);
3001 c = t->rec_enable_control ();
3006 case ControllableDescriptor::PanDirection:
3008 c = r->pannable()->pan_azimuth_control;
3012 case ControllableDescriptor::PanWidth:
3014 c = r->pannable()->pan_width_control;
3018 case ControllableDescriptor::PanElevation:
3020 c = r->pannable()->pan_elevation_control;
3024 case ControllableDescriptor::Balance:
3025 /* XXX simple pan control */
3028 case ControllableDescriptor::PluginParameter:
3030 uint32_t plugin = desc.target (0);
3031 uint32_t parameter_index = desc.target (1);
3033 /* revert to zero based counting */
3039 if (parameter_index > 0) {
3043 boost::shared_ptr<Processor> p = r->nth_plugin (plugin);
3046 c = boost::dynamic_pointer_cast<ARDOUR::AutomationControl>(
3047 p->control(Evoral::Parameter(PluginAutomation, 0, parameter_index)));
3052 case ControllableDescriptor::SendGain:
3054 uint32_t send = desc.target (0);
3056 /* revert to zero-based counting */
3062 boost::shared_ptr<Processor> p = r->nth_send (send);
3065 boost::shared_ptr<Send> s = boost::dynamic_pointer_cast<Send>(p);
3066 boost::shared_ptr<Amp> a = s->amp();
3069 c = s->amp()->gain_control();
3076 /* relax and return a null pointer */
3084 Session::add_instant_xml (XMLNode& node, bool write_to_config)
3087 Stateful::add_instant_xml (node, _path);
3090 if (write_to_config) {
3091 Config->add_instant_xml (node);
3096 Session::instant_xml (const string& node_name)
3098 return Stateful::instant_xml (node_name, _path);
3102 Session::save_history (string snapshot_name)
3110 if (snapshot_name.empty()) {
3111 snapshot_name = _current_snapshot_name;
3114 const string history_filename = legalize_for_path (snapshot_name) + history_suffix;
3115 const string backup_filename = history_filename + backup_suffix;
3116 const std::string xml_path(Glib::build_filename (_session_dir->root_path(), history_filename));
3117 const std::string backup_path(Glib::build_filename (_session_dir->root_path(), backup_filename));
3119 if (Glib::file_test (xml_path, Glib::FILE_TEST_EXISTS)) {
3120 if (::g_rename (xml_path.c_str(), backup_path.c_str()) != 0) {
3121 error << _("could not backup old history file, current history not saved") << endmsg;
3126 if (!Config->get_save_history() || Config->get_saved_history_depth() < 0) {
3130 tree.set_root (&_history.get_state (Config->get_saved_history_depth()));
3132 if (!tree.write (xml_path))
3134 error << string_compose (_("history could not be saved to %1"), xml_path) << endmsg;
3136 if (g_remove (xml_path.c_str()) != 0) {
3137 error << string_compose(_("Could not remove history file at path \"%1\" (%2)"),
3138 xml_path, g_strerror (errno)) << endmsg;
3140 if (::g_rename (backup_path.c_str(), xml_path.c_str()) != 0) {
3141 error << string_compose (_("could not restore history file from backup %1 (%2)"),
3142 backup_path, g_strerror (errno)) << endmsg;
3152 Session::restore_history (string snapshot_name)
3156 if (snapshot_name.empty()) {
3157 snapshot_name = _current_snapshot_name;
3160 const std::string xml_filename = legalize_for_path (snapshot_name) + history_suffix;
3161 const std::string xml_path(Glib::build_filename (_session_dir->root_path(), xml_filename));
3163 info << "Loading history from " << xml_path << endmsg;
3165 if (!Glib::file_test (xml_path, Glib::FILE_TEST_EXISTS)) {
3166 info << string_compose (_("%1: no history file \"%2\" for this session."),
3167 _name, xml_path) << endmsg;
3171 if (!tree.read (xml_path)) {
3172 error << string_compose (_("Could not understand session history file \"%1\""),
3173 xml_path) << endmsg;
3180 for (XMLNodeConstIterator it = tree.root()->children().begin(); it != tree.root()->children().end(); it++) {
3183 UndoTransaction* ut = new UndoTransaction ();
3186 ut->set_name(t->property("name")->value());
3187 stringstream ss(t->property("tv-sec")->value());
3189 ss.str(t->property("tv-usec")->value());
3191 ut->set_timestamp(tv);
3193 for (XMLNodeConstIterator child_it = t->children().begin();
3194 child_it != t->children().end(); child_it++)
3196 XMLNode *n = *child_it;
3199 if (n->name() == "MementoCommand" ||
3200 n->name() == "MementoUndoCommand" ||
3201 n->name() == "MementoRedoCommand") {
3203 if ((c = memento_command_factory(n))) {
3207 } else if (n->name() == "NoteDiffCommand") {
3208 PBD::ID id (n->property("midi-source")->value());
3209 boost::shared_ptr<MidiSource> midi_source =
3210 boost::dynamic_pointer_cast<MidiSource, Source>(source_by_id(id));
3212 ut->add_command (new MidiModel::NoteDiffCommand(midi_source->model(), *n));
3214 error << _("Failed to downcast MidiSource for NoteDiffCommand") << endmsg;
3217 } else if (n->name() == "SysExDiffCommand") {
3219 PBD::ID id (n->property("midi-source")->value());
3220 boost::shared_ptr<MidiSource> midi_source =
3221 boost::dynamic_pointer_cast<MidiSource, Source>(source_by_id(id));
3223 ut->add_command (new MidiModel::SysExDiffCommand (midi_source->model(), *n));
3225 error << _("Failed to downcast MidiSource for SysExDiffCommand") << endmsg;
3228 } else if (n->name() == "PatchChangeDiffCommand") {
3230 PBD::ID id (n->property("midi-source")->value());
3231 boost::shared_ptr<MidiSource> midi_source =
3232 boost::dynamic_pointer_cast<MidiSource, Source>(source_by_id(id));
3234 ut->add_command (new MidiModel::PatchChangeDiffCommand (midi_source->model(), *n));
3236 error << _("Failed to downcast MidiSource for PatchChangeDiffCommand") << endmsg;
3239 } else if (n->name() == "StatefulDiffCommand") {
3240 if ((c = stateful_diff_command_factory (n))) {
3241 ut->add_command (c);
3244 error << string_compose(_("Couldn't figure out how to make a Command out of a %1 XMLNode."), n->name()) << endmsg;
3255 Session::config_changed (std::string p, bool ours)
3261 if (p == "seamless-loop") {
3263 } else if (p == "rf-speed") {
3265 } else if (p == "auto-loop") {
3267 } else if (p == "auto-input") {
3269 if (Config->get_monitoring_model() == HardwareMonitoring && transport_rolling()) {
3270 /* auto-input only makes a difference if we're rolling */
3271 set_track_monitor_input_status (!config.get_auto_input());
3274 } else if (p == "punch-in") {
3278 if ((location = _locations->auto_punch_location()) != 0) {
3280 if (config.get_punch_in ()) {
3281 replace_event (SessionEvent::PunchIn, location->start());
3283 remove_event (location->start(), SessionEvent::PunchIn);
3287 } else if (p == "punch-out") {
3291 if ((location = _locations->auto_punch_location()) != 0) {
3293 if (config.get_punch_out()) {
3294 replace_event (SessionEvent::PunchOut, location->end());
3296 clear_events (SessionEvent::PunchOut);
3300 } else if (p == "edit-mode") {
3302 Glib::Threads::Mutex::Lock lm (playlists->lock);
3304 for (SessionPlaylists::List::iterator i = playlists->playlists.begin(); i != playlists->playlists.end(); ++i) {
3305 (*i)->set_edit_mode (Config->get_edit_mode ());
3308 } else if (p == "use-video-sync") {
3310 waiting_for_sync_offset = config.get_use_video_sync();
3312 } else if (p == "mmc-control") {
3314 //poke_midi_thread ();
3316 } else if (p == "mmc-device-id" || p == "mmc-receive-id" || p == "mmc-receive-device-id") {
3318 _mmc->set_receive_device_id (Config->get_mmc_receive_device_id());
3320 } else if (p == "mmc-send-id" || p == "mmc-send-device-id") {
3322 _mmc->set_send_device_id (Config->get_mmc_send_device_id());
3324 } else if (p == "midi-control") {
3326 //poke_midi_thread ();
3328 } else if (p == "raid-path") {
3330 setup_raid_path (config.get_raid_path());
3332 } else if (p == "timecode-format") {
3336 } else if (p == "video-pullup") {
3340 } else if (p == "seamless-loop") {
3342 if (play_loop && transport_rolling()) {
3343 // to reset diskstreams etc
3344 request_play_loop (true);
3347 } else if (p == "rf-speed") {
3349 cumulative_rf_motion = 0;
3352 } else if (p == "click-sound") {
3354 setup_click_sounds (1);
3356 } else if (p == "click-emphasis-sound") {
3358 setup_click_sounds (-1);
3360 } else if (p == "clicking") {
3362 if (Config->get_clicking()) {
3363 if (_click_io && click_data) { // don't require emphasis data
3370 } else if (p == "click-gain") {
3373 _click_gain->set_gain (Config->get_click_gain(), this);
3376 } else if (p == "send-mtc") {
3378 if (Config->get_send_mtc ()) {
3379 /* mark us ready to send */
3380 next_quarter_frame_to_send = 0;
3383 } else if (p == "send-mmc") {
3385 _mmc->enable_send (Config->get_send_mmc ());
3387 } else if (p == "midi-feedback") {
3389 session_midi_feedback = Config->get_midi_feedback();
3391 } else if (p == "jack-time-master") {
3393 engine().reset_timebase ();
3395 } else if (p == "native-file-header-format") {
3397 if (!first_file_header_format_reset) {
3398 reset_native_file_format ();
3401 first_file_header_format_reset = false;
3403 } else if (p == "native-file-data-format") {
3405 if (!first_file_data_format_reset) {
3406 reset_native_file_format ();
3409 first_file_data_format_reset = false;
3411 } else if (p == "external-sync") {
3412 if (!config.get_external_sync()) {
3413 drop_sync_source ();
3415 switch_to_sync_source (Config->get_sync_source());
3417 } else if (p == "denormal-model") {
3419 } else if (p == "history-depth") {
3420 set_history_depth (Config->get_history_depth());
3421 } else if (p == "remote-model") {
3422 /* XXX DO SOMETHING HERE TO TELL THE GUI THAT WE NEED
3425 } else if (p == "sync-all-route-ordering") {
3427 /* sync to editor order unless mixer is used for remote IDs
3430 switch (Config->get_remote_model()) {
3432 sync_order_keys (EditorSort);
3435 sync_order_keys (EditorSort);
3438 sync_order_keys (MixerSort);
3441 } else if (p == "initial-program-change") {
3443 if (_mmc->output_port() && Config->get_initial_program_change() >= 0) {
3446 buf[0] = MIDI::program; // channel zero by default
3447 buf[1] = (Config->get_initial_program_change() & 0x7f);
3449 _mmc->output_port()->midimsg (buf, sizeof (buf), 0);
3451 } else if (p == "solo-mute-override") {
3452 // catch_up_on_solo_mute_override ();
3453 } else if (p == "listen-position" || p == "pfl-position") {
3454 listen_position_changed ();
3455 } else if (p == "solo-control-is-listen-control") {
3456 solo_control_mode_changed ();
3457 } else if (p == "timecode-offset" || p == "timecode-offset-negative") {
3458 last_timecode_valid = false;
3459 } else if (p == "playback-buffer-seconds") {
3460 AudioSource::allocate_working_buffers (frame_rate());
3461 } else if (p == "automation-thinning-factor") {
3462 Evoral::ControlList::set_thinning_factor (Config->get_automation_thinning_factor());
3463 } else if (p == "ltc-source-port") {
3464 reconnect_ltc_input ();
3465 } else if (p == "ltc-sink-port") {
3466 reconnect_ltc_output ();
3467 } else if (p == "timecode-generator-offset") {
3468 ltc_tx_parse_offset();
3475 Session::set_history_depth (uint32_t d)
3477 _history.set_depth (d);
3481 Session::load_diskstreams_2X (XMLNode const & node, int)
3484 XMLNodeConstIterator citer;
3486 clist = node.children();
3488 for (citer = clist.begin(); citer != clist.end(); ++citer) {
3491 /* diskstreams added automatically by DiskstreamCreated handler */
3492 if ((*citer)->name() == "AudioDiskstream" || (*citer)->name() == "DiskStream") {
3493 boost::shared_ptr<AudioDiskstream> dsp (new AudioDiskstream (*this, **citer));
3494 _diskstreams_2X.push_back (dsp);
3496 error << _("Session: unknown diskstream type in XML") << endmsg;
3500 catch (failed_constructor& err) {
3501 error << _("Session: could not load diskstream via XML state") << endmsg;
3509 /** Connect things to the MMC object */
3511 Session::setup_midi_machine_control ()
3513 _mmc = new MIDI::MachineControl;
3514 _mmc->set_ports (_midi_ports->mmc_input_port(), _midi_ports->mmc_output_port());
3516 _mmc->Play.connect_same_thread (*this, boost::bind (&Session::mmc_deferred_play, this, _1));
3517 _mmc->DeferredPlay.connect_same_thread (*this, boost::bind (&Session::mmc_deferred_play, this, _1));
3518 _mmc->Stop.connect_same_thread (*this, boost::bind (&Session::mmc_stop, this, _1));
3519 _mmc->FastForward.connect_same_thread (*this, boost::bind (&Session::mmc_fast_forward, this, _1));
3520 _mmc->Rewind.connect_same_thread (*this, boost::bind (&Session::mmc_rewind, this, _1));
3521 _mmc->Pause.connect_same_thread (*this, boost::bind (&Session::mmc_pause, this, _1));
3522 _mmc->RecordPause.connect_same_thread (*this, boost::bind (&Session::mmc_record_pause, this, _1));
3523 _mmc->RecordStrobe.connect_same_thread (*this, boost::bind (&Session::mmc_record_strobe, this, _1));
3524 _mmc->RecordExit.connect_same_thread (*this, boost::bind (&Session::mmc_record_exit, this, _1));
3525 _mmc->Locate.connect_same_thread (*this, boost::bind (&Session::mmc_locate, this, _1, _2));
3526 _mmc->Step.connect_same_thread (*this, boost::bind (&Session::mmc_step, this, _1, _2));
3527 _mmc->Shuttle.connect_same_thread (*this, boost::bind (&Session::mmc_shuttle, this, _1, _2, _3));
3528 _mmc->TrackRecordStatusChange.connect_same_thread (*this, boost::bind (&Session::mmc_record_enable, this, _1, _2, _3));
3530 /* also handle MIDI SPP because its so common */
3532 _mmc->SPPStart.connect_same_thread (*this, boost::bind (&Session::spp_start, this));
3533 _mmc->SPPContinue.connect_same_thread (*this, boost::bind (&Session::spp_continue, this));
3534 _mmc->SPPStop.connect_same_thread (*this, boost::bind (&Session::spp_stop, this));
3537 boost::shared_ptr<Controllable>
3538 Session::solo_cut_control() const
3540 /* the solo cut control is a bit of an anomaly, at least as of Febrary 2011. There are no other
3541 controls in Ardour that currently get presented to the user in the GUI that require
3542 access as a Controllable and are also NOT owned by some SessionObject (e.g. Route, or MonitorProcessor).
3544 its actually an RCConfiguration parameter, so we use a ProxyControllable to wrap
3545 it up as a Controllable. Changes to the Controllable will just map back to the RCConfiguration
3549 return _solo_cut_control;
3553 Session::rename (const std::string& new_name)
3555 string legal_name = legalize_for_path (new_name);
3561 string const old_sources_root = _session_dir->sources_root();
3563 #define RENAME ::rename
3568 * interchange subdirectory
3572 * Backup files are left unchanged and not renamed.
3575 /* pass one: not 100% safe check that the new directory names don't
3579 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
3584 /* this is a stupid hack because Glib::path_get_dirname() is
3585 * lexical-only, and so passing it /a/b/c/ gives a different
3586 * result than passing it /a/b/c ...
3589 if (oldstr[oldstr.length()-1] == G_DIR_SEPARATOR) {
3590 oldstr = oldstr.substr (0, oldstr.length() - 1);
3593 string base = Glib::path_get_dirname (oldstr);
3594 string p = Glib::path_get_basename (oldstr);
3596 newstr = Glib::build_filename (base, legal_name);
3598 if (Glib::file_test (newstr, Glib::FILE_TEST_EXISTS)) {
3605 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
3610 /* this is a stupid hack because Glib::path_get_dirname() is
3611 * lexical-only, and so passing it /a/b/c/ gives a different
3612 * result than passing it /a/b/c ...
3615 if (oldstr[oldstr.length()-1] == G_DIR_SEPARATOR) {
3616 oldstr = oldstr.substr (0, oldstr.length() - 1);
3619 string base = Glib::path_get_dirname (oldstr);
3620 string p = Glib::path_get_basename (oldstr);
3622 newstr = Glib::build_filename (base, legal_name);
3624 cerr << "Rename " << oldstr << " => " << newstr << endl;
3626 if (RENAME (oldstr.c_str(), newstr.c_str()) != 0) {
3631 (*_session_dir) = newstr;
3636 /* directory below interchange */
3638 v.push_back (newstr);
3639 v.push_back (interchange_dir_name);
3642 oldstr = Glib::build_filename (v);
3645 v.push_back (newstr);
3646 v.push_back (interchange_dir_name);
3647 v.push_back (legal_name);
3649 newstr = Glib::build_filename (v);
3651 cerr << "Rename " << oldstr << " => " << newstr << endl;
3653 if (RENAME (oldstr.c_str(), newstr.c_str()) != 0) {
3660 oldstr = Glib::build_filename (newpath, _current_snapshot_name) + statefile_suffix;
3661 newstr= Glib::build_filename (newpath, legal_name) + statefile_suffix;
3663 cerr << "Rename " << oldstr << " => " << newstr << endl;
3665 if (RENAME (oldstr.c_str(), newstr.c_str()) != 0) {
3672 oldstr = Glib::build_filename (newpath, _current_snapshot_name) + history_suffix;
3674 if (Glib::file_test (oldstr, Glib::FILE_TEST_EXISTS)) {
3675 newstr = Glib::build_filename (newpath, legal_name) + history_suffix;
3677 cerr << "Rename " << oldstr << " => " << newstr << endl;
3679 if (RENAME (oldstr.c_str(), newstr.c_str()) != 0) {
3684 /* update file source paths */
3686 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ++i) {
3687 boost::shared_ptr<FileSource> fs = boost::dynamic_pointer_cast<FileSource> (i->second);
3689 string p = fs->path ();
3690 boost::replace_all (p, old_sources_root, _session_dir->sources_root());
3695 /* remove old name from recent sessions */
3697 remove_recent_sessions (_path);
3700 _current_snapshot_name = new_name;
3705 /* save state again to get everything just right */
3707 save_state (_current_snapshot_name);
3710 /* add to recent sessions */
3712 store_recent_sessions (new_name, _path);