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);
883 Session::save_default_options ()
885 return config.save_state();
895 Session::get_template()
897 /* if we don't disable rec-enable, diskstreams
898 will believe they need to store their capture
899 sources in their state node.
902 disable_record (false);
908 Session::state (bool full_state)
910 XMLNode* node = new XMLNode("Session");
914 snprintf(buf, sizeof(buf), "%d", CURRENT_SESSION_FILE_VERSION);
915 node->add_property("version", buf);
917 /* store configuration settings */
921 node->add_property ("name", _name);
922 snprintf (buf, sizeof (buf), "%" PRId64, _nominal_frame_rate);
923 node->add_property ("sample-rate", buf);
925 if (session_dirs.size() > 1) {
929 vector<space_and_path>::iterator i = session_dirs.begin();
930 vector<space_and_path>::iterator next;
932 ++i; /* skip the first one */
936 while (i != session_dirs.end()) {
940 if (next != session_dirs.end()) {
941 p += G_SEARCHPATH_SEPARATOR;
950 child = node->add_child ("Path");
951 child->add_content (p);
955 /* save the ID counter */
957 snprintf (buf, sizeof (buf), "%" PRIu64, ID::counter());
958 node->add_property ("id-counter", buf);
960 /* save the event ID counter */
962 snprintf (buf, sizeof (buf), "%d", Evoral::event_id_counter());
963 node->add_property ("event-counter", buf);
965 /* various options */
967 list<XMLNode*> midi_port_nodes = _midi_ports->get_midi_port_states();
968 if (!midi_port_nodes.empty()) {
969 XMLNode* midi_port_stuff = new XMLNode ("MIDIPorts");
970 for (list<XMLNode*>::const_iterator n = midi_port_nodes.begin(); n != midi_port_nodes.end(); ++n) {
971 midi_port_stuff->add_child_nocopy (**n);
973 node->add_child_nocopy (*midi_port_stuff);
976 node->add_child_nocopy (config.get_variables ());
978 node->add_child_nocopy (ARDOUR::SessionMetadata::Metadata()->get_state());
980 child = node->add_child ("Sources");
983 Glib::Threads::Mutex::Lock sl (source_lock);
985 for (SourceMap::iterator siter = sources.begin(); siter != sources.end(); ++siter) {
987 /* Don't save information about non-file Sources, or
988 * about non-destructive file sources that are empty
989 * and unused by any regions.
992 boost::shared_ptr<FileSource> fs;
994 if ((fs = boost::dynamic_pointer_cast<FileSource> (siter->second)) != 0) {
996 if (!fs->destructive()) {
997 if (fs->empty() && !fs->used()) {
1002 child->add_child_nocopy (siter->second->get_state());
1007 child = node->add_child ("Regions");
1010 Glib::Threads::Mutex::Lock rl (region_lock);
1011 const RegionFactory::RegionMap& region_map (RegionFactory::all_regions());
1012 for (RegionFactory::RegionMap::const_iterator i = region_map.begin(); i != region_map.end(); ++i) {
1013 boost::shared_ptr<Region> r = i->second;
1014 /* only store regions not attached to playlists */
1015 if (r->playlist() == 0) {
1016 if (boost::dynamic_pointer_cast<AudioRegion>(r)) {
1017 child->add_child_nocopy ((boost::dynamic_pointer_cast<AudioRegion>(r))->get_basic_state ());
1019 child->add_child_nocopy (r->get_state ());
1024 RegionFactory::CompoundAssociations& cassocs (RegionFactory::compound_associations());
1026 if (!cassocs.empty()) {
1027 XMLNode* ca = node->add_child (X_("CompoundAssociations"));
1029 for (RegionFactory::CompoundAssociations::iterator i = cassocs.begin(); i != cassocs.end(); ++i) {
1031 XMLNode* can = new XMLNode (X_("CompoundAssociation"));
1032 i->first->id().print (buf, sizeof (buf));
1033 can->add_property (X_("copy"), buf);
1034 i->second->id().print (buf, sizeof (buf));
1035 can->add_property (X_("original"), buf);
1036 ca->add_child_nocopy (*can);
1042 node->add_child_nocopy (_locations->get_state());
1044 // for a template, just create a new Locations, populate it
1045 // with the default start and end, and get the state for that.
1046 Locations loc (*this);
1047 Location* range = new Location (*this, 0, 0, _("session"), Location::IsSessionRange);
1048 range->set (max_framepos, 0);
1050 node->add_child_nocopy (loc.get_state());
1053 child = node->add_child ("Bundles");
1055 boost::shared_ptr<BundleList> bundles = _bundles.reader ();
1056 for (BundleList::iterator i = bundles->begin(); i != bundles->end(); ++i) {
1057 boost::shared_ptr<UserBundle> b = boost::dynamic_pointer_cast<UserBundle> (*i);
1059 child->add_child_nocopy (b->get_state());
1064 child = node->add_child ("Routes");
1066 boost::shared_ptr<RouteList> r = routes.reader ();
1068 RoutePublicOrderSorter cmp;
1069 RouteList public_order (*r);
1070 public_order.sort (cmp);
1072 /* the sort should have put control outs first */
1075 assert (_monitor_out == public_order.front());
1078 for (RouteList::iterator i = public_order.begin(); i != public_order.end(); ++i) {
1079 if (!(*i)->is_auditioner()) {
1081 child->add_child_nocopy ((*i)->get_state());
1083 child->add_child_nocopy ((*i)->get_template());
1089 playlists->add_state (node, full_state);
1091 child = node->add_child ("RouteGroups");
1092 for (list<RouteGroup *>::iterator i = _route_groups.begin(); i != _route_groups.end(); ++i) {
1093 child->add_child_nocopy ((*i)->get_state());
1097 XMLNode* gain_child = node->add_child ("Click");
1098 gain_child->add_child_nocopy (_click_io->state (full_state));
1099 gain_child->add_child_nocopy (_click_gain->state (full_state));
1103 XMLNode* ltc_input_child = node->add_child ("LTC-In");
1104 ltc_input_child->add_child_nocopy (_ltc_input->state (full_state));
1108 XMLNode* ltc_output_child = node->add_child ("LTC-Out");
1109 ltc_output_child->add_child_nocopy (_ltc_output->state (full_state));
1112 node->add_child_nocopy (_speakers->get_state());
1113 node->add_child_nocopy (_tempo_map->get_state());
1114 node->add_child_nocopy (get_control_protocol_state());
1117 node->add_child_copy (*_extra_xml);
1124 Session::get_control_protocol_state ()
1126 ControlProtocolManager& cpm (ControlProtocolManager::instance());
1127 return cpm.get_state();
1131 Session::set_state (const XMLNode& node, int version)
1135 const XMLProperty* prop;
1138 _state_of_the_state = StateOfTheState (_state_of_the_state|CannotSave);
1140 if (node.name() != X_("Session")) {
1141 fatal << _("programming error: Session: incorrect XML node sent to set_state()") << endmsg;
1145 if ((prop = node.property ("name")) != 0) {
1146 _name = prop->value ();
1149 if ((prop = node.property (X_("sample-rate"))) != 0) {
1151 _nominal_frame_rate = atoi (prop->value());
1153 if (_nominal_frame_rate != _current_frame_rate) {
1154 boost::optional<int> r = AskAboutSampleRateMismatch (_nominal_frame_rate, _current_frame_rate);
1155 if (r.get_value_or (0)) {
1161 setup_raid_path(_session_dir->root_path());
1163 if ((prop = node.property (X_("id-counter"))) != 0) {
1165 sscanf (prop->value().c_str(), "%" PRIu64, &x);
1166 ID::init_counter (x);
1168 /* old sessions used a timebased counter, so fake
1169 the startup ID counter based on a standard
1174 ID::init_counter (now);
1177 if ((prop = node.property (X_("event-counter"))) != 0) {
1178 Evoral::init_event_id_counter (atoi (prop->value()));
1182 if ((child = find_named_node (node, "MIDIPorts")) != 0) {
1183 _midi_ports->set_midi_port_states (child->children());
1186 IO::disable_connecting ();
1188 Stateful::save_extra_xml (node);
1190 if (((child = find_named_node (node, "Options")) != 0)) { /* old style */
1191 load_options (*child);
1192 } else if ((child = find_named_node (node, "Config")) != 0) { /* new style */
1193 load_options (*child);
1195 error << _("Session: XML state has no options section") << endmsg;
1198 if (version >= 3000) {
1199 if ((child = find_named_node (node, "Metadata")) == 0) {
1200 warning << _("Session: XML state has no metadata section") << endmsg;
1201 } else if ( ARDOUR::SessionMetadata::Metadata()->set_state (*child, version) ) {
1206 if ((child = find_named_node (node, X_("Speakers"))) != 0) {
1207 _speakers->set_state (*child, version);
1210 if ((child = find_named_node (node, "Sources")) == 0) {
1211 error << _("Session: XML state has no sources section") << endmsg;
1213 } else if (load_sources (*child)) {
1217 if ((child = find_named_node (node, "TempoMap")) == 0) {
1218 error << _("Session: XML state has no Tempo Map section") << endmsg;
1220 } else if (_tempo_map->set_state (*child, version)) {
1224 if ((child = find_named_node (node, "Locations")) == 0) {
1225 error << _("Session: XML state has no locations section") << endmsg;
1227 } else if (_locations->set_state (*child, version)) {
1233 if ((location = _locations->auto_loop_location()) != 0) {
1234 set_auto_loop_location (location);
1237 if ((location = _locations->auto_punch_location()) != 0) {
1238 set_auto_punch_location (location);
1241 if ((location = _locations->session_range_location()) != 0) {
1242 delete _session_range_location;
1243 _session_range_location = location;
1246 if (_session_range_location) {
1247 AudioFileSource::set_header_position_offset (_session_range_location->start());
1250 if ((child = find_named_node (node, "Regions")) == 0) {
1251 error << _("Session: XML state has no Regions section") << endmsg;
1253 } else if (load_regions (*child)) {
1257 if ((child = find_named_node (node, "Playlists")) == 0) {
1258 error << _("Session: XML state has no playlists section") << endmsg;
1260 } else if (playlists->load (*this, *child)) {
1264 if ((child = find_named_node (node, "UnusedPlaylists")) == 0) {
1266 } else if (playlists->load_unused (*this, *child)) {
1270 if ((child = find_named_node (node, "CompoundAssociations")) != 0) {
1271 if (load_compounds (*child)) {
1276 if (version >= 3000) {
1277 if ((child = find_named_node (node, "Bundles")) == 0) {
1278 warning << _("Session: XML state has no bundles section") << endmsg;
1281 /* We can't load Bundles yet as they need to be able
1282 to convert from port names to Port objects, which can't happen until
1284 _bundle_xml_node = new XMLNode (*child);
1288 if (version < 3000) {
1289 if ((child = find_named_node (node, X_("DiskStreams"))) == 0) {
1290 error << _("Session: XML state has no diskstreams section") << endmsg;
1292 } else if (load_diskstreams_2X (*child, version)) {
1297 if ((child = find_named_node (node, "Routes")) == 0) {
1298 error << _("Session: XML state has no routes section") << endmsg;
1300 } else if (load_routes (*child, version)) {
1304 /* our diskstreams list is no longer needed as they are now all owned by their Route */
1305 _diskstreams_2X.clear ();
1307 if (version >= 3000) {
1309 if ((child = find_named_node (node, "RouteGroups")) == 0) {
1310 error << _("Session: XML state has no route groups section") << endmsg;
1312 } else if (load_route_groups (*child, version)) {
1316 } else if (version < 3000) {
1318 if ((child = find_named_node (node, "EditGroups")) == 0) {
1319 error << _("Session: XML state has no edit groups section") << endmsg;
1321 } else if (load_route_groups (*child, version)) {
1325 if ((child = find_named_node (node, "MixGroups")) == 0) {
1326 error << _("Session: XML state has no mix groups section") << endmsg;
1328 } else if (load_route_groups (*child, version)) {
1333 if ((child = find_named_node (node, "Click")) == 0) {
1334 warning << _("Session: XML state has no click section") << endmsg;
1335 } else if (_click_io) {
1336 setup_click_state (&node);
1339 if ((child = find_named_node (node, ControlProtocolManager::state_node_name)) != 0) {
1340 ControlProtocolManager::instance().set_state (*child, version);
1343 update_have_rec_enabled_track ();
1345 /* here beginneth the second phase ... */
1347 StateReady (); /* EMIT SIGNAL */
1356 Session::load_routes (const XMLNode& node, int version)
1359 XMLNodeConstIterator niter;
1360 RouteList new_routes;
1362 nlist = node.children();
1366 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1368 boost::shared_ptr<Route> route;
1369 if (version < 3000) {
1370 route = XMLRouteFactory_2X (**niter, version);
1372 route = XMLRouteFactory (**niter, version);
1376 error << _("Session: cannot create Route from XML description.") << endmsg;
1380 BootMessage (string_compose (_("Loaded track/bus %1"), route->name()));
1382 new_routes.push_back (route);
1385 add_routes (new_routes, false, false, false);
1390 boost::shared_ptr<Route>
1391 Session::XMLRouteFactory (const XMLNode& node, int version)
1393 boost::shared_ptr<Route> ret;
1395 if (node.name() != "Route") {
1399 XMLNode* ds_child = find_named_node (node, X_("Diskstream"));
1401 DataType type = DataType::AUDIO;
1402 const XMLProperty* prop = node.property("default-type");
1405 type = DataType (prop->value());
1408 assert (type != DataType::NIL);
1412 boost::shared_ptr<Track> track;
1414 if (type == DataType::AUDIO) {
1415 track.reset (new AudioTrack (*this, X_("toBeResetFroXML")));
1417 track.reset (new MidiTrack (*this, X_("toBeResetFroXML")));
1420 if (track->init()) {
1424 if (track->set_state (node, version)) {
1428 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
1429 // boost_debug_shared_ptr_mark_interesting (track.get(), "Track");
1434 enum Route::Flag flags = Route::Flag(0);
1435 const XMLProperty* prop = node.property("flags");
1437 flags = Route::Flag (string_2_enum (prop->value(), flags));
1440 boost::shared_ptr<Route> r (new Route (*this, X_("toBeResetFroXML"), flags));
1442 if (r->init () == 0 && r->set_state (node, version) == 0) {
1443 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
1444 // boost_debug_shared_ptr_mark_interesting (r.get(), "Route");
1453 boost::shared_ptr<Route>
1454 Session::XMLRouteFactory_2X (const XMLNode& node, int version)
1456 boost::shared_ptr<Route> ret;
1458 if (node.name() != "Route") {
1462 XMLProperty const * ds_prop = node.property (X_("diskstream-id"));
1464 ds_prop = node.property (X_("diskstream"));
1467 DataType type = DataType::AUDIO;
1468 const XMLProperty* prop = node.property("default-type");
1471 type = DataType (prop->value());
1474 assert (type != DataType::NIL);
1478 list<boost::shared_ptr<Diskstream> >::iterator i = _diskstreams_2X.begin ();
1479 while (i != _diskstreams_2X.end() && (*i)->id() != ds_prop->value()) {
1483 if (i == _diskstreams_2X.end()) {
1484 error << _("Could not find diskstream for route") << endmsg;
1485 return boost::shared_ptr<Route> ();
1488 boost::shared_ptr<Track> track;
1490 if (type == DataType::AUDIO) {
1491 track.reset (new AudioTrack (*this, X_("toBeResetFroXML")));
1493 track.reset (new MidiTrack (*this, X_("toBeResetFroXML")));
1496 if (track->init()) {
1500 if (track->set_state (node, version)) {
1504 track->set_diskstream (*i);
1506 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
1507 // boost_debug_shared_ptr_mark_interesting (track.get(), "Track");
1512 enum Route::Flag flags = Route::Flag(0);
1513 const XMLProperty* prop = node.property("flags");
1515 flags = Route::Flag (string_2_enum (prop->value(), flags));
1518 boost::shared_ptr<Route> r (new Route (*this, X_("toBeResetFroXML"), flags));
1520 if (r->init () == 0 && r->set_state (node, version) == 0) {
1521 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
1522 // boost_debug_shared_ptr_mark_interesting (r.get(), "Route");
1532 Session::load_regions (const XMLNode& node)
1535 XMLNodeConstIterator niter;
1536 boost::shared_ptr<Region> region;
1538 nlist = node.children();
1542 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1543 if ((region = XMLRegionFactory (**niter, false)) == 0) {
1544 error << _("Session: cannot create Region from XML description.");
1545 const XMLProperty *name = (**niter).property("name");
1548 error << " " << string_compose (_("Can not load state for region '%1'"), name->value());
1559 Session::load_compounds (const XMLNode& node)
1561 XMLNodeList calist = node.children();
1562 XMLNodeConstIterator caiter;
1563 XMLProperty *caprop;
1565 for (caiter = calist.begin(); caiter != calist.end(); ++caiter) {
1566 XMLNode* ca = *caiter;
1570 if ((caprop = ca->property (X_("original"))) == 0) {
1573 orig_id = caprop->value();
1575 if ((caprop = ca->property (X_("copy"))) == 0) {
1578 copy_id = caprop->value();
1580 boost::shared_ptr<Region> orig = RegionFactory::region_by_id (orig_id);
1581 boost::shared_ptr<Region> copy = RegionFactory::region_by_id (copy_id);
1583 if (!orig || !copy) {
1584 warning << string_compose (_("Regions in compound description not found (ID's %1 and %2): ignored"),
1590 RegionFactory::add_compound_association (orig, copy);
1597 Session::load_nested_sources (const XMLNode& node)
1600 XMLNodeConstIterator niter;
1602 nlist = node.children();
1604 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1605 if ((*niter)->name() == "Source") {
1607 /* it may already exist, so don't recreate it unnecessarily
1610 XMLProperty* prop = (*niter)->property (X_("id"));
1612 error << _("Nested source has no ID info in session file! (ignored)") << endmsg;
1616 ID source_id (prop->value());
1618 if (!source_by_id (source_id)) {
1621 SourceFactory::create (*this, **niter, true);
1623 catch (failed_constructor& err) {
1624 error << string_compose (_("Cannot reconstruct nested source for region %1"), name()) << endmsg;
1631 boost::shared_ptr<Region>
1632 Session::XMLRegionFactory (const XMLNode& node, bool full)
1634 const XMLProperty* type = node.property("type");
1638 const XMLNodeList& nlist = node.children();
1640 for (XMLNodeConstIterator niter = nlist.begin(); niter != nlist.end(); ++niter) {
1641 XMLNode *child = (*niter);
1642 if (child->name() == "NestedSource") {
1643 load_nested_sources (*child);
1647 if (!type || type->value() == "audio") {
1648 return boost::shared_ptr<Region>(XMLAudioRegionFactory (node, full));
1649 } else if (type->value() == "midi") {
1650 return boost::shared_ptr<Region>(XMLMidiRegionFactory (node, full));
1653 } catch (failed_constructor& err) {
1654 return boost::shared_ptr<Region> ();
1657 return boost::shared_ptr<Region> ();
1660 boost::shared_ptr<AudioRegion>
1661 Session::XMLAudioRegionFactory (const XMLNode& node, bool /*full*/)
1663 const XMLProperty* prop;
1664 boost::shared_ptr<Source> source;
1665 boost::shared_ptr<AudioSource> as;
1667 SourceList master_sources;
1668 uint32_t nchans = 1;
1671 if (node.name() != X_("Region")) {
1672 return boost::shared_ptr<AudioRegion>();
1675 if ((prop = node.property (X_("channels"))) != 0) {
1676 nchans = atoi (prop->value().c_str());
1679 if ((prop = node.property ("name")) == 0) {
1680 cerr << "no name for this region\n";
1684 if ((prop = node.property (X_("source-0"))) == 0) {
1685 if ((prop = node.property ("source")) == 0) {
1686 error << _("Session: XMLNode describing a AudioRegion is incomplete (no source)") << endmsg;
1687 return boost::shared_ptr<AudioRegion>();
1691 PBD::ID s_id (prop->value());
1693 if ((source = source_by_id (s_id)) == 0) {
1694 error << string_compose(_("Session: XMLNode describing a AudioRegion references an unknown source id =%1"), s_id) << endmsg;
1695 return boost::shared_ptr<AudioRegion>();
1698 as = boost::dynamic_pointer_cast<AudioSource>(source);
1700 error << string_compose(_("Session: XMLNode describing a AudioRegion references a non-audio source id =%1"), s_id) << endmsg;
1701 return boost::shared_ptr<AudioRegion>();
1704 sources.push_back (as);
1706 /* pickup other channels */
1708 for (uint32_t n=1; n < nchans; ++n) {
1709 snprintf (buf, sizeof(buf), X_("source-%d"), n);
1710 if ((prop = node.property (buf)) != 0) {
1712 PBD::ID id2 (prop->value());
1714 if ((source = source_by_id (id2)) == 0) {
1715 error << string_compose(_("Session: XMLNode describing a AudioRegion references an unknown source id =%1"), id2) << endmsg;
1716 return boost::shared_ptr<AudioRegion>();
1719 as = boost::dynamic_pointer_cast<AudioSource>(source);
1721 error << string_compose(_("Session: XMLNode describing a AudioRegion references a non-audio source id =%1"), id2) << endmsg;
1722 return boost::shared_ptr<AudioRegion>();
1724 sources.push_back (as);
1728 for (uint32_t n = 0; n < nchans; ++n) {
1729 snprintf (buf, sizeof(buf), X_("master-source-%d"), n);
1730 if ((prop = node.property (buf)) != 0) {
1732 PBD::ID id2 (prop->value());
1734 if ((source = source_by_id (id2)) == 0) {
1735 error << string_compose(_("Session: XMLNode describing a AudioRegion references an unknown source id =%1"), id2) << endmsg;
1736 return boost::shared_ptr<AudioRegion>();
1739 as = boost::dynamic_pointer_cast<AudioSource>(source);
1741 error << string_compose(_("Session: XMLNode describing a AudioRegion references a non-audio source id =%1"), id2) << endmsg;
1742 return boost::shared_ptr<AudioRegion>();
1744 master_sources.push_back (as);
1749 boost::shared_ptr<AudioRegion> region (boost::dynamic_pointer_cast<AudioRegion> (RegionFactory::create (sources, node)));
1751 /* a final detail: this is the one and only place that we know how long missing files are */
1753 if (region->whole_file()) {
1754 for (SourceList::iterator sx = sources.begin(); sx != sources.end(); ++sx) {
1755 boost::shared_ptr<SilentFileSource> sfp = boost::dynamic_pointer_cast<SilentFileSource> (*sx);
1757 sfp->set_length (region->length());
1762 if (!master_sources.empty()) {
1763 if (master_sources.size() != nchans) {
1764 error << _("Session: XMLNode describing an AudioRegion is missing some master sources; ignored") << endmsg;
1766 region->set_master_sources (master_sources);
1774 catch (failed_constructor& err) {
1775 return boost::shared_ptr<AudioRegion>();
1779 boost::shared_ptr<MidiRegion>
1780 Session::XMLMidiRegionFactory (const XMLNode& node, bool /*full*/)
1782 const XMLProperty* prop;
1783 boost::shared_ptr<Source> source;
1784 boost::shared_ptr<MidiSource> ms;
1787 if (node.name() != X_("Region")) {
1788 return boost::shared_ptr<MidiRegion>();
1791 if ((prop = node.property ("name")) == 0) {
1792 cerr << "no name for this region\n";
1796 if ((prop = node.property (X_("source-0"))) == 0) {
1797 if ((prop = node.property ("source")) == 0) {
1798 error << _("Session: XMLNode describing a MidiRegion is incomplete (no source)") << endmsg;
1799 return boost::shared_ptr<MidiRegion>();
1803 PBD::ID s_id (prop->value());
1805 if ((source = source_by_id (s_id)) == 0) {
1806 error << string_compose(_("Session: XMLNode describing a MidiRegion references an unknown source id =%1"), s_id) << endmsg;
1807 return boost::shared_ptr<MidiRegion>();
1810 ms = boost::dynamic_pointer_cast<MidiSource>(source);
1812 error << string_compose(_("Session: XMLNode describing a MidiRegion references a non-midi source id =%1"), s_id) << endmsg;
1813 return boost::shared_ptr<MidiRegion>();
1816 sources.push_back (ms);
1819 boost::shared_ptr<MidiRegion> region (boost::dynamic_pointer_cast<MidiRegion> (RegionFactory::create (sources, node)));
1820 /* a final detail: this is the one and only place that we know how long missing files are */
1822 if (region->whole_file()) {
1823 for (SourceList::iterator sx = sources.begin(); sx != sources.end(); ++sx) {
1824 boost::shared_ptr<SilentFileSource> sfp = boost::dynamic_pointer_cast<SilentFileSource> (*sx);
1826 sfp->set_length (region->length());
1834 catch (failed_constructor& err) {
1835 return boost::shared_ptr<MidiRegion>();
1840 Session::get_sources_as_xml ()
1843 XMLNode* node = new XMLNode (X_("Sources"));
1844 Glib::Threads::Mutex::Lock lm (source_lock);
1846 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ++i) {
1847 node->add_child_nocopy (i->second->get_state());
1854 Session::path_from_region_name (DataType type, string name, string identifier)
1856 char buf[PATH_MAX+1];
1858 SessionDirectory sdir(get_best_session_directory_for_new_source());
1859 std::string source_dir = ((type == DataType::AUDIO)
1860 ? sdir.sound_path() : sdir.midi_path());
1862 string ext = native_header_format_extension (config.get_native_file_header_format(), type);
1864 for (n = 0; n < 999999; ++n) {
1865 if (identifier.length()) {
1866 snprintf (buf, sizeof(buf), "%s%s%" PRIu32 "%s", name.c_str(),
1867 identifier.c_str(), n, ext.c_str());
1869 snprintf (buf, sizeof(buf), "%s-%" PRIu32 "%s", name.c_str(),
1873 std::string source_path = Glib::build_filename (source_dir, buf);
1875 if (!Glib::file_test (source_path, Glib::FILE_TEST_EXISTS)) {
1880 error << string_compose (_("cannot create new file from region name \"%1\" with ident = \"%2\": too many existing files with similar names"),
1889 Session::load_sources (const XMLNode& node)
1892 XMLNodeConstIterator niter;
1893 boost::shared_ptr<Source> source;
1895 nlist = node.children();
1899 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1902 if ((source = XMLSourceFactory (**niter)) == 0) {
1903 error << _("Session: cannot create Source from XML description.") << endmsg;
1906 } catch (MissingSource& err) {
1910 if (!no_questions_about_missing_files) {
1911 user_choice = MissingFile (this, err.path, err.type).get_value_or (-1);
1916 switch (user_choice) {
1918 /* user added a new search location, so try again */
1923 /* user asked to quit the entire session load
1928 no_questions_about_missing_files = true;
1932 no_questions_about_missing_files = true;
1937 warning << _("A sound file is missing. It will be replaced by silence.") << endmsg;
1938 source = SourceFactory::createSilent (*this, **niter, max_framecnt, _current_frame_rate);
1947 boost::shared_ptr<Source>
1948 Session::XMLSourceFactory (const XMLNode& node)
1950 if (node.name() != "Source") {
1951 return boost::shared_ptr<Source>();
1955 /* note: do peak building in another thread when loading session state */
1956 return SourceFactory::create (*this, node, true);
1959 catch (failed_constructor& err) {
1960 error << string_compose (_("Found a sound file that cannot be used by %1. Talk to the progammers."), PROGRAM_NAME) << endmsg;
1961 return boost::shared_ptr<Source>();
1966 Session::save_template (string template_name)
1970 if (_state_of_the_state & CannotSave) {
1974 std::string user_template_dir(user_template_directory());
1976 if (g_mkdir_with_parents (user_template_dir.c_str(), 0755) != 0) {
1977 error << string_compose(_("Could not create templates directory \"%1\" (%2)"),
1978 user_template_dir, g_strerror (errno)) << endmsg;
1982 tree.set_root (&get_template());
1984 std::string template_dir_path(user_template_dir);
1986 /* directory to put the template in */
1987 template_dir_path = Glib::build_filename (template_dir_path, template_name);
1989 if (Glib::file_test (template_dir_path, Glib::FILE_TEST_EXISTS)) {
1990 warning << string_compose(_("Template \"%1\" already exists - new version not created"),
1991 template_dir_path) << endmsg;
1995 if (g_mkdir_with_parents (template_dir_path.c_str(), 0755) != 0) {
1996 error << string_compose(_("Could not create directory for Session template\"%1\" (%2)"),
1997 template_dir_path, g_strerror (errno)) << endmsg;
2002 std::string template_file_path(template_dir_path);
2003 template_file_path = Glib::build_filename (template_file_path, template_name + template_suffix);
2005 if (!tree.write (template_file_path)) {
2006 error << _("template not saved") << endmsg;
2010 /* copy plugin state directory */
2012 std::string template_plugin_state_path(template_dir_path);
2013 template_plugin_state_path = Glib::build_filename (template_plugin_state_path, X_("plugins"));
2015 if (g_mkdir_with_parents (template_plugin_state_path.c_str(), 0755) != 0) {
2016 error << string_compose(_("Could not create directory for Session template plugin state\"%1\" (%2)"),
2017 template_plugin_state_path, g_strerror (errno)) << endmsg;
2021 copy_files (plugins_dir(), template_plugin_state_path);
2027 Session::refresh_disk_space ()
2029 #if __APPLE__ || (HAVE_SYS_VFS_H && HAVE_SYS_STATVFS_H)
2031 Glib::Threads::Mutex::Lock lm (space_lock);
2033 /* get freespace on every FS that is part of the session path */
2035 _total_free_4k_blocks = 0;
2036 _total_free_4k_blocks_uncertain = false;
2038 for (vector<space_and_path>::iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
2040 struct statfs statfsbuf;
2041 statfs (i->path.c_str(), &statfsbuf);
2043 double const scale = statfsbuf.f_bsize / 4096.0;
2045 /* See if this filesystem is read-only */
2046 struct statvfs statvfsbuf;
2047 statvfs (i->path.c_str(), &statvfsbuf);
2049 /* f_bavail can be 0 if it is undefined for whatever
2050 filesystem we are looking at; Samba shares mounted
2051 via GVFS are an example of this.
2053 if (statfsbuf.f_bavail == 0) {
2054 /* block count unknown */
2056 i->blocks_unknown = true;
2057 } else if (statvfsbuf.f_flag & ST_RDONLY) {
2058 /* read-only filesystem */
2060 i->blocks_unknown = false;
2062 /* read/write filesystem with known space */
2063 i->blocks = (uint32_t) floor (statfsbuf.f_bavail * scale);
2064 i->blocks_unknown = false;
2067 _total_free_4k_blocks += i->blocks;
2068 if (i->blocks_unknown) {
2069 _total_free_4k_blocks_uncertain = true;
2072 #elif defined (COMPILER_MSVC)
2073 vector<string> scanned_volumes;
2074 vector<string>::iterator j;
2075 vector<space_and_path>::iterator i;
2076 DWORD nSectorsPerCluster, nBytesPerSector,
2077 nFreeClusters, nTotalClusters;
2081 _total_free_4k_blocks = 0;
2083 for (i = session_dirs.begin(); i != session_dirs.end(); i++) {
2084 strncpy (disk_drive, (*i).path.c_str(), 3);
2088 volume_found = false;
2089 if (0 != (GetDiskFreeSpace(disk_drive, &nSectorsPerCluster, &nBytesPerSector, &nFreeClusters, &nTotalClusters)))
2091 int64_t nBytesPerCluster = nBytesPerSector * nSectorsPerCluster;
2092 int64_t nFreeBytes = nBytesPerCluster * (int64_t)nFreeClusters;
2093 i->blocks = (uint32_t)(nFreeBytes / 4096);
2095 for (j = scanned_volumes.begin(); j != scanned_volumes.end(); j++) {
2096 if (0 == j->compare(disk_drive)) {
2097 volume_found = true;
2102 if (!volume_found) {
2103 scanned_volumes.push_back(disk_drive);
2104 _total_free_4k_blocks += i->blocks;
2109 if (0 == _total_free_4k_blocks) {
2110 strncpy (disk_drive, path().c_str(), 3);
2113 if (0 != (GetDiskFreeSpace(disk_drive, &nSectorsPerCluster, &nBytesPerSector, &nFreeClusters, &nTotalClusters)))
2115 int64_t nBytesPerCluster = nBytesPerSector * nSectorsPerCluster;
2116 int64_t nFreeBytes = nBytesPerCluster * (int64_t)nFreeClusters;
2117 _total_free_4k_blocks = (uint32_t)(nFreeBytes / 4096);
2124 Session::get_best_session_directory_for_new_source ()
2126 vector<space_and_path>::iterator i;
2127 string result = _session_dir->root_path();
2129 /* handle common case without system calls */
2131 if (session_dirs.size() == 1) {
2135 /* OK, here's the algorithm we're following here:
2137 We want to select which directory to use for
2138 the next file source to be created. Ideally,
2139 we'd like to use a round-robin process so as to
2140 get maximum performance benefits from splitting
2141 the files across multiple disks.
2143 However, in situations without much diskspace, an
2144 RR approach may end up filling up a filesystem
2145 with new files while others still have space.
2146 Its therefore important to pay some attention to
2147 the freespace in the filesystem holding each
2148 directory as well. However, if we did that by
2149 itself, we'd keep creating new files in the file
2150 system with the most space until it was as full
2151 as all others, thus negating any performance
2152 benefits of this RAID-1 like approach.
2154 So, we use a user-configurable space threshold. If
2155 there are at least 2 filesystems with more than this
2156 much space available, we use RR selection between them.
2157 If not, then we pick the filesystem with the most space.
2159 This gets a good balance between the two
2163 refresh_disk_space ();
2165 int free_enough = 0;
2167 for (i = session_dirs.begin(); i != session_dirs.end(); ++i) {
2168 if ((*i).blocks * 4096 >= Config->get_disk_choice_space_threshold()) {
2173 if (free_enough >= 2) {
2174 /* use RR selection process, ensuring that the one
2178 i = last_rr_session_dir;
2181 if (++i == session_dirs.end()) {
2182 i = session_dirs.begin();
2185 if ((*i).blocks * 4096 >= Config->get_disk_choice_space_threshold()) {
2186 SessionDirectory sdir(i->path);
2187 if (sdir.create ()) {
2189 last_rr_session_dir = i;
2194 } while (i != last_rr_session_dir);
2198 /* pick FS with the most freespace (and that
2199 seems to actually work ...)
2202 vector<space_and_path> sorted;
2203 space_and_path_ascending_cmp cmp;
2205 sorted = session_dirs;
2206 sort (sorted.begin(), sorted.end(), cmp);
2208 for (i = sorted.begin(); i != sorted.end(); ++i) {
2209 SessionDirectory sdir(i->path);
2210 if (sdir.create ()) {
2212 last_rr_session_dir = i;
2222 Session::automation_dir () const
2224 return Glib::build_filename (_path, "automation");
2228 Session::analysis_dir () const
2230 return Glib::build_filename (_path, "analysis");
2234 Session::plugins_dir () const
2236 return Glib::build_filename (_path, "plugins");
2240 Session::externals_dir () const
2242 return Glib::build_filename (_path, "externals");
2246 Session::load_bundles (XMLNode const & node)
2248 XMLNodeList nlist = node.children();
2249 XMLNodeConstIterator niter;
2253 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2254 if ((*niter)->name() == "InputBundle") {
2255 add_bundle (boost::shared_ptr<UserBundle> (new UserBundle (**niter, true)));
2256 } else if ((*niter)->name() == "OutputBundle") {
2257 add_bundle (boost::shared_ptr<UserBundle> (new UserBundle (**niter, false)));
2259 error << string_compose(_("Unknown node \"%1\" found in Bundles list from session file"), (*niter)->name()) << endmsg;
2268 Session::load_route_groups (const XMLNode& node, int version)
2270 XMLNodeList nlist = node.children();
2271 XMLNodeConstIterator niter;
2275 if (version >= 3000) {
2277 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2278 if ((*niter)->name() == "RouteGroup") {
2279 RouteGroup* rg = new RouteGroup (*this, "");
2280 add_route_group (rg);
2281 rg->set_state (**niter, version);
2285 } else if (version < 3000) {
2287 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2288 if ((*niter)->name() == "EditGroup" || (*niter)->name() == "MixGroup") {
2289 RouteGroup* rg = new RouteGroup (*this, "");
2290 add_route_group (rg);
2291 rg->set_state (**niter, version);
2300 Session::auto_save()
2302 save_state (_current_snapshot_name);
2306 state_file_filter (const string &str, void* /*arg*/)
2308 return (str.length() > strlen(statefile_suffix) &&
2309 str.find (statefile_suffix) == (str.length() - strlen (statefile_suffix)));
2313 remove_end(string state)
2315 string statename(state);
2317 string::size_type start,end;
2318 if ((start = statename.find_last_of (G_DIR_SEPARATOR)) != string::npos) {
2319 statename = statename.substr (start+1);
2322 if ((end = statename.rfind(".ardour")) == string::npos) {
2323 end = statename.length();
2326 return string(statename.substr (0, end));
2330 Session::possible_states (string path)
2332 vector<string> states;
2333 find_files_matching_filter (states, path, state_file_filter, 0, false, false);
2335 transform(states.begin(), states.end(), states.begin(), remove_end);
2337 sort (states.begin(), states.end());
2343 Session::possible_states () const
2345 return possible_states(_path);
2349 Session::add_route_group (RouteGroup* g)
2351 _route_groups.push_back (g);
2352 route_group_added (g); /* EMIT SIGNAL */
2354 g->RouteAdded.connect_same_thread (*this, boost::bind (&Session::route_added_to_route_group, this, _1, _2));
2355 g->RouteRemoved.connect_same_thread (*this, boost::bind (&Session::route_removed_from_route_group, this, _1, _2));
2356 g->PropertyChanged.connect_same_thread (*this, boost::bind (&Session::route_group_property_changed, this, g));
2362 Session::remove_route_group (RouteGroup& rg)
2364 list<RouteGroup*>::iterator i;
2366 if ((i = find (_route_groups.begin(), _route_groups.end(), &rg)) != _route_groups.end()) {
2367 _route_groups.erase (i);
2370 route_group_removed (); /* EMIT SIGNAL */
2374 /** Set a new order for our route groups, without adding or removing any.
2375 * @param groups Route group list in the new order.
2378 Session::reorder_route_groups (list<RouteGroup*> groups)
2380 _route_groups = groups;
2382 route_groups_reordered (); /* EMIT SIGNAL */
2388 Session::route_group_by_name (string name)
2390 list<RouteGroup *>::iterator i;
2392 for (i = _route_groups.begin(); i != _route_groups.end(); ++i) {
2393 if ((*i)->name() == name) {
2401 Session::all_route_group() const
2403 return *_all_route_group;
2407 Session::add_commands (vector<Command*> const & cmds)
2409 for (vector<Command*>::const_iterator i = cmds.begin(); i != cmds.end(); ++i) {
2415 Session::begin_reversible_command (const string& name)
2417 begin_reversible_command (g_quark_from_string (name.c_str ()));
2420 /** Begin a reversible command using a GQuark to identify it.
2421 * begin_reversible_command() and commit_reversible_command() calls may be nested,
2422 * but there must be as many begin...()s as there are commit...()s.
2425 Session::begin_reversible_command (GQuark q)
2427 /* If nested begin/commit pairs are used, we create just one UndoTransaction
2428 to hold all the commands that are committed. This keeps the order of
2429 commands correct in the history.
2432 if (_current_trans == 0) {
2433 /* start a new transaction */
2434 assert (_current_trans_quarks.empty ());
2435 _current_trans = new UndoTransaction();
2436 _current_trans->set_name (g_quark_to_string (q));
2439 _current_trans_quarks.push_front (q);
2443 Session::commit_reversible_command (Command *cmd)
2445 assert (_current_trans);
2446 assert (!_current_trans_quarks.empty ());
2451 _current_trans->add_command (cmd);
2454 _current_trans_quarks.pop_front ();
2456 if (!_current_trans_quarks.empty ()) {
2457 /* the transaction we're committing is not the top-level one */
2461 if (_current_trans->empty()) {
2462 /* no commands were added to the transaction, so just get rid of it */
2463 delete _current_trans;
2468 gettimeofday (&now, 0);
2469 _current_trans->set_timestamp (now);
2471 _history.add (_current_trans);
2476 accept_all_audio_files (const string& path, void* /*arg*/)
2478 if (!Glib::file_test (path, Glib::FILE_TEST_IS_REGULAR)) {
2482 if (!AudioFileSource::safe_audio_file_extension (path)) {
2490 accept_all_midi_files (const string& path, void* /*arg*/)
2492 if (!Glib::file_test (path, Glib::FILE_TEST_IS_REGULAR)) {
2496 return ((path.length() > 4 && path.find (".mid") != (path.length() - 4)) ||
2497 (path.length() > 4 && path.find (".smf") != (path.length() - 4)) ||
2498 (path.length() > 5 && path.find (".midi") != (path.length() - 5)));
2502 accept_all_state_files (const string& path, void* /*arg*/)
2504 if (!Glib::file_test (path, Glib::FILE_TEST_IS_REGULAR)) {
2508 return (path.length() > 7 && path.find (".ardour") == (path.length() - 7));
2512 Session::find_all_sources (string path, set<string>& result)
2517 if (!tree.read (path)) {
2521 if ((node = find_named_node (*tree.root(), "Sources")) == 0) {
2526 XMLNodeConstIterator niter;
2528 nlist = node->children();
2532 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2536 if ((prop = (*niter)->property (X_("type"))) == 0) {
2540 DataType type (prop->value());
2542 if ((prop = (*niter)->property (X_("name"))) == 0) {
2546 if (Glib::path_is_absolute (prop->value())) {
2547 /* external file, ignore */
2555 if (FileSource::find (*this, type, prop->value(), true, is_new, chan, found_path)) {
2556 result.insert (found_path);
2564 Session::find_all_sources_across_snapshots (set<string>& result, bool exclude_this_snapshot)
2566 vector<string> state_files;
2568 string this_snapshot_path;
2574 if (ripped[ripped.length()-1] == G_DIR_SEPARATOR) {
2575 ripped = ripped.substr (0, ripped.length() - 1);
2578 find_files_matching_filter (state_files, ripped, accept_all_state_files, (void *) 0, true, true);
2580 if (state_files.empty()) {
2585 this_snapshot_path = _path;
2586 this_snapshot_path += legalize_for_path (_current_snapshot_name);
2587 this_snapshot_path += statefile_suffix;
2589 for (vector<string>::iterator i = state_files.begin(); i != state_files.end(); ++i) {
2591 if (exclude_this_snapshot && *i == this_snapshot_path) {
2595 if (find_all_sources (*i, result) < 0) {
2603 struct RegionCounter {
2604 typedef std::map<PBD::ID,boost::shared_ptr<AudioSource> > AudioSourceList;
2605 AudioSourceList::iterator iter;
2606 boost::shared_ptr<Region> region;
2609 RegionCounter() : count (0) {}
2613 Session::ask_about_playlist_deletion (boost::shared_ptr<Playlist> p)
2615 boost::optional<int> r = AskAboutPlaylistDeletion (p);
2616 return r.get_value_or (1);
2620 Session::cleanup_regions ()
2622 const RegionFactory::RegionMap& regions (RegionFactory::regions());
2624 for (RegionFactory::RegionMap::const_iterator i = regions.begin(); i != regions.end(); ++i) {
2626 uint32_t used = playlists->region_use_count (i->second);
2628 if (used == 0 && !i->second->automatic ()) {
2629 RegionFactory::map_remove (i->second);
2633 /* dump the history list */
2640 Session::cleanup_sources (CleanupReport& rep)
2642 // FIXME: needs adaptation to midi
2644 vector<boost::shared_ptr<Source> > dead_sources;
2647 vector<string> candidates;
2648 vector<string> unused;
2649 set<string> all_sources;
2658 _state_of_the_state = (StateOfTheState) (_state_of_the_state | InCleanup);
2660 /* consider deleting all unused playlists */
2662 if (playlists->maybe_delete_unused (boost::bind (Session::ask_about_playlist_deletion, _1))) {
2667 /* sync the "all regions" property of each playlist with its current state
2670 playlists->sync_all_regions_with_regions ();
2672 /* find all un-used sources */
2677 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ) {
2679 SourceMap::iterator tmp;
2684 /* do not bother with files that are zero size, otherwise we remove the current "nascent"
2688 if (!i->second->used() && (i->second->length(i->second->timeline_position() > 0))) {
2689 dead_sources.push_back (i->second);
2690 i->second->drop_references ();
2696 /* build a list of all the possible audio directories for the session */
2698 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
2699 SessionDirectory sdir ((*i).path);
2700 asp += sdir.sound_path();
2702 audio_path += asp.to_string();
2705 /* build a list of all the possible midi directories for the session */
2707 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
2708 SessionDirectory sdir ((*i).path);
2709 msp += sdir.midi_path();
2711 midi_path += msp.to_string();
2713 find_files_matching_filter (candidates, audio_path, accept_all_audio_files, (void *) 0, true, true);
2714 find_files_matching_filter (candidates, midi_path, accept_all_midi_files, (void *) 0, true, true);
2716 /* find all sources, but don't use this snapshot because the
2717 state file on disk still references sources we may have already
2721 find_all_sources_across_snapshots (all_sources, true);
2723 /* add our current source list
2726 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ) {
2727 boost::shared_ptr<FileSource> fs;
2728 SourceMap::iterator tmp = i;
2731 if ((fs = boost::dynamic_pointer_cast<FileSource> (i->second)) != 0) {
2733 if (!fs->is_stub()) {
2735 if (playlists->source_use_count (fs) != 0) {
2736 all_sources.insert (fs->path());
2739 /* we might not remove this source from disk, because it may be used
2740 by other snapshots, but its not being used in this version
2741 so lets get rid of it now, along with any representative regions
2745 RegionFactory::remove_regions_using_source (i->second);
2754 for (vector<string>::iterator x = candidates.begin(); x != candidates.end(); ++x) {
2759 for (set<string>::iterator i = all_sources.begin(); i != all_sources.end(); ++i) {
2761 tmppath1 = canonical_path (spath);
2762 tmppath2 = canonical_path ((*i));
2764 if (tmppath1 == tmppath2) {
2771 unused.push_back (spath);
2775 /* now try to move all unused files into the "dead" directory(ies) */
2777 for (vector<string>::iterator x = unused.begin(); x != unused.end(); ++x) {
2778 struct stat statbuf;
2782 /* don't move the file across filesystems, just
2783 stick it in the `dead_dir_name' directory
2784 on whichever filesystem it was already on.
2787 if ((*x).find ("/sounds/") != string::npos) {
2789 /* old school, go up 1 level */
2791 newpath = Glib::path_get_dirname (*x); // "sounds"
2792 newpath = Glib::path_get_dirname (newpath); // "session-name"
2796 /* new school, go up 4 levels */
2798 newpath = Glib::path_get_dirname (*x); // "audiofiles" or "midifiles"
2799 newpath = Glib::path_get_dirname (newpath); // "session-name"
2800 newpath = Glib::path_get_dirname (newpath); // "interchange"
2801 newpath = Glib::path_get_dirname (newpath); // "session-dir"
2804 newpath = Glib::build_filename (newpath, dead_dir_name);
2806 if (g_mkdir_with_parents (newpath.c_str(), 0755) < 0) {
2807 error << string_compose(_("Session: cannot create dead file folder \"%1\" (%2)"), newpath, strerror (errno)) << endmsg;
2811 newpath = Glib::build_filename (newpath, Glib::path_get_basename ((*x)));
2813 if (Glib::file_test (newpath, Glib::FILE_TEST_EXISTS)) {
2815 /* the new path already exists, try versioning */
2817 char buf[PATH_MAX+1];
2821 snprintf (buf, sizeof (buf), "%s.%d", newpath.c_str(), version);
2824 while (Glib::file_test (newpath_v.c_str(), Glib::FILE_TEST_EXISTS) && version < 999) {
2825 snprintf (buf, sizeof (buf), "%s.%d", newpath.c_str(), ++version);
2829 if (version == 999) {
2830 error << string_compose (_("there are already 1000 files with names like %1; versioning discontinued"),
2834 newpath = newpath_v;
2839 /* it doesn't exist, or we can't read it or something */
2843 stat ((*x).c_str(), &statbuf);
2845 if (::rename ((*x).c_str(), newpath.c_str()) != 0) {
2846 error << string_compose (_("cannot rename unused file source from %1 to %2 (%3)"),
2847 (*x), newpath, strerror (errno))
2852 /* see if there an easy to find peakfile for this file, and remove it.
2855 string base = basename_nosuffix (*x);
2856 base += "%A"; /* this is what we add for the channel suffix of all native files,
2857 or for the first channel of embedded files. it will miss
2858 some peakfiles for other channels
2860 string peakpath = peak_path (base);
2862 if (Glib::file_test (peakpath.c_str(), Glib::FILE_TEST_EXISTS)) {
2863 if (::g_unlink (peakpath.c_str()) != 0) {
2864 error << string_compose (_("cannot remove peakfile %1 for %2 (%3)"),
2865 peakpath, _path, strerror (errno))
2867 /* try to back out */
2868 ::rename (newpath.c_str(), _path.c_str());
2873 rep.paths.push_back (*x);
2874 rep.space += statbuf.st_size;
2877 /* dump the history list */
2881 /* save state so we don't end up a session file
2882 referring to non-existent sources.
2889 _state_of_the_state = (StateOfTheState) (_state_of_the_state & ~InCleanup);
2895 Session::cleanup_trash_sources (CleanupReport& rep)
2897 // FIXME: needs adaptation for MIDI
2899 vector<space_and_path>::iterator i;
2905 for (i = session_dirs.begin(); i != session_dirs.end(); ++i) {
2907 dead_dir = Glib::build_filename ((*i).path, dead_dir_name);
2909 clear_directory (dead_dir, &rep.space, &rep.paths);
2916 Session::set_dirty ()
2918 bool was_dirty = dirty();
2920 _state_of_the_state = StateOfTheState (_state_of_the_state | Dirty);
2924 DirtyChanged(); /* EMIT SIGNAL */
2930 Session::set_clean ()
2932 bool was_dirty = dirty();
2934 _state_of_the_state = Clean;
2938 DirtyChanged(); /* EMIT SIGNAL */
2943 Session::set_deletion_in_progress ()
2945 _state_of_the_state = StateOfTheState (_state_of_the_state | Deletion);
2949 Session::clear_deletion_in_progress ()
2951 _state_of_the_state = StateOfTheState (_state_of_the_state & (~Deletion));
2955 Session::add_controllable (boost::shared_ptr<Controllable> c)
2957 /* this adds a controllable to the list managed by the Session.
2958 this is a subset of those managed by the Controllable class
2959 itself, and represents the only ones whose state will be saved
2960 as part of the session.
2963 Glib::Threads::Mutex::Lock lm (controllables_lock);
2964 controllables.insert (c);
2967 struct null_deleter { void operator()(void const *) const {} };
2970 Session::remove_controllable (Controllable* c)
2972 if (_state_of_the_state & Deletion) {
2976 Glib::Threads::Mutex::Lock lm (controllables_lock);
2978 Controllables::iterator x = controllables.find (boost::shared_ptr<Controllable>(c, null_deleter()));
2980 if (x != controllables.end()) {
2981 controllables.erase (x);
2985 boost::shared_ptr<Controllable>
2986 Session::controllable_by_id (const PBD::ID& id)
2988 Glib::Threads::Mutex::Lock lm (controllables_lock);
2990 for (Controllables::iterator i = controllables.begin(); i != controllables.end(); ++i) {
2991 if ((*i)->id() == id) {
2996 return boost::shared_ptr<Controllable>();
2999 boost::shared_ptr<Controllable>
3000 Session::controllable_by_descriptor (const ControllableDescriptor& desc)
3002 boost::shared_ptr<Controllable> c;
3003 boost::shared_ptr<Route> r;
3005 switch (desc.top_level_type()) {
3006 case ControllableDescriptor::NamedRoute:
3008 std::string str = desc.top_level_name();
3009 if (str == "master") {
3011 } else if (str == "control" || str == "listen") {
3014 r = route_by_name (desc.top_level_name());
3019 case ControllableDescriptor::RemoteControlID:
3020 r = route_by_remote_id (desc.rid());
3028 switch (desc.subtype()) {
3029 case ControllableDescriptor::Gain:
3030 c = r->gain_control ();
3033 case ControllableDescriptor::Solo:
3034 c = r->solo_control();
3037 case ControllableDescriptor::Mute:
3038 c = r->mute_control();
3041 case ControllableDescriptor::Recenable:
3043 boost::shared_ptr<Track> t = boost::dynamic_pointer_cast<Track>(r);
3046 c = t->rec_enable_control ();
3051 case ControllableDescriptor::PanDirection:
3053 c = r->pannable()->pan_azimuth_control;
3057 case ControllableDescriptor::PanWidth:
3059 c = r->pannable()->pan_width_control;
3063 case ControllableDescriptor::PanElevation:
3065 c = r->pannable()->pan_elevation_control;
3069 case ControllableDescriptor::Balance:
3070 /* XXX simple pan control */
3073 case ControllableDescriptor::PluginParameter:
3075 uint32_t plugin = desc.target (0);
3076 uint32_t parameter_index = desc.target (1);
3078 /* revert to zero based counting */
3084 if (parameter_index > 0) {
3088 boost::shared_ptr<Processor> p = r->nth_plugin (plugin);
3091 c = boost::dynamic_pointer_cast<ARDOUR::AutomationControl>(
3092 p->control(Evoral::Parameter(PluginAutomation, 0, parameter_index)));
3097 case ControllableDescriptor::SendGain:
3099 uint32_t send = desc.target (0);
3101 /* revert to zero-based counting */
3107 boost::shared_ptr<Processor> p = r->nth_send (send);
3110 boost::shared_ptr<Send> s = boost::dynamic_pointer_cast<Send>(p);
3111 boost::shared_ptr<Amp> a = s->amp();
3114 c = s->amp()->gain_control();
3121 /* relax and return a null pointer */
3129 Session::add_instant_xml (XMLNode& node, bool write_to_config)
3132 Stateful::add_instant_xml (node, _path);
3135 if (write_to_config) {
3136 Config->add_instant_xml (node);
3141 Session::instant_xml (const string& node_name)
3143 return Stateful::instant_xml (node_name, _path);
3147 Session::save_history (string snapshot_name)
3155 if (snapshot_name.empty()) {
3156 snapshot_name = _current_snapshot_name;
3159 const string history_filename = legalize_for_path (snapshot_name) + history_suffix;
3160 const string backup_filename = history_filename + backup_suffix;
3161 const std::string xml_path(Glib::build_filename (_session_dir->root_path(), history_filename));
3162 const std::string backup_path(Glib::build_filename (_session_dir->root_path(), backup_filename));
3164 if (Glib::file_test (xml_path, Glib::FILE_TEST_EXISTS)) {
3165 if (::g_rename (xml_path.c_str(), backup_path.c_str()) != 0) {
3166 error << _("could not backup old history file, current history not saved") << endmsg;
3171 if (!Config->get_save_history() || Config->get_saved_history_depth() < 0) {
3175 tree.set_root (&_history.get_state (Config->get_saved_history_depth()));
3177 if (!tree.write (xml_path))
3179 error << string_compose (_("history could not be saved to %1"), xml_path) << endmsg;
3181 if (g_remove (xml_path.c_str()) != 0) {
3182 error << string_compose(_("Could not remove history file at path \"%1\" (%2)"),
3183 xml_path, g_strerror (errno)) << endmsg;
3185 if (::g_rename (backup_path.c_str(), xml_path.c_str()) != 0) {
3186 error << string_compose (_("could not restore history file from backup %1 (%2)"),
3187 backup_path, g_strerror (errno)) << endmsg;
3197 Session::restore_history (string snapshot_name)
3201 if (snapshot_name.empty()) {
3202 snapshot_name = _current_snapshot_name;
3205 const std::string xml_filename = legalize_for_path (snapshot_name) + history_suffix;
3206 const std::string xml_path(Glib::build_filename (_session_dir->root_path(), xml_filename));
3208 info << "Loading history from " << xml_path << endmsg;
3210 if (!Glib::file_test (xml_path, Glib::FILE_TEST_EXISTS)) {
3211 info << string_compose (_("%1: no history file \"%2\" for this session."),
3212 _name, xml_path) << endmsg;
3216 if (!tree.read (xml_path)) {
3217 error << string_compose (_("Could not understand session history file \"%1\""),
3218 xml_path) << endmsg;
3225 for (XMLNodeConstIterator it = tree.root()->children().begin(); it != tree.root()->children().end(); it++) {
3228 UndoTransaction* ut = new UndoTransaction ();
3231 ut->set_name(t->property("name")->value());
3232 stringstream ss(t->property("tv-sec")->value());
3234 ss.str(t->property("tv-usec")->value());
3236 ut->set_timestamp(tv);
3238 for (XMLNodeConstIterator child_it = t->children().begin();
3239 child_it != t->children().end(); child_it++)
3241 XMLNode *n = *child_it;
3244 if (n->name() == "MementoCommand" ||
3245 n->name() == "MementoUndoCommand" ||
3246 n->name() == "MementoRedoCommand") {
3248 if ((c = memento_command_factory(n))) {
3252 } else if (n->name() == "NoteDiffCommand") {
3253 PBD::ID id (n->property("midi-source")->value());
3254 boost::shared_ptr<MidiSource> midi_source =
3255 boost::dynamic_pointer_cast<MidiSource, Source>(source_by_id(id));
3257 ut->add_command (new MidiModel::NoteDiffCommand(midi_source->model(), *n));
3259 error << _("Failed to downcast MidiSource for NoteDiffCommand") << endmsg;
3262 } else if (n->name() == "SysExDiffCommand") {
3264 PBD::ID id (n->property("midi-source")->value());
3265 boost::shared_ptr<MidiSource> midi_source =
3266 boost::dynamic_pointer_cast<MidiSource, Source>(source_by_id(id));
3268 ut->add_command (new MidiModel::SysExDiffCommand (midi_source->model(), *n));
3270 error << _("Failed to downcast MidiSource for SysExDiffCommand") << endmsg;
3273 } else if (n->name() == "PatchChangeDiffCommand") {
3275 PBD::ID id (n->property("midi-source")->value());
3276 boost::shared_ptr<MidiSource> midi_source =
3277 boost::dynamic_pointer_cast<MidiSource, Source>(source_by_id(id));
3279 ut->add_command (new MidiModel::PatchChangeDiffCommand (midi_source->model(), *n));
3281 error << _("Failed to downcast MidiSource for PatchChangeDiffCommand") << endmsg;
3284 } else if (n->name() == "StatefulDiffCommand") {
3285 if ((c = stateful_diff_command_factory (n))) {
3286 ut->add_command (c);
3289 error << string_compose(_("Couldn't figure out how to make a Command out of a %1 XMLNode."), n->name()) << endmsg;
3300 Session::config_changed (std::string p, bool ours)
3306 if (p == "seamless-loop") {
3308 } else if (p == "rf-speed") {
3310 } else if (p == "auto-loop") {
3312 } else if (p == "auto-input") {
3314 if (Config->get_monitoring_model() == HardwareMonitoring && transport_rolling()) {
3315 /* auto-input only makes a difference if we're rolling */
3316 set_track_monitor_input_status (!config.get_auto_input());
3319 } else if (p == "punch-in") {
3323 if ((location = _locations->auto_punch_location()) != 0) {
3325 if (config.get_punch_in ()) {
3326 replace_event (SessionEvent::PunchIn, location->start());
3328 remove_event (location->start(), SessionEvent::PunchIn);
3332 } else if (p == "punch-out") {
3336 if ((location = _locations->auto_punch_location()) != 0) {
3338 if (config.get_punch_out()) {
3339 replace_event (SessionEvent::PunchOut, location->end());
3341 clear_events (SessionEvent::PunchOut);
3345 } else if (p == "edit-mode") {
3347 Glib::Threads::Mutex::Lock lm (playlists->lock);
3349 for (SessionPlaylists::List::iterator i = playlists->playlists.begin(); i != playlists->playlists.end(); ++i) {
3350 (*i)->set_edit_mode (Config->get_edit_mode ());
3353 } else if (p == "use-video-sync") {
3355 waiting_for_sync_offset = config.get_use_video_sync();
3357 } else if (p == "mmc-control") {
3359 //poke_midi_thread ();
3361 } else if (p == "mmc-device-id" || p == "mmc-receive-id" || p == "mmc-receive-device-id") {
3363 _mmc->set_receive_device_id (Config->get_mmc_receive_device_id());
3365 } else if (p == "mmc-send-id" || p == "mmc-send-device-id") {
3367 _mmc->set_send_device_id (Config->get_mmc_send_device_id());
3369 } else if (p == "midi-control") {
3371 //poke_midi_thread ();
3373 } else if (p == "raid-path") {
3375 setup_raid_path (config.get_raid_path());
3377 } else if (p == "timecode-format") {
3381 } else if (p == "video-pullup") {
3385 } else if (p == "seamless-loop") {
3387 if (play_loop && transport_rolling()) {
3388 // to reset diskstreams etc
3389 request_play_loop (true);
3392 } else if (p == "rf-speed") {
3394 cumulative_rf_motion = 0;
3397 } else if (p == "click-sound") {
3399 setup_click_sounds (1);
3401 } else if (p == "click-emphasis-sound") {
3403 setup_click_sounds (-1);
3405 } else if (p == "clicking") {
3407 if (Config->get_clicking()) {
3408 if (_click_io && click_data) { // don't require emphasis data
3415 } else if (p == "click-gain") {
3418 _click_gain->set_gain (Config->get_click_gain(), this);
3421 } else if (p == "send-mtc") {
3423 if (Config->get_send_mtc ()) {
3424 /* mark us ready to send */
3425 next_quarter_frame_to_send = 0;
3428 } else if (p == "send-mmc") {
3430 _mmc->enable_send (Config->get_send_mmc ());
3432 } else if (p == "midi-feedback") {
3434 session_midi_feedback = Config->get_midi_feedback();
3436 } else if (p == "jack-time-master") {
3438 engine().reset_timebase ();
3440 } else if (p == "native-file-header-format") {
3442 if (!first_file_header_format_reset) {
3443 reset_native_file_format ();
3446 first_file_header_format_reset = false;
3448 } else if (p == "native-file-data-format") {
3450 if (!first_file_data_format_reset) {
3451 reset_native_file_format ();
3454 first_file_data_format_reset = false;
3456 } else if (p == "external-sync") {
3457 if (!config.get_external_sync()) {
3458 drop_sync_source ();
3460 switch_to_sync_source (Config->get_sync_source());
3462 } else if (p == "denormal-model") {
3464 } else if (p == "history-depth") {
3465 set_history_depth (Config->get_history_depth());
3466 } else if (p == "remote-model") {
3467 /* XXX DO SOMETHING HERE TO TELL THE GUI THAT WE NEED
3470 } else if (p == "initial-program-change") {
3472 if (_mmc->output_port() && Config->get_initial_program_change() >= 0) {
3475 buf[0] = MIDI::program; // channel zero by default
3476 buf[1] = (Config->get_initial_program_change() & 0x7f);
3478 _mmc->output_port()->midimsg (buf, sizeof (buf), 0);
3480 } else if (p == "solo-mute-override") {
3481 // catch_up_on_solo_mute_override ();
3482 } else if (p == "listen-position" || p == "pfl-position") {
3483 listen_position_changed ();
3484 } else if (p == "solo-control-is-listen-control") {
3485 solo_control_mode_changed ();
3486 } else if (p == "timecode-offset" || p == "timecode-offset-negative") {
3487 last_timecode_valid = false;
3488 } else if (p == "playback-buffer-seconds") {
3489 AudioSource::allocate_working_buffers (frame_rate());
3490 } else if (p == "automation-thinning-factor") {
3491 Evoral::ControlList::set_thinning_factor (Config->get_automation_thinning_factor());
3492 } else if (p == "ltc-source-port") {
3493 reconnect_ltc_input ();
3494 } else if (p == "ltc-sink-port") {
3495 reconnect_ltc_output ();
3496 } else if (p == "timecode-generator-offset") {
3497 ltc_tx_parse_offset();
3504 Session::set_history_depth (uint32_t d)
3506 _history.set_depth (d);
3510 Session::load_diskstreams_2X (XMLNode const & node, int)
3513 XMLNodeConstIterator citer;
3515 clist = node.children();
3517 for (citer = clist.begin(); citer != clist.end(); ++citer) {
3520 /* diskstreams added automatically by DiskstreamCreated handler */
3521 if ((*citer)->name() == "AudioDiskstream" || (*citer)->name() == "DiskStream") {
3522 boost::shared_ptr<AudioDiskstream> dsp (new AudioDiskstream (*this, **citer));
3523 _diskstreams_2X.push_back (dsp);
3525 error << _("Session: unknown diskstream type in XML") << endmsg;
3529 catch (failed_constructor& err) {
3530 error << _("Session: could not load diskstream via XML state") << endmsg;
3538 /** Connect things to the MMC object */
3540 Session::setup_midi_machine_control ()
3542 _mmc = new MIDI::MachineControl;
3543 _mmc->set_ports (_midi_ports->mmc_input_port(), _midi_ports->mmc_output_port());
3545 _mmc->Play.connect_same_thread (*this, boost::bind (&Session::mmc_deferred_play, this, _1));
3546 _mmc->DeferredPlay.connect_same_thread (*this, boost::bind (&Session::mmc_deferred_play, this, _1));
3547 _mmc->Stop.connect_same_thread (*this, boost::bind (&Session::mmc_stop, this, _1));
3548 _mmc->FastForward.connect_same_thread (*this, boost::bind (&Session::mmc_fast_forward, this, _1));
3549 _mmc->Rewind.connect_same_thread (*this, boost::bind (&Session::mmc_rewind, this, _1));
3550 _mmc->Pause.connect_same_thread (*this, boost::bind (&Session::mmc_pause, this, _1));
3551 _mmc->RecordPause.connect_same_thread (*this, boost::bind (&Session::mmc_record_pause, this, _1));
3552 _mmc->RecordStrobe.connect_same_thread (*this, boost::bind (&Session::mmc_record_strobe, this, _1));
3553 _mmc->RecordExit.connect_same_thread (*this, boost::bind (&Session::mmc_record_exit, this, _1));
3554 _mmc->Locate.connect_same_thread (*this, boost::bind (&Session::mmc_locate, this, _1, _2));
3555 _mmc->Step.connect_same_thread (*this, boost::bind (&Session::mmc_step, this, _1, _2));
3556 _mmc->Shuttle.connect_same_thread (*this, boost::bind (&Session::mmc_shuttle, this, _1, _2, _3));
3557 _mmc->TrackRecordStatusChange.connect_same_thread (*this, boost::bind (&Session::mmc_record_enable, this, _1, _2, _3));
3559 /* also handle MIDI SPP because its so common */
3561 _mmc->SPPStart.connect_same_thread (*this, boost::bind (&Session::spp_start, this));
3562 _mmc->SPPContinue.connect_same_thread (*this, boost::bind (&Session::spp_continue, this));
3563 _mmc->SPPStop.connect_same_thread (*this, boost::bind (&Session::spp_stop, this));
3566 boost::shared_ptr<Controllable>
3567 Session::solo_cut_control() const
3569 /* the solo cut control is a bit of an anomaly, at least as of Febrary 2011. There are no other
3570 controls in Ardour that currently get presented to the user in the GUI that require
3571 access as a Controllable and are also NOT owned by some SessionObject (e.g. Route, or MonitorProcessor).
3573 its actually an RCConfiguration parameter, so we use a ProxyControllable to wrap
3574 it up as a Controllable. Changes to the Controllable will just map back to the RCConfiguration
3578 return _solo_cut_control;
3582 Session::rename (const std::string& new_name)
3584 string legal_name = legalize_for_path (new_name);
3590 string const old_sources_root = _session_dir->sources_root();
3595 * interchange subdirectory
3599 * Backup files are left unchanged and not renamed.
3602 /* pass one: not 100% safe check that the new directory names don't
3606 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
3611 /* this is a stupid hack because Glib::path_get_dirname() is
3612 * lexical-only, and so passing it /a/b/c/ gives a different
3613 * result than passing it /a/b/c ...
3616 if (oldstr[oldstr.length()-1] == G_DIR_SEPARATOR) {
3617 oldstr = oldstr.substr (0, oldstr.length() - 1);
3620 string base = Glib::path_get_dirname (oldstr);
3621 string p = Glib::path_get_basename (oldstr);
3623 newstr = Glib::build_filename (base, legal_name);
3625 if (Glib::file_test (newstr, Glib::FILE_TEST_EXISTS)) {
3632 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
3637 /* this is a stupid hack because Glib::path_get_dirname() is
3638 * lexical-only, and so passing it /a/b/c/ gives a different
3639 * result than passing it /a/b/c ...
3642 if (oldstr[oldstr.length()-1] == G_DIR_SEPARATOR) {
3643 oldstr = oldstr.substr (0, oldstr.length() - 1);
3646 string base = Glib::path_get_dirname (oldstr);
3647 string p = Glib::path_get_basename (oldstr);
3649 newstr = Glib::build_filename (base, legal_name);
3651 cerr << "Rename " << oldstr << " => " << newstr << endl;
3653 if (::g_rename (oldstr.c_str(), newstr.c_str()) != 0) {
3654 error << string_compose (_("renaming %s as %2 failed (%3)"), oldstr, newstr, g_strerror (errno)) << endmsg;
3659 (*_session_dir) = newstr;
3664 /* directory below interchange */
3666 v.push_back (newstr);
3667 v.push_back (interchange_dir_name);
3670 oldstr = Glib::build_filename (v);
3673 v.push_back (newstr);
3674 v.push_back (interchange_dir_name);
3675 v.push_back (legal_name);
3677 newstr = Glib::build_filename (v);
3679 cerr << "Rename " << oldstr << " => " << newstr << endl;
3681 if (::g_rename (oldstr.c_str(), newstr.c_str()) != 0) {
3682 error << string_compose (_("renaming %s as %2 failed (%3)"), oldstr, newstr, g_strerror (errno)) << endmsg;
3689 oldstr = Glib::build_filename (newpath, _current_snapshot_name) + statefile_suffix;
3690 newstr= Glib::build_filename (newpath, legal_name) + statefile_suffix;
3692 cerr << "Rename " << oldstr << " => " << newstr << endl;
3694 if (::g_rename (oldstr.c_str(), newstr.c_str()) != 0) {
3695 error << string_compose (_("renaming %s as %2 failed (%3)"), oldstr, newstr, g_strerror (errno)) << endmsg;
3702 oldstr = Glib::build_filename (newpath, _current_snapshot_name) + history_suffix;
3704 if (Glib::file_test (oldstr, Glib::FILE_TEST_EXISTS)) {
3705 newstr = Glib::build_filename (newpath, legal_name) + history_suffix;
3707 cerr << "Rename " << oldstr << " => " << newstr << endl;
3709 if (::g_rename (oldstr.c_str(), newstr.c_str()) != 0) {
3710 error << string_compose (_("renaming %s as %2 failed (%3)"), oldstr, newstr, g_strerror (errno)) << endmsg;
3715 /* update file source paths */
3717 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ++i) {
3718 boost::shared_ptr<FileSource> fs = boost::dynamic_pointer_cast<FileSource> (i->second);
3720 string p = fs->path ();
3721 boost::replace_all (p, old_sources_root, _session_dir->sources_root());
3726 /* remove old name from recent sessions */
3728 remove_recent_sessions (_path);
3731 _current_snapshot_name = new_name;
3734 /* re-add directory separator - reverse hack to oldstr above */
3735 if (_path[_path.length()-1] != G_DIR_SEPARATOR) {
3736 _path += G_DIR_SEPARATOR;
3741 /* save state again to get everything just right */
3743 save_state (_current_snapshot_name);
3746 /* add to recent sessions */
3748 store_recent_sessions (new_name, _path);
3754 Session::get_session_info_from_path (XMLTree& tree, const string& xmlpath)
3756 if (!Glib::file_test (xmlpath, Glib::FILE_TEST_EXISTS)) {
3760 if (!tree.read (xmlpath)) {
3768 Session::get_info_from_path (const string& xmlpath, float& sample_rate, SampleFormat& data_format)
3771 bool found_sr = false;
3772 bool found_data_format = false;
3774 if (get_session_info_from_path (tree, xmlpath)) {
3780 const XMLProperty* prop;
3781 if ((prop = tree.root()->property (X_("sample-rate"))) != 0) {
3782 sample_rate = atoi (prop->value());
3786 const XMLNodeList& children (tree.root()->children());
3787 for (XMLNodeList::const_iterator c = children.begin(); c != children.end(); ++c) {
3788 const XMLNode* child = *c;
3789 if (child->name() == "Config") {
3790 const XMLNodeList& options (child->children());
3791 for (XMLNodeList::const_iterator oc = options.begin(); oc != options.end(); ++oc) {
3792 const XMLNode* option = *oc;
3793 const XMLProperty* name = option->property("name");
3799 if (name->value() == "native-file-data-format") {
3800 const XMLProperty* value = option->property ("value");
3802 SampleFormat fmt = (SampleFormat) string_2_enum (option->property ("value")->value(), fmt);
3804 found_data_format = true;
3810 if (found_data_format) {
3815 return !(found_sr && found_data_format); // zero if they are both found