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()) {
983 cerr << "DEBUG: source '"
984 << fs->name() << "' id: "
985 << fs->id() << " is marked as empty and unused and is not saved.\n";
991 cerr << "DEBUG: saving source '"
992 << fs->name() << "' id: "
993 << fs->id() << ".\n";
996 child->add_child_nocopy (siter->second->get_state());
1001 child = node->add_child ("Regions");
1004 Glib::Threads::Mutex::Lock rl (region_lock);
1005 const RegionFactory::RegionMap& region_map (RegionFactory::all_regions());
1006 for (RegionFactory::RegionMap::const_iterator i = region_map.begin(); i != region_map.end(); ++i) {
1007 boost::shared_ptr<Region> r = i->second;
1008 /* only store regions not attached to playlists */
1009 if (r->playlist() == 0) {
1010 if (boost::dynamic_pointer_cast<AudioRegion>(r)) {
1011 child->add_child_nocopy ((boost::dynamic_pointer_cast<AudioRegion>(r))->get_basic_state ());
1013 child->add_child_nocopy (r->get_state ());
1018 RegionFactory::CompoundAssociations& cassocs (RegionFactory::compound_associations());
1020 if (!cassocs.empty()) {
1021 XMLNode* ca = node->add_child (X_("CompoundAssociations"));
1023 for (RegionFactory::CompoundAssociations::iterator i = cassocs.begin(); i != cassocs.end(); ++i) {
1025 XMLNode* can = new XMLNode (X_("CompoundAssociation"));
1026 i->first->id().print (buf, sizeof (buf));
1027 can->add_property (X_("copy"), buf);
1028 i->second->id().print (buf, sizeof (buf));
1029 can->add_property (X_("original"), buf);
1030 ca->add_child_nocopy (*can);
1036 node->add_child_nocopy (_locations->get_state());
1038 // for a template, just create a new Locations, populate it
1039 // with the default start and end, and get the state for that.
1040 Locations loc (*this);
1041 Location* range = new Location (*this, 0, 0, _("session"), Location::IsSessionRange);
1042 range->set (max_framepos, 0);
1044 node->add_child_nocopy (loc.get_state());
1047 child = node->add_child ("Bundles");
1049 boost::shared_ptr<BundleList> bundles = _bundles.reader ();
1050 for (BundleList::iterator i = bundles->begin(); i != bundles->end(); ++i) {
1051 boost::shared_ptr<UserBundle> b = boost::dynamic_pointer_cast<UserBundle> (*i);
1053 child->add_child_nocopy (b->get_state());
1058 child = node->add_child ("Routes");
1060 boost::shared_ptr<RouteList> r = routes.reader ();
1062 RoutePublicOrderSorter cmp;
1063 RouteList public_order (*r);
1064 public_order.sort (cmp);
1066 /* the sort should have put control outs first */
1069 assert (_monitor_out == public_order.front());
1072 for (RouteList::iterator i = public_order.begin(); i != public_order.end(); ++i) {
1073 if (!(*i)->is_auditioner()) {
1075 child->add_child_nocopy ((*i)->get_state());
1077 child->add_child_nocopy ((*i)->get_template());
1083 playlists->add_state (node, full_state);
1085 child = node->add_child ("RouteGroups");
1086 for (list<RouteGroup *>::iterator i = _route_groups.begin(); i != _route_groups.end(); ++i) {
1087 child->add_child_nocopy ((*i)->get_state());
1091 XMLNode* gain_child = node->add_child ("Click");
1092 gain_child->add_child_nocopy (_click_io->state (full_state));
1093 gain_child->add_child_nocopy (_click_gain->state (full_state));
1097 XMLNode* ltc_input_child = node->add_child ("LTC-In");
1098 ltc_input_child->add_child_nocopy (_ltc_input->state (full_state));
1102 XMLNode* ltc_output_child = node->add_child ("LTC-Out");
1103 ltc_output_child->add_child_nocopy (_ltc_output->state (full_state));
1106 node->add_child_nocopy (_speakers->get_state());
1107 node->add_child_nocopy (_tempo_map->get_state());
1108 node->add_child_nocopy (get_control_protocol_state());
1111 node->add_child_copy (*_extra_xml);
1118 Session::get_control_protocol_state ()
1120 ControlProtocolManager& cpm (ControlProtocolManager::instance());
1121 return cpm.get_state();
1125 Session::set_state (const XMLNode& node, int version)
1129 const XMLProperty* prop;
1132 _state_of_the_state = StateOfTheState (_state_of_the_state|CannotSave);
1134 if (node.name() != X_("Session")) {
1135 fatal << _("programming error: Session: incorrect XML node sent to set_state()") << endmsg;
1139 if ((prop = node.property ("name")) != 0) {
1140 _name = prop->value ();
1143 if ((prop = node.property (X_("sample-rate"))) != 0) {
1145 _nominal_frame_rate = atoi (prop->value());
1147 if (_nominal_frame_rate != _current_frame_rate) {
1148 boost::optional<int> r = AskAboutSampleRateMismatch (_nominal_frame_rate, _current_frame_rate);
1149 if (r.get_value_or (0)) {
1155 setup_raid_path(_session_dir->root_path());
1157 if ((prop = node.property (X_("id-counter"))) != 0) {
1159 sscanf (prop->value().c_str(), "%" PRIu64, &x);
1160 ID::init_counter (x);
1162 /* old sessions used a timebased counter, so fake
1163 the startup ID counter based on a standard
1168 ID::init_counter (now);
1171 if ((prop = node.property (X_("event-counter"))) != 0) {
1172 Evoral::init_event_id_counter (atoi (prop->value()));
1176 if ((child = find_named_node (node, "MIDIPorts")) != 0) {
1177 _midi_ports->set_midi_port_states (child->children());
1180 IO::disable_connecting ();
1182 Stateful::save_extra_xml (node);
1184 if (((child = find_named_node (node, "Options")) != 0)) { /* old style */
1185 load_options (*child);
1186 } else if ((child = find_named_node (node, "Config")) != 0) { /* new style */
1187 load_options (*child);
1189 error << _("Session: XML state has no options section") << endmsg;
1192 if (version >= 3000) {
1193 if ((child = find_named_node (node, "Metadata")) == 0) {
1194 warning << _("Session: XML state has no metadata section") << endmsg;
1195 } else if ( ARDOUR::SessionMetadata::Metadata()->set_state (*child, version) ) {
1200 if ((child = find_named_node (node, X_("Speakers"))) != 0) {
1201 _speakers->set_state (*child, version);
1204 if ((child = find_named_node (node, "Sources")) == 0) {
1205 error << _("Session: XML state has no sources section") << endmsg;
1207 } else if (load_sources (*child)) {
1211 if ((child = find_named_node (node, "TempoMap")) == 0) {
1212 error << _("Session: XML state has no Tempo Map section") << endmsg;
1214 } else if (_tempo_map->set_state (*child, version)) {
1218 if ((child = find_named_node (node, "Locations")) == 0) {
1219 error << _("Session: XML state has no locations section") << endmsg;
1221 } else if (_locations->set_state (*child, version)) {
1227 if ((location = _locations->auto_loop_location()) != 0) {
1228 set_auto_loop_location (location);
1231 if ((location = _locations->auto_punch_location()) != 0) {
1232 set_auto_punch_location (location);
1235 if ((location = _locations->session_range_location()) != 0) {
1236 delete _session_range_location;
1237 _session_range_location = location;
1240 if (_session_range_location) {
1241 AudioFileSource::set_header_position_offset (_session_range_location->start());
1244 if ((child = find_named_node (node, "Regions")) == 0) {
1245 error << _("Session: XML state has no Regions section") << endmsg;
1247 } else if (load_regions (*child)) {
1251 if ((child = find_named_node (node, "Playlists")) == 0) {
1252 error << _("Session: XML state has no playlists section") << endmsg;
1254 } else if (playlists->load (*this, *child)) {
1258 if ((child = find_named_node (node, "UnusedPlaylists")) == 0) {
1260 } else if (playlists->load_unused (*this, *child)) {
1264 if ((child = find_named_node (node, "CompoundAssociations")) != 0) {
1265 if (load_compounds (*child)) {
1270 if (version >= 3000) {
1271 if ((child = find_named_node (node, "Bundles")) == 0) {
1272 warning << _("Session: XML state has no bundles section") << endmsg;
1275 /* We can't load Bundles yet as they need to be able
1276 to convert from port names to Port objects, which can't happen until
1278 _bundle_xml_node = new XMLNode (*child);
1282 if (version < 3000) {
1283 if ((child = find_named_node (node, X_("DiskStreams"))) == 0) {
1284 error << _("Session: XML state has no diskstreams section") << endmsg;
1286 } else if (load_diskstreams_2X (*child, version)) {
1291 if ((child = find_named_node (node, "Routes")) == 0) {
1292 error << _("Session: XML state has no routes section") << endmsg;
1294 } else if (load_routes (*child, version)) {
1298 /* our diskstreams list is no longer needed as they are now all owned by their Route */
1299 _diskstreams_2X.clear ();
1301 if (version >= 3000) {
1303 if ((child = find_named_node (node, "RouteGroups")) == 0) {
1304 error << _("Session: XML state has no route groups section") << endmsg;
1306 } else if (load_route_groups (*child, version)) {
1310 } else if (version < 3000) {
1312 if ((child = find_named_node (node, "EditGroups")) == 0) {
1313 error << _("Session: XML state has no edit groups section") << endmsg;
1315 } else if (load_route_groups (*child, version)) {
1319 if ((child = find_named_node (node, "MixGroups")) == 0) {
1320 error << _("Session: XML state has no mix groups section") << endmsg;
1322 } else if (load_route_groups (*child, version)) {
1327 if ((child = find_named_node (node, "Click")) == 0) {
1328 warning << _("Session: XML state has no click section") << endmsg;
1329 } else if (_click_io) {
1330 setup_click_state (&node);
1333 if ((child = find_named_node (node, ControlProtocolManager::state_node_name)) != 0) {
1334 ControlProtocolManager::instance().set_state (*child, version);
1337 update_have_rec_enabled_track ();
1339 /* here beginneth the second phase ... */
1341 StateReady (); /* EMIT SIGNAL */
1350 Session::load_routes (const XMLNode& node, int version)
1353 XMLNodeConstIterator niter;
1354 RouteList new_routes;
1356 nlist = node.children();
1360 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1362 boost::shared_ptr<Route> route;
1363 if (version < 3000) {
1364 route = XMLRouteFactory_2X (**niter, version);
1366 route = XMLRouteFactory (**niter, version);
1370 error << _("Session: cannot create Route from XML description.") << endmsg;
1374 BootMessage (string_compose (_("Loaded track/bus %1"), route->name()));
1376 new_routes.push_back (route);
1379 add_routes (new_routes, false, false, false);
1384 boost::shared_ptr<Route>
1385 Session::XMLRouteFactory (const XMLNode& node, int version)
1387 boost::shared_ptr<Route> ret;
1389 if (node.name() != "Route") {
1393 XMLNode* ds_child = find_named_node (node, X_("Diskstream"));
1395 DataType type = DataType::AUDIO;
1396 const XMLProperty* prop = node.property("default-type");
1399 type = DataType (prop->value());
1402 assert (type != DataType::NIL);
1406 boost::shared_ptr<Track> track;
1408 if (type == DataType::AUDIO) {
1409 track.reset (new AudioTrack (*this, X_("toBeResetFroXML")));
1411 track.reset (new MidiTrack (*this, X_("toBeResetFroXML")));
1414 if (track->init()) {
1418 if (track->set_state (node, version)) {
1422 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
1423 // boost_debug_shared_ptr_mark_interesting (track.get(), "Track");
1428 boost::shared_ptr<Route> r (new Route (*this, X_("toBeResetFroXML")));
1430 if (r->init () == 0 && r->set_state (node, version) == 0) {
1431 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
1432 // boost_debug_shared_ptr_mark_interesting (r.get(), "Route");
1441 boost::shared_ptr<Route>
1442 Session::XMLRouteFactory_2X (const XMLNode& node, int version)
1444 boost::shared_ptr<Route> ret;
1446 if (node.name() != "Route") {
1450 XMLProperty const * ds_prop = node.property (X_("diskstream-id"));
1452 ds_prop = node.property (X_("diskstream"));
1455 DataType type = DataType::AUDIO;
1456 const XMLProperty* prop = node.property("default-type");
1459 type = DataType (prop->value());
1462 assert (type != DataType::NIL);
1466 list<boost::shared_ptr<Diskstream> >::iterator i = _diskstreams_2X.begin ();
1467 while (i != _diskstreams_2X.end() && (*i)->id() != ds_prop->value()) {
1471 if (i == _diskstreams_2X.end()) {
1472 error << _("Could not find diskstream for route") << endmsg;
1473 return boost::shared_ptr<Route> ();
1476 boost::shared_ptr<Track> track;
1478 if (type == DataType::AUDIO) {
1479 track.reset (new AudioTrack (*this, X_("toBeResetFroXML")));
1481 track.reset (new MidiTrack (*this, X_("toBeResetFroXML")));
1484 if (track->init()) {
1488 if (track->set_state (node, version)) {
1492 track->set_diskstream (*i);
1494 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
1495 // boost_debug_shared_ptr_mark_interesting (track.get(), "Track");
1500 boost::shared_ptr<Route> r (new Route (*this, X_("toBeResetFroXML")));
1502 if (r->init () == 0 && r->set_state (node, version) == 0) {
1503 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
1504 // boost_debug_shared_ptr_mark_interesting (r.get(), "Route");
1514 Session::load_regions (const XMLNode& node)
1517 XMLNodeConstIterator niter;
1518 boost::shared_ptr<Region> region;
1520 nlist = node.children();
1524 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1525 if ((region = XMLRegionFactory (**niter, false)) == 0) {
1526 error << _("Session: cannot create Region from XML description.");
1527 const XMLProperty *name = (**niter).property("name");
1530 error << " " << string_compose (_("Can not load state for region '%1'"), name->value());
1541 Session::load_compounds (const XMLNode& node)
1543 XMLNodeList calist = node.children();
1544 XMLNodeConstIterator caiter;
1545 XMLProperty *caprop;
1547 for (caiter = calist.begin(); caiter != calist.end(); ++caiter) {
1548 XMLNode* ca = *caiter;
1552 if ((caprop = ca->property (X_("original"))) == 0) {
1555 orig_id = caprop->value();
1557 if ((caprop = ca->property (X_("copy"))) == 0) {
1560 copy_id = caprop->value();
1562 boost::shared_ptr<Region> orig = RegionFactory::region_by_id (orig_id);
1563 boost::shared_ptr<Region> copy = RegionFactory::region_by_id (copy_id);
1565 if (!orig || !copy) {
1566 warning << string_compose (_("Regions in compound description not found (ID's %1 and %2): ignored"),
1572 RegionFactory::add_compound_association (orig, copy);
1579 Session::load_nested_sources (const XMLNode& node)
1582 XMLNodeConstIterator niter;
1584 nlist = node.children();
1586 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1587 if ((*niter)->name() == "Source") {
1589 /* it may already exist, so don't recreate it unnecessarily
1592 XMLProperty* prop = (*niter)->property (X_("id"));
1594 error << _("Nested source has no ID info in session file! (ignored)") << endmsg;
1598 ID source_id (prop->value());
1600 if (!source_by_id (source_id)) {
1603 SourceFactory::create (*this, **niter, true);
1605 catch (failed_constructor& err) {
1606 error << string_compose (_("Cannot reconstruct nested source for region %1"), name()) << endmsg;
1613 boost::shared_ptr<Region>
1614 Session::XMLRegionFactory (const XMLNode& node, bool full)
1616 const XMLProperty* type = node.property("type");
1620 const XMLNodeList& nlist = node.children();
1622 for (XMLNodeConstIterator niter = nlist.begin(); niter != nlist.end(); ++niter) {
1623 XMLNode *child = (*niter);
1624 if (child->name() == "NestedSource") {
1625 load_nested_sources (*child);
1629 if (!type || type->value() == "audio") {
1630 return boost::shared_ptr<Region>(XMLAudioRegionFactory (node, full));
1631 } else if (type->value() == "midi") {
1632 return boost::shared_ptr<Region>(XMLMidiRegionFactory (node, full));
1635 } catch (failed_constructor& err) {
1636 return boost::shared_ptr<Region> ();
1639 return boost::shared_ptr<Region> ();
1642 boost::shared_ptr<AudioRegion>
1643 Session::XMLAudioRegionFactory (const XMLNode& node, bool /*full*/)
1645 const XMLProperty* prop;
1646 boost::shared_ptr<Source> source;
1647 boost::shared_ptr<AudioSource> as;
1649 SourceList master_sources;
1650 uint32_t nchans = 1;
1653 if (node.name() != X_("Region")) {
1654 return boost::shared_ptr<AudioRegion>();
1657 if ((prop = node.property (X_("channels"))) != 0) {
1658 nchans = atoi (prop->value().c_str());
1661 if ((prop = node.property ("name")) == 0) {
1662 cerr << "no name for this region\n";
1666 if ((prop = node.property (X_("source-0"))) == 0) {
1667 if ((prop = node.property ("source")) == 0) {
1668 error << _("Session: XMLNode describing a AudioRegion is incomplete (no source)") << endmsg;
1669 return boost::shared_ptr<AudioRegion>();
1673 PBD::ID s_id (prop->value());
1675 if ((source = source_by_id (s_id)) == 0) {
1676 error << string_compose(_("Session: XMLNode describing a AudioRegion references an unknown source id =%1"), s_id) << endmsg;
1677 return boost::shared_ptr<AudioRegion>();
1680 as = boost::dynamic_pointer_cast<AudioSource>(source);
1682 error << string_compose(_("Session: XMLNode describing a AudioRegion references a non-audio source id =%1"), s_id) << endmsg;
1683 return boost::shared_ptr<AudioRegion>();
1686 sources.push_back (as);
1688 /* pickup other channels */
1690 for (uint32_t n=1; n < nchans; ++n) {
1691 snprintf (buf, sizeof(buf), X_("source-%d"), n);
1692 if ((prop = node.property (buf)) != 0) {
1694 PBD::ID id2 (prop->value());
1696 if ((source = source_by_id (id2)) == 0) {
1697 error << string_compose(_("Session: XMLNode describing a AudioRegion references an unknown source id =%1"), id2) << endmsg;
1698 return boost::shared_ptr<AudioRegion>();
1701 as = boost::dynamic_pointer_cast<AudioSource>(source);
1703 error << string_compose(_("Session: XMLNode describing a AudioRegion references a non-audio source id =%1"), id2) << endmsg;
1704 return boost::shared_ptr<AudioRegion>();
1706 sources.push_back (as);
1710 for (uint32_t n = 0; n < nchans; ++n) {
1711 snprintf (buf, sizeof(buf), X_("master-source-%d"), n);
1712 if ((prop = node.property (buf)) != 0) {
1714 PBD::ID id2 (prop->value());
1716 if ((source = source_by_id (id2)) == 0) {
1717 error << string_compose(_("Session: XMLNode describing a AudioRegion references an unknown source id =%1"), id2) << endmsg;
1718 return boost::shared_ptr<AudioRegion>();
1721 as = boost::dynamic_pointer_cast<AudioSource>(source);
1723 error << string_compose(_("Session: XMLNode describing a AudioRegion references a non-audio source id =%1"), id2) << endmsg;
1724 return boost::shared_ptr<AudioRegion>();
1726 master_sources.push_back (as);
1731 boost::shared_ptr<AudioRegion> region (boost::dynamic_pointer_cast<AudioRegion> (RegionFactory::create (sources, node)));
1733 /* a final detail: this is the one and only place that we know how long missing files are */
1735 if (region->whole_file()) {
1736 for (SourceList::iterator sx = sources.begin(); sx != sources.end(); ++sx) {
1737 boost::shared_ptr<SilentFileSource> sfp = boost::dynamic_pointer_cast<SilentFileSource> (*sx);
1739 sfp->set_length (region->length());
1744 if (!master_sources.empty()) {
1745 if (master_sources.size() != nchans) {
1746 error << _("Session: XMLNode describing an AudioRegion is missing some master sources; ignored") << endmsg;
1748 region->set_master_sources (master_sources);
1756 catch (failed_constructor& err) {
1757 return boost::shared_ptr<AudioRegion>();
1761 boost::shared_ptr<MidiRegion>
1762 Session::XMLMidiRegionFactory (const XMLNode& node, bool /*full*/)
1764 const XMLProperty* prop;
1765 boost::shared_ptr<Source> source;
1766 boost::shared_ptr<MidiSource> ms;
1769 if (node.name() != X_("Region")) {
1770 return boost::shared_ptr<MidiRegion>();
1773 if ((prop = node.property ("name")) == 0) {
1774 cerr << "no name for this region\n";
1778 if ((prop = node.property (X_("source-0"))) == 0) {
1779 if ((prop = node.property ("source")) == 0) {
1780 error << _("Session: XMLNode describing a MidiRegion is incomplete (no source)") << endmsg;
1781 return boost::shared_ptr<MidiRegion>();
1785 PBD::ID s_id (prop->value());
1787 if ((source = source_by_id (s_id)) == 0) {
1788 error << string_compose(_("Session: XMLNode describing a MidiRegion references an unknown source id =%1"), s_id) << endmsg;
1789 return boost::shared_ptr<MidiRegion>();
1792 ms = boost::dynamic_pointer_cast<MidiSource>(source);
1794 error << string_compose(_("Session: XMLNode describing a MidiRegion references a non-midi source id =%1"), s_id) << endmsg;
1795 return boost::shared_ptr<MidiRegion>();
1798 sources.push_back (ms);
1801 boost::shared_ptr<MidiRegion> region (boost::dynamic_pointer_cast<MidiRegion> (RegionFactory::create (sources, node)));
1802 /* a final detail: this is the one and only place that we know how long missing files are */
1804 if (region->whole_file()) {
1805 for (SourceList::iterator sx = sources.begin(); sx != sources.end(); ++sx) {
1806 boost::shared_ptr<SilentFileSource> sfp = boost::dynamic_pointer_cast<SilentFileSource> (*sx);
1808 sfp->set_length (region->length());
1816 catch (failed_constructor& err) {
1817 return boost::shared_ptr<MidiRegion>();
1822 Session::get_sources_as_xml ()
1825 XMLNode* node = new XMLNode (X_("Sources"));
1826 Glib::Threads::Mutex::Lock lm (source_lock);
1828 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ++i) {
1829 node->add_child_nocopy (i->second->get_state());
1836 Session::path_from_region_name (DataType type, string name, string identifier)
1838 char buf[PATH_MAX+1];
1840 SessionDirectory sdir(get_best_session_directory_for_new_source());
1841 std::string source_dir = ((type == DataType::AUDIO)
1842 ? sdir.sound_path() : sdir.midi_path());
1844 string ext = native_header_format_extension (config.get_native_file_header_format(), type);
1846 for (n = 0; n < 999999; ++n) {
1847 if (identifier.length()) {
1848 snprintf (buf, sizeof(buf), "%s%s%" PRIu32 "%s", name.c_str(),
1849 identifier.c_str(), n, ext.c_str());
1851 snprintf (buf, sizeof(buf), "%s-%" PRIu32 "%s", name.c_str(),
1855 std::string source_path = Glib::build_filename (source_dir, buf);
1857 if (!Glib::file_test (source_path, Glib::FILE_TEST_EXISTS)) {
1862 error << string_compose (_("cannot create new file from region name \"%1\" with ident = \"%2\": too many existing files with similar names"),
1871 Session::load_sources (const XMLNode& node)
1874 XMLNodeConstIterator niter;
1875 boost::shared_ptr<Source> source;
1877 nlist = node.children();
1881 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1884 if ((source = XMLSourceFactory (**niter)) == 0) {
1885 error << _("Session: cannot create Source from XML description.") << endmsg;
1888 } catch (MissingSource& err) {
1892 if (!no_questions_about_missing_files) {
1893 user_choice = MissingFile (this, err.path, err.type).get_value_or (-1);
1898 switch (user_choice) {
1900 /* user added a new search location, so try again */
1905 /* user asked to quit the entire session load
1910 no_questions_about_missing_files = true;
1914 no_questions_about_missing_files = true;
1919 warning << _("A sound file is missing. It will be replaced by silence.") << endmsg;
1920 source = SourceFactory::createSilent (*this, **niter, max_framecnt, _current_frame_rate);
1929 boost::shared_ptr<Source>
1930 Session::XMLSourceFactory (const XMLNode& node)
1932 if (node.name() != "Source") {
1933 return boost::shared_ptr<Source>();
1937 /* note: do peak building in another thread when loading session state */
1938 return SourceFactory::create (*this, node, true);
1941 catch (failed_constructor& err) {
1942 error << string_compose (_("Found a sound file that cannot be used by %1. Talk to the progammers."), PROGRAM_NAME) << endmsg;
1943 return boost::shared_ptr<Source>();
1948 Session::save_template (string template_name)
1952 if (_state_of_the_state & CannotSave) {
1956 std::string user_template_dir(user_template_directory());
1958 if (g_mkdir_with_parents (user_template_dir.c_str(), 0755) != 0) {
1959 error << string_compose(_("Could not create templates directory \"%1\" (%2)"),
1960 user_template_dir, g_strerror (errno)) << endmsg;
1964 tree.set_root (&get_template());
1966 std::string template_dir_path(user_template_dir);
1968 /* directory to put the template in */
1969 template_dir_path = Glib::build_filename (template_dir_path, template_name);
1971 if (Glib::file_test (template_dir_path, Glib::FILE_TEST_EXISTS)) {
1972 warning << string_compose(_("Template \"%1\" already exists - new version not created"),
1973 template_dir_path) << endmsg;
1977 if (g_mkdir_with_parents (template_dir_path.c_str(), 0755) != 0) {
1978 error << string_compose(_("Could not create directory for Session template\"%1\" (%2)"),
1979 template_dir_path, g_strerror (errno)) << endmsg;
1984 std::string template_file_path(template_dir_path);
1985 template_file_path = Glib::build_filename (template_file_path, template_name + template_suffix);
1987 if (!tree.write (template_file_path)) {
1988 error << _("template not saved") << endmsg;
1992 /* copy plugin state directory */
1994 std::string template_plugin_state_path(template_dir_path);
1995 template_plugin_state_path = Glib::build_filename (template_plugin_state_path, X_("plugins"));
1997 if (g_mkdir_with_parents (template_plugin_state_path.c_str(), 0755) != 0) {
1998 error << string_compose(_("Could not create directory for Session template plugin state\"%1\" (%2)"),
1999 template_plugin_state_path, g_strerror (errno)) << endmsg;
2003 copy_files (plugins_dir(), template_plugin_state_path);
2009 Session::refresh_disk_space ()
2011 #if __APPLE__ || (HAVE_SYS_VFS_H && HAVE_SYS_STATVFS_H)
2013 Glib::Threads::Mutex::Lock lm (space_lock);
2015 /* get freespace on every FS that is part of the session path */
2017 _total_free_4k_blocks = 0;
2018 _total_free_4k_blocks_uncertain = false;
2020 for (vector<space_and_path>::iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
2022 struct statfs statfsbuf;
2023 statfs (i->path.c_str(), &statfsbuf);
2025 double const scale = statfsbuf.f_bsize / 4096.0;
2027 /* See if this filesystem is read-only */
2028 struct statvfs statvfsbuf;
2029 statvfs (i->path.c_str(), &statvfsbuf);
2031 /* f_bavail can be 0 if it is undefined for whatever
2032 filesystem we are looking at; Samba shares mounted
2033 via GVFS are an example of this.
2035 if (statfsbuf.f_bavail == 0) {
2036 /* block count unknown */
2038 i->blocks_unknown = true;
2039 } else if (statvfsbuf.f_flag & ST_RDONLY) {
2040 /* read-only filesystem */
2042 i->blocks_unknown = false;
2044 /* read/write filesystem with known space */
2045 i->blocks = (uint32_t) floor (statfsbuf.f_bavail * scale);
2046 i->blocks_unknown = false;
2049 _total_free_4k_blocks += i->blocks;
2050 if (i->blocks_unknown) {
2051 _total_free_4k_blocks_uncertain = true;
2058 Session::get_best_session_directory_for_new_source ()
2060 vector<space_and_path>::iterator i;
2061 string result = _session_dir->root_path();
2063 /* handle common case without system calls */
2065 if (session_dirs.size() == 1) {
2069 /* OK, here's the algorithm we're following here:
2071 We want to select which directory to use for
2072 the next file source to be created. Ideally,
2073 we'd like to use a round-robin process so as to
2074 get maximum performance benefits from splitting
2075 the files across multiple disks.
2077 However, in situations without much diskspace, an
2078 RR approach may end up filling up a filesystem
2079 with new files while others still have space.
2080 Its therefore important to pay some attention to
2081 the freespace in the filesystem holding each
2082 directory as well. However, if we did that by
2083 itself, we'd keep creating new files in the file
2084 system with the most space until it was as full
2085 as all others, thus negating any performance
2086 benefits of this RAID-1 like approach.
2088 So, we use a user-configurable space threshold. If
2089 there are at least 2 filesystems with more than this
2090 much space available, we use RR selection between them.
2091 If not, then we pick the filesystem with the most space.
2093 This gets a good balance between the two
2097 refresh_disk_space ();
2099 int free_enough = 0;
2101 for (i = session_dirs.begin(); i != session_dirs.end(); ++i) {
2102 if ((*i).blocks * 4096 >= Config->get_disk_choice_space_threshold()) {
2107 if (free_enough >= 2) {
2108 /* use RR selection process, ensuring that the one
2112 i = last_rr_session_dir;
2115 if (++i == session_dirs.end()) {
2116 i = session_dirs.begin();
2119 if ((*i).blocks * 4096 >= Config->get_disk_choice_space_threshold()) {
2120 SessionDirectory sdir(i->path);
2121 if (sdir.create ()) {
2123 last_rr_session_dir = i;
2128 } while (i != last_rr_session_dir);
2132 /* pick FS with the most freespace (and that
2133 seems to actually work ...)
2136 vector<space_and_path> sorted;
2137 space_and_path_ascending_cmp cmp;
2139 sorted = session_dirs;
2140 sort (sorted.begin(), sorted.end(), cmp);
2142 for (i = sorted.begin(); i != sorted.end(); ++i) {
2143 SessionDirectory sdir(i->path);
2144 if (sdir.create ()) {
2146 last_rr_session_dir = i;
2156 Session::automation_dir () const
2158 return Glib::build_filename (_path, "automation");
2162 Session::analysis_dir () const
2164 return Glib::build_filename (_path, "analysis");
2168 Session::plugins_dir () const
2170 return Glib::build_filename (_path, "plugins");
2174 Session::externals_dir () const
2176 return Glib::build_filename (_path, "externals");
2180 Session::load_bundles (XMLNode const & node)
2182 XMLNodeList nlist = node.children();
2183 XMLNodeConstIterator niter;
2187 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2188 if ((*niter)->name() == "InputBundle") {
2189 add_bundle (boost::shared_ptr<UserBundle> (new UserBundle (**niter, true)));
2190 } else if ((*niter)->name() == "OutputBundle") {
2191 add_bundle (boost::shared_ptr<UserBundle> (new UserBundle (**niter, false)));
2193 error << string_compose(_("Unknown node \"%1\" found in Bundles list from session file"), (*niter)->name()) << endmsg;
2202 Session::load_route_groups (const XMLNode& node, int version)
2204 XMLNodeList nlist = node.children();
2205 XMLNodeConstIterator niter;
2209 if (version >= 3000) {
2211 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2212 if ((*niter)->name() == "RouteGroup") {
2213 RouteGroup* rg = new RouteGroup (*this, "");
2214 add_route_group (rg);
2215 rg->set_state (**niter, version);
2219 } else if (version < 3000) {
2221 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2222 if ((*niter)->name() == "EditGroup" || (*niter)->name() == "MixGroup") {
2223 RouteGroup* rg = new RouteGroup (*this, "");
2224 add_route_group (rg);
2225 rg->set_state (**niter, version);
2234 Session::auto_save()
2236 save_state (_current_snapshot_name);
2240 state_file_filter (const string &str, void */*arg*/)
2242 return (str.length() > strlen(statefile_suffix) &&
2243 str.find (statefile_suffix) == (str.length() - strlen (statefile_suffix)));
2247 bool operator()(const string* a, const string* b) {
2253 remove_end(string* state)
2255 string statename(*state);
2257 string::size_type start,end;
2258 if ((start = statename.find_last_of (G_DIR_SEPARATOR)) != string::npos) {
2259 statename = statename.substr (start+1);
2262 if ((end = statename.rfind(".ardour")) == string::npos) {
2263 end = statename.length();
2266 return new string(statename.substr (0, end));
2270 Session::possible_states (string path)
2272 PathScanner scanner;
2273 vector<string*>* states = scanner (path, state_file_filter, 0, false, false);
2275 transform(states->begin(), states->end(), states->begin(), remove_end);
2278 sort (states->begin(), states->end(), cmp);
2284 Session::possible_states () const
2286 return possible_states(_path);
2290 Session::add_route_group (RouteGroup* g)
2292 _route_groups.push_back (g);
2293 route_group_added (g); /* EMIT SIGNAL */
2295 g->RouteAdded.connect_same_thread (*this, boost::bind (&Session::route_added_to_route_group, this, _1, _2));
2296 g->RouteRemoved.connect_same_thread (*this, boost::bind (&Session::route_removed_from_route_group, this, _1, _2));
2297 g->PropertyChanged.connect_same_thread (*this, boost::bind (&Session::route_group_property_changed, this, g));
2303 Session::remove_route_group (RouteGroup& rg)
2305 list<RouteGroup*>::iterator i;
2307 if ((i = find (_route_groups.begin(), _route_groups.end(), &rg)) != _route_groups.end()) {
2308 _route_groups.erase (i);
2311 route_group_removed (); /* EMIT SIGNAL */
2315 /** Set a new order for our route groups, without adding or removing any.
2316 * @param groups Route group list in the new order.
2319 Session::reorder_route_groups (list<RouteGroup*> groups)
2321 _route_groups = groups;
2323 route_groups_reordered (); /* EMIT SIGNAL */
2329 Session::route_group_by_name (string name)
2331 list<RouteGroup *>::iterator i;
2333 for (i = _route_groups.begin(); i != _route_groups.end(); ++i) {
2334 if ((*i)->name() == name) {
2342 Session::all_route_group() const
2344 return *_all_route_group;
2348 Session::add_commands (vector<Command*> const & cmds)
2350 for (vector<Command*>::const_iterator i = cmds.begin(); i != cmds.end(); ++i) {
2356 Session::begin_reversible_command (const string& name)
2358 begin_reversible_command (g_quark_from_string (name.c_str ()));
2361 /** Begin a reversible command using a GQuark to identify it.
2362 * begin_reversible_command() and commit_reversible_command() calls may be nested,
2363 * but there must be as many begin...()s as there are commit...()s.
2366 Session::begin_reversible_command (GQuark q)
2368 /* If nested begin/commit pairs are used, we create just one UndoTransaction
2369 to hold all the commands that are committed. This keeps the order of
2370 commands correct in the history.
2373 if (_current_trans == 0) {
2374 /* start a new transaction */
2375 assert (_current_trans_quarks.empty ());
2376 _current_trans = new UndoTransaction();
2377 _current_trans->set_name (g_quark_to_string (q));
2380 _current_trans_quarks.push_front (q);
2384 Session::commit_reversible_command (Command *cmd)
2386 assert (_current_trans);
2387 assert (!_current_trans_quarks.empty ());
2392 _current_trans->add_command (cmd);
2395 _current_trans_quarks.pop_front ();
2397 if (!_current_trans_quarks.empty ()) {
2398 /* the transaction we're committing is not the top-level one */
2402 if (_current_trans->empty()) {
2403 /* no commands were added to the transaction, so just get rid of it */
2404 delete _current_trans;
2409 gettimeofday (&now, 0);
2410 _current_trans->set_timestamp (now);
2412 _history.add (_current_trans);
2417 accept_all_audio_files (const string& path, void */*arg*/)
2419 if (!Glib::file_test (path, Glib::FILE_TEST_IS_REGULAR)) {
2423 if (!AudioFileSource::safe_audio_file_extension (path)) {
2431 accept_all_midi_files (const string& path, void */*arg*/)
2433 if (!Glib::file_test (path, Glib::FILE_TEST_IS_REGULAR)) {
2437 return ((path.length() > 4 && path.find (".mid") != (path.length() - 4)) ||
2438 (path.length() > 4 && path.find (".smf") != (path.length() - 4)) ||
2439 (path.length() > 5 && path.find (".midi") != (path.length() - 5)));
2443 accept_all_state_files (const string& path, void */*arg*/)
2445 if (!Glib::file_test (path, Glib::FILE_TEST_IS_REGULAR)) {
2449 return (path.length() > 7 && path.find (".ardour") == (path.length() - 7));
2453 Session::find_all_sources (string path, set<string>& result)
2458 if (!tree.read (path)) {
2462 if ((node = find_named_node (*tree.root(), "Sources")) == 0) {
2467 XMLNodeConstIterator niter;
2469 nlist = node->children();
2473 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2477 if ((prop = (*niter)->property (X_("type"))) == 0) {
2481 DataType type (prop->value());
2483 if ((prop = (*niter)->property (X_("name"))) == 0) {
2487 if (Glib::path_is_absolute (prop->value())) {
2488 /* external file, ignore */
2496 if (FileSource::find (*this, type, prop->value(), true, is_new, chan, found_path)) {
2497 result.insert (found_path);
2505 Session::find_all_sources_across_snapshots (set<string>& result, bool exclude_this_snapshot)
2507 PathScanner scanner;
2508 vector<string*>* state_files;
2510 string this_snapshot_path;
2516 if (ripped[ripped.length()-1] == G_DIR_SEPARATOR) {
2517 ripped = ripped.substr (0, ripped.length() - 1);
2520 state_files = scanner (ripped, accept_all_state_files, (void *) 0, true, true);
2522 if (state_files == 0) {
2527 this_snapshot_path = _path;
2528 this_snapshot_path += legalize_for_path (_current_snapshot_name);
2529 this_snapshot_path += statefile_suffix;
2531 for (vector<string*>::iterator i = state_files->begin(); i != state_files->end(); ++i) {
2533 if (exclude_this_snapshot && **i == this_snapshot_path) {
2537 if (find_all_sources (**i, result) < 0) {
2545 struct RegionCounter {
2546 typedef std::map<PBD::ID,boost::shared_ptr<AudioSource> > AudioSourceList;
2547 AudioSourceList::iterator iter;
2548 boost::shared_ptr<Region> region;
2551 RegionCounter() : count (0) {}
2555 Session::ask_about_playlist_deletion (boost::shared_ptr<Playlist> p)
2557 boost::optional<int> r = AskAboutPlaylistDeletion (p);
2558 return r.get_value_or (1);
2562 Session::cleanup_regions ()
2564 const RegionFactory::RegionMap& regions (RegionFactory::regions());
2566 for (RegionFactory::RegionMap::const_iterator i = regions.begin(); i != regions.end(); ++i) {
2568 uint32_t used = playlists->region_use_count (i->second);
2570 if (used == 0 && !i->second->automatic ()) {
2571 RegionFactory::map_remove (i->second);
2575 /* dump the history list */
2582 Session::cleanup_sources (CleanupReport& rep)
2584 // FIXME: needs adaptation to midi
2586 vector<boost::shared_ptr<Source> > dead_sources;
2587 PathScanner scanner;
2590 vector<space_and_path>::iterator i;
2591 vector<space_and_path>::iterator nexti;
2592 vector<string*>* candidates;
2593 vector<string*>* candidates2;
2594 vector<string> unused;
2595 set<string> all_sources;
2600 _state_of_the_state = (StateOfTheState) (_state_of_the_state | InCleanup);
2602 /* consider deleting all unused playlists */
2604 if (playlists->maybe_delete_unused (boost::bind (Session::ask_about_playlist_deletion, _1))) {
2609 /* sync the "all regions" property of each playlist with its current state
2612 playlists->sync_all_regions_with_regions ();
2614 /* find all un-used sources */
2619 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ) {
2621 SourceMap::iterator tmp;
2626 /* do not bother with files that are zero size, otherwise we remove the current "nascent"
2630 if (!i->second->used() && (i->second->length(i->second->timeline_position() > 0))) {
2631 dead_sources.push_back (i->second);
2632 i->second->drop_references ();
2638 /* build a list of all the possible audio directories for the session */
2640 for (i = session_dirs.begin(); i != session_dirs.end(); ) {
2645 SessionDirectory sdir ((*i).path);
2646 audio_path += sdir.sound_path();
2648 if (nexti != session_dirs.end()) {
2656 /* build a list of all the possible midi directories for the session */
2658 for (i = session_dirs.begin(); i != session_dirs.end(); ) {
2663 SessionDirectory sdir ((*i).path);
2664 midi_path += sdir.midi_path();
2666 if (nexti != session_dirs.end()) {
2673 candidates = scanner (audio_path, accept_all_audio_files, (void *) 0, true, true);
2674 candidates2 = scanner (midi_path, accept_all_midi_files, (void *) 0, true, true);
2680 for (vector<string*>::iterator i = candidates2->begin(); i != candidates2->end(); ++i) {
2681 candidates->push_back (*i);
2686 candidates = candidates2; // might still be null
2689 /* find all sources, but don't use this snapshot because the
2690 state file on disk still references sources we may have already
2694 find_all_sources_across_snapshots (all_sources, true);
2696 /* add our current source list
2699 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ) {
2700 boost::shared_ptr<FileSource> fs;
2701 SourceMap::iterator tmp = i;
2704 if ((fs = boost::dynamic_pointer_cast<FileSource> (i->second)) != 0) {
2705 if (playlists->source_use_count (fs) != 0) {
2706 all_sources.insert (fs->path());
2709 /* we might not remove this source from disk, because it may be used
2710 by other snapshots, but its not being used in this version
2711 so lets get rid of it now, along with any representative regions
2715 RegionFactory::remove_regions_using_source (i->second);
2723 char tmppath1[PATH_MAX+1];
2724 char tmppath2[PATH_MAX+1];
2727 for (vector<string*>::iterator x = candidates->begin(); x != candidates->end(); ++x) {
2732 for (set<string>::iterator i = all_sources.begin(); i != all_sources.end(); ++i) {
2734 if (realpath(spath.c_str(), tmppath1) == 0) {
2735 error << string_compose (_("Cannot expand path %1 (%2)"),
2736 spath, strerror (errno)) << endmsg;
2740 if (realpath((*i).c_str(), tmppath2) == 0) {
2741 error << string_compose (_("Cannot expand path %1 (%2)"),
2742 (*i), strerror (errno)) << endmsg;
2746 if (strcmp(tmppath1, tmppath2) == 0) {
2753 unused.push_back (spath);
2762 /* now try to move all unused files into the "dead" directory(ies) */
2764 for (vector<string>::iterator x = unused.begin(); x != unused.end(); ++x) {
2765 struct stat statbuf;
2769 /* don't move the file across filesystems, just
2770 stick it in the `dead_dir_name' directory
2771 on whichever filesystem it was already on.
2774 if ((*x).find ("/sounds/") != string::npos) {
2776 /* old school, go up 1 level */
2778 newpath = Glib::path_get_dirname (*x); // "sounds"
2779 newpath = Glib::path_get_dirname (newpath); // "session-name"
2783 /* new school, go up 4 levels */
2785 newpath = Glib::path_get_dirname (*x); // "audiofiles" or "midifiles"
2786 newpath = Glib::path_get_dirname (newpath); // "session-name"
2787 newpath = Glib::path_get_dirname (newpath); // "interchange"
2788 newpath = Glib::path_get_dirname (newpath); // "session-dir"
2791 newpath = Glib::build_filename (newpath, dead_dir_name);
2793 if (g_mkdir_with_parents (newpath.c_str(), 0755) < 0) {
2794 error << string_compose(_("Session: cannot create dead file folder \"%1\" (%2)"), newpath, strerror (errno)) << endmsg;
2798 newpath = Glib::build_filename (newpath, Glib::path_get_basename ((*x)));
2800 if (Glib::file_test (newpath, Glib::FILE_TEST_EXISTS)) {
2802 /* the new path already exists, try versioning */
2804 char buf[PATH_MAX+1];
2808 snprintf (buf, sizeof (buf), "%s.%d", newpath.c_str(), version);
2811 while (Glib::file_test (newpath_v.c_str(), Glib::FILE_TEST_EXISTS) && version < 999) {
2812 snprintf (buf, sizeof (buf), "%s.%d", newpath.c_str(), ++version);
2816 if (version == 999) {
2817 error << string_compose (_("there are already 1000 files with names like %1; versioning discontinued"),
2821 newpath = newpath_v;
2826 /* it doesn't exist, or we can't read it or something */
2830 stat ((*x).c_str(), &statbuf);
2832 if (::rename ((*x).c_str(), newpath.c_str()) != 0) {
2833 error << string_compose (_("cannot rename unused file source from %1 to %2 (%3)"),
2834 (*x), newpath, strerror (errno))
2839 /* see if there an easy to find peakfile for this file, and remove it.
2842 string base = basename_nosuffix (*x);
2843 base += "%A"; /* this is what we add for the channel suffix of all native files,
2844 or for the first channel of embedded files. it will miss
2845 some peakfiles for other channels
2847 string peakpath = peak_path (base);
2849 if (Glib::file_test (peakpath.c_str(), Glib::FILE_TEST_EXISTS)) {
2850 if (::unlink (peakpath.c_str()) != 0) {
2851 error << string_compose (_("cannot remove peakfile %1 for %2 (%3)"),
2852 peakpath, _path, strerror (errno))
2854 /* try to back out */
2855 ::rename (newpath.c_str(), _path.c_str());
2860 rep.paths.push_back (*x);
2861 rep.space += statbuf.st_size;
2864 /* dump the history list */
2868 /* save state so we don't end up a session file
2869 referring to non-existent sources.
2876 _state_of_the_state = (StateOfTheState) (_state_of_the_state & ~InCleanup);
2882 Session::cleanup_trash_sources (CleanupReport& rep)
2884 // FIXME: needs adaptation for MIDI
2886 vector<space_and_path>::iterator i;
2892 for (i = session_dirs.begin(); i != session_dirs.end(); ++i) {
2894 dead_dir = Glib::build_filename ((*i).path, dead_dir_name);
2896 clear_directory (dead_dir, &rep.space, &rep.paths);
2903 Session::set_dirty ()
2905 bool was_dirty = dirty();
2907 _state_of_the_state = StateOfTheState (_state_of_the_state | Dirty);
2911 DirtyChanged(); /* EMIT SIGNAL */
2917 Session::set_clean ()
2919 bool was_dirty = dirty();
2921 _state_of_the_state = Clean;
2925 DirtyChanged(); /* EMIT SIGNAL */
2930 Session::set_deletion_in_progress ()
2932 _state_of_the_state = StateOfTheState (_state_of_the_state | Deletion);
2936 Session::clear_deletion_in_progress ()
2938 _state_of_the_state = StateOfTheState (_state_of_the_state & (~Deletion));
2942 Session::add_controllable (boost::shared_ptr<Controllable> c)
2944 /* this adds a controllable to the list managed by the Session.
2945 this is a subset of those managed by the Controllable class
2946 itself, and represents the only ones whose state will be saved
2947 as part of the session.
2950 Glib::Threads::Mutex::Lock lm (controllables_lock);
2951 controllables.insert (c);
2954 struct null_deleter { void operator()(void const *) const {} };
2957 Session::remove_controllable (Controllable* c)
2959 if (_state_of_the_state & Deletion) {
2963 Glib::Threads::Mutex::Lock lm (controllables_lock);
2965 Controllables::iterator x = controllables.find (boost::shared_ptr<Controllable>(c, null_deleter()));
2967 if (x != controllables.end()) {
2968 controllables.erase (x);
2972 boost::shared_ptr<Controllable>
2973 Session::controllable_by_id (const PBD::ID& id)
2975 Glib::Threads::Mutex::Lock lm (controllables_lock);
2977 for (Controllables::iterator i = controllables.begin(); i != controllables.end(); ++i) {
2978 if ((*i)->id() == id) {
2983 return boost::shared_ptr<Controllable>();
2986 boost::shared_ptr<Controllable>
2987 Session::controllable_by_descriptor (const ControllableDescriptor& desc)
2989 boost::shared_ptr<Controllable> c;
2990 boost::shared_ptr<Route> r;
2992 switch (desc.top_level_type()) {
2993 case ControllableDescriptor::NamedRoute:
2995 std::string str = desc.top_level_name();
2996 if (str == "master") {
2998 } else if (str == "control" || str == "listen") {
3001 r = route_by_name (desc.top_level_name());
3006 case ControllableDescriptor::RemoteControlID:
3007 r = route_by_remote_id (desc.rid());
3015 switch (desc.subtype()) {
3016 case ControllableDescriptor::Gain:
3017 c = r->gain_control ();
3020 case ControllableDescriptor::Solo:
3021 c = r->solo_control();
3024 case ControllableDescriptor::Mute:
3025 c = r->mute_control();
3028 case ControllableDescriptor::Recenable:
3030 boost::shared_ptr<Track> t = boost::dynamic_pointer_cast<Track>(r);
3033 c = t->rec_enable_control ();
3038 case ControllableDescriptor::PanDirection:
3040 c = r->pannable()->pan_azimuth_control;
3044 case ControllableDescriptor::PanWidth:
3046 c = r->pannable()->pan_width_control;
3050 case ControllableDescriptor::PanElevation:
3052 c = r->pannable()->pan_elevation_control;
3056 case ControllableDescriptor::Balance:
3057 /* XXX simple pan control */
3060 case ControllableDescriptor::PluginParameter:
3062 uint32_t plugin = desc.target (0);
3063 uint32_t parameter_index = desc.target (1);
3065 /* revert to zero based counting */
3071 if (parameter_index > 0) {
3075 boost::shared_ptr<Processor> p = r->nth_plugin (plugin);
3078 c = boost::dynamic_pointer_cast<ARDOUR::AutomationControl>(
3079 p->control(Evoral::Parameter(PluginAutomation, 0, parameter_index)));
3084 case ControllableDescriptor::SendGain:
3086 uint32_t send = desc.target (0);
3088 /* revert to zero-based counting */
3094 boost::shared_ptr<Processor> p = r->nth_send (send);
3097 boost::shared_ptr<Send> s = boost::dynamic_pointer_cast<Send>(p);
3098 boost::shared_ptr<Amp> a = s->amp();
3101 c = s->amp()->gain_control();
3108 /* relax and return a null pointer */
3116 Session::add_instant_xml (XMLNode& node, bool write_to_config)
3119 Stateful::add_instant_xml (node, _path);
3122 if (write_to_config) {
3123 Config->add_instant_xml (node);
3128 Session::instant_xml (const string& node_name)
3130 return Stateful::instant_xml (node_name, _path);
3134 Session::save_history (string snapshot_name)
3142 if (snapshot_name.empty()) {
3143 snapshot_name = _current_snapshot_name;
3146 const string history_filename = legalize_for_path (snapshot_name) + history_suffix;
3147 const string backup_filename = history_filename + backup_suffix;
3148 const std::string xml_path(Glib::build_filename (_session_dir->root_path(), history_filename));
3149 const std::string backup_path(Glib::build_filename (_session_dir->root_path(), backup_filename));
3151 if (Glib::file_test (xml_path, Glib::FILE_TEST_EXISTS)) {
3152 if (::g_rename (xml_path.c_str(), backup_path.c_str()) != 0) {
3153 error << _("could not backup old history file, current history not saved") << endmsg;
3158 if (!Config->get_save_history() || Config->get_saved_history_depth() < 0) {
3162 tree.set_root (&_history.get_state (Config->get_saved_history_depth()));
3164 if (!tree.write (xml_path))
3166 error << string_compose (_("history could not be saved to %1"), xml_path) << endmsg;
3168 if (g_remove (xml_path.c_str()) != 0) {
3169 error << string_compose(_("Could not remove history file at path \"%1\" (%2)"),
3170 xml_path, g_strerror (errno)) << endmsg;
3172 if (::g_rename (backup_path.c_str(), xml_path.c_str()) != 0) {
3173 error << string_compose (_("could not restore history file from backup %1 (%2)"),
3174 backup_path, g_strerror (errno)) << endmsg;
3184 Session::restore_history (string snapshot_name)
3188 if (snapshot_name.empty()) {
3189 snapshot_name = _current_snapshot_name;
3192 const std::string xml_filename = legalize_for_path (snapshot_name) + history_suffix;
3193 const std::string xml_path(Glib::build_filename (_session_dir->root_path(), xml_filename));
3195 info << "Loading history from " << xml_path << endmsg;
3197 if (!Glib::file_test (xml_path, Glib::FILE_TEST_EXISTS)) {
3198 info << string_compose (_("%1: no history file \"%2\" for this session."),
3199 _name, xml_path) << endmsg;
3203 if (!tree.read (xml_path)) {
3204 error << string_compose (_("Could not understand session history file \"%1\""),
3205 xml_path) << endmsg;
3212 for (XMLNodeConstIterator it = tree.root()->children().begin(); it != tree.root()->children().end(); it++) {
3215 UndoTransaction* ut = new UndoTransaction ();
3218 ut->set_name(t->property("name")->value());
3219 stringstream ss(t->property("tv-sec")->value());
3221 ss.str(t->property("tv-usec")->value());
3223 ut->set_timestamp(tv);
3225 for (XMLNodeConstIterator child_it = t->children().begin();
3226 child_it != t->children().end(); child_it++)
3228 XMLNode *n = *child_it;
3231 if (n->name() == "MementoCommand" ||
3232 n->name() == "MementoUndoCommand" ||
3233 n->name() == "MementoRedoCommand") {
3235 if ((c = memento_command_factory(n))) {
3239 } else if (n->name() == "NoteDiffCommand") {
3240 PBD::ID id (n->property("midi-source")->value());
3241 boost::shared_ptr<MidiSource> midi_source =
3242 boost::dynamic_pointer_cast<MidiSource, Source>(source_by_id(id));
3244 ut->add_command (new MidiModel::NoteDiffCommand(midi_source->model(), *n));
3246 error << _("Failed to downcast MidiSource for NoteDiffCommand") << endmsg;
3249 } else if (n->name() == "SysExDiffCommand") {
3251 PBD::ID id (n->property("midi-source")->value());
3252 boost::shared_ptr<MidiSource> midi_source =
3253 boost::dynamic_pointer_cast<MidiSource, Source>(source_by_id(id));
3255 ut->add_command (new MidiModel::SysExDiffCommand (midi_source->model(), *n));
3257 error << _("Failed to downcast MidiSource for SysExDiffCommand") << endmsg;
3260 } else if (n->name() == "PatchChangeDiffCommand") {
3262 PBD::ID id (n->property("midi-source")->value());
3263 boost::shared_ptr<MidiSource> midi_source =
3264 boost::dynamic_pointer_cast<MidiSource, Source>(source_by_id(id));
3266 ut->add_command (new MidiModel::PatchChangeDiffCommand (midi_source->model(), *n));
3268 error << _("Failed to downcast MidiSource for PatchChangeDiffCommand") << endmsg;
3271 } else if (n->name() == "StatefulDiffCommand") {
3272 if ((c = stateful_diff_command_factory (n))) {
3273 ut->add_command (c);
3276 error << string_compose(_("Couldn't figure out how to make a Command out of a %1 XMLNode."), n->name()) << endmsg;
3287 Session::config_changed (std::string p, bool ours)
3293 if (p == "seamless-loop") {
3295 } else if (p == "rf-speed") {
3297 } else if (p == "auto-loop") {
3299 } else if (p == "auto-input") {
3301 if (Config->get_monitoring_model() == HardwareMonitoring && transport_rolling()) {
3302 /* auto-input only makes a difference if we're rolling */
3303 set_track_monitor_input_status (!config.get_auto_input());
3306 } else if (p == "punch-in") {
3310 if ((location = _locations->auto_punch_location()) != 0) {
3312 if (config.get_punch_in ()) {
3313 replace_event (SessionEvent::PunchIn, location->start());
3315 remove_event (location->start(), SessionEvent::PunchIn);
3319 } else if (p == "punch-out") {
3323 if ((location = _locations->auto_punch_location()) != 0) {
3325 if (config.get_punch_out()) {
3326 replace_event (SessionEvent::PunchOut, location->end());
3328 clear_events (SessionEvent::PunchOut);
3332 } else if (p == "edit-mode") {
3334 Glib::Threads::Mutex::Lock lm (playlists->lock);
3336 for (SessionPlaylists::List::iterator i = playlists->playlists.begin(); i != playlists->playlists.end(); ++i) {
3337 (*i)->set_edit_mode (Config->get_edit_mode ());
3340 } else if (p == "use-video-sync") {
3342 waiting_for_sync_offset = config.get_use_video_sync();
3344 } else if (p == "mmc-control") {
3346 //poke_midi_thread ();
3348 } else if (p == "mmc-device-id" || p == "mmc-receive-id" || p == "mmc-receive-device-id") {
3350 _mmc->set_receive_device_id (Config->get_mmc_receive_device_id());
3352 } else if (p == "mmc-send-id" || p == "mmc-send-device-id") {
3354 _mmc->set_send_device_id (Config->get_mmc_send_device_id());
3356 } else if (p == "midi-control") {
3358 //poke_midi_thread ();
3360 } else if (p == "raid-path") {
3362 setup_raid_path (config.get_raid_path());
3364 } else if (p == "timecode-format") {
3368 } else if (p == "video-pullup") {
3372 } else if (p == "seamless-loop") {
3374 if (play_loop && transport_rolling()) {
3375 // to reset diskstreams etc
3376 request_play_loop (true);
3379 } else if (p == "rf-speed") {
3381 cumulative_rf_motion = 0;
3384 } else if (p == "click-sound") {
3386 setup_click_sounds (1);
3388 } else if (p == "click-emphasis-sound") {
3390 setup_click_sounds (-1);
3392 } else if (p == "clicking") {
3394 if (Config->get_clicking()) {
3395 if (_click_io && click_data) { // don't require emphasis data
3402 } else if (p == "click-gain") {
3405 _click_gain->set_gain (Config->get_click_gain(), this);
3408 } else if (p == "send-mtc") {
3410 if (Config->get_send_mtc ()) {
3411 /* mark us ready to send */
3412 next_quarter_frame_to_send = 0;
3415 } else if (p == "send-mmc") {
3417 _mmc->enable_send (Config->get_send_mmc ());
3419 } else if (p == "midi-feedback") {
3421 session_midi_feedback = Config->get_midi_feedback();
3423 } else if (p == "jack-time-master") {
3425 engine().reset_timebase ();
3427 } else if (p == "native-file-header-format") {
3429 if (!first_file_header_format_reset) {
3430 reset_native_file_format ();
3433 first_file_header_format_reset = false;
3435 } else if (p == "native-file-data-format") {
3437 if (!first_file_data_format_reset) {
3438 reset_native_file_format ();
3441 first_file_data_format_reset = false;
3443 } else if (p == "external-sync") {
3444 if (!config.get_external_sync()) {
3445 drop_sync_source ();
3447 switch_to_sync_source (Config->get_sync_source());
3449 } else if (p == "denormal-model") {
3451 } else if (p == "history-depth") {
3452 set_history_depth (Config->get_history_depth());
3453 } else if (p == "remote-model") {
3454 /* XXX DO SOMETHING HERE TO TELL THE GUI THAT WE NEED
3457 } else if (p == "initial-program-change") {
3459 if (_mmc->output_port() && Config->get_initial_program_change() >= 0) {
3462 buf[0] = MIDI::program; // channel zero by default
3463 buf[1] = (Config->get_initial_program_change() & 0x7f);
3465 _mmc->output_port()->midimsg (buf, sizeof (buf), 0);
3467 } else if (p == "solo-mute-override") {
3468 // catch_up_on_solo_mute_override ();
3469 } else if (p == "listen-position" || p == "pfl-position") {
3470 listen_position_changed ();
3471 } else if (p == "solo-control-is-listen-control") {
3472 solo_control_mode_changed ();
3473 } else if (p == "timecode-offset" || p == "timecode-offset-negative") {
3474 last_timecode_valid = false;
3475 } else if (p == "playback-buffer-seconds") {
3476 AudioSource::allocate_working_buffers (frame_rate());
3477 } else if (p == "automation-thinning-factor") {
3478 Evoral::ControlList::set_thinning_factor (Config->get_automation_thinning_factor());
3479 } else if (p == "ltc-source-port") {
3480 reconnect_ltc_input ();
3481 } else if (p == "ltc-sink-port") {
3482 reconnect_ltc_output ();
3483 } else if (p == "timecode-generator-offset") {
3484 ltc_tx_parse_offset();
3491 Session::set_history_depth (uint32_t d)
3493 _history.set_depth (d);
3497 Session::load_diskstreams_2X (XMLNode const & node, int)
3500 XMLNodeConstIterator citer;
3502 clist = node.children();
3504 for (citer = clist.begin(); citer != clist.end(); ++citer) {
3507 /* diskstreams added automatically by DiskstreamCreated handler */
3508 if ((*citer)->name() == "AudioDiskstream" || (*citer)->name() == "DiskStream") {
3509 boost::shared_ptr<AudioDiskstream> dsp (new AudioDiskstream (*this, **citer));
3510 _diskstreams_2X.push_back (dsp);
3512 error << _("Session: unknown diskstream type in XML") << endmsg;
3516 catch (failed_constructor& err) {
3517 error << _("Session: could not load diskstream via XML state") << endmsg;
3525 /** Connect things to the MMC object */
3527 Session::setup_midi_machine_control ()
3529 _mmc = new MIDI::MachineControl;
3530 _mmc->set_ports (_midi_ports->mmc_input_port(), _midi_ports->mmc_output_port());
3532 _mmc->Play.connect_same_thread (*this, boost::bind (&Session::mmc_deferred_play, this, _1));
3533 _mmc->DeferredPlay.connect_same_thread (*this, boost::bind (&Session::mmc_deferred_play, this, _1));
3534 _mmc->Stop.connect_same_thread (*this, boost::bind (&Session::mmc_stop, this, _1));
3535 _mmc->FastForward.connect_same_thread (*this, boost::bind (&Session::mmc_fast_forward, this, _1));
3536 _mmc->Rewind.connect_same_thread (*this, boost::bind (&Session::mmc_rewind, this, _1));
3537 _mmc->Pause.connect_same_thread (*this, boost::bind (&Session::mmc_pause, this, _1));
3538 _mmc->RecordPause.connect_same_thread (*this, boost::bind (&Session::mmc_record_pause, this, _1));
3539 _mmc->RecordStrobe.connect_same_thread (*this, boost::bind (&Session::mmc_record_strobe, this, _1));
3540 _mmc->RecordExit.connect_same_thread (*this, boost::bind (&Session::mmc_record_exit, this, _1));
3541 _mmc->Locate.connect_same_thread (*this, boost::bind (&Session::mmc_locate, this, _1, _2));
3542 _mmc->Step.connect_same_thread (*this, boost::bind (&Session::mmc_step, this, _1, _2));
3543 _mmc->Shuttle.connect_same_thread (*this, boost::bind (&Session::mmc_shuttle, this, _1, _2, _3));
3544 _mmc->TrackRecordStatusChange.connect_same_thread (*this, boost::bind (&Session::mmc_record_enable, this, _1, _2, _3));
3546 /* also handle MIDI SPP because its so common */
3548 _mmc->SPPStart.connect_same_thread (*this, boost::bind (&Session::spp_start, this));
3549 _mmc->SPPContinue.connect_same_thread (*this, boost::bind (&Session::spp_continue, this));
3550 _mmc->SPPStop.connect_same_thread (*this, boost::bind (&Session::spp_stop, this));
3553 boost::shared_ptr<Controllable>
3554 Session::solo_cut_control() const
3556 /* the solo cut control is a bit of an anomaly, at least as of Febrary 2011. There are no other
3557 controls in Ardour that currently get presented to the user in the GUI that require
3558 access as a Controllable and are also NOT owned by some SessionObject (e.g. Route, or MonitorProcessor).
3560 its actually an RCConfiguration parameter, so we use a ProxyControllable to wrap
3561 it up as a Controllable. Changes to the Controllable will just map back to the RCConfiguration
3565 return _solo_cut_control;
3569 Session::rename (const std::string& new_name)
3571 string legal_name = legalize_for_path (new_name);
3577 string const old_sources_root = _session_dir->sources_root();
3579 #define RENAME ::rename
3584 * interchange subdirectory
3588 * Backup files are left unchanged and not renamed.
3591 /* pass one: not 100% safe check that the new directory names don't
3595 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
3600 /* this is a stupid hack because Glib::path_get_dirname() is
3601 * lexical-only, and so passing it /a/b/c/ gives a different
3602 * result than passing it /a/b/c ...
3605 if (oldstr[oldstr.length()-1] == G_DIR_SEPARATOR) {
3606 oldstr = oldstr.substr (0, oldstr.length() - 1);
3609 string base = Glib::path_get_dirname (oldstr);
3610 string p = Glib::path_get_basename (oldstr);
3612 newstr = Glib::build_filename (base, legal_name);
3614 if (Glib::file_test (newstr, Glib::FILE_TEST_EXISTS)) {
3621 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
3626 /* this is a stupid hack because Glib::path_get_dirname() is
3627 * lexical-only, and so passing it /a/b/c/ gives a different
3628 * result than passing it /a/b/c ...
3631 if (oldstr[oldstr.length()-1] == G_DIR_SEPARATOR) {
3632 oldstr = oldstr.substr (0, oldstr.length() - 1);
3635 string base = Glib::path_get_dirname (oldstr);
3636 string p = Glib::path_get_basename (oldstr);
3638 newstr = Glib::build_filename (base, legal_name);
3640 cerr << "Rename " << oldstr << " => " << newstr << endl;
3642 if (RENAME (oldstr.c_str(), newstr.c_str()) != 0) {
3647 (*_session_dir) = newstr;
3652 /* directory below interchange */
3654 v.push_back (newstr);
3655 v.push_back (interchange_dir_name);
3658 oldstr = Glib::build_filename (v);
3661 v.push_back (newstr);
3662 v.push_back (interchange_dir_name);
3663 v.push_back (legal_name);
3665 newstr = Glib::build_filename (v);
3667 cerr << "Rename " << oldstr << " => " << newstr << endl;
3669 if (RENAME (oldstr.c_str(), newstr.c_str()) != 0) {
3676 oldstr = Glib::build_filename (newpath, _current_snapshot_name) + statefile_suffix;
3677 newstr= Glib::build_filename (newpath, legal_name) + statefile_suffix;
3679 cerr << "Rename " << oldstr << " => " << newstr << endl;
3681 if (RENAME (oldstr.c_str(), newstr.c_str()) != 0) {
3688 oldstr = Glib::build_filename (newpath, _current_snapshot_name) + history_suffix;
3690 if (Glib::file_test (oldstr, Glib::FILE_TEST_EXISTS)) {
3691 newstr = Glib::build_filename (newpath, legal_name) + history_suffix;
3693 cerr << "Rename " << oldstr << " => " << newstr << endl;
3695 if (RENAME (oldstr.c_str(), newstr.c_str()) != 0) {
3700 /* update file source paths */
3702 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ++i) {
3703 boost::shared_ptr<FileSource> fs = boost::dynamic_pointer_cast<FileSource> (i->second);
3705 string p = fs->path ();
3706 boost::replace_all (p, old_sources_root, _session_dir->sources_root());
3711 /* remove old name from recent sessions */
3713 remove_recent_sessions (_path);
3716 _current_snapshot_name = new_name;
3721 /* save state again to get everything just right */
3723 save_state (_current_snapshot_name);
3726 /* add to recent sessions */
3728 store_recent_sessions (new_name, _path);
3736 Session::get_session_info_from_path (XMLTree& tree, const string& xmlpath)
3738 if (!Glib::file_test (xmlpath, Glib::FILE_TEST_EXISTS)) {
3742 if (!tree.read (xmlpath)) {
3750 Session::get_info_from_path (const string& xmlpath, float& sample_rate, SampleFormat& data_format)
3753 bool found_sr = false;
3754 bool found_data_format = false;
3756 if (get_session_info_from_path (tree, xmlpath)) {
3762 const XMLProperty* prop;
3763 if ((prop = tree.root()->property (X_("sample-rate"))) != 0) {
3764 sample_rate = atoi (prop->value());
3768 const XMLNodeList& children (tree.root()->children());
3769 for (XMLNodeList::const_iterator c = children.begin(); c != children.end(); ++c) {
3770 const XMLNode* child = *c;
3771 if (child->name() == "Config") {
3772 const XMLNodeList& options (child->children());
3773 for (XMLNodeList::const_iterator oc = options.begin(); oc != options.end(); ++oc) {
3774 const XMLNode* option = *oc;
3775 const XMLProperty* name = option->property("name");
3781 if (name->value() == "native-file-data-format") {
3782 const XMLProperty* value = option->property ("value");
3784 SampleFormat fmt = (SampleFormat) string_2_enum (option->property ("value")->value(), fmt);
3786 found_data_format = true;
3792 if (found_data_format) {
3797 return !(found_sr && found_data_format); // zero if they are both found