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/playlist_source.h"
100 #include "ardour/port.h"
101 #include "ardour/processor.h"
102 #include "ardour/proxy_controllable.h"
103 #include "ardour/recent_sessions.h"
104 #include "ardour/region_factory.h"
105 #include "ardour/route_group.h"
106 #include "ardour/send.h"
107 #include "ardour/session.h"
108 #include "ardour/session_directory.h"
109 #include "ardour/session_metadata.h"
110 #include "ardour/session_playlists.h"
111 #include "ardour/session_state_utils.h"
112 #include "ardour/silentfilesource.h"
113 #include "ardour/sndfilesource.h"
114 #include "ardour/source_factory.h"
115 #include "ardour/speakers.h"
116 #include "ardour/template_utils.h"
117 #include "ardour/tempo.h"
118 #include "ardour/ticker.h"
119 #include "ardour/user_bundle.h"
121 #include "control_protocol/control_protocol.h"
127 using namespace ARDOUR;
131 Session::pre_engine_init (string fullpath)
133 if (fullpath.empty()) {
135 throw failed_constructor();
138 /* discover canonical fullpath */
140 _path = canonical_path(fullpath);
142 /* we require _path to end with a dir separator */
144 if (_path[_path.length()-1] != G_DIR_SEPARATOR) {
145 _path += G_DIR_SEPARATOR;
150 _is_new = !Glib::file_test (_path, Glib::FileTest (G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR));
152 /* finish initialization that can't be done in a normal C++ constructor
156 timerclear (&last_mmc_step);
157 g_atomic_int_set (&processing_prohibited, 0);
158 g_atomic_int_set (&_record_status, Disabled);
159 g_atomic_int_set (&_playback_load, 100);
160 g_atomic_int_set (&_capture_load, 100);
162 _all_route_group->set_active (true, this);
163 interpolation.add_channel_to (0, 0);
165 if (config.get_use_video_sync()) {
166 waiting_for_sync_offset = true;
168 waiting_for_sync_offset = false;
171 last_rr_session_dir = session_dirs.begin();
173 set_history_depth (Config->get_history_depth());
175 /* default: assume simple stereo speaker configuration */
177 _speakers->setup_default_speakers (2);
179 _solo_cut_control.reset (new ProxyControllable (_("solo cut control (dB)"), PBD::Controllable::GainLike,
180 boost::bind (&RCConfiguration::set_solo_mute_gain, Config, _1),
181 boost::bind (&RCConfiguration::get_solo_mute_gain, Config)));
182 add_controllable (_solo_cut_control);
184 /* These are all static "per-class" signals */
186 SourceFactory::SourceCreated.connect_same_thread (*this, boost::bind (&Session::add_source, this, _1));
187 PlaylistFactory::PlaylistCreated.connect_same_thread (*this, boost::bind (&Session::add_playlist, this, _1, _2));
188 AutomationList::AutomationListCreated.connect_same_thread (*this, boost::bind (&Session::add_automation_list, this, _1));
189 Controllable::Destroyed.connect_same_thread (*this, boost::bind (&Session::remove_controllable, this, _1));
190 IO::PortCountChanged.connect_same_thread (*this, boost::bind (&Session::ensure_buffers, this, _1));
192 /* stop IO objects from doing stuff until we're ready for them */
194 Delivery::disable_panners ();
195 IO::disable_connecting ();
197 AudioFileSource::set_peak_dir (_session_dir->peak_path());
201 Session::post_engine_init ()
203 BootMessage (_("Set block size and sample rate"));
205 set_block_size (_engine.samples_per_cycle());
206 set_frame_rate (_engine.sample_rate());
208 BootMessage (_("Using configuration"));
210 _midi_ports = new MidiPortManager;
212 MIDISceneChanger* msc;
214 _scene_changer = msc = new MIDISceneChanger (*this);
215 msc->set_input_port (scene_input_port());
216 msc->set_output_port (scene_out());
218 boost::function<framecnt_t(void)> timer_func (boost::bind (&Session::audible_frame, this));
219 boost::dynamic_pointer_cast<AsyncMIDIPort>(scene_in())->set_timer (timer_func);
221 setup_midi_machine_control ();
223 if (_butler->start_thread()) {
227 if (start_midi_thread ()) {
231 setup_click_sounds (0);
232 setup_midi_control ();
234 _engine.Halted.connect_same_thread (*this, boost::bind (&Session::engine_halted, this));
235 _engine.Xrun.connect_same_thread (*this, boost::bind (&Session::xrun_recovery, this));
238 /* tempo map requires sample rate knowledge */
240 _tempo_map = new TempoMap (_current_frame_rate);
241 _tempo_map->PropertyChanged.connect_same_thread (*this, boost::bind (&Session::tempo_map_changed, this, _1));
243 /* MidiClock requires a tempo map */
245 midi_clock = new MidiClockTicker ();
246 midi_clock->set_session (this);
248 /* crossfades require sample rate knowledge */
250 SndFileSource::setup_standard_crossfades (*this, frame_rate());
251 _engine.GraphReordered.connect_same_thread (*this, boost::bind (&Session::graph_reordered, this));
253 AudioDiskstream::allocate_working_buffers();
254 refresh_disk_space ();
256 /* we're finally ready to call set_state() ... all objects have
257 * been created, the engine is running.
261 if (set_state (*state_tree->root(), Stateful::loading_state_version)) {
265 // set_state() will call setup_raid_path(), but if it's a new session we need
266 // to call setup_raid_path() here.
267 setup_raid_path (_path);
272 boost::function<void (std::string)> ff (boost::bind (&Session::config_changed, this, _1, false));
273 boost::function<void (std::string)> ft (boost::bind (&Session::config_changed, this, _1, true));
275 Config->map_parameters (ff);
276 config.map_parameters (ft);
278 /* Reset all panners */
280 Delivery::reset_panners ();
282 /* this will cause the CPM to instantiate any protocols that are in use
283 * (or mandatory), which will pass it this Session, and then call
284 * set_state() on each instantiated protocol to match stored state.
287 ControlProtocolManager::instance().set_session (this);
289 /* This must be done after the ControlProtocolManager set_session above,
290 as it will set states for ports which the ControlProtocolManager creates.
293 // XXX set state of MIDI::Port's
294 // MidiPortManager::instance()->set_port_states (Config->midi_port_states ());
296 /* And this must be done after the MIDI::Manager::set_port_states as
297 * it will try to make connections whose details are loaded by set_port_states.
302 /* Let control protocols know that we are now all connected, so they
303 * could start talking to surfaces if they want to.
306 ControlProtocolManager::instance().midi_connectivity_established ();
308 if (_is_new && !no_auto_connect()) {
309 Glib::Threads::Mutex::Lock lm (AudioEngine::instance()->process_lock());
310 auto_connect_master_bus ();
313 _state_of_the_state = StateOfTheState (_state_of_the_state & ~(CannotSave|Dirty));
315 /* update latencies */
317 initialize_latencies ();
319 _locations->added.connect_same_thread (*this, boost::bind (&Session::location_added, this, _1));
320 _locations->removed.connect_same_thread (*this, boost::bind (&Session::location_removed, this, _1));
321 _locations->changed.connect_same_thread (*this, boost::bind (&Session::locations_changed, this));
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 send_immediate_mmc (MIDI::MachineControlCommand (MIDI::MachineControl::cmdMmcReset));
337 send_immediate_mmc (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_recurse (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 /* prevent concurrent saves from different threads */
672 Glib::Threads::Mutex::Lock lm (save_state_lock);
674 if (!_writable || (_state_of_the_state & CannotSave)) {
678 if (g_atomic_int_get(&_suspend_save)) {
682 _save_queued = false;
684 if (!_engine.connected ()) {
685 error << string_compose (_("the %1 audio engine is not connected and state saving would lose all I/O connections. Session not saved"),
691 /* tell sources we're saving first, in case they write out to a new file
692 * which should be saved with the state rather than the old one */
693 for (SourceMap::const_iterator i = sources.begin(); i != sources.end(); ++i) {
695 i->second->session_saved();
696 } catch (Evoral::SMF::FileError& e) {
697 error << string_compose ("Could not write to MIDI file %1; MIDI data not saved.", e.file_name ()) << endmsg;
701 SaveSession (); /* EMIT SIGNAL */
703 tree.set_root (&get_state());
705 if (snapshot_name.empty()) {
706 snapshot_name = _current_snapshot_name;
707 } else if (switch_to_snapshot) {
708 _current_snapshot_name = snapshot_name;
713 /* proper save: use statefile_suffix (.ardour in English) */
715 xml_path = Glib::build_filename (xml_path, legalize_for_path (snapshot_name) + statefile_suffix);
717 /* make a backup copy of the old file */
719 if (Glib::file_test (xml_path, Glib::FILE_TEST_EXISTS) && !create_backup_file (xml_path)) {
720 // create_backup_file will log the error
726 /* pending save: use pending_suffix (.pending in English) */
727 xml_path = Glib::build_filename (xml_path, legalize_for_path (snapshot_name) + pending_suffix);
730 std::string tmp_path(_session_dir->root_path());
731 tmp_path = Glib::build_filename (tmp_path, legalize_for_path (snapshot_name) + temp_suffix);
733 // cerr << "actually writing state to " << xml_path << endl;
735 if (!tree.write (tmp_path)) {
736 error << string_compose (_("state could not be saved to %1"), tmp_path) << endmsg;
737 if (g_remove (tmp_path.c_str()) != 0) {
738 error << string_compose(_("Could not remove temporary session file at path \"%1\" (%2)"),
739 tmp_path, g_strerror (errno)) << endmsg;
745 if (::g_rename (tmp_path.c_str(), xml_path.c_str()) != 0) {
746 error << string_compose (_("could not rename temporary session file %1 to %2 (%3)"),
747 tmp_path, xml_path, g_strerror(errno)) << endmsg;
748 if (g_remove (tmp_path.c_str()) != 0) {
749 error << string_compose(_("Could not remove temporary session file at path \"%1\" (%2)"),
750 tmp_path, g_strerror (errno)) << endmsg;
758 save_history (snapshot_name);
760 bool was_dirty = dirty();
762 _state_of_the_state = StateOfTheState (_state_of_the_state & ~Dirty);
765 DirtyChanged (); /* EMIT SIGNAL */
768 StateSaved (snapshot_name); /* EMIT SIGNAL */
775 Session::restore_state (string snapshot_name)
777 if (load_state (snapshot_name) == 0) {
778 set_state (*state_tree->root(), Stateful::loading_state_version);
785 Session::load_state (string snapshot_name)
790 state_was_pending = false;
792 /* check for leftover pending state from a crashed capture attempt */
794 std::string xmlpath(_session_dir->root_path());
795 xmlpath = Glib::build_filename (xmlpath, legalize_for_path (snapshot_name) + pending_suffix);
797 if (Glib::file_test (xmlpath, Glib::FILE_TEST_EXISTS)) {
799 /* there is pending state from a crashed capture attempt */
801 boost::optional<int> r = AskAboutPendingState();
802 if (r.get_value_or (1)) {
803 state_was_pending = true;
807 if (!state_was_pending) {
808 xmlpath = Glib::build_filename (_session_dir->root_path(), snapshot_name);
811 if (!Glib::file_test (xmlpath, Glib::FILE_TEST_EXISTS)) {
812 xmlpath = Glib::build_filename (_session_dir->root_path(), legalize_for_path (snapshot_name) + statefile_suffix);
813 if (!Glib::file_test (xmlpath, Glib::FILE_TEST_EXISTS)) {
814 error << string_compose(_("%1: session file \"%2\" doesn't exist!"), _name, xmlpath) << endmsg;
819 state_tree = new XMLTree;
823 _writable = exists_and_writable (xmlpath) && exists_and_writable(Glib::path_get_dirname(xmlpath));
825 if (!state_tree->read (xmlpath)) {
826 error << string_compose(_("Could not understand session file %1"), xmlpath) << endmsg;
832 XMLNode& root (*state_tree->root());
834 if (root.name() != X_("Session")) {
835 error << string_compose (_("Session file %1 is not a session"), xmlpath) << endmsg;
841 const XMLProperty* prop;
843 if ((prop = root.property ("version")) == 0) {
844 /* no version implies very old version of Ardour */
845 Stateful::loading_state_version = 1000;
847 if (prop->value().find ('.') != string::npos) {
848 /* old school version format */
849 if (prop->value()[0] == '2') {
850 Stateful::loading_state_version = 2000;
852 Stateful::loading_state_version = 3000;
855 Stateful::loading_state_version = atoi (prop->value());
859 if (Stateful::loading_state_version < CURRENT_SESSION_FILE_VERSION && _writable) {
861 std::string backup_path(_session_dir->root_path());
862 std::string backup_filename = string_compose ("%1-%2%3", legalize_for_path (snapshot_name), Stateful::loading_state_version, statefile_suffix);
863 backup_path = Glib::build_filename (backup_path, backup_filename);
865 // only create a backup for a given statefile version once
867 if (!Glib::file_test (backup_path, Glib::FILE_TEST_EXISTS)) {
869 VersionMismatch (xmlpath, backup_path);
871 if (!copy_file (xmlpath, backup_path)) {;
881 Session::load_options (const XMLNode& node)
883 LocaleGuard lg (X_("POSIX"));
884 config.set_variables (node);
889 Session::save_default_options ()
891 return config.save_state();
901 Session::get_template()
903 /* if we don't disable rec-enable, diskstreams
904 will believe they need to store their capture
905 sources in their state node.
908 disable_record (false);
914 Session::state (bool full_state)
916 XMLNode* node = new XMLNode("Session");
920 snprintf(buf, sizeof(buf), "%d", CURRENT_SESSION_FILE_VERSION);
921 node->add_property("version", buf);
923 /* store configuration settings */
927 node->add_property ("name", _name);
928 snprintf (buf, sizeof (buf), "%" PRId64, _nominal_frame_rate);
929 node->add_property ("sample-rate", buf);
931 if (session_dirs.size() > 1) {
935 vector<space_and_path>::iterator i = session_dirs.begin();
936 vector<space_and_path>::iterator next;
938 ++i; /* skip the first one */
942 while (i != session_dirs.end()) {
946 if (next != session_dirs.end()) {
947 p += G_SEARCHPATH_SEPARATOR;
956 child = node->add_child ("Path");
957 child->add_content (p);
961 /* save the ID counter */
963 snprintf (buf, sizeof (buf), "%" PRIu64, ID::counter());
964 node->add_property ("id-counter", buf);
966 /* save the event ID counter */
968 snprintf (buf, sizeof (buf), "%d", Evoral::event_id_counter());
969 node->add_property ("event-counter", buf);
971 /* various options */
973 list<XMLNode*> midi_port_nodes = _midi_ports->get_midi_port_states();
974 if (!midi_port_nodes.empty()) {
975 XMLNode* midi_port_stuff = new XMLNode ("MIDIPorts");
976 for (list<XMLNode*>::const_iterator n = midi_port_nodes.begin(); n != midi_port_nodes.end(); ++n) {
977 midi_port_stuff->add_child_nocopy (**n);
979 node->add_child_nocopy (*midi_port_stuff);
982 node->add_child_nocopy (config.get_variables ());
984 node->add_child_nocopy (ARDOUR::SessionMetadata::Metadata()->get_state());
986 child = node->add_child ("Sources");
989 Glib::Threads::Mutex::Lock sl (source_lock);
991 for (SourceMap::iterator siter = sources.begin(); siter != sources.end(); ++siter) {
993 /* Don't save information about non-file Sources, or
994 * about non-destructive file sources that are empty
995 * and unused by any regions.
998 boost::shared_ptr<FileSource> fs;
1000 if ((fs = boost::dynamic_pointer_cast<FileSource> (siter->second)) != 0) {
1002 if (!fs->destructive()) {
1003 if (fs->empty() && !fs->used()) {
1008 child->add_child_nocopy (siter->second->get_state());
1013 child = node->add_child ("Regions");
1016 Glib::Threads::Mutex::Lock rl (region_lock);
1017 const RegionFactory::RegionMap& region_map (RegionFactory::all_regions());
1018 for (RegionFactory::RegionMap::const_iterator i = region_map.begin(); i != region_map.end(); ++i) {
1019 boost::shared_ptr<Region> r = i->second;
1020 /* only store regions not attached to playlists */
1021 if (r->playlist() == 0) {
1022 if (boost::dynamic_pointer_cast<AudioRegion>(r)) {
1023 child->add_child_nocopy ((boost::dynamic_pointer_cast<AudioRegion>(r))->get_basic_state ());
1025 child->add_child_nocopy (r->get_state ());
1030 RegionFactory::CompoundAssociations& cassocs (RegionFactory::compound_associations());
1032 if (!cassocs.empty()) {
1033 XMLNode* ca = node->add_child (X_("CompoundAssociations"));
1035 for (RegionFactory::CompoundAssociations::iterator i = cassocs.begin(); i != cassocs.end(); ++i) {
1037 XMLNode* can = new XMLNode (X_("CompoundAssociation"));
1038 i->first->id().print (buf, sizeof (buf));
1039 can->add_property (X_("copy"), buf);
1040 i->second->id().print (buf, sizeof (buf));
1041 can->add_property (X_("original"), buf);
1042 ca->add_child_nocopy (*can);
1048 node->add_child_nocopy (_locations->get_state());
1050 // for a template, just create a new Locations, populate it
1051 // with the default start and end, and get the state for that.
1052 Locations loc (*this);
1053 Location* range = new Location (*this, 0, 0, _("session"), Location::IsSessionRange);
1054 range->set (max_framepos, 0);
1056 node->add_child_nocopy (loc.get_state());
1059 child = node->add_child ("Bundles");
1061 boost::shared_ptr<BundleList> bundles = _bundles.reader ();
1062 for (BundleList::iterator i = bundles->begin(); i != bundles->end(); ++i) {
1063 boost::shared_ptr<UserBundle> b = boost::dynamic_pointer_cast<UserBundle> (*i);
1065 child->add_child_nocopy (b->get_state());
1070 child = node->add_child ("Routes");
1072 boost::shared_ptr<RouteList> r = routes.reader ();
1074 RoutePublicOrderSorter cmp;
1075 RouteList public_order (*r);
1076 public_order.sort (cmp);
1078 /* the sort should have put control outs first */
1081 assert (_monitor_out == public_order.front());
1084 for (RouteList::iterator i = public_order.begin(); i != public_order.end(); ++i) {
1085 if (!(*i)->is_auditioner()) {
1087 child->add_child_nocopy ((*i)->get_state());
1089 child->add_child_nocopy ((*i)->get_template());
1095 playlists->add_state (node, full_state);
1097 child = node->add_child ("RouteGroups");
1098 for (list<RouteGroup *>::iterator i = _route_groups.begin(); i != _route_groups.end(); ++i) {
1099 child->add_child_nocopy ((*i)->get_state());
1103 XMLNode* gain_child = node->add_child ("Click");
1104 gain_child->add_child_nocopy (_click_io->state (full_state));
1105 gain_child->add_child_nocopy (_click_gain->state (full_state));
1109 XMLNode* ltc_input_child = node->add_child ("LTC-In");
1110 ltc_input_child->add_child_nocopy (_ltc_input->state (full_state));
1114 XMLNode* ltc_output_child = node->add_child ("LTC-Out");
1115 ltc_output_child->add_child_nocopy (_ltc_output->state (full_state));
1118 node->add_child_nocopy (_speakers->get_state());
1119 node->add_child_nocopy (_tempo_map->get_state());
1120 node->add_child_nocopy (get_control_protocol_state());
1123 node->add_child_copy (*_extra_xml);
1130 Session::get_control_protocol_state ()
1132 ControlProtocolManager& cpm (ControlProtocolManager::instance());
1133 return cpm.get_state();
1137 Session::set_state (const XMLNode& node, int version)
1141 const XMLProperty* prop;
1144 _state_of_the_state = StateOfTheState (_state_of_the_state|CannotSave);
1146 if (node.name() != X_("Session")) {
1147 fatal << _("programming error: Session: incorrect XML node sent to set_state()") << endmsg;
1151 if ((prop = node.property ("name")) != 0) {
1152 _name = prop->value ();
1155 if ((prop = node.property (X_("sample-rate"))) != 0) {
1157 _nominal_frame_rate = atoi (prop->value());
1159 if (_nominal_frame_rate != _current_frame_rate) {
1160 boost::optional<int> r = AskAboutSampleRateMismatch (_nominal_frame_rate, _current_frame_rate);
1161 if (r.get_value_or (0)) {
1167 setup_raid_path(_session_dir->root_path());
1169 if ((prop = node.property (X_("id-counter"))) != 0) {
1171 sscanf (prop->value().c_str(), "%" PRIu64, &x);
1172 ID::init_counter (x);
1174 /* old sessions used a timebased counter, so fake
1175 the startup ID counter based on a standard
1180 ID::init_counter (now);
1183 if ((prop = node.property (X_("event-counter"))) != 0) {
1184 Evoral::init_event_id_counter (atoi (prop->value()));
1188 if ((child = find_named_node (node, "MIDIPorts")) != 0) {
1189 _midi_ports->set_midi_port_states (child->children());
1192 IO::disable_connecting ();
1194 Stateful::save_extra_xml (node);
1196 if (((child = find_named_node (node, "Options")) != 0)) { /* old style */
1197 load_options (*child);
1198 } else if ((child = find_named_node (node, "Config")) != 0) { /* new style */
1199 load_options (*child);
1201 error << _("Session: XML state has no options section") << endmsg;
1204 if (version >= 3000) {
1205 if ((child = find_named_node (node, "Metadata")) == 0) {
1206 warning << _("Session: XML state has no metadata section") << endmsg;
1207 } else if ( ARDOUR::SessionMetadata::Metadata()->set_state (*child, version) ) {
1212 if ((child = find_named_node (node, X_("Speakers"))) != 0) {
1213 _speakers->set_state (*child, version);
1216 if ((child = find_named_node (node, "Sources")) == 0) {
1217 error << _("Session: XML state has no sources section") << endmsg;
1219 } else if (load_sources (*child)) {
1223 if ((child = find_named_node (node, "TempoMap")) == 0) {
1224 error << _("Session: XML state has no Tempo Map section") << endmsg;
1226 } else if (_tempo_map->set_state (*child, version)) {
1230 if ((child = find_named_node (node, "Locations")) == 0) {
1231 error << _("Session: XML state has no locations section") << endmsg;
1233 } else if (_locations->set_state (*child, version)) {
1237 locations_changed ();
1239 if (_session_range_location) {
1240 AudioFileSource::set_header_position_offset (_session_range_location->start());
1243 if ((child = find_named_node (node, "Regions")) == 0) {
1244 error << _("Session: XML state has no Regions section") << endmsg;
1246 } else if (load_regions (*child)) {
1250 if ((child = find_named_node (node, "Playlists")) == 0) {
1251 error << _("Session: XML state has no playlists section") << endmsg;
1253 } else if (playlists->load (*this, *child)) {
1257 if ((child = find_named_node (node, "UnusedPlaylists")) == 0) {
1259 } else if (playlists->load_unused (*this, *child)) {
1263 if ((child = find_named_node (node, "CompoundAssociations")) != 0) {
1264 if (load_compounds (*child)) {
1269 if (version >= 3000) {
1270 if ((child = find_named_node (node, "Bundles")) == 0) {
1271 warning << _("Session: XML state has no bundles section") << endmsg;
1274 /* We can't load Bundles yet as they need to be able
1275 to convert from port names to Port objects, which can't happen until
1277 _bundle_xml_node = new XMLNode (*child);
1281 if (version < 3000) {
1282 if ((child = find_named_node (node, X_("DiskStreams"))) == 0) {
1283 error << _("Session: XML state has no diskstreams section") << endmsg;
1285 } else if (load_diskstreams_2X (*child, version)) {
1290 if ((child = find_named_node (node, "Routes")) == 0) {
1291 error << _("Session: XML state has no routes section") << endmsg;
1293 } else if (load_routes (*child, version)) {
1297 /* our diskstreams list is no longer needed as they are now all owned by their Route */
1298 _diskstreams_2X.clear ();
1300 if (version >= 3000) {
1302 if ((child = find_named_node (node, "RouteGroups")) == 0) {
1303 error << _("Session: XML state has no route groups section") << endmsg;
1305 } else if (load_route_groups (*child, version)) {
1309 } else if (version < 3000) {
1311 if ((child = find_named_node (node, "EditGroups")) == 0) {
1312 error << _("Session: XML state has no edit groups section") << endmsg;
1314 } else if (load_route_groups (*child, version)) {
1318 if ((child = find_named_node (node, "MixGroups")) == 0) {
1319 error << _("Session: XML state has no mix groups section") << endmsg;
1321 } else if (load_route_groups (*child, version)) {
1326 if ((child = find_named_node (node, "Click")) == 0) {
1327 warning << _("Session: XML state has no click section") << endmsg;
1328 } else if (_click_io) {
1329 setup_click_state (&node);
1332 if ((child = find_named_node (node, ControlProtocolManager::state_node_name)) != 0) {
1333 ControlProtocolManager::instance().set_state (*child, version);
1336 update_have_rec_enabled_track ();
1338 /* here beginneth the second phase ... */
1340 StateReady (); /* EMIT SIGNAL */
1353 Session::load_routes (const XMLNode& node, int version)
1356 XMLNodeConstIterator niter;
1357 RouteList new_routes;
1359 nlist = node.children();
1363 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1365 boost::shared_ptr<Route> route;
1366 if (version < 3000) {
1367 route = XMLRouteFactory_2X (**niter, version);
1369 route = XMLRouteFactory (**niter, version);
1373 error << _("Session: cannot create Route from XML description.") << endmsg;
1377 BootMessage (string_compose (_("Loaded track/bus %1"), route->name()));
1379 new_routes.push_back (route);
1382 add_routes (new_routes, false, false, false);
1387 boost::shared_ptr<Route>
1388 Session::XMLRouteFactory (const XMLNode& node, int version)
1390 boost::shared_ptr<Route> ret;
1392 if (node.name() != "Route") {
1396 XMLNode* ds_child = find_named_node (node, X_("Diskstream"));
1398 DataType type = DataType::AUDIO;
1399 const XMLProperty* prop = node.property("default-type");
1402 type = DataType (prop->value());
1405 assert (type != DataType::NIL);
1409 boost::shared_ptr<Track> track;
1411 if (type == DataType::AUDIO) {
1412 track.reset (new AudioTrack (*this, X_("toBeResetFroXML")));
1414 track.reset (new MidiTrack (*this, X_("toBeResetFroXML")));
1417 if (track->init()) {
1421 if (track->set_state (node, version)) {
1425 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
1426 // boost_debug_shared_ptr_mark_interesting (track.get(), "Track");
1431 enum Route::Flag flags = Route::Flag(0);
1432 const XMLProperty* prop = node.property("flags");
1434 flags = Route::Flag (string_2_enum (prop->value(), flags));
1437 boost::shared_ptr<Route> r (new Route (*this, X_("toBeResetFroXML"), flags));
1439 if (r->init () == 0 && r->set_state (node, version) == 0) {
1440 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
1441 // boost_debug_shared_ptr_mark_interesting (r.get(), "Route");
1450 boost::shared_ptr<Route>
1451 Session::XMLRouteFactory_2X (const XMLNode& node, int version)
1453 boost::shared_ptr<Route> ret;
1455 if (node.name() != "Route") {
1459 XMLProperty const * ds_prop = node.property (X_("diskstream-id"));
1461 ds_prop = node.property (X_("diskstream"));
1464 DataType type = DataType::AUDIO;
1465 const XMLProperty* prop = node.property("default-type");
1468 type = DataType (prop->value());
1471 assert (type != DataType::NIL);
1475 list<boost::shared_ptr<Diskstream> >::iterator i = _diskstreams_2X.begin ();
1476 while (i != _diskstreams_2X.end() && (*i)->id() != ds_prop->value()) {
1480 if (i == _diskstreams_2X.end()) {
1481 error << _("Could not find diskstream for route") << endmsg;
1482 return boost::shared_ptr<Route> ();
1485 boost::shared_ptr<Track> track;
1487 if (type == DataType::AUDIO) {
1488 track.reset (new AudioTrack (*this, X_("toBeResetFroXML")));
1490 track.reset (new MidiTrack (*this, X_("toBeResetFroXML")));
1493 if (track->init()) {
1497 if (track->set_state (node, version)) {
1501 track->set_diskstream (*i);
1503 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
1504 // boost_debug_shared_ptr_mark_interesting (track.get(), "Track");
1509 enum Route::Flag flags = Route::Flag(0);
1510 const XMLProperty* prop = node.property("flags");
1512 flags = Route::Flag (string_2_enum (prop->value(), flags));
1515 boost::shared_ptr<Route> r (new Route (*this, X_("toBeResetFroXML"), flags));
1517 if (r->init () == 0 && r->set_state (node, version) == 0) {
1518 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
1519 // boost_debug_shared_ptr_mark_interesting (r.get(), "Route");
1529 Session::load_regions (const XMLNode& node)
1532 XMLNodeConstIterator niter;
1533 boost::shared_ptr<Region> region;
1535 nlist = node.children();
1539 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1540 if ((region = XMLRegionFactory (**niter, false)) == 0) {
1541 error << _("Session: cannot create Region from XML description.");
1542 const XMLProperty *name = (**niter).property("name");
1545 error << " " << string_compose (_("Can not load state for region '%1'"), name->value());
1556 Session::load_compounds (const XMLNode& node)
1558 XMLNodeList calist = node.children();
1559 XMLNodeConstIterator caiter;
1560 XMLProperty *caprop;
1562 for (caiter = calist.begin(); caiter != calist.end(); ++caiter) {
1563 XMLNode* ca = *caiter;
1567 if ((caprop = ca->property (X_("original"))) == 0) {
1570 orig_id = caprop->value();
1572 if ((caprop = ca->property (X_("copy"))) == 0) {
1575 copy_id = caprop->value();
1577 boost::shared_ptr<Region> orig = RegionFactory::region_by_id (orig_id);
1578 boost::shared_ptr<Region> copy = RegionFactory::region_by_id (copy_id);
1580 if (!orig || !copy) {
1581 warning << string_compose (_("Regions in compound description not found (ID's %1 and %2): ignored"),
1587 RegionFactory::add_compound_association (orig, copy);
1594 Session::load_nested_sources (const XMLNode& node)
1597 XMLNodeConstIterator niter;
1599 nlist = node.children();
1601 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1602 if ((*niter)->name() == "Source") {
1604 /* it may already exist, so don't recreate it unnecessarily
1607 XMLProperty* prop = (*niter)->property (X_("id"));
1609 error << _("Nested source has no ID info in session file! (ignored)") << endmsg;
1613 ID source_id (prop->value());
1615 if (!source_by_id (source_id)) {
1618 SourceFactory::create (*this, **niter, true);
1620 catch (failed_constructor& err) {
1621 error << string_compose (_("Cannot reconstruct nested source for region %1"), name()) << endmsg;
1628 boost::shared_ptr<Region>
1629 Session::XMLRegionFactory (const XMLNode& node, bool full)
1631 const XMLProperty* type = node.property("type");
1635 const XMLNodeList& nlist = node.children();
1637 for (XMLNodeConstIterator niter = nlist.begin(); niter != nlist.end(); ++niter) {
1638 XMLNode *child = (*niter);
1639 if (child->name() == "NestedSource") {
1640 load_nested_sources (*child);
1644 if (!type || type->value() == "audio") {
1645 return boost::shared_ptr<Region>(XMLAudioRegionFactory (node, full));
1646 } else if (type->value() == "midi") {
1647 return boost::shared_ptr<Region>(XMLMidiRegionFactory (node, full));
1650 } catch (failed_constructor& err) {
1651 return boost::shared_ptr<Region> ();
1654 return boost::shared_ptr<Region> ();
1657 boost::shared_ptr<AudioRegion>
1658 Session::XMLAudioRegionFactory (const XMLNode& node, bool /*full*/)
1660 const XMLProperty* prop;
1661 boost::shared_ptr<Source> source;
1662 boost::shared_ptr<AudioSource> as;
1664 SourceList master_sources;
1665 uint32_t nchans = 1;
1668 if (node.name() != X_("Region")) {
1669 return boost::shared_ptr<AudioRegion>();
1672 if ((prop = node.property (X_("channels"))) != 0) {
1673 nchans = atoi (prop->value().c_str());
1676 if ((prop = node.property ("name")) == 0) {
1677 cerr << "no name for this region\n";
1681 if ((prop = node.property (X_("source-0"))) == 0) {
1682 if ((prop = node.property ("source")) == 0) {
1683 error << _("Session: XMLNode describing a AudioRegion is incomplete (no source)") << endmsg;
1684 return boost::shared_ptr<AudioRegion>();
1688 PBD::ID s_id (prop->value());
1690 if ((source = source_by_id (s_id)) == 0) {
1691 error << string_compose(_("Session: XMLNode describing a AudioRegion references an unknown source id =%1"), s_id) << endmsg;
1692 return boost::shared_ptr<AudioRegion>();
1695 as = boost::dynamic_pointer_cast<AudioSource>(source);
1697 error << string_compose(_("Session: XMLNode describing a AudioRegion references a non-audio source id =%1"), s_id) << endmsg;
1698 return boost::shared_ptr<AudioRegion>();
1701 sources.push_back (as);
1703 /* pickup other channels */
1705 for (uint32_t n=1; n < nchans; ++n) {
1706 snprintf (buf, sizeof(buf), X_("source-%d"), n);
1707 if ((prop = node.property (buf)) != 0) {
1709 PBD::ID id2 (prop->value());
1711 if ((source = source_by_id (id2)) == 0) {
1712 error << string_compose(_("Session: XMLNode describing a AudioRegion references an unknown source id =%1"), id2) << endmsg;
1713 return boost::shared_ptr<AudioRegion>();
1716 as = boost::dynamic_pointer_cast<AudioSource>(source);
1718 error << string_compose(_("Session: XMLNode describing a AudioRegion references a non-audio source id =%1"), id2) << endmsg;
1719 return boost::shared_ptr<AudioRegion>();
1721 sources.push_back (as);
1725 for (uint32_t n = 0; n < nchans; ++n) {
1726 snprintf (buf, sizeof(buf), X_("master-source-%d"), n);
1727 if ((prop = node.property (buf)) != 0) {
1729 PBD::ID id2 (prop->value());
1731 if ((source = source_by_id (id2)) == 0) {
1732 error << string_compose(_("Session: XMLNode describing a AudioRegion references an unknown source id =%1"), id2) << endmsg;
1733 return boost::shared_ptr<AudioRegion>();
1736 as = boost::dynamic_pointer_cast<AudioSource>(source);
1738 error << string_compose(_("Session: XMLNode describing a AudioRegion references a non-audio source id =%1"), id2) << endmsg;
1739 return boost::shared_ptr<AudioRegion>();
1741 master_sources.push_back (as);
1746 boost::shared_ptr<AudioRegion> region (boost::dynamic_pointer_cast<AudioRegion> (RegionFactory::create (sources, node)));
1748 /* a final detail: this is the one and only place that we know how long missing files are */
1750 if (region->whole_file()) {
1751 for (SourceList::iterator sx = sources.begin(); sx != sources.end(); ++sx) {
1752 boost::shared_ptr<SilentFileSource> sfp = boost::dynamic_pointer_cast<SilentFileSource> (*sx);
1754 sfp->set_length (region->length());
1759 if (!master_sources.empty()) {
1760 if (master_sources.size() != nchans) {
1761 error << _("Session: XMLNode describing an AudioRegion is missing some master sources; ignored") << endmsg;
1763 region->set_master_sources (master_sources);
1771 catch (failed_constructor& err) {
1772 return boost::shared_ptr<AudioRegion>();
1776 boost::shared_ptr<MidiRegion>
1777 Session::XMLMidiRegionFactory (const XMLNode& node, bool /*full*/)
1779 const XMLProperty* prop;
1780 boost::shared_ptr<Source> source;
1781 boost::shared_ptr<MidiSource> ms;
1784 if (node.name() != X_("Region")) {
1785 return boost::shared_ptr<MidiRegion>();
1788 if ((prop = node.property ("name")) == 0) {
1789 cerr << "no name for this region\n";
1793 if ((prop = node.property (X_("source-0"))) == 0) {
1794 if ((prop = node.property ("source")) == 0) {
1795 error << _("Session: XMLNode describing a MidiRegion is incomplete (no source)") << endmsg;
1796 return boost::shared_ptr<MidiRegion>();
1800 PBD::ID s_id (prop->value());
1802 if ((source = source_by_id (s_id)) == 0) {
1803 error << string_compose(_("Session: XMLNode describing a MidiRegion references an unknown source id =%1"), s_id) << endmsg;
1804 return boost::shared_ptr<MidiRegion>();
1807 ms = boost::dynamic_pointer_cast<MidiSource>(source);
1809 error << string_compose(_("Session: XMLNode describing a MidiRegion references a non-midi source id =%1"), s_id) << endmsg;
1810 return boost::shared_ptr<MidiRegion>();
1813 sources.push_back (ms);
1816 boost::shared_ptr<MidiRegion> region (boost::dynamic_pointer_cast<MidiRegion> (RegionFactory::create (sources, node)));
1817 /* a final detail: this is the one and only place that we know how long missing files are */
1819 if (region->whole_file()) {
1820 for (SourceList::iterator sx = sources.begin(); sx != sources.end(); ++sx) {
1821 boost::shared_ptr<SilentFileSource> sfp = boost::dynamic_pointer_cast<SilentFileSource> (*sx);
1823 sfp->set_length (region->length());
1831 catch (failed_constructor& err) {
1832 return boost::shared_ptr<MidiRegion>();
1837 Session::get_sources_as_xml ()
1840 XMLNode* node = new XMLNode (X_("Sources"));
1841 Glib::Threads::Mutex::Lock lm (source_lock);
1843 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ++i) {
1844 node->add_child_nocopy (i->second->get_state());
1851 Session::load_sources (const XMLNode& node)
1854 XMLNodeConstIterator niter;
1855 boost::shared_ptr<Source> source; /* don't need this but it stops some
1856 * versions of gcc complaining about
1857 * discarded return values.
1860 nlist = node.children();
1864 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1867 if ((source = XMLSourceFactory (**niter)) == 0) {
1868 error << _("Session: cannot create Source from XML description.") << endmsg;
1871 } catch (MissingSource& err) {
1875 if (err.type == DataType::MIDI && Glib::path_is_absolute (err.path)) {
1876 error << string_compose (_("A external MIDI file is missing. %1 cannot currently recover from missing external MIDI files"),
1877 PROGRAM_NAME) << endmsg;
1881 if (!no_questions_about_missing_files) {
1882 user_choice = MissingFile (this, err.path, err.type).get_value_or (-1);
1887 switch (user_choice) {
1889 /* user added a new search location, so try again */
1894 /* user asked to quit the entire session load
1899 no_questions_about_missing_files = true;
1903 no_questions_about_missing_files = true;
1910 case DataType::AUDIO:
1911 source = SourceFactory::createSilent (*this, **niter, max_framecnt, _current_frame_rate);
1914 case DataType::MIDI:
1915 /* The MIDI file is actually missing so
1916 * just create a new one in the same
1917 * location. Do not announce its
1921 if (!Glib::path_is_absolute (err.path)) {
1922 fullpath = Glib::build_filename (source_search_path (DataType::MIDI).front(), err.path);
1924 /* this should be an unrecoverable error: we would be creating a MIDI file outside
1929 /* Note that we do not announce the source just yet - we need to reset its ID before we do that */
1930 source = SourceFactory::createWritable (DataType::MIDI, *this, fullpath, false, _current_frame_rate, false, false);
1931 /* reset ID to match the missing one */
1932 source->set_id (**niter);
1933 /* Now we can announce it */
1934 SourceFactory::SourceCreated (source);
1945 boost::shared_ptr<Source>
1946 Session::XMLSourceFactory (const XMLNode& node)
1948 if (node.name() != "Source") {
1949 return boost::shared_ptr<Source>();
1953 /* note: do peak building in another thread when loading session state */
1954 return SourceFactory::create (*this, node, true);
1957 catch (failed_constructor& err) {
1958 error << string_compose (_("Found a sound file that cannot be used by %1. Talk to the programmers."), PROGRAM_NAME) << endmsg;
1959 return boost::shared_ptr<Source>();
1964 Session::save_template (string template_name)
1968 if (_state_of_the_state & CannotSave) {
1972 std::string user_template_dir(user_template_directory());
1974 if (g_mkdir_with_parents (user_template_dir.c_str(), 0755) != 0) {
1975 error << string_compose(_("Could not create templates directory \"%1\" (%2)"),
1976 user_template_dir, g_strerror (errno)) << endmsg;
1980 tree.set_root (&get_template());
1982 std::string template_dir_path(user_template_dir);
1984 /* directory to put the template in */
1985 template_dir_path = Glib::build_filename (template_dir_path, template_name);
1987 if (Glib::file_test (template_dir_path, Glib::FILE_TEST_EXISTS)) {
1988 warning << string_compose(_("Template \"%1\" already exists - new version not created"),
1989 template_dir_path) << endmsg;
1993 if (g_mkdir_with_parents (template_dir_path.c_str(), 0755) != 0) {
1994 error << string_compose(_("Could not create directory for Session template\"%1\" (%2)"),
1995 template_dir_path, g_strerror (errno)) << endmsg;
2000 std::string template_file_path(template_dir_path);
2001 template_file_path = Glib::build_filename (template_file_path, template_name + template_suffix);
2003 if (!tree.write (template_file_path)) {
2004 error << _("template not saved") << endmsg;
2008 /* copy plugin state directory */
2010 std::string template_plugin_state_path(template_dir_path);
2011 template_plugin_state_path = Glib::build_filename (template_plugin_state_path, X_("plugins"));
2013 if (g_mkdir_with_parents (template_plugin_state_path.c_str(), 0755) != 0) {
2014 error << string_compose(_("Could not create directory for Session template plugin state\"%1\" (%2)"),
2015 template_plugin_state_path, g_strerror (errno)) << endmsg;
2019 copy_recurse (plugins_dir(), template_plugin_state_path);
2025 Session::refresh_disk_space ()
2027 #if __APPLE__ || (HAVE_SYS_VFS_H && HAVE_SYS_STATVFS_H)
2029 Glib::Threads::Mutex::Lock lm (space_lock);
2031 /* get freespace on every FS that is part of the session path */
2033 _total_free_4k_blocks = 0;
2034 _total_free_4k_blocks_uncertain = false;
2036 for (vector<space_and_path>::iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
2038 struct statfs statfsbuf;
2039 statfs (i->path.c_str(), &statfsbuf);
2041 double const scale = statfsbuf.f_bsize / 4096.0;
2043 /* See if this filesystem is read-only */
2044 struct statvfs statvfsbuf;
2045 statvfs (i->path.c_str(), &statvfsbuf);
2047 /* f_bavail can be 0 if it is undefined for whatever
2048 filesystem we are looking at; Samba shares mounted
2049 via GVFS are an example of this.
2051 if (statfsbuf.f_bavail == 0) {
2052 /* block count unknown */
2054 i->blocks_unknown = true;
2055 } else if (statvfsbuf.f_flag & ST_RDONLY) {
2056 /* read-only filesystem */
2058 i->blocks_unknown = false;
2060 /* read/write filesystem with known space */
2061 i->blocks = (uint32_t) floor (statfsbuf.f_bavail * scale);
2062 i->blocks_unknown = false;
2065 _total_free_4k_blocks += i->blocks;
2066 if (i->blocks_unknown) {
2067 _total_free_4k_blocks_uncertain = true;
2070 #elif defined (COMPILER_MSVC)
2071 vector<string> scanned_volumes;
2072 vector<string>::iterator j;
2073 vector<space_and_path>::iterator i;
2074 DWORD nSectorsPerCluster, nBytesPerSector,
2075 nFreeClusters, nTotalClusters;
2079 _total_free_4k_blocks = 0;
2081 for (i = session_dirs.begin(); i != session_dirs.end(); i++) {
2082 strncpy (disk_drive, (*i).path.c_str(), 3);
2086 volume_found = false;
2087 if (0 != (GetDiskFreeSpace(disk_drive, &nSectorsPerCluster, &nBytesPerSector, &nFreeClusters, &nTotalClusters)))
2089 int64_t nBytesPerCluster = nBytesPerSector * nSectorsPerCluster;
2090 int64_t nFreeBytes = nBytesPerCluster * (int64_t)nFreeClusters;
2091 i->blocks = (uint32_t)(nFreeBytes / 4096);
2093 for (j = scanned_volumes.begin(); j != scanned_volumes.end(); j++) {
2094 if (0 == j->compare(disk_drive)) {
2095 volume_found = true;
2100 if (!volume_found) {
2101 scanned_volumes.push_back(disk_drive);
2102 _total_free_4k_blocks += i->blocks;
2107 if (0 == _total_free_4k_blocks) {
2108 strncpy (disk_drive, path().c_str(), 3);
2111 if (0 != (GetDiskFreeSpace(disk_drive, &nSectorsPerCluster, &nBytesPerSector, &nFreeClusters, &nTotalClusters)))
2113 int64_t nBytesPerCluster = nBytesPerSector * nSectorsPerCluster;
2114 int64_t nFreeBytes = nBytesPerCluster * (int64_t)nFreeClusters;
2115 _total_free_4k_blocks = (uint32_t)(nFreeBytes / 4096);
2122 Session::get_best_session_directory_for_new_audio ()
2124 vector<space_and_path>::iterator i;
2125 string result = _session_dir->root_path();
2127 /* handle common case without system calls */
2129 if (session_dirs.size() == 1) {
2133 /* OK, here's the algorithm we're following here:
2135 We want to select which directory to use for
2136 the next file source to be created. Ideally,
2137 we'd like to use a round-robin process so as to
2138 get maximum performance benefits from splitting
2139 the files across multiple disks.
2141 However, in situations without much diskspace, an
2142 RR approach may end up filling up a filesystem
2143 with new files while others still have space.
2144 Its therefore important to pay some attention to
2145 the freespace in the filesystem holding each
2146 directory as well. However, if we did that by
2147 itself, we'd keep creating new files in the file
2148 system with the most space until it was as full
2149 as all others, thus negating any performance
2150 benefits of this RAID-1 like approach.
2152 So, we use a user-configurable space threshold. If
2153 there are at least 2 filesystems with more than this
2154 much space available, we use RR selection between them.
2155 If not, then we pick the filesystem with the most space.
2157 This gets a good balance between the two
2161 refresh_disk_space ();
2163 int free_enough = 0;
2165 for (i = session_dirs.begin(); i != session_dirs.end(); ++i) {
2166 if ((*i).blocks * 4096 >= Config->get_disk_choice_space_threshold()) {
2171 if (free_enough >= 2) {
2172 /* use RR selection process, ensuring that the one
2176 i = last_rr_session_dir;
2179 if (++i == session_dirs.end()) {
2180 i = session_dirs.begin();
2183 if ((*i).blocks * 4096 >= Config->get_disk_choice_space_threshold()) {
2184 SessionDirectory sdir(i->path);
2185 if (sdir.create ()) {
2187 last_rr_session_dir = i;
2192 } while (i != last_rr_session_dir);
2196 /* pick FS with the most freespace (and that
2197 seems to actually work ...)
2200 vector<space_and_path> sorted;
2201 space_and_path_ascending_cmp cmp;
2203 sorted = session_dirs;
2204 sort (sorted.begin(), sorted.end(), cmp);
2206 for (i = sorted.begin(); i != sorted.end(); ++i) {
2207 SessionDirectory sdir(i->path);
2208 if (sdir.create ()) {
2210 last_rr_session_dir = i;
2220 Session::automation_dir () const
2222 return Glib::build_filename (_path, "automation");
2226 Session::analysis_dir () const
2228 return Glib::build_filename (_path, "analysis");
2232 Session::plugins_dir () const
2234 return Glib::build_filename (_path, "plugins");
2238 Session::externals_dir () const
2240 return Glib::build_filename (_path, "externals");
2244 Session::load_bundles (XMLNode const & node)
2246 XMLNodeList nlist = node.children();
2247 XMLNodeConstIterator niter;
2251 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2252 if ((*niter)->name() == "InputBundle") {
2253 add_bundle (boost::shared_ptr<UserBundle> (new UserBundle (**niter, true)));
2254 } else if ((*niter)->name() == "OutputBundle") {
2255 add_bundle (boost::shared_ptr<UserBundle> (new UserBundle (**niter, false)));
2257 error << string_compose(_("Unknown node \"%1\" found in Bundles list from session file"), (*niter)->name()) << endmsg;
2266 Session::load_route_groups (const XMLNode& node, int version)
2268 XMLNodeList nlist = node.children();
2269 XMLNodeConstIterator niter;
2273 if (version >= 3000) {
2275 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2276 if ((*niter)->name() == "RouteGroup") {
2277 RouteGroup* rg = new RouteGroup (*this, "");
2278 add_route_group (rg);
2279 rg->set_state (**niter, version);
2283 } else if (version < 3000) {
2285 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2286 if ((*niter)->name() == "EditGroup" || (*niter)->name() == "MixGroup") {
2287 RouteGroup* rg = new RouteGroup (*this, "");
2288 add_route_group (rg);
2289 rg->set_state (**niter, version);
2298 state_file_filter (const string &str, void* /*arg*/)
2300 return (str.length() > strlen(statefile_suffix) &&
2301 str.find (statefile_suffix) == (str.length() - strlen (statefile_suffix)));
2305 remove_end(string state)
2307 string statename(state);
2309 string::size_type start,end;
2310 if ((start = statename.find_last_of (G_DIR_SEPARATOR)) != string::npos) {
2311 statename = statename.substr (start+1);
2314 if ((end = statename.rfind(".ardour")) == string::npos) {
2315 end = statename.length();
2318 return string(statename.substr (0, end));
2322 Session::possible_states (string path)
2324 vector<string> states;
2325 find_files_matching_filter (states, path, state_file_filter, 0, false, false);
2327 transform(states.begin(), states.end(), states.begin(), remove_end);
2329 sort (states.begin(), states.end());
2335 Session::possible_states () const
2337 return possible_states(_path);
2341 Session::add_route_group (RouteGroup* g)
2343 _route_groups.push_back (g);
2344 route_group_added (g); /* EMIT SIGNAL */
2346 g->RouteAdded.connect_same_thread (*this, boost::bind (&Session::route_added_to_route_group, this, _1, _2));
2347 g->RouteRemoved.connect_same_thread (*this, boost::bind (&Session::route_removed_from_route_group, this, _1, _2));
2348 g->PropertyChanged.connect_same_thread (*this, boost::bind (&Session::route_group_property_changed, this, g));
2354 Session::remove_route_group (RouteGroup& rg)
2356 list<RouteGroup*>::iterator i;
2358 if ((i = find (_route_groups.begin(), _route_groups.end(), &rg)) != _route_groups.end()) {
2359 _route_groups.erase (i);
2362 route_group_removed (); /* EMIT SIGNAL */
2366 /** Set a new order for our route groups, without adding or removing any.
2367 * @param groups Route group list in the new order.
2370 Session::reorder_route_groups (list<RouteGroup*> groups)
2372 _route_groups = groups;
2374 route_groups_reordered (); /* EMIT SIGNAL */
2380 Session::route_group_by_name (string name)
2382 list<RouteGroup *>::iterator i;
2384 for (i = _route_groups.begin(); i != _route_groups.end(); ++i) {
2385 if ((*i)->name() == name) {
2393 Session::all_route_group() const
2395 return *_all_route_group;
2399 Session::add_commands (vector<Command*> const & cmds)
2401 for (vector<Command*>::const_iterator i = cmds.begin(); i != cmds.end(); ++i) {
2407 Session::begin_reversible_command (const string& name)
2409 begin_reversible_command (g_quark_from_string (name.c_str ()));
2412 /** Begin a reversible command using a GQuark to identify it.
2413 * begin_reversible_command() and commit_reversible_command() calls may be nested,
2414 * but there must be as many begin...()s as there are commit...()s.
2417 Session::begin_reversible_command (GQuark q)
2419 /* If nested begin/commit pairs are used, we create just one UndoTransaction
2420 to hold all the commands that are committed. This keeps the order of
2421 commands correct in the history.
2424 if (_current_trans == 0) {
2425 /* start a new transaction */
2426 assert (_current_trans_quarks.empty ());
2427 _current_trans = new UndoTransaction();
2428 _current_trans->set_name (g_quark_to_string (q));
2431 _current_trans_quarks.push_front (q);
2435 Session::commit_reversible_command (Command *cmd)
2437 assert (_current_trans);
2438 assert (!_current_trans_quarks.empty ());
2443 _current_trans->add_command (cmd);
2446 _current_trans_quarks.pop_front ();
2448 if (!_current_trans_quarks.empty ()) {
2449 /* the transaction we're committing is not the top-level one */
2453 if (_current_trans->empty()) {
2454 /* no commands were added to the transaction, so just get rid of it */
2455 delete _current_trans;
2460 gettimeofday (&now, 0);
2461 _current_trans->set_timestamp (now);
2463 _history.add (_current_trans);
2468 accept_all_audio_files (const string& path, void* /*arg*/)
2470 if (!Glib::file_test (path, Glib::FILE_TEST_IS_REGULAR)) {
2474 if (!AudioFileSource::safe_audio_file_extension (path)) {
2482 accept_all_midi_files (const string& path, void* /*arg*/)
2484 if (!Glib::file_test (path, Glib::FILE_TEST_IS_REGULAR)) {
2488 return ((path.length() > 4 && path.find (".mid") != (path.length() - 4)) ||
2489 (path.length() > 4 && path.find (".smf") != (path.length() - 4)) ||
2490 (path.length() > 5 && path.find (".midi") != (path.length() - 5)));
2494 accept_all_state_files (const string& path, void* /*arg*/)
2496 if (!Glib::file_test (path, Glib::FILE_TEST_IS_REGULAR)) {
2500 return (path.length() > 7 && path.find (".ardour") == (path.length() - 7));
2504 Session::find_all_sources (string path, set<string>& result)
2509 if (!tree.read (path)) {
2513 if ((node = find_named_node (*tree.root(), "Sources")) == 0) {
2518 XMLNodeConstIterator niter;
2520 nlist = node->children();
2524 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2528 if ((prop = (*niter)->property (X_("type"))) == 0) {
2532 DataType type (prop->value());
2534 if ((prop = (*niter)->property (X_("name"))) == 0) {
2538 if (Glib::path_is_absolute (prop->value())) {
2539 /* external file, ignore */
2547 if (FileSource::find (*this, type, prop->value(), true, is_new, chan, found_path)) {
2548 result.insert (found_path);
2556 Session::find_all_sources_across_snapshots (set<string>& result, bool exclude_this_snapshot)
2558 vector<string> state_files;
2560 string this_snapshot_path;
2566 if (ripped[ripped.length()-1] == G_DIR_SEPARATOR) {
2567 ripped = ripped.substr (0, ripped.length() - 1);
2570 find_files_matching_filter (state_files, ripped, accept_all_state_files, (void *) 0, true, true);
2572 if (state_files.empty()) {
2577 this_snapshot_path = _path;
2578 this_snapshot_path += legalize_for_path (_current_snapshot_name);
2579 this_snapshot_path += statefile_suffix;
2581 for (vector<string>::iterator i = state_files.begin(); i != state_files.end(); ++i) {
2583 if (exclude_this_snapshot && *i == this_snapshot_path) {
2587 if (find_all_sources (*i, result) < 0) {
2595 struct RegionCounter {
2596 typedef std::map<PBD::ID,boost::shared_ptr<AudioSource> > AudioSourceList;
2597 AudioSourceList::iterator iter;
2598 boost::shared_ptr<Region> region;
2601 RegionCounter() : count (0) {}
2605 Session::ask_about_playlist_deletion (boost::shared_ptr<Playlist> p)
2607 boost::optional<int> r = AskAboutPlaylistDeletion (p);
2608 return r.get_value_or (1);
2612 Session::cleanup_regions ()
2614 bool removed = false;
2615 const RegionFactory::RegionMap& regions (RegionFactory::regions());
2617 for (RegionFactory::RegionMap::const_iterator i = regions.begin(); i != regions.end(); ++i) {
2619 uint32_t used = playlists->region_use_count (i->second);
2621 if (used == 0 && !i->second->automatic ()) {
2623 RegionFactory::map_remove (i->second);
2628 // re-check to remove parent references of compound regions
2629 for (RegionFactory::RegionMap::const_iterator i = regions.begin(); i != regions.end(); ++i) {
2630 if (!(i->second->whole_file() && i->second->max_source_level() > 0)) {
2633 assert(boost::dynamic_pointer_cast<PlaylistSource>(i->second->source (0)) != 0);
2634 if (0 == playlists->region_use_count (i->second)) {
2635 RegionFactory::map_remove (i->second);
2640 /* dump the history list */
2647 Session::cleanup_sources (CleanupReport& rep)
2649 // FIXME: needs adaptation to midi
2651 vector<boost::shared_ptr<Source> > dead_sources;
2654 vector<string> candidates;
2655 vector<string> unused;
2656 set<string> all_sources;
2665 _state_of_the_state = (StateOfTheState) (_state_of_the_state | InCleanup);
2667 /* consider deleting all unused playlists */
2669 if (playlists->maybe_delete_unused (boost::bind (Session::ask_about_playlist_deletion, _1))) {
2674 /* sync the "all regions" property of each playlist with its current state
2677 playlists->sync_all_regions_with_regions ();
2679 /* find all un-used sources */
2684 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ) {
2686 SourceMap::iterator tmp;
2691 /* do not bother with files that are zero size, otherwise we remove the current "nascent"
2695 if (!i->second->used() && (i->second->length(i->second->timeline_position() > 0))) {
2696 dead_sources.push_back (i->second);
2697 i->second->drop_references ();
2703 /* build a list of all the possible audio directories for the session */
2705 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
2706 SessionDirectory sdir ((*i).path);
2707 asp += sdir.sound_path();
2709 audio_path += asp.to_string();
2712 /* build a list of all the possible midi directories for the session */
2714 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
2715 SessionDirectory sdir ((*i).path);
2716 msp += sdir.midi_path();
2718 midi_path += msp.to_string();
2720 find_files_matching_filter (candidates, audio_path, accept_all_audio_files, (void *) 0, true, true);
2721 find_files_matching_filter (candidates, midi_path, accept_all_midi_files, (void *) 0, true, true);
2723 /* find all sources, but don't use this snapshot because the
2724 state file on disk still references sources we may have already
2728 find_all_sources_across_snapshots (all_sources, true);
2730 /* add our current source list
2733 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ) {
2734 boost::shared_ptr<FileSource> fs;
2735 SourceMap::iterator tmp = i;
2738 if ((fs = boost::dynamic_pointer_cast<FileSource> (i->second)) != 0) {
2740 if (!fs->is_stub()) {
2742 if (playlists->source_use_count (fs) != 0) {
2743 all_sources.insert (fs->path());
2746 /* we might not remove this source from disk, because it may be used
2747 by other snapshots, but its not being used in this version
2748 so lets get rid of it now, along with any representative regions
2752 RegionFactory::remove_regions_using_source (i->second);
2761 for (vector<string>::iterator x = candidates.begin(); x != candidates.end(); ++x) {
2766 for (set<string>::iterator i = all_sources.begin(); i != all_sources.end(); ++i) {
2768 tmppath1 = canonical_path (spath);
2769 tmppath2 = canonical_path ((*i));
2771 if (tmppath1 == tmppath2) {
2778 unused.push_back (spath);
2782 /* now try to move all unused files into the "dead" directory(ies) */
2784 for (vector<string>::iterator x = unused.begin(); x != unused.end(); ++x) {
2785 struct stat statbuf;
2789 /* don't move the file across filesystems, just
2790 stick it in the `dead_dir_name' directory
2791 on whichever filesystem it was already on.
2794 if ((*x).find ("/sounds/") != string::npos) {
2796 /* old school, go up 1 level */
2798 newpath = Glib::path_get_dirname (*x); // "sounds"
2799 newpath = Glib::path_get_dirname (newpath); // "session-name"
2803 /* new school, go up 4 levels */
2805 newpath = Glib::path_get_dirname (*x); // "audiofiles" or "midifiles"
2806 newpath = Glib::path_get_dirname (newpath); // "session-name"
2807 newpath = Glib::path_get_dirname (newpath); // "interchange"
2808 newpath = Glib::path_get_dirname (newpath); // "session-dir"
2811 newpath = Glib::build_filename (newpath, dead_dir_name);
2813 if (g_mkdir_with_parents (newpath.c_str(), 0755) < 0) {
2814 error << string_compose(_("Session: cannot create dead file folder \"%1\" (%2)"), newpath, strerror (errno)) << endmsg;
2818 newpath = Glib::build_filename (newpath, Glib::path_get_basename ((*x)));
2820 if (Glib::file_test (newpath, Glib::FILE_TEST_EXISTS)) {
2822 /* the new path already exists, try versioning */
2824 char buf[PATH_MAX+1];
2828 snprintf (buf, sizeof (buf), "%s.%d", newpath.c_str(), version);
2831 while (Glib::file_test (newpath_v.c_str(), Glib::FILE_TEST_EXISTS) && version < 999) {
2832 snprintf (buf, sizeof (buf), "%s.%d", newpath.c_str(), ++version);
2836 if (version == 999) {
2837 error << string_compose (_("there are already 1000 files with names like %1; versioning discontinued"),
2841 newpath = newpath_v;
2846 /* it doesn't exist, or we can't read it or something */
2850 stat ((*x).c_str(), &statbuf);
2852 if (::rename ((*x).c_str(), newpath.c_str()) != 0) {
2853 error << string_compose (_("cannot rename unused file source from %1 to %2 (%3)"),
2854 (*x), newpath, strerror (errno))
2859 /* see if there an easy to find peakfile for this file, and remove it.
2862 string base = basename_nosuffix (*x);
2863 base += "%A"; /* this is what we add for the channel suffix of all native files,
2864 or for the first channel of embedded files. it will miss
2865 some peakfiles for other channels
2867 string peakpath = peak_path (base);
2869 if (Glib::file_test (peakpath.c_str(), Glib::FILE_TEST_EXISTS)) {
2870 if (::g_unlink (peakpath.c_str()) != 0) {
2871 error << string_compose (_("cannot remove peakfile %1 for %2 (%3)"),
2872 peakpath, _path, strerror (errno))
2874 /* try to back out */
2875 ::rename (newpath.c_str(), _path.c_str());
2880 rep.paths.push_back (*x);
2881 rep.space += statbuf.st_size;
2884 /* dump the history list */
2888 /* save state so we don't end up a session file
2889 referring to non-existent sources.
2896 _state_of_the_state = (StateOfTheState) (_state_of_the_state & ~InCleanup);
2902 Session::cleanup_trash_sources (CleanupReport& rep)
2904 // FIXME: needs adaptation for MIDI
2906 vector<space_and_path>::iterator i;
2912 for (i = session_dirs.begin(); i != session_dirs.end(); ++i) {
2914 dead_dir = Glib::build_filename ((*i).path, dead_dir_name);
2916 clear_directory (dead_dir, &rep.space, &rep.paths);
2923 Session::set_dirty ()
2925 /* never mark session dirty during loading */
2927 if (_state_of_the_state & Loading) {
2931 bool was_dirty = dirty();
2933 _state_of_the_state = StateOfTheState (_state_of_the_state | Dirty);
2937 DirtyChanged(); /* EMIT SIGNAL */
2943 Session::set_clean ()
2945 bool was_dirty = dirty();
2947 _state_of_the_state = Clean;
2951 DirtyChanged(); /* EMIT SIGNAL */
2956 Session::set_deletion_in_progress ()
2958 _state_of_the_state = StateOfTheState (_state_of_the_state | Deletion);
2962 Session::clear_deletion_in_progress ()
2964 _state_of_the_state = StateOfTheState (_state_of_the_state & (~Deletion));
2968 Session::add_controllable (boost::shared_ptr<Controllable> c)
2970 /* this adds a controllable to the list managed by the Session.
2971 this is a subset of those managed by the Controllable class
2972 itself, and represents the only ones whose state will be saved
2973 as part of the session.
2976 Glib::Threads::Mutex::Lock lm (controllables_lock);
2977 controllables.insert (c);
2980 struct null_deleter { void operator()(void const *) const {} };
2983 Session::remove_controllable (Controllable* c)
2985 if (_state_of_the_state & Deletion) {
2989 Glib::Threads::Mutex::Lock lm (controllables_lock);
2991 Controllables::iterator x = controllables.find (boost::shared_ptr<Controllable>(c, null_deleter()));
2993 if (x != controllables.end()) {
2994 controllables.erase (x);
2998 boost::shared_ptr<Controllable>
2999 Session::controllable_by_id (const PBD::ID& id)
3001 Glib::Threads::Mutex::Lock lm (controllables_lock);
3003 for (Controllables::iterator i = controllables.begin(); i != controllables.end(); ++i) {
3004 if ((*i)->id() == id) {
3009 return boost::shared_ptr<Controllable>();
3012 boost::shared_ptr<Controllable>
3013 Session::controllable_by_descriptor (const ControllableDescriptor& desc)
3015 boost::shared_ptr<Controllable> c;
3016 boost::shared_ptr<Route> r;
3018 switch (desc.top_level_type()) {
3019 case ControllableDescriptor::NamedRoute:
3021 std::string str = desc.top_level_name();
3022 if (str == "Master" || str == "master") {
3024 } else if (str == "control" || str == "listen") {
3027 r = route_by_name (desc.top_level_name());
3032 case ControllableDescriptor::RemoteControlID:
3033 r = route_by_remote_id (desc.rid());
3041 switch (desc.subtype()) {
3042 case ControllableDescriptor::Gain:
3043 c = r->gain_control ();
3046 case ControllableDescriptor::Solo:
3047 c = r->solo_control();
3050 case ControllableDescriptor::Mute:
3051 c = r->mute_control();
3054 case ControllableDescriptor::Recenable:
3056 boost::shared_ptr<Track> t = boost::dynamic_pointer_cast<Track>(r);
3059 c = t->rec_enable_control ();
3064 case ControllableDescriptor::PanDirection:
3066 c = r->pannable()->pan_azimuth_control;
3070 case ControllableDescriptor::PanWidth:
3072 c = r->pannable()->pan_width_control;
3076 case ControllableDescriptor::PanElevation:
3078 c = r->pannable()->pan_elevation_control;
3082 case ControllableDescriptor::Balance:
3083 /* XXX simple pan control */
3086 case ControllableDescriptor::PluginParameter:
3088 uint32_t plugin = desc.target (0);
3089 uint32_t parameter_index = desc.target (1);
3091 /* revert to zero based counting */
3097 if (parameter_index > 0) {
3101 boost::shared_ptr<Processor> p = r->nth_plugin (plugin);
3104 c = boost::dynamic_pointer_cast<ARDOUR::AutomationControl>(
3105 p->control(Evoral::Parameter(PluginAutomation, 0, parameter_index)));
3110 case ControllableDescriptor::SendGain:
3112 uint32_t send = desc.target (0);
3114 /* revert to zero-based counting */
3120 boost::shared_ptr<Processor> p = r->nth_send (send);
3123 boost::shared_ptr<Send> s = boost::dynamic_pointer_cast<Send>(p);
3124 boost::shared_ptr<Amp> a = s->amp();
3127 c = s->amp()->gain_control();
3134 /* relax and return a null pointer */
3142 Session::add_instant_xml (XMLNode& node, bool write_to_config)
3145 Stateful::add_instant_xml (node, _path);
3148 if (write_to_config) {
3149 Config->add_instant_xml (node);
3154 Session::instant_xml (const string& node_name)
3156 return Stateful::instant_xml (node_name, _path);
3160 Session::save_history (string snapshot_name)
3168 if (!Config->get_save_history() || Config->get_saved_history_depth() < 0 ||
3169 (_history.undo_depth() == 0 && _history.redo_depth() == 0)) {
3173 if (snapshot_name.empty()) {
3174 snapshot_name = _current_snapshot_name;
3177 const string history_filename = legalize_for_path (snapshot_name) + history_suffix;
3178 const string backup_filename = history_filename + backup_suffix;
3179 const std::string xml_path(Glib::build_filename (_session_dir->root_path(), history_filename));
3180 const std::string backup_path(Glib::build_filename (_session_dir->root_path(), backup_filename));
3182 if (Glib::file_test (xml_path, Glib::FILE_TEST_EXISTS)) {
3183 if (::g_rename (xml_path.c_str(), backup_path.c_str()) != 0) {
3184 error << _("could not backup old history file, current history not saved") << endmsg;
3189 tree.set_root (&_history.get_state (Config->get_saved_history_depth()));
3191 if (!tree.write (xml_path))
3193 error << string_compose (_("history could not be saved to %1"), xml_path) << endmsg;
3195 if (g_remove (xml_path.c_str()) != 0) {
3196 error << string_compose(_("Could not remove history file at path \"%1\" (%2)"),
3197 xml_path, g_strerror (errno)) << endmsg;
3199 if (::g_rename (backup_path.c_str(), xml_path.c_str()) != 0) {
3200 error << string_compose (_("could not restore history file from backup %1 (%2)"),
3201 backup_path, g_strerror (errno)) << endmsg;
3211 Session::restore_history (string snapshot_name)
3215 if (snapshot_name.empty()) {
3216 snapshot_name = _current_snapshot_name;
3219 const std::string xml_filename = legalize_for_path (snapshot_name) + history_suffix;
3220 const std::string xml_path(Glib::build_filename (_session_dir->root_path(), xml_filename));
3222 info << "Loading history from " << xml_path << endmsg;
3224 if (!Glib::file_test (xml_path, Glib::FILE_TEST_EXISTS)) {
3225 info << string_compose (_("%1: no history file \"%2\" for this session."),
3226 _name, xml_path) << endmsg;
3230 if (!tree.read (xml_path)) {
3231 error << string_compose (_("Could not understand session history file \"%1\""),
3232 xml_path) << endmsg;
3239 for (XMLNodeConstIterator it = tree.root()->children().begin(); it != tree.root()->children().end(); it++) {
3242 UndoTransaction* ut = new UndoTransaction ();
3245 ut->set_name(t->property("name")->value());
3246 stringstream ss(t->property("tv-sec")->value());
3248 ss.str(t->property("tv-usec")->value());
3250 ut->set_timestamp(tv);
3252 for (XMLNodeConstIterator child_it = t->children().begin();
3253 child_it != t->children().end(); child_it++)
3255 XMLNode *n = *child_it;
3258 if (n->name() == "MementoCommand" ||
3259 n->name() == "MementoUndoCommand" ||
3260 n->name() == "MementoRedoCommand") {
3262 if ((c = memento_command_factory(n))) {
3266 } else if (n->name() == "NoteDiffCommand") {
3267 PBD::ID id (n->property("midi-source")->value());
3268 boost::shared_ptr<MidiSource> midi_source =
3269 boost::dynamic_pointer_cast<MidiSource, Source>(source_by_id(id));
3271 ut->add_command (new MidiModel::NoteDiffCommand(midi_source->model(), *n));
3273 error << _("Failed to downcast MidiSource for NoteDiffCommand") << endmsg;
3276 } else if (n->name() == "SysExDiffCommand") {
3278 PBD::ID id (n->property("midi-source")->value());
3279 boost::shared_ptr<MidiSource> midi_source =
3280 boost::dynamic_pointer_cast<MidiSource, Source>(source_by_id(id));
3282 ut->add_command (new MidiModel::SysExDiffCommand (midi_source->model(), *n));
3284 error << _("Failed to downcast MidiSource for SysExDiffCommand") << endmsg;
3287 } else if (n->name() == "PatchChangeDiffCommand") {
3289 PBD::ID id (n->property("midi-source")->value());
3290 boost::shared_ptr<MidiSource> midi_source =
3291 boost::dynamic_pointer_cast<MidiSource, Source>(source_by_id(id));
3293 ut->add_command (new MidiModel::PatchChangeDiffCommand (midi_source->model(), *n));
3295 error << _("Failed to downcast MidiSource for PatchChangeDiffCommand") << endmsg;
3298 } else if (n->name() == "StatefulDiffCommand") {
3299 if ((c = stateful_diff_command_factory (n))) {
3300 ut->add_command (c);
3303 error << string_compose(_("Couldn't figure out how to make a Command out of a %1 XMLNode."), n->name()) << endmsg;
3314 Session::config_changed (std::string p, bool ours)
3320 if (p == "seamless-loop") {
3322 } else if (p == "rf-speed") {
3324 } else if (p == "auto-loop") {
3326 } else if (p == "auto-input") {
3328 if (Config->get_monitoring_model() == HardwareMonitoring && transport_rolling()) {
3329 /* auto-input only makes a difference if we're rolling */
3330 set_track_monitor_input_status (!config.get_auto_input());
3333 } else if (p == "punch-in") {
3337 if ((location = _locations->auto_punch_location()) != 0) {
3339 if (config.get_punch_in ()) {
3340 replace_event (SessionEvent::PunchIn, location->start());
3342 remove_event (location->start(), SessionEvent::PunchIn);
3346 } else if (p == "punch-out") {
3350 if ((location = _locations->auto_punch_location()) != 0) {
3352 if (config.get_punch_out()) {
3353 replace_event (SessionEvent::PunchOut, location->end());
3355 clear_events (SessionEvent::PunchOut);
3359 } else if (p == "edit-mode") {
3361 Glib::Threads::Mutex::Lock lm (playlists->lock);
3363 for (SessionPlaylists::List::iterator i = playlists->playlists.begin(); i != playlists->playlists.end(); ++i) {
3364 (*i)->set_edit_mode (Config->get_edit_mode ());
3367 } else if (p == "use-video-sync") {
3369 waiting_for_sync_offset = config.get_use_video_sync();
3371 } else if (p == "mmc-control") {
3373 //poke_midi_thread ();
3375 } else if (p == "mmc-device-id" || p == "mmc-receive-id" || p == "mmc-receive-device-id") {
3377 _mmc->set_receive_device_id (Config->get_mmc_receive_device_id());
3379 } else if (p == "mmc-send-id" || p == "mmc-send-device-id") {
3381 _mmc->set_send_device_id (Config->get_mmc_send_device_id());
3383 } else if (p == "midi-control") {
3385 //poke_midi_thread ();
3387 } else if (p == "raid-path") {
3389 setup_raid_path (config.get_raid_path());
3391 } else if (p == "timecode-format") {
3395 } else if (p == "video-pullup") {
3399 } else if (p == "seamless-loop") {
3401 if (play_loop && transport_rolling()) {
3402 // to reset diskstreams etc
3403 request_play_loop (true);
3406 } else if (p == "rf-speed") {
3408 cumulative_rf_motion = 0;
3411 } else if (p == "click-sound") {
3413 setup_click_sounds (1);
3415 } else if (p == "click-emphasis-sound") {
3417 setup_click_sounds (-1);
3419 } else if (p == "clicking") {
3421 if (Config->get_clicking()) {
3422 if (_click_io && click_data) { // don't require emphasis data
3429 } else if (p == "click-gain") {
3432 _click_gain->set_gain (Config->get_click_gain(), this);
3435 } else if (p == "send-mtc") {
3437 if (Config->get_send_mtc ()) {
3438 /* mark us ready to send */
3439 next_quarter_frame_to_send = 0;
3442 } else if (p == "send-mmc") {
3444 _mmc->enable_send (Config->get_send_mmc ());
3446 } else if (p == "midi-feedback") {
3448 session_midi_feedback = Config->get_midi_feedback();
3450 } else if (p == "jack-time-master") {
3452 engine().reset_timebase ();
3454 } else if (p == "native-file-header-format") {
3456 if (!first_file_header_format_reset) {
3457 reset_native_file_format ();
3460 first_file_header_format_reset = false;
3462 } else if (p == "native-file-data-format") {
3464 if (!first_file_data_format_reset) {
3465 reset_native_file_format ();
3468 first_file_data_format_reset = false;
3470 } else if (p == "external-sync") {
3471 if (!config.get_external_sync()) {
3472 drop_sync_source ();
3474 switch_to_sync_source (Config->get_sync_source());
3476 } else if (p == "denormal-model") {
3478 } else if (p == "history-depth") {
3479 set_history_depth (Config->get_history_depth());
3480 } else if (p == "remote-model") {
3481 /* XXX DO SOMETHING HERE TO TELL THE GUI THAT WE NEED
3484 } else if (p == "initial-program-change") {
3486 if (_mmc->output_port() && Config->get_initial_program_change() >= 0) {
3489 buf[0] = MIDI::program; // channel zero by default
3490 buf[1] = (Config->get_initial_program_change() & 0x7f);
3492 _mmc->output_port()->midimsg (buf, sizeof (buf), 0);
3494 } else if (p == "solo-mute-override") {
3495 // catch_up_on_solo_mute_override ();
3496 } else if (p == "listen-position" || p == "pfl-position") {
3497 listen_position_changed ();
3498 } else if (p == "solo-control-is-listen-control") {
3499 solo_control_mode_changed ();
3500 } else if (p == "solo-mute-gain") {
3501 _solo_cut_control->Changed();
3502 } else if (p == "timecode-offset" || p == "timecode-offset-negative") {
3503 last_timecode_valid = false;
3504 } else if (p == "playback-buffer-seconds") {
3505 AudioSource::allocate_working_buffers (frame_rate());
3506 } else if (p == "automation-thinning-factor") {
3507 Evoral::ControlList::set_thinning_factor (Config->get_automation_thinning_factor());
3508 } else if (p == "ltc-source-port") {
3509 reconnect_ltc_input ();
3510 } else if (p == "ltc-sink-port") {
3511 reconnect_ltc_output ();
3512 } else if (p == "timecode-generator-offset") {
3513 ltc_tx_parse_offset();
3520 Session::set_history_depth (uint32_t d)
3522 _history.set_depth (d);
3526 Session::load_diskstreams_2X (XMLNode const & node, int)
3529 XMLNodeConstIterator citer;
3531 clist = node.children();
3533 for (citer = clist.begin(); citer != clist.end(); ++citer) {
3536 /* diskstreams added automatically by DiskstreamCreated handler */
3537 if ((*citer)->name() == "AudioDiskstream" || (*citer)->name() == "DiskStream") {
3538 boost::shared_ptr<AudioDiskstream> dsp (new AudioDiskstream (*this, **citer));
3539 _diskstreams_2X.push_back (dsp);
3541 error << _("Session: unknown diskstream type in XML") << endmsg;
3545 catch (failed_constructor& err) {
3546 error << _("Session: could not load diskstream via XML state") << endmsg;
3554 /** Connect things to the MMC object */
3556 Session::setup_midi_machine_control ()
3558 _mmc = new MIDI::MachineControl;
3559 _mmc->set_ports (_midi_ports->mmc_input_port(), _midi_ports->mmc_output_port());
3561 _mmc->Play.connect_same_thread (*this, boost::bind (&Session::mmc_deferred_play, this, _1));
3562 _mmc->DeferredPlay.connect_same_thread (*this, boost::bind (&Session::mmc_deferred_play, this, _1));
3563 _mmc->Stop.connect_same_thread (*this, boost::bind (&Session::mmc_stop, this, _1));
3564 _mmc->FastForward.connect_same_thread (*this, boost::bind (&Session::mmc_fast_forward, this, _1));
3565 _mmc->Rewind.connect_same_thread (*this, boost::bind (&Session::mmc_rewind, this, _1));
3566 _mmc->Pause.connect_same_thread (*this, boost::bind (&Session::mmc_pause, this, _1));
3567 _mmc->RecordPause.connect_same_thread (*this, boost::bind (&Session::mmc_record_pause, this, _1));
3568 _mmc->RecordStrobe.connect_same_thread (*this, boost::bind (&Session::mmc_record_strobe, this, _1));
3569 _mmc->RecordExit.connect_same_thread (*this, boost::bind (&Session::mmc_record_exit, this, _1));
3570 _mmc->Locate.connect_same_thread (*this, boost::bind (&Session::mmc_locate, this, _1, _2));
3571 _mmc->Step.connect_same_thread (*this, boost::bind (&Session::mmc_step, this, _1, _2));
3572 _mmc->Shuttle.connect_same_thread (*this, boost::bind (&Session::mmc_shuttle, this, _1, _2, _3));
3573 _mmc->TrackRecordStatusChange.connect_same_thread (*this, boost::bind (&Session::mmc_record_enable, this, _1, _2, _3));
3575 /* also handle MIDI SPP because its so common */
3577 _mmc->SPPStart.connect_same_thread (*this, boost::bind (&Session::spp_start, this));
3578 _mmc->SPPContinue.connect_same_thread (*this, boost::bind (&Session::spp_continue, this));
3579 _mmc->SPPStop.connect_same_thread (*this, boost::bind (&Session::spp_stop, this));
3582 boost::shared_ptr<Controllable>
3583 Session::solo_cut_control() const
3585 /* the solo cut control is a bit of an anomaly, at least as of Febrary 2011. There are no other
3586 controls in Ardour that currently get presented to the user in the GUI that require
3587 access as a Controllable and are also NOT owned by some SessionObject (e.g. Route, or MonitorProcessor).
3589 its actually an RCConfiguration parameter, so we use a ProxyControllable to wrap
3590 it up as a Controllable. Changes to the Controllable will just map back to the RCConfiguration
3594 return _solo_cut_control;
3598 Session::rename (const std::string& new_name)
3600 string legal_name = legalize_for_path (new_name);
3606 string const old_sources_root = _session_dir->sources_root();
3611 * interchange subdirectory
3615 * Backup files are left unchanged and not renamed.
3618 /* pass one: not 100% safe check that the new directory names don't
3622 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
3627 /* this is a stupid hack because Glib::path_get_dirname() is
3628 * lexical-only, and so passing it /a/b/c/ gives a different
3629 * result than passing it /a/b/c ...
3632 if (oldstr[oldstr.length()-1] == G_DIR_SEPARATOR) {
3633 oldstr = oldstr.substr (0, oldstr.length() - 1);
3636 string base = Glib::path_get_dirname (oldstr);
3637 string p = Glib::path_get_basename (oldstr);
3639 newstr = Glib::build_filename (base, legal_name);
3641 if (Glib::file_test (newstr, Glib::FILE_TEST_EXISTS)) {
3648 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
3653 /* this is a stupid hack because Glib::path_get_dirname() is
3654 * lexical-only, and so passing it /a/b/c/ gives a different
3655 * result than passing it /a/b/c ...
3658 if (oldstr[oldstr.length()-1] == G_DIR_SEPARATOR) {
3659 oldstr = oldstr.substr (0, oldstr.length() - 1);
3662 string base = Glib::path_get_dirname (oldstr);
3663 string p = Glib::path_get_basename (oldstr);
3665 newstr = Glib::build_filename (base, legal_name);
3667 cerr << "Rename " << oldstr << " => " << newstr << endl;
3669 if (::g_rename (oldstr.c_str(), newstr.c_str()) != 0) {
3670 error << string_compose (_("renaming %s as %2 failed (%3)"), oldstr, newstr, g_strerror (errno)) << endmsg;
3675 (*_session_dir) = newstr;
3680 /* directory below interchange */
3682 v.push_back (newstr);
3683 v.push_back (interchange_dir_name);
3686 oldstr = Glib::build_filename (v);
3689 v.push_back (newstr);
3690 v.push_back (interchange_dir_name);
3691 v.push_back (legal_name);
3693 newstr = Glib::build_filename (v);
3695 cerr << "Rename " << oldstr << " => " << newstr << endl;
3697 if (::g_rename (oldstr.c_str(), newstr.c_str()) != 0) {
3698 error << string_compose (_("renaming %s as %2 failed (%3)"), oldstr, newstr, g_strerror (errno)) << endmsg;
3705 oldstr = Glib::build_filename (newpath, _current_snapshot_name) + statefile_suffix;
3706 newstr= Glib::build_filename (newpath, legal_name) + statefile_suffix;
3708 cerr << "Rename " << oldstr << " => " << newstr << endl;
3710 if (::g_rename (oldstr.c_str(), newstr.c_str()) != 0) {
3711 error << string_compose (_("renaming %s as %2 failed (%3)"), oldstr, newstr, g_strerror (errno)) << endmsg;
3718 oldstr = Glib::build_filename (newpath, _current_snapshot_name) + history_suffix;
3720 if (Glib::file_test (oldstr, Glib::FILE_TEST_EXISTS)) {
3721 newstr = Glib::build_filename (newpath, legal_name) + history_suffix;
3723 cerr << "Rename " << oldstr << " => " << newstr << endl;
3725 if (::g_rename (oldstr.c_str(), newstr.c_str()) != 0) {
3726 error << string_compose (_("renaming %s as %2 failed (%3)"), oldstr, newstr, g_strerror (errno)) << endmsg;
3731 /* update file source paths */
3733 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ++i) {
3734 boost::shared_ptr<FileSource> fs = boost::dynamic_pointer_cast<FileSource> (i->second);
3736 string p = fs->path ();
3737 boost::replace_all (p, old_sources_root, _session_dir->sources_root());
3742 /* remove old name from recent sessions */
3744 remove_recent_sessions (_path);
3747 _current_snapshot_name = new_name;
3750 /* re-add directory separator - reverse hack to oldstr above */
3751 if (_path[_path.length()-1] != G_DIR_SEPARATOR) {
3752 _path += G_DIR_SEPARATOR;
3757 /* save state again to get everything just right */
3759 save_state (_current_snapshot_name);
3762 /* add to recent sessions */
3764 store_recent_sessions (new_name, _path);
3770 Session::get_session_info_from_path (XMLTree& tree, const string& xmlpath)
3772 if (!Glib::file_test (xmlpath, Glib::FILE_TEST_EXISTS)) {
3776 if (!tree.read (xmlpath)) {
3784 Session::get_info_from_path (const string& xmlpath, float& sample_rate, SampleFormat& data_format)
3787 bool found_sr = false;
3788 bool found_data_format = false;
3790 if (get_session_info_from_path (tree, xmlpath)) {
3796 const XMLProperty* prop;
3797 if ((prop = tree.root()->property (X_("sample-rate"))) != 0) {
3798 sample_rate = atoi (prop->value());
3802 const XMLNodeList& children (tree.root()->children());
3803 for (XMLNodeList::const_iterator c = children.begin(); c != children.end(); ++c) {
3804 const XMLNode* child = *c;
3805 if (child->name() == "Config") {
3806 const XMLNodeList& options (child->children());
3807 for (XMLNodeList::const_iterator oc = options.begin(); oc != options.end(); ++oc) {
3808 const XMLNode* option = *oc;
3809 const XMLProperty* name = option->property("name");
3815 if (name->value() == "native-file-data-format") {
3816 const XMLProperty* value = option->property ("value");
3818 SampleFormat fmt = (SampleFormat) string_2_enum (option->property ("value")->value(), fmt);
3820 found_data_format = true;
3826 if (found_data_format) {
3831 return !(found_sr && found_data_format); // zero if they are both found
3834 typedef std::vector<boost::shared_ptr<FileSource> > SeveralFileSources;
3835 typedef std::map<std::string,SeveralFileSources> SourcePathMap;
3838 Session::bring_all_sources_into_session (boost::function<void(uint32_t,uint32_t,string)> callback)
3842 SourcePathMap source_path_map;
3844 boost::shared_ptr<AudioFileSource> afs;
3849 Glib::Threads::Mutex::Lock lm (source_lock);
3851 cerr << " total sources = " << sources.size();
3853 for (SourceMap::const_iterator i = sources.begin(); i != sources.end(); ++i) {
3854 boost::shared_ptr<FileSource> fs = boost::dynamic_pointer_cast<FileSource> (i->second);
3860 if (fs->within_session()) {
3861 cerr << "skip " << fs->name() << endl;
3865 if (source_path_map.find (fs->path()) != source_path_map.end()) {
3866 source_path_map[fs->path()].push_back (fs);
3868 SeveralFileSources v;
3870 source_path_map.insert (make_pair (fs->path(), v));
3876 cerr << " fsources = " << total << endl;
3878 for (SourcePathMap::iterator i = source_path_map.begin(); i != source_path_map.end(); ++i) {
3880 /* tell caller where we are */
3882 string old_path = i->first;
3884 callback (n, total, old_path);
3886 cerr << old_path << endl;
3890 switch (i->second.front()->type()) {
3891 case DataType::AUDIO:
3892 new_path = new_audio_source_path_for_embedded (old_path);
3895 case DataType::MIDI:
3899 cerr << "Move " << old_path << " => " << new_path << endl;
3901 if (!copy_file (old_path, new_path)) {
3902 cerr << "failed !\n";
3906 /* make sure we stop looking in the external
3907 dir/folder. Remember, this is an all-or-nothing
3908 operations, it doesn't merge just some files.
3910 remove_dir_from_search_path (Glib::path_get_dirname (old_path), i->second.front()->type());
3912 for (SeveralFileSources::iterator f = i->second.begin(); f != i->second.end(); ++f) {
3913 (*f)->set_path (new_path);
3918 save_state ("", false, false);