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 /* no need to call legalize_for_path() since the string
497 * in session_template is already a legal path name
499 string out_path = Glib::build_filename (_session_dir->root_path(), _name + statefile_suffix);
501 ofstream out(out_path.c_str());
507 /* Copy plugin state files from template to new session */
508 std::string template_plugins = Glib::build_filename (session_template, X_("plugins"));
509 copy_files (template_plugins, plugins_dir ());
514 error << string_compose (_("Could not open %1 for writing session template"), out_path)
520 error << string_compose (_("Could not open session template %1 for reading"), in_path)
527 /* set initial start + end point */
529 _state_of_the_state = Clean;
531 /* set up Master Out and Control Out if necessary */
536 ChanCount count(DataType::AUDIO, bus_profile->master_out_channels);
538 if (bus_profile->master_out_channels) {
539 boost::shared_ptr<Route> r (new Route (*this, _("master"), Route::MasterOut, DataType::AUDIO));
543 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
544 // boost_debug_shared_ptr_mark_interesting (r.get(), "Route");
547 Glib::Threads::Mutex::Lock lm (AudioEngine::instance()->process_lock ());
548 r->input()->ensure_io (count, false, this);
549 r->output()->ensure_io (count, false, this);
555 /* prohibit auto-connect to master, because there isn't one */
556 bus_profile->output_ac = AutoConnectOption (bus_profile->output_ac & ~AutoConnectMaster);
560 add_routes (rl, false, false, false);
563 /* this allows the user to override settings with an environment variable.
566 if (no_auto_connect()) {
567 bus_profile->input_ac = AutoConnectOption (0);
568 bus_profile->output_ac = AutoConnectOption (0);
571 Config->set_input_auto_connect (bus_profile->input_ac);
572 Config->set_output_auto_connect (bus_profile->output_ac);
575 if (Config->get_use_monitor_bus() && bus_profile) {
576 add_monitor_section ();
583 Session::maybe_write_autosave()
585 if (dirty() && record_status() != Recording) {
586 save_state("", true);
591 Session::remove_pending_capture_state ()
593 std::string pending_state_file_path(_session_dir->root_path());
595 pending_state_file_path = Glib::build_filename (pending_state_file_path, legalize_for_path (_current_snapshot_name) + pending_suffix);
597 if (!Glib::file_test (pending_state_file_path, Glib::FILE_TEST_EXISTS)) return;
599 if (g_remove (pending_state_file_path.c_str()) != 0) {
600 error << string_compose(_("Could not remove pending capture state at path \"%1\" (%2)"),
601 pending_state_file_path, g_strerror (errno)) << endmsg;
605 /** Rename a state file.
606 * @param old_name Old snapshot name.
607 * @param new_name New snapshot name.
610 Session::rename_state (string old_name, string new_name)
612 if (old_name == _current_snapshot_name || old_name == _name) {
613 /* refuse to rename the current snapshot or the "main" one */
617 const string old_xml_filename = legalize_for_path (old_name) + statefile_suffix;
618 const string new_xml_filename = legalize_for_path (new_name) + statefile_suffix;
620 const std::string old_xml_path(Glib::build_filename (_session_dir->root_path(), old_xml_filename));
621 const std::string new_xml_path(Glib::build_filename (_session_dir->root_path(), new_xml_filename));
623 if (::g_rename (old_xml_path.c_str(), new_xml_path.c_str()) != 0) {
624 error << string_compose(_("could not rename snapshot %1 to %2 (%3)"),
625 old_name, new_name, g_strerror(errno)) << endmsg;
629 /** Remove a state file.
630 * @param snapshot_name Snapshot name.
633 Session::remove_state (string snapshot_name)
635 if (!_writable || snapshot_name == _current_snapshot_name || snapshot_name == _name) {
636 // refuse to remove the current snapshot or the "main" one
640 std::string xml_path(_session_dir->root_path());
642 xml_path = Glib::build_filename (xml_path, legalize_for_path (snapshot_name) + statefile_suffix);
644 if (!create_backup_file (xml_path)) {
645 // don't remove it if a backup can't be made
646 // create_backup_file will log the error.
651 if (g_remove (xml_path.c_str()) != 0) {
652 error << string_compose(_("Could not remove session file at path \"%1\" (%2)"),
653 xml_path, g_strerror (errno)) << endmsg;
657 /** @param snapshot_name Name to save under, without .ardour / .pending prefix */
659 Session::save_state (string snapshot_name, bool pending, bool switch_to_snapshot)
662 std::string xml_path(_session_dir->root_path());
664 if (!_writable || (_state_of_the_state & CannotSave)) {
668 if (!_engine.connected ()) {
669 error << string_compose (_("the %1 audio engine is not connected and state saving would lose all I/O connections. Session not saved"),
675 /* tell sources we're saving first, in case they write out to a new file
676 * which should be saved with the state rather than the old one */
677 for (SourceMap::const_iterator i = sources.begin(); i != sources.end(); ++i) {
679 i->second->session_saved();
680 } catch (Evoral::SMF::FileError& e) {
681 error << string_compose ("Could not write to MIDI file %1; MIDI data not saved.", e.file_name ()) << endmsg;
685 SaveSession (); /* EMIT SIGNAL */
687 tree.set_root (&get_state());
689 if (snapshot_name.empty()) {
690 snapshot_name = _current_snapshot_name;
691 } else if (switch_to_snapshot) {
692 _current_snapshot_name = snapshot_name;
697 /* proper save: use statefile_suffix (.ardour in English) */
699 xml_path = Glib::build_filename (xml_path, legalize_for_path (snapshot_name) + statefile_suffix);
701 /* make a backup copy of the old file */
703 if (Glib::file_test (xml_path, Glib::FILE_TEST_EXISTS) && !create_backup_file (xml_path)) {
704 // create_backup_file will log the error
710 /* pending save: use pending_suffix (.pending in English) */
711 xml_path = Glib::build_filename (xml_path, legalize_for_path (snapshot_name) + pending_suffix);
714 std::string tmp_path(_session_dir->root_path());
715 tmp_path = Glib::build_filename (tmp_path, legalize_for_path (snapshot_name) + temp_suffix);
717 // cerr << "actually writing state to " << xml_path << endl;
719 if (!tree.write (tmp_path)) {
720 error << string_compose (_("state could not be saved to %1"), tmp_path) << endmsg;
721 if (g_remove (tmp_path.c_str()) != 0) {
722 error << string_compose(_("Could not remove temporary session file at path \"%1\" (%2)"),
723 tmp_path, g_strerror (errno)) << endmsg;
729 if (::rename (tmp_path.c_str(), xml_path.c_str()) != 0) {
730 error << string_compose (_("could not rename temporary session file %1 to %2"),
731 tmp_path, xml_path) << endmsg;
732 if (g_remove (tmp_path.c_str()) != 0) {
733 error << string_compose(_("Could not remove temporary session file at path \"%1\" (%2)"),
734 tmp_path, g_strerror (errno)) << endmsg;
742 save_history (snapshot_name);
744 bool was_dirty = dirty();
746 _state_of_the_state = StateOfTheState (_state_of_the_state & ~Dirty);
749 DirtyChanged (); /* EMIT SIGNAL */
752 StateSaved (snapshot_name); /* EMIT SIGNAL */
759 Session::restore_state (string snapshot_name)
761 if (load_state (snapshot_name) == 0) {
762 set_state (*state_tree->root(), Stateful::loading_state_version);
769 Session::load_state (string snapshot_name)
774 state_was_pending = false;
776 /* check for leftover pending state from a crashed capture attempt */
778 std::string xmlpath(_session_dir->root_path());
779 xmlpath = Glib::build_filename (xmlpath, legalize_for_path (snapshot_name) + pending_suffix);
781 if (Glib::file_test (xmlpath, Glib::FILE_TEST_EXISTS)) {
783 /* there is pending state from a crashed capture attempt */
785 boost::optional<int> r = AskAboutPendingState();
786 if (r.get_value_or (1)) {
787 state_was_pending = true;
791 if (!state_was_pending) {
792 xmlpath = Glib::build_filename (_session_dir->root_path(), snapshot_name);
795 if (!Glib::file_test (xmlpath, Glib::FILE_TEST_EXISTS)) {
796 xmlpath = Glib::build_filename (_session_dir->root_path(), legalize_for_path (snapshot_name) + statefile_suffix);
797 if (!Glib::file_test (xmlpath, Glib::FILE_TEST_EXISTS)) {
798 error << string_compose(_("%1: session file \"%2\" doesn't exist!"), _name, xmlpath) << endmsg;
803 state_tree = new XMLTree;
807 _writable = exists_and_writable (xmlpath);
809 if (!state_tree->read (xmlpath)) {
810 error << string_compose(_("Could not understand session file %1"), xmlpath) << endmsg;
816 XMLNode& root (*state_tree->root());
818 if (root.name() != X_("Session")) {
819 error << string_compose (_("Session file %1 is not a session"), xmlpath) << endmsg;
825 const XMLProperty* prop;
827 if ((prop = root.property ("version")) == 0) {
828 /* no version implies very old version of Ardour */
829 Stateful::loading_state_version = 1000;
831 if (prop->value().find ('.') != string::npos) {
832 /* old school version format */
833 if (prop->value()[0] == '2') {
834 Stateful::loading_state_version = 2000;
836 Stateful::loading_state_version = 3000;
839 Stateful::loading_state_version = atoi (prop->value());
843 if (Stateful::loading_state_version < CURRENT_SESSION_FILE_VERSION && _writable) {
845 std::string backup_path(_session_dir->root_path());
846 std::string backup_filename = string_compose ("%1-%2%3", legalize_for_path (snapshot_name), Stateful::loading_state_version, statefile_suffix);
847 backup_path = Glib::build_filename (backup_path, backup_filename);
849 // only create a backup for a given statefile version once
851 if (!Glib::file_test (backup_path, Glib::FILE_TEST_EXISTS)) {
853 VersionMismatch (xmlpath, backup_path);
855 if (!copy_file (xmlpath, backup_path)) {;
865 Session::load_options (const XMLNode& node)
867 LocaleGuard lg (X_("POSIX"));
868 config.set_variables (node);
879 Session::get_template()
881 /* if we don't disable rec-enable, diskstreams
882 will believe they need to store their capture
883 sources in their state node.
886 disable_record (false);
892 Session::state (bool full_state)
894 XMLNode* node = new XMLNode("Session");
898 snprintf(buf, sizeof(buf), "%d", CURRENT_SESSION_FILE_VERSION);
899 node->add_property("version", buf);
901 /* store configuration settings */
905 node->add_property ("name", _name);
906 snprintf (buf, sizeof (buf), "%" PRId64, _nominal_frame_rate);
907 node->add_property ("sample-rate", buf);
909 if (session_dirs.size() > 1) {
913 vector<space_and_path>::iterator i = session_dirs.begin();
914 vector<space_and_path>::iterator next;
916 ++i; /* skip the first one */
920 while (i != session_dirs.end()) {
924 if (next != session_dirs.end()) {
934 child = node->add_child ("Path");
935 child->add_content (p);
939 /* save the ID counter */
941 snprintf (buf, sizeof (buf), "%" PRIu64, ID::counter());
942 node->add_property ("id-counter", buf);
944 /* save the event ID counter */
946 snprintf (buf, sizeof (buf), "%d", Evoral::event_id_counter());
947 node->add_property ("event-counter", buf);
949 /* various options */
951 list<XMLNode*> midi_port_nodes = _midi_ports->get_midi_port_states();
952 if (!midi_port_nodes.empty()) {
953 XMLNode* midi_port_stuff = new XMLNode ("MIDIPorts");
954 for (list<XMLNode*>::const_iterator n = midi_port_nodes.begin(); n != midi_port_nodes.end(); ++n) {
955 midi_port_stuff->add_child_nocopy (**n);
957 node->add_child_nocopy (*midi_port_stuff);
960 node->add_child_nocopy (config.get_variables ());
962 node->add_child_nocopy (ARDOUR::SessionMetadata::Metadata()->get_state());
964 child = node->add_child ("Sources");
967 Glib::Threads::Mutex::Lock sl (source_lock);
969 for (SourceMap::iterator siter = sources.begin(); siter != sources.end(); ++siter) {
971 /* Don't save information about non-file Sources, or
972 * about non-destructive file sources that are empty
973 * and unused by any regions.
976 boost::shared_ptr<FileSource> fs;
978 if ((fs = boost::dynamic_pointer_cast<FileSource> (siter->second)) != 0) {
980 if (!fs->destructive()) {
981 if (fs->empty() && !fs->used()) {
986 child->add_child_nocopy (siter->second->get_state());
991 child = node->add_child ("Regions");
994 Glib::Threads::Mutex::Lock rl (region_lock);
995 const RegionFactory::RegionMap& region_map (RegionFactory::all_regions());
996 for (RegionFactory::RegionMap::const_iterator i = region_map.begin(); i != region_map.end(); ++i) {
997 boost::shared_ptr<Region> r = i->second;
998 /* only store regions not attached to playlists */
999 if (r->playlist() == 0) {
1000 if (boost::dynamic_pointer_cast<AudioRegion>(r)) {
1001 child->add_child_nocopy ((boost::dynamic_pointer_cast<AudioRegion>(r))->get_basic_state ());
1003 child->add_child_nocopy (r->get_state ());
1008 RegionFactory::CompoundAssociations& cassocs (RegionFactory::compound_associations());
1010 if (!cassocs.empty()) {
1011 XMLNode* ca = node->add_child (X_("CompoundAssociations"));
1013 for (RegionFactory::CompoundAssociations::iterator i = cassocs.begin(); i != cassocs.end(); ++i) {
1015 XMLNode* can = new XMLNode (X_("CompoundAssociation"));
1016 i->first->id().print (buf, sizeof (buf));
1017 can->add_property (X_("copy"), buf);
1018 i->second->id().print (buf, sizeof (buf));
1019 can->add_property (X_("original"), buf);
1020 ca->add_child_nocopy (*can);
1026 node->add_child_nocopy (_locations->get_state());
1028 // for a template, just create a new Locations, populate it
1029 // with the default start and end, and get the state for that.
1030 Locations loc (*this);
1031 Location* range = new Location (*this, 0, 0, _("session"), Location::IsSessionRange);
1032 range->set (max_framepos, 0);
1034 node->add_child_nocopy (loc.get_state());
1037 child = node->add_child ("Bundles");
1039 boost::shared_ptr<BundleList> bundles = _bundles.reader ();
1040 for (BundleList::iterator i = bundles->begin(); i != bundles->end(); ++i) {
1041 boost::shared_ptr<UserBundle> b = boost::dynamic_pointer_cast<UserBundle> (*i);
1043 child->add_child_nocopy (b->get_state());
1048 child = node->add_child ("Routes");
1050 boost::shared_ptr<RouteList> r = routes.reader ();
1052 RoutePublicOrderSorter cmp;
1053 RouteList public_order (*r);
1054 public_order.sort (cmp);
1056 /* the sort should have put control outs first */
1059 assert (_monitor_out == public_order.front());
1062 for (RouteList::iterator i = public_order.begin(); i != public_order.end(); ++i) {
1063 if (!(*i)->is_auditioner()) {
1065 child->add_child_nocopy ((*i)->get_state());
1067 child->add_child_nocopy ((*i)->get_template());
1073 playlists->add_state (node, full_state);
1075 child = node->add_child ("RouteGroups");
1076 for (list<RouteGroup *>::iterator i = _route_groups.begin(); i != _route_groups.end(); ++i) {
1077 child->add_child_nocopy ((*i)->get_state());
1081 XMLNode* gain_child = node->add_child ("Click");
1082 gain_child->add_child_nocopy (_click_io->state (full_state));
1083 gain_child->add_child_nocopy (_click_gain->state (full_state));
1087 XMLNode* ltc_input_child = node->add_child ("LTC-In");
1088 ltc_input_child->add_child_nocopy (_ltc_input->state (full_state));
1092 XMLNode* ltc_output_child = node->add_child ("LTC-Out");
1093 ltc_output_child->add_child_nocopy (_ltc_output->state (full_state));
1096 node->add_child_nocopy (_speakers->get_state());
1097 node->add_child_nocopy (_tempo_map->get_state());
1098 node->add_child_nocopy (get_control_protocol_state());
1101 node->add_child_copy (*_extra_xml);
1108 Session::get_control_protocol_state ()
1110 ControlProtocolManager& cpm (ControlProtocolManager::instance());
1111 return cpm.get_state();
1115 Session::set_state (const XMLNode& node, int version)
1119 const XMLProperty* prop;
1122 _state_of_the_state = StateOfTheState (_state_of_the_state|CannotSave);
1124 if (node.name() != X_("Session")) {
1125 fatal << _("programming error: Session: incorrect XML node sent to set_state()") << endmsg;
1129 if ((prop = node.property ("name")) != 0) {
1130 _name = prop->value ();
1133 if ((prop = node.property (X_("sample-rate"))) != 0) {
1135 _nominal_frame_rate = atoi (prop->value());
1137 if (_nominal_frame_rate != _current_frame_rate) {
1138 boost::optional<int> r = AskAboutSampleRateMismatch (_nominal_frame_rate, _current_frame_rate);
1139 if (r.get_value_or (0)) {
1145 setup_raid_path(_session_dir->root_path());
1147 if ((prop = node.property (X_("id-counter"))) != 0) {
1149 sscanf (prop->value().c_str(), "%" PRIu64, &x);
1150 ID::init_counter (x);
1152 /* old sessions used a timebased counter, so fake
1153 the startup ID counter based on a standard
1158 ID::init_counter (now);
1161 if ((prop = node.property (X_("event-counter"))) != 0) {
1162 Evoral::init_event_id_counter (atoi (prop->value()));
1166 if ((child = find_named_node (node, "MIDIPorts")) != 0) {
1167 _midi_ports->set_midi_port_states (child->children());
1170 IO::disable_connecting ();
1172 Stateful::save_extra_xml (node);
1174 if (((child = find_named_node (node, "Options")) != 0)) { /* old style */
1175 load_options (*child);
1176 } else if ((child = find_named_node (node, "Config")) != 0) { /* new style */
1177 load_options (*child);
1179 error << _("Session: XML state has no options section") << endmsg;
1182 if (version >= 3000) {
1183 if ((child = find_named_node (node, "Metadata")) == 0) {
1184 warning << _("Session: XML state has no metadata section") << endmsg;
1185 } else if ( ARDOUR::SessionMetadata::Metadata()->set_state (*child, version) ) {
1190 if ((child = find_named_node (node, X_("Speakers"))) != 0) {
1191 _speakers->set_state (*child, version);
1194 if ((child = find_named_node (node, "Sources")) == 0) {
1195 error << _("Session: XML state has no sources section") << endmsg;
1197 } else if (load_sources (*child)) {
1201 if ((child = find_named_node (node, "TempoMap")) == 0) {
1202 error << _("Session: XML state has no Tempo Map section") << endmsg;
1204 } else if (_tempo_map->set_state (*child, version)) {
1208 if ((child = find_named_node (node, "Locations")) == 0) {
1209 error << _("Session: XML state has no locations section") << endmsg;
1211 } else if (_locations->set_state (*child, version)) {
1217 if ((location = _locations->auto_loop_location()) != 0) {
1218 set_auto_loop_location (location);
1221 if ((location = _locations->auto_punch_location()) != 0) {
1222 set_auto_punch_location (location);
1225 if ((location = _locations->session_range_location()) != 0) {
1226 delete _session_range_location;
1227 _session_range_location = location;
1230 if (_session_range_location) {
1231 AudioFileSource::set_header_position_offset (_session_range_location->start());
1234 if ((child = find_named_node (node, "Regions")) == 0) {
1235 error << _("Session: XML state has no Regions section") << endmsg;
1237 } else if (load_regions (*child)) {
1241 if ((child = find_named_node (node, "Playlists")) == 0) {
1242 error << _("Session: XML state has no playlists section") << endmsg;
1244 } else if (playlists->load (*this, *child)) {
1248 if ((child = find_named_node (node, "UnusedPlaylists")) == 0) {
1250 } else if (playlists->load_unused (*this, *child)) {
1254 if ((child = find_named_node (node, "CompoundAssociations")) != 0) {
1255 if (load_compounds (*child)) {
1260 if (version >= 3000) {
1261 if ((child = find_named_node (node, "Bundles")) == 0) {
1262 warning << _("Session: XML state has no bundles section") << endmsg;
1265 /* We can't load Bundles yet as they need to be able
1266 to convert from port names to Port objects, which can't happen until
1268 _bundle_xml_node = new XMLNode (*child);
1272 if (version < 3000) {
1273 if ((child = find_named_node (node, X_("DiskStreams"))) == 0) {
1274 error << _("Session: XML state has no diskstreams section") << endmsg;
1276 } else if (load_diskstreams_2X (*child, version)) {
1281 if ((child = find_named_node (node, "Routes")) == 0) {
1282 error << _("Session: XML state has no routes section") << endmsg;
1284 } else if (load_routes (*child, version)) {
1288 /* our diskstreams list is no longer needed as they are now all owned by their Route */
1289 _diskstreams_2X.clear ();
1291 if (version >= 3000) {
1293 if ((child = find_named_node (node, "RouteGroups")) == 0) {
1294 error << _("Session: XML state has no route groups section") << endmsg;
1296 } else if (load_route_groups (*child, version)) {
1300 } else if (version < 3000) {
1302 if ((child = find_named_node (node, "EditGroups")) == 0) {
1303 error << _("Session: XML state has no edit groups section") << endmsg;
1305 } else if (load_route_groups (*child, version)) {
1309 if ((child = find_named_node (node, "MixGroups")) == 0) {
1310 error << _("Session: XML state has no mix groups section") << endmsg;
1312 } else if (load_route_groups (*child, version)) {
1317 if ((child = find_named_node (node, "Click")) == 0) {
1318 warning << _("Session: XML state has no click section") << endmsg;
1319 } else if (_click_io) {
1320 setup_click_state (&node);
1323 if ((child = find_named_node (node, ControlProtocolManager::state_node_name)) != 0) {
1324 ControlProtocolManager::instance().set_state (*child, version);
1327 update_have_rec_enabled_track ();
1329 /* here beginneth the second phase ... */
1331 StateReady (); /* EMIT SIGNAL */
1340 Session::load_routes (const XMLNode& node, int version)
1343 XMLNodeConstIterator niter;
1344 RouteList new_routes;
1346 nlist = node.children();
1350 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1352 boost::shared_ptr<Route> route;
1353 if (version < 3000) {
1354 route = XMLRouteFactory_2X (**niter, version);
1356 route = XMLRouteFactory (**niter, version);
1360 error << _("Session: cannot create Route from XML description.") << endmsg;
1364 BootMessage (string_compose (_("Loaded track/bus %1"), route->name()));
1366 new_routes.push_back (route);
1369 add_routes (new_routes, false, false, false);
1374 boost::shared_ptr<Route>
1375 Session::XMLRouteFactory (const XMLNode& node, int version)
1377 boost::shared_ptr<Route> ret;
1379 if (node.name() != "Route") {
1383 XMLNode* ds_child = find_named_node (node, X_("Diskstream"));
1385 DataType type = DataType::AUDIO;
1386 const XMLProperty* prop = node.property("default-type");
1389 type = DataType (prop->value());
1392 assert (type != DataType::NIL);
1396 boost::shared_ptr<Track> track;
1398 if (type == DataType::AUDIO) {
1399 track.reset (new AudioTrack (*this, X_("toBeResetFroXML")));
1401 track.reset (new MidiTrack (*this, X_("toBeResetFroXML")));
1404 if (track->init()) {
1408 if (track->set_state (node, version)) {
1412 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
1413 // boost_debug_shared_ptr_mark_interesting (track.get(), "Track");
1418 boost::shared_ptr<Route> r (new Route (*this, X_("toBeResetFroXML")));
1420 if (r->init () == 0 && r->set_state (node, version) == 0) {
1421 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
1422 // boost_debug_shared_ptr_mark_interesting (r.get(), "Route");
1431 boost::shared_ptr<Route>
1432 Session::XMLRouteFactory_2X (const XMLNode& node, int version)
1434 boost::shared_ptr<Route> ret;
1436 if (node.name() != "Route") {
1440 XMLProperty const * ds_prop = node.property (X_("diskstream-id"));
1442 ds_prop = node.property (X_("diskstream"));
1445 DataType type = DataType::AUDIO;
1446 const XMLProperty* prop = node.property("default-type");
1449 type = DataType (prop->value());
1452 assert (type != DataType::NIL);
1456 list<boost::shared_ptr<Diskstream> >::iterator i = _diskstreams_2X.begin ();
1457 while (i != _diskstreams_2X.end() && (*i)->id() != ds_prop->value()) {
1461 if (i == _diskstreams_2X.end()) {
1462 error << _("Could not find diskstream for route") << endmsg;
1463 return boost::shared_ptr<Route> ();
1466 boost::shared_ptr<Track> track;
1468 if (type == DataType::AUDIO) {
1469 track.reset (new AudioTrack (*this, X_("toBeResetFroXML")));
1471 track.reset (new MidiTrack (*this, X_("toBeResetFroXML")));
1474 if (track->init()) {
1478 if (track->set_state (node, version)) {
1482 track->set_diskstream (*i);
1484 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
1485 // boost_debug_shared_ptr_mark_interesting (track.get(), "Track");
1490 boost::shared_ptr<Route> r (new Route (*this, X_("toBeResetFroXML")));
1492 if (r->init () == 0 && r->set_state (node, version) == 0) {
1493 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
1494 // boost_debug_shared_ptr_mark_interesting (r.get(), "Route");
1504 Session::load_regions (const XMLNode& node)
1507 XMLNodeConstIterator niter;
1508 boost::shared_ptr<Region> region;
1510 nlist = node.children();
1514 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1515 if ((region = XMLRegionFactory (**niter, false)) == 0) {
1516 error << _("Session: cannot create Region from XML description.");
1517 const XMLProperty *name = (**niter).property("name");
1520 error << " " << string_compose (_("Can not load state for region '%1'"), name->value());
1531 Session::load_compounds (const XMLNode& node)
1533 XMLNodeList calist = node.children();
1534 XMLNodeConstIterator caiter;
1535 XMLProperty *caprop;
1537 for (caiter = calist.begin(); caiter != calist.end(); ++caiter) {
1538 XMLNode* ca = *caiter;
1542 if ((caprop = ca->property (X_("original"))) == 0) {
1545 orig_id = caprop->value();
1547 if ((caprop = ca->property (X_("copy"))) == 0) {
1550 copy_id = caprop->value();
1552 boost::shared_ptr<Region> orig = RegionFactory::region_by_id (orig_id);
1553 boost::shared_ptr<Region> copy = RegionFactory::region_by_id (copy_id);
1555 if (!orig || !copy) {
1556 warning << string_compose (_("Regions in compound description not found (ID's %1 and %2): ignored"),
1562 RegionFactory::add_compound_association (orig, copy);
1569 Session::load_nested_sources (const XMLNode& node)
1572 XMLNodeConstIterator niter;
1574 nlist = node.children();
1576 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1577 if ((*niter)->name() == "Source") {
1579 /* it may already exist, so don't recreate it unnecessarily
1582 XMLProperty* prop = (*niter)->property (X_("id"));
1584 error << _("Nested source has no ID info in session file! (ignored)") << endmsg;
1588 ID source_id (prop->value());
1590 if (!source_by_id (source_id)) {
1593 SourceFactory::create (*this, **niter, true);
1595 catch (failed_constructor& err) {
1596 error << string_compose (_("Cannot reconstruct nested source for region %1"), name()) << endmsg;
1603 boost::shared_ptr<Region>
1604 Session::XMLRegionFactory (const XMLNode& node, bool full)
1606 const XMLProperty* type = node.property("type");
1610 const XMLNodeList& nlist = node.children();
1612 for (XMLNodeConstIterator niter = nlist.begin(); niter != nlist.end(); ++niter) {
1613 XMLNode *child = (*niter);
1614 if (child->name() == "NestedSource") {
1615 load_nested_sources (*child);
1619 if (!type || type->value() == "audio") {
1620 return boost::shared_ptr<Region>(XMLAudioRegionFactory (node, full));
1621 } else if (type->value() == "midi") {
1622 return boost::shared_ptr<Region>(XMLMidiRegionFactory (node, full));
1625 } catch (failed_constructor& err) {
1626 return boost::shared_ptr<Region> ();
1629 return boost::shared_ptr<Region> ();
1632 boost::shared_ptr<AudioRegion>
1633 Session::XMLAudioRegionFactory (const XMLNode& node, bool /*full*/)
1635 const XMLProperty* prop;
1636 boost::shared_ptr<Source> source;
1637 boost::shared_ptr<AudioSource> as;
1639 SourceList master_sources;
1640 uint32_t nchans = 1;
1643 if (node.name() != X_("Region")) {
1644 return boost::shared_ptr<AudioRegion>();
1647 if ((prop = node.property (X_("channels"))) != 0) {
1648 nchans = atoi (prop->value().c_str());
1651 if ((prop = node.property ("name")) == 0) {
1652 cerr << "no name for this region\n";
1656 if ((prop = node.property (X_("source-0"))) == 0) {
1657 if ((prop = node.property ("source")) == 0) {
1658 error << _("Session: XMLNode describing a AudioRegion is incomplete (no source)") << endmsg;
1659 return boost::shared_ptr<AudioRegion>();
1663 PBD::ID s_id (prop->value());
1665 if ((source = source_by_id (s_id)) == 0) {
1666 error << string_compose(_("Session: XMLNode describing a AudioRegion references an unknown source id =%1"), s_id) << endmsg;
1667 return boost::shared_ptr<AudioRegion>();
1670 as = boost::dynamic_pointer_cast<AudioSource>(source);
1672 error << string_compose(_("Session: XMLNode describing a AudioRegion references a non-audio source id =%1"), s_id) << endmsg;
1673 return boost::shared_ptr<AudioRegion>();
1676 sources.push_back (as);
1678 /* pickup other channels */
1680 for (uint32_t n=1; n < nchans; ++n) {
1681 snprintf (buf, sizeof(buf), X_("source-%d"), n);
1682 if ((prop = node.property (buf)) != 0) {
1684 PBD::ID id2 (prop->value());
1686 if ((source = source_by_id (id2)) == 0) {
1687 error << string_compose(_("Session: XMLNode describing a AudioRegion references an unknown source id =%1"), id2) << endmsg;
1688 return boost::shared_ptr<AudioRegion>();
1691 as = boost::dynamic_pointer_cast<AudioSource>(source);
1693 error << string_compose(_("Session: XMLNode describing a AudioRegion references a non-audio source id =%1"), id2) << endmsg;
1694 return boost::shared_ptr<AudioRegion>();
1696 sources.push_back (as);
1700 for (uint32_t n = 0; n < nchans; ++n) {
1701 snprintf (buf, sizeof(buf), X_("master-source-%d"), n);
1702 if ((prop = node.property (buf)) != 0) {
1704 PBD::ID id2 (prop->value());
1706 if ((source = source_by_id (id2)) == 0) {
1707 error << string_compose(_("Session: XMLNode describing a AudioRegion references an unknown source id =%1"), id2) << endmsg;
1708 return boost::shared_ptr<AudioRegion>();
1711 as = boost::dynamic_pointer_cast<AudioSource>(source);
1713 error << string_compose(_("Session: XMLNode describing a AudioRegion references a non-audio source id =%1"), id2) << endmsg;
1714 return boost::shared_ptr<AudioRegion>();
1716 master_sources.push_back (as);
1721 boost::shared_ptr<AudioRegion> region (boost::dynamic_pointer_cast<AudioRegion> (RegionFactory::create (sources, node)));
1723 /* a final detail: this is the one and only place that we know how long missing files are */
1725 if (region->whole_file()) {
1726 for (SourceList::iterator sx = sources.begin(); sx != sources.end(); ++sx) {
1727 boost::shared_ptr<SilentFileSource> sfp = boost::dynamic_pointer_cast<SilentFileSource> (*sx);
1729 sfp->set_length (region->length());
1734 if (!master_sources.empty()) {
1735 if (master_sources.size() != nchans) {
1736 error << _("Session: XMLNode describing an AudioRegion is missing some master sources; ignored") << endmsg;
1738 region->set_master_sources (master_sources);
1746 catch (failed_constructor& err) {
1747 return boost::shared_ptr<AudioRegion>();
1751 boost::shared_ptr<MidiRegion>
1752 Session::XMLMidiRegionFactory (const XMLNode& node, bool /*full*/)
1754 const XMLProperty* prop;
1755 boost::shared_ptr<Source> source;
1756 boost::shared_ptr<MidiSource> ms;
1759 if (node.name() != X_("Region")) {
1760 return boost::shared_ptr<MidiRegion>();
1763 if ((prop = node.property ("name")) == 0) {
1764 cerr << "no name for this region\n";
1768 if ((prop = node.property (X_("source-0"))) == 0) {
1769 if ((prop = node.property ("source")) == 0) {
1770 error << _("Session: XMLNode describing a MidiRegion is incomplete (no source)") << endmsg;
1771 return boost::shared_ptr<MidiRegion>();
1775 PBD::ID s_id (prop->value());
1777 if ((source = source_by_id (s_id)) == 0) {
1778 error << string_compose(_("Session: XMLNode describing a MidiRegion references an unknown source id =%1"), s_id) << endmsg;
1779 return boost::shared_ptr<MidiRegion>();
1782 ms = boost::dynamic_pointer_cast<MidiSource>(source);
1784 error << string_compose(_("Session: XMLNode describing a MidiRegion references a non-midi source id =%1"), s_id) << endmsg;
1785 return boost::shared_ptr<MidiRegion>();
1788 sources.push_back (ms);
1791 boost::shared_ptr<MidiRegion> region (boost::dynamic_pointer_cast<MidiRegion> (RegionFactory::create (sources, node)));
1792 /* a final detail: this is the one and only place that we know how long missing files are */
1794 if (region->whole_file()) {
1795 for (SourceList::iterator sx = sources.begin(); sx != sources.end(); ++sx) {
1796 boost::shared_ptr<SilentFileSource> sfp = boost::dynamic_pointer_cast<SilentFileSource> (*sx);
1798 sfp->set_length (region->length());
1806 catch (failed_constructor& err) {
1807 return boost::shared_ptr<MidiRegion>();
1812 Session::get_sources_as_xml ()
1815 XMLNode* node = new XMLNode (X_("Sources"));
1816 Glib::Threads::Mutex::Lock lm (source_lock);
1818 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ++i) {
1819 node->add_child_nocopy (i->second->get_state());
1826 Session::path_from_region_name (DataType type, string name, string identifier)
1828 char buf[PATH_MAX+1];
1830 SessionDirectory sdir(get_best_session_directory_for_new_source());
1831 std::string source_dir = ((type == DataType::AUDIO)
1832 ? sdir.sound_path() : sdir.midi_path());
1834 string ext = native_header_format_extension (config.get_native_file_header_format(), type);
1836 for (n = 0; n < 999999; ++n) {
1837 if (identifier.length()) {
1838 snprintf (buf, sizeof(buf), "%s%s%" PRIu32 "%s", name.c_str(),
1839 identifier.c_str(), n, ext.c_str());
1841 snprintf (buf, sizeof(buf), "%s-%" PRIu32 "%s", name.c_str(),
1845 std::string source_path = Glib::build_filename (source_dir, buf);
1847 if (!Glib::file_test (source_path, Glib::FILE_TEST_EXISTS)) {
1852 error << string_compose (_("cannot create new file from region name \"%1\" with ident = \"%2\": too many existing files with similar names"),
1861 Session::load_sources (const XMLNode& node)
1864 XMLNodeConstIterator niter;
1865 boost::shared_ptr<Source> source;
1867 nlist = node.children();
1871 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1874 if ((source = XMLSourceFactory (**niter)) == 0) {
1875 error << _("Session: cannot create Source from XML description.") << endmsg;
1878 } catch (MissingSource& err) {
1882 if (!no_questions_about_missing_files) {
1883 user_choice = MissingFile (this, err.path, err.type).get_value_or (-1);
1888 switch (user_choice) {
1890 /* user added a new search location, so try again */
1895 /* user asked to quit the entire session load
1900 no_questions_about_missing_files = true;
1904 no_questions_about_missing_files = true;
1909 warning << _("A sound file is missing. It will be replaced by silence.") << endmsg;
1910 source = SourceFactory::createSilent (*this, **niter, max_framecnt, _current_frame_rate);
1919 boost::shared_ptr<Source>
1920 Session::XMLSourceFactory (const XMLNode& node)
1922 if (node.name() != "Source") {
1923 return boost::shared_ptr<Source>();
1927 /* note: do peak building in another thread when loading session state */
1928 return SourceFactory::create (*this, node, true);
1931 catch (failed_constructor& err) {
1932 error << string_compose (_("Found a sound file that cannot be used by %1. Talk to the progammers."), PROGRAM_NAME) << endmsg;
1933 return boost::shared_ptr<Source>();
1938 Session::save_template (string template_name)
1942 if (_state_of_the_state & CannotSave) {
1946 std::string user_template_dir(user_template_directory());
1948 if (g_mkdir_with_parents (user_template_dir.c_str(), 0755) != 0) {
1949 error << string_compose(_("Could not create templates directory \"%1\" (%2)"),
1950 user_template_dir, g_strerror (errno)) << endmsg;
1954 tree.set_root (&get_template());
1956 std::string template_dir_path(user_template_dir);
1958 /* directory to put the template in */
1959 template_dir_path = Glib::build_filename (template_dir_path, template_name);
1961 if (Glib::file_test (template_dir_path, Glib::FILE_TEST_EXISTS)) {
1962 warning << string_compose(_("Template \"%1\" already exists - new version not created"),
1963 template_dir_path) << endmsg;
1967 if (g_mkdir_with_parents (template_dir_path.c_str(), 0755) != 0) {
1968 error << string_compose(_("Could not create directory for Session template\"%1\" (%2)"),
1969 template_dir_path, g_strerror (errno)) << endmsg;
1974 std::string template_file_path(template_dir_path);
1975 template_file_path = Glib::build_filename (template_file_path, template_name + template_suffix);
1977 if (!tree.write (template_file_path)) {
1978 error << _("template not saved") << endmsg;
1982 /* copy plugin state directory */
1984 std::string template_plugin_state_path(template_dir_path);
1985 template_plugin_state_path = Glib::build_filename (template_plugin_state_path, X_("plugins"));
1987 if (g_mkdir_with_parents (template_plugin_state_path.c_str(), 0755) != 0) {
1988 error << string_compose(_("Could not create directory for Session template plugin state\"%1\" (%2)"),
1989 template_plugin_state_path, g_strerror (errno)) << endmsg;
1993 copy_files (plugins_dir(), template_plugin_state_path);
1999 Session::refresh_disk_space ()
2001 #if __APPLE__ || (HAVE_SYS_VFS_H && HAVE_SYS_STATVFS_H)
2003 Glib::Threads::Mutex::Lock lm (space_lock);
2005 /* get freespace on every FS that is part of the session path */
2007 _total_free_4k_blocks = 0;
2008 _total_free_4k_blocks_uncertain = false;
2010 for (vector<space_and_path>::iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
2012 struct statfs statfsbuf;
2013 statfs (i->path.c_str(), &statfsbuf);
2015 double const scale = statfsbuf.f_bsize / 4096.0;
2017 /* See if this filesystem is read-only */
2018 struct statvfs statvfsbuf;
2019 statvfs (i->path.c_str(), &statvfsbuf);
2021 /* f_bavail can be 0 if it is undefined for whatever
2022 filesystem we are looking at; Samba shares mounted
2023 via GVFS are an example of this.
2025 if (statfsbuf.f_bavail == 0) {
2026 /* block count unknown */
2028 i->blocks_unknown = true;
2029 } else if (statvfsbuf.f_flag & ST_RDONLY) {
2030 /* read-only filesystem */
2032 i->blocks_unknown = false;
2034 /* read/write filesystem with known space */
2035 i->blocks = (uint32_t) floor (statfsbuf.f_bavail * scale);
2036 i->blocks_unknown = false;
2039 _total_free_4k_blocks += i->blocks;
2040 if (i->blocks_unknown) {
2041 _total_free_4k_blocks_uncertain = true;
2048 Session::get_best_session_directory_for_new_source ()
2050 vector<space_and_path>::iterator i;
2051 string result = _session_dir->root_path();
2053 /* handle common case without system calls */
2055 if (session_dirs.size() == 1) {
2059 /* OK, here's the algorithm we're following here:
2061 We want to select which directory to use for
2062 the next file source to be created. Ideally,
2063 we'd like to use a round-robin process so as to
2064 get maximum performance benefits from splitting
2065 the files across multiple disks.
2067 However, in situations without much diskspace, an
2068 RR approach may end up filling up a filesystem
2069 with new files while others still have space.
2070 Its therefore important to pay some attention to
2071 the freespace in the filesystem holding each
2072 directory as well. However, if we did that by
2073 itself, we'd keep creating new files in the file
2074 system with the most space until it was as full
2075 as all others, thus negating any performance
2076 benefits of this RAID-1 like approach.
2078 So, we use a user-configurable space threshold. If
2079 there are at least 2 filesystems with more than this
2080 much space available, we use RR selection between them.
2081 If not, then we pick the filesystem with the most space.
2083 This gets a good balance between the two
2087 refresh_disk_space ();
2089 int free_enough = 0;
2091 for (i = session_dirs.begin(); i != session_dirs.end(); ++i) {
2092 if ((*i).blocks * 4096 >= Config->get_disk_choice_space_threshold()) {
2097 if (free_enough >= 2) {
2098 /* use RR selection process, ensuring that the one
2102 i = last_rr_session_dir;
2105 if (++i == session_dirs.end()) {
2106 i = session_dirs.begin();
2109 if ((*i).blocks * 4096 >= Config->get_disk_choice_space_threshold()) {
2110 SessionDirectory sdir(i->path);
2111 if (sdir.create ()) {
2113 last_rr_session_dir = i;
2118 } while (i != last_rr_session_dir);
2122 /* pick FS with the most freespace (and that
2123 seems to actually work ...)
2126 vector<space_and_path> sorted;
2127 space_and_path_ascending_cmp cmp;
2129 sorted = session_dirs;
2130 sort (sorted.begin(), sorted.end(), cmp);
2132 for (i = sorted.begin(); i != sorted.end(); ++i) {
2133 SessionDirectory sdir(i->path);
2134 if (sdir.create ()) {
2136 last_rr_session_dir = i;
2146 Session::automation_dir () const
2148 return Glib::build_filename (_path, "automation");
2152 Session::analysis_dir () const
2154 return Glib::build_filename (_path, "analysis");
2158 Session::plugins_dir () const
2160 return Glib::build_filename (_path, "plugins");
2164 Session::externals_dir () const
2166 return Glib::build_filename (_path, "externals");
2170 Session::load_bundles (XMLNode const & node)
2172 XMLNodeList nlist = node.children();
2173 XMLNodeConstIterator niter;
2177 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2178 if ((*niter)->name() == "InputBundle") {
2179 add_bundle (boost::shared_ptr<UserBundle> (new UserBundle (**niter, true)));
2180 } else if ((*niter)->name() == "OutputBundle") {
2181 add_bundle (boost::shared_ptr<UserBundle> (new UserBundle (**niter, false)));
2183 error << string_compose(_("Unknown node \"%1\" found in Bundles list from session file"), (*niter)->name()) << endmsg;
2192 Session::load_route_groups (const XMLNode& node, int version)
2194 XMLNodeList nlist = node.children();
2195 XMLNodeConstIterator niter;
2199 if (version >= 3000) {
2201 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2202 if ((*niter)->name() == "RouteGroup") {
2203 RouteGroup* rg = new RouteGroup (*this, "");
2204 add_route_group (rg);
2205 rg->set_state (**niter, version);
2209 } else if (version < 3000) {
2211 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2212 if ((*niter)->name() == "EditGroup" || (*niter)->name() == "MixGroup") {
2213 RouteGroup* rg = new RouteGroup (*this, "");
2214 add_route_group (rg);
2215 rg->set_state (**niter, version);
2224 Session::auto_save()
2226 save_state (_current_snapshot_name);
2230 state_file_filter (const string &str, void */*arg*/)
2232 return (str.length() > strlen(statefile_suffix) &&
2233 str.find (statefile_suffix) == (str.length() - strlen (statefile_suffix)));
2237 bool operator()(const string* a, const string* b) {
2243 remove_end(string* state)
2245 string statename(*state);
2247 string::size_type start,end;
2248 if ((start = statename.find_last_of (G_DIR_SEPARATOR)) != string::npos) {
2249 statename = statename.substr (start+1);
2252 if ((end = statename.rfind(".ardour")) == string::npos) {
2253 end = statename.length();
2256 return new string(statename.substr (0, end));
2260 Session::possible_states (string path)
2262 PathScanner scanner;
2263 vector<string*>* states = scanner (path, state_file_filter, 0, false, false);
2265 transform(states->begin(), states->end(), states->begin(), remove_end);
2268 sort (states->begin(), states->end(), cmp);
2274 Session::possible_states () const
2276 return possible_states(_path);
2280 Session::add_route_group (RouteGroup* g)
2282 _route_groups.push_back (g);
2283 route_group_added (g); /* EMIT SIGNAL */
2285 g->RouteAdded.connect_same_thread (*this, boost::bind (&Session::route_added_to_route_group, this, _1, _2));
2286 g->RouteRemoved.connect_same_thread (*this, boost::bind (&Session::route_removed_from_route_group, this, _1, _2));
2287 g->PropertyChanged.connect_same_thread (*this, boost::bind (&Session::route_group_property_changed, this, g));
2293 Session::remove_route_group (RouteGroup& rg)
2295 list<RouteGroup*>::iterator i;
2297 if ((i = find (_route_groups.begin(), _route_groups.end(), &rg)) != _route_groups.end()) {
2298 _route_groups.erase (i);
2301 route_group_removed (); /* EMIT SIGNAL */
2305 /** Set a new order for our route groups, without adding or removing any.
2306 * @param groups Route group list in the new order.
2309 Session::reorder_route_groups (list<RouteGroup*> groups)
2311 _route_groups = groups;
2313 route_groups_reordered (); /* EMIT SIGNAL */
2319 Session::route_group_by_name (string name)
2321 list<RouteGroup *>::iterator i;
2323 for (i = _route_groups.begin(); i != _route_groups.end(); ++i) {
2324 if ((*i)->name() == name) {
2332 Session::all_route_group() const
2334 return *_all_route_group;
2338 Session::add_commands (vector<Command*> const & cmds)
2340 for (vector<Command*>::const_iterator i = cmds.begin(); i != cmds.end(); ++i) {
2346 Session::begin_reversible_command (const string& name)
2348 begin_reversible_command (g_quark_from_string (name.c_str ()));
2351 /** Begin a reversible command using a GQuark to identify it.
2352 * begin_reversible_command() and commit_reversible_command() calls may be nested,
2353 * but there must be as many begin...()s as there are commit...()s.
2356 Session::begin_reversible_command (GQuark q)
2358 /* If nested begin/commit pairs are used, we create just one UndoTransaction
2359 to hold all the commands that are committed. This keeps the order of
2360 commands correct in the history.
2363 if (_current_trans == 0) {
2364 /* start a new transaction */
2365 assert (_current_trans_quarks.empty ());
2366 _current_trans = new UndoTransaction();
2367 _current_trans->set_name (g_quark_to_string (q));
2370 _current_trans_quarks.push_front (q);
2374 Session::commit_reversible_command (Command *cmd)
2376 assert (_current_trans);
2377 assert (!_current_trans_quarks.empty ());
2382 _current_trans->add_command (cmd);
2385 _current_trans_quarks.pop_front ();
2387 if (!_current_trans_quarks.empty ()) {
2388 /* the transaction we're committing is not the top-level one */
2392 if (_current_trans->empty()) {
2393 /* no commands were added to the transaction, so just get rid of it */
2394 delete _current_trans;
2399 gettimeofday (&now, 0);
2400 _current_trans->set_timestamp (now);
2402 _history.add (_current_trans);
2407 accept_all_audio_files (const string& path, void */*arg*/)
2409 if (!Glib::file_test (path, Glib::FILE_TEST_IS_REGULAR)) {
2413 if (!AudioFileSource::safe_audio_file_extension (path)) {
2421 accept_all_midi_files (const string& path, void */*arg*/)
2423 if (!Glib::file_test (path, Glib::FILE_TEST_IS_REGULAR)) {
2427 return ((path.length() > 4 && path.find (".mid") != (path.length() - 4)) ||
2428 (path.length() > 4 && path.find (".smf") != (path.length() - 4)) ||
2429 (path.length() > 5 && path.find (".midi") != (path.length() - 5)));
2433 accept_all_state_files (const string& path, void */*arg*/)
2435 if (!Glib::file_test (path, Glib::FILE_TEST_IS_REGULAR)) {
2439 return (path.length() > 7 && path.find (".ardour") == (path.length() - 7));
2443 Session::find_all_sources (string path, set<string>& result)
2448 if (!tree.read (path)) {
2452 if ((node = find_named_node (*tree.root(), "Sources")) == 0) {
2457 XMLNodeConstIterator niter;
2459 nlist = node->children();
2463 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2467 if ((prop = (*niter)->property (X_("type"))) == 0) {
2471 DataType type (prop->value());
2473 if ((prop = (*niter)->property (X_("name"))) == 0) {
2477 if (Glib::path_is_absolute (prop->value())) {
2478 /* external file, ignore */
2486 if (FileSource::find (*this, type, prop->value(), true, is_new, chan, found_path)) {
2487 result.insert (found_path);
2495 Session::find_all_sources_across_snapshots (set<string>& result, bool exclude_this_snapshot)
2497 PathScanner scanner;
2498 vector<string*>* state_files;
2500 string this_snapshot_path;
2506 if (ripped[ripped.length()-1] == G_DIR_SEPARATOR) {
2507 ripped = ripped.substr (0, ripped.length() - 1);
2510 state_files = scanner (ripped, accept_all_state_files, (void *) 0, true, true);
2512 if (state_files == 0) {
2517 this_snapshot_path = _path;
2518 this_snapshot_path += legalize_for_path (_current_snapshot_name);
2519 this_snapshot_path += statefile_suffix;
2521 for (vector<string*>::iterator i = state_files->begin(); i != state_files->end(); ++i) {
2523 if (exclude_this_snapshot && **i == this_snapshot_path) {
2527 if (find_all_sources (**i, result) < 0) {
2535 struct RegionCounter {
2536 typedef std::map<PBD::ID,boost::shared_ptr<AudioSource> > AudioSourceList;
2537 AudioSourceList::iterator iter;
2538 boost::shared_ptr<Region> region;
2541 RegionCounter() : count (0) {}
2545 Session::ask_about_playlist_deletion (boost::shared_ptr<Playlist> p)
2547 boost::optional<int> r = AskAboutPlaylistDeletion (p);
2548 return r.get_value_or (1);
2552 Session::cleanup_regions ()
2554 const RegionFactory::RegionMap& regions (RegionFactory::regions());
2556 for (RegionFactory::RegionMap::const_iterator i = regions.begin(); i != regions.end(); ++i) {
2558 uint32_t used = playlists->region_use_count (i->second);
2560 if (used == 0 && !i->second->automatic ()) {
2561 RegionFactory::map_remove (i->second);
2565 /* dump the history list */
2572 Session::cleanup_sources (CleanupReport& rep)
2574 // FIXME: needs adaptation to midi
2576 vector<boost::shared_ptr<Source> > dead_sources;
2577 PathScanner scanner;
2580 vector<space_and_path>::iterator i;
2581 vector<space_and_path>::iterator nexti;
2582 vector<string*>* candidates;
2583 vector<string*>* candidates2;
2584 vector<string> unused;
2585 set<string> all_sources;
2590 _state_of_the_state = (StateOfTheState) (_state_of_the_state | InCleanup);
2592 /* consider deleting all unused playlists */
2594 if (playlists->maybe_delete_unused (boost::bind (Session::ask_about_playlist_deletion, _1))) {
2599 /* sync the "all regions" property of each playlist with its current state
2602 playlists->sync_all_regions_with_regions ();
2604 /* find all un-used sources */
2609 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ) {
2611 SourceMap::iterator tmp;
2616 /* do not bother with files that are zero size, otherwise we remove the current "nascent"
2620 if (!i->second->used() && (i->second->length(i->second->timeline_position() > 0))) {
2621 dead_sources.push_back (i->second);
2622 i->second->drop_references ();
2628 /* build a list of all the possible audio directories for the session */
2630 for (i = session_dirs.begin(); i != session_dirs.end(); ) {
2635 SessionDirectory sdir ((*i).path);
2636 audio_path += sdir.sound_path();
2638 if (nexti != session_dirs.end()) {
2646 /* build a list of all the possible midi directories for the session */
2648 for (i = session_dirs.begin(); i != session_dirs.end(); ) {
2653 SessionDirectory sdir ((*i).path);
2654 midi_path += sdir.midi_path();
2656 if (nexti != session_dirs.end()) {
2663 candidates = scanner (audio_path, accept_all_audio_files, (void *) 0, true, true);
2664 candidates2 = scanner (midi_path, accept_all_midi_files, (void *) 0, true, true);
2670 for (vector<string*>::iterator i = candidates2->begin(); i != candidates2->end(); ++i) {
2671 candidates->push_back (*i);
2676 candidates = candidates2; // might still be null
2679 /* find all sources, but don't use this snapshot because the
2680 state file on disk still references sources we may have already
2684 find_all_sources_across_snapshots (all_sources, true);
2686 /* add our current source list
2689 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ) {
2690 boost::shared_ptr<FileSource> fs;
2691 SourceMap::iterator tmp = i;
2694 if ((fs = boost::dynamic_pointer_cast<FileSource> (i->second)) != 0) {
2695 if (playlists->source_use_count (fs) != 0) {
2696 all_sources.insert (fs->path());
2699 /* we might not remove this source from disk, because it may be used
2700 by other snapshots, but its not being used in this version
2701 so lets get rid of it now, along with any representative regions
2705 RegionFactory::remove_regions_using_source (i->second);
2713 char tmppath1[PATH_MAX+1];
2714 char tmppath2[PATH_MAX+1];
2717 for (vector<string*>::iterator x = candidates->begin(); x != candidates->end(); ++x) {
2722 for (set<string>::iterator i = all_sources.begin(); i != all_sources.end(); ++i) {
2724 if (realpath(spath.c_str(), tmppath1) == 0) {
2725 error << string_compose (_("Cannot expand path %1 (%2)"),
2726 spath, strerror (errno)) << endmsg;
2730 if (realpath((*i).c_str(), tmppath2) == 0) {
2731 error << string_compose (_("Cannot expand path %1 (%2)"),
2732 (*i), strerror (errno)) << endmsg;
2736 if (strcmp(tmppath1, tmppath2) == 0) {
2743 unused.push_back (spath);
2752 /* now try to move all unused files into the "dead" directory(ies) */
2754 for (vector<string>::iterator x = unused.begin(); x != unused.end(); ++x) {
2755 struct stat statbuf;
2759 /* don't move the file across filesystems, just
2760 stick it in the `dead_dir_name' directory
2761 on whichever filesystem it was already on.
2764 if ((*x).find ("/sounds/") != string::npos) {
2766 /* old school, go up 1 level */
2768 newpath = Glib::path_get_dirname (*x); // "sounds"
2769 newpath = Glib::path_get_dirname (newpath); // "session-name"
2773 /* new school, go up 4 levels */
2775 newpath = Glib::path_get_dirname (*x); // "audiofiles" or "midifiles"
2776 newpath = Glib::path_get_dirname (newpath); // "session-name"
2777 newpath = Glib::path_get_dirname (newpath); // "interchange"
2778 newpath = Glib::path_get_dirname (newpath); // "session-dir"
2781 newpath = Glib::build_filename (newpath, dead_dir_name);
2783 if (g_mkdir_with_parents (newpath.c_str(), 0755) < 0) {
2784 error << string_compose(_("Session: cannot create dead file folder \"%1\" (%2)"), newpath, strerror (errno)) << endmsg;
2788 newpath = Glib::build_filename (newpath, Glib::path_get_basename ((*x)));
2790 if (Glib::file_test (newpath, Glib::FILE_TEST_EXISTS)) {
2792 /* the new path already exists, try versioning */
2794 char buf[PATH_MAX+1];
2798 snprintf (buf, sizeof (buf), "%s.%d", newpath.c_str(), version);
2801 while (Glib::file_test (newpath_v.c_str(), Glib::FILE_TEST_EXISTS) && version < 999) {
2802 snprintf (buf, sizeof (buf), "%s.%d", newpath.c_str(), ++version);
2806 if (version == 999) {
2807 error << string_compose (_("there are already 1000 files with names like %1; versioning discontinued"),
2811 newpath = newpath_v;
2816 /* it doesn't exist, or we can't read it or something */
2820 stat ((*x).c_str(), &statbuf);
2822 if (::rename ((*x).c_str(), newpath.c_str()) != 0) {
2823 error << string_compose (_("cannot rename unused file source from %1 to %2 (%3)"),
2824 (*x), newpath, strerror (errno))
2829 /* see if there an easy to find peakfile for this file, and remove it.
2832 string base = basename_nosuffix (*x);
2833 base += "%A"; /* this is what we add for the channel suffix of all native files,
2834 or for the first channel of embedded files. it will miss
2835 some peakfiles for other channels
2837 string peakpath = peak_path (base);
2839 if (Glib::file_test (peakpath.c_str(), Glib::FILE_TEST_EXISTS)) {
2840 if (::unlink (peakpath.c_str()) != 0) {
2841 error << string_compose (_("cannot remove peakfile %1 for %2 (%3)"),
2842 peakpath, _path, strerror (errno))
2844 /* try to back out */
2845 ::rename (newpath.c_str(), _path.c_str());
2850 rep.paths.push_back (*x);
2851 rep.space += statbuf.st_size;
2854 /* dump the history list */
2858 /* save state so we don't end up a session file
2859 referring to non-existent sources.
2866 _state_of_the_state = (StateOfTheState) (_state_of_the_state & ~InCleanup);
2872 Session::cleanup_trash_sources (CleanupReport& rep)
2874 // FIXME: needs adaptation for MIDI
2876 vector<space_and_path>::iterator i;
2882 for (i = session_dirs.begin(); i != session_dirs.end(); ++i) {
2884 dead_dir = Glib::build_filename ((*i).path, dead_dir_name);
2886 clear_directory (dead_dir, &rep.space, &rep.paths);
2893 Session::set_dirty ()
2895 bool was_dirty = dirty();
2897 _state_of_the_state = StateOfTheState (_state_of_the_state | Dirty);
2901 DirtyChanged(); /* EMIT SIGNAL */
2907 Session::set_clean ()
2909 bool was_dirty = dirty();
2911 _state_of_the_state = Clean;
2915 DirtyChanged(); /* EMIT SIGNAL */
2920 Session::set_deletion_in_progress ()
2922 _state_of_the_state = StateOfTheState (_state_of_the_state | Deletion);
2926 Session::clear_deletion_in_progress ()
2928 _state_of_the_state = StateOfTheState (_state_of_the_state & (~Deletion));
2932 Session::add_controllable (boost::shared_ptr<Controllable> c)
2934 /* this adds a controllable to the list managed by the Session.
2935 this is a subset of those managed by the Controllable class
2936 itself, and represents the only ones whose state will be saved
2937 as part of the session.
2940 Glib::Threads::Mutex::Lock lm (controllables_lock);
2941 controllables.insert (c);
2944 struct null_deleter { void operator()(void const *) const {} };
2947 Session::remove_controllable (Controllable* c)
2949 if (_state_of_the_state & Deletion) {
2953 Glib::Threads::Mutex::Lock lm (controllables_lock);
2955 Controllables::iterator x = controllables.find (boost::shared_ptr<Controllable>(c, null_deleter()));
2957 if (x != controllables.end()) {
2958 controllables.erase (x);
2962 boost::shared_ptr<Controllable>
2963 Session::controllable_by_id (const PBD::ID& id)
2965 Glib::Threads::Mutex::Lock lm (controllables_lock);
2967 for (Controllables::iterator i = controllables.begin(); i != controllables.end(); ++i) {
2968 if ((*i)->id() == id) {
2973 return boost::shared_ptr<Controllable>();
2976 boost::shared_ptr<Controllable>
2977 Session::controllable_by_descriptor (const ControllableDescriptor& desc)
2979 boost::shared_ptr<Controllable> c;
2980 boost::shared_ptr<Route> r;
2982 switch (desc.top_level_type()) {
2983 case ControllableDescriptor::NamedRoute:
2985 std::string str = desc.top_level_name();
2986 if (str == "master") {
2988 } else if (str == "control" || str == "listen") {
2991 r = route_by_name (desc.top_level_name());
2996 case ControllableDescriptor::RemoteControlID:
2997 r = route_by_remote_id (desc.rid());
3005 switch (desc.subtype()) {
3006 case ControllableDescriptor::Gain:
3007 c = r->gain_control ();
3010 case ControllableDescriptor::Solo:
3011 c = r->solo_control();
3014 case ControllableDescriptor::Mute:
3015 c = r->mute_control();
3018 case ControllableDescriptor::Recenable:
3020 boost::shared_ptr<Track> t = boost::dynamic_pointer_cast<Track>(r);
3023 c = t->rec_enable_control ();
3028 case ControllableDescriptor::PanDirection:
3030 c = r->pannable()->pan_azimuth_control;
3034 case ControllableDescriptor::PanWidth:
3036 c = r->pannable()->pan_width_control;
3040 case ControllableDescriptor::PanElevation:
3042 c = r->pannable()->pan_elevation_control;
3046 case ControllableDescriptor::Balance:
3047 /* XXX simple pan control */
3050 case ControllableDescriptor::PluginParameter:
3052 uint32_t plugin = desc.target (0);
3053 uint32_t parameter_index = desc.target (1);
3055 /* revert to zero based counting */
3061 if (parameter_index > 0) {
3065 boost::shared_ptr<Processor> p = r->nth_plugin (plugin);
3068 c = boost::dynamic_pointer_cast<ARDOUR::AutomationControl>(
3069 p->control(Evoral::Parameter(PluginAutomation, 0, parameter_index)));
3074 case ControllableDescriptor::SendGain:
3076 uint32_t send = desc.target (0);
3078 /* revert to zero-based counting */
3084 boost::shared_ptr<Processor> p = r->nth_send (send);
3087 boost::shared_ptr<Send> s = boost::dynamic_pointer_cast<Send>(p);
3088 boost::shared_ptr<Amp> a = s->amp();
3091 c = s->amp()->gain_control();
3098 /* relax and return a null pointer */
3106 Session::add_instant_xml (XMLNode& node, bool write_to_config)
3109 Stateful::add_instant_xml (node, _path);
3112 if (write_to_config) {
3113 Config->add_instant_xml (node);
3118 Session::instant_xml (const string& node_name)
3120 return Stateful::instant_xml (node_name, _path);
3124 Session::save_history (string snapshot_name)
3132 if (snapshot_name.empty()) {
3133 snapshot_name = _current_snapshot_name;
3136 const string history_filename = legalize_for_path (snapshot_name) + history_suffix;
3137 const string backup_filename = history_filename + backup_suffix;
3138 const std::string xml_path(Glib::build_filename (_session_dir->root_path(), history_filename));
3139 const std::string backup_path(Glib::build_filename (_session_dir->root_path(), backup_filename));
3141 if (Glib::file_test (xml_path, Glib::FILE_TEST_EXISTS)) {
3142 if (::g_rename (xml_path.c_str(), backup_path.c_str()) != 0) {
3143 error << _("could not backup old history file, current history not saved") << endmsg;
3148 if (!Config->get_save_history() || Config->get_saved_history_depth() < 0) {
3152 tree.set_root (&_history.get_state (Config->get_saved_history_depth()));
3154 if (!tree.write (xml_path))
3156 error << string_compose (_("history could not be saved to %1"), xml_path) << endmsg;
3158 if (g_remove (xml_path.c_str()) != 0) {
3159 error << string_compose(_("Could not remove history file at path \"%1\" (%2)"),
3160 xml_path, g_strerror (errno)) << endmsg;
3162 if (::g_rename (backup_path.c_str(), xml_path.c_str()) != 0) {
3163 error << string_compose (_("could not restore history file from backup %1 (%2)"),
3164 backup_path, g_strerror (errno)) << endmsg;
3174 Session::restore_history (string snapshot_name)
3178 if (snapshot_name.empty()) {
3179 snapshot_name = _current_snapshot_name;
3182 const std::string xml_filename = legalize_for_path (snapshot_name) + history_suffix;
3183 const std::string xml_path(Glib::build_filename (_session_dir->root_path(), xml_filename));
3185 info << "Loading history from " << xml_path << endmsg;
3187 if (!Glib::file_test (xml_path, Glib::FILE_TEST_EXISTS)) {
3188 info << string_compose (_("%1: no history file \"%2\" for this session."),
3189 _name, xml_path) << endmsg;
3193 if (!tree.read (xml_path)) {
3194 error << string_compose (_("Could not understand session history file \"%1\""),
3195 xml_path) << endmsg;
3202 for (XMLNodeConstIterator it = tree.root()->children().begin(); it != tree.root()->children().end(); it++) {
3205 UndoTransaction* ut = new UndoTransaction ();
3208 ut->set_name(t->property("name")->value());
3209 stringstream ss(t->property("tv-sec")->value());
3211 ss.str(t->property("tv-usec")->value());
3213 ut->set_timestamp(tv);
3215 for (XMLNodeConstIterator child_it = t->children().begin();
3216 child_it != t->children().end(); child_it++)
3218 XMLNode *n = *child_it;
3221 if (n->name() == "MementoCommand" ||
3222 n->name() == "MementoUndoCommand" ||
3223 n->name() == "MementoRedoCommand") {
3225 if ((c = memento_command_factory(n))) {
3229 } else if (n->name() == "NoteDiffCommand") {
3230 PBD::ID id (n->property("midi-source")->value());
3231 boost::shared_ptr<MidiSource> midi_source =
3232 boost::dynamic_pointer_cast<MidiSource, Source>(source_by_id(id));
3234 ut->add_command (new MidiModel::NoteDiffCommand(midi_source->model(), *n));
3236 error << _("Failed to downcast MidiSource for NoteDiffCommand") << endmsg;
3239 } else if (n->name() == "SysExDiffCommand") {
3241 PBD::ID id (n->property("midi-source")->value());
3242 boost::shared_ptr<MidiSource> midi_source =
3243 boost::dynamic_pointer_cast<MidiSource, Source>(source_by_id(id));
3245 ut->add_command (new MidiModel::SysExDiffCommand (midi_source->model(), *n));
3247 error << _("Failed to downcast MidiSource for SysExDiffCommand") << endmsg;
3250 } else if (n->name() == "PatchChangeDiffCommand") {
3252 PBD::ID id (n->property("midi-source")->value());
3253 boost::shared_ptr<MidiSource> midi_source =
3254 boost::dynamic_pointer_cast<MidiSource, Source>(source_by_id(id));
3256 ut->add_command (new MidiModel::PatchChangeDiffCommand (midi_source->model(), *n));
3258 error << _("Failed to downcast MidiSource for PatchChangeDiffCommand") << endmsg;
3261 } else if (n->name() == "StatefulDiffCommand") {
3262 if ((c = stateful_diff_command_factory (n))) {
3263 ut->add_command (c);
3266 error << string_compose(_("Couldn't figure out how to make a Command out of a %1 XMLNode."), n->name()) << endmsg;
3277 Session::config_changed (std::string p, bool ours)
3283 if (p == "seamless-loop") {
3285 } else if (p == "rf-speed") {
3287 } else if (p == "auto-loop") {
3289 } else if (p == "auto-input") {
3291 if (Config->get_monitoring_model() == HardwareMonitoring && transport_rolling()) {
3292 /* auto-input only makes a difference if we're rolling */
3293 set_track_monitor_input_status (!config.get_auto_input());
3296 } else if (p == "punch-in") {
3300 if ((location = _locations->auto_punch_location()) != 0) {
3302 if (config.get_punch_in ()) {
3303 replace_event (SessionEvent::PunchIn, location->start());
3305 remove_event (location->start(), SessionEvent::PunchIn);
3309 } else if (p == "punch-out") {
3313 if ((location = _locations->auto_punch_location()) != 0) {
3315 if (config.get_punch_out()) {
3316 replace_event (SessionEvent::PunchOut, location->end());
3318 clear_events (SessionEvent::PunchOut);
3322 } else if (p == "edit-mode") {
3324 Glib::Threads::Mutex::Lock lm (playlists->lock);
3326 for (SessionPlaylists::List::iterator i = playlists->playlists.begin(); i != playlists->playlists.end(); ++i) {
3327 (*i)->set_edit_mode (Config->get_edit_mode ());
3330 } else if (p == "use-video-sync") {
3332 waiting_for_sync_offset = config.get_use_video_sync();
3334 } else if (p == "mmc-control") {
3336 //poke_midi_thread ();
3338 } else if (p == "mmc-device-id" || p == "mmc-receive-id" || p == "mmc-receive-device-id") {
3340 _mmc->set_receive_device_id (Config->get_mmc_receive_device_id());
3342 } else if (p == "mmc-send-id" || p == "mmc-send-device-id") {
3344 _mmc->set_send_device_id (Config->get_mmc_send_device_id());
3346 } else if (p == "midi-control") {
3348 //poke_midi_thread ();
3350 } else if (p == "raid-path") {
3352 setup_raid_path (config.get_raid_path());
3354 } else if (p == "timecode-format") {
3358 } else if (p == "video-pullup") {
3362 } else if (p == "seamless-loop") {
3364 if (play_loop && transport_rolling()) {
3365 // to reset diskstreams etc
3366 request_play_loop (true);
3369 } else if (p == "rf-speed") {
3371 cumulative_rf_motion = 0;
3374 } else if (p == "click-sound") {
3376 setup_click_sounds (1);
3378 } else if (p == "click-emphasis-sound") {
3380 setup_click_sounds (-1);
3382 } else if (p == "clicking") {
3384 if (Config->get_clicking()) {
3385 if (_click_io && click_data) { // don't require emphasis data
3392 } else if (p == "click-gain") {
3395 _click_gain->set_gain (Config->get_click_gain(), this);
3398 } else if (p == "send-mtc") {
3400 if (Config->get_send_mtc ()) {
3401 /* mark us ready to send */
3402 next_quarter_frame_to_send = 0;
3405 } else if (p == "send-mmc") {
3407 _mmc->enable_send (Config->get_send_mmc ());
3409 } else if (p == "midi-feedback") {
3411 session_midi_feedback = Config->get_midi_feedback();
3413 } else if (p == "jack-time-master") {
3415 engine().reset_timebase ();
3417 } else if (p == "native-file-header-format") {
3419 if (!first_file_header_format_reset) {
3420 reset_native_file_format ();
3423 first_file_header_format_reset = false;
3425 } else if (p == "native-file-data-format") {
3427 if (!first_file_data_format_reset) {
3428 reset_native_file_format ();
3431 first_file_data_format_reset = false;
3433 } else if (p == "external-sync") {
3434 if (!config.get_external_sync()) {
3435 drop_sync_source ();
3437 switch_to_sync_source (Config->get_sync_source());
3439 } else if (p == "denormal-model") {
3441 } else if (p == "history-depth") {
3442 set_history_depth (Config->get_history_depth());
3443 } else if (p == "remote-model") {
3444 /* XXX DO SOMETHING HERE TO TELL THE GUI THAT WE NEED
3447 } else if (p == "initial-program-change") {
3449 if (_mmc->output_port() && Config->get_initial_program_change() >= 0) {
3452 buf[0] = MIDI::program; // channel zero by default
3453 buf[1] = (Config->get_initial_program_change() & 0x7f);
3455 _mmc->output_port()->midimsg (buf, sizeof (buf), 0);
3457 } else if (p == "solo-mute-override") {
3458 // catch_up_on_solo_mute_override ();
3459 } else if (p == "listen-position" || p == "pfl-position") {
3460 listen_position_changed ();
3461 } else if (p == "solo-control-is-listen-control") {
3462 solo_control_mode_changed ();
3463 } else if (p == "timecode-offset" || p == "timecode-offset-negative") {
3464 last_timecode_valid = false;
3465 } else if (p == "playback-buffer-seconds") {
3466 AudioSource::allocate_working_buffers (frame_rate());
3467 } else if (p == "automation-thinning-factor") {
3468 Evoral::ControlList::set_thinning_factor (Config->get_automation_thinning_factor());
3469 } else if (p == "ltc-source-port") {
3470 reconnect_ltc_input ();
3471 } else if (p == "ltc-sink-port") {
3472 reconnect_ltc_output ();
3473 } else if (p == "timecode-generator-offset") {
3474 ltc_tx_parse_offset();
3481 Session::set_history_depth (uint32_t d)
3483 _history.set_depth (d);
3487 Session::load_diskstreams_2X (XMLNode const & node, int)
3490 XMLNodeConstIterator citer;
3492 clist = node.children();
3494 for (citer = clist.begin(); citer != clist.end(); ++citer) {
3497 /* diskstreams added automatically by DiskstreamCreated handler */
3498 if ((*citer)->name() == "AudioDiskstream" || (*citer)->name() == "DiskStream") {
3499 boost::shared_ptr<AudioDiskstream> dsp (new AudioDiskstream (*this, **citer));
3500 _diskstreams_2X.push_back (dsp);
3502 error << _("Session: unknown diskstream type in XML") << endmsg;
3506 catch (failed_constructor& err) {
3507 error << _("Session: could not load diskstream via XML state") << endmsg;
3515 /** Connect things to the MMC object */
3517 Session::setup_midi_machine_control ()
3519 _mmc = new MIDI::MachineControl;
3520 _mmc->set_ports (_midi_ports->mmc_input_port(), _midi_ports->mmc_output_port());
3522 _mmc->Play.connect_same_thread (*this, boost::bind (&Session::mmc_deferred_play, this, _1));
3523 _mmc->DeferredPlay.connect_same_thread (*this, boost::bind (&Session::mmc_deferred_play, this, _1));
3524 _mmc->Stop.connect_same_thread (*this, boost::bind (&Session::mmc_stop, this, _1));
3525 _mmc->FastForward.connect_same_thread (*this, boost::bind (&Session::mmc_fast_forward, this, _1));
3526 _mmc->Rewind.connect_same_thread (*this, boost::bind (&Session::mmc_rewind, this, _1));
3527 _mmc->Pause.connect_same_thread (*this, boost::bind (&Session::mmc_pause, this, _1));
3528 _mmc->RecordPause.connect_same_thread (*this, boost::bind (&Session::mmc_record_pause, this, _1));
3529 _mmc->RecordStrobe.connect_same_thread (*this, boost::bind (&Session::mmc_record_strobe, this, _1));
3530 _mmc->RecordExit.connect_same_thread (*this, boost::bind (&Session::mmc_record_exit, this, _1));
3531 _mmc->Locate.connect_same_thread (*this, boost::bind (&Session::mmc_locate, this, _1, _2));
3532 _mmc->Step.connect_same_thread (*this, boost::bind (&Session::mmc_step, this, _1, _2));
3533 _mmc->Shuttle.connect_same_thread (*this, boost::bind (&Session::mmc_shuttle, this, _1, _2, _3));
3534 _mmc->TrackRecordStatusChange.connect_same_thread (*this, boost::bind (&Session::mmc_record_enable, this, _1, _2, _3));
3536 /* also handle MIDI SPP because its so common */
3538 _mmc->SPPStart.connect_same_thread (*this, boost::bind (&Session::spp_start, this));
3539 _mmc->SPPContinue.connect_same_thread (*this, boost::bind (&Session::spp_continue, this));
3540 _mmc->SPPStop.connect_same_thread (*this, boost::bind (&Session::spp_stop, this));
3543 boost::shared_ptr<Controllable>
3544 Session::solo_cut_control() const
3546 /* the solo cut control is a bit of an anomaly, at least as of Febrary 2011. There are no other
3547 controls in Ardour that currently get presented to the user in the GUI that require
3548 access as a Controllable and are also NOT owned by some SessionObject (e.g. Route, or MonitorProcessor).
3550 its actually an RCConfiguration parameter, so we use a ProxyControllable to wrap
3551 it up as a Controllable. Changes to the Controllable will just map back to the RCConfiguration
3555 return _solo_cut_control;
3559 Session::rename (const std::string& new_name)
3561 string legal_name = legalize_for_path (new_name);
3567 string const old_sources_root = _session_dir->sources_root();
3569 #define RENAME ::rename
3574 * interchange subdirectory
3578 * Backup files are left unchanged and not renamed.
3581 /* pass one: not 100% safe check that the new directory names don't
3585 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
3590 /* this is a stupid hack because Glib::path_get_dirname() is
3591 * lexical-only, and so passing it /a/b/c/ gives a different
3592 * result than passing it /a/b/c ...
3595 if (oldstr[oldstr.length()-1] == G_DIR_SEPARATOR) {
3596 oldstr = oldstr.substr (0, oldstr.length() - 1);
3599 string base = Glib::path_get_dirname (oldstr);
3600 string p = Glib::path_get_basename (oldstr);
3602 newstr = Glib::build_filename (base, legal_name);
3604 if (Glib::file_test (newstr, Glib::FILE_TEST_EXISTS)) {
3611 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
3616 /* this is a stupid hack because Glib::path_get_dirname() is
3617 * lexical-only, and so passing it /a/b/c/ gives a different
3618 * result than passing it /a/b/c ...
3621 if (oldstr[oldstr.length()-1] == G_DIR_SEPARATOR) {
3622 oldstr = oldstr.substr (0, oldstr.length() - 1);
3625 string base = Glib::path_get_dirname (oldstr);
3626 string p = Glib::path_get_basename (oldstr);
3628 newstr = Glib::build_filename (base, legal_name);
3630 cerr << "Rename " << oldstr << " => " << newstr << endl;
3632 if (RENAME (oldstr.c_str(), newstr.c_str()) != 0) {
3637 (*_session_dir) = newstr;
3642 /* directory below interchange */
3644 v.push_back (newstr);
3645 v.push_back (interchange_dir_name);
3648 oldstr = Glib::build_filename (v);
3651 v.push_back (newstr);
3652 v.push_back (interchange_dir_name);
3653 v.push_back (legal_name);
3655 newstr = Glib::build_filename (v);
3657 cerr << "Rename " << oldstr << " => " << newstr << endl;
3659 if (RENAME (oldstr.c_str(), newstr.c_str()) != 0) {
3666 oldstr = Glib::build_filename (newpath, _current_snapshot_name) + statefile_suffix;
3667 newstr= Glib::build_filename (newpath, legal_name) + statefile_suffix;
3669 cerr << "Rename " << oldstr << " => " << newstr << endl;
3671 if (RENAME (oldstr.c_str(), newstr.c_str()) != 0) {
3678 oldstr = Glib::build_filename (newpath, _current_snapshot_name) + history_suffix;
3680 if (Glib::file_test (oldstr, Glib::FILE_TEST_EXISTS)) {
3681 newstr = Glib::build_filename (newpath, legal_name) + history_suffix;
3683 cerr << "Rename " << oldstr << " => " << newstr << endl;
3685 if (RENAME (oldstr.c_str(), newstr.c_str()) != 0) {
3690 /* update file source paths */
3692 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ++i) {
3693 boost::shared_ptr<FileSource> fs = boost::dynamic_pointer_cast<FileSource> (i->second);
3695 string p = fs->path ();
3696 boost::replace_all (p, old_sources_root, _session_dir->sources_root());
3701 /* remove old name from recent sessions */
3703 remove_recent_sessions (_path);
3706 _current_snapshot_name = new_name;
3711 /* save state again to get everything just right */
3713 save_state (_current_snapshot_name);
3716 /* add to recent sessions */
3718 store_recent_sessions (new_name, _path);
3726 Session::get_session_info_from_path (XMLTree& tree, const string& xmlpath)
3728 if (!Glib::file_test (xmlpath, Glib::FILE_TEST_EXISTS)) {
3732 if (!tree.read (xmlpath)) {
3740 Session::get_info_from_path (const string& xmlpath, float& sample_rate, SampleFormat& data_format)
3743 bool found_sr = false;
3744 bool found_data_format = false;
3746 if (get_session_info_from_path (tree, xmlpath)) {
3752 const XMLProperty* prop;
3753 if ((prop = tree.root()->property (X_("sample-rate"))) != 0) {
3754 sample_rate = atoi (prop->value());
3758 const XMLNodeList& children (tree.root()->children());
3759 for (XMLNodeList::const_iterator c = children.begin(); c != children.end(); ++c) {
3760 const XMLNode* child = *c;
3761 if (child->name() == "Config") {
3762 const XMLNodeList& options (child->children());
3763 for (XMLNodeList::const_iterator oc = options.begin(); oc != options.end(); ++oc) {
3764 const XMLNode* option = *oc;
3765 const XMLProperty* name = option->property("name");
3771 if (name->value() == "native-file-data-format") {
3772 const XMLProperty* value = option->property ("value");
3774 SampleFormat fmt = (SampleFormat) string_2_enum (option->property ("value")->value(), fmt);
3776 found_data_format = true;
3782 if (found_data_format) {
3787 return !(found_sr && found_data_format); // zero if they are both found