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 */
44 #include <sys/param.h>
45 #include <sys/mount.h>
48 #ifdef HAVE_SYS_STATVFS_H
49 #include <sys/statvfs.h>
53 #include <glib/gstdio.h>
56 #include <glibmm/threads.h>
58 #include <boost/algorithm/string.hpp>
60 #include "midi++/mmc.h"
61 #include "midi++/port.h"
63 #include "evoral/SMF.hpp"
65 #include "pbd/boost_debug.h"
66 #include "pbd/basename.h"
67 #include "pbd/controllable_descriptor.h"
68 #include "pbd/enumwriter.h"
69 #include "pbd/error.h"
70 #include "pbd/file_utils.h"
71 #include "pbd/pathexpand.h"
72 #include "pbd/pthread_utils.h"
73 #include "pbd/stacktrace.h"
74 #include "pbd/convert.h"
75 #include "pbd/localtime_r.h"
77 #include "ardour/amp.h"
78 #include "ardour/async_midi_port.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_scene_changer.h"
95 #include "ardour/midi_source.h"
96 #include "ardour/midi_track.h"
97 #include "ardour/pannable.h"
98 #include "ardour/playlist_factory.h"
99 #include "ardour/port.h"
100 #include "ardour/processor.h"
101 #include "ardour/proxy_controllable.h"
102 #include "ardour/recent_sessions.h"
103 #include "ardour/region_factory.h"
104 #include "ardour/route_group.h"
105 #include "ardour/send.h"
106 #include "ardour/session.h"
107 #include "ardour/session_directory.h"
108 #include "ardour/session_metadata.h"
109 #include "ardour/session_playlists.h"
110 #include "ardour/session_state_utils.h"
111 #include "ardour/silentfilesource.h"
112 #include "ardour/sndfilesource.h"
113 #include "ardour/source_factory.h"
114 #include "ardour/speakers.h"
115 #include "ardour/template_utils.h"
116 #include "ardour/tempo.h"
117 #include "ardour/ticker.h"
118 #include "ardour/user_bundle.h"
120 #include "control_protocol/control_protocol.h"
126 using namespace ARDOUR;
130 Session::pre_engine_init (string fullpath)
132 if (fullpath.empty()) {
134 throw failed_constructor();
137 /* discover canonical fullpath */
139 _path = canonical_path(fullpath);
141 /* we require _path to end with a dir separator */
143 if (_path[_path.length()-1] != G_DIR_SEPARATOR) {
144 _path += G_DIR_SEPARATOR;
149 _is_new = !Glib::file_test (_path, Glib::FileTest (G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR));
151 /* finish initialization that can't be done in a normal C++ constructor
155 timerclear (&last_mmc_step);
156 g_atomic_int_set (&processing_prohibited, 0);
157 g_atomic_int_set (&_record_status, Disabled);
158 g_atomic_int_set (&_playback_load, 100);
159 g_atomic_int_set (&_capture_load, 100);
161 _all_route_group->set_active (true, this);
162 interpolation.add_channel_to (0, 0);
164 if (config.get_use_video_sync()) {
165 waiting_for_sync_offset = true;
167 waiting_for_sync_offset = false;
170 last_rr_session_dir = session_dirs.begin();
172 set_history_depth (Config->get_history_depth());
174 /* default: assume simple stereo speaker configuration */
176 _speakers->setup_default_speakers (2);
178 _solo_cut_control.reset (new ProxyControllable (_("solo cut control (dB)"), PBD::Controllable::GainLike,
179 boost::bind (&RCConfiguration::set_solo_mute_gain, Config, _1),
180 boost::bind (&RCConfiguration::get_solo_mute_gain, Config)));
181 add_controllable (_solo_cut_control);
183 /* These are all static "per-class" signals */
185 SourceFactory::SourceCreated.connect_same_thread (*this, boost::bind (&Session::add_source, this, _1));
186 PlaylistFactory::PlaylistCreated.connect_same_thread (*this, boost::bind (&Session::add_playlist, this, _1, _2));
187 AutomationList::AutomationListCreated.connect_same_thread (*this, boost::bind (&Session::add_automation_list, this, _1));
188 Controllable::Destroyed.connect_same_thread (*this, boost::bind (&Session::remove_controllable, this, _1));
189 IO::PortCountChanged.connect_same_thread (*this, boost::bind (&Session::ensure_buffers, this, _1));
191 /* stop IO objects from doing stuff until we're ready for them */
193 Delivery::disable_panners ();
194 IO::disable_connecting ();
196 AudioFileSource::set_peak_dir (_session_dir->peak_path());
200 Session::post_engine_init ()
202 BootMessage (_("Set block size and sample rate"));
204 set_block_size (_engine.samples_per_cycle());
205 set_frame_rate (_engine.sample_rate());
207 BootMessage (_("Using configuration"));
209 _midi_ports = new MidiPortManager;
211 MIDISceneChanger* msc;
213 _scene_changer = msc = new MIDISceneChanger (*this);
214 msc->set_input_port (scene_input_port());
215 msc->set_output_port (scene_out());
217 boost::function<framecnt_t(void)> timer_func (boost::bind (&Session::audible_frame, this));
218 boost::dynamic_pointer_cast<AsyncMIDIPort>(scene_in())->set_timer (timer_func);
220 setup_midi_machine_control ();
222 if (_butler->start_thread()) {
226 if (start_midi_thread ()) {
230 setup_click_sounds (0);
231 setup_midi_control ();
233 _engine.Halted.connect_same_thread (*this, boost::bind (&Session::engine_halted, this));
234 _engine.Xrun.connect_same_thread (*this, boost::bind (&Session::xrun_recovery, this));
237 /* tempo map requires sample rate knowledge */
239 _tempo_map = new TempoMap (_current_frame_rate);
240 _tempo_map->PropertyChanged.connect_same_thread (*this, boost::bind (&Session::tempo_map_changed, this, _1));
242 /* MidiClock requires a tempo map */
244 midi_clock = new MidiClockTicker ();
245 midi_clock->set_session (this);
247 /* crossfades require sample rate knowledge */
249 SndFileSource::setup_standard_crossfades (*this, frame_rate());
250 _engine.GraphReordered.connect_same_thread (*this, boost::bind (&Session::graph_reordered, this));
252 AudioDiskstream::allocate_working_buffers();
253 refresh_disk_space ();
255 /* we're finally ready to call set_state() ... all objects have
256 * been created, the engine is running.
260 if (set_state (*state_tree->root(), Stateful::loading_state_version)) {
264 // set_state() will call setup_raid_path(), but if it's a new session we need
265 // to call setup_raid_path() here.
266 setup_raid_path (_path);
271 boost::function<void (std::string)> ff (boost::bind (&Session::config_changed, this, _1, false));
272 boost::function<void (std::string)> ft (boost::bind (&Session::config_changed, this, _1, true));
274 Config->map_parameters (ff);
275 config.map_parameters (ft);
277 /* Reset all panners */
279 Delivery::reset_panners ();
281 /* this will cause the CPM to instantiate any protocols that are in use
282 * (or mandatory), which will pass it this Session, and then call
283 * set_state() on each instantiated protocol to match stored state.
286 ControlProtocolManager::instance().set_session (this);
288 /* This must be done after the ControlProtocolManager set_session above,
289 as it will set states for ports which the ControlProtocolManager creates.
292 // XXX set state of MIDI::Port's
293 // MidiPortManager::instance()->set_port_states (Config->midi_port_states ());
295 /* And this must be done after the MIDI::Manager::set_port_states as
296 * it will try to make connections whose details are loaded by set_port_states.
301 /* Let control protocols know that we are now all connected, so they
302 * could start talking to surfaces if they want to.
305 ControlProtocolManager::instance().midi_connectivity_established ();
307 if (_is_new && !no_auto_connect()) {
308 Glib::Threads::Mutex::Lock lm (AudioEngine::instance()->process_lock());
309 auto_connect_master_bus ();
312 _state_of_the_state = StateOfTheState (_state_of_the_state & ~(CannotSave|Dirty));
314 /* update latencies */
316 initialize_latencies ();
318 _locations->changed.connect_same_thread (*this, boost::bind (&Session::locations_changed, this));
319 _locations->added.connect_same_thread (*this, boost::bind (&Session::locations_added, this, _1));
321 } catch (AudioEngine::PortRegistrationFailure& err) {
322 /* handle this one in a different way than all others, so that its clear what happened */
323 error << err.what() << endmsg;
329 BootMessage (_("Reset Remote Controls"));
331 // send_full_time_code (0);
332 _engine.transport_locate (0);
334 _mmc->send (MIDI::MachineControlCommand (MIDI::MachineControl::cmdMmcReset));
335 _mmc->send (MIDI::MachineControlCommand (Timecode::Time ()));
337 MIDI::Name::MidiPatchManager::instance().set_session (this);
340 /* initial program change will be delivered later; see ::config_changed() */
342 _state_of_the_state = Clean;
344 Port::set_connecting_blocked (false);
346 DirtyChanged (); /* EMIT SIGNAL */
350 } else if (state_was_pending) {
352 remove_pending_capture_state ();
353 state_was_pending = false;
360 Session::raid_path () const
362 Searchpath raid_search_path;
364 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
365 raid_search_path += (*i).path;
368 return raid_search_path.to_string ();
372 Session::setup_raid_path (string path)
381 session_dirs.clear ();
383 Searchpath search_path(path);
384 Searchpath sound_search_path;
385 Searchpath midi_search_path;
387 for (Searchpath::const_iterator i = search_path.begin(); i != search_path.end(); ++i) {
389 sp.blocks = 0; // not needed
390 session_dirs.push_back (sp);
392 SessionDirectory sdir(sp.path);
394 sound_search_path += sdir.sound_path ();
395 midi_search_path += sdir.midi_path ();
398 // reset the round-robin soundfile path thingie
399 last_rr_session_dir = session_dirs.begin();
403 Session::path_is_within_session (const std::string& path)
405 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
406 if (PBD::path_is_within (i->path, path)) {
414 Session::ensure_subdirs ()
418 dir = session_directory().peak_path();
420 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
421 error << string_compose(_("Session: cannot create session peakfile folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
425 dir = session_directory().sound_path();
427 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
428 error << string_compose(_("Session: cannot create session sounds dir \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
432 dir = session_directory().midi_path();
434 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
435 error << string_compose(_("Session: cannot create session midi dir \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
439 dir = session_directory().dead_path();
441 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
442 error << string_compose(_("Session: cannot create session dead sounds folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
446 dir = session_directory().export_path();
448 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
449 error << string_compose(_("Session: cannot create session export folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
453 dir = analysis_dir ();
455 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
456 error << string_compose(_("Session: cannot create session analysis folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
460 dir = plugins_dir ();
462 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
463 error << string_compose(_("Session: cannot create session plugins folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
467 dir = externals_dir ();
469 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
470 error << string_compose(_("Session: cannot create session externals folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
477 /** @param session_template directory containing session template, or empty.
478 * Caller must not hold process lock.
481 Session::create (const string& session_template, BusProfile* bus_profile)
483 if (g_mkdir_with_parents (_path.c_str(), 0755) < 0) {
484 error << string_compose(_("Session: cannot create session folder \"%1\" (%2)"), _path, strerror (errno)) << endmsg;
488 if (ensure_subdirs ()) {
492 _writable = exists_and_writable (_path);
494 if (!session_template.empty()) {
495 std::string in_path = session_template_dir_to_file (session_template);
497 ifstream in(in_path.c_str());
500 /* no need to call legalize_for_path() since the string
501 * in session_template is already a legal path name
503 string out_path = Glib::build_filename (_session_dir->root_path(), _name + statefile_suffix);
505 ofstream out(out_path.c_str());
511 /* Copy plugin state files from template to new session */
512 std::string template_plugins = Glib::build_filename (session_template, X_("plugins"));
513 copy_files (template_plugins, plugins_dir ());
518 error << string_compose (_("Could not open %1 for writing session template"), out_path)
524 error << string_compose (_("Could not open session template %1 for reading"), in_path)
531 /* set initial start + end point */
533 _state_of_the_state = Clean;
535 /* set up Master Out and Control Out if necessary */
540 ChanCount count(DataType::AUDIO, bus_profile->master_out_channels);
542 if (bus_profile->master_out_channels) {
543 boost::shared_ptr<Route> r (new Route (*this, _("master"), Route::MasterOut, DataType::AUDIO));
547 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
548 // boost_debug_shared_ptr_mark_interesting (r.get(), "Route");
551 Glib::Threads::Mutex::Lock lm (AudioEngine::instance()->process_lock ());
552 r->input()->ensure_io (count, false, this);
553 r->output()->ensure_io (count, false, this);
559 /* prohibit auto-connect to master, because there isn't one */
560 bus_profile->output_ac = AutoConnectOption (bus_profile->output_ac & ~AutoConnectMaster);
564 add_routes (rl, false, false, false);
567 /* this allows the user to override settings with an environment variable.
570 if (no_auto_connect()) {
571 bus_profile->input_ac = AutoConnectOption (0);
572 bus_profile->output_ac = AutoConnectOption (0);
575 Config->set_input_auto_connect (bus_profile->input_ac);
576 Config->set_output_auto_connect (bus_profile->output_ac);
579 if (Config->get_use_monitor_bus() && bus_profile) {
580 add_monitor_section ();
587 Session::maybe_write_autosave()
589 if (dirty() && record_status() != Recording) {
590 save_state("", true);
595 Session::remove_pending_capture_state ()
597 std::string pending_state_file_path(_session_dir->root_path());
599 pending_state_file_path = Glib::build_filename (pending_state_file_path, legalize_for_path (_current_snapshot_name) + pending_suffix);
601 if (!Glib::file_test (pending_state_file_path, Glib::FILE_TEST_EXISTS)) return;
603 if (g_remove (pending_state_file_path.c_str()) != 0) {
604 error << string_compose(_("Could not remove pending capture state at path \"%1\" (%2)"),
605 pending_state_file_path, g_strerror (errno)) << endmsg;
609 /** Rename a state file.
610 * @param old_name Old snapshot name.
611 * @param new_name New snapshot name.
614 Session::rename_state (string old_name, string new_name)
616 if (old_name == _current_snapshot_name || old_name == _name) {
617 /* refuse to rename the current snapshot or the "main" one */
621 const string old_xml_filename = legalize_for_path (old_name) + statefile_suffix;
622 const string new_xml_filename = legalize_for_path (new_name) + statefile_suffix;
624 const std::string old_xml_path(Glib::build_filename (_session_dir->root_path(), old_xml_filename));
625 const std::string new_xml_path(Glib::build_filename (_session_dir->root_path(), new_xml_filename));
627 if (::g_rename (old_xml_path.c_str(), new_xml_path.c_str()) != 0) {
628 error << string_compose(_("could not rename snapshot %1 to %2 (%3)"),
629 old_name, new_name, g_strerror(errno)) << endmsg;
633 /** Remove a state file.
634 * @param snapshot_name Snapshot name.
637 Session::remove_state (string snapshot_name)
639 if (!_writable || snapshot_name == _current_snapshot_name || snapshot_name == _name) {
640 // refuse to remove the current snapshot or the "main" one
644 std::string xml_path(_session_dir->root_path());
646 xml_path = Glib::build_filename (xml_path, legalize_for_path (snapshot_name) + statefile_suffix);
648 if (!create_backup_file (xml_path)) {
649 // don't remove it if a backup can't be made
650 // create_backup_file will log the error.
655 if (g_remove (xml_path.c_str()) != 0) {
656 error << string_compose(_("Could not remove session file at path \"%1\" (%2)"),
657 xml_path, g_strerror (errno)) << endmsg;
661 /** @param snapshot_name Name to save under, without .ardour / .pending prefix */
663 Session::save_state (string snapshot_name, bool pending, bool switch_to_snapshot)
666 std::string xml_path(_session_dir->root_path());
668 if (!_writable || (_state_of_the_state & CannotSave)) {
672 if (g_atomic_int_get(&_suspend_save)) {
676 _save_queued = false;
678 if (!_engine.connected ()) {
679 error << string_compose (_("the %1 audio engine is not connected and state saving would lose all I/O connections. Session not saved"),
685 /* tell sources we're saving first, in case they write out to a new file
686 * which should be saved with the state rather than the old one */
687 for (SourceMap::const_iterator i = sources.begin(); i != sources.end(); ++i) {
689 i->second->session_saved();
690 } catch (Evoral::SMF::FileError& e) {
691 error << string_compose ("Could not write to MIDI file %1; MIDI data not saved.", e.file_name ()) << endmsg;
695 SaveSession (); /* EMIT SIGNAL */
697 tree.set_root (&get_state());
699 if (snapshot_name.empty()) {
700 snapshot_name = _current_snapshot_name;
701 } else if (switch_to_snapshot) {
702 _current_snapshot_name = snapshot_name;
707 /* proper save: use statefile_suffix (.ardour in English) */
709 xml_path = Glib::build_filename (xml_path, legalize_for_path (snapshot_name) + statefile_suffix);
711 /* make a backup copy of the old file */
713 if (Glib::file_test (xml_path, Glib::FILE_TEST_EXISTS) && !create_backup_file (xml_path)) {
714 // create_backup_file will log the error
720 /* pending save: use pending_suffix (.pending in English) */
721 xml_path = Glib::build_filename (xml_path, legalize_for_path (snapshot_name) + pending_suffix);
724 std::string tmp_path(_session_dir->root_path());
725 tmp_path = Glib::build_filename (tmp_path, legalize_for_path (snapshot_name) + temp_suffix);
727 // cerr << "actually writing state to " << xml_path << endl;
729 if (!tree.write (tmp_path)) {
730 error << string_compose (_("state could not be saved to %1"), tmp_path) << endmsg;
731 if (g_remove (tmp_path.c_str()) != 0) {
732 error << string_compose(_("Could not remove temporary session file at path \"%1\" (%2)"),
733 tmp_path, g_strerror (errno)) << endmsg;
739 if (::g_rename (tmp_path.c_str(), xml_path.c_str()) != 0) {
740 error << string_compose (_("could not rename temporary session file %1 to %2 (%3)"),
741 tmp_path, xml_path, g_strerror(errno)) << endmsg;
742 if (g_remove (tmp_path.c_str()) != 0) {
743 error << string_compose(_("Could not remove temporary session file at path \"%1\" (%2)"),
744 tmp_path, g_strerror (errno)) << endmsg;
752 save_history (snapshot_name);
754 bool was_dirty = dirty();
756 _state_of_the_state = StateOfTheState (_state_of_the_state & ~Dirty);
759 DirtyChanged (); /* EMIT SIGNAL */
762 StateSaved (snapshot_name); /* EMIT SIGNAL */
769 Session::restore_state (string snapshot_name)
771 if (load_state (snapshot_name) == 0) {
772 set_state (*state_tree->root(), Stateful::loading_state_version);
779 Session::load_state (string snapshot_name)
784 state_was_pending = false;
786 /* check for leftover pending state from a crashed capture attempt */
788 std::string xmlpath(_session_dir->root_path());
789 xmlpath = Glib::build_filename (xmlpath, legalize_for_path (snapshot_name) + pending_suffix);
791 if (Glib::file_test (xmlpath, Glib::FILE_TEST_EXISTS)) {
793 /* there is pending state from a crashed capture attempt */
795 boost::optional<int> r = AskAboutPendingState();
796 if (r.get_value_or (1)) {
797 state_was_pending = true;
801 if (!state_was_pending) {
802 xmlpath = Glib::build_filename (_session_dir->root_path(), snapshot_name);
805 if (!Glib::file_test (xmlpath, Glib::FILE_TEST_EXISTS)) {
806 xmlpath = Glib::build_filename (_session_dir->root_path(), legalize_for_path (snapshot_name) + statefile_suffix);
807 if (!Glib::file_test (xmlpath, Glib::FILE_TEST_EXISTS)) {
808 error << string_compose(_("%1: session file \"%2\" doesn't exist!"), _name, xmlpath) << endmsg;
813 state_tree = new XMLTree;
817 _writable = exists_and_writable (xmlpath) && exists_and_writable(Glib::path_get_dirname(xmlpath));
819 if (!state_tree->read (xmlpath)) {
820 error << string_compose(_("Could not understand session file %1"), xmlpath) << endmsg;
826 XMLNode& root (*state_tree->root());
828 if (root.name() != X_("Session")) {
829 error << string_compose (_("Session file %1 is not a session"), xmlpath) << endmsg;
835 const XMLProperty* prop;
837 if ((prop = root.property ("version")) == 0) {
838 /* no version implies very old version of Ardour */
839 Stateful::loading_state_version = 1000;
841 if (prop->value().find ('.') != string::npos) {
842 /* old school version format */
843 if (prop->value()[0] == '2') {
844 Stateful::loading_state_version = 2000;
846 Stateful::loading_state_version = 3000;
849 Stateful::loading_state_version = atoi (prop->value());
853 if (Stateful::loading_state_version < CURRENT_SESSION_FILE_VERSION && _writable) {
855 std::string backup_path(_session_dir->root_path());
856 std::string backup_filename = string_compose ("%1-%2%3", legalize_for_path (snapshot_name), Stateful::loading_state_version, statefile_suffix);
857 backup_path = Glib::build_filename (backup_path, backup_filename);
859 // only create a backup for a given statefile version once
861 if (!Glib::file_test (backup_path, Glib::FILE_TEST_EXISTS)) {
863 VersionMismatch (xmlpath, backup_path);
865 if (!copy_file (xmlpath, backup_path)) {;
875 Session::load_options (const XMLNode& node)
877 LocaleGuard lg (X_("POSIX"));
878 config.set_variables (node);
889 Session::get_template()
891 /* if we don't disable rec-enable, diskstreams
892 will believe they need to store their capture
893 sources in their state node.
896 disable_record (false);
902 Session::state (bool full_state)
904 XMLNode* node = new XMLNode("Session");
908 snprintf(buf, sizeof(buf), "%d", CURRENT_SESSION_FILE_VERSION);
909 node->add_property("version", buf);
911 /* store configuration settings */
915 node->add_property ("name", _name);
916 snprintf (buf, sizeof (buf), "%" PRId64, _nominal_frame_rate);
917 node->add_property ("sample-rate", buf);
919 if (session_dirs.size() > 1) {
923 vector<space_and_path>::iterator i = session_dirs.begin();
924 vector<space_and_path>::iterator next;
926 ++i; /* skip the first one */
930 while (i != session_dirs.end()) {
934 if (next != session_dirs.end()) {
935 p += G_SEARCHPATH_SEPARATOR;
944 child = node->add_child ("Path");
945 child->add_content (p);
949 /* save the ID counter */
951 snprintf (buf, sizeof (buf), "%" PRIu64, ID::counter());
952 node->add_property ("id-counter", buf);
954 /* save the event ID counter */
956 snprintf (buf, sizeof (buf), "%d", Evoral::event_id_counter());
957 node->add_property ("event-counter", buf);
959 /* various options */
961 list<XMLNode*> midi_port_nodes = _midi_ports->get_midi_port_states();
962 if (!midi_port_nodes.empty()) {
963 XMLNode* midi_port_stuff = new XMLNode ("MIDIPorts");
964 for (list<XMLNode*>::const_iterator n = midi_port_nodes.begin(); n != midi_port_nodes.end(); ++n) {
965 midi_port_stuff->add_child_nocopy (**n);
967 node->add_child_nocopy (*midi_port_stuff);
970 node->add_child_nocopy (config.get_variables ());
972 node->add_child_nocopy (ARDOUR::SessionMetadata::Metadata()->get_state());
974 child = node->add_child ("Sources");
977 Glib::Threads::Mutex::Lock sl (source_lock);
979 for (SourceMap::iterator siter = sources.begin(); siter != sources.end(); ++siter) {
981 /* Don't save information about non-file Sources, or
982 * about non-destructive file sources that are empty
983 * and unused by any regions.
986 boost::shared_ptr<FileSource> fs;
988 if ((fs = boost::dynamic_pointer_cast<FileSource> (siter->second)) != 0) {
990 if (!fs->destructive()) {
991 if (fs->empty() && !fs->used()) {
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 enum Route::Flag flags = Route::Flag(0);
1429 const XMLProperty* prop = node.property("flags");
1431 flags = Route::Flag (string_2_enum (prop->value(), flags));
1434 boost::shared_ptr<Route> r (new Route (*this, X_("toBeResetFroXML"), flags));
1436 if (r->init () == 0 && r->set_state (node, version) == 0) {
1437 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
1438 // boost_debug_shared_ptr_mark_interesting (r.get(), "Route");
1447 boost::shared_ptr<Route>
1448 Session::XMLRouteFactory_2X (const XMLNode& node, int version)
1450 boost::shared_ptr<Route> ret;
1452 if (node.name() != "Route") {
1456 XMLProperty const * ds_prop = node.property (X_("diskstream-id"));
1458 ds_prop = node.property (X_("diskstream"));
1461 DataType type = DataType::AUDIO;
1462 const XMLProperty* prop = node.property("default-type");
1465 type = DataType (prop->value());
1468 assert (type != DataType::NIL);
1472 list<boost::shared_ptr<Diskstream> >::iterator i = _diskstreams_2X.begin ();
1473 while (i != _diskstreams_2X.end() && (*i)->id() != ds_prop->value()) {
1477 if (i == _diskstreams_2X.end()) {
1478 error << _("Could not find diskstream for route") << endmsg;
1479 return boost::shared_ptr<Route> ();
1482 boost::shared_ptr<Track> track;
1484 if (type == DataType::AUDIO) {
1485 track.reset (new AudioTrack (*this, X_("toBeResetFroXML")));
1487 track.reset (new MidiTrack (*this, X_("toBeResetFroXML")));
1490 if (track->init()) {
1494 if (track->set_state (node, version)) {
1498 track->set_diskstream (*i);
1500 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
1501 // boost_debug_shared_ptr_mark_interesting (track.get(), "Track");
1506 enum Route::Flag flags = Route::Flag(0);
1507 const XMLProperty* prop = node.property("flags");
1509 flags = Route::Flag (string_2_enum (prop->value(), flags));
1512 boost::shared_ptr<Route> r (new Route (*this, X_("toBeResetFroXML"), flags));
1514 if (r->init () == 0 && r->set_state (node, version) == 0) {
1515 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
1516 // boost_debug_shared_ptr_mark_interesting (r.get(), "Route");
1526 Session::load_regions (const XMLNode& node)
1529 XMLNodeConstIterator niter;
1530 boost::shared_ptr<Region> region;
1532 nlist = node.children();
1536 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1537 if ((region = XMLRegionFactory (**niter, false)) == 0) {
1538 error << _("Session: cannot create Region from XML description.");
1539 const XMLProperty *name = (**niter).property("name");
1542 error << " " << string_compose (_("Can not load state for region '%1'"), name->value());
1553 Session::load_compounds (const XMLNode& node)
1555 XMLNodeList calist = node.children();
1556 XMLNodeConstIterator caiter;
1557 XMLProperty *caprop;
1559 for (caiter = calist.begin(); caiter != calist.end(); ++caiter) {
1560 XMLNode* ca = *caiter;
1564 if ((caprop = ca->property (X_("original"))) == 0) {
1567 orig_id = caprop->value();
1569 if ((caprop = ca->property (X_("copy"))) == 0) {
1572 copy_id = caprop->value();
1574 boost::shared_ptr<Region> orig = RegionFactory::region_by_id (orig_id);
1575 boost::shared_ptr<Region> copy = RegionFactory::region_by_id (copy_id);
1577 if (!orig || !copy) {
1578 warning << string_compose (_("Regions in compound description not found (ID's %1 and %2): ignored"),
1584 RegionFactory::add_compound_association (orig, copy);
1591 Session::load_nested_sources (const XMLNode& node)
1594 XMLNodeConstIterator niter;
1596 nlist = node.children();
1598 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1599 if ((*niter)->name() == "Source") {
1601 /* it may already exist, so don't recreate it unnecessarily
1604 XMLProperty* prop = (*niter)->property (X_("id"));
1606 error << _("Nested source has no ID info in session file! (ignored)") << endmsg;
1610 ID source_id (prop->value());
1612 if (!source_by_id (source_id)) {
1615 SourceFactory::create (*this, **niter, true);
1617 catch (failed_constructor& err) {
1618 error << string_compose (_("Cannot reconstruct nested source for region %1"), name()) << endmsg;
1625 boost::shared_ptr<Region>
1626 Session::XMLRegionFactory (const XMLNode& node, bool full)
1628 const XMLProperty* type = node.property("type");
1632 const XMLNodeList& nlist = node.children();
1634 for (XMLNodeConstIterator niter = nlist.begin(); niter != nlist.end(); ++niter) {
1635 XMLNode *child = (*niter);
1636 if (child->name() == "NestedSource") {
1637 load_nested_sources (*child);
1641 if (!type || type->value() == "audio") {
1642 return boost::shared_ptr<Region>(XMLAudioRegionFactory (node, full));
1643 } else if (type->value() == "midi") {
1644 return boost::shared_ptr<Region>(XMLMidiRegionFactory (node, full));
1647 } catch (failed_constructor& err) {
1648 return boost::shared_ptr<Region> ();
1651 return boost::shared_ptr<Region> ();
1654 boost::shared_ptr<AudioRegion>
1655 Session::XMLAudioRegionFactory (const XMLNode& node, bool /*full*/)
1657 const XMLProperty* prop;
1658 boost::shared_ptr<Source> source;
1659 boost::shared_ptr<AudioSource> as;
1661 SourceList master_sources;
1662 uint32_t nchans = 1;
1665 if (node.name() != X_("Region")) {
1666 return boost::shared_ptr<AudioRegion>();
1669 if ((prop = node.property (X_("channels"))) != 0) {
1670 nchans = atoi (prop->value().c_str());
1673 if ((prop = node.property ("name")) == 0) {
1674 cerr << "no name for this region\n";
1678 if ((prop = node.property (X_("source-0"))) == 0) {
1679 if ((prop = node.property ("source")) == 0) {
1680 error << _("Session: XMLNode describing a AudioRegion is incomplete (no source)") << endmsg;
1681 return boost::shared_ptr<AudioRegion>();
1685 PBD::ID s_id (prop->value());
1687 if ((source = source_by_id (s_id)) == 0) {
1688 error << string_compose(_("Session: XMLNode describing a AudioRegion references an unknown source id =%1"), s_id) << endmsg;
1689 return boost::shared_ptr<AudioRegion>();
1692 as = boost::dynamic_pointer_cast<AudioSource>(source);
1694 error << string_compose(_("Session: XMLNode describing a AudioRegion references a non-audio source id =%1"), s_id) << endmsg;
1695 return boost::shared_ptr<AudioRegion>();
1698 sources.push_back (as);
1700 /* pickup other channels */
1702 for (uint32_t n=1; n < nchans; ++n) {
1703 snprintf (buf, sizeof(buf), X_("source-%d"), n);
1704 if ((prop = node.property (buf)) != 0) {
1706 PBD::ID id2 (prop->value());
1708 if ((source = source_by_id (id2)) == 0) {
1709 error << string_compose(_("Session: XMLNode describing a AudioRegion references an unknown source id =%1"), id2) << endmsg;
1710 return boost::shared_ptr<AudioRegion>();
1713 as = boost::dynamic_pointer_cast<AudioSource>(source);
1715 error << string_compose(_("Session: XMLNode describing a AudioRegion references a non-audio source id =%1"), id2) << endmsg;
1716 return boost::shared_ptr<AudioRegion>();
1718 sources.push_back (as);
1722 for (uint32_t n = 0; n < nchans; ++n) {
1723 snprintf (buf, sizeof(buf), X_("master-source-%d"), n);
1724 if ((prop = node.property (buf)) != 0) {
1726 PBD::ID id2 (prop->value());
1728 if ((source = source_by_id (id2)) == 0) {
1729 error << string_compose(_("Session: XMLNode describing a AudioRegion references an unknown source id =%1"), id2) << endmsg;
1730 return boost::shared_ptr<AudioRegion>();
1733 as = boost::dynamic_pointer_cast<AudioSource>(source);
1735 error << string_compose(_("Session: XMLNode describing a AudioRegion references a non-audio source id =%1"), id2) << endmsg;
1736 return boost::shared_ptr<AudioRegion>();
1738 master_sources.push_back (as);
1743 boost::shared_ptr<AudioRegion> region (boost::dynamic_pointer_cast<AudioRegion> (RegionFactory::create (sources, node)));
1745 /* a final detail: this is the one and only place that we know how long missing files are */
1747 if (region->whole_file()) {
1748 for (SourceList::iterator sx = sources.begin(); sx != sources.end(); ++sx) {
1749 boost::shared_ptr<SilentFileSource> sfp = boost::dynamic_pointer_cast<SilentFileSource> (*sx);
1751 sfp->set_length (region->length());
1756 if (!master_sources.empty()) {
1757 if (master_sources.size() != nchans) {
1758 error << _("Session: XMLNode describing an AudioRegion is missing some master sources; ignored") << endmsg;
1760 region->set_master_sources (master_sources);
1768 catch (failed_constructor& err) {
1769 return boost::shared_ptr<AudioRegion>();
1773 boost::shared_ptr<MidiRegion>
1774 Session::XMLMidiRegionFactory (const XMLNode& node, bool /*full*/)
1776 const XMLProperty* prop;
1777 boost::shared_ptr<Source> source;
1778 boost::shared_ptr<MidiSource> ms;
1781 if (node.name() != X_("Region")) {
1782 return boost::shared_ptr<MidiRegion>();
1785 if ((prop = node.property ("name")) == 0) {
1786 cerr << "no name for this region\n";
1790 if ((prop = node.property (X_("source-0"))) == 0) {
1791 if ((prop = node.property ("source")) == 0) {
1792 error << _("Session: XMLNode describing a MidiRegion is incomplete (no source)") << endmsg;
1793 return boost::shared_ptr<MidiRegion>();
1797 PBD::ID s_id (prop->value());
1799 if ((source = source_by_id (s_id)) == 0) {
1800 error << string_compose(_("Session: XMLNode describing a MidiRegion references an unknown source id =%1"), s_id) << endmsg;
1801 return boost::shared_ptr<MidiRegion>();
1804 ms = boost::dynamic_pointer_cast<MidiSource>(source);
1806 error << string_compose(_("Session: XMLNode describing a MidiRegion references a non-midi source id =%1"), s_id) << endmsg;
1807 return boost::shared_ptr<MidiRegion>();
1810 sources.push_back (ms);
1813 boost::shared_ptr<MidiRegion> region (boost::dynamic_pointer_cast<MidiRegion> (RegionFactory::create (sources, node)));
1814 /* a final detail: this is the one and only place that we know how long missing files are */
1816 if (region->whole_file()) {
1817 for (SourceList::iterator sx = sources.begin(); sx != sources.end(); ++sx) {
1818 boost::shared_ptr<SilentFileSource> sfp = boost::dynamic_pointer_cast<SilentFileSource> (*sx);
1820 sfp->set_length (region->length());
1828 catch (failed_constructor& err) {
1829 return boost::shared_ptr<MidiRegion>();
1834 Session::get_sources_as_xml ()
1837 XMLNode* node = new XMLNode (X_("Sources"));
1838 Glib::Threads::Mutex::Lock lm (source_lock);
1840 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ++i) {
1841 node->add_child_nocopy (i->second->get_state());
1848 Session::path_from_region_name (DataType type, string name, string identifier)
1850 char buf[PATH_MAX+1];
1852 SessionDirectory sdir(get_best_session_directory_for_new_source());
1853 std::string source_dir = ((type == DataType::AUDIO)
1854 ? sdir.sound_path() : sdir.midi_path());
1856 string ext = native_header_format_extension (config.get_native_file_header_format(), type);
1858 for (n = 0; n < 999999; ++n) {
1859 if (identifier.length()) {
1860 snprintf (buf, sizeof(buf), "%s%s%" PRIu32 "%s", name.c_str(),
1861 identifier.c_str(), n, ext.c_str());
1863 snprintf (buf, sizeof(buf), "%s-%" PRIu32 "%s", name.c_str(),
1867 std::string source_path = Glib::build_filename (source_dir, buf);
1869 if (!Glib::file_test (source_path, Glib::FILE_TEST_EXISTS)) {
1874 error << string_compose (_("cannot create new file from region name \"%1\" with ident = \"%2\": too many existing files with similar names"),
1883 Session::load_sources (const XMLNode& node)
1886 XMLNodeConstIterator niter;
1887 boost::shared_ptr<Source> source;
1889 nlist = node.children();
1893 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1896 if ((source = XMLSourceFactory (**niter)) == 0) {
1897 error << _("Session: cannot create Source from XML description.") << endmsg;
1900 } catch (MissingSource& err) {
1904 if (!no_questions_about_missing_files) {
1905 user_choice = MissingFile (this, err.path, err.type).get_value_or (-1);
1910 switch (user_choice) {
1912 /* user added a new search location, so try again */
1917 /* user asked to quit the entire session load
1922 no_questions_about_missing_files = true;
1926 no_questions_about_missing_files = true;
1931 warning << _("A sound file is missing. It will be replaced by silence.") << endmsg;
1932 source = SourceFactory::createSilent (*this, **niter, max_framecnt, _current_frame_rate);
1941 boost::shared_ptr<Source>
1942 Session::XMLSourceFactory (const XMLNode& node)
1944 if (node.name() != "Source") {
1945 return boost::shared_ptr<Source>();
1949 /* note: do peak building in another thread when loading session state */
1950 return SourceFactory::create (*this, node, true);
1953 catch (failed_constructor& err) {
1954 error << string_compose (_("Found a sound file that cannot be used by %1. Talk to the progammers."), PROGRAM_NAME) << endmsg;
1955 return boost::shared_ptr<Source>();
1960 Session::save_template (string template_name)
1964 if (_state_of_the_state & CannotSave) {
1968 std::string user_template_dir(user_template_directory());
1970 if (g_mkdir_with_parents (user_template_dir.c_str(), 0755) != 0) {
1971 error << string_compose(_("Could not create templates directory \"%1\" (%2)"),
1972 user_template_dir, g_strerror (errno)) << endmsg;
1976 tree.set_root (&get_template());
1978 std::string template_dir_path(user_template_dir);
1980 /* directory to put the template in */
1981 template_dir_path = Glib::build_filename (template_dir_path, template_name);
1983 if (Glib::file_test (template_dir_path, Glib::FILE_TEST_EXISTS)) {
1984 warning << string_compose(_("Template \"%1\" already exists - new version not created"),
1985 template_dir_path) << endmsg;
1989 if (g_mkdir_with_parents (template_dir_path.c_str(), 0755) != 0) {
1990 error << string_compose(_("Could not create directory for Session template\"%1\" (%2)"),
1991 template_dir_path, g_strerror (errno)) << endmsg;
1996 std::string template_file_path(template_dir_path);
1997 template_file_path = Glib::build_filename (template_file_path, template_name + template_suffix);
1999 if (!tree.write (template_file_path)) {
2000 error << _("template not saved") << endmsg;
2004 /* copy plugin state directory */
2006 std::string template_plugin_state_path(template_dir_path);
2007 template_plugin_state_path = Glib::build_filename (template_plugin_state_path, X_("plugins"));
2009 if (g_mkdir_with_parents (template_plugin_state_path.c_str(), 0755) != 0) {
2010 error << string_compose(_("Could not create directory for Session template plugin state\"%1\" (%2)"),
2011 template_plugin_state_path, g_strerror (errno)) << endmsg;
2015 copy_files (plugins_dir(), template_plugin_state_path);
2021 Session::refresh_disk_space ()
2023 #if __APPLE__ || (HAVE_SYS_VFS_H && HAVE_SYS_STATVFS_H)
2025 Glib::Threads::Mutex::Lock lm (space_lock);
2027 /* get freespace on every FS that is part of the session path */
2029 _total_free_4k_blocks = 0;
2030 _total_free_4k_blocks_uncertain = false;
2032 for (vector<space_and_path>::iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
2034 struct statfs statfsbuf;
2035 statfs (i->path.c_str(), &statfsbuf);
2037 double const scale = statfsbuf.f_bsize / 4096.0;
2039 /* See if this filesystem is read-only */
2040 struct statvfs statvfsbuf;
2041 statvfs (i->path.c_str(), &statvfsbuf);
2043 /* f_bavail can be 0 if it is undefined for whatever
2044 filesystem we are looking at; Samba shares mounted
2045 via GVFS are an example of this.
2047 if (statfsbuf.f_bavail == 0) {
2048 /* block count unknown */
2050 i->blocks_unknown = true;
2051 } else if (statvfsbuf.f_flag & ST_RDONLY) {
2052 /* read-only filesystem */
2054 i->blocks_unknown = false;
2056 /* read/write filesystem with known space */
2057 i->blocks = (uint32_t) floor (statfsbuf.f_bavail * scale);
2058 i->blocks_unknown = false;
2061 _total_free_4k_blocks += i->blocks;
2062 if (i->blocks_unknown) {
2063 _total_free_4k_blocks_uncertain = true;
2066 #elif defined (COMPILER_MSVC)
2067 vector<string> scanned_volumes;
2068 vector<string>::iterator j;
2069 vector<space_and_path>::iterator i;
2070 DWORD nSectorsPerCluster, nBytesPerSector,
2071 nFreeClusters, nTotalClusters;
2075 _total_free_4k_blocks = 0;
2077 for (i = session_dirs.begin(); i != session_dirs.end(); i++) {
2078 strncpy (disk_drive, (*i).path.c_str(), 3);
2082 volume_found = false;
2083 if (0 != (GetDiskFreeSpace(disk_drive, &nSectorsPerCluster, &nBytesPerSector, &nFreeClusters, &nTotalClusters)))
2085 int64_t nBytesPerCluster = nBytesPerSector * nSectorsPerCluster;
2086 int64_t nFreeBytes = nBytesPerCluster * (int64_t)nFreeClusters;
2087 i->blocks = (uint32_t)(nFreeBytes / 4096);
2089 for (j = scanned_volumes.begin(); j != scanned_volumes.end(); j++) {
2090 if (0 == j->compare(disk_drive)) {
2091 volume_found = true;
2096 if (!volume_found) {
2097 scanned_volumes.push_back(disk_drive);
2098 _total_free_4k_blocks += i->blocks;
2103 if (0 == _total_free_4k_blocks) {
2104 strncpy (disk_drive, path().c_str(), 3);
2107 if (0 != (GetDiskFreeSpace(disk_drive, &nSectorsPerCluster, &nBytesPerSector, &nFreeClusters, &nTotalClusters)))
2109 int64_t nBytesPerCluster = nBytesPerSector * nSectorsPerCluster;
2110 int64_t nFreeBytes = nBytesPerCluster * (int64_t)nFreeClusters;
2111 _total_free_4k_blocks = (uint32_t)(nFreeBytes / 4096);
2118 Session::get_best_session_directory_for_new_source ()
2120 vector<space_and_path>::iterator i;
2121 string result = _session_dir->root_path();
2123 /* handle common case without system calls */
2125 if (session_dirs.size() == 1) {
2129 /* OK, here's the algorithm we're following here:
2131 We want to select which directory to use for
2132 the next file source to be created. Ideally,
2133 we'd like to use a round-robin process so as to
2134 get maximum performance benefits from splitting
2135 the files across multiple disks.
2137 However, in situations without much diskspace, an
2138 RR approach may end up filling up a filesystem
2139 with new files while others still have space.
2140 Its therefore important to pay some attention to
2141 the freespace in the filesystem holding each
2142 directory as well. However, if we did that by
2143 itself, we'd keep creating new files in the file
2144 system with the most space until it was as full
2145 as all others, thus negating any performance
2146 benefits of this RAID-1 like approach.
2148 So, we use a user-configurable space threshold. If
2149 there are at least 2 filesystems with more than this
2150 much space available, we use RR selection between them.
2151 If not, then we pick the filesystem with the most space.
2153 This gets a good balance between the two
2157 refresh_disk_space ();
2159 int free_enough = 0;
2161 for (i = session_dirs.begin(); i != session_dirs.end(); ++i) {
2162 if ((*i).blocks * 4096 >= Config->get_disk_choice_space_threshold()) {
2167 if (free_enough >= 2) {
2168 /* use RR selection process, ensuring that the one
2172 i = last_rr_session_dir;
2175 if (++i == session_dirs.end()) {
2176 i = session_dirs.begin();
2179 if ((*i).blocks * 4096 >= Config->get_disk_choice_space_threshold()) {
2180 SessionDirectory sdir(i->path);
2181 if (sdir.create ()) {
2183 last_rr_session_dir = i;
2188 } while (i != last_rr_session_dir);
2192 /* pick FS with the most freespace (and that
2193 seems to actually work ...)
2196 vector<space_and_path> sorted;
2197 space_and_path_ascending_cmp cmp;
2199 sorted = session_dirs;
2200 sort (sorted.begin(), sorted.end(), cmp);
2202 for (i = sorted.begin(); i != sorted.end(); ++i) {
2203 SessionDirectory sdir(i->path);
2204 if (sdir.create ()) {
2206 last_rr_session_dir = i;
2216 Session::automation_dir () const
2218 return Glib::build_filename (_path, "automation");
2222 Session::analysis_dir () const
2224 return Glib::build_filename (_path, "analysis");
2228 Session::plugins_dir () const
2230 return Glib::build_filename (_path, "plugins");
2234 Session::externals_dir () const
2236 return Glib::build_filename (_path, "externals");
2240 Session::load_bundles (XMLNode const & node)
2242 XMLNodeList nlist = node.children();
2243 XMLNodeConstIterator niter;
2247 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2248 if ((*niter)->name() == "InputBundle") {
2249 add_bundle (boost::shared_ptr<UserBundle> (new UserBundle (**niter, true)));
2250 } else if ((*niter)->name() == "OutputBundle") {
2251 add_bundle (boost::shared_ptr<UserBundle> (new UserBundle (**niter, false)));
2253 error << string_compose(_("Unknown node \"%1\" found in Bundles list from session file"), (*niter)->name()) << endmsg;
2262 Session::load_route_groups (const XMLNode& node, int version)
2264 XMLNodeList nlist = node.children();
2265 XMLNodeConstIterator niter;
2269 if (version >= 3000) {
2271 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2272 if ((*niter)->name() == "RouteGroup") {
2273 RouteGroup* rg = new RouteGroup (*this, "");
2274 add_route_group (rg);
2275 rg->set_state (**niter, version);
2279 } else if (version < 3000) {
2281 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2282 if ((*niter)->name() == "EditGroup" || (*niter)->name() == "MixGroup") {
2283 RouteGroup* rg = new RouteGroup (*this, "");
2284 add_route_group (rg);
2285 rg->set_state (**niter, version);
2294 Session::auto_save()
2296 save_state (_current_snapshot_name);
2300 state_file_filter (const string &str, void* /*arg*/)
2302 return (str.length() > strlen(statefile_suffix) &&
2303 str.find (statefile_suffix) == (str.length() - strlen (statefile_suffix)));
2307 remove_end(string state)
2309 string statename(state);
2311 string::size_type start,end;
2312 if ((start = statename.find_last_of (G_DIR_SEPARATOR)) != string::npos) {
2313 statename = statename.substr (start+1);
2316 if ((end = statename.rfind(".ardour")) == string::npos) {
2317 end = statename.length();
2320 return string(statename.substr (0, end));
2324 Session::possible_states (string path)
2326 vector<string> states;
2327 find_files_matching_filter (states, path, state_file_filter, 0, false, false);
2329 transform(states.begin(), states.end(), states.begin(), remove_end);
2331 sort (states.begin(), states.end());
2337 Session::possible_states () const
2339 return possible_states(_path);
2343 Session::add_route_group (RouteGroup* g)
2345 _route_groups.push_back (g);
2346 route_group_added (g); /* EMIT SIGNAL */
2348 g->RouteAdded.connect_same_thread (*this, boost::bind (&Session::route_added_to_route_group, this, _1, _2));
2349 g->RouteRemoved.connect_same_thread (*this, boost::bind (&Session::route_removed_from_route_group, this, _1, _2));
2350 g->PropertyChanged.connect_same_thread (*this, boost::bind (&Session::route_group_property_changed, this, g));
2356 Session::remove_route_group (RouteGroup& rg)
2358 list<RouteGroup*>::iterator i;
2360 if ((i = find (_route_groups.begin(), _route_groups.end(), &rg)) != _route_groups.end()) {
2361 _route_groups.erase (i);
2364 route_group_removed (); /* EMIT SIGNAL */
2368 /** Set a new order for our route groups, without adding or removing any.
2369 * @param groups Route group list in the new order.
2372 Session::reorder_route_groups (list<RouteGroup*> groups)
2374 _route_groups = groups;
2376 route_groups_reordered (); /* EMIT SIGNAL */
2382 Session::route_group_by_name (string name)
2384 list<RouteGroup *>::iterator i;
2386 for (i = _route_groups.begin(); i != _route_groups.end(); ++i) {
2387 if ((*i)->name() == name) {
2395 Session::all_route_group() const
2397 return *_all_route_group;
2401 Session::add_commands (vector<Command*> const & cmds)
2403 for (vector<Command*>::const_iterator i = cmds.begin(); i != cmds.end(); ++i) {
2409 Session::begin_reversible_command (const string& name)
2411 begin_reversible_command (g_quark_from_string (name.c_str ()));
2414 /** Begin a reversible command using a GQuark to identify it.
2415 * begin_reversible_command() and commit_reversible_command() calls may be nested,
2416 * but there must be as many begin...()s as there are commit...()s.
2419 Session::begin_reversible_command (GQuark q)
2421 /* If nested begin/commit pairs are used, we create just one UndoTransaction
2422 to hold all the commands that are committed. This keeps the order of
2423 commands correct in the history.
2426 if (_current_trans == 0) {
2427 /* start a new transaction */
2428 assert (_current_trans_quarks.empty ());
2429 _current_trans = new UndoTransaction();
2430 _current_trans->set_name (g_quark_to_string (q));
2433 _current_trans_quarks.push_front (q);
2437 Session::commit_reversible_command (Command *cmd)
2439 assert (_current_trans);
2440 assert (!_current_trans_quarks.empty ());
2445 _current_trans->add_command (cmd);
2448 _current_trans_quarks.pop_front ();
2450 if (!_current_trans_quarks.empty ()) {
2451 /* the transaction we're committing is not the top-level one */
2455 if (_current_trans->empty()) {
2456 /* no commands were added to the transaction, so just get rid of it */
2457 delete _current_trans;
2462 gettimeofday (&now, 0);
2463 _current_trans->set_timestamp (now);
2465 _history.add (_current_trans);
2470 accept_all_audio_files (const string& path, void* /*arg*/)
2472 if (!Glib::file_test (path, Glib::FILE_TEST_IS_REGULAR)) {
2476 if (!AudioFileSource::safe_audio_file_extension (path)) {
2484 accept_all_midi_files (const string& path, void* /*arg*/)
2486 if (!Glib::file_test (path, Glib::FILE_TEST_IS_REGULAR)) {
2490 return ((path.length() > 4 && path.find (".mid") != (path.length() - 4)) ||
2491 (path.length() > 4 && path.find (".smf") != (path.length() - 4)) ||
2492 (path.length() > 5 && path.find (".midi") != (path.length() - 5)));
2496 accept_all_state_files (const string& path, void* /*arg*/)
2498 if (!Glib::file_test (path, Glib::FILE_TEST_IS_REGULAR)) {
2502 return (path.length() > 7 && path.find (".ardour") == (path.length() - 7));
2506 Session::find_all_sources (string path, set<string>& result)
2511 if (!tree.read (path)) {
2515 if ((node = find_named_node (*tree.root(), "Sources")) == 0) {
2520 XMLNodeConstIterator niter;
2522 nlist = node->children();
2526 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2530 if ((prop = (*niter)->property (X_("type"))) == 0) {
2534 DataType type (prop->value());
2536 if ((prop = (*niter)->property (X_("name"))) == 0) {
2540 if (Glib::path_is_absolute (prop->value())) {
2541 /* external file, ignore */
2549 if (FileSource::find (*this, type, prop->value(), true, is_new, chan, found_path)) {
2550 result.insert (found_path);
2558 Session::find_all_sources_across_snapshots (set<string>& result, bool exclude_this_snapshot)
2560 vector<string> state_files;
2562 string this_snapshot_path;
2568 if (ripped[ripped.length()-1] == G_DIR_SEPARATOR) {
2569 ripped = ripped.substr (0, ripped.length() - 1);
2572 find_files_matching_filter (state_files, ripped, accept_all_state_files, (void *) 0, true, true);
2574 if (state_files.empty()) {
2579 this_snapshot_path = _path;
2580 this_snapshot_path += legalize_for_path (_current_snapshot_name);
2581 this_snapshot_path += statefile_suffix;
2583 for (vector<string>::iterator i = state_files.begin(); i != state_files.end(); ++i) {
2585 if (exclude_this_snapshot && *i == this_snapshot_path) {
2589 if (find_all_sources (*i, result) < 0) {
2597 struct RegionCounter {
2598 typedef std::map<PBD::ID,boost::shared_ptr<AudioSource> > AudioSourceList;
2599 AudioSourceList::iterator iter;
2600 boost::shared_ptr<Region> region;
2603 RegionCounter() : count (0) {}
2607 Session::ask_about_playlist_deletion (boost::shared_ptr<Playlist> p)
2609 boost::optional<int> r = AskAboutPlaylistDeletion (p);
2610 return r.get_value_or (1);
2614 Session::cleanup_regions ()
2616 const RegionFactory::RegionMap& regions (RegionFactory::regions());
2618 for (RegionFactory::RegionMap::const_iterator i = regions.begin(); i != regions.end(); ++i) {
2620 uint32_t used = playlists->region_use_count (i->second);
2622 if (used == 0 && !i->second->automatic ()) {
2623 RegionFactory::map_remove (i->second);
2627 /* dump the history list */
2634 Session::cleanup_sources (CleanupReport& rep)
2636 // FIXME: needs adaptation to midi
2638 vector<boost::shared_ptr<Source> > dead_sources;
2641 vector<string> candidates;
2642 vector<string> unused;
2643 set<string> all_sources;
2652 _state_of_the_state = (StateOfTheState) (_state_of_the_state | InCleanup);
2654 /* consider deleting all unused playlists */
2656 if (playlists->maybe_delete_unused (boost::bind (Session::ask_about_playlist_deletion, _1))) {
2661 /* sync the "all regions" property of each playlist with its current state
2664 playlists->sync_all_regions_with_regions ();
2666 /* find all un-used sources */
2671 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ) {
2673 SourceMap::iterator tmp;
2678 /* do not bother with files that are zero size, otherwise we remove the current "nascent"
2682 if (!i->second->used() && (i->second->length(i->second->timeline_position() > 0))) {
2683 dead_sources.push_back (i->second);
2684 i->second->drop_references ();
2690 /* build a list of all the possible audio directories for the session */
2692 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
2693 SessionDirectory sdir ((*i).path);
2694 asp += sdir.sound_path();
2696 audio_path += asp.to_string();
2699 /* build a list of all the possible midi directories for the session */
2701 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
2702 SessionDirectory sdir ((*i).path);
2703 msp += sdir.midi_path();
2705 midi_path += msp.to_string();
2707 find_files_matching_filter (candidates, audio_path, accept_all_audio_files, (void *) 0, true, true);
2708 find_files_matching_filter (candidates, midi_path, accept_all_midi_files, (void *) 0, true, true);
2710 /* find all sources, but don't use this snapshot because the
2711 state file on disk still references sources we may have already
2715 find_all_sources_across_snapshots (all_sources, true);
2717 /* add our current source list
2720 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ) {
2721 boost::shared_ptr<FileSource> fs;
2722 SourceMap::iterator tmp = i;
2725 if ((fs = boost::dynamic_pointer_cast<FileSource> (i->second)) != 0) {
2727 if (!fs->is_stub()) {
2729 if (playlists->source_use_count (fs) != 0) {
2730 all_sources.insert (fs->path());
2733 /* we might not remove this source from disk, because it may be used
2734 by other snapshots, but its not being used in this version
2735 so lets get rid of it now, along with any representative regions
2739 RegionFactory::remove_regions_using_source (i->second);
2748 for (vector<string>::iterator x = candidates.begin(); x != candidates.end(); ++x) {
2753 for (set<string>::iterator i = all_sources.begin(); i != all_sources.end(); ++i) {
2755 tmppath1 = canonical_path (spath);
2756 tmppath2 = canonical_path ((*i));
2758 if (tmppath1 == tmppath2) {
2765 unused.push_back (spath);
2769 /* now try to move all unused files into the "dead" directory(ies) */
2771 for (vector<string>::iterator x = unused.begin(); x != unused.end(); ++x) {
2772 struct stat statbuf;
2776 /* don't move the file across filesystems, just
2777 stick it in the `dead_dir_name' directory
2778 on whichever filesystem it was already on.
2781 if ((*x).find ("/sounds/") != string::npos) {
2783 /* old school, go up 1 level */
2785 newpath = Glib::path_get_dirname (*x); // "sounds"
2786 newpath = Glib::path_get_dirname (newpath); // "session-name"
2790 /* new school, go up 4 levels */
2792 newpath = Glib::path_get_dirname (*x); // "audiofiles" or "midifiles"
2793 newpath = Glib::path_get_dirname (newpath); // "session-name"
2794 newpath = Glib::path_get_dirname (newpath); // "interchange"
2795 newpath = Glib::path_get_dirname (newpath); // "session-dir"
2798 newpath = Glib::build_filename (newpath, dead_dir_name);
2800 if (g_mkdir_with_parents (newpath.c_str(), 0755) < 0) {
2801 error << string_compose(_("Session: cannot create dead file folder \"%1\" (%2)"), newpath, strerror (errno)) << endmsg;
2805 newpath = Glib::build_filename (newpath, Glib::path_get_basename ((*x)));
2807 if (Glib::file_test (newpath, Glib::FILE_TEST_EXISTS)) {
2809 /* the new path already exists, try versioning */
2811 char buf[PATH_MAX+1];
2815 snprintf (buf, sizeof (buf), "%s.%d", newpath.c_str(), version);
2818 while (Glib::file_test (newpath_v.c_str(), Glib::FILE_TEST_EXISTS) && version < 999) {
2819 snprintf (buf, sizeof (buf), "%s.%d", newpath.c_str(), ++version);
2823 if (version == 999) {
2824 error << string_compose (_("there are already 1000 files with names like %1; versioning discontinued"),
2828 newpath = newpath_v;
2833 /* it doesn't exist, or we can't read it or something */
2837 stat ((*x).c_str(), &statbuf);
2839 if (::rename ((*x).c_str(), newpath.c_str()) != 0) {
2840 error << string_compose (_("cannot rename unused file source from %1 to %2 (%3)"),
2841 (*x), newpath, strerror (errno))
2846 /* see if there an easy to find peakfile for this file, and remove it.
2849 string base = basename_nosuffix (*x);
2850 base += "%A"; /* this is what we add for the channel suffix of all native files,
2851 or for the first channel of embedded files. it will miss
2852 some peakfiles for other channels
2854 string peakpath = peak_path (base);
2856 if (Glib::file_test (peakpath.c_str(), Glib::FILE_TEST_EXISTS)) {
2857 if (::g_unlink (peakpath.c_str()) != 0) {
2858 error << string_compose (_("cannot remove peakfile %1 for %2 (%3)"),
2859 peakpath, _path, strerror (errno))
2861 /* try to back out */
2862 ::rename (newpath.c_str(), _path.c_str());
2867 rep.paths.push_back (*x);
2868 rep.space += statbuf.st_size;
2871 /* dump the history list */
2875 /* save state so we don't end up a session file
2876 referring to non-existent sources.
2883 _state_of_the_state = (StateOfTheState) (_state_of_the_state & ~InCleanup);
2889 Session::cleanup_trash_sources (CleanupReport& rep)
2891 // FIXME: needs adaptation for MIDI
2893 vector<space_and_path>::iterator i;
2899 for (i = session_dirs.begin(); i != session_dirs.end(); ++i) {
2901 dead_dir = Glib::build_filename ((*i).path, dead_dir_name);
2903 clear_directory (dead_dir, &rep.space, &rep.paths);
2910 Session::set_dirty ()
2912 bool was_dirty = dirty();
2914 _state_of_the_state = StateOfTheState (_state_of_the_state | Dirty);
2918 DirtyChanged(); /* EMIT SIGNAL */
2924 Session::set_clean ()
2926 bool was_dirty = dirty();
2928 _state_of_the_state = Clean;
2932 DirtyChanged(); /* EMIT SIGNAL */
2937 Session::set_deletion_in_progress ()
2939 _state_of_the_state = StateOfTheState (_state_of_the_state | Deletion);
2943 Session::clear_deletion_in_progress ()
2945 _state_of_the_state = StateOfTheState (_state_of_the_state & (~Deletion));
2949 Session::add_controllable (boost::shared_ptr<Controllable> c)
2951 /* this adds a controllable to the list managed by the Session.
2952 this is a subset of those managed by the Controllable class
2953 itself, and represents the only ones whose state will be saved
2954 as part of the session.
2957 Glib::Threads::Mutex::Lock lm (controllables_lock);
2958 controllables.insert (c);
2961 struct null_deleter { void operator()(void const *) const {} };
2964 Session::remove_controllable (Controllable* c)
2966 if (_state_of_the_state & Deletion) {
2970 Glib::Threads::Mutex::Lock lm (controllables_lock);
2972 Controllables::iterator x = controllables.find (boost::shared_ptr<Controllable>(c, null_deleter()));
2974 if (x != controllables.end()) {
2975 controllables.erase (x);
2979 boost::shared_ptr<Controllable>
2980 Session::controllable_by_id (const PBD::ID& id)
2982 Glib::Threads::Mutex::Lock lm (controllables_lock);
2984 for (Controllables::iterator i = controllables.begin(); i != controllables.end(); ++i) {
2985 if ((*i)->id() == id) {
2990 return boost::shared_ptr<Controllable>();
2993 boost::shared_ptr<Controllable>
2994 Session::controllable_by_descriptor (const ControllableDescriptor& desc)
2996 boost::shared_ptr<Controllable> c;
2997 boost::shared_ptr<Route> r;
2999 switch (desc.top_level_type()) {
3000 case ControllableDescriptor::NamedRoute:
3002 std::string str = desc.top_level_name();
3003 if (str == "master") {
3005 } else if (str == "control" || str == "listen") {
3008 r = route_by_name (desc.top_level_name());
3013 case ControllableDescriptor::RemoteControlID:
3014 r = route_by_remote_id (desc.rid());
3022 switch (desc.subtype()) {
3023 case ControllableDescriptor::Gain:
3024 c = r->gain_control ();
3027 case ControllableDescriptor::Solo:
3028 c = r->solo_control();
3031 case ControllableDescriptor::Mute:
3032 c = r->mute_control();
3035 case ControllableDescriptor::Recenable:
3037 boost::shared_ptr<Track> t = boost::dynamic_pointer_cast<Track>(r);
3040 c = t->rec_enable_control ();
3045 case ControllableDescriptor::PanDirection:
3047 c = r->pannable()->pan_azimuth_control;
3051 case ControllableDescriptor::PanWidth:
3053 c = r->pannable()->pan_width_control;
3057 case ControllableDescriptor::PanElevation:
3059 c = r->pannable()->pan_elevation_control;
3063 case ControllableDescriptor::Balance:
3064 /* XXX simple pan control */
3067 case ControllableDescriptor::PluginParameter:
3069 uint32_t plugin = desc.target (0);
3070 uint32_t parameter_index = desc.target (1);
3072 /* revert to zero based counting */
3078 if (parameter_index > 0) {
3082 boost::shared_ptr<Processor> p = r->nth_plugin (plugin);
3085 c = boost::dynamic_pointer_cast<ARDOUR::AutomationControl>(
3086 p->control(Evoral::Parameter(PluginAutomation, 0, parameter_index)));
3091 case ControllableDescriptor::SendGain:
3093 uint32_t send = desc.target (0);
3095 /* revert to zero-based counting */
3101 boost::shared_ptr<Processor> p = r->nth_send (send);
3104 boost::shared_ptr<Send> s = boost::dynamic_pointer_cast<Send>(p);
3105 boost::shared_ptr<Amp> a = s->amp();
3108 c = s->amp()->gain_control();
3115 /* relax and return a null pointer */
3123 Session::add_instant_xml (XMLNode& node, bool write_to_config)
3126 Stateful::add_instant_xml (node, _path);
3129 if (write_to_config) {
3130 Config->add_instant_xml (node);
3135 Session::instant_xml (const string& node_name)
3137 return Stateful::instant_xml (node_name, _path);
3141 Session::save_history (string snapshot_name)
3149 if (snapshot_name.empty()) {
3150 snapshot_name = _current_snapshot_name;
3153 const string history_filename = legalize_for_path (snapshot_name) + history_suffix;
3154 const string backup_filename = history_filename + backup_suffix;
3155 const std::string xml_path(Glib::build_filename (_session_dir->root_path(), history_filename));
3156 const std::string backup_path(Glib::build_filename (_session_dir->root_path(), backup_filename));
3158 if (Glib::file_test (xml_path, Glib::FILE_TEST_EXISTS)) {
3159 if (::g_rename (xml_path.c_str(), backup_path.c_str()) != 0) {
3160 error << _("could not backup old history file, current history not saved") << endmsg;
3165 if (!Config->get_save_history() || Config->get_saved_history_depth() < 0) {
3169 tree.set_root (&_history.get_state (Config->get_saved_history_depth()));
3171 if (!tree.write (xml_path))
3173 error << string_compose (_("history could not be saved to %1"), xml_path) << endmsg;
3175 if (g_remove (xml_path.c_str()) != 0) {
3176 error << string_compose(_("Could not remove history file at path \"%1\" (%2)"),
3177 xml_path, g_strerror (errno)) << endmsg;
3179 if (::g_rename (backup_path.c_str(), xml_path.c_str()) != 0) {
3180 error << string_compose (_("could not restore history file from backup %1 (%2)"),
3181 backup_path, g_strerror (errno)) << endmsg;
3191 Session::restore_history (string snapshot_name)
3195 if (snapshot_name.empty()) {
3196 snapshot_name = _current_snapshot_name;
3199 const std::string xml_filename = legalize_for_path (snapshot_name) + history_suffix;
3200 const std::string xml_path(Glib::build_filename (_session_dir->root_path(), xml_filename));
3202 info << "Loading history from " << xml_path << endmsg;
3204 if (!Glib::file_test (xml_path, Glib::FILE_TEST_EXISTS)) {
3205 info << string_compose (_("%1: no history file \"%2\" for this session."),
3206 _name, xml_path) << endmsg;
3210 if (!tree.read (xml_path)) {
3211 error << string_compose (_("Could not understand session history file \"%1\""),
3212 xml_path) << endmsg;
3219 for (XMLNodeConstIterator it = tree.root()->children().begin(); it != tree.root()->children().end(); it++) {
3222 UndoTransaction* ut = new UndoTransaction ();
3225 ut->set_name(t->property("name")->value());
3226 stringstream ss(t->property("tv-sec")->value());
3228 ss.str(t->property("tv-usec")->value());
3230 ut->set_timestamp(tv);
3232 for (XMLNodeConstIterator child_it = t->children().begin();
3233 child_it != t->children().end(); child_it++)
3235 XMLNode *n = *child_it;
3238 if (n->name() == "MementoCommand" ||
3239 n->name() == "MementoUndoCommand" ||
3240 n->name() == "MementoRedoCommand") {
3242 if ((c = memento_command_factory(n))) {
3246 } else if (n->name() == "NoteDiffCommand") {
3247 PBD::ID id (n->property("midi-source")->value());
3248 boost::shared_ptr<MidiSource> midi_source =
3249 boost::dynamic_pointer_cast<MidiSource, Source>(source_by_id(id));
3251 ut->add_command (new MidiModel::NoteDiffCommand(midi_source->model(), *n));
3253 error << _("Failed to downcast MidiSource for NoteDiffCommand") << endmsg;
3256 } else if (n->name() == "SysExDiffCommand") {
3258 PBD::ID id (n->property("midi-source")->value());
3259 boost::shared_ptr<MidiSource> midi_source =
3260 boost::dynamic_pointer_cast<MidiSource, Source>(source_by_id(id));
3262 ut->add_command (new MidiModel::SysExDiffCommand (midi_source->model(), *n));
3264 error << _("Failed to downcast MidiSource for SysExDiffCommand") << endmsg;
3267 } else if (n->name() == "PatchChangeDiffCommand") {
3269 PBD::ID id (n->property("midi-source")->value());
3270 boost::shared_ptr<MidiSource> midi_source =
3271 boost::dynamic_pointer_cast<MidiSource, Source>(source_by_id(id));
3273 ut->add_command (new MidiModel::PatchChangeDiffCommand (midi_source->model(), *n));
3275 error << _("Failed to downcast MidiSource for PatchChangeDiffCommand") << endmsg;
3278 } else if (n->name() == "StatefulDiffCommand") {
3279 if ((c = stateful_diff_command_factory (n))) {
3280 ut->add_command (c);
3283 error << string_compose(_("Couldn't figure out how to make a Command out of a %1 XMLNode."), n->name()) << endmsg;
3294 Session::config_changed (std::string p, bool ours)
3300 if (p == "seamless-loop") {
3302 } else if (p == "rf-speed") {
3304 } else if (p == "auto-loop") {
3306 } else if (p == "auto-input") {
3308 if (Config->get_monitoring_model() == HardwareMonitoring && transport_rolling()) {
3309 /* auto-input only makes a difference if we're rolling */
3310 set_track_monitor_input_status (!config.get_auto_input());
3313 } else if (p == "punch-in") {
3317 if ((location = _locations->auto_punch_location()) != 0) {
3319 if (config.get_punch_in ()) {
3320 replace_event (SessionEvent::PunchIn, location->start());
3322 remove_event (location->start(), SessionEvent::PunchIn);
3326 } else if (p == "punch-out") {
3330 if ((location = _locations->auto_punch_location()) != 0) {
3332 if (config.get_punch_out()) {
3333 replace_event (SessionEvent::PunchOut, location->end());
3335 clear_events (SessionEvent::PunchOut);
3339 } else if (p == "edit-mode") {
3341 Glib::Threads::Mutex::Lock lm (playlists->lock);
3343 for (SessionPlaylists::List::iterator i = playlists->playlists.begin(); i != playlists->playlists.end(); ++i) {
3344 (*i)->set_edit_mode (Config->get_edit_mode ());
3347 } else if (p == "use-video-sync") {
3349 waiting_for_sync_offset = config.get_use_video_sync();
3351 } else if (p == "mmc-control") {
3353 //poke_midi_thread ();
3355 } else if (p == "mmc-device-id" || p == "mmc-receive-id" || p == "mmc-receive-device-id") {
3357 _mmc->set_receive_device_id (Config->get_mmc_receive_device_id());
3359 } else if (p == "mmc-send-id" || p == "mmc-send-device-id") {
3361 _mmc->set_send_device_id (Config->get_mmc_send_device_id());
3363 } else if (p == "midi-control") {
3365 //poke_midi_thread ();
3367 } else if (p == "raid-path") {
3369 setup_raid_path (config.get_raid_path());
3371 } else if (p == "timecode-format") {
3375 } else if (p == "video-pullup") {
3379 } else if (p == "seamless-loop") {
3381 if (play_loop && transport_rolling()) {
3382 // to reset diskstreams etc
3383 request_play_loop (true);
3386 } else if (p == "rf-speed") {
3388 cumulative_rf_motion = 0;
3391 } else if (p == "click-sound") {
3393 setup_click_sounds (1);
3395 } else if (p == "click-emphasis-sound") {
3397 setup_click_sounds (-1);
3399 } else if (p == "clicking") {
3401 if (Config->get_clicking()) {
3402 if (_click_io && click_data) { // don't require emphasis data
3409 } else if (p == "click-gain") {
3412 _click_gain->set_gain (Config->get_click_gain(), this);
3415 } else if (p == "send-mtc") {
3417 if (Config->get_send_mtc ()) {
3418 /* mark us ready to send */
3419 next_quarter_frame_to_send = 0;
3422 } else if (p == "send-mmc") {
3424 _mmc->enable_send (Config->get_send_mmc ());
3426 } else if (p == "midi-feedback") {
3428 session_midi_feedback = Config->get_midi_feedback();
3430 } else if (p == "jack-time-master") {
3432 engine().reset_timebase ();
3434 } else if (p == "native-file-header-format") {
3436 if (!first_file_header_format_reset) {
3437 reset_native_file_format ();
3440 first_file_header_format_reset = false;
3442 } else if (p == "native-file-data-format") {
3444 if (!first_file_data_format_reset) {
3445 reset_native_file_format ();
3448 first_file_data_format_reset = false;
3450 } else if (p == "external-sync") {
3451 if (!config.get_external_sync()) {
3452 drop_sync_source ();
3454 switch_to_sync_source (Config->get_sync_source());
3456 } else if (p == "denormal-model") {
3458 } else if (p == "history-depth") {
3459 set_history_depth (Config->get_history_depth());
3460 } else if (p == "remote-model") {
3461 /* XXX DO SOMETHING HERE TO TELL THE GUI THAT WE NEED
3464 } else if (p == "initial-program-change") {
3466 if (_mmc->output_port() && Config->get_initial_program_change() >= 0) {
3469 buf[0] = MIDI::program; // channel zero by default
3470 buf[1] = (Config->get_initial_program_change() & 0x7f);
3472 _mmc->output_port()->midimsg (buf, sizeof (buf), 0);
3474 } else if (p == "solo-mute-override") {
3475 // catch_up_on_solo_mute_override ();
3476 } else if (p == "listen-position" || p == "pfl-position") {
3477 listen_position_changed ();
3478 } else if (p == "solo-control-is-listen-control") {
3479 solo_control_mode_changed ();
3480 } else if (p == "timecode-offset" || p == "timecode-offset-negative") {
3481 last_timecode_valid = false;
3482 } else if (p == "playback-buffer-seconds") {
3483 AudioSource::allocate_working_buffers (frame_rate());
3484 } else if (p == "automation-thinning-factor") {
3485 Evoral::ControlList::set_thinning_factor (Config->get_automation_thinning_factor());
3486 } else if (p == "ltc-source-port") {
3487 reconnect_ltc_input ();
3488 } else if (p == "ltc-sink-port") {
3489 reconnect_ltc_output ();
3490 } else if (p == "timecode-generator-offset") {
3491 ltc_tx_parse_offset();
3498 Session::set_history_depth (uint32_t d)
3500 _history.set_depth (d);
3504 Session::load_diskstreams_2X (XMLNode const & node, int)
3507 XMLNodeConstIterator citer;
3509 clist = node.children();
3511 for (citer = clist.begin(); citer != clist.end(); ++citer) {
3514 /* diskstreams added automatically by DiskstreamCreated handler */
3515 if ((*citer)->name() == "AudioDiskstream" || (*citer)->name() == "DiskStream") {
3516 boost::shared_ptr<AudioDiskstream> dsp (new AudioDiskstream (*this, **citer));
3517 _diskstreams_2X.push_back (dsp);
3519 error << _("Session: unknown diskstream type in XML") << endmsg;
3523 catch (failed_constructor& err) {
3524 error << _("Session: could not load diskstream via XML state") << endmsg;
3532 /** Connect things to the MMC object */
3534 Session::setup_midi_machine_control ()
3536 _mmc = new MIDI::MachineControl;
3537 _mmc->set_ports (_midi_ports->mmc_input_port(), _midi_ports->mmc_output_port());
3539 _mmc->Play.connect_same_thread (*this, boost::bind (&Session::mmc_deferred_play, this, _1));
3540 _mmc->DeferredPlay.connect_same_thread (*this, boost::bind (&Session::mmc_deferred_play, this, _1));
3541 _mmc->Stop.connect_same_thread (*this, boost::bind (&Session::mmc_stop, this, _1));
3542 _mmc->FastForward.connect_same_thread (*this, boost::bind (&Session::mmc_fast_forward, this, _1));
3543 _mmc->Rewind.connect_same_thread (*this, boost::bind (&Session::mmc_rewind, this, _1));
3544 _mmc->Pause.connect_same_thread (*this, boost::bind (&Session::mmc_pause, this, _1));
3545 _mmc->RecordPause.connect_same_thread (*this, boost::bind (&Session::mmc_record_pause, this, _1));
3546 _mmc->RecordStrobe.connect_same_thread (*this, boost::bind (&Session::mmc_record_strobe, this, _1));
3547 _mmc->RecordExit.connect_same_thread (*this, boost::bind (&Session::mmc_record_exit, this, _1));
3548 _mmc->Locate.connect_same_thread (*this, boost::bind (&Session::mmc_locate, this, _1, _2));
3549 _mmc->Step.connect_same_thread (*this, boost::bind (&Session::mmc_step, this, _1, _2));
3550 _mmc->Shuttle.connect_same_thread (*this, boost::bind (&Session::mmc_shuttle, this, _1, _2, _3));
3551 _mmc->TrackRecordStatusChange.connect_same_thread (*this, boost::bind (&Session::mmc_record_enable, this, _1, _2, _3));
3553 /* also handle MIDI SPP because its so common */
3555 _mmc->SPPStart.connect_same_thread (*this, boost::bind (&Session::spp_start, this));
3556 _mmc->SPPContinue.connect_same_thread (*this, boost::bind (&Session::spp_continue, this));
3557 _mmc->SPPStop.connect_same_thread (*this, boost::bind (&Session::spp_stop, this));
3560 boost::shared_ptr<Controllable>
3561 Session::solo_cut_control() const
3563 /* the solo cut control is a bit of an anomaly, at least as of Febrary 2011. There are no other
3564 controls in Ardour that currently get presented to the user in the GUI that require
3565 access as a Controllable and are also NOT owned by some SessionObject (e.g. Route, or MonitorProcessor).
3567 its actually an RCConfiguration parameter, so we use a ProxyControllable to wrap
3568 it up as a Controllable. Changes to the Controllable will just map back to the RCConfiguration
3572 return _solo_cut_control;
3576 Session::rename (const std::string& new_name)
3578 string legal_name = legalize_for_path (new_name);
3584 string const old_sources_root = _session_dir->sources_root();
3589 * interchange subdirectory
3593 * Backup files are left unchanged and not renamed.
3596 /* pass one: not 100% safe check that the new directory names don't
3600 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
3605 /* this is a stupid hack because Glib::path_get_dirname() is
3606 * lexical-only, and so passing it /a/b/c/ gives a different
3607 * result than passing it /a/b/c ...
3610 if (oldstr[oldstr.length()-1] == G_DIR_SEPARATOR) {
3611 oldstr = oldstr.substr (0, oldstr.length() - 1);
3614 string base = Glib::path_get_dirname (oldstr);
3615 string p = Glib::path_get_basename (oldstr);
3617 newstr = Glib::build_filename (base, legal_name);
3619 if (Glib::file_test (newstr, Glib::FILE_TEST_EXISTS)) {
3626 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
3631 /* this is a stupid hack because Glib::path_get_dirname() is
3632 * lexical-only, and so passing it /a/b/c/ gives a different
3633 * result than passing it /a/b/c ...
3636 if (oldstr[oldstr.length()-1] == G_DIR_SEPARATOR) {
3637 oldstr = oldstr.substr (0, oldstr.length() - 1);
3640 string base = Glib::path_get_dirname (oldstr);
3641 string p = Glib::path_get_basename (oldstr);
3643 newstr = Glib::build_filename (base, legal_name);
3645 cerr << "Rename " << oldstr << " => " << newstr << endl;
3647 if (::g_rename (oldstr.c_str(), newstr.c_str()) != 0) {
3648 error << string_compose (_("renaming %s as %2 failed (%3)"), oldstr, newstr, g_strerror (errno)) << endmsg;
3653 (*_session_dir) = newstr;
3658 /* directory below interchange */
3660 v.push_back (newstr);
3661 v.push_back (interchange_dir_name);
3664 oldstr = Glib::build_filename (v);
3667 v.push_back (newstr);
3668 v.push_back (interchange_dir_name);
3669 v.push_back (legal_name);
3671 newstr = Glib::build_filename (v);
3673 cerr << "Rename " << oldstr << " => " << newstr << endl;
3675 if (::g_rename (oldstr.c_str(), newstr.c_str()) != 0) {
3676 error << string_compose (_("renaming %s as %2 failed (%3)"), oldstr, newstr, g_strerror (errno)) << endmsg;
3683 oldstr = Glib::build_filename (newpath, _current_snapshot_name) + statefile_suffix;
3684 newstr= Glib::build_filename (newpath, legal_name) + statefile_suffix;
3686 cerr << "Rename " << oldstr << " => " << newstr << endl;
3688 if (::g_rename (oldstr.c_str(), newstr.c_str()) != 0) {
3689 error << string_compose (_("renaming %s as %2 failed (%3)"), oldstr, newstr, g_strerror (errno)) << endmsg;
3696 oldstr = Glib::build_filename (newpath, _current_snapshot_name) + history_suffix;
3698 if (Glib::file_test (oldstr, Glib::FILE_TEST_EXISTS)) {
3699 newstr = Glib::build_filename (newpath, legal_name) + history_suffix;
3701 cerr << "Rename " << oldstr << " => " << newstr << endl;
3703 if (::g_rename (oldstr.c_str(), newstr.c_str()) != 0) {
3704 error << string_compose (_("renaming %s as %2 failed (%3)"), oldstr, newstr, g_strerror (errno)) << endmsg;
3709 /* update file source paths */
3711 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ++i) {
3712 boost::shared_ptr<FileSource> fs = boost::dynamic_pointer_cast<FileSource> (i->second);
3714 string p = fs->path ();
3715 boost::replace_all (p, old_sources_root, _session_dir->sources_root());
3720 /* remove old name from recent sessions */
3722 remove_recent_sessions (_path);
3725 _current_snapshot_name = new_name;
3728 /* re-add directory separator - reverse hack to oldstr above */
3729 if (_path[_path.length()-1] != G_DIR_SEPARATOR) {
3730 _path += G_DIR_SEPARATOR;
3735 /* save state again to get everything just right */
3737 save_state (_current_snapshot_name);
3740 /* add to recent sessions */
3742 store_recent_sessions (new_name, _path);
3748 Session::get_session_info_from_path (XMLTree& tree, const string& xmlpath)
3750 if (!Glib::file_test (xmlpath, Glib::FILE_TEST_EXISTS)) {
3754 if (!tree.read (xmlpath)) {
3762 Session::get_info_from_path (const string& xmlpath, float& sample_rate, SampleFormat& data_format)
3765 bool found_sr = false;
3766 bool found_data_format = false;
3768 if (get_session_info_from_path (tree, xmlpath)) {
3774 const XMLProperty* prop;
3775 if ((prop = tree.root()->property (X_("sample-rate"))) != 0) {
3776 sample_rate = atoi (prop->value());
3780 const XMLNodeList& children (tree.root()->children());
3781 for (XMLNodeList::const_iterator c = children.begin(); c != children.end(); ++c) {
3782 const XMLNode* child = *c;
3783 if (child->name() == "Config") {
3784 const XMLNodeList& options (child->children());
3785 for (XMLNodeList::const_iterator oc = options.begin(); oc != options.end(); ++oc) {
3786 const XMLNode* option = *oc;
3787 const XMLProperty* name = option->property("name");
3793 if (name->value() == "native-file-data-format") {
3794 const XMLProperty* value = option->property ("value");
3796 SampleFormat fmt = (SampleFormat) string_2_enum (option->property ("value")->value(), fmt);
3798 found_data_format = true;
3804 if (found_data_format) {
3809 return !(found_sr && found_data_format); // zero if they are both found