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/pathscanner.h"
73 #include "pbd/pthread_utils.h"
74 #include "pbd/stacktrace.h"
75 #include "pbd/convert.h"
76 #include "pbd/clear_dir.h"
77 #include "pbd/localtime_r.h"
79 #include "ardour/amp.h"
80 #include "ardour/async_midi_port.h"
81 #include "ardour/audio_diskstream.h"
82 #include "ardour/audio_track.h"
83 #include "ardour/audioengine.h"
84 #include "ardour/audiofilesource.h"
85 #include "ardour/audioregion.h"
86 #include "ardour/automation_control.h"
87 #include "ardour/butler.h"
88 #include "ardour/control_protocol_manager.h"
89 #include "ardour/directory_names.h"
90 #include "ardour/filename_extensions.h"
91 #include "ardour/graph.h"
92 #include "ardour/location.h"
93 #include "ardour/midi_model.h"
94 #include "ardour/midi_patch_manager.h"
95 #include "ardour/midi_region.h"
96 #include "ardour/midi_scene_changer.h"
97 #include "ardour/midi_source.h"
98 #include "ardour/midi_track.h"
99 #include "ardour/pannable.h"
100 #include "ardour/playlist_factory.h"
101 #include "ardour/port.h"
102 #include "ardour/processor.h"
103 #include "ardour/proxy_controllable.h"
104 #include "ardour/recent_sessions.h"
105 #include "ardour/region_factory.h"
106 #include "ardour/route_group.h"
107 #include "ardour/send.h"
108 #include "ardour/session.h"
109 #include "ardour/session_directory.h"
110 #include "ardour/session_metadata.h"
111 #include "ardour/session_playlists.h"
112 #include "ardour/session_state_utils.h"
113 #include "ardour/silentfilesource.h"
114 #include "ardour/sndfilesource.h"
115 #include "ardour/source_factory.h"
116 #include "ardour/speakers.h"
117 #include "ardour/template_utils.h"
118 #include "ardour/tempo.h"
119 #include "ardour/ticker.h"
120 #include "ardour/user_bundle.h"
122 #include "control_protocol/control_protocol.h"
128 using namespace ARDOUR;
132 Session::pre_engine_init (string fullpath)
134 if (fullpath.empty()) {
136 throw failed_constructor();
139 /* discover canonical fullpath */
141 _path = canonical_path(fullpath);
143 /* we require _path to end with a dir separator */
145 if (_path[_path.length()-1] != G_DIR_SEPARATOR) {
146 _path += G_DIR_SEPARATOR;
151 _is_new = !Glib::file_test (_path, Glib::FileTest (G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR));
153 /* finish initialization that can't be done in a normal C++ constructor
157 timerclear (&last_mmc_step);
158 g_atomic_int_set (&processing_prohibited, 0);
159 g_atomic_int_set (&_record_status, Disabled);
160 g_atomic_int_set (&_playback_load, 100);
161 g_atomic_int_set (&_capture_load, 100);
163 _all_route_group->set_active (true, this);
164 interpolation.add_channel_to (0, 0);
166 if (config.get_use_video_sync()) {
167 waiting_for_sync_offset = true;
169 waiting_for_sync_offset = false;
172 last_rr_session_dir = session_dirs.begin();
174 set_history_depth (Config->get_history_depth());
176 /* default: assume simple stereo speaker configuration */
178 _speakers->setup_default_speakers (2);
180 _solo_cut_control.reset (new ProxyControllable (_("solo cut control (dB)"), PBD::Controllable::GainLike,
181 boost::bind (&RCConfiguration::set_solo_mute_gain, Config, _1),
182 boost::bind (&RCConfiguration::get_solo_mute_gain, Config)));
183 add_controllable (_solo_cut_control);
185 /* These are all static "per-class" signals */
187 SourceFactory::SourceCreated.connect_same_thread (*this, boost::bind (&Session::add_source, this, _1));
188 PlaylistFactory::PlaylistCreated.connect_same_thread (*this, boost::bind (&Session::add_playlist, this, _1, _2));
189 AutomationList::AutomationListCreated.connect_same_thread (*this, boost::bind (&Session::add_automation_list, this, _1));
190 Controllable::Destroyed.connect_same_thread (*this, boost::bind (&Session::remove_controllable, this, _1));
191 IO::PortCountChanged.connect_same_thread (*this, boost::bind (&Session::ensure_buffers, this, _1));
193 /* stop IO objects from doing stuff until we're ready for them */
195 Delivery::disable_panners ();
196 IO::disable_connecting ();
198 AudioFileSource::set_peak_dir (_session_dir->peak_path());
202 Session::post_engine_init ()
204 BootMessage (_("Set block size and sample rate"));
206 set_block_size (_engine.samples_per_cycle());
207 set_frame_rate (_engine.sample_rate());
209 BootMessage (_("Using configuration"));
211 _midi_ports = new MidiPortManager;
213 MIDISceneChanger* msc;
215 _scene_changer = msc = new MIDISceneChanger (*this);
216 msc->set_input_port (scene_input_port());
217 msc->set_output_port (scene_out());
219 boost::function<framecnt_t(void)> timer_func (boost::bind (&Session::audible_frame, this));
220 boost::dynamic_pointer_cast<AsyncMIDIPort>(scene_in())->set_timer (timer_func);
222 setup_midi_machine_control ();
224 if (_butler->start_thread()) {
228 if (start_midi_thread ()) {
232 setup_click_sounds (0);
233 setup_midi_control ();
235 _engine.Halted.connect_same_thread (*this, boost::bind (&Session::engine_halted, this));
236 _engine.Xrun.connect_same_thread (*this, boost::bind (&Session::xrun_recovery, this));
239 /* tempo map requires sample rate knowledge */
241 _tempo_map = new TempoMap (_current_frame_rate);
242 _tempo_map->PropertyChanged.connect_same_thread (*this, boost::bind (&Session::tempo_map_changed, this, _1));
244 /* MidiClock requires a tempo map */
246 midi_clock = new MidiClockTicker ();
247 midi_clock->set_session (this);
249 /* crossfades require sample rate knowledge */
251 SndFileSource::setup_standard_crossfades (*this, frame_rate());
252 _engine.GraphReordered.connect_same_thread (*this, boost::bind (&Session::graph_reordered, this));
254 AudioDiskstream::allocate_working_buffers();
255 refresh_disk_space ();
257 /* we're finally ready to call set_state() ... all objects have
258 * been created, the engine is running.
262 if (set_state (*state_tree->root(), Stateful::loading_state_version)) {
266 // set_state() will call setup_raid_path(), but if it's a new session we need
267 // to call setup_raid_path() here.
268 setup_raid_path (_path);
273 boost::function<void (std::string)> ff (boost::bind (&Session::config_changed, this, _1, false));
274 boost::function<void (std::string)> ft (boost::bind (&Session::config_changed, this, _1, true));
276 Config->map_parameters (ff);
277 config.map_parameters (ft);
279 /* Reset all panners */
281 Delivery::reset_panners ();
283 /* this will cause the CPM to instantiate any protocols that are in use
284 * (or mandatory), which will pass it this Session, and then call
285 * set_state() on each instantiated protocol to match stored state.
288 ControlProtocolManager::instance().set_session (this);
290 /* This must be done after the ControlProtocolManager set_session above,
291 as it will set states for ports which the ControlProtocolManager creates.
294 // XXX set state of MIDI::Port's
295 // MidiPortManager::instance()->set_port_states (Config->midi_port_states ());
297 /* And this must be done after the MIDI::Manager::set_port_states as
298 * it will try to make connections whose details are loaded by set_port_states.
303 /* Let control protocols know that we are now all connected, so they
304 * could start talking to surfaces if they want to.
307 ControlProtocolManager::instance().midi_connectivity_established ();
309 if (_is_new && !no_auto_connect()) {
310 Glib::Threads::Mutex::Lock lm (AudioEngine::instance()->process_lock());
311 auto_connect_master_bus ();
314 _state_of_the_state = StateOfTheState (_state_of_the_state & ~(CannotSave|Dirty));
316 /* update latencies */
318 initialize_latencies ();
320 _locations->changed.connect_same_thread (*this, boost::bind (&Session::locations_changed, this));
321 _locations->added.connect_same_thread (*this, boost::bind (&Session::locations_added, this, _1));
323 } catch (AudioEngine::PortRegistrationFailure& err) {
324 /* handle this one in a different way than all others, so that its clear what happened */
325 error << err.what() << endmsg;
331 BootMessage (_("Reset Remote Controls"));
333 // send_full_time_code (0);
334 _engine.transport_locate (0);
336 _mmc->send (MIDI::MachineControlCommand (MIDI::MachineControl::cmdMmcReset));
337 _mmc->send (MIDI::MachineControlCommand (Timecode::Time ()));
339 MIDI::Name::MidiPatchManager::instance().set_session (this);
342 /* initial program change will be delivered later; see ::config_changed() */
344 _state_of_the_state = Clean;
346 Port::set_connecting_blocked (false);
348 DirtyChanged (); /* EMIT SIGNAL */
352 } else if (state_was_pending) {
354 remove_pending_capture_state ();
355 state_was_pending = false;
362 Session::raid_path () const
364 Searchpath raid_search_path;
366 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
367 raid_search_path += (*i).path;
370 return raid_search_path.to_string ();
374 Session::setup_raid_path (string path)
383 session_dirs.clear ();
385 Searchpath search_path(path);
386 Searchpath sound_search_path;
387 Searchpath midi_search_path;
389 for (Searchpath::const_iterator i = search_path.begin(); i != search_path.end(); ++i) {
391 sp.blocks = 0; // not needed
392 session_dirs.push_back (sp);
394 SessionDirectory sdir(sp.path);
396 sound_search_path += sdir.sound_path ();
397 midi_search_path += sdir.midi_path ();
400 // reset the round-robin soundfile path thingie
401 last_rr_session_dir = session_dirs.begin();
405 Session::path_is_within_session (const std::string& path)
407 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
408 if (PBD::path_is_within (i->path, path)) {
416 Session::ensure_subdirs ()
420 dir = session_directory().peak_path();
422 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
423 error << string_compose(_("Session: cannot create session peakfile folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
427 dir = session_directory().sound_path();
429 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
430 error << string_compose(_("Session: cannot create session sounds dir \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
434 dir = session_directory().midi_path();
436 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
437 error << string_compose(_("Session: cannot create session midi dir \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
441 dir = session_directory().dead_path();
443 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
444 error << string_compose(_("Session: cannot create session dead sounds folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
448 dir = session_directory().export_path();
450 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
451 error << string_compose(_("Session: cannot create session export folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
455 dir = analysis_dir ();
457 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
458 error << string_compose(_("Session: cannot create session analysis folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
462 dir = plugins_dir ();
464 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
465 error << string_compose(_("Session: cannot create session plugins folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
469 dir = externals_dir ();
471 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
472 error << string_compose(_("Session: cannot create session externals folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
479 /** @param session_template directory containing session template, or empty.
480 * Caller must not hold process lock.
483 Session::create (const string& session_template, BusProfile* bus_profile)
485 if (g_mkdir_with_parents (_path.c_str(), 0755) < 0) {
486 error << string_compose(_("Session: cannot create session folder \"%1\" (%2)"), _path, strerror (errno)) << endmsg;
490 if (ensure_subdirs ()) {
494 _writable = exists_and_writable (_path);
496 if (!session_template.empty()) {
497 std::string in_path = session_template_dir_to_file (session_template);
499 ifstream in(in_path.c_str());
502 /* no need to call legalize_for_path() since the string
503 * in session_template is already a legal path name
505 string out_path = Glib::build_filename (_session_dir->root_path(), _name + statefile_suffix);
507 ofstream out(out_path.c_str());
513 /* Copy plugin state files from template to new session */
514 std::string template_plugins = Glib::build_filename (session_template, X_("plugins"));
515 copy_files (template_plugins, plugins_dir ());
520 error << string_compose (_("Could not open %1 for writing session template"), out_path)
526 error << string_compose (_("Could not open session template %1 for reading"), in_path)
533 /* set initial start + end point */
535 _state_of_the_state = Clean;
537 /* set up Master Out and Control Out if necessary */
542 ChanCount count(DataType::AUDIO, bus_profile->master_out_channels);
544 if (bus_profile->master_out_channels) {
545 boost::shared_ptr<Route> r (new Route (*this, _("master"), Route::MasterOut, DataType::AUDIO));
549 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
550 // boost_debug_shared_ptr_mark_interesting (r.get(), "Route");
553 Glib::Threads::Mutex::Lock lm (AudioEngine::instance()->process_lock ());
554 r->input()->ensure_io (count, false, this);
555 r->output()->ensure_io (count, false, this);
561 /* prohibit auto-connect to master, because there isn't one */
562 bus_profile->output_ac = AutoConnectOption (bus_profile->output_ac & ~AutoConnectMaster);
566 add_routes (rl, false, false, false);
569 /* this allows the user to override settings with an environment variable.
572 if (no_auto_connect()) {
573 bus_profile->input_ac = AutoConnectOption (0);
574 bus_profile->output_ac = AutoConnectOption (0);
577 Config->set_input_auto_connect (bus_profile->input_ac);
578 Config->set_output_auto_connect (bus_profile->output_ac);
581 if (Config->get_use_monitor_bus() && bus_profile) {
582 add_monitor_section ();
589 Session::maybe_write_autosave()
591 if (dirty() && record_status() != Recording) {
592 save_state("", true);
597 Session::remove_pending_capture_state ()
599 std::string pending_state_file_path(_session_dir->root_path());
601 pending_state_file_path = Glib::build_filename (pending_state_file_path, legalize_for_path (_current_snapshot_name) + pending_suffix);
603 if (!Glib::file_test (pending_state_file_path, Glib::FILE_TEST_EXISTS)) return;
605 if (g_remove (pending_state_file_path.c_str()) != 0) {
606 error << string_compose(_("Could not remove pending capture state at path \"%1\" (%2)"),
607 pending_state_file_path, g_strerror (errno)) << endmsg;
611 /** Rename a state file.
612 * @param old_name Old snapshot name.
613 * @param new_name New snapshot name.
616 Session::rename_state (string old_name, string new_name)
618 if (old_name == _current_snapshot_name || old_name == _name) {
619 /* refuse to rename the current snapshot or the "main" one */
623 const string old_xml_filename = legalize_for_path (old_name) + statefile_suffix;
624 const string new_xml_filename = legalize_for_path (new_name) + statefile_suffix;
626 const std::string old_xml_path(Glib::build_filename (_session_dir->root_path(), old_xml_filename));
627 const std::string new_xml_path(Glib::build_filename (_session_dir->root_path(), new_xml_filename));
629 if (::g_rename (old_xml_path.c_str(), new_xml_path.c_str()) != 0) {
630 error << string_compose(_("could not rename snapshot %1 to %2 (%3)"),
631 old_name, new_name, g_strerror(errno)) << endmsg;
635 /** Remove a state file.
636 * @param snapshot_name Snapshot name.
639 Session::remove_state (string snapshot_name)
641 if (!_writable || snapshot_name == _current_snapshot_name || snapshot_name == _name) {
642 // refuse to remove the current snapshot or the "main" one
646 std::string xml_path(_session_dir->root_path());
648 xml_path = Glib::build_filename (xml_path, legalize_for_path (snapshot_name) + statefile_suffix);
650 if (!create_backup_file (xml_path)) {
651 // don't remove it if a backup can't be made
652 // create_backup_file will log the error.
657 if (g_remove (xml_path.c_str()) != 0) {
658 error << string_compose(_("Could not remove session file at path \"%1\" (%2)"),
659 xml_path, g_strerror (errno)) << endmsg;
663 /** @param snapshot_name Name to save under, without .ardour / .pending prefix */
665 Session::save_state (string snapshot_name, bool pending, bool switch_to_snapshot)
668 std::string xml_path(_session_dir->root_path());
670 if (!_writable || (_state_of_the_state & CannotSave)) {
674 if (!_engine.connected ()) {
675 error << string_compose (_("the %1 audio engine is not connected and state saving would lose all I/O connections. Session not saved"),
681 /* tell sources we're saving first, in case they write out to a new file
682 * which should be saved with the state rather than the old one */
683 for (SourceMap::const_iterator i = sources.begin(); i != sources.end(); ++i) {
685 i->second->session_saved();
686 } catch (Evoral::SMF::FileError& e) {
687 error << string_compose ("Could not write to MIDI file %1; MIDI data not saved.", e.file_name ()) << endmsg;
691 SaveSession (); /* EMIT SIGNAL */
693 tree.set_root (&get_state());
695 if (snapshot_name.empty()) {
696 snapshot_name = _current_snapshot_name;
697 } else if (switch_to_snapshot) {
698 _current_snapshot_name = snapshot_name;
703 /* proper save: use statefile_suffix (.ardour in English) */
705 xml_path = Glib::build_filename (xml_path, legalize_for_path (snapshot_name) + statefile_suffix);
707 /* make a backup copy of the old file */
709 if (Glib::file_test (xml_path, Glib::FILE_TEST_EXISTS) && !create_backup_file (xml_path)) {
710 // create_backup_file will log the error
716 /* pending save: use pending_suffix (.pending in English) */
717 xml_path = Glib::build_filename (xml_path, legalize_for_path (snapshot_name) + pending_suffix);
720 std::string tmp_path(_session_dir->root_path());
721 tmp_path = Glib::build_filename (tmp_path, legalize_for_path (snapshot_name) + temp_suffix);
723 // cerr << "actually writing state to " << xml_path << endl;
725 if (!tree.write (tmp_path)) {
726 error << string_compose (_("state could not be saved to %1"), tmp_path) << endmsg;
727 if (g_remove (tmp_path.c_str()) != 0) {
728 error << string_compose(_("Could not remove temporary session file at path \"%1\" (%2)"),
729 tmp_path, g_strerror (errno)) << endmsg;
735 if (::g_rename (tmp_path.c_str(), xml_path.c_str()) != 0) {
736 error << string_compose (_("could not rename temporary session file %1 to %2 (%3)"),
737 tmp_path, xml_path, g_strerror(errno)) << endmsg;
738 if (g_remove (tmp_path.c_str()) != 0) {
739 error << string_compose(_("Could not remove temporary session file at path \"%1\" (%2)"),
740 tmp_path, g_strerror (errno)) << endmsg;
748 save_history (snapshot_name);
750 bool was_dirty = dirty();
752 _state_of_the_state = StateOfTheState (_state_of_the_state & ~Dirty);
755 DirtyChanged (); /* EMIT SIGNAL */
758 StateSaved (snapshot_name); /* EMIT SIGNAL */
765 Session::restore_state (string snapshot_name)
767 if (load_state (snapshot_name) == 0) {
768 set_state (*state_tree->root(), Stateful::loading_state_version);
775 Session::load_state (string snapshot_name)
780 state_was_pending = false;
782 /* check for leftover pending state from a crashed capture attempt */
784 std::string xmlpath(_session_dir->root_path());
785 xmlpath = Glib::build_filename (xmlpath, legalize_for_path (snapshot_name) + pending_suffix);
787 if (Glib::file_test (xmlpath, Glib::FILE_TEST_EXISTS)) {
789 /* there is pending state from a crashed capture attempt */
791 boost::optional<int> r = AskAboutPendingState();
792 if (r.get_value_or (1)) {
793 state_was_pending = true;
797 if (!state_was_pending) {
798 xmlpath = Glib::build_filename (_session_dir->root_path(), snapshot_name);
801 if (!Glib::file_test (xmlpath, Glib::FILE_TEST_EXISTS)) {
802 xmlpath = Glib::build_filename (_session_dir->root_path(), legalize_for_path (snapshot_name) + statefile_suffix);
803 if (!Glib::file_test (xmlpath, Glib::FILE_TEST_EXISTS)) {
804 error << string_compose(_("%1: session file \"%2\" doesn't exist!"), _name, xmlpath) << endmsg;
809 state_tree = new XMLTree;
813 _writable = exists_and_writable (xmlpath) && exists_and_writable(Glib::path_get_dirname(xmlpath));
815 if (!state_tree->read (xmlpath)) {
816 error << string_compose(_("Could not understand session file %1"), xmlpath) << endmsg;
822 XMLNode& root (*state_tree->root());
824 if (root.name() != X_("Session")) {
825 error << string_compose (_("Session file %1 is not a session"), xmlpath) << endmsg;
831 const XMLProperty* prop;
833 if ((prop = root.property ("version")) == 0) {
834 /* no version implies very old version of Ardour */
835 Stateful::loading_state_version = 1000;
837 if (prop->value().find ('.') != string::npos) {
838 /* old school version format */
839 if (prop->value()[0] == '2') {
840 Stateful::loading_state_version = 2000;
842 Stateful::loading_state_version = 3000;
845 Stateful::loading_state_version = atoi (prop->value());
849 if (Stateful::loading_state_version < CURRENT_SESSION_FILE_VERSION && _writable) {
851 std::string backup_path(_session_dir->root_path());
852 std::string backup_filename = string_compose ("%1-%2%3", legalize_for_path (snapshot_name), Stateful::loading_state_version, statefile_suffix);
853 backup_path = Glib::build_filename (backup_path, backup_filename);
855 // only create a backup for a given statefile version once
857 if (!Glib::file_test (backup_path, Glib::FILE_TEST_EXISTS)) {
859 VersionMismatch (xmlpath, backup_path);
861 if (!copy_file (xmlpath, backup_path)) {;
871 Session::load_options (const XMLNode& node)
873 LocaleGuard lg (X_("POSIX"));
874 config.set_variables (node);
885 Session::get_template()
887 /* if we don't disable rec-enable, diskstreams
888 will believe they need to store their capture
889 sources in their state node.
892 disable_record (false);
898 Session::state (bool full_state)
900 XMLNode* node = new XMLNode("Session");
904 snprintf(buf, sizeof(buf), "%d", CURRENT_SESSION_FILE_VERSION);
905 node->add_property("version", buf);
907 /* store configuration settings */
911 node->add_property ("name", _name);
912 snprintf (buf, sizeof (buf), "%" PRId64, _nominal_frame_rate);
913 node->add_property ("sample-rate", buf);
915 if (session_dirs.size() > 1) {
919 vector<space_and_path>::iterator i = session_dirs.begin();
920 vector<space_and_path>::iterator next;
922 ++i; /* skip the first one */
926 while (i != session_dirs.end()) {
930 if (next != session_dirs.end()) {
931 p += G_SEARCHPATH_SEPARATOR;
940 child = node->add_child ("Path");
941 child->add_content (p);
945 /* save the ID counter */
947 snprintf (buf, sizeof (buf), "%" PRIu64, ID::counter());
948 node->add_property ("id-counter", buf);
950 /* save the event ID counter */
952 snprintf (buf, sizeof (buf), "%d", Evoral::event_id_counter());
953 node->add_property ("event-counter", buf);
955 /* various options */
957 list<XMLNode*> midi_port_nodes = _midi_ports->get_midi_port_states();
958 if (!midi_port_nodes.empty()) {
959 XMLNode* midi_port_stuff = new XMLNode ("MIDIPorts");
960 for (list<XMLNode*>::const_iterator n = midi_port_nodes.begin(); n != midi_port_nodes.end(); ++n) {
961 midi_port_stuff->add_child_nocopy (**n);
963 node->add_child_nocopy (*midi_port_stuff);
966 node->add_child_nocopy (config.get_variables ());
968 node->add_child_nocopy (ARDOUR::SessionMetadata::Metadata()->get_state());
970 child = node->add_child ("Sources");
973 Glib::Threads::Mutex::Lock sl (source_lock);
975 for (SourceMap::iterator siter = sources.begin(); siter != sources.end(); ++siter) {
977 /* Don't save information about non-file Sources, or
978 * about non-destructive file sources that are empty
979 * and unused by any regions.
982 boost::shared_ptr<FileSource> fs;
984 if ((fs = boost::dynamic_pointer_cast<FileSource> (siter->second)) != 0) {
986 if (!fs->destructive()) {
987 if (fs->empty() && !fs->used()) {
992 child->add_child_nocopy (siter->second->get_state());
997 child = node->add_child ("Regions");
1000 Glib::Threads::Mutex::Lock rl (region_lock);
1001 const RegionFactory::RegionMap& region_map (RegionFactory::all_regions());
1002 for (RegionFactory::RegionMap::const_iterator i = region_map.begin(); i != region_map.end(); ++i) {
1003 boost::shared_ptr<Region> r = i->second;
1004 /* only store regions not attached to playlists */
1005 if (r->playlist() == 0) {
1006 if (boost::dynamic_pointer_cast<AudioRegion>(r)) {
1007 child->add_child_nocopy ((boost::dynamic_pointer_cast<AudioRegion>(r))->get_basic_state ());
1009 child->add_child_nocopy (r->get_state ());
1014 RegionFactory::CompoundAssociations& cassocs (RegionFactory::compound_associations());
1016 if (!cassocs.empty()) {
1017 XMLNode* ca = node->add_child (X_("CompoundAssociations"));
1019 for (RegionFactory::CompoundAssociations::iterator i = cassocs.begin(); i != cassocs.end(); ++i) {
1021 XMLNode* can = new XMLNode (X_("CompoundAssociation"));
1022 i->first->id().print (buf, sizeof (buf));
1023 can->add_property (X_("copy"), buf);
1024 i->second->id().print (buf, sizeof (buf));
1025 can->add_property (X_("original"), buf);
1026 ca->add_child_nocopy (*can);
1032 node->add_child_nocopy (_locations->get_state());
1034 // for a template, just create a new Locations, populate it
1035 // with the default start and end, and get the state for that.
1036 Locations loc (*this);
1037 Location* range = new Location (*this, 0, 0, _("session"), Location::IsSessionRange);
1038 range->set (max_framepos, 0);
1040 node->add_child_nocopy (loc.get_state());
1043 child = node->add_child ("Bundles");
1045 boost::shared_ptr<BundleList> bundles = _bundles.reader ();
1046 for (BundleList::iterator i = bundles->begin(); i != bundles->end(); ++i) {
1047 boost::shared_ptr<UserBundle> b = boost::dynamic_pointer_cast<UserBundle> (*i);
1049 child->add_child_nocopy (b->get_state());
1054 child = node->add_child ("Routes");
1056 boost::shared_ptr<RouteList> r = routes.reader ();
1058 RoutePublicOrderSorter cmp;
1059 RouteList public_order (*r);
1060 public_order.sort (cmp);
1062 /* the sort should have put control outs first */
1065 assert (_monitor_out == public_order.front());
1068 for (RouteList::iterator i = public_order.begin(); i != public_order.end(); ++i) {
1069 if (!(*i)->is_auditioner()) {
1071 child->add_child_nocopy ((*i)->get_state());
1073 child->add_child_nocopy ((*i)->get_template());
1079 playlists->add_state (node, full_state);
1081 child = node->add_child ("RouteGroups");
1082 for (list<RouteGroup *>::iterator i = _route_groups.begin(); i != _route_groups.end(); ++i) {
1083 child->add_child_nocopy ((*i)->get_state());
1087 XMLNode* gain_child = node->add_child ("Click");
1088 gain_child->add_child_nocopy (_click_io->state (full_state));
1089 gain_child->add_child_nocopy (_click_gain->state (full_state));
1093 XMLNode* ltc_input_child = node->add_child ("LTC-In");
1094 ltc_input_child->add_child_nocopy (_ltc_input->state (full_state));
1098 XMLNode* ltc_output_child = node->add_child ("LTC-Out");
1099 ltc_output_child->add_child_nocopy (_ltc_output->state (full_state));
1102 node->add_child_nocopy (_speakers->get_state());
1103 node->add_child_nocopy (_tempo_map->get_state());
1104 node->add_child_nocopy (get_control_protocol_state());
1107 node->add_child_copy (*_extra_xml);
1114 Session::get_control_protocol_state ()
1116 ControlProtocolManager& cpm (ControlProtocolManager::instance());
1117 return cpm.get_state();
1121 Session::set_state (const XMLNode& node, int version)
1125 const XMLProperty* prop;
1128 _state_of_the_state = StateOfTheState (_state_of_the_state|CannotSave);
1130 if (node.name() != X_("Session")) {
1131 fatal << _("programming error: Session: incorrect XML node sent to set_state()") << endmsg;
1135 if ((prop = node.property ("name")) != 0) {
1136 _name = prop->value ();
1139 if ((prop = node.property (X_("sample-rate"))) != 0) {
1141 _nominal_frame_rate = atoi (prop->value());
1143 if (_nominal_frame_rate != _current_frame_rate) {
1144 boost::optional<int> r = AskAboutSampleRateMismatch (_nominal_frame_rate, _current_frame_rate);
1145 if (r.get_value_or (0)) {
1151 setup_raid_path(_session_dir->root_path());
1153 if ((prop = node.property (X_("id-counter"))) != 0) {
1155 sscanf (prop->value().c_str(), "%" PRIu64, &x);
1156 ID::init_counter (x);
1158 /* old sessions used a timebased counter, so fake
1159 the startup ID counter based on a standard
1164 ID::init_counter (now);
1167 if ((prop = node.property (X_("event-counter"))) != 0) {
1168 Evoral::init_event_id_counter (atoi (prop->value()));
1172 if ((child = find_named_node (node, "MIDIPorts")) != 0) {
1173 _midi_ports->set_midi_port_states (child->children());
1176 IO::disable_connecting ();
1178 Stateful::save_extra_xml (node);
1180 if (((child = find_named_node (node, "Options")) != 0)) { /* old style */
1181 load_options (*child);
1182 } else if ((child = find_named_node (node, "Config")) != 0) { /* new style */
1183 load_options (*child);
1185 error << _("Session: XML state has no options section") << endmsg;
1188 if (version >= 3000) {
1189 if ((child = find_named_node (node, "Metadata")) == 0) {
1190 warning << _("Session: XML state has no metadata section") << endmsg;
1191 } else if ( ARDOUR::SessionMetadata::Metadata()->set_state (*child, version) ) {
1196 if ((child = find_named_node (node, X_("Speakers"))) != 0) {
1197 _speakers->set_state (*child, version);
1200 if ((child = find_named_node (node, "Sources")) == 0) {
1201 error << _("Session: XML state has no sources section") << endmsg;
1203 } else if (load_sources (*child)) {
1207 if ((child = find_named_node (node, "TempoMap")) == 0) {
1208 error << _("Session: XML state has no Tempo Map section") << endmsg;
1210 } else if (_tempo_map->set_state (*child, version)) {
1214 if ((child = find_named_node (node, "Locations")) == 0) {
1215 error << _("Session: XML state has no locations section") << endmsg;
1217 } else if (_locations->set_state (*child, version)) {
1223 if ((location = _locations->auto_loop_location()) != 0) {
1224 set_auto_loop_location (location);
1227 if ((location = _locations->auto_punch_location()) != 0) {
1228 set_auto_punch_location (location);
1231 if ((location = _locations->session_range_location()) != 0) {
1232 delete _session_range_location;
1233 _session_range_location = location;
1236 if (_session_range_location) {
1237 AudioFileSource::set_header_position_offset (_session_range_location->start());
1240 if ((child = find_named_node (node, "Regions")) == 0) {
1241 error << _("Session: XML state has no Regions section") << endmsg;
1243 } else if (load_regions (*child)) {
1247 if ((child = find_named_node (node, "Playlists")) == 0) {
1248 error << _("Session: XML state has no playlists section") << endmsg;
1250 } else if (playlists->load (*this, *child)) {
1254 if ((child = find_named_node (node, "UnusedPlaylists")) == 0) {
1256 } else if (playlists->load_unused (*this, *child)) {
1260 if ((child = find_named_node (node, "CompoundAssociations")) != 0) {
1261 if (load_compounds (*child)) {
1266 if (version >= 3000) {
1267 if ((child = find_named_node (node, "Bundles")) == 0) {
1268 warning << _("Session: XML state has no bundles section") << endmsg;
1271 /* We can't load Bundles yet as they need to be able
1272 to convert from port names to Port objects, which can't happen until
1274 _bundle_xml_node = new XMLNode (*child);
1278 if (version < 3000) {
1279 if ((child = find_named_node (node, X_("DiskStreams"))) == 0) {
1280 error << _("Session: XML state has no diskstreams section") << endmsg;
1282 } else if (load_diskstreams_2X (*child, version)) {
1287 if ((child = find_named_node (node, "Routes")) == 0) {
1288 error << _("Session: XML state has no routes section") << endmsg;
1290 } else if (load_routes (*child, version)) {
1294 /* our diskstreams list is no longer needed as they are now all owned by their Route */
1295 _diskstreams_2X.clear ();
1297 if (version >= 3000) {
1299 if ((child = find_named_node (node, "RouteGroups")) == 0) {
1300 error << _("Session: XML state has no route groups section") << endmsg;
1302 } else if (load_route_groups (*child, version)) {
1306 } else if (version < 3000) {
1308 if ((child = find_named_node (node, "EditGroups")) == 0) {
1309 error << _("Session: XML state has no edit groups section") << endmsg;
1311 } else if (load_route_groups (*child, version)) {
1315 if ((child = find_named_node (node, "MixGroups")) == 0) {
1316 error << _("Session: XML state has no mix groups section") << endmsg;
1318 } else if (load_route_groups (*child, version)) {
1323 if ((child = find_named_node (node, "Click")) == 0) {
1324 warning << _("Session: XML state has no click section") << endmsg;
1325 } else if (_click_io) {
1326 setup_click_state (&node);
1329 if ((child = find_named_node (node, ControlProtocolManager::state_node_name)) != 0) {
1330 ControlProtocolManager::instance().set_state (*child, version);
1333 update_have_rec_enabled_track ();
1335 /* here beginneth the second phase ... */
1337 StateReady (); /* EMIT SIGNAL */
1346 Session::load_routes (const XMLNode& node, int version)
1349 XMLNodeConstIterator niter;
1350 RouteList new_routes;
1352 nlist = node.children();
1356 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1358 boost::shared_ptr<Route> route;
1359 if (version < 3000) {
1360 route = XMLRouteFactory_2X (**niter, version);
1362 route = XMLRouteFactory (**niter, version);
1366 error << _("Session: cannot create Route from XML description.") << endmsg;
1370 BootMessage (string_compose (_("Loaded track/bus %1"), route->name()));
1372 new_routes.push_back (route);
1375 add_routes (new_routes, false, false, false);
1380 boost::shared_ptr<Route>
1381 Session::XMLRouteFactory (const XMLNode& node, int version)
1383 boost::shared_ptr<Route> ret;
1385 if (node.name() != "Route") {
1389 XMLNode* ds_child = find_named_node (node, X_("Diskstream"));
1391 DataType type = DataType::AUDIO;
1392 const XMLProperty* prop = node.property("default-type");
1395 type = DataType (prop->value());
1398 assert (type != DataType::NIL);
1402 boost::shared_ptr<Track> track;
1404 if (type == DataType::AUDIO) {
1405 track.reset (new AudioTrack (*this, X_("toBeResetFroXML")));
1407 track.reset (new MidiTrack (*this, X_("toBeResetFroXML")));
1410 if (track->init()) {
1414 if (track->set_state (node, version)) {
1418 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
1419 // boost_debug_shared_ptr_mark_interesting (track.get(), "Track");
1424 enum Route::Flag flags = Route::Flag(0);
1425 const XMLProperty* prop = node.property("flags");
1427 flags = Route::Flag (string_2_enum (prop->value(), flags));
1430 boost::shared_ptr<Route> r (new Route (*this, X_("toBeResetFroXML"), flags));
1432 if (r->init () == 0 && r->set_state (node, version) == 0) {
1433 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
1434 // boost_debug_shared_ptr_mark_interesting (r.get(), "Route");
1443 boost::shared_ptr<Route>
1444 Session::XMLRouteFactory_2X (const XMLNode& node, int version)
1446 boost::shared_ptr<Route> ret;
1448 if (node.name() != "Route") {
1452 XMLProperty const * ds_prop = node.property (X_("diskstream-id"));
1454 ds_prop = node.property (X_("diskstream"));
1457 DataType type = DataType::AUDIO;
1458 const XMLProperty* prop = node.property("default-type");
1461 type = DataType (prop->value());
1464 assert (type != DataType::NIL);
1468 list<boost::shared_ptr<Diskstream> >::iterator i = _diskstreams_2X.begin ();
1469 while (i != _diskstreams_2X.end() && (*i)->id() != ds_prop->value()) {
1473 if (i == _diskstreams_2X.end()) {
1474 error << _("Could not find diskstream for route") << endmsg;
1475 return boost::shared_ptr<Route> ();
1478 boost::shared_ptr<Track> track;
1480 if (type == DataType::AUDIO) {
1481 track.reset (new AudioTrack (*this, X_("toBeResetFroXML")));
1483 track.reset (new MidiTrack (*this, X_("toBeResetFroXML")));
1486 if (track->init()) {
1490 if (track->set_state (node, version)) {
1494 track->set_diskstream (*i);
1496 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
1497 // boost_debug_shared_ptr_mark_interesting (track.get(), "Track");
1502 enum Route::Flag flags = Route::Flag(0);
1503 const XMLProperty* prop = node.property("flags");
1505 flags = Route::Flag (string_2_enum (prop->value(), flags));
1508 boost::shared_ptr<Route> r (new Route (*this, X_("toBeResetFroXML"), flags));
1510 if (r->init () == 0 && r->set_state (node, version) == 0) {
1511 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
1512 // boost_debug_shared_ptr_mark_interesting (r.get(), "Route");
1522 Session::load_regions (const XMLNode& node)
1525 XMLNodeConstIterator niter;
1526 boost::shared_ptr<Region> region;
1528 nlist = node.children();
1532 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1533 if ((region = XMLRegionFactory (**niter, false)) == 0) {
1534 error << _("Session: cannot create Region from XML description.");
1535 const XMLProperty *name = (**niter).property("name");
1538 error << " " << string_compose (_("Can not load state for region '%1'"), name->value());
1549 Session::load_compounds (const XMLNode& node)
1551 XMLNodeList calist = node.children();
1552 XMLNodeConstIterator caiter;
1553 XMLProperty *caprop;
1555 for (caiter = calist.begin(); caiter != calist.end(); ++caiter) {
1556 XMLNode* ca = *caiter;
1560 if ((caprop = ca->property (X_("original"))) == 0) {
1563 orig_id = caprop->value();
1565 if ((caprop = ca->property (X_("copy"))) == 0) {
1568 copy_id = caprop->value();
1570 boost::shared_ptr<Region> orig = RegionFactory::region_by_id (orig_id);
1571 boost::shared_ptr<Region> copy = RegionFactory::region_by_id (copy_id);
1573 if (!orig || !copy) {
1574 warning << string_compose (_("Regions in compound description not found (ID's %1 and %2): ignored"),
1580 RegionFactory::add_compound_association (orig, copy);
1587 Session::load_nested_sources (const XMLNode& node)
1590 XMLNodeConstIterator niter;
1592 nlist = node.children();
1594 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1595 if ((*niter)->name() == "Source") {
1597 /* it may already exist, so don't recreate it unnecessarily
1600 XMLProperty* prop = (*niter)->property (X_("id"));
1602 error << _("Nested source has no ID info in session file! (ignored)") << endmsg;
1606 ID source_id (prop->value());
1608 if (!source_by_id (source_id)) {
1611 SourceFactory::create (*this, **niter, true);
1613 catch (failed_constructor& err) {
1614 error << string_compose (_("Cannot reconstruct nested source for region %1"), name()) << endmsg;
1621 boost::shared_ptr<Region>
1622 Session::XMLRegionFactory (const XMLNode& node, bool full)
1624 const XMLProperty* type = node.property("type");
1628 const XMLNodeList& nlist = node.children();
1630 for (XMLNodeConstIterator niter = nlist.begin(); niter != nlist.end(); ++niter) {
1631 XMLNode *child = (*niter);
1632 if (child->name() == "NestedSource") {
1633 load_nested_sources (*child);
1637 if (!type || type->value() == "audio") {
1638 return boost::shared_ptr<Region>(XMLAudioRegionFactory (node, full));
1639 } else if (type->value() == "midi") {
1640 return boost::shared_ptr<Region>(XMLMidiRegionFactory (node, full));
1643 } catch (failed_constructor& err) {
1644 return boost::shared_ptr<Region> ();
1647 return boost::shared_ptr<Region> ();
1650 boost::shared_ptr<AudioRegion>
1651 Session::XMLAudioRegionFactory (const XMLNode& node, bool /*full*/)
1653 const XMLProperty* prop;
1654 boost::shared_ptr<Source> source;
1655 boost::shared_ptr<AudioSource> as;
1657 SourceList master_sources;
1658 uint32_t nchans = 1;
1661 if (node.name() != X_("Region")) {
1662 return boost::shared_ptr<AudioRegion>();
1665 if ((prop = node.property (X_("channels"))) != 0) {
1666 nchans = atoi (prop->value().c_str());
1669 if ((prop = node.property ("name")) == 0) {
1670 cerr << "no name for this region\n";
1674 if ((prop = node.property (X_("source-0"))) == 0) {
1675 if ((prop = node.property ("source")) == 0) {
1676 error << _("Session: XMLNode describing a AudioRegion is incomplete (no source)") << endmsg;
1677 return boost::shared_ptr<AudioRegion>();
1681 PBD::ID s_id (prop->value());
1683 if ((source = source_by_id (s_id)) == 0) {
1684 error << string_compose(_("Session: XMLNode describing a AudioRegion references an unknown source id =%1"), s_id) << endmsg;
1685 return boost::shared_ptr<AudioRegion>();
1688 as = boost::dynamic_pointer_cast<AudioSource>(source);
1690 error << string_compose(_("Session: XMLNode describing a AudioRegion references a non-audio source id =%1"), s_id) << endmsg;
1691 return boost::shared_ptr<AudioRegion>();
1694 sources.push_back (as);
1696 /* pickup other channels */
1698 for (uint32_t n=1; n < nchans; ++n) {
1699 snprintf (buf, sizeof(buf), X_("source-%d"), n);
1700 if ((prop = node.property (buf)) != 0) {
1702 PBD::ID id2 (prop->value());
1704 if ((source = source_by_id (id2)) == 0) {
1705 error << string_compose(_("Session: XMLNode describing a AudioRegion references an unknown source id =%1"), id2) << endmsg;
1706 return boost::shared_ptr<AudioRegion>();
1709 as = boost::dynamic_pointer_cast<AudioSource>(source);
1711 error << string_compose(_("Session: XMLNode describing a AudioRegion references a non-audio source id =%1"), id2) << endmsg;
1712 return boost::shared_ptr<AudioRegion>();
1714 sources.push_back (as);
1718 for (uint32_t n = 0; n < nchans; ++n) {
1719 snprintf (buf, sizeof(buf), X_("master-source-%d"), n);
1720 if ((prop = node.property (buf)) != 0) {
1722 PBD::ID id2 (prop->value());
1724 if ((source = source_by_id (id2)) == 0) {
1725 error << string_compose(_("Session: XMLNode describing a AudioRegion references an unknown source id =%1"), id2) << endmsg;
1726 return boost::shared_ptr<AudioRegion>();
1729 as = boost::dynamic_pointer_cast<AudioSource>(source);
1731 error << string_compose(_("Session: XMLNode describing a AudioRegion references a non-audio source id =%1"), id2) << endmsg;
1732 return boost::shared_ptr<AudioRegion>();
1734 master_sources.push_back (as);
1739 boost::shared_ptr<AudioRegion> region (boost::dynamic_pointer_cast<AudioRegion> (RegionFactory::create (sources, node)));
1741 /* a final detail: this is the one and only place that we know how long missing files are */
1743 if (region->whole_file()) {
1744 for (SourceList::iterator sx = sources.begin(); sx != sources.end(); ++sx) {
1745 boost::shared_ptr<SilentFileSource> sfp = boost::dynamic_pointer_cast<SilentFileSource> (*sx);
1747 sfp->set_length (region->length());
1752 if (!master_sources.empty()) {
1753 if (master_sources.size() != nchans) {
1754 error << _("Session: XMLNode describing an AudioRegion is missing some master sources; ignored") << endmsg;
1756 region->set_master_sources (master_sources);
1764 catch (failed_constructor& err) {
1765 return boost::shared_ptr<AudioRegion>();
1769 boost::shared_ptr<MidiRegion>
1770 Session::XMLMidiRegionFactory (const XMLNode& node, bool /*full*/)
1772 const XMLProperty* prop;
1773 boost::shared_ptr<Source> source;
1774 boost::shared_ptr<MidiSource> ms;
1777 if (node.name() != X_("Region")) {
1778 return boost::shared_ptr<MidiRegion>();
1781 if ((prop = node.property ("name")) == 0) {
1782 cerr << "no name for this region\n";
1786 if ((prop = node.property (X_("source-0"))) == 0) {
1787 if ((prop = node.property ("source")) == 0) {
1788 error << _("Session: XMLNode describing a MidiRegion is incomplete (no source)") << endmsg;
1789 return boost::shared_ptr<MidiRegion>();
1793 PBD::ID s_id (prop->value());
1795 if ((source = source_by_id (s_id)) == 0) {
1796 error << string_compose(_("Session: XMLNode describing a MidiRegion references an unknown source id =%1"), s_id) << endmsg;
1797 return boost::shared_ptr<MidiRegion>();
1800 ms = boost::dynamic_pointer_cast<MidiSource>(source);
1802 error << string_compose(_("Session: XMLNode describing a MidiRegion references a non-midi source id =%1"), s_id) << endmsg;
1803 return boost::shared_ptr<MidiRegion>();
1806 sources.push_back (ms);
1809 boost::shared_ptr<MidiRegion> region (boost::dynamic_pointer_cast<MidiRegion> (RegionFactory::create (sources, node)));
1810 /* a final detail: this is the one and only place that we know how long missing files are */
1812 if (region->whole_file()) {
1813 for (SourceList::iterator sx = sources.begin(); sx != sources.end(); ++sx) {
1814 boost::shared_ptr<SilentFileSource> sfp = boost::dynamic_pointer_cast<SilentFileSource> (*sx);
1816 sfp->set_length (region->length());
1824 catch (failed_constructor& err) {
1825 return boost::shared_ptr<MidiRegion>();
1830 Session::get_sources_as_xml ()
1833 XMLNode* node = new XMLNode (X_("Sources"));
1834 Glib::Threads::Mutex::Lock lm (source_lock);
1836 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ++i) {
1837 node->add_child_nocopy (i->second->get_state());
1844 Session::path_from_region_name (DataType type, string name, string identifier)
1846 char buf[PATH_MAX+1];
1848 SessionDirectory sdir(get_best_session_directory_for_new_source());
1849 std::string source_dir = ((type == DataType::AUDIO)
1850 ? sdir.sound_path() : sdir.midi_path());
1852 string ext = native_header_format_extension (config.get_native_file_header_format(), type);
1854 for (n = 0; n < 999999; ++n) {
1855 if (identifier.length()) {
1856 snprintf (buf, sizeof(buf), "%s%s%" PRIu32 "%s", name.c_str(),
1857 identifier.c_str(), n, ext.c_str());
1859 snprintf (buf, sizeof(buf), "%s-%" PRIu32 "%s", name.c_str(),
1863 std::string source_path = Glib::build_filename (source_dir, buf);
1865 if (!Glib::file_test (source_path, Glib::FILE_TEST_EXISTS)) {
1870 error << string_compose (_("cannot create new file from region name \"%1\" with ident = \"%2\": too many existing files with similar names"),
1879 Session::load_sources (const XMLNode& node)
1882 XMLNodeConstIterator niter;
1883 boost::shared_ptr<Source> source;
1885 nlist = node.children();
1889 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1892 if ((source = XMLSourceFactory (**niter)) == 0) {
1893 error << _("Session: cannot create Source from XML description.") << endmsg;
1896 } catch (MissingSource& err) {
1900 if (!no_questions_about_missing_files) {
1901 user_choice = MissingFile (this, err.path, err.type).get_value_or (-1);
1906 switch (user_choice) {
1908 /* user added a new search location, so try again */
1913 /* user asked to quit the entire session load
1918 no_questions_about_missing_files = true;
1922 no_questions_about_missing_files = true;
1927 warning << _("A sound file is missing. It will be replaced by silence.") << endmsg;
1928 source = SourceFactory::createSilent (*this, **niter, max_framecnt, _current_frame_rate);
1937 boost::shared_ptr<Source>
1938 Session::XMLSourceFactory (const XMLNode& node)
1940 if (node.name() != "Source") {
1941 return boost::shared_ptr<Source>();
1945 /* note: do peak building in another thread when loading session state */
1946 return SourceFactory::create (*this, node, true);
1949 catch (failed_constructor& err) {
1950 error << string_compose (_("Found a sound file that cannot be used by %1. Talk to the progammers."), PROGRAM_NAME) << endmsg;
1951 return boost::shared_ptr<Source>();
1956 Session::save_template (string template_name)
1960 if (_state_of_the_state & CannotSave) {
1964 std::string user_template_dir(user_template_directory());
1966 if (g_mkdir_with_parents (user_template_dir.c_str(), 0755) != 0) {
1967 error << string_compose(_("Could not create templates directory \"%1\" (%2)"),
1968 user_template_dir, g_strerror (errno)) << endmsg;
1972 tree.set_root (&get_template());
1974 std::string template_dir_path(user_template_dir);
1976 /* directory to put the template in */
1977 template_dir_path = Glib::build_filename (template_dir_path, template_name);
1979 if (Glib::file_test (template_dir_path, Glib::FILE_TEST_EXISTS)) {
1980 warning << string_compose(_("Template \"%1\" already exists - new version not created"),
1981 template_dir_path) << endmsg;
1985 if (g_mkdir_with_parents (template_dir_path.c_str(), 0755) != 0) {
1986 error << string_compose(_("Could not create directory for Session template\"%1\" (%2)"),
1987 template_dir_path, g_strerror (errno)) << endmsg;
1992 std::string template_file_path(template_dir_path);
1993 template_file_path = Glib::build_filename (template_file_path, template_name + template_suffix);
1995 if (!tree.write (template_file_path)) {
1996 error << _("template not saved") << endmsg;
2000 /* copy plugin state directory */
2002 std::string template_plugin_state_path(template_dir_path);
2003 template_plugin_state_path = Glib::build_filename (template_plugin_state_path, X_("plugins"));
2005 if (g_mkdir_with_parents (template_plugin_state_path.c_str(), 0755) != 0) {
2006 error << string_compose(_("Could not create directory for Session template plugin state\"%1\" (%2)"),
2007 template_plugin_state_path, g_strerror (errno)) << endmsg;
2011 copy_files (plugins_dir(), template_plugin_state_path);
2017 Session::refresh_disk_space ()
2019 #if __APPLE__ || (HAVE_SYS_VFS_H && HAVE_SYS_STATVFS_H)
2021 Glib::Threads::Mutex::Lock lm (space_lock);
2023 /* get freespace on every FS that is part of the session path */
2025 _total_free_4k_blocks = 0;
2026 _total_free_4k_blocks_uncertain = false;
2028 for (vector<space_and_path>::iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
2030 struct statfs statfsbuf;
2031 statfs (i->path.c_str(), &statfsbuf);
2033 double const scale = statfsbuf.f_bsize / 4096.0;
2035 /* See if this filesystem is read-only */
2036 struct statvfs statvfsbuf;
2037 statvfs (i->path.c_str(), &statvfsbuf);
2039 /* f_bavail can be 0 if it is undefined for whatever
2040 filesystem we are looking at; Samba shares mounted
2041 via GVFS are an example of this.
2043 if (statfsbuf.f_bavail == 0) {
2044 /* block count unknown */
2046 i->blocks_unknown = true;
2047 } else if (statvfsbuf.f_flag & ST_RDONLY) {
2048 /* read-only filesystem */
2050 i->blocks_unknown = false;
2052 /* read/write filesystem with known space */
2053 i->blocks = (uint32_t) floor (statfsbuf.f_bavail * scale);
2054 i->blocks_unknown = false;
2057 _total_free_4k_blocks += i->blocks;
2058 if (i->blocks_unknown) {
2059 _total_free_4k_blocks_uncertain = true;
2062 #elif defined (COMPILER_MSVC)
2063 vector<string> scanned_volumes;
2064 vector<string>::iterator j;
2065 vector<space_and_path>::iterator i;
2066 DWORD nSectorsPerCluster, nBytesPerSector,
2067 nFreeClusters, nTotalClusters;
2071 _total_free_4k_blocks = 0;
2073 for (i = session_dirs.begin(); i != session_dirs.end(); i++) {
2074 strncpy (disk_drive, (*i).path.c_str(), 3);
2078 volume_found = false;
2079 if (0 != (GetDiskFreeSpace(disk_drive, &nSectorsPerCluster, &nBytesPerSector, &nFreeClusters, &nTotalClusters)))
2081 int64_t nBytesPerCluster = nBytesPerSector * nSectorsPerCluster;
2082 int64_t nFreeBytes = nBytesPerCluster * (int64_t)nFreeClusters;
2083 i->blocks = (uint32_t)(nFreeBytes / 4096);
2085 for (j = scanned_volumes.begin(); j != scanned_volumes.end(); j++) {
2086 if (0 == j->compare(disk_drive)) {
2087 volume_found = true;
2092 if (!volume_found) {
2093 scanned_volumes.push_back(disk_drive);
2094 _total_free_4k_blocks += i->blocks;
2099 if (0 == _total_free_4k_blocks) {
2100 strncpy (disk_drive, path().c_str(), 3);
2103 if (0 != (GetDiskFreeSpace(disk_drive, &nSectorsPerCluster, &nBytesPerSector, &nFreeClusters, &nTotalClusters)))
2105 int64_t nBytesPerCluster = nBytesPerSector * nSectorsPerCluster;
2106 int64_t nFreeBytes = nBytesPerCluster * (int64_t)nFreeClusters;
2107 _total_free_4k_blocks = (uint32_t)(nFreeBytes / 4096);
2114 Session::get_best_session_directory_for_new_source ()
2116 vector<space_and_path>::iterator i;
2117 string result = _session_dir->root_path();
2119 /* handle common case without system calls */
2121 if (session_dirs.size() == 1) {
2125 /* OK, here's the algorithm we're following here:
2127 We want to select which directory to use for
2128 the next file source to be created. Ideally,
2129 we'd like to use a round-robin process so as to
2130 get maximum performance benefits from splitting
2131 the files across multiple disks.
2133 However, in situations without much diskspace, an
2134 RR approach may end up filling up a filesystem
2135 with new files while others still have space.
2136 Its therefore important to pay some attention to
2137 the freespace in the filesystem holding each
2138 directory as well. However, if we did that by
2139 itself, we'd keep creating new files in the file
2140 system with the most space until it was as full
2141 as all others, thus negating any performance
2142 benefits of this RAID-1 like approach.
2144 So, we use a user-configurable space threshold. If
2145 there are at least 2 filesystems with more than this
2146 much space available, we use RR selection between them.
2147 If not, then we pick the filesystem with the most space.
2149 This gets a good balance between the two
2153 refresh_disk_space ();
2155 int free_enough = 0;
2157 for (i = session_dirs.begin(); i != session_dirs.end(); ++i) {
2158 if ((*i).blocks * 4096 >= Config->get_disk_choice_space_threshold()) {
2163 if (free_enough >= 2) {
2164 /* use RR selection process, ensuring that the one
2168 i = last_rr_session_dir;
2171 if (++i == session_dirs.end()) {
2172 i = session_dirs.begin();
2175 if ((*i).blocks * 4096 >= Config->get_disk_choice_space_threshold()) {
2176 SessionDirectory sdir(i->path);
2177 if (sdir.create ()) {
2179 last_rr_session_dir = i;
2184 } while (i != last_rr_session_dir);
2188 /* pick FS with the most freespace (and that
2189 seems to actually work ...)
2192 vector<space_and_path> sorted;
2193 space_and_path_ascending_cmp cmp;
2195 sorted = session_dirs;
2196 sort (sorted.begin(), sorted.end(), cmp);
2198 for (i = sorted.begin(); i != sorted.end(); ++i) {
2199 SessionDirectory sdir(i->path);
2200 if (sdir.create ()) {
2202 last_rr_session_dir = i;
2212 Session::automation_dir () const
2214 return Glib::build_filename (_path, "automation");
2218 Session::analysis_dir () const
2220 return Glib::build_filename (_path, "analysis");
2224 Session::plugins_dir () const
2226 return Glib::build_filename (_path, "plugins");
2230 Session::externals_dir () const
2232 return Glib::build_filename (_path, "externals");
2236 Session::load_bundles (XMLNode const & node)
2238 XMLNodeList nlist = node.children();
2239 XMLNodeConstIterator niter;
2243 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2244 if ((*niter)->name() == "InputBundle") {
2245 add_bundle (boost::shared_ptr<UserBundle> (new UserBundle (**niter, true)));
2246 } else if ((*niter)->name() == "OutputBundle") {
2247 add_bundle (boost::shared_ptr<UserBundle> (new UserBundle (**niter, false)));
2249 error << string_compose(_("Unknown node \"%1\" found in Bundles list from session file"), (*niter)->name()) << endmsg;
2258 Session::load_route_groups (const XMLNode& node, int version)
2260 XMLNodeList nlist = node.children();
2261 XMLNodeConstIterator niter;
2265 if (version >= 3000) {
2267 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2268 if ((*niter)->name() == "RouteGroup") {
2269 RouteGroup* rg = new RouteGroup (*this, "");
2270 add_route_group (rg);
2271 rg->set_state (**niter, version);
2275 } else if (version < 3000) {
2277 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2278 if ((*niter)->name() == "EditGroup" || (*niter)->name() == "MixGroup") {
2279 RouteGroup* rg = new RouteGroup (*this, "");
2280 add_route_group (rg);
2281 rg->set_state (**niter, version);
2290 Session::auto_save()
2292 save_state (_current_snapshot_name);
2296 state_file_filter (const string &str, void* /*arg*/)
2298 return (str.length() > strlen(statefile_suffix) &&
2299 str.find (statefile_suffix) == (str.length() - strlen (statefile_suffix)));
2303 bool operator()(const string* a, const string* b) {
2309 remove_end(string* state)
2311 string statename(*state);
2313 string::size_type start,end;
2314 if ((start = statename.find_last_of (G_DIR_SEPARATOR)) != string::npos) {
2315 statename = statename.substr (start+1);
2318 if ((end = statename.rfind(".ardour")) == string::npos) {
2319 end = statename.length();
2322 return new string(statename.substr (0, end));
2326 Session::possible_states (string path)
2328 PathScanner scanner;
2329 vector<string*>* states = scanner (path, state_file_filter, 0, false, false);
2331 transform(states->begin(), states->end(), states->begin(), remove_end);
2334 sort (states->begin(), states->end(), cmp);
2340 Session::possible_states () const
2342 return possible_states(_path);
2346 Session::add_route_group (RouteGroup* g)
2348 _route_groups.push_back (g);
2349 route_group_added (g); /* EMIT SIGNAL */
2351 g->RouteAdded.connect_same_thread (*this, boost::bind (&Session::route_added_to_route_group, this, _1, _2));
2352 g->RouteRemoved.connect_same_thread (*this, boost::bind (&Session::route_removed_from_route_group, this, _1, _2));
2353 g->PropertyChanged.connect_same_thread (*this, boost::bind (&Session::route_group_property_changed, this, g));
2359 Session::remove_route_group (RouteGroup& rg)
2361 list<RouteGroup*>::iterator i;
2363 if ((i = find (_route_groups.begin(), _route_groups.end(), &rg)) != _route_groups.end()) {
2364 _route_groups.erase (i);
2367 route_group_removed (); /* EMIT SIGNAL */
2371 /** Set a new order for our route groups, without adding or removing any.
2372 * @param groups Route group list in the new order.
2375 Session::reorder_route_groups (list<RouteGroup*> groups)
2377 _route_groups = groups;
2379 route_groups_reordered (); /* EMIT SIGNAL */
2385 Session::route_group_by_name (string name)
2387 list<RouteGroup *>::iterator i;
2389 for (i = _route_groups.begin(); i != _route_groups.end(); ++i) {
2390 if ((*i)->name() == name) {
2398 Session::all_route_group() const
2400 return *_all_route_group;
2404 Session::add_commands (vector<Command*> const & cmds)
2406 for (vector<Command*>::const_iterator i = cmds.begin(); i != cmds.end(); ++i) {
2412 Session::begin_reversible_command (const string& name)
2414 begin_reversible_command (g_quark_from_string (name.c_str ()));
2417 /** Begin a reversible command using a GQuark to identify it.
2418 * begin_reversible_command() and commit_reversible_command() calls may be nested,
2419 * but there must be as many begin...()s as there are commit...()s.
2422 Session::begin_reversible_command (GQuark q)
2424 /* If nested begin/commit pairs are used, we create just one UndoTransaction
2425 to hold all the commands that are committed. This keeps the order of
2426 commands correct in the history.
2429 if (_current_trans == 0) {
2430 /* start a new transaction */
2431 assert (_current_trans_quarks.empty ());
2432 _current_trans = new UndoTransaction();
2433 _current_trans->set_name (g_quark_to_string (q));
2436 _current_trans_quarks.push_front (q);
2440 Session::commit_reversible_command (Command *cmd)
2442 assert (_current_trans);
2443 assert (!_current_trans_quarks.empty ());
2448 _current_trans->add_command (cmd);
2451 _current_trans_quarks.pop_front ();
2453 if (!_current_trans_quarks.empty ()) {
2454 /* the transaction we're committing is not the top-level one */
2458 if (_current_trans->empty()) {
2459 /* no commands were added to the transaction, so just get rid of it */
2460 delete _current_trans;
2465 gettimeofday (&now, 0);
2466 _current_trans->set_timestamp (now);
2468 _history.add (_current_trans);
2473 accept_all_audio_files (const string& path, void* /*arg*/)
2475 if (!Glib::file_test (path, Glib::FILE_TEST_IS_REGULAR)) {
2479 if (!AudioFileSource::safe_audio_file_extension (path)) {
2487 accept_all_midi_files (const string& path, void* /*arg*/)
2489 if (!Glib::file_test (path, Glib::FILE_TEST_IS_REGULAR)) {
2493 return ((path.length() > 4 && path.find (".mid") != (path.length() - 4)) ||
2494 (path.length() > 4 && path.find (".smf") != (path.length() - 4)) ||
2495 (path.length() > 5 && path.find (".midi") != (path.length() - 5)));
2499 accept_all_state_files (const string& path, void* /*arg*/)
2501 if (!Glib::file_test (path, Glib::FILE_TEST_IS_REGULAR)) {
2505 return (path.length() > 7 && path.find (".ardour") == (path.length() - 7));
2509 Session::find_all_sources (string path, set<string>& result)
2514 if (!tree.read (path)) {
2518 if ((node = find_named_node (*tree.root(), "Sources")) == 0) {
2523 XMLNodeConstIterator niter;
2525 nlist = node->children();
2529 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2533 if ((prop = (*niter)->property (X_("type"))) == 0) {
2537 DataType type (prop->value());
2539 if ((prop = (*niter)->property (X_("name"))) == 0) {
2543 if (Glib::path_is_absolute (prop->value())) {
2544 /* external file, ignore */
2552 if (FileSource::find (*this, type, prop->value(), true, is_new, chan, found_path)) {
2553 result.insert (found_path);
2561 Session::find_all_sources_across_snapshots (set<string>& result, bool exclude_this_snapshot)
2563 PathScanner scanner;
2564 vector<string*>* state_files;
2566 string this_snapshot_path;
2572 if (ripped[ripped.length()-1] == G_DIR_SEPARATOR) {
2573 ripped = ripped.substr (0, ripped.length() - 1);
2576 state_files = scanner (ripped, accept_all_state_files, (void *) 0, true, true);
2578 if (state_files == 0) {
2583 this_snapshot_path = _path;
2584 this_snapshot_path += legalize_for_path (_current_snapshot_name);
2585 this_snapshot_path += statefile_suffix;
2587 for (vector<string*>::iterator i = state_files->begin(); i != state_files->end(); ++i) {
2589 if (exclude_this_snapshot && **i == this_snapshot_path) {
2593 if (find_all_sources (**i, result) < 0) {
2601 struct RegionCounter {
2602 typedef std::map<PBD::ID,boost::shared_ptr<AudioSource> > AudioSourceList;
2603 AudioSourceList::iterator iter;
2604 boost::shared_ptr<Region> region;
2607 RegionCounter() : count (0) {}
2611 Session::ask_about_playlist_deletion (boost::shared_ptr<Playlist> p)
2613 boost::optional<int> r = AskAboutPlaylistDeletion (p);
2614 return r.get_value_or (1);
2618 Session::cleanup_regions ()
2620 const RegionFactory::RegionMap& regions (RegionFactory::regions());
2622 for (RegionFactory::RegionMap::const_iterator i = regions.begin(); i != regions.end(); ++i) {
2624 uint32_t used = playlists->region_use_count (i->second);
2626 if (used == 0 && !i->second->automatic ()) {
2627 RegionFactory::map_remove (i->second);
2631 /* dump the history list */
2638 Session::cleanup_sources (CleanupReport& rep)
2640 // FIXME: needs adaptation to midi
2642 vector<boost::shared_ptr<Source> > dead_sources;
2643 PathScanner scanner;
2646 vector<space_and_path>::iterator i;
2647 vector<space_and_path>::iterator nexti;
2648 vector<string*>* candidates;
2649 vector<string*>* candidates2;
2650 vector<string> unused;
2651 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 (i = session_dirs.begin(); i != session_dirs.end(); ) {
2703 SessionDirectory sdir ((*i).path);
2704 audio_path += sdir.sound_path();
2706 if (nexti != session_dirs.end()) {
2707 audio_path += G_SEARCHPATH_SEPARATOR;
2714 /* build a list of all the possible midi directories for the session */
2716 for (i = session_dirs.begin(); i != session_dirs.end(); ) {
2721 SessionDirectory sdir ((*i).path);
2722 midi_path += sdir.midi_path();
2724 if (nexti != session_dirs.end()) {
2725 midi_path += G_SEARCHPATH_SEPARATOR;
2731 candidates = scanner (audio_path, accept_all_audio_files, (void *) 0, true, true);
2732 candidates2 = scanner (midi_path, accept_all_midi_files, (void *) 0, true, true);
2738 for (vector<string*>::iterator i = candidates2->begin(); i != candidates2->end(); ++i) {
2739 candidates->push_back (*i);
2744 candidates = candidates2; // might still be null
2747 /* find all sources, but don't use this snapshot because the
2748 state file on disk still references sources we may have already
2752 find_all_sources_across_snapshots (all_sources, true);
2754 /* add our current source list
2757 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ) {
2758 boost::shared_ptr<FileSource> fs;
2759 SourceMap::iterator tmp = i;
2762 if ((fs = boost::dynamic_pointer_cast<FileSource> (i->second)) != 0) {
2764 if (!fs->is_stub()) {
2766 if (playlists->source_use_count (fs) != 0) {
2767 all_sources.insert (fs->path());
2770 /* we might not remove this source from disk, because it may be used
2771 by other snapshots, but its not being used in this version
2772 so lets get rid of it now, along with any representative regions
2776 RegionFactory::remove_regions_using_source (i->second);
2786 for (vector<string*>::iterator x = candidates->begin(); x != candidates->end(); ++x) {
2791 for (set<string>::iterator i = all_sources.begin(); i != all_sources.end(); ++i) {
2793 tmppath1 = canonical_path (spath);
2794 tmppath2 = canonical_path ((*i));
2796 if (tmppath1 == tmppath2) {
2803 unused.push_back (spath);
2812 /* now try to move all unused files into the "dead" directory(ies) */
2814 for (vector<string>::iterator x = unused.begin(); x != unused.end(); ++x) {
2815 struct stat statbuf;
2819 /* don't move the file across filesystems, just
2820 stick it in the `dead_dir_name' directory
2821 on whichever filesystem it was already on.
2824 if ((*x).find ("/sounds/") != string::npos) {
2826 /* old school, go up 1 level */
2828 newpath = Glib::path_get_dirname (*x); // "sounds"
2829 newpath = Glib::path_get_dirname (newpath); // "session-name"
2833 /* new school, go up 4 levels */
2835 newpath = Glib::path_get_dirname (*x); // "audiofiles" or "midifiles"
2836 newpath = Glib::path_get_dirname (newpath); // "session-name"
2837 newpath = Glib::path_get_dirname (newpath); // "interchange"
2838 newpath = Glib::path_get_dirname (newpath); // "session-dir"
2841 newpath = Glib::build_filename (newpath, dead_dir_name);
2843 if (g_mkdir_with_parents (newpath.c_str(), 0755) < 0) {
2844 error << string_compose(_("Session: cannot create dead file folder \"%1\" (%2)"), newpath, strerror (errno)) << endmsg;
2848 newpath = Glib::build_filename (newpath, Glib::path_get_basename ((*x)));
2850 if (Glib::file_test (newpath, Glib::FILE_TEST_EXISTS)) {
2852 /* the new path already exists, try versioning */
2854 char buf[PATH_MAX+1];
2858 snprintf (buf, sizeof (buf), "%s.%d", newpath.c_str(), version);
2861 while (Glib::file_test (newpath_v.c_str(), Glib::FILE_TEST_EXISTS) && version < 999) {
2862 snprintf (buf, sizeof (buf), "%s.%d", newpath.c_str(), ++version);
2866 if (version == 999) {
2867 error << string_compose (_("there are already 1000 files with names like %1; versioning discontinued"),
2871 newpath = newpath_v;
2876 /* it doesn't exist, or we can't read it or something */
2880 stat ((*x).c_str(), &statbuf);
2882 if (::rename ((*x).c_str(), newpath.c_str()) != 0) {
2883 error << string_compose (_("cannot rename unused file source from %1 to %2 (%3)"),
2884 (*x), newpath, strerror (errno))
2889 /* see if there an easy to find peakfile for this file, and remove it.
2892 string base = basename_nosuffix (*x);
2893 base += "%A"; /* this is what we add for the channel suffix of all native files,
2894 or for the first channel of embedded files. it will miss
2895 some peakfiles for other channels
2897 string peakpath = peak_path (base);
2899 if (Glib::file_test (peakpath.c_str(), Glib::FILE_TEST_EXISTS)) {
2900 if (::g_unlink (peakpath.c_str()) != 0) {
2901 error << string_compose (_("cannot remove peakfile %1 for %2 (%3)"),
2902 peakpath, _path, strerror (errno))
2904 /* try to back out */
2905 ::rename (newpath.c_str(), _path.c_str());
2910 rep.paths.push_back (*x);
2911 rep.space += statbuf.st_size;
2914 /* dump the history list */
2918 /* save state so we don't end up a session file
2919 referring to non-existent sources.
2926 _state_of_the_state = (StateOfTheState) (_state_of_the_state & ~InCleanup);
2932 Session::cleanup_trash_sources (CleanupReport& rep)
2934 // FIXME: needs adaptation for MIDI
2936 vector<space_and_path>::iterator i;
2942 for (i = session_dirs.begin(); i != session_dirs.end(); ++i) {
2944 dead_dir = Glib::build_filename ((*i).path, dead_dir_name);
2946 clear_directory (dead_dir, &rep.space, &rep.paths);
2953 Session::set_dirty ()
2955 bool was_dirty = dirty();
2957 _state_of_the_state = StateOfTheState (_state_of_the_state | Dirty);
2961 DirtyChanged(); /* EMIT SIGNAL */
2967 Session::set_clean ()
2969 bool was_dirty = dirty();
2971 _state_of_the_state = Clean;
2975 DirtyChanged(); /* EMIT SIGNAL */
2980 Session::set_deletion_in_progress ()
2982 _state_of_the_state = StateOfTheState (_state_of_the_state | Deletion);
2986 Session::clear_deletion_in_progress ()
2988 _state_of_the_state = StateOfTheState (_state_of_the_state & (~Deletion));
2992 Session::add_controllable (boost::shared_ptr<Controllable> c)
2994 /* this adds a controllable to the list managed by the Session.
2995 this is a subset of those managed by the Controllable class
2996 itself, and represents the only ones whose state will be saved
2997 as part of the session.
3000 Glib::Threads::Mutex::Lock lm (controllables_lock);
3001 controllables.insert (c);
3004 struct null_deleter { void operator()(void const *) const {} };
3007 Session::remove_controllable (Controllable* c)
3009 if (_state_of_the_state & Deletion) {
3013 Glib::Threads::Mutex::Lock lm (controllables_lock);
3015 Controllables::iterator x = controllables.find (boost::shared_ptr<Controllable>(c, null_deleter()));
3017 if (x != controllables.end()) {
3018 controllables.erase (x);
3022 boost::shared_ptr<Controllable>
3023 Session::controllable_by_id (const PBD::ID& id)
3025 Glib::Threads::Mutex::Lock lm (controllables_lock);
3027 for (Controllables::iterator i = controllables.begin(); i != controllables.end(); ++i) {
3028 if ((*i)->id() == id) {
3033 return boost::shared_ptr<Controllable>();
3036 boost::shared_ptr<Controllable>
3037 Session::controllable_by_descriptor (const ControllableDescriptor& desc)
3039 boost::shared_ptr<Controllable> c;
3040 boost::shared_ptr<Route> r;
3042 switch (desc.top_level_type()) {
3043 case ControllableDescriptor::NamedRoute:
3045 std::string str = desc.top_level_name();
3046 if (str == "master") {
3048 } else if (str == "control" || str == "listen") {
3051 r = route_by_name (desc.top_level_name());
3056 case ControllableDescriptor::RemoteControlID:
3057 r = route_by_remote_id (desc.rid());
3065 switch (desc.subtype()) {
3066 case ControllableDescriptor::Gain:
3067 c = r->gain_control ();
3070 case ControllableDescriptor::Solo:
3071 c = r->solo_control();
3074 case ControllableDescriptor::Mute:
3075 c = r->mute_control();
3078 case ControllableDescriptor::Recenable:
3080 boost::shared_ptr<Track> t = boost::dynamic_pointer_cast<Track>(r);
3083 c = t->rec_enable_control ();
3088 case ControllableDescriptor::PanDirection:
3090 c = r->pannable()->pan_azimuth_control;
3094 case ControllableDescriptor::PanWidth:
3096 c = r->pannable()->pan_width_control;
3100 case ControllableDescriptor::PanElevation:
3102 c = r->pannable()->pan_elevation_control;
3106 case ControllableDescriptor::Balance:
3107 /* XXX simple pan control */
3110 case ControllableDescriptor::PluginParameter:
3112 uint32_t plugin = desc.target (0);
3113 uint32_t parameter_index = desc.target (1);
3115 /* revert to zero based counting */
3121 if (parameter_index > 0) {
3125 boost::shared_ptr<Processor> p = r->nth_plugin (plugin);
3128 c = boost::dynamic_pointer_cast<ARDOUR::AutomationControl>(
3129 p->control(Evoral::Parameter(PluginAutomation, 0, parameter_index)));
3134 case ControllableDescriptor::SendGain:
3136 uint32_t send = desc.target (0);
3138 /* revert to zero-based counting */
3144 boost::shared_ptr<Processor> p = r->nth_send (send);
3147 boost::shared_ptr<Send> s = boost::dynamic_pointer_cast<Send>(p);
3148 boost::shared_ptr<Amp> a = s->amp();
3151 c = s->amp()->gain_control();
3158 /* relax and return a null pointer */
3166 Session::add_instant_xml (XMLNode& node, bool write_to_config)
3169 Stateful::add_instant_xml (node, _path);
3172 if (write_to_config) {
3173 Config->add_instant_xml (node);
3178 Session::instant_xml (const string& node_name)
3180 return Stateful::instant_xml (node_name, _path);
3184 Session::save_history (string snapshot_name)
3192 if (snapshot_name.empty()) {
3193 snapshot_name = _current_snapshot_name;
3196 const string history_filename = legalize_for_path (snapshot_name) + history_suffix;
3197 const string backup_filename = history_filename + backup_suffix;
3198 const std::string xml_path(Glib::build_filename (_session_dir->root_path(), history_filename));
3199 const std::string backup_path(Glib::build_filename (_session_dir->root_path(), backup_filename));
3201 if (Glib::file_test (xml_path, Glib::FILE_TEST_EXISTS)) {
3202 if (::g_rename (xml_path.c_str(), backup_path.c_str()) != 0) {
3203 error << _("could not backup old history file, current history not saved") << endmsg;
3208 if (!Config->get_save_history() || Config->get_saved_history_depth() < 0) {
3212 tree.set_root (&_history.get_state (Config->get_saved_history_depth()));
3214 if (!tree.write (xml_path))
3216 error << string_compose (_("history could not be saved to %1"), xml_path) << endmsg;
3218 if (g_remove (xml_path.c_str()) != 0) {
3219 error << string_compose(_("Could not remove history file at path \"%1\" (%2)"),
3220 xml_path, g_strerror (errno)) << endmsg;
3222 if (::g_rename (backup_path.c_str(), xml_path.c_str()) != 0) {
3223 error << string_compose (_("could not restore history file from backup %1 (%2)"),
3224 backup_path, g_strerror (errno)) << endmsg;
3234 Session::restore_history (string snapshot_name)
3238 if (snapshot_name.empty()) {
3239 snapshot_name = _current_snapshot_name;
3242 const std::string xml_filename = legalize_for_path (snapshot_name) + history_suffix;
3243 const std::string xml_path(Glib::build_filename (_session_dir->root_path(), xml_filename));
3245 info << "Loading history from " << xml_path << endmsg;
3247 if (!Glib::file_test (xml_path, Glib::FILE_TEST_EXISTS)) {
3248 info << string_compose (_("%1: no history file \"%2\" for this session."),
3249 _name, xml_path) << endmsg;
3253 if (!tree.read (xml_path)) {
3254 error << string_compose (_("Could not understand session history file \"%1\""),
3255 xml_path) << endmsg;
3262 for (XMLNodeConstIterator it = tree.root()->children().begin(); it != tree.root()->children().end(); it++) {
3265 UndoTransaction* ut = new UndoTransaction ();
3268 ut->set_name(t->property("name")->value());
3269 stringstream ss(t->property("tv-sec")->value());
3271 ss.str(t->property("tv-usec")->value());
3273 ut->set_timestamp(tv);
3275 for (XMLNodeConstIterator child_it = t->children().begin();
3276 child_it != t->children().end(); child_it++)
3278 XMLNode *n = *child_it;
3281 if (n->name() == "MementoCommand" ||
3282 n->name() == "MementoUndoCommand" ||
3283 n->name() == "MementoRedoCommand") {
3285 if ((c = memento_command_factory(n))) {
3289 } else if (n->name() == "NoteDiffCommand") {
3290 PBD::ID id (n->property("midi-source")->value());
3291 boost::shared_ptr<MidiSource> midi_source =
3292 boost::dynamic_pointer_cast<MidiSource, Source>(source_by_id(id));
3294 ut->add_command (new MidiModel::NoteDiffCommand(midi_source->model(), *n));
3296 error << _("Failed to downcast MidiSource for NoteDiffCommand") << endmsg;
3299 } else if (n->name() == "SysExDiffCommand") {
3301 PBD::ID id (n->property("midi-source")->value());
3302 boost::shared_ptr<MidiSource> midi_source =
3303 boost::dynamic_pointer_cast<MidiSource, Source>(source_by_id(id));
3305 ut->add_command (new MidiModel::SysExDiffCommand (midi_source->model(), *n));
3307 error << _("Failed to downcast MidiSource for SysExDiffCommand") << endmsg;
3310 } else if (n->name() == "PatchChangeDiffCommand") {
3312 PBD::ID id (n->property("midi-source")->value());
3313 boost::shared_ptr<MidiSource> midi_source =
3314 boost::dynamic_pointer_cast<MidiSource, Source>(source_by_id(id));
3316 ut->add_command (new MidiModel::PatchChangeDiffCommand (midi_source->model(), *n));
3318 error << _("Failed to downcast MidiSource for PatchChangeDiffCommand") << endmsg;
3321 } else if (n->name() == "StatefulDiffCommand") {
3322 if ((c = stateful_diff_command_factory (n))) {
3323 ut->add_command (c);
3326 error << string_compose(_("Couldn't figure out how to make a Command out of a %1 XMLNode."), n->name()) << endmsg;
3337 Session::config_changed (std::string p, bool ours)
3343 if (p == "seamless-loop") {
3345 } else if (p == "rf-speed") {
3347 } else if (p == "auto-loop") {
3349 } else if (p == "auto-input") {
3351 if (Config->get_monitoring_model() == HardwareMonitoring && transport_rolling()) {
3352 /* auto-input only makes a difference if we're rolling */
3353 set_track_monitor_input_status (!config.get_auto_input());
3356 } else if (p == "punch-in") {
3360 if ((location = _locations->auto_punch_location()) != 0) {
3362 if (config.get_punch_in ()) {
3363 replace_event (SessionEvent::PunchIn, location->start());
3365 remove_event (location->start(), SessionEvent::PunchIn);
3369 } else if (p == "punch-out") {
3373 if ((location = _locations->auto_punch_location()) != 0) {
3375 if (config.get_punch_out()) {
3376 replace_event (SessionEvent::PunchOut, location->end());
3378 clear_events (SessionEvent::PunchOut);
3382 } else if (p == "edit-mode") {
3384 Glib::Threads::Mutex::Lock lm (playlists->lock);
3386 for (SessionPlaylists::List::iterator i = playlists->playlists.begin(); i != playlists->playlists.end(); ++i) {
3387 (*i)->set_edit_mode (Config->get_edit_mode ());
3390 } else if (p == "use-video-sync") {
3392 waiting_for_sync_offset = config.get_use_video_sync();
3394 } else if (p == "mmc-control") {
3396 //poke_midi_thread ();
3398 } else if (p == "mmc-device-id" || p == "mmc-receive-id" || p == "mmc-receive-device-id") {
3400 _mmc->set_receive_device_id (Config->get_mmc_receive_device_id());
3402 } else if (p == "mmc-send-id" || p == "mmc-send-device-id") {
3404 _mmc->set_send_device_id (Config->get_mmc_send_device_id());
3406 } else if (p == "midi-control") {
3408 //poke_midi_thread ();
3410 } else if (p == "raid-path") {
3412 setup_raid_path (config.get_raid_path());
3414 } else if (p == "timecode-format") {
3418 } else if (p == "video-pullup") {
3422 } else if (p == "seamless-loop") {
3424 if (play_loop && transport_rolling()) {
3425 // to reset diskstreams etc
3426 request_play_loop (true);
3429 } else if (p == "rf-speed") {
3431 cumulative_rf_motion = 0;
3434 } else if (p == "click-sound") {
3436 setup_click_sounds (1);
3438 } else if (p == "click-emphasis-sound") {
3440 setup_click_sounds (-1);
3442 } else if (p == "clicking") {
3444 if (Config->get_clicking()) {
3445 if (_click_io && click_data) { // don't require emphasis data
3452 } else if (p == "click-gain") {
3455 _click_gain->set_gain (Config->get_click_gain(), this);
3458 } else if (p == "send-mtc") {
3460 if (Config->get_send_mtc ()) {
3461 /* mark us ready to send */
3462 next_quarter_frame_to_send = 0;
3465 } else if (p == "send-mmc") {
3467 _mmc->enable_send (Config->get_send_mmc ());
3469 } else if (p == "midi-feedback") {
3471 session_midi_feedback = Config->get_midi_feedback();
3473 } else if (p == "jack-time-master") {
3475 engine().reset_timebase ();
3477 } else if (p == "native-file-header-format") {
3479 if (!first_file_header_format_reset) {
3480 reset_native_file_format ();
3483 first_file_header_format_reset = false;
3485 } else if (p == "native-file-data-format") {
3487 if (!first_file_data_format_reset) {
3488 reset_native_file_format ();
3491 first_file_data_format_reset = false;
3493 } else if (p == "external-sync") {
3494 if (!config.get_external_sync()) {
3495 drop_sync_source ();
3497 switch_to_sync_source (Config->get_sync_source());
3499 } else if (p == "denormal-model") {
3501 } else if (p == "history-depth") {
3502 set_history_depth (Config->get_history_depth());
3503 } else if (p == "remote-model") {
3504 /* XXX DO SOMETHING HERE TO TELL THE GUI THAT WE NEED
3507 } else if (p == "initial-program-change") {
3509 if (_mmc->output_port() && Config->get_initial_program_change() >= 0) {
3512 buf[0] = MIDI::program; // channel zero by default
3513 buf[1] = (Config->get_initial_program_change() & 0x7f);
3515 _mmc->output_port()->midimsg (buf, sizeof (buf), 0);
3517 } else if (p == "solo-mute-override") {
3518 // catch_up_on_solo_mute_override ();
3519 } else if (p == "listen-position" || p == "pfl-position") {
3520 listen_position_changed ();
3521 } else if (p == "solo-control-is-listen-control") {
3522 solo_control_mode_changed ();
3523 } else if (p == "timecode-offset" || p == "timecode-offset-negative") {
3524 last_timecode_valid = false;
3525 } else if (p == "playback-buffer-seconds") {
3526 AudioSource::allocate_working_buffers (frame_rate());
3527 } else if (p == "automation-thinning-factor") {
3528 Evoral::ControlList::set_thinning_factor (Config->get_automation_thinning_factor());
3529 } else if (p == "ltc-source-port") {
3530 reconnect_ltc_input ();
3531 } else if (p == "ltc-sink-port") {
3532 reconnect_ltc_output ();
3533 } else if (p == "timecode-generator-offset") {
3534 ltc_tx_parse_offset();
3541 Session::set_history_depth (uint32_t d)
3543 _history.set_depth (d);
3547 Session::load_diskstreams_2X (XMLNode const & node, int)
3550 XMLNodeConstIterator citer;
3552 clist = node.children();
3554 for (citer = clist.begin(); citer != clist.end(); ++citer) {
3557 /* diskstreams added automatically by DiskstreamCreated handler */
3558 if ((*citer)->name() == "AudioDiskstream" || (*citer)->name() == "DiskStream") {
3559 boost::shared_ptr<AudioDiskstream> dsp (new AudioDiskstream (*this, **citer));
3560 _diskstreams_2X.push_back (dsp);
3562 error << _("Session: unknown diskstream type in XML") << endmsg;
3566 catch (failed_constructor& err) {
3567 error << _("Session: could not load diskstream via XML state") << endmsg;
3575 /** Connect things to the MMC object */
3577 Session::setup_midi_machine_control ()
3579 _mmc = new MIDI::MachineControl;
3580 _mmc->set_ports (_midi_ports->mmc_input_port(), _midi_ports->mmc_output_port());
3582 _mmc->Play.connect_same_thread (*this, boost::bind (&Session::mmc_deferred_play, this, _1));
3583 _mmc->DeferredPlay.connect_same_thread (*this, boost::bind (&Session::mmc_deferred_play, this, _1));
3584 _mmc->Stop.connect_same_thread (*this, boost::bind (&Session::mmc_stop, this, _1));
3585 _mmc->FastForward.connect_same_thread (*this, boost::bind (&Session::mmc_fast_forward, this, _1));
3586 _mmc->Rewind.connect_same_thread (*this, boost::bind (&Session::mmc_rewind, this, _1));
3587 _mmc->Pause.connect_same_thread (*this, boost::bind (&Session::mmc_pause, this, _1));
3588 _mmc->RecordPause.connect_same_thread (*this, boost::bind (&Session::mmc_record_pause, this, _1));
3589 _mmc->RecordStrobe.connect_same_thread (*this, boost::bind (&Session::mmc_record_strobe, this, _1));
3590 _mmc->RecordExit.connect_same_thread (*this, boost::bind (&Session::mmc_record_exit, this, _1));
3591 _mmc->Locate.connect_same_thread (*this, boost::bind (&Session::mmc_locate, this, _1, _2));
3592 _mmc->Step.connect_same_thread (*this, boost::bind (&Session::mmc_step, this, _1, _2));
3593 _mmc->Shuttle.connect_same_thread (*this, boost::bind (&Session::mmc_shuttle, this, _1, _2, _3));
3594 _mmc->TrackRecordStatusChange.connect_same_thread (*this, boost::bind (&Session::mmc_record_enable, this, _1, _2, _3));
3596 /* also handle MIDI SPP because its so common */
3598 _mmc->SPPStart.connect_same_thread (*this, boost::bind (&Session::spp_start, this));
3599 _mmc->SPPContinue.connect_same_thread (*this, boost::bind (&Session::spp_continue, this));
3600 _mmc->SPPStop.connect_same_thread (*this, boost::bind (&Session::spp_stop, this));
3603 boost::shared_ptr<Controllable>
3604 Session::solo_cut_control() const
3606 /* the solo cut control is a bit of an anomaly, at least as of Febrary 2011. There are no other
3607 controls in Ardour that currently get presented to the user in the GUI that require
3608 access as a Controllable and are also NOT owned by some SessionObject (e.g. Route, or MonitorProcessor).
3610 its actually an RCConfiguration parameter, so we use a ProxyControllable to wrap
3611 it up as a Controllable. Changes to the Controllable will just map back to the RCConfiguration
3615 return _solo_cut_control;
3619 Session::rename (const std::string& new_name)
3621 string legal_name = legalize_for_path (new_name);
3627 string const old_sources_root = _session_dir->sources_root();
3632 * interchange subdirectory
3636 * Backup files are left unchanged and not renamed.
3639 /* pass one: not 100% safe check that the new directory names don't
3643 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
3648 /* this is a stupid hack because Glib::path_get_dirname() is
3649 * lexical-only, and so passing it /a/b/c/ gives a different
3650 * result than passing it /a/b/c ...
3653 if (oldstr[oldstr.length()-1] == G_DIR_SEPARATOR) {
3654 oldstr = oldstr.substr (0, oldstr.length() - 1);
3657 string base = Glib::path_get_dirname (oldstr);
3658 string p = Glib::path_get_basename (oldstr);
3660 newstr = Glib::build_filename (base, legal_name);
3662 if (Glib::file_test (newstr, Glib::FILE_TEST_EXISTS)) {
3669 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
3674 /* this is a stupid hack because Glib::path_get_dirname() is
3675 * lexical-only, and so passing it /a/b/c/ gives a different
3676 * result than passing it /a/b/c ...
3679 if (oldstr[oldstr.length()-1] == G_DIR_SEPARATOR) {
3680 oldstr = oldstr.substr (0, oldstr.length() - 1);
3683 string base = Glib::path_get_dirname (oldstr);
3684 string p = Glib::path_get_basename (oldstr);
3686 newstr = Glib::build_filename (base, legal_name);
3688 cerr << "Rename " << oldstr << " => " << newstr << endl;
3690 if (::g_rename (oldstr.c_str(), newstr.c_str()) != 0) {
3691 error << string_compose (_("renaming %s as %2 failed (%3)"), oldstr, newstr, g_strerror (errno)) << endmsg;
3696 (*_session_dir) = newstr;
3701 /* directory below interchange */
3703 v.push_back (newstr);
3704 v.push_back (interchange_dir_name);
3707 oldstr = Glib::build_filename (v);
3710 v.push_back (newstr);
3711 v.push_back (interchange_dir_name);
3712 v.push_back (legal_name);
3714 newstr = Glib::build_filename (v);
3716 cerr << "Rename " << oldstr << " => " << newstr << endl;
3718 if (::g_rename (oldstr.c_str(), newstr.c_str()) != 0) {
3719 error << string_compose (_("renaming %s as %2 failed (%3)"), oldstr, newstr, g_strerror (errno)) << endmsg;
3726 oldstr = Glib::build_filename (newpath, _current_snapshot_name) + statefile_suffix;
3727 newstr= Glib::build_filename (newpath, legal_name) + statefile_suffix;
3729 cerr << "Rename " << oldstr << " => " << newstr << endl;
3731 if (::g_rename (oldstr.c_str(), newstr.c_str()) != 0) {
3732 error << string_compose (_("renaming %s as %2 failed (%3)"), oldstr, newstr, g_strerror (errno)) << endmsg;
3739 oldstr = Glib::build_filename (newpath, _current_snapshot_name) + history_suffix;
3741 if (Glib::file_test (oldstr, Glib::FILE_TEST_EXISTS)) {
3742 newstr = Glib::build_filename (newpath, legal_name) + history_suffix;
3744 cerr << "Rename " << oldstr << " => " << newstr << endl;
3746 if (::g_rename (oldstr.c_str(), newstr.c_str()) != 0) {
3747 error << string_compose (_("renaming %s as %2 failed (%3)"), oldstr, newstr, g_strerror (errno)) << endmsg;
3752 /* update file source paths */
3754 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ++i) {
3755 boost::shared_ptr<FileSource> fs = boost::dynamic_pointer_cast<FileSource> (i->second);
3757 string p = fs->path ();
3758 boost::replace_all (p, old_sources_root, _session_dir->sources_root());
3763 /* remove old name from recent sessions */
3765 remove_recent_sessions (_path);
3768 _current_snapshot_name = new_name;
3771 /* re-add directory separator - reverse hack to oldstr above */
3772 if (_path[_path.length()-1] != G_DIR_SEPARATOR) {
3773 _path += G_DIR_SEPARATOR;
3778 /* save state again to get everything just right */
3780 save_state (_current_snapshot_name);
3783 /* add to recent sessions */
3785 store_recent_sessions (new_name, _path);
3791 Session::get_session_info_from_path (XMLTree& tree, const string& xmlpath)
3793 if (!Glib::file_test (xmlpath, Glib::FILE_TEST_EXISTS)) {
3797 if (!tree.read (xmlpath)) {
3805 Session::get_info_from_path (const string& xmlpath, float& sample_rate, SampleFormat& data_format)
3808 bool found_sr = false;
3809 bool found_data_format = false;
3811 if (get_session_info_from_path (tree, xmlpath)) {
3817 const XMLProperty* prop;
3818 if ((prop = tree.root()->property (X_("sample-rate"))) != 0) {
3819 sample_rate = atoi (prop->value());
3823 const XMLNodeList& children (tree.root()->children());
3824 for (XMLNodeList::const_iterator c = children.begin(); c != children.end(); ++c) {
3825 const XMLNode* child = *c;
3826 if (child->name() == "Config") {
3827 const XMLNodeList& options (child->children());
3828 for (XMLNodeList::const_iterator oc = options.begin(); oc != options.end(); ++oc) {
3829 const XMLNode* option = *oc;
3830 const XMLProperty* name = option->property("name");
3836 if (name->value() == "native-file-data-format") {
3837 const XMLProperty* value = option->property ("value");
3839 SampleFormat fmt = (SampleFormat) string_2_enum (option->property ("value")->value(), fmt);
3841 found_data_format = true;
3847 if (found_data_format) {
3852 return !(found_sr && found_data_format); // zero if they are both found