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 BootMessage (_("Using configuration"));
215 _midi_ports = new MidiPortManager;
216 setup_midi_machine_control ();
218 if (_butler->start_thread()) {
222 if (start_midi_thread ()) {
226 setup_click_sounds (0);
227 setup_midi_control ();
229 _engine.Halted.connect_same_thread (*this, boost::bind (&Session::engine_halted, this));
230 _engine.Xrun.connect_same_thread (*this, boost::bind (&Session::xrun_recovery, this));
233 /* tempo map requires sample rate knowledge */
235 _tempo_map = new TempoMap (_current_frame_rate);
236 _tempo_map->PropertyChanged.connect_same_thread (*this, boost::bind (&Session::tempo_map_changed, this, _1));
238 /* MidiClock requires a tempo map */
240 midi_clock = new MidiClockTicker ();
241 midi_clock->set_session (this);
243 /* crossfades require sample rate knowledge */
245 SndFileSource::setup_standard_crossfades (*this, frame_rate());
246 _engine.GraphReordered.connect_same_thread (*this, boost::bind (&Session::graph_reordered, this));
248 AudioDiskstream::allocate_working_buffers();
249 refresh_disk_space ();
251 /* we're finally ready to call set_state() ... all objects have
252 * been created, the engine is running.
256 if (set_state (*state_tree->root(), Stateful::loading_state_version)) {
260 // set_state() will call setup_raid_path(), but if it's a new session we need
261 // to call setup_raid_path() here.
262 setup_raid_path (_path);
267 boost::function<void (std::string)> ff (boost::bind (&Session::config_changed, this, _1, false));
268 boost::function<void (std::string)> ft (boost::bind (&Session::config_changed, this, _1, true));
270 Config->map_parameters (ff);
271 config.map_parameters (ft);
273 /* Reset all panners */
275 Delivery::reset_panners ();
277 /* this will cause the CPM to instantiate any protocols that are in use
278 * (or mandatory), which will pass it this Session, and then call
279 * set_state() on each instantiated protocol to match stored state.
282 ControlProtocolManager::instance().set_session (this);
284 /* This must be done after the ControlProtocolManager set_session above,
285 as it will set states for ports which the ControlProtocolManager creates.
288 // XXX set state of MIDI::Port's
289 // MidiPortManager::instance()->set_port_states (Config->midi_port_states ());
291 /* And this must be done after the MIDI::Manager::set_port_states as
292 * it will try to make connections whose details are loaded by set_port_states.
297 /* Let control protocols know that we are now all connected, so they
298 * could start talking to surfaces if they want to.
301 ControlProtocolManager::instance().midi_connectivity_established ();
303 if (_is_new && !no_auto_connect()) {
304 Glib::Threads::Mutex::Lock lm (AudioEngine::instance()->process_lock());
305 auto_connect_master_bus ();
308 _state_of_the_state = StateOfTheState (_state_of_the_state & ~(CannotSave|Dirty));
310 /* update latencies */
312 initialize_latencies ();
314 _locations->changed.connect_same_thread (*this, boost::bind (&Session::locations_changed, this));
315 _locations->added.connect_same_thread (*this, boost::bind (&Session::locations_added, this, _1));
317 } catch (AudioEngine::PortRegistrationFailure& err) {
318 /* handle this one in a different way than all others, so that its clear what happened */
319 error << err.what() << endmsg;
325 BootMessage (_("Reset Remote Controls"));
327 // send_full_time_code (0);
328 _engine.transport_locate (0);
330 _mmc->send (MIDI::MachineControlCommand (MIDI::MachineControl::cmdMmcReset));
331 _mmc->send (MIDI::MachineControlCommand (Timecode::Time ()));
333 MIDI::Name::MidiPatchManager::instance().set_session (this);
336 /* initial program change will be delivered later; see ::config_changed() */
338 _state_of_the_state = Clean;
340 Port::set_connecting_blocked (false);
342 DirtyChanged (); /* EMIT SIGNAL */
346 } else if (state_was_pending) {
348 remove_pending_capture_state ();
349 state_was_pending = false;
356 Session::raid_path () const
358 SearchPath raid_search_path;
360 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
361 raid_search_path += (*i).path;
364 return raid_search_path.to_string ();
368 Session::setup_raid_path (string path)
377 session_dirs.clear ();
379 SearchPath search_path(path);
380 SearchPath sound_search_path;
381 SearchPath midi_search_path;
383 for (SearchPath::const_iterator i = search_path.begin(); i != search_path.end(); ++i) {
385 sp.blocks = 0; // not needed
386 session_dirs.push_back (sp);
388 SessionDirectory sdir(sp.path);
390 sound_search_path += sdir.sound_path ();
391 midi_search_path += sdir.midi_path ();
394 // reset the round-robin soundfile path thingie
395 last_rr_session_dir = session_dirs.begin();
399 Session::path_is_within_session (const std::string& path)
401 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
402 if (PBD::path_is_within (i->path, path)) {
410 Session::ensure_subdirs ()
414 dir = session_directory().peak_path();
416 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
417 error << string_compose(_("Session: cannot create session peakfile folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
421 dir = session_directory().sound_path();
423 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
424 error << string_compose(_("Session: cannot create session sounds dir \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
428 dir = session_directory().midi_path();
430 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
431 error << string_compose(_("Session: cannot create session midi dir \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
435 dir = session_directory().dead_path();
437 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
438 error << string_compose(_("Session: cannot create session dead sounds folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
442 dir = session_directory().export_path();
444 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
445 error << string_compose(_("Session: cannot create session export folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
449 dir = analysis_dir ();
451 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
452 error << string_compose(_("Session: cannot create session analysis folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
456 dir = plugins_dir ();
458 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
459 error << string_compose(_("Session: cannot create session plugins folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
463 dir = externals_dir ();
465 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
466 error << string_compose(_("Session: cannot create session externals folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
473 /** @param session_template directory containing session template, or empty.
474 * Caller must not hold process lock.
477 Session::create (const string& session_template, BusProfile* bus_profile)
479 if (g_mkdir_with_parents (_path.c_str(), 0755) < 0) {
480 error << string_compose(_("Session: cannot create session folder \"%1\" (%2)"), _path, strerror (errno)) << endmsg;
484 if (ensure_subdirs ()) {
488 _writable = exists_and_writable (_path);
490 if (!session_template.empty()) {
491 std::string in_path = session_template_dir_to_file (session_template);
493 ifstream in(in_path.c_str());
496 string out_path = _path;
498 out_path += statefile_suffix;
500 ofstream out(out_path.c_str());
506 /* Copy plugin state files from template to new session */
507 std::string template_plugins = Glib::build_filename (session_template, X_("plugins"));
508 copy_files (template_plugins, plugins_dir ());
513 error << string_compose (_("Could not open %1 for writing session template"), out_path)
519 error << string_compose (_("Could not open session template %1 for reading"), in_path)
526 /* set initial start + end point */
528 _state_of_the_state = Clean;
530 /* set up Master Out and Control Out if necessary */
535 ChanCount count(DataType::AUDIO, bus_profile->master_out_channels);
537 if (bus_profile->master_out_channels) {
538 boost::shared_ptr<Route> r (new Route (*this, _("master"), Route::MasterOut, DataType::AUDIO));
542 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
543 // boost_debug_shared_ptr_mark_interesting (r.get(), "Route");
546 Glib::Threads::Mutex::Lock lm (AudioEngine::instance()->process_lock ());
547 r->input()->ensure_io (count, false, this);
548 r->output()->ensure_io (count, false, this);
554 /* prohibit auto-connect to master, because there isn't one */
555 bus_profile->output_ac = AutoConnectOption (bus_profile->output_ac & ~AutoConnectMaster);
559 add_routes (rl, false, false, false);
562 /* this allows the user to override settings with an environment variable.
565 if (no_auto_connect()) {
566 bus_profile->input_ac = AutoConnectOption (0);
567 bus_profile->output_ac = AutoConnectOption (0);
570 Config->set_input_auto_connect (bus_profile->input_ac);
571 Config->set_output_auto_connect (bus_profile->output_ac);
574 if (Config->get_use_monitor_bus() && bus_profile) {
575 add_monitor_section ();
582 Session::maybe_write_autosave()
584 if (dirty() && record_status() != Recording) {
585 save_state("", true);
590 Session::remove_pending_capture_state ()
592 std::string pending_state_file_path(_session_dir->root_path());
594 pending_state_file_path = Glib::build_filename (pending_state_file_path, legalize_for_path (_current_snapshot_name) + pending_suffix);
596 if (!Glib::file_test (pending_state_file_path, Glib::FILE_TEST_EXISTS)) return;
598 if (g_remove (pending_state_file_path.c_str()) != 0) {
599 error << string_compose(_("Could not remove pending capture state at path \"%1\" (%2)"),
600 pending_state_file_path, g_strerror (errno)) << endmsg;
604 /** Rename a state file.
605 * @param old_name Old snapshot name.
606 * @param new_name New snapshot name.
609 Session::rename_state (string old_name, string new_name)
611 if (old_name == _current_snapshot_name || old_name == _name) {
612 /* refuse to rename the current snapshot or the "main" one */
616 const string old_xml_filename = legalize_for_path (old_name) + statefile_suffix;
617 const string new_xml_filename = legalize_for_path (new_name) + statefile_suffix;
619 const std::string old_xml_path(Glib::build_filename (_session_dir->root_path(), old_xml_filename));
620 const std::string new_xml_path(Glib::build_filename (_session_dir->root_path(), new_xml_filename));
622 if (::g_rename (old_xml_path.c_str(), new_xml_path.c_str()) != 0) {
623 error << string_compose(_("could not rename snapshot %1 to %2 (%3)"),
624 old_name, new_name, g_strerror(errno)) << endmsg;
628 /** Remove a state file.
629 * @param snapshot_name Snapshot name.
632 Session::remove_state (string snapshot_name)
634 if (!_writable || snapshot_name == _current_snapshot_name || snapshot_name == _name) {
635 // refuse to remove the current snapshot or the "main" one
639 std::string xml_path(_session_dir->root_path());
641 xml_path = Glib::build_filename (xml_path, legalize_for_path (snapshot_name) + statefile_suffix);
643 if (!create_backup_file (xml_path)) {
644 // don't remove it if a backup can't be made
645 // create_backup_file will log the error.
650 if (g_remove (xml_path.c_str()) != 0) {
651 error << string_compose(_("Could not remove session file at path \"%1\" (%2)"),
652 xml_path, g_strerror (errno)) << endmsg;
656 /** @param snapshot_name Name to save under, without .ardour / .pending prefix */
658 Session::save_state (string snapshot_name, bool pending, bool switch_to_snapshot)
661 std::string xml_path(_session_dir->root_path());
663 if (!_writable || (_state_of_the_state & CannotSave)) {
667 if (!_engine.connected ()) {
668 error << string_compose (_("the %1 audio engine is not connected and state saving would lose all I/O connections. Session not saved"),
674 /* tell sources we're saving first, in case they write out to a new file
675 * which should be saved with the state rather than the old one */
676 for (SourceMap::const_iterator i = sources.begin(); i != sources.end(); ++i) {
678 i->second->session_saved();
679 } catch (Evoral::SMF::FileError& e) {
680 error << string_compose ("Could not write to MIDI file %1; MIDI data not saved.", e.file_name ()) << endmsg;
684 SaveSession (); /* EMIT SIGNAL */
686 tree.set_root (&get_state());
688 if (snapshot_name.empty()) {
689 snapshot_name = _current_snapshot_name;
690 } else if (switch_to_snapshot) {
691 _current_snapshot_name = snapshot_name;
696 /* proper save: use statefile_suffix (.ardour in English) */
698 xml_path = Glib::build_filename (xml_path, legalize_for_path (snapshot_name) + statefile_suffix);
700 /* make a backup copy of the old file */
702 if (Glib::file_test (xml_path, Glib::FILE_TEST_EXISTS) && !create_backup_file (xml_path)) {
703 // create_backup_file will log the error
709 /* pending save: use pending_suffix (.pending in English) */
710 xml_path = Glib::build_filename (xml_path, legalize_for_path (snapshot_name) + pending_suffix);
713 std::string tmp_path(_session_dir->root_path());
714 tmp_path = Glib::build_filename (tmp_path, legalize_for_path (snapshot_name) + temp_suffix);
716 // cerr << "actually writing state to " << xml_path << endl;
718 if (!tree.write (tmp_path)) {
719 error << string_compose (_("state could not be saved to %1"), tmp_path) << endmsg;
720 if (g_remove (tmp_path.c_str()) != 0) {
721 error << string_compose(_("Could not remove temporary session file at path \"%1\" (%2)"),
722 tmp_path, g_strerror (errno)) << endmsg;
728 if (::rename (tmp_path.c_str(), xml_path.c_str()) != 0) {
729 error << string_compose (_("could not rename temporary session file %1 to %2"),
730 tmp_path, xml_path) << endmsg;
731 if (g_remove (tmp_path.c_str()) != 0) {
732 error << string_compose(_("Could not remove temporary session file at path \"%1\" (%2)"),
733 tmp_path, g_strerror (errno)) << endmsg;
741 save_history (snapshot_name);
743 bool was_dirty = dirty();
745 _state_of_the_state = StateOfTheState (_state_of_the_state & ~Dirty);
748 DirtyChanged (); /* EMIT SIGNAL */
751 StateSaved (snapshot_name); /* EMIT SIGNAL */
758 Session::restore_state (string snapshot_name)
760 if (load_state (snapshot_name) == 0) {
761 set_state (*state_tree->root(), Stateful::loading_state_version);
768 Session::load_state (string snapshot_name)
773 state_was_pending = false;
775 /* check for leftover pending state from a crashed capture attempt */
777 std::string xmlpath(_session_dir->root_path());
778 xmlpath = Glib::build_filename (xmlpath, legalize_for_path (snapshot_name) + pending_suffix);
780 if (Glib::file_test (xmlpath, Glib::FILE_TEST_EXISTS)) {
782 /* there is pending state from a crashed capture attempt */
784 boost::optional<int> r = AskAboutPendingState();
785 if (r.get_value_or (1)) {
786 state_was_pending = true;
790 if (!state_was_pending) {
791 xmlpath = Glib::build_filename (_session_dir->root_path(), snapshot_name);
794 if (!Glib::file_test (xmlpath, Glib::FILE_TEST_EXISTS)) {
795 xmlpath = Glib::build_filename (_session_dir->root_path(), legalize_for_path (snapshot_name) + statefile_suffix);
796 if (!Glib::file_test (xmlpath, Glib::FILE_TEST_EXISTS)) {
797 error << string_compose(_("%1: session file \"%2\" doesn't exist!"), _name, xmlpath) << endmsg;
802 state_tree = new XMLTree;
806 _writable = exists_and_writable (xmlpath);
808 if (!state_tree->read (xmlpath)) {
809 error << string_compose(_("Could not understand session file %1"), xmlpath) << endmsg;
815 XMLNode& root (*state_tree->root());
817 if (root.name() != X_("Session")) {
818 error << string_compose (_("Session file %1 is not a session"), xmlpath) << endmsg;
824 const XMLProperty* prop;
826 if ((prop = root.property ("version")) == 0) {
827 /* no version implies very old version of Ardour */
828 Stateful::loading_state_version = 1000;
830 if (prop->value().find ('.') != string::npos) {
831 /* old school version format */
832 if (prop->value()[0] == '2') {
833 Stateful::loading_state_version = 2000;
835 Stateful::loading_state_version = 3000;
838 Stateful::loading_state_version = atoi (prop->value());
842 if (Stateful::loading_state_version < CURRENT_SESSION_FILE_VERSION && _writable) {
844 std::string backup_path(_session_dir->root_path());
845 std::string backup_filename = string_compose ("%1-%2%3", legalize_for_path (snapshot_name), Stateful::loading_state_version, statefile_suffix);
846 backup_path = Glib::build_filename (backup_path, backup_filename);
848 // only create a backup for a given statefile version once
850 if (!Glib::file_test (backup_path, Glib::FILE_TEST_EXISTS)) {
852 VersionMismatch (xmlpath, backup_path);
854 if (!copy_file (xmlpath, backup_path)) {;
864 Session::load_options (const XMLNode& node)
866 LocaleGuard lg (X_("POSIX"));
867 config.set_variables (node);
878 Session::get_template()
880 /* if we don't disable rec-enable, diskstreams
881 will believe they need to store their capture
882 sources in their state node.
885 disable_record (false);
891 Session::state (bool full_state)
893 XMLNode* node = new XMLNode("Session");
897 snprintf(buf, sizeof(buf), "%d", CURRENT_SESSION_FILE_VERSION);
898 node->add_property("version", buf);
900 /* store configuration settings */
904 node->add_property ("name", _name);
905 snprintf (buf, sizeof (buf), "%" PRId64, _nominal_frame_rate);
906 node->add_property ("sample-rate", buf);
908 if (session_dirs.size() > 1) {
912 vector<space_and_path>::iterator i = session_dirs.begin();
913 vector<space_and_path>::iterator next;
915 ++i; /* skip the first one */
919 while (i != session_dirs.end()) {
923 if (next != session_dirs.end()) {
933 child = node->add_child ("Path");
934 child->add_content (p);
938 /* save the ID counter */
940 snprintf (buf, sizeof (buf), "%" PRIu64, ID::counter());
941 node->add_property ("id-counter", buf);
943 /* save the event ID counter */
945 snprintf (buf, sizeof (buf), "%d", Evoral::event_id_counter());
946 node->add_property ("event-counter", buf);
948 /* various options */
950 list<XMLNode*> midi_port_nodes = _midi_ports->get_midi_port_states();
951 if (!midi_port_nodes.empty()) {
952 XMLNode* midi_port_stuff = new XMLNode ("MIDIPorts");
953 for (list<XMLNode*>::const_iterator n = midi_port_nodes.begin(); n != midi_port_nodes.end(); ++n) {
954 midi_port_stuff->add_child_nocopy (**n);
956 node->add_child_nocopy (*midi_port_stuff);
959 node->add_child_nocopy (config.get_variables ());
961 node->add_child_nocopy (ARDOUR::SessionMetadata::Metadata()->get_state());
963 child = node->add_child ("Sources");
966 Glib::Threads::Mutex::Lock sl (source_lock);
968 for (SourceMap::iterator siter = sources.begin(); siter != sources.end(); ++siter) {
970 /* Don't save information about non-file Sources, or
971 * about non-destructive file sources that are empty
972 * and unused by any regions.
975 boost::shared_ptr<FileSource> fs;
977 if ((fs = boost::dynamic_pointer_cast<FileSource> (siter->second)) != 0) {
979 if (!fs->destructive()) {
980 if (fs->empty() && !fs->used()) {
985 child->add_child_nocopy (siter->second->get_state());
990 child = node->add_child ("Regions");
993 Glib::Threads::Mutex::Lock rl (region_lock);
994 const RegionFactory::RegionMap& region_map (RegionFactory::all_regions());
995 for (RegionFactory::RegionMap::const_iterator i = region_map.begin(); i != region_map.end(); ++i) {
996 boost::shared_ptr<Region> r = i->second;
997 /* only store regions not attached to playlists */
998 if (r->playlist() == 0) {
999 if (boost::dynamic_pointer_cast<AudioRegion>(r)) {
1000 child->add_child_nocopy ((boost::dynamic_pointer_cast<AudioRegion>(r))->get_basic_state ());
1002 child->add_child_nocopy (r->get_state ());
1007 RegionFactory::CompoundAssociations& cassocs (RegionFactory::compound_associations());
1009 if (!cassocs.empty()) {
1010 XMLNode* ca = node->add_child (X_("CompoundAssociations"));
1012 for (RegionFactory::CompoundAssociations::iterator i = cassocs.begin(); i != cassocs.end(); ++i) {
1014 XMLNode* can = new XMLNode (X_("CompoundAssociation"));
1015 i->first->id().print (buf, sizeof (buf));
1016 can->add_property (X_("copy"), buf);
1017 i->second->id().print (buf, sizeof (buf));
1018 can->add_property (X_("original"), buf);
1019 ca->add_child_nocopy (*can);
1025 node->add_child_nocopy (_locations->get_state());
1027 // for a template, just create a new Locations, populate it
1028 // with the default start and end, and get the state for that.
1029 Locations loc (*this);
1030 Location* range = new Location (*this, 0, 0, _("session"), Location::IsSessionRange);
1031 range->set (max_framepos, 0);
1033 node->add_child_nocopy (loc.get_state());
1036 child = node->add_child ("Bundles");
1038 boost::shared_ptr<BundleList> bundles = _bundles.reader ();
1039 for (BundleList::iterator i = bundles->begin(); i != bundles->end(); ++i) {
1040 boost::shared_ptr<UserBundle> b = boost::dynamic_pointer_cast<UserBundle> (*i);
1042 child->add_child_nocopy (b->get_state());
1047 child = node->add_child ("Routes");
1049 boost::shared_ptr<RouteList> r = routes.reader ();
1051 RoutePublicOrderSorter cmp;
1052 RouteList public_order (*r);
1053 public_order.sort (cmp);
1055 /* the sort should have put control outs first */
1058 assert (_monitor_out == public_order.front());
1061 for (RouteList::iterator i = public_order.begin(); i != public_order.end(); ++i) {
1062 if (!(*i)->is_auditioner()) {
1064 child->add_child_nocopy ((*i)->get_state());
1066 child->add_child_nocopy ((*i)->get_template());
1072 playlists->add_state (node, full_state);
1074 child = node->add_child ("RouteGroups");
1075 for (list<RouteGroup *>::iterator i = _route_groups.begin(); i != _route_groups.end(); ++i) {
1076 child->add_child_nocopy ((*i)->get_state());
1080 XMLNode* gain_child = node->add_child ("Click");
1081 gain_child->add_child_nocopy (_click_io->state (full_state));
1082 gain_child->add_child_nocopy (_click_gain->state (full_state));
1086 XMLNode* ltc_input_child = node->add_child ("LTC-In");
1087 ltc_input_child->add_child_nocopy (_ltc_input->state (full_state));
1091 XMLNode* ltc_output_child = node->add_child ("LTC-Out");
1092 ltc_output_child->add_child_nocopy (_ltc_output->state (full_state));
1095 node->add_child_nocopy (_speakers->get_state());
1096 node->add_child_nocopy (_tempo_map->get_state());
1097 node->add_child_nocopy (get_control_protocol_state());
1100 node->add_child_copy (*_extra_xml);
1107 Session::get_control_protocol_state ()
1109 ControlProtocolManager& cpm (ControlProtocolManager::instance());
1110 return cpm.get_state();
1114 Session::set_state (const XMLNode& node, int version)
1118 const XMLProperty* prop;
1121 _state_of_the_state = StateOfTheState (_state_of_the_state|CannotSave);
1123 if (node.name() != X_("Session")) {
1124 fatal << _("programming error: Session: incorrect XML node sent to set_state()") << endmsg;
1128 if ((prop = node.property ("name")) != 0) {
1129 _name = prop->value ();
1132 if ((prop = node.property (X_("sample-rate"))) != 0) {
1134 _nominal_frame_rate = atoi (prop->value());
1136 if (_nominal_frame_rate != _current_frame_rate) {
1137 boost::optional<int> r = AskAboutSampleRateMismatch (_nominal_frame_rate, _current_frame_rate);
1138 if (r.get_value_or (0)) {
1144 setup_raid_path(_session_dir->root_path());
1146 if ((prop = node.property (X_("id-counter"))) != 0) {
1148 sscanf (prop->value().c_str(), "%" PRIu64, &x);
1149 ID::init_counter (x);
1151 /* old sessions used a timebased counter, so fake
1152 the startup ID counter based on a standard
1157 ID::init_counter (now);
1160 if ((prop = node.property (X_("event-counter"))) != 0) {
1161 Evoral::init_event_id_counter (atoi (prop->value()));
1165 if ((child = find_named_node (node, "MIDIPorts")) != 0) {
1166 _midi_ports->set_midi_port_states (child->children());
1169 IO::disable_connecting ();
1171 Stateful::save_extra_xml (node);
1173 if (((child = find_named_node (node, "Options")) != 0)) { /* old style */
1174 load_options (*child);
1175 } else if ((child = find_named_node (node, "Config")) != 0) { /* new style */
1176 load_options (*child);
1178 error << _("Session: XML state has no options section") << endmsg;
1181 if (version >= 3000) {
1182 if ((child = find_named_node (node, "Metadata")) == 0) {
1183 warning << _("Session: XML state has no metadata section") << endmsg;
1184 } else if ( ARDOUR::SessionMetadata::Metadata()->set_state (*child, version) ) {
1189 if ((child = find_named_node (node, X_("Speakers"))) != 0) {
1190 _speakers->set_state (*child, version);
1193 if ((child = find_named_node (node, "Sources")) == 0) {
1194 error << _("Session: XML state has no sources section") << endmsg;
1196 } else if (load_sources (*child)) {
1200 if ((child = find_named_node (node, "TempoMap")) == 0) {
1201 error << _("Session: XML state has no Tempo Map section") << endmsg;
1203 } else if (_tempo_map->set_state (*child, version)) {
1207 if ((child = find_named_node (node, "Locations")) == 0) {
1208 error << _("Session: XML state has no locations section") << endmsg;
1210 } else if (_locations->set_state (*child, version)) {
1216 if ((location = _locations->auto_loop_location()) != 0) {
1217 set_auto_loop_location (location);
1220 if ((location = _locations->auto_punch_location()) != 0) {
1221 set_auto_punch_location (location);
1224 if ((location = _locations->session_range_location()) != 0) {
1225 delete _session_range_location;
1226 _session_range_location = location;
1229 if (_session_range_location) {
1230 AudioFileSource::set_header_position_offset (_session_range_location->start());
1233 if ((child = find_named_node (node, "Regions")) == 0) {
1234 error << _("Session: XML state has no Regions section") << endmsg;
1236 } else if (load_regions (*child)) {
1240 if ((child = find_named_node (node, "Playlists")) == 0) {
1241 error << _("Session: XML state has no playlists section") << endmsg;
1243 } else if (playlists->load (*this, *child)) {
1247 if ((child = find_named_node (node, "UnusedPlaylists")) == 0) {
1249 } else if (playlists->load_unused (*this, *child)) {
1253 if ((child = find_named_node (node, "CompoundAssociations")) != 0) {
1254 if (load_compounds (*child)) {
1259 if (version >= 3000) {
1260 if ((child = find_named_node (node, "Bundles")) == 0) {
1261 warning << _("Session: XML state has no bundles section") << endmsg;
1264 /* We can't load Bundles yet as they need to be able
1265 to convert from port names to Port objects, which can't happen until
1267 _bundle_xml_node = new XMLNode (*child);
1271 if (version < 3000) {
1272 if ((child = find_named_node (node, X_("DiskStreams"))) == 0) {
1273 error << _("Session: XML state has no diskstreams section") << endmsg;
1275 } else if (load_diskstreams_2X (*child, version)) {
1280 if ((child = find_named_node (node, "Routes")) == 0) {
1281 error << _("Session: XML state has no routes section") << endmsg;
1283 } else if (load_routes (*child, version)) {
1287 /* our diskstreams list is no longer needed as they are now all owned by their Route */
1288 _diskstreams_2X.clear ();
1290 if (version >= 3000) {
1292 if ((child = find_named_node (node, "RouteGroups")) == 0) {
1293 error << _("Session: XML state has no route groups section") << endmsg;
1295 } else if (load_route_groups (*child, version)) {
1299 } else if (version < 3000) {
1301 if ((child = find_named_node (node, "EditGroups")) == 0) {
1302 error << _("Session: XML state has no edit groups section") << endmsg;
1304 } else if (load_route_groups (*child, version)) {
1308 if ((child = find_named_node (node, "MixGroups")) == 0) {
1309 error << _("Session: XML state has no mix groups section") << endmsg;
1311 } else if (load_route_groups (*child, version)) {
1316 if ((child = find_named_node (node, "Click")) == 0) {
1317 warning << _("Session: XML state has no click section") << endmsg;
1318 } else if (_click_io) {
1319 const XMLNodeList& children (child->children());
1320 XMLNodeList::const_iterator i = children.begin();
1321 _click_io->set_state (**i, version);
1323 if (i != children.end()) {
1324 _click_gain->set_state (**i, version);
1328 if ((child = find_named_node (node, ControlProtocolManager::state_node_name)) != 0) {
1329 ControlProtocolManager::instance().set_state (*child, version);
1332 update_have_rec_enabled_track ();
1334 /* here beginneth the second phase ... */
1336 StateReady (); /* EMIT SIGNAL */
1345 Session::load_routes (const XMLNode& node, int version)
1348 XMLNodeConstIterator niter;
1349 RouteList new_routes;
1351 nlist = node.children();
1355 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1357 boost::shared_ptr<Route> route;
1358 if (version < 3000) {
1359 route = XMLRouteFactory_2X (**niter, version);
1361 route = XMLRouteFactory (**niter, version);
1365 error << _("Session: cannot create Route from XML description.") << endmsg;
1369 BootMessage (string_compose (_("Loaded track/bus %1"), route->name()));
1371 new_routes.push_back (route);
1374 add_routes (new_routes, false, false, false);
1379 boost::shared_ptr<Route>
1380 Session::XMLRouteFactory (const XMLNode& node, int version)
1382 boost::shared_ptr<Route> ret;
1384 if (node.name() != "Route") {
1388 XMLNode* ds_child = find_named_node (node, X_("Diskstream"));
1390 DataType type = DataType::AUDIO;
1391 const XMLProperty* prop = node.property("default-type");
1394 type = DataType (prop->value());
1397 assert (type != DataType::NIL);
1401 boost::shared_ptr<Track> track;
1403 if (type == DataType::AUDIO) {
1404 track.reset (new AudioTrack (*this, X_("toBeResetFroXML")));
1406 track.reset (new MidiTrack (*this, X_("toBeResetFroXML")));
1409 if (track->init()) {
1413 if (track->set_state (node, version)) {
1417 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
1418 // boost_debug_shared_ptr_mark_interesting (track.get(), "Track");
1423 boost::shared_ptr<Route> r (new Route (*this, X_("toBeResetFroXML")));
1425 if (r->init () == 0 && r->set_state (node, version) == 0) {
1426 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
1427 // boost_debug_shared_ptr_mark_interesting (r.get(), "Route");
1436 boost::shared_ptr<Route>
1437 Session::XMLRouteFactory_2X (const XMLNode& node, int version)
1439 boost::shared_ptr<Route> ret;
1441 if (node.name() != "Route") {
1445 XMLProperty const * ds_prop = node.property (X_("diskstream-id"));
1447 ds_prop = node.property (X_("diskstream"));
1450 DataType type = DataType::AUDIO;
1451 const XMLProperty* prop = node.property("default-type");
1454 type = DataType (prop->value());
1457 assert (type != DataType::NIL);
1461 list<boost::shared_ptr<Diskstream> >::iterator i = _diskstreams_2X.begin ();
1462 while (i != _diskstreams_2X.end() && (*i)->id() != ds_prop->value()) {
1466 if (i == _diskstreams_2X.end()) {
1467 error << _("Could not find diskstream for route") << endmsg;
1468 return boost::shared_ptr<Route> ();
1471 boost::shared_ptr<Track> track;
1473 if (type == DataType::AUDIO) {
1474 track.reset (new AudioTrack (*this, X_("toBeResetFroXML")));
1476 track.reset (new MidiTrack (*this, X_("toBeResetFroXML")));
1479 if (track->init()) {
1483 if (track->set_state (node, version)) {
1487 track->set_diskstream (*i);
1489 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
1490 // boost_debug_shared_ptr_mark_interesting (track.get(), "Track");
1495 boost::shared_ptr<Route> r (new Route (*this, X_("toBeResetFroXML")));
1497 if (r->init () == 0 && r->set_state (node, version) == 0) {
1498 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
1499 // boost_debug_shared_ptr_mark_interesting (r.get(), "Route");
1509 Session::load_regions (const XMLNode& node)
1512 XMLNodeConstIterator niter;
1513 boost::shared_ptr<Region> region;
1515 nlist = node.children();
1519 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1520 if ((region = XMLRegionFactory (**niter, false)) == 0) {
1521 error << _("Session: cannot create Region from XML description.");
1522 const XMLProperty *name = (**niter).property("name");
1525 error << " " << string_compose (_("Can not load state for region '%1'"), name->value());
1536 Session::load_compounds (const XMLNode& node)
1538 XMLNodeList calist = node.children();
1539 XMLNodeConstIterator caiter;
1540 XMLProperty *caprop;
1542 for (caiter = calist.begin(); caiter != calist.end(); ++caiter) {
1543 XMLNode* ca = *caiter;
1547 if ((caprop = ca->property (X_("original"))) == 0) {
1550 orig_id = caprop->value();
1552 if ((caprop = ca->property (X_("copy"))) == 0) {
1555 copy_id = caprop->value();
1557 boost::shared_ptr<Region> orig = RegionFactory::region_by_id (orig_id);
1558 boost::shared_ptr<Region> copy = RegionFactory::region_by_id (copy_id);
1560 if (!orig || !copy) {
1561 warning << string_compose (_("Regions in compound description not found (ID's %1 and %2): ignored"),
1567 RegionFactory::add_compound_association (orig, copy);
1574 Session::load_nested_sources (const XMLNode& node)
1577 XMLNodeConstIterator niter;
1579 nlist = node.children();
1581 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1582 if ((*niter)->name() == "Source") {
1584 /* it may already exist, so don't recreate it unnecessarily
1587 XMLProperty* prop = (*niter)->property (X_("id"));
1589 error << _("Nested source has no ID info in session file! (ignored)") << endmsg;
1593 ID source_id (prop->value());
1595 if (!source_by_id (source_id)) {
1598 SourceFactory::create (*this, **niter, true);
1600 catch (failed_constructor& err) {
1601 error << string_compose (_("Cannot reconstruct nested source for region %1"), name()) << endmsg;
1608 boost::shared_ptr<Region>
1609 Session::XMLRegionFactory (const XMLNode& node, bool full)
1611 const XMLProperty* type = node.property("type");
1615 const XMLNodeList& nlist = node.children();
1617 for (XMLNodeConstIterator niter = nlist.begin(); niter != nlist.end(); ++niter) {
1618 XMLNode *child = (*niter);
1619 if (child->name() == "NestedSource") {
1620 load_nested_sources (*child);
1624 if (!type || type->value() == "audio") {
1625 return boost::shared_ptr<Region>(XMLAudioRegionFactory (node, full));
1626 } else if (type->value() == "midi") {
1627 return boost::shared_ptr<Region>(XMLMidiRegionFactory (node, full));
1630 } catch (failed_constructor& err) {
1631 return boost::shared_ptr<Region> ();
1634 return boost::shared_ptr<Region> ();
1637 boost::shared_ptr<AudioRegion>
1638 Session::XMLAudioRegionFactory (const XMLNode& node, bool /*full*/)
1640 const XMLProperty* prop;
1641 boost::shared_ptr<Source> source;
1642 boost::shared_ptr<AudioSource> as;
1644 SourceList master_sources;
1645 uint32_t nchans = 1;
1648 if (node.name() != X_("Region")) {
1649 return boost::shared_ptr<AudioRegion>();
1652 if ((prop = node.property (X_("channels"))) != 0) {
1653 nchans = atoi (prop->value().c_str());
1656 if ((prop = node.property ("name")) == 0) {
1657 cerr << "no name for this region\n";
1661 if ((prop = node.property (X_("source-0"))) == 0) {
1662 if ((prop = node.property ("source")) == 0) {
1663 error << _("Session: XMLNode describing a AudioRegion is incomplete (no source)") << endmsg;
1664 return boost::shared_ptr<AudioRegion>();
1668 PBD::ID s_id (prop->value());
1670 if ((source = source_by_id (s_id)) == 0) {
1671 error << string_compose(_("Session: XMLNode describing a AudioRegion references an unknown source id =%1"), s_id) << endmsg;
1672 return boost::shared_ptr<AudioRegion>();
1675 as = boost::dynamic_pointer_cast<AudioSource>(source);
1677 error << string_compose(_("Session: XMLNode describing a AudioRegion references a non-audio source id =%1"), s_id) << endmsg;
1678 return boost::shared_ptr<AudioRegion>();
1681 sources.push_back (as);
1683 /* pickup other channels */
1685 for (uint32_t n=1; n < nchans; ++n) {
1686 snprintf (buf, sizeof(buf), X_("source-%d"), n);
1687 if ((prop = node.property (buf)) != 0) {
1689 PBD::ID id2 (prop->value());
1691 if ((source = source_by_id (id2)) == 0) {
1692 error << string_compose(_("Session: XMLNode describing a AudioRegion references an unknown source id =%1"), id2) << endmsg;
1693 return boost::shared_ptr<AudioRegion>();
1696 as = boost::dynamic_pointer_cast<AudioSource>(source);
1698 error << string_compose(_("Session: XMLNode describing a AudioRegion references a non-audio source id =%1"), id2) << endmsg;
1699 return boost::shared_ptr<AudioRegion>();
1701 sources.push_back (as);
1705 for (uint32_t n = 0; n < nchans; ++n) {
1706 snprintf (buf, sizeof(buf), X_("master-source-%d"), n);
1707 if ((prop = node.property (buf)) != 0) {
1709 PBD::ID id2 (prop->value());
1711 if ((source = source_by_id (id2)) == 0) {
1712 error << string_compose(_("Session: XMLNode describing a AudioRegion references an unknown source id =%1"), id2) << endmsg;
1713 return boost::shared_ptr<AudioRegion>();
1716 as = boost::dynamic_pointer_cast<AudioSource>(source);
1718 error << string_compose(_("Session: XMLNode describing a AudioRegion references a non-audio source id =%1"), id2) << endmsg;
1719 return boost::shared_ptr<AudioRegion>();
1721 master_sources.push_back (as);
1726 boost::shared_ptr<AudioRegion> region (boost::dynamic_pointer_cast<AudioRegion> (RegionFactory::create (sources, node)));
1728 /* a final detail: this is the one and only place that we know how long missing files are */
1730 if (region->whole_file()) {
1731 for (SourceList::iterator sx = sources.begin(); sx != sources.end(); ++sx) {
1732 boost::shared_ptr<SilentFileSource> sfp = boost::dynamic_pointer_cast<SilentFileSource> (*sx);
1734 sfp->set_length (region->length());
1739 if (!master_sources.empty()) {
1740 if (master_sources.size() != nchans) {
1741 error << _("Session: XMLNode describing an AudioRegion is missing some master sources; ignored") << endmsg;
1743 region->set_master_sources (master_sources);
1751 catch (failed_constructor& err) {
1752 return boost::shared_ptr<AudioRegion>();
1756 boost::shared_ptr<MidiRegion>
1757 Session::XMLMidiRegionFactory (const XMLNode& node, bool /*full*/)
1759 const XMLProperty* prop;
1760 boost::shared_ptr<Source> source;
1761 boost::shared_ptr<MidiSource> ms;
1764 if (node.name() != X_("Region")) {
1765 return boost::shared_ptr<MidiRegion>();
1768 if ((prop = node.property ("name")) == 0) {
1769 cerr << "no name for this region\n";
1773 if ((prop = node.property (X_("source-0"))) == 0) {
1774 if ((prop = node.property ("source")) == 0) {
1775 error << _("Session: XMLNode describing a MidiRegion is incomplete (no source)") << endmsg;
1776 return boost::shared_ptr<MidiRegion>();
1780 PBD::ID s_id (prop->value());
1782 if ((source = source_by_id (s_id)) == 0) {
1783 error << string_compose(_("Session: XMLNode describing a MidiRegion references an unknown source id =%1"), s_id) << endmsg;
1784 return boost::shared_ptr<MidiRegion>();
1787 ms = boost::dynamic_pointer_cast<MidiSource>(source);
1789 error << string_compose(_("Session: XMLNode describing a MidiRegion references a non-midi source id =%1"), s_id) << endmsg;
1790 return boost::shared_ptr<MidiRegion>();
1793 sources.push_back (ms);
1796 boost::shared_ptr<MidiRegion> region (boost::dynamic_pointer_cast<MidiRegion> (RegionFactory::create (sources, node)));
1797 /* a final detail: this is the one and only place that we know how long missing files are */
1799 if (region->whole_file()) {
1800 for (SourceList::iterator sx = sources.begin(); sx != sources.end(); ++sx) {
1801 boost::shared_ptr<SilentFileSource> sfp = boost::dynamic_pointer_cast<SilentFileSource> (*sx);
1803 sfp->set_length (region->length());
1811 catch (failed_constructor& err) {
1812 return boost::shared_ptr<MidiRegion>();
1817 Session::get_sources_as_xml ()
1820 XMLNode* node = new XMLNode (X_("Sources"));
1821 Glib::Threads::Mutex::Lock lm (source_lock);
1823 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ++i) {
1824 node->add_child_nocopy (i->second->get_state());
1831 Session::path_from_region_name (DataType type, string name, string identifier)
1833 char buf[PATH_MAX+1];
1835 SessionDirectory sdir(get_best_session_directory_for_new_source());
1836 std::string source_dir = ((type == DataType::AUDIO)
1837 ? sdir.sound_path() : sdir.midi_path());
1839 string ext = native_header_format_extension (config.get_native_file_header_format(), type);
1841 for (n = 0; n < 999999; ++n) {
1842 if (identifier.length()) {
1843 snprintf (buf, sizeof(buf), "%s%s%" PRIu32 "%s", name.c_str(),
1844 identifier.c_str(), n, ext.c_str());
1846 snprintf (buf, sizeof(buf), "%s-%" PRIu32 "%s", name.c_str(),
1850 std::string source_path = Glib::build_filename (source_dir, buf);
1852 if (!Glib::file_test (source_path, Glib::FILE_TEST_EXISTS)) {
1857 error << string_compose (_("cannot create new file from region name \"%1\" with ident = \"%2\": too many existing files with similar names"),
1866 Session::load_sources (const XMLNode& node)
1869 XMLNodeConstIterator niter;
1870 boost::shared_ptr<Source> source;
1872 nlist = node.children();
1876 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1879 if ((source = XMLSourceFactory (**niter)) == 0) {
1880 error << _("Session: cannot create Source from XML description.") << endmsg;
1883 } catch (MissingSource& err) {
1887 if (!no_questions_about_missing_files) {
1888 user_choice = MissingFile (this, err.path, err.type).get_value_or (-1);
1893 switch (user_choice) {
1895 /* user added a new search location, so try again */
1900 /* user asked to quit the entire session load
1905 no_questions_about_missing_files = true;
1909 no_questions_about_missing_files = true;
1914 warning << _("A sound file is missing. It will be replaced by silence.") << endmsg;
1915 source = SourceFactory::createSilent (*this, **niter, max_framecnt, _current_frame_rate);
1924 boost::shared_ptr<Source>
1925 Session::XMLSourceFactory (const XMLNode& node)
1927 if (node.name() != "Source") {
1928 return boost::shared_ptr<Source>();
1932 /* note: do peak building in another thread when loading session state */
1933 return SourceFactory::create (*this, node, true);
1936 catch (failed_constructor& err) {
1937 error << string_compose (_("Found a sound file that cannot be used by %1. Talk to the progammers."), PROGRAM_NAME) << endmsg;
1938 return boost::shared_ptr<Source>();
1943 Session::save_template (string template_name)
1947 if (_state_of_the_state & CannotSave) {
1951 std::string user_template_dir(user_template_directory());
1953 if (g_mkdir_with_parents (user_template_dir.c_str(), 0755) != 0) {
1954 error << string_compose(_("Could not create templates directory \"%1\" (%2)"),
1955 user_template_dir, g_strerror (errno)) << endmsg;
1959 tree.set_root (&get_template());
1961 std::string template_dir_path(user_template_dir);
1963 /* directory to put the template in */
1964 template_dir_path = Glib::build_filename (template_dir_path, template_name);
1966 if (Glib::file_test (template_dir_path, Glib::FILE_TEST_EXISTS)) {
1967 warning << string_compose(_("Template \"%1\" already exists - new version not created"),
1968 template_dir_path) << endmsg;
1972 if (g_mkdir_with_parents (template_dir_path.c_str(), 0755) != 0) {
1973 error << string_compose(_("Could not create directory for Session template\"%1\" (%2)"),
1974 template_dir_path, g_strerror (errno)) << endmsg;
1979 std::string template_file_path(template_dir_path);
1980 template_file_path = Glib::build_filename (template_file_path, template_name + template_suffix);
1982 if (!tree.write (template_file_path)) {
1983 error << _("template not saved") << endmsg;
1987 /* copy plugin state directory */
1989 std::string template_plugin_state_path(template_dir_path);
1990 template_plugin_state_path = Glib::build_filename (template_plugin_state_path, X_("plugins"));
1992 if (g_mkdir_with_parents (template_plugin_state_path.c_str(), 0755) != 0) {
1993 error << string_compose(_("Could not create directory for Session template plugin state\"%1\" (%2)"),
1994 template_plugin_state_path, g_strerror (errno)) << endmsg;
1998 copy_files (plugins_dir(), template_plugin_state_path);
2004 Session::refresh_disk_space ()
2006 #if __APPLE__ || (HAVE_SYS_VFS_H && HAVE_SYS_STATVFS_H)
2008 Glib::Threads::Mutex::Lock lm (space_lock);
2010 /* get freespace on every FS that is part of the session path */
2012 _total_free_4k_blocks = 0;
2013 _total_free_4k_blocks_uncertain = false;
2015 for (vector<space_and_path>::iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
2017 struct statfs statfsbuf;
2018 statfs (i->path.c_str(), &statfsbuf);
2020 double const scale = statfsbuf.f_bsize / 4096.0;
2022 /* See if this filesystem is read-only */
2023 struct statvfs statvfsbuf;
2024 statvfs (i->path.c_str(), &statvfsbuf);
2026 /* f_bavail can be 0 if it is undefined for whatever
2027 filesystem we are looking at; Samba shares mounted
2028 via GVFS are an example of this.
2030 if (statfsbuf.f_bavail == 0) {
2031 /* block count unknown */
2033 i->blocks_unknown = true;
2034 } else if (statvfsbuf.f_flag & ST_RDONLY) {
2035 /* read-only filesystem */
2037 i->blocks_unknown = false;
2039 /* read/write filesystem with known space */
2040 i->blocks = (uint32_t) floor (statfsbuf.f_bavail * scale);
2041 i->blocks_unknown = false;
2044 _total_free_4k_blocks += i->blocks;
2045 if (i->blocks_unknown) {
2046 _total_free_4k_blocks_uncertain = true;
2053 Session::get_best_session_directory_for_new_source ()
2055 vector<space_and_path>::iterator i;
2056 string result = _session_dir->root_path();
2058 /* handle common case without system calls */
2060 if (session_dirs.size() == 1) {
2064 /* OK, here's the algorithm we're following here:
2066 We want to select which directory to use for
2067 the next file source to be created. Ideally,
2068 we'd like to use a round-robin process so as to
2069 get maximum performance benefits from splitting
2070 the files across multiple disks.
2072 However, in situations without much diskspace, an
2073 RR approach may end up filling up a filesystem
2074 with new files while others still have space.
2075 Its therefore important to pay some attention to
2076 the freespace in the filesystem holding each
2077 directory as well. However, if we did that by
2078 itself, we'd keep creating new files in the file
2079 system with the most space until it was as full
2080 as all others, thus negating any performance
2081 benefits of this RAID-1 like approach.
2083 So, we use a user-configurable space threshold. If
2084 there are at least 2 filesystems with more than this
2085 much space available, we use RR selection between them.
2086 If not, then we pick the filesystem with the most space.
2088 This gets a good balance between the two
2092 refresh_disk_space ();
2094 int free_enough = 0;
2096 for (i = session_dirs.begin(); i != session_dirs.end(); ++i) {
2097 if ((*i).blocks * 4096 >= Config->get_disk_choice_space_threshold()) {
2102 if (free_enough >= 2) {
2103 /* use RR selection process, ensuring that the one
2107 i = last_rr_session_dir;
2110 if (++i == session_dirs.end()) {
2111 i = session_dirs.begin();
2114 if ((*i).blocks * 4096 >= Config->get_disk_choice_space_threshold()) {
2115 SessionDirectory sdir(i->path);
2116 if (sdir.create ()) {
2118 last_rr_session_dir = i;
2123 } while (i != last_rr_session_dir);
2127 /* pick FS with the most freespace (and that
2128 seems to actually work ...)
2131 vector<space_and_path> sorted;
2132 space_and_path_ascending_cmp cmp;
2134 sorted = session_dirs;
2135 sort (sorted.begin(), sorted.end(), cmp);
2137 for (i = sorted.begin(); i != sorted.end(); ++i) {
2138 SessionDirectory sdir(i->path);
2139 if (sdir.create ()) {
2141 last_rr_session_dir = i;
2151 Session::automation_dir () const
2153 return Glib::build_filename (_path, "automation");
2157 Session::analysis_dir () const
2159 return Glib::build_filename (_path, "analysis");
2163 Session::plugins_dir () const
2165 return Glib::build_filename (_path, "plugins");
2169 Session::externals_dir () const
2171 return Glib::build_filename (_path, "externals");
2175 Session::load_bundles (XMLNode const & node)
2177 XMLNodeList nlist = node.children();
2178 XMLNodeConstIterator niter;
2182 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2183 if ((*niter)->name() == "InputBundle") {
2184 add_bundle (boost::shared_ptr<UserBundle> (new UserBundle (**niter, true)));
2185 } else if ((*niter)->name() == "OutputBundle") {
2186 add_bundle (boost::shared_ptr<UserBundle> (new UserBundle (**niter, false)));
2188 error << string_compose(_("Unknown node \"%1\" found in Bundles list from session file"), (*niter)->name()) << endmsg;
2197 Session::load_route_groups (const XMLNode& node, int version)
2199 XMLNodeList nlist = node.children();
2200 XMLNodeConstIterator niter;
2204 if (version >= 3000) {
2206 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2207 if ((*niter)->name() == "RouteGroup") {
2208 RouteGroup* rg = new RouteGroup (*this, "");
2209 add_route_group (rg);
2210 rg->set_state (**niter, version);
2214 } else if (version < 3000) {
2216 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2217 if ((*niter)->name() == "EditGroup" || (*niter)->name() == "MixGroup") {
2218 RouteGroup* rg = new RouteGroup (*this, "");
2219 add_route_group (rg);
2220 rg->set_state (**niter, version);
2229 Session::auto_save()
2231 save_state (_current_snapshot_name);
2235 state_file_filter (const string &str, void */*arg*/)
2237 return (str.length() > strlen(statefile_suffix) &&
2238 str.find (statefile_suffix) == (str.length() - strlen (statefile_suffix)));
2242 bool operator()(const string* a, const string* b) {
2248 remove_end(string* state)
2250 string statename(*state);
2252 string::size_type start,end;
2253 if ((start = statename.find_last_of (G_DIR_SEPARATOR)) != string::npos) {
2254 statename = statename.substr (start+1);
2257 if ((end = statename.rfind(".ardour")) == string::npos) {
2258 end = statename.length();
2261 return new string(statename.substr (0, end));
2265 Session::possible_states (string path)
2267 PathScanner scanner;
2268 vector<string*>* states = scanner (path, state_file_filter, 0, false, false);
2270 transform(states->begin(), states->end(), states->begin(), remove_end);
2273 sort (states->begin(), states->end(), cmp);
2279 Session::possible_states () const
2281 return possible_states(_path);
2285 Session::add_route_group (RouteGroup* g)
2287 _route_groups.push_back (g);
2288 route_group_added (g); /* EMIT SIGNAL */
2290 g->RouteAdded.connect_same_thread (*this, boost::bind (&Session::route_added_to_route_group, this, _1, _2));
2291 g->RouteRemoved.connect_same_thread (*this, boost::bind (&Session::route_removed_from_route_group, this, _1, _2));
2292 g->PropertyChanged.connect_same_thread (*this, boost::bind (&Session::route_group_property_changed, this, g));
2298 Session::remove_route_group (RouteGroup& rg)
2300 list<RouteGroup*>::iterator i;
2302 if ((i = find (_route_groups.begin(), _route_groups.end(), &rg)) != _route_groups.end()) {
2303 _route_groups.erase (i);
2306 route_group_removed (); /* EMIT SIGNAL */
2310 /** Set a new order for our route groups, without adding or removing any.
2311 * @param groups Route group list in the new order.
2314 Session::reorder_route_groups (list<RouteGroup*> groups)
2316 _route_groups = groups;
2318 route_groups_reordered (); /* EMIT SIGNAL */
2324 Session::route_group_by_name (string name)
2326 list<RouteGroup *>::iterator i;
2328 for (i = _route_groups.begin(); i != _route_groups.end(); ++i) {
2329 if ((*i)->name() == name) {
2337 Session::all_route_group() const
2339 return *_all_route_group;
2343 Session::add_commands (vector<Command*> const & cmds)
2345 for (vector<Command*>::const_iterator i = cmds.begin(); i != cmds.end(); ++i) {
2351 Session::begin_reversible_command (const string& name)
2353 begin_reversible_command (g_quark_from_string (name.c_str ()));
2356 /** Begin a reversible command using a GQuark to identify it.
2357 * begin_reversible_command() and commit_reversible_command() calls may be nested,
2358 * but there must be as many begin...()s as there are commit...()s.
2361 Session::begin_reversible_command (GQuark q)
2363 /* If nested begin/commit pairs are used, we create just one UndoTransaction
2364 to hold all the commands that are committed. This keeps the order of
2365 commands correct in the history.
2368 if (_current_trans == 0) {
2369 /* start a new transaction */
2370 assert (_current_trans_quarks.empty ());
2371 _current_trans = new UndoTransaction();
2372 _current_trans->set_name (g_quark_to_string (q));
2375 _current_trans_quarks.push_front (q);
2379 Session::commit_reversible_command (Command *cmd)
2381 assert (_current_trans);
2382 assert (!_current_trans_quarks.empty ());
2387 _current_trans->add_command (cmd);
2390 _current_trans_quarks.pop_front ();
2392 if (!_current_trans_quarks.empty ()) {
2393 /* the transaction we're committing is not the top-level one */
2397 if (_current_trans->empty()) {
2398 /* no commands were added to the transaction, so just get rid of it */
2399 delete _current_trans;
2404 gettimeofday (&now, 0);
2405 _current_trans->set_timestamp (now);
2407 _history.add (_current_trans);
2412 accept_all_audio_files (const string& path, void */*arg*/)
2414 if (!Glib::file_test (path, Glib::FILE_TEST_IS_REGULAR)) {
2418 if (!AudioFileSource::safe_audio_file_extension (path)) {
2426 accept_all_midi_files (const string& path, void */*arg*/)
2428 if (!Glib::file_test (path, Glib::FILE_TEST_IS_REGULAR)) {
2432 return ((path.length() > 4 && path.find (".mid") != (path.length() - 4)) ||
2433 (path.length() > 4 && path.find (".smf") != (path.length() - 4)) ||
2434 (path.length() > 5 && path.find (".midi") != (path.length() - 5)));
2438 accept_all_state_files (const string& path, void */*arg*/)
2440 if (!Glib::file_test (path, Glib::FILE_TEST_IS_REGULAR)) {
2444 return (path.length() > 7 && path.find (".ardour") == (path.length() - 7));
2448 Session::find_all_sources (string path, set<string>& result)
2453 if (!tree.read (path)) {
2457 if ((node = find_named_node (*tree.root(), "Sources")) == 0) {
2462 XMLNodeConstIterator niter;
2464 nlist = node->children();
2468 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2472 if ((prop = (*niter)->property (X_("type"))) == 0) {
2476 DataType type (prop->value());
2478 if ((prop = (*niter)->property (X_("name"))) == 0) {
2482 if (Glib::path_is_absolute (prop->value())) {
2483 /* external file, ignore */
2491 if (FileSource::find (*this, type, prop->value(), true, is_new, chan, found_path)) {
2492 result.insert (found_path);
2500 Session::find_all_sources_across_snapshots (set<string>& result, bool exclude_this_snapshot)
2502 PathScanner scanner;
2503 vector<string*>* state_files;
2505 string this_snapshot_path;
2511 if (ripped[ripped.length()-1] == G_DIR_SEPARATOR) {
2512 ripped = ripped.substr (0, ripped.length() - 1);
2515 state_files = scanner (ripped, accept_all_state_files, (void *) 0, true, true);
2517 if (state_files == 0) {
2522 this_snapshot_path = _path;
2523 this_snapshot_path += legalize_for_path (_current_snapshot_name);
2524 this_snapshot_path += statefile_suffix;
2526 for (vector<string*>::iterator i = state_files->begin(); i != state_files->end(); ++i) {
2528 if (exclude_this_snapshot && **i == this_snapshot_path) {
2532 if (find_all_sources (**i, result) < 0) {
2540 struct RegionCounter {
2541 typedef std::map<PBD::ID,boost::shared_ptr<AudioSource> > AudioSourceList;
2542 AudioSourceList::iterator iter;
2543 boost::shared_ptr<Region> region;
2546 RegionCounter() : count (0) {}
2550 Session::ask_about_playlist_deletion (boost::shared_ptr<Playlist> p)
2552 boost::optional<int> r = AskAboutPlaylistDeletion (p);
2553 return r.get_value_or (1);
2557 Session::cleanup_regions ()
2559 const RegionFactory::RegionMap& regions (RegionFactory::regions());
2561 for (RegionFactory::RegionMap::const_iterator i = regions.begin(); i != regions.end(); ++i) {
2563 uint32_t used = playlists->region_use_count (i->second);
2565 if (used == 0 && !i->second->automatic ()) {
2566 RegionFactory::map_remove (i->second);
2570 /* dump the history list */
2577 Session::cleanup_sources (CleanupReport& rep)
2579 // FIXME: needs adaptation to midi
2581 vector<boost::shared_ptr<Source> > dead_sources;
2582 PathScanner scanner;
2585 vector<space_and_path>::iterator i;
2586 vector<space_and_path>::iterator nexti;
2587 vector<string*>* candidates;
2588 vector<string*>* candidates2;
2589 vector<string> unused;
2590 set<string> all_sources;
2595 _state_of_the_state = (StateOfTheState) (_state_of_the_state | InCleanup);
2597 /* consider deleting all unused playlists */
2599 if (playlists->maybe_delete_unused (boost::bind (Session::ask_about_playlist_deletion, _1))) {
2604 /* sync the "all regions" property of each playlist with its current state
2607 playlists->sync_all_regions_with_regions ();
2609 /* find all un-used sources */
2614 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ) {
2616 SourceMap::iterator tmp;
2621 /* do not bother with files that are zero size, otherwise we remove the current "nascent"
2625 if (!i->second->used() && (i->second->length(i->second->timeline_position() > 0))) {
2626 dead_sources.push_back (i->second);
2627 i->second->drop_references ();
2633 /* build a list of all the possible audio directories for the session */
2635 for (i = session_dirs.begin(); i != session_dirs.end(); ) {
2640 SessionDirectory sdir ((*i).path);
2641 audio_path += sdir.sound_path();
2643 if (nexti != session_dirs.end()) {
2651 /* build a list of all the possible midi directories for the session */
2653 for (i = session_dirs.begin(); i != session_dirs.end(); ) {
2658 SessionDirectory sdir ((*i).path);
2659 midi_path += sdir.midi_path();
2661 if (nexti != session_dirs.end()) {
2668 candidates = scanner (audio_path, accept_all_audio_files, (void *) 0, true, true);
2669 candidates2 = scanner (midi_path, accept_all_midi_files, (void *) 0, true, true);
2675 for (vector<string*>::iterator i = candidates2->begin(); i != candidates2->end(); ++i) {
2676 candidates->push_back (*i);
2681 candidates = candidates2; // might still be null
2684 /* find all sources, but don't use this snapshot because the
2685 state file on disk still references sources we may have already
2689 find_all_sources_across_snapshots (all_sources, true);
2691 /* add our current source list
2694 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ) {
2695 boost::shared_ptr<FileSource> fs;
2696 SourceMap::iterator tmp = i;
2699 if ((fs = boost::dynamic_pointer_cast<FileSource> (i->second)) != 0) {
2700 if (playlists->source_use_count (fs) != 0) {
2701 all_sources.insert (fs->path());
2704 /* we might not remove this source from disk, because it may be used
2705 by other snapshots, but its not being used in this version
2706 so lets get rid of it now, along with any representative regions
2710 RegionFactory::remove_regions_using_source (i->second);
2718 char tmppath1[PATH_MAX+1];
2719 char tmppath2[PATH_MAX+1];
2722 for (vector<string*>::iterator x = candidates->begin(); x != candidates->end(); ++x) {
2727 for (set<string>::iterator i = all_sources.begin(); i != all_sources.end(); ++i) {
2729 if (realpath(spath.c_str(), tmppath1) == 0) {
2730 error << string_compose (_("Cannot expand path %1 (%2)"),
2731 spath, strerror (errno)) << endmsg;
2735 if (realpath((*i).c_str(), tmppath2) == 0) {
2736 error << string_compose (_("Cannot expand path %1 (%2)"),
2737 (*i), strerror (errno)) << endmsg;
2741 if (strcmp(tmppath1, tmppath2) == 0) {
2748 unused.push_back (spath);
2757 /* now try to move all unused files into the "dead" directory(ies) */
2759 for (vector<string>::iterator x = unused.begin(); x != unused.end(); ++x) {
2760 struct stat statbuf;
2764 /* don't move the file across filesystems, just
2765 stick it in the `dead_dir_name' directory
2766 on whichever filesystem it was already on.
2769 if ((*x).find ("/sounds/") != string::npos) {
2771 /* old school, go up 1 level */
2773 newpath = Glib::path_get_dirname (*x); // "sounds"
2774 newpath = Glib::path_get_dirname (newpath); // "session-name"
2778 /* new school, go up 4 levels */
2780 newpath = Glib::path_get_dirname (*x); // "audiofiles" or "midifiles"
2781 newpath = Glib::path_get_dirname (newpath); // "session-name"
2782 newpath = Glib::path_get_dirname (newpath); // "interchange"
2783 newpath = Glib::path_get_dirname (newpath); // "session-dir"
2786 newpath = Glib::build_filename (newpath, dead_dir_name);
2788 if (g_mkdir_with_parents (newpath.c_str(), 0755) < 0) {
2789 error << string_compose(_("Session: cannot create dead file folder \"%1\" (%2)"), newpath, strerror (errno)) << endmsg;
2793 newpath = Glib::build_filename (newpath, Glib::path_get_basename ((*x)));
2795 if (Glib::file_test (newpath, Glib::FILE_TEST_EXISTS)) {
2797 /* the new path already exists, try versioning */
2799 char buf[PATH_MAX+1];
2803 snprintf (buf, sizeof (buf), "%s.%d", newpath.c_str(), version);
2806 while (Glib::file_test (newpath_v.c_str(), Glib::FILE_TEST_EXISTS) && version < 999) {
2807 snprintf (buf, sizeof (buf), "%s.%d", newpath.c_str(), ++version);
2811 if (version == 999) {
2812 error << string_compose (_("there are already 1000 files with names like %1; versioning discontinued"),
2816 newpath = newpath_v;
2821 /* it doesn't exist, or we can't read it or something */
2825 stat ((*x).c_str(), &statbuf);
2827 if (::rename ((*x).c_str(), newpath.c_str()) != 0) {
2828 error << string_compose (_("cannot rename unused file source from %1 to %2 (%3)"),
2829 (*x), newpath, strerror (errno))
2834 /* see if there an easy to find peakfile for this file, and remove it.
2837 string base = basename_nosuffix (*x);
2838 base += "%A"; /* this is what we add for the channel suffix of all native files,
2839 or for the first channel of embedded files. it will miss
2840 some peakfiles for other channels
2842 string peakpath = peak_path (base);
2844 if (Glib::file_test (peakpath.c_str(), Glib::FILE_TEST_EXISTS)) {
2845 if (::unlink (peakpath.c_str()) != 0) {
2846 error << string_compose (_("cannot remove peakfile %1 for %2 (%3)"),
2847 peakpath, _path, strerror (errno))
2849 /* try to back out */
2850 ::rename (newpath.c_str(), _path.c_str());
2855 rep.paths.push_back (*x);
2856 rep.space += statbuf.st_size;
2859 /* dump the history list */
2863 /* save state so we don't end up a session file
2864 referring to non-existent sources.
2871 _state_of_the_state = (StateOfTheState) (_state_of_the_state & ~InCleanup);
2877 Session::cleanup_trash_sources (CleanupReport& rep)
2879 // FIXME: needs adaptation for MIDI
2881 vector<space_and_path>::iterator i;
2887 for (i = session_dirs.begin(); i != session_dirs.end(); ++i) {
2889 dead_dir = Glib::build_filename ((*i).path, dead_dir_name);
2891 clear_directory (dead_dir, &rep.space, &rep.paths);
2898 Session::set_dirty ()
2900 bool was_dirty = dirty();
2902 _state_of_the_state = StateOfTheState (_state_of_the_state | Dirty);
2906 DirtyChanged(); /* EMIT SIGNAL */
2912 Session::set_clean ()
2914 bool was_dirty = dirty();
2916 _state_of_the_state = Clean;
2920 DirtyChanged(); /* EMIT SIGNAL */
2925 Session::set_deletion_in_progress ()
2927 _state_of_the_state = StateOfTheState (_state_of_the_state | Deletion);
2931 Session::clear_deletion_in_progress ()
2933 _state_of_the_state = StateOfTheState (_state_of_the_state & (~Deletion));
2937 Session::add_controllable (boost::shared_ptr<Controllable> c)
2939 /* this adds a controllable to the list managed by the Session.
2940 this is a subset of those managed by the Controllable class
2941 itself, and represents the only ones whose state will be saved
2942 as part of the session.
2945 Glib::Threads::Mutex::Lock lm (controllables_lock);
2946 controllables.insert (c);
2949 struct null_deleter { void operator()(void const *) const {} };
2952 Session::remove_controllable (Controllable* c)
2954 if (_state_of_the_state & Deletion) {
2958 Glib::Threads::Mutex::Lock lm (controllables_lock);
2960 Controllables::iterator x = controllables.find (boost::shared_ptr<Controllable>(c, null_deleter()));
2962 if (x != controllables.end()) {
2963 controllables.erase (x);
2967 boost::shared_ptr<Controllable>
2968 Session::controllable_by_id (const PBD::ID& id)
2970 Glib::Threads::Mutex::Lock lm (controllables_lock);
2972 for (Controllables::iterator i = controllables.begin(); i != controllables.end(); ++i) {
2973 if ((*i)->id() == id) {
2978 return boost::shared_ptr<Controllable>();
2981 boost::shared_ptr<Controllable>
2982 Session::controllable_by_descriptor (const ControllableDescriptor& desc)
2984 boost::shared_ptr<Controllable> c;
2985 boost::shared_ptr<Route> r;
2987 switch (desc.top_level_type()) {
2988 case ControllableDescriptor::NamedRoute:
2990 std::string str = desc.top_level_name();
2991 if (str == "master") {
2993 } else if (str == "control" || str == "listen") {
2996 r = route_by_name (desc.top_level_name());
3001 case ControllableDescriptor::RemoteControlID:
3002 r = route_by_remote_id (desc.rid());
3010 switch (desc.subtype()) {
3011 case ControllableDescriptor::Gain:
3012 c = r->gain_control ();
3015 case ControllableDescriptor::Solo:
3016 c = r->solo_control();
3019 case ControllableDescriptor::Mute:
3020 c = r->mute_control();
3023 case ControllableDescriptor::Recenable:
3025 boost::shared_ptr<Track> t = boost::dynamic_pointer_cast<Track>(r);
3028 c = t->rec_enable_control ();
3033 case ControllableDescriptor::PanDirection:
3035 c = r->pannable()->pan_azimuth_control;
3039 case ControllableDescriptor::PanWidth:
3041 c = r->pannable()->pan_width_control;
3045 case ControllableDescriptor::PanElevation:
3047 c = r->pannable()->pan_elevation_control;
3051 case ControllableDescriptor::Balance:
3052 /* XXX simple pan control */
3055 case ControllableDescriptor::PluginParameter:
3057 uint32_t plugin = desc.target (0);
3058 uint32_t parameter_index = desc.target (1);
3060 /* revert to zero based counting */
3066 if (parameter_index > 0) {
3070 boost::shared_ptr<Processor> p = r->nth_plugin (plugin);
3073 c = boost::dynamic_pointer_cast<ARDOUR::AutomationControl>(
3074 p->control(Evoral::Parameter(PluginAutomation, 0, parameter_index)));
3079 case ControllableDescriptor::SendGain:
3081 uint32_t send = desc.target (0);
3083 /* revert to zero-based counting */
3089 boost::shared_ptr<Processor> p = r->nth_send (send);
3092 boost::shared_ptr<Send> s = boost::dynamic_pointer_cast<Send>(p);
3093 boost::shared_ptr<Amp> a = s->amp();
3096 c = s->amp()->gain_control();
3103 /* relax and return a null pointer */
3111 Session::add_instant_xml (XMLNode& node, bool write_to_config)
3114 Stateful::add_instant_xml (node, _path);
3117 if (write_to_config) {
3118 Config->add_instant_xml (node);
3123 Session::instant_xml (const string& node_name)
3125 return Stateful::instant_xml (node_name, _path);
3129 Session::save_history (string snapshot_name)
3137 if (snapshot_name.empty()) {
3138 snapshot_name = _current_snapshot_name;
3141 const string history_filename = legalize_for_path (snapshot_name) + history_suffix;
3142 const string backup_filename = history_filename + backup_suffix;
3143 const std::string xml_path(Glib::build_filename (_session_dir->root_path(), history_filename));
3144 const std::string backup_path(Glib::build_filename (_session_dir->root_path(), backup_filename));
3146 if (Glib::file_test (xml_path, Glib::FILE_TEST_EXISTS)) {
3147 if (::g_rename (xml_path.c_str(), backup_path.c_str()) != 0) {
3148 error << _("could not backup old history file, current history not saved") << endmsg;
3153 if (!Config->get_save_history() || Config->get_saved_history_depth() < 0) {
3157 tree.set_root (&_history.get_state (Config->get_saved_history_depth()));
3159 if (!tree.write (xml_path))
3161 error << string_compose (_("history could not be saved to %1"), xml_path) << endmsg;
3163 if (g_remove (xml_path.c_str()) != 0) {
3164 error << string_compose(_("Could not remove history file at path \"%1\" (%2)"),
3165 xml_path, g_strerror (errno)) << endmsg;
3167 if (::g_rename (backup_path.c_str(), xml_path.c_str()) != 0) {
3168 error << string_compose (_("could not restore history file from backup %1 (%2)"),
3169 backup_path, g_strerror (errno)) << endmsg;
3179 Session::restore_history (string snapshot_name)
3183 if (snapshot_name.empty()) {
3184 snapshot_name = _current_snapshot_name;
3187 const std::string xml_filename = legalize_for_path (snapshot_name) + history_suffix;
3188 const std::string xml_path(Glib::build_filename (_session_dir->root_path(), xml_filename));
3190 info << "Loading history from " << xml_path << endmsg;
3192 if (!Glib::file_test (xml_path, Glib::FILE_TEST_EXISTS)) {
3193 info << string_compose (_("%1: no history file \"%2\" for this session."),
3194 _name, xml_path) << endmsg;
3198 if (!tree.read (xml_path)) {
3199 error << string_compose (_("Could not understand session history file \"%1\""),
3200 xml_path) << endmsg;
3207 for (XMLNodeConstIterator it = tree.root()->children().begin(); it != tree.root()->children().end(); it++) {
3210 UndoTransaction* ut = new UndoTransaction ();
3213 ut->set_name(t->property("name")->value());
3214 stringstream ss(t->property("tv-sec")->value());
3216 ss.str(t->property("tv-usec")->value());
3218 ut->set_timestamp(tv);
3220 for (XMLNodeConstIterator child_it = t->children().begin();
3221 child_it != t->children().end(); child_it++)
3223 XMLNode *n = *child_it;
3226 if (n->name() == "MementoCommand" ||
3227 n->name() == "MementoUndoCommand" ||
3228 n->name() == "MementoRedoCommand") {
3230 if ((c = memento_command_factory(n))) {
3234 } else if (n->name() == "NoteDiffCommand") {
3235 PBD::ID id (n->property("midi-source")->value());
3236 boost::shared_ptr<MidiSource> midi_source =
3237 boost::dynamic_pointer_cast<MidiSource, Source>(source_by_id(id));
3239 ut->add_command (new MidiModel::NoteDiffCommand(midi_source->model(), *n));
3241 error << _("Failed to downcast MidiSource for NoteDiffCommand") << endmsg;
3244 } else if (n->name() == "SysExDiffCommand") {
3246 PBD::ID id (n->property("midi-source")->value());
3247 boost::shared_ptr<MidiSource> midi_source =
3248 boost::dynamic_pointer_cast<MidiSource, Source>(source_by_id(id));
3250 ut->add_command (new MidiModel::SysExDiffCommand (midi_source->model(), *n));
3252 error << _("Failed to downcast MidiSource for SysExDiffCommand") << endmsg;
3255 } else if (n->name() == "PatchChangeDiffCommand") {
3257 PBD::ID id (n->property("midi-source")->value());
3258 boost::shared_ptr<MidiSource> midi_source =
3259 boost::dynamic_pointer_cast<MidiSource, Source>(source_by_id(id));
3261 ut->add_command (new MidiModel::PatchChangeDiffCommand (midi_source->model(), *n));
3263 error << _("Failed to downcast MidiSource for PatchChangeDiffCommand") << endmsg;
3266 } else if (n->name() == "StatefulDiffCommand") {
3267 if ((c = stateful_diff_command_factory (n))) {
3268 ut->add_command (c);
3271 error << string_compose(_("Couldn't figure out how to make a Command out of a %1 XMLNode."), n->name()) << endmsg;
3282 Session::config_changed (std::string p, bool ours)
3288 if (p == "seamless-loop") {
3290 } else if (p == "rf-speed") {
3292 } else if (p == "auto-loop") {
3294 } else if (p == "auto-input") {
3296 if (Config->get_monitoring_model() == HardwareMonitoring && transport_rolling()) {
3297 /* auto-input only makes a difference if we're rolling */
3298 set_track_monitor_input_status (!config.get_auto_input());
3301 } else if (p == "punch-in") {
3305 if ((location = _locations->auto_punch_location()) != 0) {
3307 if (config.get_punch_in ()) {
3308 replace_event (SessionEvent::PunchIn, location->start());
3310 remove_event (location->start(), SessionEvent::PunchIn);
3314 } else if (p == "punch-out") {
3318 if ((location = _locations->auto_punch_location()) != 0) {
3320 if (config.get_punch_out()) {
3321 replace_event (SessionEvent::PunchOut, location->end());
3323 clear_events (SessionEvent::PunchOut);
3327 } else if (p == "edit-mode") {
3329 Glib::Threads::Mutex::Lock lm (playlists->lock);
3331 for (SessionPlaylists::List::iterator i = playlists->playlists.begin(); i != playlists->playlists.end(); ++i) {
3332 (*i)->set_edit_mode (Config->get_edit_mode ());
3335 } else if (p == "use-video-sync") {
3337 waiting_for_sync_offset = config.get_use_video_sync();
3339 } else if (p == "mmc-control") {
3341 //poke_midi_thread ();
3343 } else if (p == "mmc-device-id" || p == "mmc-receive-id" || p == "mmc-receive-device-id") {
3345 _mmc->set_receive_device_id (Config->get_mmc_receive_device_id());
3347 } else if (p == "mmc-send-id" || p == "mmc-send-device-id") {
3349 _mmc->set_send_device_id (Config->get_mmc_send_device_id());
3351 } else if (p == "midi-control") {
3353 //poke_midi_thread ();
3355 } else if (p == "raid-path") {
3357 setup_raid_path (config.get_raid_path());
3359 } else if (p == "timecode-format") {
3363 } else if (p == "video-pullup") {
3367 } else if (p == "seamless-loop") {
3369 if (play_loop && transport_rolling()) {
3370 // to reset diskstreams etc
3371 request_play_loop (true);
3374 } else if (p == "rf-speed") {
3376 cumulative_rf_motion = 0;
3379 } else if (p == "click-sound") {
3381 setup_click_sounds (1);
3383 } else if (p == "click-emphasis-sound") {
3385 setup_click_sounds (-1);
3387 } else if (p == "clicking") {
3389 if (Config->get_clicking()) {
3390 if (_click_io && click_data) { // don't require emphasis data
3397 } else if (p == "click-gain") {
3400 _click_gain->set_gain (Config->get_click_gain(), this);
3403 } else if (p == "send-mtc") {
3405 if (Config->get_send_mtc ()) {
3406 /* mark us ready to send */
3407 next_quarter_frame_to_send = 0;
3410 } else if (p == "send-mmc") {
3412 _mmc->enable_send (Config->get_send_mmc ());
3414 } else if (p == "midi-feedback") {
3416 session_midi_feedback = Config->get_midi_feedback();
3418 } else if (p == "jack-time-master") {
3420 engine().reset_timebase ();
3422 } else if (p == "native-file-header-format") {
3424 if (!first_file_header_format_reset) {
3425 reset_native_file_format ();
3428 first_file_header_format_reset = false;
3430 } else if (p == "native-file-data-format") {
3432 if (!first_file_data_format_reset) {
3433 reset_native_file_format ();
3436 first_file_data_format_reset = false;
3438 } else if (p == "external-sync") {
3439 if (!config.get_external_sync()) {
3440 drop_sync_source ();
3442 switch_to_sync_source (Config->get_sync_source());
3444 } else if (p == "denormal-model") {
3446 } else if (p == "history-depth") {
3447 set_history_depth (Config->get_history_depth());
3448 } else if (p == "remote-model") {
3449 /* XXX DO SOMETHING HERE TO TELL THE GUI THAT WE NEED
3452 } else if (p == "sync-all-route-ordering") {
3454 /* sync to editor order unless mixer is used for remote IDs
3457 switch (Config->get_remote_model()) {
3459 sync_order_keys (EditorSort);
3462 sync_order_keys (EditorSort);
3465 sync_order_keys (MixerSort);
3468 } else if (p == "initial-program-change") {
3470 if (_mmc->output_port() && Config->get_initial_program_change() >= 0) {
3473 buf[0] = MIDI::program; // channel zero by default
3474 buf[1] = (Config->get_initial_program_change() & 0x7f);
3476 _mmc->output_port()->midimsg (buf, sizeof (buf), 0);
3478 } else if (p == "solo-mute-override") {
3479 // catch_up_on_solo_mute_override ();
3480 } else if (p == "listen-position" || p == "pfl-position") {
3481 listen_position_changed ();
3482 } else if (p == "solo-control-is-listen-control") {
3483 solo_control_mode_changed ();
3484 } else if (p == "timecode-offset" || p == "timecode-offset-negative") {
3485 last_timecode_valid = false;
3486 } else if (p == "playback-buffer-seconds") {
3487 AudioSource::allocate_working_buffers (frame_rate());
3488 } else if (p == "automation-thinning-factor") {
3489 Evoral::ControlList::set_thinning_factor (Config->get_automation_thinning_factor());
3490 } else if (p == "ltc-source-port") {
3491 reconnect_ltc_input ();
3492 } else if (p == "ltc-sink-port") {
3493 reconnect_ltc_output ();
3494 } else if (p == "timecode-generator-offset") {
3495 ltc_tx_parse_offset();
3502 Session::set_history_depth (uint32_t d)
3504 _history.set_depth (d);
3508 Session::load_diskstreams_2X (XMLNode const & node, int)
3511 XMLNodeConstIterator citer;
3513 clist = node.children();
3515 for (citer = clist.begin(); citer != clist.end(); ++citer) {
3518 /* diskstreams added automatically by DiskstreamCreated handler */
3519 if ((*citer)->name() == "AudioDiskstream" || (*citer)->name() == "DiskStream") {
3520 boost::shared_ptr<AudioDiskstream> dsp (new AudioDiskstream (*this, **citer));
3521 _diskstreams_2X.push_back (dsp);
3523 error << _("Session: unknown diskstream type in XML") << endmsg;
3527 catch (failed_constructor& err) {
3528 error << _("Session: could not load diskstream via XML state") << endmsg;
3536 /** Connect things to the MMC object */
3538 Session::setup_midi_machine_control ()
3540 _mmc = new MIDI::MachineControl;
3541 _mmc->set_ports (_midi_ports->mmc_input_port(), _midi_ports->mmc_output_port());
3543 _mmc->Play.connect_same_thread (*this, boost::bind (&Session::mmc_deferred_play, this, _1));
3544 _mmc->DeferredPlay.connect_same_thread (*this, boost::bind (&Session::mmc_deferred_play, this, _1));
3545 _mmc->Stop.connect_same_thread (*this, boost::bind (&Session::mmc_stop, this, _1));
3546 _mmc->FastForward.connect_same_thread (*this, boost::bind (&Session::mmc_fast_forward, this, _1));
3547 _mmc->Rewind.connect_same_thread (*this, boost::bind (&Session::mmc_rewind, this, _1));
3548 _mmc->Pause.connect_same_thread (*this, boost::bind (&Session::mmc_pause, this, _1));
3549 _mmc->RecordPause.connect_same_thread (*this, boost::bind (&Session::mmc_record_pause, this, _1));
3550 _mmc->RecordStrobe.connect_same_thread (*this, boost::bind (&Session::mmc_record_strobe, this, _1));
3551 _mmc->RecordExit.connect_same_thread (*this, boost::bind (&Session::mmc_record_exit, this, _1));
3552 _mmc->Locate.connect_same_thread (*this, boost::bind (&Session::mmc_locate, this, _1, _2));
3553 _mmc->Step.connect_same_thread (*this, boost::bind (&Session::mmc_step, this, _1, _2));
3554 _mmc->Shuttle.connect_same_thread (*this, boost::bind (&Session::mmc_shuttle, this, _1, _2, _3));
3555 _mmc->TrackRecordStatusChange.connect_same_thread (*this, boost::bind (&Session::mmc_record_enable, this, _1, _2, _3));
3557 /* also handle MIDI SPP because its so common */
3559 _mmc->SPPStart.connect_same_thread (*this, boost::bind (&Session::spp_start, this));
3560 _mmc->SPPContinue.connect_same_thread (*this, boost::bind (&Session::spp_continue, this));
3561 _mmc->SPPStop.connect_same_thread (*this, boost::bind (&Session::spp_stop, this));
3564 boost::shared_ptr<Controllable>
3565 Session::solo_cut_control() const
3567 /* the solo cut control is a bit of an anomaly, at least as of Febrary 2011. There are no other
3568 controls in Ardour that currently get presented to the user in the GUI that require
3569 access as a Controllable and are also NOT owned by some SessionObject (e.g. Route, or MonitorProcessor).
3571 its actually an RCConfiguration parameter, so we use a ProxyControllable to wrap
3572 it up as a Controllable. Changes to the Controllable will just map back to the RCConfiguration
3576 return _solo_cut_control;
3580 Session::rename (const std::string& new_name)
3582 string legal_name = legalize_for_path (new_name);
3588 string const old_sources_root = _session_dir->sources_root();
3590 #define RENAME ::rename
3595 * interchange subdirectory
3599 * Backup files are left unchanged and not renamed.
3602 /* pass one: not 100% safe check that the new directory names don't
3606 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
3611 /* this is a stupid hack because Glib::path_get_dirname() is
3612 * lexical-only, and so passing it /a/b/c/ gives a different
3613 * result than passing it /a/b/c ...
3616 if (oldstr[oldstr.length()-1] == G_DIR_SEPARATOR) {
3617 oldstr = oldstr.substr (0, oldstr.length() - 1);
3620 string base = Glib::path_get_dirname (oldstr);
3621 string p = Glib::path_get_basename (oldstr);
3623 newstr = Glib::build_filename (base, legal_name);
3625 if (Glib::file_test (newstr, Glib::FILE_TEST_EXISTS)) {
3632 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
3637 /* this is a stupid hack because Glib::path_get_dirname() is
3638 * lexical-only, and so passing it /a/b/c/ gives a different
3639 * result than passing it /a/b/c ...
3642 if (oldstr[oldstr.length()-1] == G_DIR_SEPARATOR) {
3643 oldstr = oldstr.substr (0, oldstr.length() - 1);
3646 string base = Glib::path_get_dirname (oldstr);
3647 string p = Glib::path_get_basename (oldstr);
3649 newstr = Glib::build_filename (base, legal_name);
3651 cerr << "Rename " << oldstr << " => " << newstr << endl;
3653 if (RENAME (oldstr.c_str(), newstr.c_str()) != 0) {
3658 (*_session_dir) = newstr;
3663 /* directory below interchange */
3665 v.push_back (newstr);
3666 v.push_back (interchange_dir_name);
3669 oldstr = Glib::build_filename (v);
3672 v.push_back (newstr);
3673 v.push_back (interchange_dir_name);
3674 v.push_back (legal_name);
3676 newstr = Glib::build_filename (v);
3678 cerr << "Rename " << oldstr << " => " << newstr << endl;
3680 if (RENAME (oldstr.c_str(), newstr.c_str()) != 0) {
3687 oldstr = Glib::build_filename (newpath, _current_snapshot_name) + statefile_suffix;
3688 newstr= Glib::build_filename (newpath, legal_name) + statefile_suffix;
3690 cerr << "Rename " << oldstr << " => " << newstr << endl;
3692 if (RENAME (oldstr.c_str(), newstr.c_str()) != 0) {
3699 oldstr = Glib::build_filename (newpath, _current_snapshot_name) + history_suffix;
3701 if (Glib::file_test (oldstr, Glib::FILE_TEST_EXISTS)) {
3702 newstr = Glib::build_filename (newpath, legal_name) + history_suffix;
3704 cerr << "Rename " << oldstr << " => " << newstr << endl;
3706 if (RENAME (oldstr.c_str(), newstr.c_str()) != 0) {
3711 /* update file source paths */
3713 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ++i) {
3714 boost::shared_ptr<FileSource> fs = boost::dynamic_pointer_cast<FileSource> (i->second);
3716 string p = fs->path ();
3717 boost::replace_all (p, old_sources_root, _session_dir->sources_root());
3722 /* remove old name from recent sessions */
3724 remove_recent_sessions (_path);
3727 _current_snapshot_name = new_name;
3732 /* save state again to get everything just right */
3734 save_state (_current_snapshot_name);
3737 /* add to recent sessions */
3739 store_recent_sessions (new_name, _path);