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 /* default: assume simple stereo speaker configuration */
182 _speakers->setup_default_speakers (2);
184 _solo_cut_control.reset (new ProxyControllable (_("solo cut control (dB)"), PBD::Controllable::GainLike,
185 boost::bind (&RCConfiguration::set_solo_mute_gain, Config, _1),
186 boost::bind (&RCConfiguration::get_solo_mute_gain, Config)));
187 add_controllable (_solo_cut_control);
189 /* These are all static "per-class" signals */
191 SourceFactory::SourceCreated.connect_same_thread (*this, boost::bind (&Session::add_source, this, _1));
192 PlaylistFactory::PlaylistCreated.connect_same_thread (*this, boost::bind (&Session::add_playlist, this, _1, _2));
193 AutomationList::AutomationListCreated.connect_same_thread (*this, boost::bind (&Session::add_automation_list, this, _1));
194 Controllable::Destroyed.connect_same_thread (*this, boost::bind (&Session::remove_controllable, this, _1));
195 IO::PortCountChanged.connect_same_thread (*this, boost::bind (&Session::ensure_buffers, this, _1));
197 /* stop IO objects from doing stuff until we're ready for them */
199 Delivery::disable_panners ();
200 IO::disable_connecting ();
202 AudioFileSource::set_peak_dir (_session_dir->peak_path());
206 Session::post_engine_init ()
208 BootMessage (_("Set block size and sample rate"));
210 set_block_size (_engine.samples_per_cycle());
211 set_frame_rate (_engine.sample_rate());
213 if (how_many_dsp_threads () > 1) {
214 /* For now, only create the graph if we are using >1 DSP threads, as
215 it is a bit slower than the old code with 1 thread.
217 _process_graph.reset (new Graph (*this));
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;
327 Session::raid_path () const
329 SearchPath raid_search_path;
331 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
332 raid_search_path += (*i).path;
335 return raid_search_path.to_string ();
339 Session::setup_raid_path (string path)
348 session_dirs.clear ();
350 SearchPath search_path(path);
351 SearchPath sound_search_path;
352 SearchPath midi_search_path;
354 for (SearchPath::const_iterator i = search_path.begin(); i != search_path.end(); ++i) {
356 sp.blocks = 0; // not needed
357 session_dirs.push_back (sp);
359 SessionDirectory sdir(sp.path);
361 sound_search_path += sdir.sound_path ();
362 midi_search_path += sdir.midi_path ();
365 // reset the round-robin soundfile path thingie
366 last_rr_session_dir = session_dirs.begin();
370 Session::path_is_within_session (const std::string& path)
372 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
373 if (PBD::path_is_within (i->path, path)) {
381 Session::ensure_subdirs ()
385 dir = session_directory().peak_path();
387 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
388 error << string_compose(_("Session: cannot create session peakfile folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
392 dir = session_directory().sound_path();
394 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
395 error << string_compose(_("Session: cannot create session sounds dir \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
399 dir = session_directory().midi_path();
401 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
402 error << string_compose(_("Session: cannot create session midi dir \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
406 dir = session_directory().dead_path();
408 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
409 error << string_compose(_("Session: cannot create session dead sounds folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
413 dir = session_directory().export_path();
415 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
416 error << string_compose(_("Session: cannot create session export folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
420 dir = analysis_dir ();
422 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
423 error << string_compose(_("Session: cannot create session analysis folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
427 dir = plugins_dir ();
429 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
430 error << string_compose(_("Session: cannot create session plugins folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
434 dir = externals_dir ();
436 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
437 error << string_compose(_("Session: cannot create session externals folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
444 /** @param session_template directory containing session template, or empty.
445 * Caller must not hold process lock.
448 Session::create (const string& session_template, BusProfile* bus_profile)
450 if (g_mkdir_with_parents (_path.c_str(), 0755) < 0) {
451 error << string_compose(_("Session: cannot create session folder \"%1\" (%2)"), _path, strerror (errno)) << endmsg;
455 if (ensure_subdirs ()) {
459 _writable = exists_and_writable (_path);
461 if (!session_template.empty()) {
462 std::string in_path = session_template_dir_to_file (session_template);
464 ifstream in(in_path.c_str());
467 string out_path = _path;
469 out_path += statefile_suffix;
471 ofstream out(out_path.c_str());
477 /* Copy plugin state files from template to new session */
478 std::string template_plugins = Glib::build_filename (session_template, X_("plugins"));
479 copy_files (template_plugins, plugins_dir ());
484 error << string_compose (_("Could not open %1 for writing session template"), out_path)
490 error << string_compose (_("Could not open session template %1 for reading"), in_path)
497 /* set initial start + end point */
499 _state_of_the_state = Clean;
501 /* set up Master Out and Control Out if necessary */
506 ChanCount count(DataType::AUDIO, bus_profile->master_out_channels);
508 if (bus_profile->master_out_channels) {
509 boost::shared_ptr<Route> r (new Route (*this, _("master"), Route::MasterOut, DataType::AUDIO));
513 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
514 // boost_debug_shared_ptr_mark_interesting (r.get(), "Route");
517 Glib::Threads::Mutex::Lock lm (AudioEngine::instance()->process_lock ());
518 r->input()->ensure_io (count, false, this);
519 r->output()->ensure_io (count, false, this);
525 /* prohibit auto-connect to master, because there isn't one */
526 bus_profile->output_ac = AutoConnectOption (bus_profile->output_ac & ~AutoConnectMaster);
530 add_routes (rl, false, false, false);
533 /* this allows the user to override settings with an environment variable.
536 if (no_auto_connect()) {
537 bus_profile->input_ac = AutoConnectOption (0);
538 bus_profile->output_ac = AutoConnectOption (0);
541 Config->set_input_auto_connect (bus_profile->input_ac);
542 Config->set_output_auto_connect (bus_profile->output_ac);
545 if (Config->get_use_monitor_bus() && bus_profile) {
546 add_monitor_section ();
553 Session::maybe_write_autosave()
555 if (dirty() && record_status() != Recording) {
556 save_state("", true);
561 Session::remove_pending_capture_state ()
563 std::string pending_state_file_path(_session_dir->root_path());
565 pending_state_file_path = Glib::build_filename (pending_state_file_path, legalize_for_path (_current_snapshot_name) + pending_suffix);
567 if (!Glib::file_test (pending_state_file_path, Glib::FILE_TEST_EXISTS)) return;
569 if (g_remove (pending_state_file_path.c_str()) != 0) {
570 error << string_compose(_("Could not remove pending capture state at path \"%1\" (%2)"),
571 pending_state_file_path, g_strerror (errno)) << endmsg;
575 /** Rename a state file.
576 * @param old_name Old snapshot name.
577 * @param new_name New snapshot name.
580 Session::rename_state (string old_name, string new_name)
582 if (old_name == _current_snapshot_name || old_name == _name) {
583 /* refuse to rename the current snapshot or the "main" one */
587 const string old_xml_filename = legalize_for_path (old_name) + statefile_suffix;
588 const string new_xml_filename = legalize_for_path (new_name) + statefile_suffix;
590 const std::string old_xml_path(Glib::build_filename (_session_dir->root_path(), old_xml_filename));
591 const std::string new_xml_path(Glib::build_filename (_session_dir->root_path(), new_xml_filename));
593 if (::g_rename (old_xml_path.c_str(), new_xml_path.c_str()) != 0) {
594 error << string_compose(_("could not rename snapshot %1 to %2 (%3)"),
595 old_name, new_name, g_strerror(errno)) << endmsg;
599 /** Remove a state file.
600 * @param snapshot_name Snapshot name.
603 Session::remove_state (string snapshot_name)
605 if (!_writable || snapshot_name == _current_snapshot_name || snapshot_name == _name) {
606 // refuse to remove the current snapshot or the "main" one
610 std::string xml_path(_session_dir->root_path());
612 xml_path = Glib::build_filename (xml_path, legalize_for_path (snapshot_name) + statefile_suffix);
614 if (!create_backup_file (xml_path)) {
615 // don't remove it if a backup can't be made
616 // create_backup_file will log the error.
621 if (g_remove (xml_path.c_str()) != 0) {
622 error << string_compose(_("Could not remove session file at path \"%1\" (%2)"),
623 xml_path, g_strerror (errno)) << endmsg;
627 /** @param snapshot_name Name to save under, without .ardour / .pending prefix */
629 Session::save_state (string snapshot_name, bool pending, bool switch_to_snapshot)
632 std::string xml_path(_session_dir->root_path());
634 if (!_writable || (_state_of_the_state & CannotSave)) {
638 if (!_engine.connected ()) {
639 error << string_compose (_("the %1 audio engine is not connected and state saving would lose all I/O connections. Session not saved"),
645 /* tell sources we're saving first, in case they write out to a new file
646 * which should be saved with the state rather than the old one */
647 for (SourceMap::const_iterator i = sources.begin(); i != sources.end(); ++i) {
649 i->second->session_saved();
650 } catch (Evoral::SMF::FileError& e) {
651 error << string_compose ("Could not write to MIDI file %1; MIDI data not saved.", e.file_name ()) << endmsg;
655 SaveSession (); /* EMIT SIGNAL */
657 tree.set_root (&get_state());
659 if (snapshot_name.empty()) {
660 snapshot_name = _current_snapshot_name;
661 } else if (switch_to_snapshot) {
662 _current_snapshot_name = snapshot_name;
667 /* proper save: use statefile_suffix (.ardour in English) */
669 xml_path = Glib::build_filename (xml_path, legalize_for_path (snapshot_name) + statefile_suffix);
671 /* make a backup copy of the old file */
673 if (Glib::file_test (xml_path, Glib::FILE_TEST_EXISTS) && !create_backup_file (xml_path)) {
674 // create_backup_file will log the error
680 /* pending save: use pending_suffix (.pending in English) */
681 xml_path = Glib::build_filename (xml_path, legalize_for_path (snapshot_name) + pending_suffix);
684 std::string tmp_path(_session_dir->root_path());
685 tmp_path = Glib::build_filename (tmp_path, legalize_for_path (snapshot_name) + temp_suffix);
687 // cerr << "actually writing state to " << xml_path << endl;
689 if (!tree.write (tmp_path)) {
690 error << string_compose (_("state could not be saved to %1"), tmp_path) << endmsg;
691 if (g_remove (tmp_path.c_str()) != 0) {
692 error << string_compose(_("Could not remove temporary session file at path \"%1\" (%2)"),
693 tmp_path, g_strerror (errno)) << endmsg;
699 if (::rename (tmp_path.c_str(), xml_path.c_str()) != 0) {
700 error << string_compose (_("could not rename temporary session file %1 to %2"),
701 tmp_path, xml_path) << endmsg;
702 if (g_remove (tmp_path.c_str()) != 0) {
703 error << string_compose(_("Could not remove temporary session file at path \"%1\" (%2)"),
704 tmp_path, g_strerror (errno)) << endmsg;
712 save_history (snapshot_name);
714 bool was_dirty = dirty();
716 _state_of_the_state = StateOfTheState (_state_of_the_state & ~Dirty);
719 DirtyChanged (); /* EMIT SIGNAL */
722 StateSaved (snapshot_name); /* EMIT SIGNAL */
729 Session::restore_state (string snapshot_name)
731 if (load_state (snapshot_name) == 0) {
732 set_state (*state_tree->root(), Stateful::loading_state_version);
739 Session::load_state (string snapshot_name)
744 state_was_pending = false;
746 /* check for leftover pending state from a crashed capture attempt */
748 std::string xmlpath(_session_dir->root_path());
749 xmlpath = Glib::build_filename (xmlpath, legalize_for_path (snapshot_name) + pending_suffix);
751 if (Glib::file_test (xmlpath, Glib::FILE_TEST_EXISTS)) {
753 /* there is pending state from a crashed capture attempt */
755 boost::optional<int> r = AskAboutPendingState();
756 if (r.get_value_or (1)) {
757 state_was_pending = true;
761 if (!state_was_pending) {
762 xmlpath = Glib::build_filename (_session_dir->root_path(), snapshot_name);
765 if (!Glib::file_test (xmlpath, Glib::FILE_TEST_EXISTS)) {
766 xmlpath = Glib::build_filename (_session_dir->root_path(), legalize_for_path (snapshot_name) + statefile_suffix);
767 if (!Glib::file_test (xmlpath, Glib::FILE_TEST_EXISTS)) {
768 error << string_compose(_("%1: session file \"%2\" doesn't exist!"), _name, xmlpath) << endmsg;
773 state_tree = new XMLTree;
777 _writable = exists_and_writable (xmlpath);
779 if (!state_tree->read (xmlpath)) {
780 error << string_compose(_("Could not understand session file %1"), xmlpath) << endmsg;
786 XMLNode& root (*state_tree->root());
788 if (root.name() != X_("Session")) {
789 error << string_compose (_("Session file %1 is not a session"), xmlpath) << endmsg;
795 const XMLProperty* prop;
797 if ((prop = root.property ("version")) == 0) {
798 /* no version implies very old version of Ardour */
799 Stateful::loading_state_version = 1000;
801 if (prop->value().find ('.') != string::npos) {
802 /* old school version format */
803 if (prop->value()[0] == '2') {
804 Stateful::loading_state_version = 2000;
806 Stateful::loading_state_version = 3000;
809 Stateful::loading_state_version = atoi (prop->value());
813 if (Stateful::loading_state_version < CURRENT_SESSION_FILE_VERSION && _writable) {
815 std::string backup_path(_session_dir->root_path());
816 std::string backup_filename = string_compose ("%1-%2%3", legalize_for_path (snapshot_name), Stateful::loading_state_version, statefile_suffix);
817 backup_path = Glib::build_filename (backup_path, backup_filename);
819 // only create a backup for a given statefile version once
821 if (!Glib::file_test (backup_path, Glib::FILE_TEST_EXISTS)) {
823 VersionMismatch (xmlpath, backup_path);
825 if (!copy_file (xmlpath, backup_path)) {;
835 Session::load_options (const XMLNode& node)
837 LocaleGuard lg (X_("POSIX"));
838 config.set_variables (node);
849 Session::get_template()
851 /* if we don't disable rec-enable, diskstreams
852 will believe they need to store their capture
853 sources in their state node.
856 disable_record (false);
862 Session::state (bool full_state)
864 XMLNode* node = new XMLNode("Session");
868 snprintf(buf, sizeof(buf), "%d", CURRENT_SESSION_FILE_VERSION);
869 node->add_property("version", buf);
871 /* store configuration settings */
875 node->add_property ("name", _name);
876 snprintf (buf, sizeof (buf), "%" PRId64, _nominal_frame_rate);
877 node->add_property ("sample-rate", buf);
879 if (session_dirs.size() > 1) {
883 vector<space_and_path>::iterator i = session_dirs.begin();
884 vector<space_and_path>::iterator next;
886 ++i; /* skip the first one */
890 while (i != session_dirs.end()) {
894 if (next != session_dirs.end()) {
904 child = node->add_child ("Path");
905 child->add_content (p);
909 /* save the ID counter */
911 snprintf (buf, sizeof (buf), "%" PRIu64, ID::counter());
912 node->add_property ("id-counter", buf);
914 /* save the event ID counter */
916 snprintf (buf, sizeof (buf), "%d", Evoral::event_id_counter());
917 node->add_property ("event-counter", buf);
919 /* various options */
921 list<XMLNode*> midi_port_nodes = _midi_ports->get_midi_port_states();
922 if (!midi_port_nodes.empty()) {
923 XMLNode* midi_port_stuff = new XMLNode ("MIDIPorts");
924 for (list<XMLNode*>::const_iterator n = midi_port_nodes.begin(); n != midi_port_nodes.end(); ++n) {
925 midi_port_stuff->add_child_nocopy (**n);
927 node->add_child_nocopy (*midi_port_stuff);
930 node->add_child_nocopy (config.get_variables ());
932 node->add_child_nocopy (ARDOUR::SessionMetadata::Metadata()->get_state());
934 child = node->add_child ("Sources");
937 Glib::Threads::Mutex::Lock sl (source_lock);
939 for (SourceMap::iterator siter = sources.begin(); siter != sources.end(); ++siter) {
941 /* Don't save information about non-file Sources, or
942 * about non-destructive file sources that are empty
943 * and unused by any regions.
946 boost::shared_ptr<FileSource> fs;
948 if ((fs = boost::dynamic_pointer_cast<FileSource> (siter->second)) != 0) {
950 if (!fs->destructive()) {
951 if (fs->empty() && !fs->used()) {
956 child->add_child_nocopy (siter->second->get_state());
961 child = node->add_child ("Regions");
964 Glib::Threads::Mutex::Lock rl (region_lock);
965 const RegionFactory::RegionMap& region_map (RegionFactory::all_regions());
966 for (RegionFactory::RegionMap::const_iterator i = region_map.begin(); i != region_map.end(); ++i) {
967 boost::shared_ptr<Region> r = i->second;
968 /* only store regions not attached to playlists */
969 if (r->playlist() == 0) {
970 if (boost::dynamic_pointer_cast<AudioRegion>(r)) {
971 child->add_child_nocopy ((boost::dynamic_pointer_cast<AudioRegion>(r))->get_basic_state ());
973 child->add_child_nocopy (r->get_state ());
978 RegionFactory::CompoundAssociations& cassocs (RegionFactory::compound_associations());
980 if (!cassocs.empty()) {
981 XMLNode* ca = node->add_child (X_("CompoundAssociations"));
983 for (RegionFactory::CompoundAssociations::iterator i = cassocs.begin(); i != cassocs.end(); ++i) {
985 XMLNode* can = new XMLNode (X_("CompoundAssociation"));
986 i->first->id().print (buf, sizeof (buf));
987 can->add_property (X_("copy"), buf);
988 i->second->id().print (buf, sizeof (buf));
989 can->add_property (X_("original"), buf);
990 ca->add_child_nocopy (*can);
996 node->add_child_nocopy (_locations->get_state());
998 // for a template, just create a new Locations, populate it
999 // with the default start and end, and get the state for that.
1000 Locations loc (*this);
1001 Location* range = new Location (*this, 0, 0, _("session"), Location::IsSessionRange);
1002 range->set (max_framepos, 0);
1004 node->add_child_nocopy (loc.get_state());
1007 child = node->add_child ("Bundles");
1009 boost::shared_ptr<BundleList> bundles = _bundles.reader ();
1010 for (BundleList::iterator i = bundles->begin(); i != bundles->end(); ++i) {
1011 boost::shared_ptr<UserBundle> b = boost::dynamic_pointer_cast<UserBundle> (*i);
1013 child->add_child_nocopy (b->get_state());
1018 child = node->add_child ("Routes");
1020 boost::shared_ptr<RouteList> r = routes.reader ();
1022 RoutePublicOrderSorter cmp;
1023 RouteList public_order (*r);
1024 public_order.sort (cmp);
1026 /* the sort should have put control outs first */
1029 assert (_monitor_out == public_order.front());
1032 for (RouteList::iterator i = public_order.begin(); i != public_order.end(); ++i) {
1033 if (!(*i)->is_auditioner()) {
1035 child->add_child_nocopy ((*i)->get_state());
1037 child->add_child_nocopy ((*i)->get_template());
1043 playlists->add_state (node, full_state);
1045 child = node->add_child ("RouteGroups");
1046 for (list<RouteGroup *>::iterator i = _route_groups.begin(); i != _route_groups.end(); ++i) {
1047 child->add_child_nocopy ((*i)->get_state());
1051 XMLNode* gain_child = node->add_child ("Click");
1052 gain_child->add_child_nocopy (_click_io->state (full_state));
1053 gain_child->add_child_nocopy (_click_gain->state (full_state));
1057 XMLNode* ltc_input_child = node->add_child ("LTC-In");
1058 ltc_input_child->add_child_nocopy (_ltc_input->state (full_state));
1062 XMLNode* ltc_output_child = node->add_child ("LTC-Out");
1063 ltc_output_child->add_child_nocopy (_ltc_output->state (full_state));
1066 node->add_child_nocopy (_speakers->get_state());
1067 node->add_child_nocopy (_tempo_map->get_state());
1068 node->add_child_nocopy (get_control_protocol_state());
1071 node->add_child_copy (*_extra_xml);
1078 Session::get_control_protocol_state ()
1080 ControlProtocolManager& cpm (ControlProtocolManager::instance());
1081 return cpm.get_state();
1085 Session::set_state (const XMLNode& node, int version)
1089 const XMLProperty* prop;
1092 _state_of_the_state = StateOfTheState (_state_of_the_state|CannotSave);
1094 if (node.name() != X_("Session")) {
1095 fatal << _("programming error: Session: incorrect XML node sent to set_state()") << endmsg;
1099 if ((prop = node.property ("name")) != 0) {
1100 _name = prop->value ();
1103 if ((prop = node.property (X_("sample-rate"))) != 0) {
1105 _nominal_frame_rate = atoi (prop->value());
1107 if (_nominal_frame_rate != _current_frame_rate) {
1108 boost::optional<int> r = AskAboutSampleRateMismatch (_nominal_frame_rate, _current_frame_rate);
1109 if (r.get_value_or (0)) {
1115 setup_raid_path(_session_dir->root_path());
1117 if ((prop = node.property (X_("id-counter"))) != 0) {
1119 sscanf (prop->value().c_str(), "%" PRIu64, &x);
1120 ID::init_counter (x);
1122 /* old sessions used a timebased counter, so fake
1123 the startup ID counter based on a standard
1128 ID::init_counter (now);
1131 if ((prop = node.property (X_("event-counter"))) != 0) {
1132 Evoral::init_event_id_counter (atoi (prop->value()));
1136 if ((child = find_named_node (node, "MIDIPorts")) != 0) {
1137 _midi_ports->set_midi_port_states (child->children());
1140 IO::disable_connecting ();
1142 Stateful::save_extra_xml (node);
1144 if (((child = find_named_node (node, "Options")) != 0)) { /* old style */
1145 load_options (*child);
1146 } else if ((child = find_named_node (node, "Config")) != 0) { /* new style */
1147 load_options (*child);
1149 error << _("Session: XML state has no options section") << endmsg;
1152 if (version >= 3000) {
1153 if ((child = find_named_node (node, "Metadata")) == 0) {
1154 warning << _("Session: XML state has no metadata section") << endmsg;
1155 } else if ( ARDOUR::SessionMetadata::Metadata()->set_state (*child, version) ) {
1160 if ((child = find_named_node (node, X_("Speakers"))) != 0) {
1161 _speakers->set_state (*child, version);
1164 if ((child = find_named_node (node, "Sources")) == 0) {
1165 error << _("Session: XML state has no sources section") << endmsg;
1167 } else if (load_sources (*child)) {
1171 if ((child = find_named_node (node, "TempoMap")) == 0) {
1172 error << _("Session: XML state has no Tempo Map section") << endmsg;
1174 } else if (_tempo_map->set_state (*child, version)) {
1178 if ((child = find_named_node (node, "Locations")) == 0) {
1179 error << _("Session: XML state has no locations section") << endmsg;
1181 } else if (_locations->set_state (*child, version)) {
1187 if ((location = _locations->auto_loop_location()) != 0) {
1188 set_auto_loop_location (location);
1191 if ((location = _locations->auto_punch_location()) != 0) {
1192 set_auto_punch_location (location);
1195 if ((location = _locations->session_range_location()) != 0) {
1196 delete _session_range_location;
1197 _session_range_location = location;
1200 if (_session_range_location) {
1201 AudioFileSource::set_header_position_offset (_session_range_location->start());
1204 if ((child = find_named_node (node, "Regions")) == 0) {
1205 error << _("Session: XML state has no Regions section") << endmsg;
1207 } else if (load_regions (*child)) {
1211 if ((child = find_named_node (node, "Playlists")) == 0) {
1212 error << _("Session: XML state has no playlists section") << endmsg;
1214 } else if (playlists->load (*this, *child)) {
1218 if ((child = find_named_node (node, "UnusedPlaylists")) == 0) {
1220 } else if (playlists->load_unused (*this, *child)) {
1224 if ((child = find_named_node (node, "CompoundAssociations")) != 0) {
1225 if (load_compounds (*child)) {
1230 if (version >= 3000) {
1231 if ((child = find_named_node (node, "Bundles")) == 0) {
1232 warning << _("Session: XML state has no bundles section") << endmsg;
1235 /* We can't load Bundles yet as they need to be able
1236 to convert from port names to Port objects, which can't happen until
1238 _bundle_xml_node = new XMLNode (*child);
1242 if (version < 3000) {
1243 if ((child = find_named_node (node, X_("DiskStreams"))) == 0) {
1244 error << _("Session: XML state has no diskstreams section") << endmsg;
1246 } else if (load_diskstreams_2X (*child, version)) {
1251 if ((child = find_named_node (node, "Routes")) == 0) {
1252 error << _("Session: XML state has no routes section") << endmsg;
1254 } else if (load_routes (*child, version)) {
1258 /* our diskstreams list is no longer needed as they are now all owned by their Route */
1259 _diskstreams_2X.clear ();
1261 if (version >= 3000) {
1263 if ((child = find_named_node (node, "RouteGroups")) == 0) {
1264 error << _("Session: XML state has no route groups section") << endmsg;
1266 } else if (load_route_groups (*child, version)) {
1270 } else if (version < 3000) {
1272 if ((child = find_named_node (node, "EditGroups")) == 0) {
1273 error << _("Session: XML state has no edit groups section") << endmsg;
1275 } else if (load_route_groups (*child, version)) {
1279 if ((child = find_named_node (node, "MixGroups")) == 0) {
1280 error << _("Session: XML state has no mix groups section") << endmsg;
1282 } else if (load_route_groups (*child, version)) {
1287 if ((child = find_named_node (node, "Click")) == 0) {
1288 warning << _("Session: XML state has no click section") << endmsg;
1289 } else if (_click_io) {
1290 const XMLNodeList& children (child->children());
1291 XMLNodeList::const_iterator i = children.begin();
1292 _click_io->set_state (**i, version);
1294 if (i != children.end()) {
1295 _click_gain->set_state (**i, version);
1299 if ((child = find_named_node (node, ControlProtocolManager::state_node_name)) != 0) {
1300 ControlProtocolManager::instance().set_state (*child, version);
1303 update_have_rec_enabled_track ();
1305 /* here beginneth the second phase ... */
1307 StateReady (); /* EMIT SIGNAL */
1316 Session::load_routes (const XMLNode& node, int version)
1319 XMLNodeConstIterator niter;
1320 RouteList new_routes;
1322 nlist = node.children();
1326 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1328 boost::shared_ptr<Route> route;
1329 if (version < 3000) {
1330 route = XMLRouteFactory_2X (**niter, version);
1332 route = XMLRouteFactory (**niter, version);
1336 error << _("Session: cannot create Route from XML description.") << endmsg;
1340 BootMessage (string_compose (_("Loaded track/bus %1"), route->name()));
1342 new_routes.push_back (route);
1345 add_routes (new_routes, false, false, false);
1350 boost::shared_ptr<Route>
1351 Session::XMLRouteFactory (const XMLNode& node, int version)
1353 boost::shared_ptr<Route> ret;
1355 if (node.name() != "Route") {
1359 XMLNode* ds_child = find_named_node (node, X_("Diskstream"));
1361 DataType type = DataType::AUDIO;
1362 const XMLProperty* prop = node.property("default-type");
1365 type = DataType (prop->value());
1368 assert (type != DataType::NIL);
1372 boost::shared_ptr<Track> track;
1374 if (type == DataType::AUDIO) {
1375 track.reset (new AudioTrack (*this, X_("toBeResetFroXML")));
1377 track.reset (new MidiTrack (*this, X_("toBeResetFroXML")));
1380 if (track->init()) {
1384 if (track->set_state (node, version)) {
1388 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
1389 // boost_debug_shared_ptr_mark_interesting (track.get(), "Track");
1394 boost::shared_ptr<Route> r (new Route (*this, X_("toBeResetFroXML")));
1396 if (r->init () == 0 && r->set_state (node, version) == 0) {
1397 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
1398 // boost_debug_shared_ptr_mark_interesting (r.get(), "Route");
1407 boost::shared_ptr<Route>
1408 Session::XMLRouteFactory_2X (const XMLNode& node, int version)
1410 boost::shared_ptr<Route> ret;
1412 if (node.name() != "Route") {
1416 XMLProperty const * ds_prop = node.property (X_("diskstream-id"));
1418 ds_prop = node.property (X_("diskstream"));
1421 DataType type = DataType::AUDIO;
1422 const XMLProperty* prop = node.property("default-type");
1425 type = DataType (prop->value());
1428 assert (type != DataType::NIL);
1432 list<boost::shared_ptr<Diskstream> >::iterator i = _diskstreams_2X.begin ();
1433 while (i != _diskstreams_2X.end() && (*i)->id() != ds_prop->value()) {
1437 if (i == _diskstreams_2X.end()) {
1438 error << _("Could not find diskstream for route") << endmsg;
1439 return boost::shared_ptr<Route> ();
1442 boost::shared_ptr<Track> track;
1444 if (type == DataType::AUDIO) {
1445 track.reset (new AudioTrack (*this, X_("toBeResetFroXML")));
1447 track.reset (new MidiTrack (*this, X_("toBeResetFroXML")));
1450 if (track->init()) {
1454 if (track->set_state (node, version)) {
1458 track->set_diskstream (*i);
1460 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
1461 // boost_debug_shared_ptr_mark_interesting (track.get(), "Track");
1466 boost::shared_ptr<Route> r (new Route (*this, X_("toBeResetFroXML")));
1468 if (r->init () == 0 && r->set_state (node, version) == 0) {
1469 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
1470 // boost_debug_shared_ptr_mark_interesting (r.get(), "Route");
1480 Session::load_regions (const XMLNode& node)
1483 XMLNodeConstIterator niter;
1484 boost::shared_ptr<Region> region;
1486 nlist = node.children();
1490 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1491 if ((region = XMLRegionFactory (**niter, false)) == 0) {
1492 error << _("Session: cannot create Region from XML description.");
1493 const XMLProperty *name = (**niter).property("name");
1496 error << " " << string_compose (_("Can not load state for region '%1'"), name->value());
1507 Session::load_compounds (const XMLNode& node)
1509 XMLNodeList calist = node.children();
1510 XMLNodeConstIterator caiter;
1511 XMLProperty *caprop;
1513 for (caiter = calist.begin(); caiter != calist.end(); ++caiter) {
1514 XMLNode* ca = *caiter;
1518 if ((caprop = ca->property (X_("original"))) == 0) {
1521 orig_id = caprop->value();
1523 if ((caprop = ca->property (X_("copy"))) == 0) {
1526 copy_id = caprop->value();
1528 boost::shared_ptr<Region> orig = RegionFactory::region_by_id (orig_id);
1529 boost::shared_ptr<Region> copy = RegionFactory::region_by_id (copy_id);
1531 if (!orig || !copy) {
1532 warning << string_compose (_("Regions in compound description not found (ID's %1 and %2): ignored"),
1538 RegionFactory::add_compound_association (orig, copy);
1545 Session::load_nested_sources (const XMLNode& node)
1548 XMLNodeConstIterator niter;
1550 nlist = node.children();
1552 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1553 if ((*niter)->name() == "Source") {
1555 /* it may already exist, so don't recreate it unnecessarily
1558 XMLProperty* prop = (*niter)->property (X_("id"));
1560 error << _("Nested source has no ID info in session file! (ignored)") << endmsg;
1564 ID source_id (prop->value());
1566 if (!source_by_id (source_id)) {
1569 SourceFactory::create (*this, **niter, true);
1571 catch (failed_constructor& err) {
1572 error << string_compose (_("Cannot reconstruct nested source for region %1"), name()) << endmsg;
1579 boost::shared_ptr<Region>
1580 Session::XMLRegionFactory (const XMLNode& node, bool full)
1582 const XMLProperty* type = node.property("type");
1586 const XMLNodeList& nlist = node.children();
1588 for (XMLNodeConstIterator niter = nlist.begin(); niter != nlist.end(); ++niter) {
1589 XMLNode *child = (*niter);
1590 if (child->name() == "NestedSource") {
1591 load_nested_sources (*child);
1595 if (!type || type->value() == "audio") {
1596 return boost::shared_ptr<Region>(XMLAudioRegionFactory (node, full));
1597 } else if (type->value() == "midi") {
1598 return boost::shared_ptr<Region>(XMLMidiRegionFactory (node, full));
1601 } catch (failed_constructor& err) {
1602 return boost::shared_ptr<Region> ();
1605 return boost::shared_ptr<Region> ();
1608 boost::shared_ptr<AudioRegion>
1609 Session::XMLAudioRegionFactory (const XMLNode& node, bool /*full*/)
1611 const XMLProperty* prop;
1612 boost::shared_ptr<Source> source;
1613 boost::shared_ptr<AudioSource> as;
1615 SourceList master_sources;
1616 uint32_t nchans = 1;
1619 if (node.name() != X_("Region")) {
1620 return boost::shared_ptr<AudioRegion>();
1623 if ((prop = node.property (X_("channels"))) != 0) {
1624 nchans = atoi (prop->value().c_str());
1627 if ((prop = node.property ("name")) == 0) {
1628 cerr << "no name for this region\n";
1632 if ((prop = node.property (X_("source-0"))) == 0) {
1633 if ((prop = node.property ("source")) == 0) {
1634 error << _("Session: XMLNode describing a AudioRegion is incomplete (no source)") << endmsg;
1635 return boost::shared_ptr<AudioRegion>();
1639 PBD::ID s_id (prop->value());
1641 if ((source = source_by_id (s_id)) == 0) {
1642 error << string_compose(_("Session: XMLNode describing a AudioRegion references an unknown source id =%1"), s_id) << endmsg;
1643 return boost::shared_ptr<AudioRegion>();
1646 as = boost::dynamic_pointer_cast<AudioSource>(source);
1648 error << string_compose(_("Session: XMLNode describing a AudioRegion references a non-audio source id =%1"), s_id) << endmsg;
1649 return boost::shared_ptr<AudioRegion>();
1652 sources.push_back (as);
1654 /* pickup other channels */
1656 for (uint32_t n=1; n < nchans; ++n) {
1657 snprintf (buf, sizeof(buf), X_("source-%d"), n);
1658 if ((prop = node.property (buf)) != 0) {
1660 PBD::ID id2 (prop->value());
1662 if ((source = source_by_id (id2)) == 0) {
1663 error << string_compose(_("Session: XMLNode describing a AudioRegion references an unknown source id =%1"), id2) << endmsg;
1664 return boost::shared_ptr<AudioRegion>();
1667 as = boost::dynamic_pointer_cast<AudioSource>(source);
1669 error << string_compose(_("Session: XMLNode describing a AudioRegion references a non-audio source id =%1"), id2) << endmsg;
1670 return boost::shared_ptr<AudioRegion>();
1672 sources.push_back (as);
1676 for (uint32_t n = 0; n < nchans; ++n) {
1677 snprintf (buf, sizeof(buf), X_("master-source-%d"), n);
1678 if ((prop = node.property (buf)) != 0) {
1680 PBD::ID id2 (prop->value());
1682 if ((source = source_by_id (id2)) == 0) {
1683 error << string_compose(_("Session: XMLNode describing a AudioRegion references an unknown source id =%1"), id2) << endmsg;
1684 return boost::shared_ptr<AudioRegion>();
1687 as = boost::dynamic_pointer_cast<AudioSource>(source);
1689 error << string_compose(_("Session: XMLNode describing a AudioRegion references a non-audio source id =%1"), id2) << endmsg;
1690 return boost::shared_ptr<AudioRegion>();
1692 master_sources.push_back (as);
1697 boost::shared_ptr<AudioRegion> region (boost::dynamic_pointer_cast<AudioRegion> (RegionFactory::create (sources, node)));
1699 /* a final detail: this is the one and only place that we know how long missing files are */
1701 if (region->whole_file()) {
1702 for (SourceList::iterator sx = sources.begin(); sx != sources.end(); ++sx) {
1703 boost::shared_ptr<SilentFileSource> sfp = boost::dynamic_pointer_cast<SilentFileSource> (*sx);
1705 sfp->set_length (region->length());
1710 if (!master_sources.empty()) {
1711 if (master_sources.size() != nchans) {
1712 error << _("Session: XMLNode describing an AudioRegion is missing some master sources; ignored") << endmsg;
1714 region->set_master_sources (master_sources);
1722 catch (failed_constructor& err) {
1723 return boost::shared_ptr<AudioRegion>();
1727 boost::shared_ptr<MidiRegion>
1728 Session::XMLMidiRegionFactory (const XMLNode& node, bool /*full*/)
1730 const XMLProperty* prop;
1731 boost::shared_ptr<Source> source;
1732 boost::shared_ptr<MidiSource> ms;
1735 if (node.name() != X_("Region")) {
1736 return boost::shared_ptr<MidiRegion>();
1739 if ((prop = node.property ("name")) == 0) {
1740 cerr << "no name for this region\n";
1744 if ((prop = node.property (X_("source-0"))) == 0) {
1745 if ((prop = node.property ("source")) == 0) {
1746 error << _("Session: XMLNode describing a MidiRegion is incomplete (no source)") << endmsg;
1747 return boost::shared_ptr<MidiRegion>();
1751 PBD::ID s_id (prop->value());
1753 if ((source = source_by_id (s_id)) == 0) {
1754 error << string_compose(_("Session: XMLNode describing a MidiRegion references an unknown source id =%1"), s_id) << endmsg;
1755 return boost::shared_ptr<MidiRegion>();
1758 ms = boost::dynamic_pointer_cast<MidiSource>(source);
1760 error << string_compose(_("Session: XMLNode describing a MidiRegion references a non-midi source id =%1"), s_id) << endmsg;
1761 return boost::shared_ptr<MidiRegion>();
1764 sources.push_back (ms);
1767 boost::shared_ptr<MidiRegion> region (boost::dynamic_pointer_cast<MidiRegion> (RegionFactory::create (sources, node)));
1768 /* a final detail: this is the one and only place that we know how long missing files are */
1770 if (region->whole_file()) {
1771 for (SourceList::iterator sx = sources.begin(); sx != sources.end(); ++sx) {
1772 boost::shared_ptr<SilentFileSource> sfp = boost::dynamic_pointer_cast<SilentFileSource> (*sx);
1774 sfp->set_length (region->length());
1782 catch (failed_constructor& err) {
1783 return boost::shared_ptr<MidiRegion>();
1788 Session::get_sources_as_xml ()
1791 XMLNode* node = new XMLNode (X_("Sources"));
1792 Glib::Threads::Mutex::Lock lm (source_lock);
1794 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ++i) {
1795 node->add_child_nocopy (i->second->get_state());
1802 Session::path_from_region_name (DataType type, string name, string identifier)
1804 char buf[PATH_MAX+1];
1806 SessionDirectory sdir(get_best_session_directory_for_new_source());
1807 std::string source_dir = ((type == DataType::AUDIO)
1808 ? sdir.sound_path() : sdir.midi_path());
1810 string ext = native_header_format_extension (config.get_native_file_header_format(), type);
1812 for (n = 0; n < 999999; ++n) {
1813 if (identifier.length()) {
1814 snprintf (buf, sizeof(buf), "%s%s%" PRIu32 "%s", name.c_str(),
1815 identifier.c_str(), n, ext.c_str());
1817 snprintf (buf, sizeof(buf), "%s-%" PRIu32 "%s", name.c_str(),
1821 std::string source_path = Glib::build_filename (source_dir, buf);
1823 if (!Glib::file_test (source_path, Glib::FILE_TEST_EXISTS)) {
1828 error << string_compose (_("cannot create new file from region name \"%1\" with ident = \"%2\": too many existing files with similar names"),
1837 Session::load_sources (const XMLNode& node)
1840 XMLNodeConstIterator niter;
1841 boost::shared_ptr<Source> source;
1843 nlist = node.children();
1847 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1850 if ((source = XMLSourceFactory (**niter)) == 0) {
1851 error << _("Session: cannot create Source from XML description.") << endmsg;
1854 } catch (MissingSource& err) {
1858 if (!no_questions_about_missing_files) {
1859 user_choice = MissingFile (this, err.path, err.type).get_value_or (-1);
1864 switch (user_choice) {
1866 /* user added a new search location, so try again */
1871 /* user asked to quit the entire session load
1876 no_questions_about_missing_files = true;
1880 no_questions_about_missing_files = true;
1885 warning << _("A sound file is missing. It will be replaced by silence.") << endmsg;
1886 source = SourceFactory::createSilent (*this, **niter, max_framecnt, _current_frame_rate);
1895 boost::shared_ptr<Source>
1896 Session::XMLSourceFactory (const XMLNode& node)
1898 if (node.name() != "Source") {
1899 return boost::shared_ptr<Source>();
1903 /* note: do peak building in another thread when loading session state */
1904 return SourceFactory::create (*this, node, true);
1907 catch (failed_constructor& err) {
1908 error << string_compose (_("Found a sound file that cannot be used by %1. Talk to the progammers."), PROGRAM_NAME) << endmsg;
1909 return boost::shared_ptr<Source>();
1914 Session::save_template (string template_name)
1918 if (_state_of_the_state & CannotSave) {
1922 std::string user_template_dir(user_template_directory());
1924 if (g_mkdir_with_parents (user_template_dir.c_str(), 0755) != 0) {
1925 error << string_compose(_("Could not create templates directory \"%1\" (%2)"),
1926 user_template_dir, g_strerror (errno)) << endmsg;
1930 tree.set_root (&get_template());
1932 std::string template_dir_path(user_template_dir);
1934 /* directory to put the template in */
1935 template_dir_path = Glib::build_filename (template_dir_path, template_name);
1937 if (Glib::file_test (template_dir_path, Glib::FILE_TEST_EXISTS)) {
1938 warning << string_compose(_("Template \"%1\" already exists - new version not created"),
1939 template_dir_path) << endmsg;
1943 if (g_mkdir_with_parents (template_dir_path.c_str(), 0755) != 0) {
1944 error << string_compose(_("Could not create directory for Session template\"%1\" (%2)"),
1945 template_dir_path, g_strerror (errno)) << endmsg;
1950 std::string template_file_path(template_dir_path);
1951 template_file_path = Glib::build_filename (template_file_path, template_name + template_suffix);
1953 if (!tree.write (template_file_path)) {
1954 error << _("template not saved") << endmsg;
1958 /* copy plugin state directory */
1960 std::string template_plugin_state_path(template_dir_path);
1961 template_plugin_state_path = Glib::build_filename (template_plugin_state_path, X_("plugins"));
1963 if (g_mkdir_with_parents (template_plugin_state_path.c_str(), 0755) != 0) {
1964 error << string_compose(_("Could not create directory for Session template plugin state\"%1\" (%2)"),
1965 template_plugin_state_path, g_strerror (errno)) << endmsg;
1969 copy_files (plugins_dir(), template_plugin_state_path);
1975 Session::refresh_disk_space ()
1977 #if __APPLE__ || (HAVE_SYS_VFS_H && HAVE_SYS_STATVFS_H)
1979 Glib::Threads::Mutex::Lock lm (space_lock);
1981 /* get freespace on every FS that is part of the session path */
1983 _total_free_4k_blocks = 0;
1984 _total_free_4k_blocks_uncertain = false;
1986 for (vector<space_and_path>::iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
1988 struct statfs statfsbuf;
1989 statfs (i->path.c_str(), &statfsbuf);
1991 double const scale = statfsbuf.f_bsize / 4096.0;
1993 /* See if this filesystem is read-only */
1994 struct statvfs statvfsbuf;
1995 statvfs (i->path.c_str(), &statvfsbuf);
1997 /* f_bavail can be 0 if it is undefined for whatever
1998 filesystem we are looking at; Samba shares mounted
1999 via GVFS are an example of this.
2001 if (statfsbuf.f_bavail == 0) {
2002 /* block count unknown */
2004 i->blocks_unknown = true;
2005 } else if (statvfsbuf.f_flag & ST_RDONLY) {
2006 /* read-only filesystem */
2008 i->blocks_unknown = false;
2010 /* read/write filesystem with known space */
2011 i->blocks = (uint32_t) floor (statfsbuf.f_bavail * scale);
2012 i->blocks_unknown = false;
2015 _total_free_4k_blocks += i->blocks;
2016 if (i->blocks_unknown) {
2017 _total_free_4k_blocks_uncertain = true;
2024 Session::get_best_session_directory_for_new_source ()
2026 vector<space_and_path>::iterator i;
2027 string result = _session_dir->root_path();
2029 /* handle common case without system calls */
2031 if (session_dirs.size() == 1) {
2035 /* OK, here's the algorithm we're following here:
2037 We want to select which directory to use for
2038 the next file source to be created. Ideally,
2039 we'd like to use a round-robin process so as to
2040 get maximum performance benefits from splitting
2041 the files across multiple disks.
2043 However, in situations without much diskspace, an
2044 RR approach may end up filling up a filesystem
2045 with new files while others still have space.
2046 Its therefore important to pay some attention to
2047 the freespace in the filesystem holding each
2048 directory as well. However, if we did that by
2049 itself, we'd keep creating new files in the file
2050 system with the most space until it was as full
2051 as all others, thus negating any performance
2052 benefits of this RAID-1 like approach.
2054 So, we use a user-configurable space threshold. If
2055 there are at least 2 filesystems with more than this
2056 much space available, we use RR selection between them.
2057 If not, then we pick the filesystem with the most space.
2059 This gets a good balance between the two
2063 refresh_disk_space ();
2065 int free_enough = 0;
2067 for (i = session_dirs.begin(); i != session_dirs.end(); ++i) {
2068 if ((*i).blocks * 4096 >= Config->get_disk_choice_space_threshold()) {
2073 if (free_enough >= 2) {
2074 /* use RR selection process, ensuring that the one
2078 i = last_rr_session_dir;
2081 if (++i == session_dirs.end()) {
2082 i = session_dirs.begin();
2085 if ((*i).blocks * 4096 >= Config->get_disk_choice_space_threshold()) {
2086 SessionDirectory sdir(i->path);
2087 if (sdir.create ()) {
2089 last_rr_session_dir = i;
2094 } while (i != last_rr_session_dir);
2098 /* pick FS with the most freespace (and that
2099 seems to actually work ...)
2102 vector<space_and_path> sorted;
2103 space_and_path_ascending_cmp cmp;
2105 sorted = session_dirs;
2106 sort (sorted.begin(), sorted.end(), cmp);
2108 for (i = sorted.begin(); i != sorted.end(); ++i) {
2109 SessionDirectory sdir(i->path);
2110 if (sdir.create ()) {
2112 last_rr_session_dir = i;
2122 Session::automation_dir () const
2124 return Glib::build_filename (_path, "automation");
2128 Session::analysis_dir () const
2130 return Glib::build_filename (_path, "analysis");
2134 Session::plugins_dir () const
2136 return Glib::build_filename (_path, "plugins");
2140 Session::externals_dir () const
2142 return Glib::build_filename (_path, "externals");
2146 Session::load_bundles (XMLNode const & node)
2148 XMLNodeList nlist = node.children();
2149 XMLNodeConstIterator niter;
2153 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2154 if ((*niter)->name() == "InputBundle") {
2155 add_bundle (boost::shared_ptr<UserBundle> (new UserBundle (**niter, true)));
2156 } else if ((*niter)->name() == "OutputBundle") {
2157 add_bundle (boost::shared_ptr<UserBundle> (new UserBundle (**niter, false)));
2159 error << string_compose(_("Unknown node \"%1\" found in Bundles list from session file"), (*niter)->name()) << endmsg;
2168 Session::load_route_groups (const XMLNode& node, int version)
2170 XMLNodeList nlist = node.children();
2171 XMLNodeConstIterator niter;
2175 if (version >= 3000) {
2177 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2178 if ((*niter)->name() == "RouteGroup") {
2179 RouteGroup* rg = new RouteGroup (*this, "");
2180 add_route_group (rg);
2181 rg->set_state (**niter, version);
2185 } else if (version < 3000) {
2187 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2188 if ((*niter)->name() == "EditGroup" || (*niter)->name() == "MixGroup") {
2189 RouteGroup* rg = new RouteGroup (*this, "");
2190 add_route_group (rg);
2191 rg->set_state (**niter, version);
2200 Session::auto_save()
2202 save_state (_current_snapshot_name);
2206 state_file_filter (const string &str, void */*arg*/)
2208 return (str.length() > strlen(statefile_suffix) &&
2209 str.find (statefile_suffix) == (str.length() - strlen (statefile_suffix)));
2213 bool operator()(const string* a, const string* b) {
2219 remove_end(string* state)
2221 string statename(*state);
2223 string::size_type start,end;
2224 if ((start = statename.find_last_of (G_DIR_SEPARATOR)) != string::npos) {
2225 statename = statename.substr (start+1);
2228 if ((end = statename.rfind(".ardour")) == string::npos) {
2229 end = statename.length();
2232 return new string(statename.substr (0, end));
2236 Session::possible_states (string path)
2238 PathScanner scanner;
2239 vector<string*>* states = scanner (path, state_file_filter, 0, false, false);
2241 transform(states->begin(), states->end(), states->begin(), remove_end);
2244 sort (states->begin(), states->end(), cmp);
2250 Session::possible_states () const
2252 return possible_states(_path);
2256 Session::add_route_group (RouteGroup* g)
2258 _route_groups.push_back (g);
2259 route_group_added (g); /* EMIT SIGNAL */
2261 g->RouteAdded.connect_same_thread (*this, boost::bind (&Session::route_added_to_route_group, this, _1, _2));
2262 g->RouteRemoved.connect_same_thread (*this, boost::bind (&Session::route_removed_from_route_group, this, _1, _2));
2263 g->PropertyChanged.connect_same_thread (*this, boost::bind (&Session::route_group_property_changed, this, g));
2269 Session::remove_route_group (RouteGroup& rg)
2271 list<RouteGroup*>::iterator i;
2273 if ((i = find (_route_groups.begin(), _route_groups.end(), &rg)) != _route_groups.end()) {
2274 _route_groups.erase (i);
2277 route_group_removed (); /* EMIT SIGNAL */
2281 /** Set a new order for our route groups, without adding or removing any.
2282 * @param groups Route group list in the new order.
2285 Session::reorder_route_groups (list<RouteGroup*> groups)
2287 _route_groups = groups;
2289 route_groups_reordered (); /* EMIT SIGNAL */
2295 Session::route_group_by_name (string name)
2297 list<RouteGroup *>::iterator i;
2299 for (i = _route_groups.begin(); i != _route_groups.end(); ++i) {
2300 if ((*i)->name() == name) {
2308 Session::all_route_group() const
2310 return *_all_route_group;
2314 Session::add_commands (vector<Command*> const & cmds)
2316 for (vector<Command*>::const_iterator i = cmds.begin(); i != cmds.end(); ++i) {
2322 Session::begin_reversible_command (const string& name)
2324 begin_reversible_command (g_quark_from_string (name.c_str ()));
2327 /** Begin a reversible command using a GQuark to identify it.
2328 * begin_reversible_command() and commit_reversible_command() calls may be nested,
2329 * but there must be as many begin...()s as there are commit...()s.
2332 Session::begin_reversible_command (GQuark q)
2334 /* If nested begin/commit pairs are used, we create just one UndoTransaction
2335 to hold all the commands that are committed. This keeps the order of
2336 commands correct in the history.
2339 if (_current_trans == 0) {
2340 /* start a new transaction */
2341 assert (_current_trans_quarks.empty ());
2342 _current_trans = new UndoTransaction();
2343 _current_trans->set_name (g_quark_to_string (q));
2346 _current_trans_quarks.push_front (q);
2350 Session::commit_reversible_command (Command *cmd)
2352 assert (_current_trans);
2353 assert (!_current_trans_quarks.empty ());
2358 _current_trans->add_command (cmd);
2361 _current_trans_quarks.pop_front ();
2363 if (!_current_trans_quarks.empty ()) {
2364 /* the transaction we're committing is not the top-level one */
2368 if (_current_trans->empty()) {
2369 /* no commands were added to the transaction, so just get rid of it */
2370 delete _current_trans;
2375 gettimeofday (&now, 0);
2376 _current_trans->set_timestamp (now);
2378 _history.add (_current_trans);
2383 accept_all_audio_files (const string& path, void */*arg*/)
2385 if (!Glib::file_test (path, Glib::FILE_TEST_IS_REGULAR)) {
2389 if (!AudioFileSource::safe_audio_file_extension (path)) {
2397 accept_all_midi_files (const string& path, void */*arg*/)
2399 if (!Glib::file_test (path, Glib::FILE_TEST_IS_REGULAR)) {
2403 return ((path.length() > 4 && path.find (".mid") != (path.length() - 4)) ||
2404 (path.length() > 4 && path.find (".smf") != (path.length() - 4)) ||
2405 (path.length() > 5 && path.find (".midi") != (path.length() - 5)));
2409 accept_all_state_files (const string& path, void */*arg*/)
2411 if (!Glib::file_test (path, Glib::FILE_TEST_IS_REGULAR)) {
2415 return (path.length() > 7 && path.find (".ardour") == (path.length() - 7));
2419 Session::find_all_sources (string path, set<string>& result)
2424 if (!tree.read (path)) {
2428 if ((node = find_named_node (*tree.root(), "Sources")) == 0) {
2433 XMLNodeConstIterator niter;
2435 nlist = node->children();
2439 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2443 if ((prop = (*niter)->property (X_("type"))) == 0) {
2447 DataType type (prop->value());
2449 if ((prop = (*niter)->property (X_("name"))) == 0) {
2453 if (Glib::path_is_absolute (prop->value())) {
2454 /* external file, ignore */
2462 if (FileSource::find (*this, type, prop->value(), true, is_new, chan, found_path)) {
2463 result.insert (found_path);
2471 Session::find_all_sources_across_snapshots (set<string>& result, bool exclude_this_snapshot)
2473 PathScanner scanner;
2474 vector<string*>* state_files;
2476 string this_snapshot_path;
2482 if (ripped[ripped.length()-1] == G_DIR_SEPARATOR) {
2483 ripped = ripped.substr (0, ripped.length() - 1);
2486 state_files = scanner (ripped, accept_all_state_files, (void *) 0, true, true);
2488 if (state_files == 0) {
2493 this_snapshot_path = _path;
2494 this_snapshot_path += legalize_for_path (_current_snapshot_name);
2495 this_snapshot_path += statefile_suffix;
2497 for (vector<string*>::iterator i = state_files->begin(); i != state_files->end(); ++i) {
2499 if (exclude_this_snapshot && **i == this_snapshot_path) {
2503 if (find_all_sources (**i, result) < 0) {
2511 struct RegionCounter {
2512 typedef std::map<PBD::ID,boost::shared_ptr<AudioSource> > AudioSourceList;
2513 AudioSourceList::iterator iter;
2514 boost::shared_ptr<Region> region;
2517 RegionCounter() : count (0) {}
2521 Session::ask_about_playlist_deletion (boost::shared_ptr<Playlist> p)
2523 boost::optional<int> r = AskAboutPlaylistDeletion (p);
2524 return r.get_value_or (1);
2528 Session::cleanup_regions ()
2530 const RegionFactory::RegionMap& regions (RegionFactory::regions());
2532 for (RegionFactory::RegionMap::const_iterator i = regions.begin(); i != regions.end(); ++i) {
2534 uint32_t used = playlists->region_use_count (i->second);
2536 if (used == 0 && !i->second->automatic ()) {
2537 RegionFactory::map_remove (i->second);
2541 /* dump the history list */
2548 Session::cleanup_sources (CleanupReport& rep)
2550 // FIXME: needs adaptation to midi
2552 vector<boost::shared_ptr<Source> > dead_sources;
2553 PathScanner scanner;
2556 vector<space_and_path>::iterator i;
2557 vector<space_and_path>::iterator nexti;
2558 vector<string*>* candidates;
2559 vector<string*>* candidates2;
2560 vector<string> unused;
2561 set<string> all_sources;
2566 _state_of_the_state = (StateOfTheState) (_state_of_the_state | InCleanup);
2568 /* consider deleting all unused playlists */
2570 if (playlists->maybe_delete_unused (boost::bind (Session::ask_about_playlist_deletion, _1))) {
2575 /* sync the "all regions" property of each playlist with its current state
2578 playlists->sync_all_regions_with_regions ();
2580 /* find all un-used sources */
2585 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ) {
2587 SourceMap::iterator tmp;
2592 /* do not bother with files that are zero size, otherwise we remove the current "nascent"
2596 if (!i->second->used() && (i->second->length(i->second->timeline_position() > 0))) {
2597 dead_sources.push_back (i->second);
2598 i->second->drop_references ();
2604 /* build a list of all the possible audio directories for the session */
2606 for (i = session_dirs.begin(); i != session_dirs.end(); ) {
2611 SessionDirectory sdir ((*i).path);
2612 audio_path += sdir.sound_path();
2614 if (nexti != session_dirs.end()) {
2622 /* build a list of all the possible midi directories for the session */
2624 for (i = session_dirs.begin(); i != session_dirs.end(); ) {
2629 SessionDirectory sdir ((*i).path);
2630 midi_path += sdir.midi_path();
2632 if (nexti != session_dirs.end()) {
2639 candidates = scanner (audio_path, accept_all_audio_files, (void *) 0, true, true);
2640 candidates2 = scanner (midi_path, accept_all_midi_files, (void *) 0, true, true);
2646 for (vector<string*>::iterator i = candidates2->begin(); i != candidates2->end(); ++i) {
2647 candidates->push_back (*i);
2652 candidates = candidates2; // might still be null
2655 /* find all sources, but don't use this snapshot because the
2656 state file on disk still references sources we may have already
2660 find_all_sources_across_snapshots (all_sources, true);
2662 /* add our current source list
2665 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ) {
2666 boost::shared_ptr<FileSource> fs;
2667 SourceMap::iterator tmp = i;
2670 if ((fs = boost::dynamic_pointer_cast<FileSource> (i->second)) != 0) {
2671 if (playlists->source_use_count (fs) != 0) {
2672 all_sources.insert (fs->path());
2675 /* we might not remove this source from disk, because it may be used
2676 by other snapshots, but its not being used in this version
2677 so lets get rid of it now, along with any representative regions
2681 RegionFactory::remove_regions_using_source (i->second);
2689 char tmppath1[PATH_MAX+1];
2690 char tmppath2[PATH_MAX+1];
2693 for (vector<string*>::iterator x = candidates->begin(); x != candidates->end(); ++x) {
2698 for (set<string>::iterator i = all_sources.begin(); i != all_sources.end(); ++i) {
2700 if (realpath(spath.c_str(), tmppath1) == 0) {
2701 error << string_compose (_("Cannot expand path %1 (%2)"),
2702 spath, strerror (errno)) << endmsg;
2706 if (realpath((*i).c_str(), tmppath2) == 0) {
2707 error << string_compose (_("Cannot expand path %1 (%2)"),
2708 (*i), strerror (errno)) << endmsg;
2712 if (strcmp(tmppath1, tmppath2) == 0) {
2719 unused.push_back (spath);
2728 /* now try to move all unused files into the "dead" directory(ies) */
2730 for (vector<string>::iterator x = unused.begin(); x != unused.end(); ++x) {
2731 struct stat statbuf;
2735 /* don't move the file across filesystems, just
2736 stick it in the `dead_dir_name' directory
2737 on whichever filesystem it was already on.
2740 if ((*x).find ("/sounds/") != string::npos) {
2742 /* old school, go up 1 level */
2744 newpath = Glib::path_get_dirname (*x); // "sounds"
2745 newpath = Glib::path_get_dirname (newpath); // "session-name"
2749 /* new school, go up 4 levels */
2751 newpath = Glib::path_get_dirname (*x); // "audiofiles" or "midifiles"
2752 newpath = Glib::path_get_dirname (newpath); // "session-name"
2753 newpath = Glib::path_get_dirname (newpath); // "interchange"
2754 newpath = Glib::path_get_dirname (newpath); // "session-dir"
2757 newpath = Glib::build_filename (newpath, dead_dir_name);
2759 if (g_mkdir_with_parents (newpath.c_str(), 0755) < 0) {
2760 error << string_compose(_("Session: cannot create dead file folder \"%1\" (%2)"), newpath, strerror (errno)) << endmsg;
2764 newpath = Glib::build_filename (newpath, Glib::path_get_basename ((*x)));
2766 if (Glib::file_test (newpath, Glib::FILE_TEST_EXISTS)) {
2768 /* the new path already exists, try versioning */
2770 char buf[PATH_MAX+1];
2774 snprintf (buf, sizeof (buf), "%s.%d", newpath.c_str(), version);
2777 while (Glib::file_test (newpath_v.c_str(), Glib::FILE_TEST_EXISTS) && version < 999) {
2778 snprintf (buf, sizeof (buf), "%s.%d", newpath.c_str(), ++version);
2782 if (version == 999) {
2783 error << string_compose (_("there are already 1000 files with names like %1; versioning discontinued"),
2787 newpath = newpath_v;
2792 /* it doesn't exist, or we can't read it or something */
2796 stat ((*x).c_str(), &statbuf);
2798 if (::rename ((*x).c_str(), newpath.c_str()) != 0) {
2799 error << string_compose (_("cannot rename unused file source from %1 to %2 (%3)"),
2800 (*x), newpath, strerror (errno))
2805 /* see if there an easy to find peakfile for this file, and remove it.
2808 string base = basename_nosuffix (*x);
2809 base += "%A"; /* this is what we add for the channel suffix of all native files,
2810 or for the first channel of embedded files. it will miss
2811 some peakfiles for other channels
2813 string peakpath = peak_path (base);
2815 if (Glib::file_test (peakpath.c_str(), Glib::FILE_TEST_EXISTS)) {
2816 if (::unlink (peakpath.c_str()) != 0) {
2817 error << string_compose (_("cannot remove peakfile %1 for %2 (%3)"),
2818 peakpath, _path, strerror (errno))
2820 /* try to back out */
2821 ::rename (newpath.c_str(), _path.c_str());
2826 rep.paths.push_back (*x);
2827 rep.space += statbuf.st_size;
2830 /* dump the history list */
2834 /* save state so we don't end up a session file
2835 referring to non-existent sources.
2842 _state_of_the_state = (StateOfTheState) (_state_of_the_state & ~InCleanup);
2848 Session::cleanup_trash_sources (CleanupReport& rep)
2850 // FIXME: needs adaptation for MIDI
2852 vector<space_and_path>::iterator i;
2858 for (i = session_dirs.begin(); i != session_dirs.end(); ++i) {
2860 dead_dir = Glib::build_filename ((*i).path, dead_dir_name);
2862 clear_directory (dead_dir, &rep.space, &rep.paths);
2869 Session::set_dirty ()
2871 bool was_dirty = dirty();
2873 _state_of_the_state = StateOfTheState (_state_of_the_state | Dirty);
2877 DirtyChanged(); /* EMIT SIGNAL */
2883 Session::set_clean ()
2885 bool was_dirty = dirty();
2887 _state_of_the_state = Clean;
2891 DirtyChanged(); /* EMIT SIGNAL */
2896 Session::set_deletion_in_progress ()
2898 _state_of_the_state = StateOfTheState (_state_of_the_state | Deletion);
2902 Session::clear_deletion_in_progress ()
2904 _state_of_the_state = StateOfTheState (_state_of_the_state & (~Deletion));
2908 Session::add_controllable (boost::shared_ptr<Controllable> c)
2910 /* this adds a controllable to the list managed by the Session.
2911 this is a subset of those managed by the Controllable class
2912 itself, and represents the only ones whose state will be saved
2913 as part of the session.
2916 Glib::Threads::Mutex::Lock lm (controllables_lock);
2917 controllables.insert (c);
2920 struct null_deleter { void operator()(void const *) const {} };
2923 Session::remove_controllable (Controllable* c)
2925 if (_state_of_the_state & Deletion) {
2929 Glib::Threads::Mutex::Lock lm (controllables_lock);
2931 Controllables::iterator x = controllables.find (boost::shared_ptr<Controllable>(c, null_deleter()));
2933 if (x != controllables.end()) {
2934 controllables.erase (x);
2938 boost::shared_ptr<Controllable>
2939 Session::controllable_by_id (const PBD::ID& id)
2941 Glib::Threads::Mutex::Lock lm (controllables_lock);
2943 for (Controllables::iterator i = controllables.begin(); i != controllables.end(); ++i) {
2944 if ((*i)->id() == id) {
2949 return boost::shared_ptr<Controllable>();
2952 boost::shared_ptr<Controllable>
2953 Session::controllable_by_descriptor (const ControllableDescriptor& desc)
2955 boost::shared_ptr<Controllable> c;
2956 boost::shared_ptr<Route> r;
2958 switch (desc.top_level_type()) {
2959 case ControllableDescriptor::NamedRoute:
2961 std::string str = desc.top_level_name();
2962 if (str == "master") {
2964 } else if (str == "control" || str == "listen") {
2967 r = route_by_name (desc.top_level_name());
2972 case ControllableDescriptor::RemoteControlID:
2973 r = route_by_remote_id (desc.rid());
2981 switch (desc.subtype()) {
2982 case ControllableDescriptor::Gain:
2983 c = r->gain_control ();
2986 case ControllableDescriptor::Solo:
2987 c = r->solo_control();
2990 case ControllableDescriptor::Mute:
2991 c = r->mute_control();
2994 case ControllableDescriptor::Recenable:
2996 boost::shared_ptr<Track> t = boost::dynamic_pointer_cast<Track>(r);
2999 c = t->rec_enable_control ();
3004 case ControllableDescriptor::PanDirection:
3006 c = r->pannable()->pan_azimuth_control;
3010 case ControllableDescriptor::PanWidth:
3012 c = r->pannable()->pan_width_control;
3016 case ControllableDescriptor::PanElevation:
3018 c = r->pannable()->pan_elevation_control;
3022 case ControllableDescriptor::Balance:
3023 /* XXX simple pan control */
3026 case ControllableDescriptor::PluginParameter:
3028 uint32_t plugin = desc.target (0);
3029 uint32_t parameter_index = desc.target (1);
3031 /* revert to zero based counting */
3037 if (parameter_index > 0) {
3041 boost::shared_ptr<Processor> p = r->nth_plugin (plugin);
3044 c = boost::dynamic_pointer_cast<ARDOUR::AutomationControl>(
3045 p->control(Evoral::Parameter(PluginAutomation, 0, parameter_index)));
3050 case ControllableDescriptor::SendGain:
3052 uint32_t send = desc.target (0);
3054 /* revert to zero-based counting */
3060 boost::shared_ptr<Processor> p = r->nth_send (send);
3063 boost::shared_ptr<Send> s = boost::dynamic_pointer_cast<Send>(p);
3064 boost::shared_ptr<Amp> a = s->amp();
3067 c = s->amp()->gain_control();
3074 /* relax and return a null pointer */
3082 Session::add_instant_xml (XMLNode& node, bool write_to_config)
3085 Stateful::add_instant_xml (node, _path);
3088 if (write_to_config) {
3089 Config->add_instant_xml (node);
3094 Session::instant_xml (const string& node_name)
3096 return Stateful::instant_xml (node_name, _path);
3100 Session::save_history (string snapshot_name)
3108 if (snapshot_name.empty()) {
3109 snapshot_name = _current_snapshot_name;
3112 const string history_filename = legalize_for_path (snapshot_name) + history_suffix;
3113 const string backup_filename = history_filename + backup_suffix;
3114 const std::string xml_path(Glib::build_filename (_session_dir->root_path(), history_filename));
3115 const std::string backup_path(Glib::build_filename (_session_dir->root_path(), backup_filename));
3117 if (Glib::file_test (xml_path, Glib::FILE_TEST_EXISTS)) {
3118 if (::g_rename (xml_path.c_str(), backup_path.c_str()) != 0) {
3119 error << _("could not backup old history file, current history not saved") << endmsg;
3124 if (!Config->get_save_history() || Config->get_saved_history_depth() < 0) {
3128 tree.set_root (&_history.get_state (Config->get_saved_history_depth()));
3130 if (!tree.write (xml_path))
3132 error << string_compose (_("history could not be saved to %1"), xml_path) << endmsg;
3134 if (g_remove (xml_path.c_str()) != 0) {
3135 error << string_compose(_("Could not remove history file at path \"%1\" (%2)"),
3136 xml_path, g_strerror (errno)) << endmsg;
3138 if (::g_rename (backup_path.c_str(), xml_path.c_str()) != 0) {
3139 error << string_compose (_("could not restore history file from backup %1 (%2)"),
3140 backup_path, g_strerror (errno)) << endmsg;
3150 Session::restore_history (string snapshot_name)
3154 if (snapshot_name.empty()) {
3155 snapshot_name = _current_snapshot_name;
3158 const std::string xml_filename = legalize_for_path (snapshot_name) + history_suffix;
3159 const std::string xml_path(Glib::build_filename (_session_dir->root_path(), xml_filename));
3161 info << "Loading history from " << xml_path << endmsg;
3163 if (!Glib::file_test (xml_path, Glib::FILE_TEST_EXISTS)) {
3164 info << string_compose (_("%1: no history file \"%2\" for this session."),
3165 _name, xml_path) << endmsg;
3169 if (!tree.read (xml_path)) {
3170 error << string_compose (_("Could not understand session history file \"%1\""),
3171 xml_path) << endmsg;
3178 for (XMLNodeConstIterator it = tree.root()->children().begin(); it != tree.root()->children().end(); it++) {
3181 UndoTransaction* ut = new UndoTransaction ();
3184 ut->set_name(t->property("name")->value());
3185 stringstream ss(t->property("tv-sec")->value());
3187 ss.str(t->property("tv-usec")->value());
3189 ut->set_timestamp(tv);
3191 for (XMLNodeConstIterator child_it = t->children().begin();
3192 child_it != t->children().end(); child_it++)
3194 XMLNode *n = *child_it;
3197 if (n->name() == "MementoCommand" ||
3198 n->name() == "MementoUndoCommand" ||
3199 n->name() == "MementoRedoCommand") {
3201 if ((c = memento_command_factory(n))) {
3205 } else if (n->name() == "NoteDiffCommand") {
3206 PBD::ID id (n->property("midi-source")->value());
3207 boost::shared_ptr<MidiSource> midi_source =
3208 boost::dynamic_pointer_cast<MidiSource, Source>(source_by_id(id));
3210 ut->add_command (new MidiModel::NoteDiffCommand(midi_source->model(), *n));
3212 error << _("Failed to downcast MidiSource for NoteDiffCommand") << endmsg;
3215 } else if (n->name() == "SysExDiffCommand") {
3217 PBD::ID id (n->property("midi-source")->value());
3218 boost::shared_ptr<MidiSource> midi_source =
3219 boost::dynamic_pointer_cast<MidiSource, Source>(source_by_id(id));
3221 ut->add_command (new MidiModel::SysExDiffCommand (midi_source->model(), *n));
3223 error << _("Failed to downcast MidiSource for SysExDiffCommand") << endmsg;
3226 } else if (n->name() == "PatchChangeDiffCommand") {
3228 PBD::ID id (n->property("midi-source")->value());
3229 boost::shared_ptr<MidiSource> midi_source =
3230 boost::dynamic_pointer_cast<MidiSource, Source>(source_by_id(id));
3232 ut->add_command (new MidiModel::PatchChangeDiffCommand (midi_source->model(), *n));
3234 error << _("Failed to downcast MidiSource for PatchChangeDiffCommand") << endmsg;
3237 } else if (n->name() == "StatefulDiffCommand") {
3238 if ((c = stateful_diff_command_factory (n))) {
3239 ut->add_command (c);
3242 error << string_compose(_("Couldn't figure out how to make a Command out of a %1 XMLNode."), n->name()) << endmsg;
3253 Session::config_changed (std::string p, bool ours)
3259 if (p == "seamless-loop") {
3261 } else if (p == "rf-speed") {
3263 } else if (p == "auto-loop") {
3265 } else if (p == "auto-input") {
3267 if (Config->get_monitoring_model() == HardwareMonitoring && transport_rolling()) {
3268 /* auto-input only makes a difference if we're rolling */
3269 set_track_monitor_input_status (!config.get_auto_input());
3272 } else if (p == "punch-in") {
3276 if ((location = _locations->auto_punch_location()) != 0) {
3278 if (config.get_punch_in ()) {
3279 replace_event (SessionEvent::PunchIn, location->start());
3281 remove_event (location->start(), SessionEvent::PunchIn);
3285 } else if (p == "punch-out") {
3289 if ((location = _locations->auto_punch_location()) != 0) {
3291 if (config.get_punch_out()) {
3292 replace_event (SessionEvent::PunchOut, location->end());
3294 clear_events (SessionEvent::PunchOut);
3298 } else if (p == "edit-mode") {
3300 Glib::Threads::Mutex::Lock lm (playlists->lock);
3302 for (SessionPlaylists::List::iterator i = playlists->playlists.begin(); i != playlists->playlists.end(); ++i) {
3303 (*i)->set_edit_mode (Config->get_edit_mode ());
3306 } else if (p == "use-video-sync") {
3308 waiting_for_sync_offset = config.get_use_video_sync();
3310 } else if (p == "mmc-control") {
3312 //poke_midi_thread ();
3314 } else if (p == "mmc-device-id" || p == "mmc-receive-id" || p == "mmc-receive-device-id") {
3316 _mmc->set_receive_device_id (Config->get_mmc_receive_device_id());
3318 } else if (p == "mmc-send-id" || p == "mmc-send-device-id") {
3320 _mmc->set_send_device_id (Config->get_mmc_send_device_id());
3322 } else if (p == "midi-control") {
3324 //poke_midi_thread ();
3326 } else if (p == "raid-path") {
3328 setup_raid_path (config.get_raid_path());
3330 } else if (p == "timecode-format") {
3334 } else if (p == "video-pullup") {
3338 } else if (p == "seamless-loop") {
3340 if (play_loop && transport_rolling()) {
3341 // to reset diskstreams etc
3342 request_play_loop (true);
3345 } else if (p == "rf-speed") {
3347 cumulative_rf_motion = 0;
3350 } else if (p == "click-sound") {
3352 setup_click_sounds (1);
3354 } else if (p == "click-emphasis-sound") {
3356 setup_click_sounds (-1);
3358 } else if (p == "clicking") {
3360 if (Config->get_clicking()) {
3361 if (_click_io && click_data) { // don't require emphasis data
3368 } else if (p == "click-gain") {
3371 _click_gain->set_gain (Config->get_click_gain(), this);
3374 } else if (p == "send-mtc") {
3376 if (Config->get_send_mtc ()) {
3377 /* mark us ready to send */
3378 next_quarter_frame_to_send = 0;
3381 } else if (p == "send-mmc") {
3383 _mmc->enable_send (Config->get_send_mmc ());
3385 } else if (p == "midi-feedback") {
3387 session_midi_feedback = Config->get_midi_feedback();
3389 } else if (p == "jack-time-master") {
3391 engine().reset_timebase ();
3393 } else if (p == "native-file-header-format") {
3395 if (!first_file_header_format_reset) {
3396 reset_native_file_format ();
3399 first_file_header_format_reset = false;
3401 } else if (p == "native-file-data-format") {
3403 if (!first_file_data_format_reset) {
3404 reset_native_file_format ();
3407 first_file_data_format_reset = false;
3409 } else if (p == "external-sync") {
3410 if (!config.get_external_sync()) {
3411 drop_sync_source ();
3413 switch_to_sync_source (Config->get_sync_source());
3415 } else if (p == "denormal-model") {
3417 } else if (p == "history-depth") {
3418 set_history_depth (Config->get_history_depth());
3419 } else if (p == "remote-model") {
3420 /* XXX DO SOMETHING HERE TO TELL THE GUI THAT WE NEED
3423 } else if (p == "sync-all-route-ordering") {
3425 /* sync to editor order unless mixer is used for remote IDs
3428 switch (Config->get_remote_model()) {
3430 sync_order_keys (EditorSort);
3433 sync_order_keys (EditorSort);
3436 sync_order_keys (MixerSort);
3439 } else if (p == "initial-program-change") {
3441 if (_mmc->output_port() && Config->get_initial_program_change() >= 0) {
3444 buf[0] = MIDI::program; // channel zero by default
3445 buf[1] = (Config->get_initial_program_change() & 0x7f);
3447 _mmc->output_port()->midimsg (buf, sizeof (buf), 0);
3449 } else if (p == "solo-mute-override") {
3450 // catch_up_on_solo_mute_override ();
3451 } else if (p == "listen-position" || p == "pfl-position") {
3452 listen_position_changed ();
3453 } else if (p == "solo-control-is-listen-control") {
3454 solo_control_mode_changed ();
3455 } else if (p == "timecode-offset" || p == "timecode-offset-negative") {
3456 last_timecode_valid = false;
3457 } else if (p == "playback-buffer-seconds") {
3458 AudioSource::allocate_working_buffers (frame_rate());
3459 } else if (p == "automation-thinning-factor") {
3460 Evoral::ControlList::set_thinning_factor (Config->get_automation_thinning_factor());
3461 } else if (p == "ltc-source-port") {
3462 reconnect_ltc_input ();
3463 } else if (p == "ltc-sink-port") {
3464 reconnect_ltc_output ();
3465 } else if (p == "timecode-generator-offset") {
3466 ltc_tx_parse_offset();
3473 Session::set_history_depth (uint32_t d)
3475 _history.set_depth (d);
3479 Session::load_diskstreams_2X (XMLNode const & node, int)
3482 XMLNodeConstIterator citer;
3484 clist = node.children();
3486 for (citer = clist.begin(); citer != clist.end(); ++citer) {
3489 /* diskstreams added automatically by DiskstreamCreated handler */
3490 if ((*citer)->name() == "AudioDiskstream" || (*citer)->name() == "DiskStream") {
3491 boost::shared_ptr<AudioDiskstream> dsp (new AudioDiskstream (*this, **citer));
3492 _diskstreams_2X.push_back (dsp);
3494 error << _("Session: unknown diskstream type in XML") << endmsg;
3498 catch (failed_constructor& err) {
3499 error << _("Session: could not load diskstream via XML state") << endmsg;
3507 /** Connect things to the MMC object */
3509 Session::setup_midi_machine_control ()
3511 _mmc = new MIDI::MachineControl;
3512 _mmc->set_ports (_midi_ports->mmc_input_port(), _midi_ports->mmc_output_port());
3514 _mmc->Play.connect_same_thread (*this, boost::bind (&Session::mmc_deferred_play, this, _1));
3515 _mmc->DeferredPlay.connect_same_thread (*this, boost::bind (&Session::mmc_deferred_play, this, _1));
3516 _mmc->Stop.connect_same_thread (*this, boost::bind (&Session::mmc_stop, this, _1));
3517 _mmc->FastForward.connect_same_thread (*this, boost::bind (&Session::mmc_fast_forward, this, _1));
3518 _mmc->Rewind.connect_same_thread (*this, boost::bind (&Session::mmc_rewind, this, _1));
3519 _mmc->Pause.connect_same_thread (*this, boost::bind (&Session::mmc_pause, this, _1));
3520 _mmc->RecordPause.connect_same_thread (*this, boost::bind (&Session::mmc_record_pause, this, _1));
3521 _mmc->RecordStrobe.connect_same_thread (*this, boost::bind (&Session::mmc_record_strobe, this, _1));
3522 _mmc->RecordExit.connect_same_thread (*this, boost::bind (&Session::mmc_record_exit, this, _1));
3523 _mmc->Locate.connect_same_thread (*this, boost::bind (&Session::mmc_locate, this, _1, _2));
3524 _mmc->Step.connect_same_thread (*this, boost::bind (&Session::mmc_step, this, _1, _2));
3525 _mmc->Shuttle.connect_same_thread (*this, boost::bind (&Session::mmc_shuttle, this, _1, _2, _3));
3526 _mmc->TrackRecordStatusChange.connect_same_thread (*this, boost::bind (&Session::mmc_record_enable, this, _1, _2, _3));
3528 /* also handle MIDI SPP because its so common */
3530 _mmc->SPPStart.connect_same_thread (*this, boost::bind (&Session::spp_start, this));
3531 _mmc->SPPContinue.connect_same_thread (*this, boost::bind (&Session::spp_continue, this));
3532 _mmc->SPPStop.connect_same_thread (*this, boost::bind (&Session::spp_stop, this));
3535 boost::shared_ptr<Controllable>
3536 Session::solo_cut_control() const
3538 /* the solo cut control is a bit of an anomaly, at least as of Febrary 2011. There are no other
3539 controls in Ardour that currently get presented to the user in the GUI that require
3540 access as a Controllable and are also NOT owned by some SessionObject (e.g. Route, or MonitorProcessor).
3542 its actually an RCConfiguration parameter, so we use a ProxyControllable to wrap
3543 it up as a Controllable. Changes to the Controllable will just map back to the RCConfiguration
3547 return _solo_cut_control;
3551 Session::rename (const std::string& new_name)
3553 string legal_name = legalize_for_path (new_name);
3559 string const old_sources_root = _session_dir->sources_root();
3561 #define RENAME ::rename
3566 * interchange subdirectory
3570 * Backup files are left unchanged and not renamed.
3573 /* pass one: not 100% safe check that the new directory names don't
3577 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
3582 /* this is a stupid hack because Glib::path_get_dirname() is
3583 * lexical-only, and so passing it /a/b/c/ gives a different
3584 * result than passing it /a/b/c ...
3587 if (oldstr[oldstr.length()-1] == G_DIR_SEPARATOR) {
3588 oldstr = oldstr.substr (0, oldstr.length() - 1);
3591 string base = Glib::path_get_dirname (oldstr);
3592 string p = Glib::path_get_basename (oldstr);
3594 newstr = Glib::build_filename (base, legal_name);
3596 if (Glib::file_test (newstr, Glib::FILE_TEST_EXISTS)) {
3603 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
3608 /* this is a stupid hack because Glib::path_get_dirname() is
3609 * lexical-only, and so passing it /a/b/c/ gives a different
3610 * result than passing it /a/b/c ...
3613 if (oldstr[oldstr.length()-1] == G_DIR_SEPARATOR) {
3614 oldstr = oldstr.substr (0, oldstr.length() - 1);
3617 string base = Glib::path_get_dirname (oldstr);
3618 string p = Glib::path_get_basename (oldstr);
3620 newstr = Glib::build_filename (base, legal_name);
3622 cerr << "Rename " << oldstr << " => " << newstr << endl;
3624 if (RENAME (oldstr.c_str(), newstr.c_str()) != 0) {
3629 (*_session_dir) = newstr;
3634 /* directory below interchange */
3636 v.push_back (newstr);
3637 v.push_back (interchange_dir_name);
3640 oldstr = Glib::build_filename (v);
3643 v.push_back (newstr);
3644 v.push_back (interchange_dir_name);
3645 v.push_back (legal_name);
3647 newstr = Glib::build_filename (v);
3649 cerr << "Rename " << oldstr << " => " << newstr << endl;
3651 if (RENAME (oldstr.c_str(), newstr.c_str()) != 0) {
3658 oldstr = Glib::build_filename (newpath, _current_snapshot_name) + statefile_suffix;
3659 newstr= Glib::build_filename (newpath, legal_name) + statefile_suffix;
3661 cerr << "Rename " << oldstr << " => " << newstr << endl;
3663 if (RENAME (oldstr.c_str(), newstr.c_str()) != 0) {
3670 oldstr = Glib::build_filename (newpath, _current_snapshot_name) + history_suffix;
3672 if (Glib::file_test (oldstr, Glib::FILE_TEST_EXISTS)) {
3673 newstr = Glib::build_filename (newpath, legal_name) + history_suffix;
3675 cerr << "Rename " << oldstr << " => " << newstr << endl;
3677 if (RENAME (oldstr.c_str(), newstr.c_str()) != 0) {
3682 /* update file source paths */
3684 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ++i) {
3685 boost::shared_ptr<FileSource> fs = boost::dynamic_pointer_cast<FileSource> (i->second);
3687 string p = fs->path ();
3688 boost::replace_all (p, old_sources_root, _session_dir->sources_root());
3693 /* remove old name from recent sessions */
3695 remove_recent_sessions (_path);
3698 _current_snapshot_name = new_name;
3703 /* save state again to get everything just right */
3705 save_state (_current_snapshot_name);
3708 /* add to recent sessions */
3710 store_recent_sessions (new_name, _path);