2 Copyright (C) 1999-2013 Paul Davis
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 #include "libardour-config.h"
31 #include <cstdio> /* snprintf(3) ... grrr */
44 #include <sys/param.h>
45 #include <sys/mount.h>
48 #ifdef HAVE_SYS_STATVFS_H
49 #include <sys/statvfs.h>
53 #include <glib/gstdio.h>
56 #include <glibmm/threads.h>
58 #include <boost/algorithm/string.hpp>
60 #include "midi++/mmc.h"
61 #include "midi++/port.h"
63 #include "evoral/SMF.hpp"
65 #include "pbd/boost_debug.h"
66 #include "pbd/basename.h"
67 #include "pbd/controllable_descriptor.h"
68 #include "pbd/enumwriter.h"
69 #include "pbd/error.h"
70 #include "pbd/file_utils.h"
71 #include "pbd/pathexpand.h"
72 #include "pbd/pthread_utils.h"
73 #include "pbd/stacktrace.h"
74 #include "pbd/convert.h"
75 #include "pbd/localtime_r.h"
77 #include "ardour/amp.h"
78 #include "ardour/async_midi_port.h"
79 #include "ardour/audio_diskstream.h"
80 #include "ardour/audio_track.h"
81 #include "ardour/audioengine.h"
82 #include "ardour/audiofilesource.h"
83 #include "ardour/audioregion.h"
84 #include "ardour/automation_control.h"
85 #include "ardour/butler.h"
86 #include "ardour/control_protocol_manager.h"
87 #include "ardour/directory_names.h"
88 #include "ardour/filename_extensions.h"
89 #include "ardour/graph.h"
90 #include "ardour/location.h"
91 #include "ardour/midi_model.h"
92 #include "ardour/midi_patch_manager.h"
93 #include "ardour/midi_region.h"
94 #include "ardour/midi_scene_changer.h"
95 #include "ardour/midi_source.h"
96 #include "ardour/midi_track.h"
97 #include "ardour/pannable.h"
98 #include "ardour/playlist_factory.h"
99 #include "ardour/port.h"
100 #include "ardour/processor.h"
101 #include "ardour/proxy_controllable.h"
102 #include "ardour/recent_sessions.h"
103 #include "ardour/region_factory.h"
104 #include "ardour/route_group.h"
105 #include "ardour/send.h"
106 #include "ardour/session.h"
107 #include "ardour/session_directory.h"
108 #include "ardour/session_metadata.h"
109 #include "ardour/session_playlists.h"
110 #include "ardour/session_state_utils.h"
111 #include "ardour/silentfilesource.h"
112 #include "ardour/sndfilesource.h"
113 #include "ardour/source_factory.h"
114 #include "ardour/speakers.h"
115 #include "ardour/template_utils.h"
116 #include "ardour/tempo.h"
117 #include "ardour/ticker.h"
118 #include "ardour/user_bundle.h"
120 #include "control_protocol/control_protocol.h"
126 using namespace ARDOUR;
130 Session::pre_engine_init (string fullpath)
132 if (fullpath.empty()) {
134 throw failed_constructor();
137 /* discover canonical fullpath */
139 _path = canonical_path(fullpath);
141 /* we require _path to end with a dir separator */
143 if (_path[_path.length()-1] != G_DIR_SEPARATOR) {
144 _path += G_DIR_SEPARATOR;
149 _is_new = !Glib::file_test (_path, Glib::FileTest (G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR));
151 /* finish initialization that can't be done in a normal C++ constructor
155 timerclear (&last_mmc_step);
156 g_atomic_int_set (&processing_prohibited, 0);
157 g_atomic_int_set (&_record_status, Disabled);
158 g_atomic_int_set (&_playback_load, 100);
159 g_atomic_int_set (&_capture_load, 100);
161 _all_route_group->set_active (true, this);
162 interpolation.add_channel_to (0, 0);
164 if (config.get_use_video_sync()) {
165 waiting_for_sync_offset = true;
167 waiting_for_sync_offset = false;
170 last_rr_session_dir = session_dirs.begin();
172 set_history_depth (Config->get_history_depth());
174 /* default: assume simple stereo speaker configuration */
176 _speakers->setup_default_speakers (2);
178 _solo_cut_control.reset (new ProxyControllable (_("solo cut control (dB)"), PBD::Controllable::GainLike,
179 boost::bind (&RCConfiguration::set_solo_mute_gain, Config, _1),
180 boost::bind (&RCConfiguration::get_solo_mute_gain, Config)));
181 add_controllable (_solo_cut_control);
183 /* These are all static "per-class" signals */
185 SourceFactory::SourceCreated.connect_same_thread (*this, boost::bind (&Session::add_source, this, _1));
186 PlaylistFactory::PlaylistCreated.connect_same_thread (*this, boost::bind (&Session::add_playlist, this, _1, _2));
187 AutomationList::AutomationListCreated.connect_same_thread (*this, boost::bind (&Session::add_automation_list, this, _1));
188 Controllable::Destroyed.connect_same_thread (*this, boost::bind (&Session::remove_controllable, this, _1));
189 IO::PortCountChanged.connect_same_thread (*this, boost::bind (&Session::ensure_buffers, this, _1));
191 /* stop IO objects from doing stuff until we're ready for them */
193 Delivery::disable_panners ();
194 IO::disable_connecting ();
196 AudioFileSource::set_peak_dir (_session_dir->peak_path());
200 Session::post_engine_init ()
202 BootMessage (_("Set block size and sample rate"));
204 set_block_size (_engine.samples_per_cycle());
205 set_frame_rate (_engine.sample_rate());
207 BootMessage (_("Using configuration"));
209 _midi_ports = new MidiPortManager;
211 MIDISceneChanger* msc;
213 _scene_changer = msc = new MIDISceneChanger (*this);
214 msc->set_input_port (scene_input_port());
215 msc->set_output_port (scene_out());
217 boost::function<framecnt_t(void)> timer_func (boost::bind (&Session::audible_frame, this));
218 boost::dynamic_pointer_cast<AsyncMIDIPort>(scene_in())->set_timer (timer_func);
220 setup_midi_machine_control ();
222 if (_butler->start_thread()) {
226 if (start_midi_thread ()) {
230 setup_click_sounds (0);
231 setup_midi_control ();
233 _engine.Halted.connect_same_thread (*this, boost::bind (&Session::engine_halted, this));
234 _engine.Xrun.connect_same_thread (*this, boost::bind (&Session::xrun_recovery, this));
237 /* tempo map requires sample rate knowledge */
239 _tempo_map = new TempoMap (_current_frame_rate);
240 _tempo_map->PropertyChanged.connect_same_thread (*this, boost::bind (&Session::tempo_map_changed, this, _1));
242 /* MidiClock requires a tempo map */
244 midi_clock = new MidiClockTicker ();
245 midi_clock->set_session (this);
247 /* crossfades require sample rate knowledge */
249 SndFileSource::setup_standard_crossfades (*this, frame_rate());
250 _engine.GraphReordered.connect_same_thread (*this, boost::bind (&Session::graph_reordered, this));
252 AudioDiskstream::allocate_working_buffers();
253 refresh_disk_space ();
255 /* we're finally ready to call set_state() ... all objects have
256 * been created, the engine is running.
260 if (set_state (*state_tree->root(), Stateful::loading_state_version)) {
264 // set_state() will call setup_raid_path(), but if it's a new session we need
265 // to call setup_raid_path() here.
266 setup_raid_path (_path);
271 boost::function<void (std::string)> ff (boost::bind (&Session::config_changed, this, _1, false));
272 boost::function<void (std::string)> ft (boost::bind (&Session::config_changed, this, _1, true));
274 Config->map_parameters (ff);
275 config.map_parameters (ft);
277 /* Reset all panners */
279 Delivery::reset_panners ();
281 /* this will cause the CPM to instantiate any protocols that are in use
282 * (or mandatory), which will pass it this Session, and then call
283 * set_state() on each instantiated protocol to match stored state.
286 ControlProtocolManager::instance().set_session (this);
288 /* This must be done after the ControlProtocolManager set_session above,
289 as it will set states for ports which the ControlProtocolManager creates.
292 // XXX set state of MIDI::Port's
293 // MidiPortManager::instance()->set_port_states (Config->midi_port_states ());
295 /* And this must be done after the MIDI::Manager::set_port_states as
296 * it will try to make connections whose details are loaded by set_port_states.
301 /* Let control protocols know that we are now all connected, so they
302 * could start talking to surfaces if they want to.
305 ControlProtocolManager::instance().midi_connectivity_established ();
307 if (_is_new && !no_auto_connect()) {
308 Glib::Threads::Mutex::Lock lm (AudioEngine::instance()->process_lock());
309 auto_connect_master_bus ();
312 _state_of_the_state = StateOfTheState (_state_of_the_state & ~(CannotSave|Dirty));
314 /* update latencies */
316 initialize_latencies ();
318 _locations->changed.connect_same_thread (*this, boost::bind (&Session::locations_changed, this));
319 _locations->added.connect_same_thread (*this, boost::bind (&Session::locations_added, this, _1));
321 } catch (AudioEngine::PortRegistrationFailure& err) {
322 /* handle this one in a different way than all others, so that its clear what happened */
323 error << err.what() << endmsg;
329 BootMessage (_("Reset Remote Controls"));
331 // send_full_time_code (0);
332 _engine.transport_locate (0);
334 _mmc->send (MIDI::MachineControlCommand (MIDI::MachineControl::cmdMmcReset));
335 _mmc->send (MIDI::MachineControlCommand (Timecode::Time ()));
337 MIDI::Name::MidiPatchManager::instance().set_session (this);
340 /* initial program change will be delivered later; see ::config_changed() */
342 _state_of_the_state = Clean;
344 Port::set_connecting_blocked (false);
346 DirtyChanged (); /* EMIT SIGNAL */
350 } else if (state_was_pending) {
352 remove_pending_capture_state ();
353 state_was_pending = false;
360 Session::raid_path () const
362 Searchpath raid_search_path;
364 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
365 raid_search_path += (*i).path;
368 return raid_search_path.to_string ();
372 Session::setup_raid_path (string path)
381 session_dirs.clear ();
383 Searchpath search_path(path);
384 Searchpath sound_search_path;
385 Searchpath midi_search_path;
387 for (Searchpath::const_iterator i = search_path.begin(); i != search_path.end(); ++i) {
389 sp.blocks = 0; // not needed
390 session_dirs.push_back (sp);
392 SessionDirectory sdir(sp.path);
394 sound_search_path += sdir.sound_path ();
395 midi_search_path += sdir.midi_path ();
398 // reset the round-robin soundfile path thingie
399 last_rr_session_dir = session_dirs.begin();
403 Session::path_is_within_session (const std::string& path)
405 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
406 if (PBD::path_is_within (i->path, path)) {
414 Session::ensure_subdirs ()
418 dir = session_directory().peak_path();
420 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
421 error << string_compose(_("Session: cannot create session peakfile folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
425 dir = session_directory().sound_path();
427 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
428 error << string_compose(_("Session: cannot create session sounds dir \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
432 dir = session_directory().midi_path();
434 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
435 error << string_compose(_("Session: cannot create session midi dir \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
439 dir = session_directory().dead_path();
441 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
442 error << string_compose(_("Session: cannot create session dead sounds folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
446 dir = session_directory().export_path();
448 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
449 error << string_compose(_("Session: cannot create session export folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
453 dir = analysis_dir ();
455 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
456 error << string_compose(_("Session: cannot create session analysis folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
460 dir = plugins_dir ();
462 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
463 error << string_compose(_("Session: cannot create session plugins folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
467 dir = externals_dir ();
469 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
470 error << string_compose(_("Session: cannot create session externals folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
477 /** @param session_template directory containing session template, or empty.
478 * Caller must not hold process lock.
481 Session::create (const string& session_template, BusProfile* bus_profile)
483 if (g_mkdir_with_parents (_path.c_str(), 0755) < 0) {
484 error << string_compose(_("Session: cannot create session folder \"%1\" (%2)"), _path, strerror (errno)) << endmsg;
488 if (ensure_subdirs ()) {
492 _writable = exists_and_writable (_path);
494 if (!session_template.empty()) {
495 std::string in_path = session_template_dir_to_file (session_template);
497 ifstream in(in_path.c_str());
500 /* no need to call legalize_for_path() since the string
501 * in session_template is already a legal path name
503 string out_path = Glib::build_filename (_session_dir->root_path(), _name + statefile_suffix);
505 ofstream out(out_path.c_str());
511 /* Copy plugin state files from template to new session */
512 std::string template_plugins = Glib::build_filename (session_template, X_("plugins"));
513 copy_files (template_plugins, plugins_dir ());
518 error << string_compose (_("Could not open %1 for writing session template"), out_path)
524 error << string_compose (_("Could not open session template %1 for reading"), in_path)
531 /* set initial start + end point */
533 _state_of_the_state = Clean;
535 /* set up Master Out and Control Out if necessary */
540 ChanCount count(DataType::AUDIO, bus_profile->master_out_channels);
542 if (bus_profile->master_out_channels) {
543 boost::shared_ptr<Route> r (new Route (*this, _("Master"), Route::MasterOut, DataType::AUDIO));
547 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
548 // boost_debug_shared_ptr_mark_interesting (r.get(), "Route");
551 Glib::Threads::Mutex::Lock lm (AudioEngine::instance()->process_lock ());
552 r->input()->ensure_io (count, false, this);
553 r->output()->ensure_io (count, false, this);
559 /* prohibit auto-connect to master, because there isn't one */
560 bus_profile->output_ac = AutoConnectOption (bus_profile->output_ac & ~AutoConnectMaster);
564 add_routes (rl, false, false, false);
567 /* this allows the user to override settings with an environment variable.
570 if (no_auto_connect()) {
571 bus_profile->input_ac = AutoConnectOption (0);
572 bus_profile->output_ac = AutoConnectOption (0);
575 Config->set_input_auto_connect (bus_profile->input_ac);
576 Config->set_output_auto_connect (bus_profile->output_ac);
579 if (Config->get_use_monitor_bus() && bus_profile) {
580 add_monitor_section ();
587 Session::maybe_write_autosave()
589 if (dirty() && record_status() != Recording) {
590 save_state("", true);
595 Session::remove_pending_capture_state ()
597 std::string pending_state_file_path(_session_dir->root_path());
599 pending_state_file_path = Glib::build_filename (pending_state_file_path, legalize_for_path (_current_snapshot_name) + pending_suffix);
601 if (!Glib::file_test (pending_state_file_path, Glib::FILE_TEST_EXISTS)) return;
603 if (g_remove (pending_state_file_path.c_str()) != 0) {
604 error << string_compose(_("Could not remove pending capture state at path \"%1\" (%2)"),
605 pending_state_file_path, g_strerror (errno)) << endmsg;
609 /** Rename a state file.
610 * @param old_name Old snapshot name.
611 * @param new_name New snapshot name.
614 Session::rename_state (string old_name, string new_name)
616 if (old_name == _current_snapshot_name || old_name == _name) {
617 /* refuse to rename the current snapshot or the "main" one */
621 const string old_xml_filename = legalize_for_path (old_name) + statefile_suffix;
622 const string new_xml_filename = legalize_for_path (new_name) + statefile_suffix;
624 const std::string old_xml_path(Glib::build_filename (_session_dir->root_path(), old_xml_filename));
625 const std::string new_xml_path(Glib::build_filename (_session_dir->root_path(), new_xml_filename));
627 if (::g_rename (old_xml_path.c_str(), new_xml_path.c_str()) != 0) {
628 error << string_compose(_("could not rename snapshot %1 to %2 (%3)"),
629 old_name, new_name, g_strerror(errno)) << endmsg;
633 /** Remove a state file.
634 * @param snapshot_name Snapshot name.
637 Session::remove_state (string snapshot_name)
639 if (!_writable || snapshot_name == _current_snapshot_name || snapshot_name == _name) {
640 // refuse to remove the current snapshot or the "main" one
644 std::string xml_path(_session_dir->root_path());
646 xml_path = Glib::build_filename (xml_path, legalize_for_path (snapshot_name) + statefile_suffix);
648 if (!create_backup_file (xml_path)) {
649 // don't remove it if a backup can't be made
650 // create_backup_file will log the error.
655 if (g_remove (xml_path.c_str()) != 0) {
656 error << string_compose(_("Could not remove session file at path \"%1\" (%2)"),
657 xml_path, g_strerror (errno)) << endmsg;
661 /** @param snapshot_name Name to save under, without .ardour / .pending prefix */
663 Session::save_state (string snapshot_name, bool pending, bool switch_to_snapshot)
666 std::string xml_path(_session_dir->root_path());
668 /* prevent concurrent saves from different threads */
670 Glib::Threads::Mutex::Lock lm (save_state_lock);
672 if (!_writable || (_state_of_the_state & CannotSave)) {
676 if (g_atomic_int_get(&_suspend_save)) {
680 _save_queued = false;
682 if (!_engine.connected ()) {
683 error << string_compose (_("the %1 audio engine is not connected and state saving would lose all I/O connections. Session not saved"),
689 /* tell sources we're saving first, in case they write out to a new file
690 * which should be saved with the state rather than the old one */
691 for (SourceMap::const_iterator i = sources.begin(); i != sources.end(); ++i) {
693 i->second->session_saved();
694 } catch (Evoral::SMF::FileError& e) {
695 error << string_compose ("Could not write to MIDI file %1; MIDI data not saved.", e.file_name ()) << endmsg;
699 SaveSession (); /* EMIT SIGNAL */
701 tree.set_root (&get_state());
703 if (snapshot_name.empty()) {
704 snapshot_name = _current_snapshot_name;
705 } else if (switch_to_snapshot) {
706 _current_snapshot_name = snapshot_name;
711 /* proper save: use statefile_suffix (.ardour in English) */
713 xml_path = Glib::build_filename (xml_path, legalize_for_path (snapshot_name) + statefile_suffix);
715 /* make a backup copy of the old file */
717 if (Glib::file_test (xml_path, Glib::FILE_TEST_EXISTS) && !create_backup_file (xml_path)) {
718 // create_backup_file will log the error
724 /* pending save: use pending_suffix (.pending in English) */
725 xml_path = Glib::build_filename (xml_path, legalize_for_path (snapshot_name) + pending_suffix);
728 std::string tmp_path(_session_dir->root_path());
729 tmp_path = Glib::build_filename (tmp_path, legalize_for_path (snapshot_name) + temp_suffix);
731 // cerr << "actually writing state to " << xml_path << endl;
733 if (!tree.write (tmp_path)) {
734 error << string_compose (_("state could not be saved to %1"), tmp_path) << endmsg;
735 if (g_remove (tmp_path.c_str()) != 0) {
736 error << string_compose(_("Could not remove temporary session file at path \"%1\" (%2)"),
737 tmp_path, g_strerror (errno)) << endmsg;
743 if (::g_rename (tmp_path.c_str(), xml_path.c_str()) != 0) {
744 error << string_compose (_("could not rename temporary session file %1 to %2 (%3)"),
745 tmp_path, xml_path, g_strerror(errno)) << endmsg;
746 if (g_remove (tmp_path.c_str()) != 0) {
747 error << string_compose(_("Could not remove temporary session file at path \"%1\" (%2)"),
748 tmp_path, g_strerror (errno)) << endmsg;
756 save_history (snapshot_name);
758 bool was_dirty = dirty();
760 _state_of_the_state = StateOfTheState (_state_of_the_state & ~Dirty);
763 DirtyChanged (); /* EMIT SIGNAL */
766 StateSaved (snapshot_name); /* EMIT SIGNAL */
773 Session::restore_state (string snapshot_name)
775 if (load_state (snapshot_name) == 0) {
776 set_state (*state_tree->root(), Stateful::loading_state_version);
783 Session::load_state (string snapshot_name)
788 state_was_pending = false;
790 /* check for leftover pending state from a crashed capture attempt */
792 std::string xmlpath(_session_dir->root_path());
793 xmlpath = Glib::build_filename (xmlpath, legalize_for_path (snapshot_name) + pending_suffix);
795 if (Glib::file_test (xmlpath, Glib::FILE_TEST_EXISTS)) {
797 /* there is pending state from a crashed capture attempt */
799 boost::optional<int> r = AskAboutPendingState();
800 if (r.get_value_or (1)) {
801 state_was_pending = true;
805 if (!state_was_pending) {
806 xmlpath = Glib::build_filename (_session_dir->root_path(), snapshot_name);
809 if (!Glib::file_test (xmlpath, Glib::FILE_TEST_EXISTS)) {
810 xmlpath = Glib::build_filename (_session_dir->root_path(), legalize_for_path (snapshot_name) + statefile_suffix);
811 if (!Glib::file_test (xmlpath, Glib::FILE_TEST_EXISTS)) {
812 error << string_compose(_("%1: session file \"%2\" doesn't exist!"), _name, xmlpath) << endmsg;
817 state_tree = new XMLTree;
821 _writable = exists_and_writable (xmlpath) && exists_and_writable(Glib::path_get_dirname(xmlpath));
823 if (!state_tree->read (xmlpath)) {
824 error << string_compose(_("Could not understand session file %1"), xmlpath) << endmsg;
830 XMLNode& root (*state_tree->root());
832 if (root.name() != X_("Session")) {
833 error << string_compose (_("Session file %1 is not a session"), xmlpath) << endmsg;
839 const XMLProperty* prop;
841 if ((prop = root.property ("version")) == 0) {
842 /* no version implies very old version of Ardour */
843 Stateful::loading_state_version = 1000;
845 if (prop->value().find ('.') != string::npos) {
846 /* old school version format */
847 if (prop->value()[0] == '2') {
848 Stateful::loading_state_version = 2000;
850 Stateful::loading_state_version = 3000;
853 Stateful::loading_state_version = atoi (prop->value());
857 if (Stateful::loading_state_version < CURRENT_SESSION_FILE_VERSION && _writable) {
859 std::string backup_path(_session_dir->root_path());
860 std::string backup_filename = string_compose ("%1-%2%3", legalize_for_path (snapshot_name), Stateful::loading_state_version, statefile_suffix);
861 backup_path = Glib::build_filename (backup_path, backup_filename);
863 // only create a backup for a given statefile version once
865 if (!Glib::file_test (backup_path, Glib::FILE_TEST_EXISTS)) {
867 VersionMismatch (xmlpath, backup_path);
869 if (!copy_file (xmlpath, backup_path)) {;
879 Session::load_options (const XMLNode& node)
881 LocaleGuard lg (X_("POSIX"));
882 config.set_variables (node);
887 Session::save_default_options ()
889 return config.save_state();
899 Session::get_template()
901 /* if we don't disable rec-enable, diskstreams
902 will believe they need to store their capture
903 sources in their state node.
906 disable_record (false);
912 Session::state (bool full_state)
914 XMLNode* node = new XMLNode("Session");
918 snprintf(buf, sizeof(buf), "%d", CURRENT_SESSION_FILE_VERSION);
919 node->add_property("version", buf);
921 /* store configuration settings */
925 node->add_property ("name", _name);
926 snprintf (buf, sizeof (buf), "%" PRId64, _nominal_frame_rate);
927 node->add_property ("sample-rate", buf);
929 if (session_dirs.size() > 1) {
933 vector<space_and_path>::iterator i = session_dirs.begin();
934 vector<space_and_path>::iterator next;
936 ++i; /* skip the first one */
940 while (i != session_dirs.end()) {
944 if (next != session_dirs.end()) {
945 p += G_SEARCHPATH_SEPARATOR;
954 child = node->add_child ("Path");
955 child->add_content (p);
959 /* save the ID counter */
961 snprintf (buf, sizeof (buf), "%" PRIu64, ID::counter());
962 node->add_property ("id-counter", buf);
964 /* save the event ID counter */
966 snprintf (buf, sizeof (buf), "%d", Evoral::event_id_counter());
967 node->add_property ("event-counter", buf);
969 /* various options */
971 list<XMLNode*> midi_port_nodes = _midi_ports->get_midi_port_states();
972 if (!midi_port_nodes.empty()) {
973 XMLNode* midi_port_stuff = new XMLNode ("MIDIPorts");
974 for (list<XMLNode*>::const_iterator n = midi_port_nodes.begin(); n != midi_port_nodes.end(); ++n) {
975 midi_port_stuff->add_child_nocopy (**n);
977 node->add_child_nocopy (*midi_port_stuff);
980 node->add_child_nocopy (config.get_variables ());
982 node->add_child_nocopy (ARDOUR::SessionMetadata::Metadata()->get_state());
984 child = node->add_child ("Sources");
987 Glib::Threads::Mutex::Lock sl (source_lock);
989 for (SourceMap::iterator siter = sources.begin(); siter != sources.end(); ++siter) {
991 /* Don't save information about non-file Sources, or
992 * about non-destructive file sources that are empty
993 * and unused by any regions.
996 boost::shared_ptr<FileSource> fs;
998 if ((fs = boost::dynamic_pointer_cast<FileSource> (siter->second)) != 0) {
1000 if (!fs->destructive()) {
1001 if (fs->empty() && !fs->used()) {
1006 child->add_child_nocopy (siter->second->get_state());
1011 child = node->add_child ("Regions");
1014 Glib::Threads::Mutex::Lock rl (region_lock);
1015 const RegionFactory::RegionMap& region_map (RegionFactory::all_regions());
1016 for (RegionFactory::RegionMap::const_iterator i = region_map.begin(); i != region_map.end(); ++i) {
1017 boost::shared_ptr<Region> r = i->second;
1018 /* only store regions not attached to playlists */
1019 if (r->playlist() == 0) {
1020 if (boost::dynamic_pointer_cast<AudioRegion>(r)) {
1021 child->add_child_nocopy ((boost::dynamic_pointer_cast<AudioRegion>(r))->get_basic_state ());
1023 child->add_child_nocopy (r->get_state ());
1028 RegionFactory::CompoundAssociations& cassocs (RegionFactory::compound_associations());
1030 if (!cassocs.empty()) {
1031 XMLNode* ca = node->add_child (X_("CompoundAssociations"));
1033 for (RegionFactory::CompoundAssociations::iterator i = cassocs.begin(); i != cassocs.end(); ++i) {
1035 XMLNode* can = new XMLNode (X_("CompoundAssociation"));
1036 i->first->id().print (buf, sizeof (buf));
1037 can->add_property (X_("copy"), buf);
1038 i->second->id().print (buf, sizeof (buf));
1039 can->add_property (X_("original"), buf);
1040 ca->add_child_nocopy (*can);
1046 node->add_child_nocopy (_locations->get_state());
1048 // for a template, just create a new Locations, populate it
1049 // with the default start and end, and get the state for that.
1050 Locations loc (*this);
1051 Location* range = new Location (*this, 0, 0, _("session"), Location::IsSessionRange);
1052 range->set (max_framepos, 0);
1054 node->add_child_nocopy (loc.get_state());
1057 child = node->add_child ("Bundles");
1059 boost::shared_ptr<BundleList> bundles = _bundles.reader ();
1060 for (BundleList::iterator i = bundles->begin(); i != bundles->end(); ++i) {
1061 boost::shared_ptr<UserBundle> b = boost::dynamic_pointer_cast<UserBundle> (*i);
1063 child->add_child_nocopy (b->get_state());
1068 child = node->add_child ("Routes");
1070 boost::shared_ptr<RouteList> r = routes.reader ();
1072 RoutePublicOrderSorter cmp;
1073 RouteList public_order (*r);
1074 public_order.sort (cmp);
1076 /* the sort should have put control outs first */
1079 assert (_monitor_out == public_order.front());
1082 for (RouteList::iterator i = public_order.begin(); i != public_order.end(); ++i) {
1083 if (!(*i)->is_auditioner()) {
1085 child->add_child_nocopy ((*i)->get_state());
1087 child->add_child_nocopy ((*i)->get_template());
1093 playlists->add_state (node, full_state);
1095 child = node->add_child ("RouteGroups");
1096 for (list<RouteGroup *>::iterator i = _route_groups.begin(); i != _route_groups.end(); ++i) {
1097 child->add_child_nocopy ((*i)->get_state());
1101 XMLNode* gain_child = node->add_child ("Click");
1102 gain_child->add_child_nocopy (_click_io->state (full_state));
1103 gain_child->add_child_nocopy (_click_gain->state (full_state));
1107 XMLNode* ltc_input_child = node->add_child ("LTC-In");
1108 ltc_input_child->add_child_nocopy (_ltc_input->state (full_state));
1112 XMLNode* ltc_output_child = node->add_child ("LTC-Out");
1113 ltc_output_child->add_child_nocopy (_ltc_output->state (full_state));
1116 node->add_child_nocopy (_speakers->get_state());
1117 node->add_child_nocopy (_tempo_map->get_state());
1118 node->add_child_nocopy (get_control_protocol_state());
1121 node->add_child_copy (*_extra_xml);
1128 Session::get_control_protocol_state ()
1130 ControlProtocolManager& cpm (ControlProtocolManager::instance());
1131 return cpm.get_state();
1135 Session::set_state (const XMLNode& node, int version)
1139 const XMLProperty* prop;
1142 _state_of_the_state = StateOfTheState (_state_of_the_state|CannotSave);
1144 if (node.name() != X_("Session")) {
1145 fatal << _("programming error: Session: incorrect XML node sent to set_state()") << endmsg;
1149 if ((prop = node.property ("name")) != 0) {
1150 _name = prop->value ();
1153 if ((prop = node.property (X_("sample-rate"))) != 0) {
1155 _nominal_frame_rate = atoi (prop->value());
1157 if (_nominal_frame_rate != _current_frame_rate) {
1158 boost::optional<int> r = AskAboutSampleRateMismatch (_nominal_frame_rate, _current_frame_rate);
1159 if (r.get_value_or (0)) {
1165 setup_raid_path(_session_dir->root_path());
1167 if ((prop = node.property (X_("id-counter"))) != 0) {
1169 sscanf (prop->value().c_str(), "%" PRIu64, &x);
1170 ID::init_counter (x);
1172 /* old sessions used a timebased counter, so fake
1173 the startup ID counter based on a standard
1178 ID::init_counter (now);
1181 if ((prop = node.property (X_("event-counter"))) != 0) {
1182 Evoral::init_event_id_counter (atoi (prop->value()));
1186 if ((child = find_named_node (node, "MIDIPorts")) != 0) {
1187 _midi_ports->set_midi_port_states (child->children());
1190 IO::disable_connecting ();
1192 Stateful::save_extra_xml (node);
1194 if (((child = find_named_node (node, "Options")) != 0)) { /* old style */
1195 load_options (*child);
1196 } else if ((child = find_named_node (node, "Config")) != 0) { /* new style */
1197 load_options (*child);
1199 error << _("Session: XML state has no options section") << endmsg;
1202 if (version >= 3000) {
1203 if ((child = find_named_node (node, "Metadata")) == 0) {
1204 warning << _("Session: XML state has no metadata section") << endmsg;
1205 } else if ( ARDOUR::SessionMetadata::Metadata()->set_state (*child, version) ) {
1210 if ((child = find_named_node (node, X_("Speakers"))) != 0) {
1211 _speakers->set_state (*child, version);
1214 if ((child = find_named_node (node, "Sources")) == 0) {
1215 error << _("Session: XML state has no sources section") << endmsg;
1217 } else if (load_sources (*child)) {
1221 if ((child = find_named_node (node, "TempoMap")) == 0) {
1222 error << _("Session: XML state has no Tempo Map section") << endmsg;
1224 } else if (_tempo_map->set_state (*child, version)) {
1228 if ((child = find_named_node (node, "Locations")) == 0) {
1229 error << _("Session: XML state has no locations section") << endmsg;
1231 } else if (_locations->set_state (*child, version)) {
1237 if ((location = _locations->auto_loop_location()) != 0) {
1238 set_auto_loop_location (location);
1241 if ((location = _locations->auto_punch_location()) != 0) {
1242 set_auto_punch_location (location);
1245 if ((location = _locations->session_range_location()) != 0) {
1246 delete _session_range_location;
1247 _session_range_location = location;
1250 if (_session_range_location) {
1251 AudioFileSource::set_header_position_offset (_session_range_location->start());
1254 if ((child = find_named_node (node, "Regions")) == 0) {
1255 error << _("Session: XML state has no Regions section") << endmsg;
1257 } else if (load_regions (*child)) {
1261 if ((child = find_named_node (node, "Playlists")) == 0) {
1262 error << _("Session: XML state has no playlists section") << endmsg;
1264 } else if (playlists->load (*this, *child)) {
1268 if ((child = find_named_node (node, "UnusedPlaylists")) == 0) {
1270 } else if (playlists->load_unused (*this, *child)) {
1274 if ((child = find_named_node (node, "CompoundAssociations")) != 0) {
1275 if (load_compounds (*child)) {
1280 if (version >= 3000) {
1281 if ((child = find_named_node (node, "Bundles")) == 0) {
1282 warning << _("Session: XML state has no bundles section") << endmsg;
1285 /* We can't load Bundles yet as they need to be able
1286 to convert from port names to Port objects, which can't happen until
1288 _bundle_xml_node = new XMLNode (*child);
1292 if (version < 3000) {
1293 if ((child = find_named_node (node, X_("DiskStreams"))) == 0) {
1294 error << _("Session: XML state has no diskstreams section") << endmsg;
1296 } else if (load_diskstreams_2X (*child, version)) {
1301 if ((child = find_named_node (node, "Routes")) == 0) {
1302 error << _("Session: XML state has no routes section") << endmsg;
1304 } else if (load_routes (*child, version)) {
1308 /* our diskstreams list is no longer needed as they are now all owned by their Route */
1309 _diskstreams_2X.clear ();
1311 if (version >= 3000) {
1313 if ((child = find_named_node (node, "RouteGroups")) == 0) {
1314 error << _("Session: XML state has no route groups section") << endmsg;
1316 } else if (load_route_groups (*child, version)) {
1320 } else if (version < 3000) {
1322 if ((child = find_named_node (node, "EditGroups")) == 0) {
1323 error << _("Session: XML state has no edit groups section") << endmsg;
1325 } else if (load_route_groups (*child, version)) {
1329 if ((child = find_named_node (node, "MixGroups")) == 0) {
1330 error << _("Session: XML state has no mix groups section") << endmsg;
1332 } else if (load_route_groups (*child, version)) {
1337 if ((child = find_named_node (node, "Click")) == 0) {
1338 warning << _("Session: XML state has no click section") << endmsg;
1339 } else if (_click_io) {
1340 setup_click_state (&node);
1343 if ((child = find_named_node (node, ControlProtocolManager::state_node_name)) != 0) {
1344 ControlProtocolManager::instance().set_state (*child, version);
1347 update_have_rec_enabled_track ();
1349 /* here beginneth the second phase ... */
1351 StateReady (); /* EMIT SIGNAL */
1360 Session::load_routes (const XMLNode& node, int version)
1363 XMLNodeConstIterator niter;
1364 RouteList new_routes;
1366 nlist = node.children();
1370 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1372 boost::shared_ptr<Route> route;
1373 if (version < 3000) {
1374 route = XMLRouteFactory_2X (**niter, version);
1376 route = XMLRouteFactory (**niter, version);
1380 error << _("Session: cannot create Route from XML description.") << endmsg;
1384 BootMessage (string_compose (_("Loaded track/bus %1"), route->name()));
1386 new_routes.push_back (route);
1389 add_routes (new_routes, false, false, false);
1394 boost::shared_ptr<Route>
1395 Session::XMLRouteFactory (const XMLNode& node, int version)
1397 boost::shared_ptr<Route> ret;
1399 if (node.name() != "Route") {
1403 XMLNode* ds_child = find_named_node (node, X_("Diskstream"));
1405 DataType type = DataType::AUDIO;
1406 const XMLProperty* prop = node.property("default-type");
1409 type = DataType (prop->value());
1412 assert (type != DataType::NIL);
1416 boost::shared_ptr<Track> track;
1418 if (type == DataType::AUDIO) {
1419 track.reset (new AudioTrack (*this, X_("toBeResetFroXML")));
1421 track.reset (new MidiTrack (*this, X_("toBeResetFroXML")));
1424 if (track->init()) {
1428 if (track->set_state (node, version)) {
1432 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
1433 // boost_debug_shared_ptr_mark_interesting (track.get(), "Track");
1438 enum Route::Flag flags = Route::Flag(0);
1439 const XMLProperty* prop = node.property("flags");
1441 flags = Route::Flag (string_2_enum (prop->value(), flags));
1444 boost::shared_ptr<Route> r (new Route (*this, X_("toBeResetFroXML"), flags));
1446 if (r->init () == 0 && r->set_state (node, version) == 0) {
1447 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
1448 // boost_debug_shared_ptr_mark_interesting (r.get(), "Route");
1457 boost::shared_ptr<Route>
1458 Session::XMLRouteFactory_2X (const XMLNode& node, int version)
1460 boost::shared_ptr<Route> ret;
1462 if (node.name() != "Route") {
1466 XMLProperty const * ds_prop = node.property (X_("diskstream-id"));
1468 ds_prop = node.property (X_("diskstream"));
1471 DataType type = DataType::AUDIO;
1472 const XMLProperty* prop = node.property("default-type");
1475 type = DataType (prop->value());
1478 assert (type != DataType::NIL);
1482 list<boost::shared_ptr<Diskstream> >::iterator i = _diskstreams_2X.begin ();
1483 while (i != _diskstreams_2X.end() && (*i)->id() != ds_prop->value()) {
1487 if (i == _diskstreams_2X.end()) {
1488 error << _("Could not find diskstream for route") << endmsg;
1489 return boost::shared_ptr<Route> ();
1492 boost::shared_ptr<Track> track;
1494 if (type == DataType::AUDIO) {
1495 track.reset (new AudioTrack (*this, X_("toBeResetFroXML")));
1497 track.reset (new MidiTrack (*this, X_("toBeResetFroXML")));
1500 if (track->init()) {
1504 if (track->set_state (node, version)) {
1508 track->set_diskstream (*i);
1510 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
1511 // boost_debug_shared_ptr_mark_interesting (track.get(), "Track");
1516 enum Route::Flag flags = Route::Flag(0);
1517 const XMLProperty* prop = node.property("flags");
1519 flags = Route::Flag (string_2_enum (prop->value(), flags));
1522 boost::shared_ptr<Route> r (new Route (*this, X_("toBeResetFroXML"), flags));
1524 if (r->init () == 0 && r->set_state (node, version) == 0) {
1525 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
1526 // boost_debug_shared_ptr_mark_interesting (r.get(), "Route");
1536 Session::load_regions (const XMLNode& node)
1539 XMLNodeConstIterator niter;
1540 boost::shared_ptr<Region> region;
1542 nlist = node.children();
1546 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1547 if ((region = XMLRegionFactory (**niter, false)) == 0) {
1548 error << _("Session: cannot create Region from XML description.");
1549 const XMLProperty *name = (**niter).property("name");
1552 error << " " << string_compose (_("Can not load state for region '%1'"), name->value());
1563 Session::load_compounds (const XMLNode& node)
1565 XMLNodeList calist = node.children();
1566 XMLNodeConstIterator caiter;
1567 XMLProperty *caprop;
1569 for (caiter = calist.begin(); caiter != calist.end(); ++caiter) {
1570 XMLNode* ca = *caiter;
1574 if ((caprop = ca->property (X_("original"))) == 0) {
1577 orig_id = caprop->value();
1579 if ((caprop = ca->property (X_("copy"))) == 0) {
1582 copy_id = caprop->value();
1584 boost::shared_ptr<Region> orig = RegionFactory::region_by_id (orig_id);
1585 boost::shared_ptr<Region> copy = RegionFactory::region_by_id (copy_id);
1587 if (!orig || !copy) {
1588 warning << string_compose (_("Regions in compound description not found (ID's %1 and %2): ignored"),
1594 RegionFactory::add_compound_association (orig, copy);
1601 Session::load_nested_sources (const XMLNode& node)
1604 XMLNodeConstIterator niter;
1606 nlist = node.children();
1608 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1609 if ((*niter)->name() == "Source") {
1611 /* it may already exist, so don't recreate it unnecessarily
1614 XMLProperty* prop = (*niter)->property (X_("id"));
1616 error << _("Nested source has no ID info in session file! (ignored)") << endmsg;
1620 ID source_id (prop->value());
1622 if (!source_by_id (source_id)) {
1625 SourceFactory::create (*this, **niter, true);
1627 catch (failed_constructor& err) {
1628 error << string_compose (_("Cannot reconstruct nested source for region %1"), name()) << endmsg;
1635 boost::shared_ptr<Region>
1636 Session::XMLRegionFactory (const XMLNode& node, bool full)
1638 const XMLProperty* type = node.property("type");
1642 const XMLNodeList& nlist = node.children();
1644 for (XMLNodeConstIterator niter = nlist.begin(); niter != nlist.end(); ++niter) {
1645 XMLNode *child = (*niter);
1646 if (child->name() == "NestedSource") {
1647 load_nested_sources (*child);
1651 if (!type || type->value() == "audio") {
1652 return boost::shared_ptr<Region>(XMLAudioRegionFactory (node, full));
1653 } else if (type->value() == "midi") {
1654 return boost::shared_ptr<Region>(XMLMidiRegionFactory (node, full));
1657 } catch (failed_constructor& err) {
1658 return boost::shared_ptr<Region> ();
1661 return boost::shared_ptr<Region> ();
1664 boost::shared_ptr<AudioRegion>
1665 Session::XMLAudioRegionFactory (const XMLNode& node, bool /*full*/)
1667 const XMLProperty* prop;
1668 boost::shared_ptr<Source> source;
1669 boost::shared_ptr<AudioSource> as;
1671 SourceList master_sources;
1672 uint32_t nchans = 1;
1675 if (node.name() != X_("Region")) {
1676 return boost::shared_ptr<AudioRegion>();
1679 if ((prop = node.property (X_("channels"))) != 0) {
1680 nchans = atoi (prop->value().c_str());
1683 if ((prop = node.property ("name")) == 0) {
1684 cerr << "no name for this region\n";
1688 if ((prop = node.property (X_("source-0"))) == 0) {
1689 if ((prop = node.property ("source")) == 0) {
1690 error << _("Session: XMLNode describing a AudioRegion is incomplete (no source)") << endmsg;
1691 return boost::shared_ptr<AudioRegion>();
1695 PBD::ID s_id (prop->value());
1697 if ((source = source_by_id (s_id)) == 0) {
1698 error << string_compose(_("Session: XMLNode describing a AudioRegion references an unknown source id =%1"), s_id) << endmsg;
1699 return boost::shared_ptr<AudioRegion>();
1702 as = boost::dynamic_pointer_cast<AudioSource>(source);
1704 error << string_compose(_("Session: XMLNode describing a AudioRegion references a non-audio source id =%1"), s_id) << endmsg;
1705 return boost::shared_ptr<AudioRegion>();
1708 sources.push_back (as);
1710 /* pickup other channels */
1712 for (uint32_t n=1; n < nchans; ++n) {
1713 snprintf (buf, sizeof(buf), X_("source-%d"), n);
1714 if ((prop = node.property (buf)) != 0) {
1716 PBD::ID id2 (prop->value());
1718 if ((source = source_by_id (id2)) == 0) {
1719 error << string_compose(_("Session: XMLNode describing a AudioRegion references an unknown source id =%1"), id2) << endmsg;
1720 return boost::shared_ptr<AudioRegion>();
1723 as = boost::dynamic_pointer_cast<AudioSource>(source);
1725 error << string_compose(_("Session: XMLNode describing a AudioRegion references a non-audio source id =%1"), id2) << endmsg;
1726 return boost::shared_ptr<AudioRegion>();
1728 sources.push_back (as);
1732 for (uint32_t n = 0; n < nchans; ++n) {
1733 snprintf (buf, sizeof(buf), X_("master-source-%d"), n);
1734 if ((prop = node.property (buf)) != 0) {
1736 PBD::ID id2 (prop->value());
1738 if ((source = source_by_id (id2)) == 0) {
1739 error << string_compose(_("Session: XMLNode describing a AudioRegion references an unknown source id =%1"), id2) << endmsg;
1740 return boost::shared_ptr<AudioRegion>();
1743 as = boost::dynamic_pointer_cast<AudioSource>(source);
1745 error << string_compose(_("Session: XMLNode describing a AudioRegion references a non-audio source id =%1"), id2) << endmsg;
1746 return boost::shared_ptr<AudioRegion>();
1748 master_sources.push_back (as);
1753 boost::shared_ptr<AudioRegion> region (boost::dynamic_pointer_cast<AudioRegion> (RegionFactory::create (sources, node)));
1755 /* a final detail: this is the one and only place that we know how long missing files are */
1757 if (region->whole_file()) {
1758 for (SourceList::iterator sx = sources.begin(); sx != sources.end(); ++sx) {
1759 boost::shared_ptr<SilentFileSource> sfp = boost::dynamic_pointer_cast<SilentFileSource> (*sx);
1761 sfp->set_length (region->length());
1766 if (!master_sources.empty()) {
1767 if (master_sources.size() != nchans) {
1768 error << _("Session: XMLNode describing an AudioRegion is missing some master sources; ignored") << endmsg;
1770 region->set_master_sources (master_sources);
1778 catch (failed_constructor& err) {
1779 return boost::shared_ptr<AudioRegion>();
1783 boost::shared_ptr<MidiRegion>
1784 Session::XMLMidiRegionFactory (const XMLNode& node, bool /*full*/)
1786 const XMLProperty* prop;
1787 boost::shared_ptr<Source> source;
1788 boost::shared_ptr<MidiSource> ms;
1791 if (node.name() != X_("Region")) {
1792 return boost::shared_ptr<MidiRegion>();
1795 if ((prop = node.property ("name")) == 0) {
1796 cerr << "no name for this region\n";
1800 if ((prop = node.property (X_("source-0"))) == 0) {
1801 if ((prop = node.property ("source")) == 0) {
1802 error << _("Session: XMLNode describing a MidiRegion is incomplete (no source)") << endmsg;
1803 return boost::shared_ptr<MidiRegion>();
1807 PBD::ID s_id (prop->value());
1809 if ((source = source_by_id (s_id)) == 0) {
1810 error << string_compose(_("Session: XMLNode describing a MidiRegion references an unknown source id =%1"), s_id) << endmsg;
1811 return boost::shared_ptr<MidiRegion>();
1814 ms = boost::dynamic_pointer_cast<MidiSource>(source);
1816 error << string_compose(_("Session: XMLNode describing a MidiRegion references a non-midi source id =%1"), s_id) << endmsg;
1817 return boost::shared_ptr<MidiRegion>();
1820 sources.push_back (ms);
1823 boost::shared_ptr<MidiRegion> region (boost::dynamic_pointer_cast<MidiRegion> (RegionFactory::create (sources, node)));
1824 /* a final detail: this is the one and only place that we know how long missing files are */
1826 if (region->whole_file()) {
1827 for (SourceList::iterator sx = sources.begin(); sx != sources.end(); ++sx) {
1828 boost::shared_ptr<SilentFileSource> sfp = boost::dynamic_pointer_cast<SilentFileSource> (*sx);
1830 sfp->set_length (region->length());
1838 catch (failed_constructor& err) {
1839 return boost::shared_ptr<MidiRegion>();
1844 Session::get_sources_as_xml ()
1847 XMLNode* node = new XMLNode (X_("Sources"));
1848 Glib::Threads::Mutex::Lock lm (source_lock);
1850 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ++i) {
1851 node->add_child_nocopy (i->second->get_state());
1858 Session::load_sources (const XMLNode& node)
1861 XMLNodeConstIterator niter;
1862 boost::shared_ptr<Source> source;
1864 nlist = node.children();
1868 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1871 if ((source = XMLSourceFactory (**niter)) == 0) {
1872 error << _("Session: cannot create Source from XML description.") << endmsg;
1875 } catch (MissingSource& err) {
1879 if (!no_questions_about_missing_files) {
1880 user_choice = MissingFile (this, err.path, err.type).get_value_or (-1);
1885 switch (user_choice) {
1887 /* user added a new search location, so try again */
1892 /* user asked to quit the entire session load
1897 no_questions_about_missing_files = true;
1901 no_questions_about_missing_files = true;
1906 warning << _("A sound file is missing. It will be replaced by silence.") << endmsg;
1907 source = SourceFactory::createSilent (*this, **niter, max_framecnt, _current_frame_rate);
1916 boost::shared_ptr<Source>
1917 Session::XMLSourceFactory (const XMLNode& node)
1919 if (node.name() != "Source") {
1920 return boost::shared_ptr<Source>();
1924 /* note: do peak building in another thread when loading session state */
1925 return SourceFactory::create (*this, node, true);
1928 catch (failed_constructor& err) {
1929 error << string_compose (_("Found a sound file that cannot be used by %1. Talk to the progammers."), PROGRAM_NAME) << endmsg;
1930 return boost::shared_ptr<Source>();
1935 Session::save_template (string template_name)
1939 if (_state_of_the_state & CannotSave) {
1943 std::string user_template_dir(user_template_directory());
1945 if (g_mkdir_with_parents (user_template_dir.c_str(), 0755) != 0) {
1946 error << string_compose(_("Could not create templates directory \"%1\" (%2)"),
1947 user_template_dir, g_strerror (errno)) << endmsg;
1951 tree.set_root (&get_template());
1953 std::string template_dir_path(user_template_dir);
1955 /* directory to put the template in */
1956 template_dir_path = Glib::build_filename (template_dir_path, template_name);
1958 if (Glib::file_test (template_dir_path, Glib::FILE_TEST_EXISTS)) {
1959 warning << string_compose(_("Template \"%1\" already exists - new version not created"),
1960 template_dir_path) << endmsg;
1964 if (g_mkdir_with_parents (template_dir_path.c_str(), 0755) != 0) {
1965 error << string_compose(_("Could not create directory for Session template\"%1\" (%2)"),
1966 template_dir_path, g_strerror (errno)) << endmsg;
1971 std::string template_file_path(template_dir_path);
1972 template_file_path = Glib::build_filename (template_file_path, template_name + template_suffix);
1974 if (!tree.write (template_file_path)) {
1975 error << _("template not saved") << endmsg;
1979 /* copy plugin state directory */
1981 std::string template_plugin_state_path(template_dir_path);
1982 template_plugin_state_path = Glib::build_filename (template_plugin_state_path, X_("plugins"));
1984 if (g_mkdir_with_parents (template_plugin_state_path.c_str(), 0755) != 0) {
1985 error << string_compose(_("Could not create directory for Session template plugin state\"%1\" (%2)"),
1986 template_plugin_state_path, g_strerror (errno)) << endmsg;
1990 copy_files (plugins_dir(), template_plugin_state_path);
1996 Session::refresh_disk_space ()
1998 #if __APPLE__ || (HAVE_SYS_VFS_H && HAVE_SYS_STATVFS_H)
2000 Glib::Threads::Mutex::Lock lm (space_lock);
2002 /* get freespace on every FS that is part of the session path */
2004 _total_free_4k_blocks = 0;
2005 _total_free_4k_blocks_uncertain = false;
2007 for (vector<space_and_path>::iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
2009 struct statfs statfsbuf;
2010 statfs (i->path.c_str(), &statfsbuf);
2012 double const scale = statfsbuf.f_bsize / 4096.0;
2014 /* See if this filesystem is read-only */
2015 struct statvfs statvfsbuf;
2016 statvfs (i->path.c_str(), &statvfsbuf);
2018 /* f_bavail can be 0 if it is undefined for whatever
2019 filesystem we are looking at; Samba shares mounted
2020 via GVFS are an example of this.
2022 if (statfsbuf.f_bavail == 0) {
2023 /* block count unknown */
2025 i->blocks_unknown = true;
2026 } else if (statvfsbuf.f_flag & ST_RDONLY) {
2027 /* read-only filesystem */
2029 i->blocks_unknown = false;
2031 /* read/write filesystem with known space */
2032 i->blocks = (uint32_t) floor (statfsbuf.f_bavail * scale);
2033 i->blocks_unknown = false;
2036 _total_free_4k_blocks += i->blocks;
2037 if (i->blocks_unknown) {
2038 _total_free_4k_blocks_uncertain = true;
2041 #elif defined (COMPILER_MSVC)
2042 vector<string> scanned_volumes;
2043 vector<string>::iterator j;
2044 vector<space_and_path>::iterator i;
2045 DWORD nSectorsPerCluster, nBytesPerSector,
2046 nFreeClusters, nTotalClusters;
2050 _total_free_4k_blocks = 0;
2052 for (i = session_dirs.begin(); i != session_dirs.end(); i++) {
2053 strncpy (disk_drive, (*i).path.c_str(), 3);
2057 volume_found = false;
2058 if (0 != (GetDiskFreeSpace(disk_drive, &nSectorsPerCluster, &nBytesPerSector, &nFreeClusters, &nTotalClusters)))
2060 int64_t nBytesPerCluster = nBytesPerSector * nSectorsPerCluster;
2061 int64_t nFreeBytes = nBytesPerCluster * (int64_t)nFreeClusters;
2062 i->blocks = (uint32_t)(nFreeBytes / 4096);
2064 for (j = scanned_volumes.begin(); j != scanned_volumes.end(); j++) {
2065 if (0 == j->compare(disk_drive)) {
2066 volume_found = true;
2071 if (!volume_found) {
2072 scanned_volumes.push_back(disk_drive);
2073 _total_free_4k_blocks += i->blocks;
2078 if (0 == _total_free_4k_blocks) {
2079 strncpy (disk_drive, path().c_str(), 3);
2082 if (0 != (GetDiskFreeSpace(disk_drive, &nSectorsPerCluster, &nBytesPerSector, &nFreeClusters, &nTotalClusters)))
2084 int64_t nBytesPerCluster = nBytesPerSector * nSectorsPerCluster;
2085 int64_t nFreeBytes = nBytesPerCluster * (int64_t)nFreeClusters;
2086 _total_free_4k_blocks = (uint32_t)(nFreeBytes / 4096);
2093 Session::get_best_session_directory_for_new_audio ()
2095 vector<space_and_path>::iterator i;
2096 string result = _session_dir->root_path();
2098 /* handle common case without system calls */
2100 if (session_dirs.size() == 1) {
2104 /* OK, here's the algorithm we're following here:
2106 We want to select which directory to use for
2107 the next file source to be created. Ideally,
2108 we'd like to use a round-robin process so as to
2109 get maximum performance benefits from splitting
2110 the files across multiple disks.
2112 However, in situations without much diskspace, an
2113 RR approach may end up filling up a filesystem
2114 with new files while others still have space.
2115 Its therefore important to pay some attention to
2116 the freespace in the filesystem holding each
2117 directory as well. However, if we did that by
2118 itself, we'd keep creating new files in the file
2119 system with the most space until it was as full
2120 as all others, thus negating any performance
2121 benefits of this RAID-1 like approach.
2123 So, we use a user-configurable space threshold. If
2124 there are at least 2 filesystems with more than this
2125 much space available, we use RR selection between them.
2126 If not, then we pick the filesystem with the most space.
2128 This gets a good balance between the two
2132 refresh_disk_space ();
2134 int free_enough = 0;
2136 for (i = session_dirs.begin(); i != session_dirs.end(); ++i) {
2137 if ((*i).blocks * 4096 >= Config->get_disk_choice_space_threshold()) {
2142 if (free_enough >= 2) {
2143 /* use RR selection process, ensuring that the one
2147 i = last_rr_session_dir;
2150 if (++i == session_dirs.end()) {
2151 i = session_dirs.begin();
2154 if ((*i).blocks * 4096 >= Config->get_disk_choice_space_threshold()) {
2155 SessionDirectory sdir(i->path);
2156 if (sdir.create ()) {
2158 last_rr_session_dir = i;
2163 } while (i != last_rr_session_dir);
2167 /* pick FS with the most freespace (and that
2168 seems to actually work ...)
2171 vector<space_and_path> sorted;
2172 space_and_path_ascending_cmp cmp;
2174 sorted = session_dirs;
2175 sort (sorted.begin(), sorted.end(), cmp);
2177 for (i = sorted.begin(); i != sorted.end(); ++i) {
2178 SessionDirectory sdir(i->path);
2179 if (sdir.create ()) {
2181 last_rr_session_dir = i;
2191 Session::automation_dir () const
2193 return Glib::build_filename (_path, "automation");
2197 Session::analysis_dir () const
2199 return Glib::build_filename (_path, "analysis");
2203 Session::plugins_dir () const
2205 return Glib::build_filename (_path, "plugins");
2209 Session::externals_dir () const
2211 return Glib::build_filename (_path, "externals");
2215 Session::load_bundles (XMLNode const & node)
2217 XMLNodeList nlist = node.children();
2218 XMLNodeConstIterator niter;
2222 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2223 if ((*niter)->name() == "InputBundle") {
2224 add_bundle (boost::shared_ptr<UserBundle> (new UserBundle (**niter, true)));
2225 } else if ((*niter)->name() == "OutputBundle") {
2226 add_bundle (boost::shared_ptr<UserBundle> (new UserBundle (**niter, false)));
2228 error << string_compose(_("Unknown node \"%1\" found in Bundles list from session file"), (*niter)->name()) << endmsg;
2237 Session::load_route_groups (const XMLNode& node, int version)
2239 XMLNodeList nlist = node.children();
2240 XMLNodeConstIterator niter;
2244 if (version >= 3000) {
2246 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2247 if ((*niter)->name() == "RouteGroup") {
2248 RouteGroup* rg = new RouteGroup (*this, "");
2249 add_route_group (rg);
2250 rg->set_state (**niter, version);
2254 } else if (version < 3000) {
2256 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2257 if ((*niter)->name() == "EditGroup" || (*niter)->name() == "MixGroup") {
2258 RouteGroup* rg = new RouteGroup (*this, "");
2259 add_route_group (rg);
2260 rg->set_state (**niter, version);
2269 state_file_filter (const string &str, void* /*arg*/)
2271 return (str.length() > strlen(statefile_suffix) &&
2272 str.find (statefile_suffix) == (str.length() - strlen (statefile_suffix)));
2276 remove_end(string state)
2278 string statename(state);
2280 string::size_type start,end;
2281 if ((start = statename.find_last_of (G_DIR_SEPARATOR)) != string::npos) {
2282 statename = statename.substr (start+1);
2285 if ((end = statename.rfind(".ardour")) == string::npos) {
2286 end = statename.length();
2289 return string(statename.substr (0, end));
2293 Session::possible_states (string path)
2295 vector<string> states;
2296 find_files_matching_filter (states, path, state_file_filter, 0, false, false);
2298 transform(states.begin(), states.end(), states.begin(), remove_end);
2300 sort (states.begin(), states.end());
2306 Session::possible_states () const
2308 return possible_states(_path);
2312 Session::add_route_group (RouteGroup* g)
2314 _route_groups.push_back (g);
2315 route_group_added (g); /* EMIT SIGNAL */
2317 g->RouteAdded.connect_same_thread (*this, boost::bind (&Session::route_added_to_route_group, this, _1, _2));
2318 g->RouteRemoved.connect_same_thread (*this, boost::bind (&Session::route_removed_from_route_group, this, _1, _2));
2319 g->PropertyChanged.connect_same_thread (*this, boost::bind (&Session::route_group_property_changed, this, g));
2325 Session::remove_route_group (RouteGroup& rg)
2327 list<RouteGroup*>::iterator i;
2329 if ((i = find (_route_groups.begin(), _route_groups.end(), &rg)) != _route_groups.end()) {
2330 _route_groups.erase (i);
2333 route_group_removed (); /* EMIT SIGNAL */
2337 /** Set a new order for our route groups, without adding or removing any.
2338 * @param groups Route group list in the new order.
2341 Session::reorder_route_groups (list<RouteGroup*> groups)
2343 _route_groups = groups;
2345 route_groups_reordered (); /* EMIT SIGNAL */
2351 Session::route_group_by_name (string name)
2353 list<RouteGroup *>::iterator i;
2355 for (i = _route_groups.begin(); i != _route_groups.end(); ++i) {
2356 if ((*i)->name() == name) {
2364 Session::all_route_group() const
2366 return *_all_route_group;
2370 Session::add_commands (vector<Command*> const & cmds)
2372 for (vector<Command*>::const_iterator i = cmds.begin(); i != cmds.end(); ++i) {
2378 Session::begin_reversible_command (const string& name)
2380 begin_reversible_command (g_quark_from_string (name.c_str ()));
2383 /** Begin a reversible command using a GQuark to identify it.
2384 * begin_reversible_command() and commit_reversible_command() calls may be nested,
2385 * but there must be as many begin...()s as there are commit...()s.
2388 Session::begin_reversible_command (GQuark q)
2390 /* If nested begin/commit pairs are used, we create just one UndoTransaction
2391 to hold all the commands that are committed. This keeps the order of
2392 commands correct in the history.
2395 if (_current_trans == 0) {
2396 /* start a new transaction */
2397 assert (_current_trans_quarks.empty ());
2398 _current_trans = new UndoTransaction();
2399 _current_trans->set_name (g_quark_to_string (q));
2402 _current_trans_quarks.push_front (q);
2406 Session::commit_reversible_command (Command *cmd)
2408 assert (_current_trans);
2409 assert (!_current_trans_quarks.empty ());
2414 _current_trans->add_command (cmd);
2417 _current_trans_quarks.pop_front ();
2419 if (!_current_trans_quarks.empty ()) {
2420 /* the transaction we're committing is not the top-level one */
2424 if (_current_trans->empty()) {
2425 /* no commands were added to the transaction, so just get rid of it */
2426 delete _current_trans;
2431 gettimeofday (&now, 0);
2432 _current_trans->set_timestamp (now);
2434 _history.add (_current_trans);
2439 accept_all_audio_files (const string& path, void* /*arg*/)
2441 if (!Glib::file_test (path, Glib::FILE_TEST_IS_REGULAR)) {
2445 if (!AudioFileSource::safe_audio_file_extension (path)) {
2453 accept_all_midi_files (const string& path, void* /*arg*/)
2455 if (!Glib::file_test (path, Glib::FILE_TEST_IS_REGULAR)) {
2459 return ((path.length() > 4 && path.find (".mid") != (path.length() - 4)) ||
2460 (path.length() > 4 && path.find (".smf") != (path.length() - 4)) ||
2461 (path.length() > 5 && path.find (".midi") != (path.length() - 5)));
2465 accept_all_state_files (const string& path, void* /*arg*/)
2467 if (!Glib::file_test (path, Glib::FILE_TEST_IS_REGULAR)) {
2471 return (path.length() > 7 && path.find (".ardour") == (path.length() - 7));
2475 Session::find_all_sources (string path, set<string>& result)
2480 if (!tree.read (path)) {
2484 if ((node = find_named_node (*tree.root(), "Sources")) == 0) {
2489 XMLNodeConstIterator niter;
2491 nlist = node->children();
2495 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2499 if ((prop = (*niter)->property (X_("type"))) == 0) {
2503 DataType type (prop->value());
2505 if ((prop = (*niter)->property (X_("name"))) == 0) {
2509 if (Glib::path_is_absolute (prop->value())) {
2510 /* external file, ignore */
2518 if (FileSource::find (*this, type, prop->value(), true, is_new, chan, found_path)) {
2519 result.insert (found_path);
2527 Session::find_all_sources_across_snapshots (set<string>& result, bool exclude_this_snapshot)
2529 vector<string> state_files;
2531 string this_snapshot_path;
2537 if (ripped[ripped.length()-1] == G_DIR_SEPARATOR) {
2538 ripped = ripped.substr (0, ripped.length() - 1);
2541 find_files_matching_filter (state_files, ripped, accept_all_state_files, (void *) 0, true, true);
2543 if (state_files.empty()) {
2548 this_snapshot_path = _path;
2549 this_snapshot_path += legalize_for_path (_current_snapshot_name);
2550 this_snapshot_path += statefile_suffix;
2552 for (vector<string>::iterator i = state_files.begin(); i != state_files.end(); ++i) {
2554 if (exclude_this_snapshot && *i == this_snapshot_path) {
2558 if (find_all_sources (*i, result) < 0) {
2566 struct RegionCounter {
2567 typedef std::map<PBD::ID,boost::shared_ptr<AudioSource> > AudioSourceList;
2568 AudioSourceList::iterator iter;
2569 boost::shared_ptr<Region> region;
2572 RegionCounter() : count (0) {}
2576 Session::ask_about_playlist_deletion (boost::shared_ptr<Playlist> p)
2578 boost::optional<int> r = AskAboutPlaylistDeletion (p);
2579 return r.get_value_or (1);
2583 Session::cleanup_regions ()
2585 const RegionFactory::RegionMap& regions (RegionFactory::regions());
2587 for (RegionFactory::RegionMap::const_iterator i = regions.begin(); i != regions.end(); ++i) {
2589 uint32_t used = playlists->region_use_count (i->second);
2591 if (used == 0 && !i->second->automatic ()) {
2592 RegionFactory::map_remove (i->second);
2596 /* dump the history list */
2603 Session::cleanup_sources (CleanupReport& rep)
2605 // FIXME: needs adaptation to midi
2607 vector<boost::shared_ptr<Source> > dead_sources;
2610 vector<string> candidates;
2611 vector<string> unused;
2612 set<string> all_sources;
2621 _state_of_the_state = (StateOfTheState) (_state_of_the_state | InCleanup);
2623 /* consider deleting all unused playlists */
2625 if (playlists->maybe_delete_unused (boost::bind (Session::ask_about_playlist_deletion, _1))) {
2630 /* sync the "all regions" property of each playlist with its current state
2633 playlists->sync_all_regions_with_regions ();
2635 /* find all un-used sources */
2640 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ) {
2642 SourceMap::iterator tmp;
2647 /* do not bother with files that are zero size, otherwise we remove the current "nascent"
2651 if (!i->second->used() && (i->second->length(i->second->timeline_position() > 0))) {
2652 dead_sources.push_back (i->second);
2653 i->second->drop_references ();
2659 /* build a list of all the possible audio directories for the session */
2661 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
2662 SessionDirectory sdir ((*i).path);
2663 asp += sdir.sound_path();
2665 audio_path += asp.to_string();
2668 /* build a list of all the possible midi directories for the session */
2670 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
2671 SessionDirectory sdir ((*i).path);
2672 msp += sdir.midi_path();
2674 midi_path += msp.to_string();
2676 find_files_matching_filter (candidates, audio_path, accept_all_audio_files, (void *) 0, true, true);
2677 find_files_matching_filter (candidates, midi_path, accept_all_midi_files, (void *) 0, true, true);
2679 /* find all sources, but don't use this snapshot because the
2680 state file on disk still references sources we may have already
2684 find_all_sources_across_snapshots (all_sources, true);
2686 /* add our current source list
2689 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ) {
2690 boost::shared_ptr<FileSource> fs;
2691 SourceMap::iterator tmp = i;
2694 if ((fs = boost::dynamic_pointer_cast<FileSource> (i->second)) != 0) {
2696 if (!fs->is_stub()) {
2698 if (playlists->source_use_count (fs) != 0) {
2699 all_sources.insert (fs->path());
2702 /* we might not remove this source from disk, because it may be used
2703 by other snapshots, but its not being used in this version
2704 so lets get rid of it now, along with any representative regions
2708 RegionFactory::remove_regions_using_source (i->second);
2717 for (vector<string>::iterator x = candidates.begin(); x != candidates.end(); ++x) {
2722 for (set<string>::iterator i = all_sources.begin(); i != all_sources.end(); ++i) {
2724 tmppath1 = canonical_path (spath);
2725 tmppath2 = canonical_path ((*i));
2727 if (tmppath1 == tmppath2) {
2734 unused.push_back (spath);
2738 /* now try to move all unused files into the "dead" directory(ies) */
2740 for (vector<string>::iterator x = unused.begin(); x != unused.end(); ++x) {
2741 struct stat statbuf;
2745 /* don't move the file across filesystems, just
2746 stick it in the `dead_dir_name' directory
2747 on whichever filesystem it was already on.
2750 if ((*x).find ("/sounds/") != string::npos) {
2752 /* old school, go up 1 level */
2754 newpath = Glib::path_get_dirname (*x); // "sounds"
2755 newpath = Glib::path_get_dirname (newpath); // "session-name"
2759 /* new school, go up 4 levels */
2761 newpath = Glib::path_get_dirname (*x); // "audiofiles" or "midifiles"
2762 newpath = Glib::path_get_dirname (newpath); // "session-name"
2763 newpath = Glib::path_get_dirname (newpath); // "interchange"
2764 newpath = Glib::path_get_dirname (newpath); // "session-dir"
2767 newpath = Glib::build_filename (newpath, dead_dir_name);
2769 if (g_mkdir_with_parents (newpath.c_str(), 0755) < 0) {
2770 error << string_compose(_("Session: cannot create dead file folder \"%1\" (%2)"), newpath, strerror (errno)) << endmsg;
2774 newpath = Glib::build_filename (newpath, Glib::path_get_basename ((*x)));
2776 if (Glib::file_test (newpath, Glib::FILE_TEST_EXISTS)) {
2778 /* the new path already exists, try versioning */
2780 char buf[PATH_MAX+1];
2784 snprintf (buf, sizeof (buf), "%s.%d", newpath.c_str(), version);
2787 while (Glib::file_test (newpath_v.c_str(), Glib::FILE_TEST_EXISTS) && version < 999) {
2788 snprintf (buf, sizeof (buf), "%s.%d", newpath.c_str(), ++version);
2792 if (version == 999) {
2793 error << string_compose (_("there are already 1000 files with names like %1; versioning discontinued"),
2797 newpath = newpath_v;
2802 /* it doesn't exist, or we can't read it or something */
2806 stat ((*x).c_str(), &statbuf);
2808 if (::rename ((*x).c_str(), newpath.c_str()) != 0) {
2809 error << string_compose (_("cannot rename unused file source from %1 to %2 (%3)"),
2810 (*x), newpath, strerror (errno))
2815 /* see if there an easy to find peakfile for this file, and remove it.
2818 string base = basename_nosuffix (*x);
2819 base += "%A"; /* this is what we add for the channel suffix of all native files,
2820 or for the first channel of embedded files. it will miss
2821 some peakfiles for other channels
2823 string peakpath = peak_path (base);
2825 if (Glib::file_test (peakpath.c_str(), Glib::FILE_TEST_EXISTS)) {
2826 if (::g_unlink (peakpath.c_str()) != 0) {
2827 error << string_compose (_("cannot remove peakfile %1 for %2 (%3)"),
2828 peakpath, _path, strerror (errno))
2830 /* try to back out */
2831 ::rename (newpath.c_str(), _path.c_str());
2836 rep.paths.push_back (*x);
2837 rep.space += statbuf.st_size;
2840 /* dump the history list */
2844 /* save state so we don't end up a session file
2845 referring to non-existent sources.
2852 _state_of_the_state = (StateOfTheState) (_state_of_the_state & ~InCleanup);
2858 Session::cleanup_trash_sources (CleanupReport& rep)
2860 // FIXME: needs adaptation for MIDI
2862 vector<space_and_path>::iterator i;
2868 for (i = session_dirs.begin(); i != session_dirs.end(); ++i) {
2870 dead_dir = Glib::build_filename ((*i).path, dead_dir_name);
2872 clear_directory (dead_dir, &rep.space, &rep.paths);
2879 Session::set_dirty ()
2881 bool was_dirty = dirty();
2883 _state_of_the_state = StateOfTheState (_state_of_the_state | Dirty);
2887 DirtyChanged(); /* EMIT SIGNAL */
2893 Session::set_clean ()
2895 bool was_dirty = dirty();
2897 _state_of_the_state = Clean;
2901 DirtyChanged(); /* EMIT SIGNAL */
2906 Session::set_deletion_in_progress ()
2908 _state_of_the_state = StateOfTheState (_state_of_the_state | Deletion);
2912 Session::clear_deletion_in_progress ()
2914 _state_of_the_state = StateOfTheState (_state_of_the_state & (~Deletion));
2918 Session::add_controllable (boost::shared_ptr<Controllable> c)
2920 /* this adds a controllable to the list managed by the Session.
2921 this is a subset of those managed by the Controllable class
2922 itself, and represents the only ones whose state will be saved
2923 as part of the session.
2926 Glib::Threads::Mutex::Lock lm (controllables_lock);
2927 controllables.insert (c);
2930 struct null_deleter { void operator()(void const *) const {} };
2933 Session::remove_controllable (Controllable* c)
2935 if (_state_of_the_state & Deletion) {
2939 Glib::Threads::Mutex::Lock lm (controllables_lock);
2941 Controllables::iterator x = controllables.find (boost::shared_ptr<Controllable>(c, null_deleter()));
2943 if (x != controllables.end()) {
2944 controllables.erase (x);
2948 boost::shared_ptr<Controllable>
2949 Session::controllable_by_id (const PBD::ID& id)
2951 Glib::Threads::Mutex::Lock lm (controllables_lock);
2953 for (Controllables::iterator i = controllables.begin(); i != controllables.end(); ++i) {
2954 if ((*i)->id() == id) {
2959 return boost::shared_ptr<Controllable>();
2962 boost::shared_ptr<Controllable>
2963 Session::controllable_by_descriptor (const ControllableDescriptor& desc)
2965 boost::shared_ptr<Controllable> c;
2966 boost::shared_ptr<Route> r;
2968 switch (desc.top_level_type()) {
2969 case ControllableDescriptor::NamedRoute:
2971 std::string str = desc.top_level_name();
2972 if (str == "Master" || str == "master") {
2974 } else if (str == "control" || str == "listen") {
2977 r = route_by_name (desc.top_level_name());
2982 case ControllableDescriptor::RemoteControlID:
2983 r = route_by_remote_id (desc.rid());
2991 switch (desc.subtype()) {
2992 case ControllableDescriptor::Gain:
2993 c = r->gain_control ();
2996 case ControllableDescriptor::Solo:
2997 c = r->solo_control();
3000 case ControllableDescriptor::Mute:
3001 c = r->mute_control();
3004 case ControllableDescriptor::Recenable:
3006 boost::shared_ptr<Track> t = boost::dynamic_pointer_cast<Track>(r);
3009 c = t->rec_enable_control ();
3014 case ControllableDescriptor::PanDirection:
3016 c = r->pannable()->pan_azimuth_control;
3020 case ControllableDescriptor::PanWidth:
3022 c = r->pannable()->pan_width_control;
3026 case ControllableDescriptor::PanElevation:
3028 c = r->pannable()->pan_elevation_control;
3032 case ControllableDescriptor::Balance:
3033 /* XXX simple pan control */
3036 case ControllableDescriptor::PluginParameter:
3038 uint32_t plugin = desc.target (0);
3039 uint32_t parameter_index = desc.target (1);
3041 /* revert to zero based counting */
3047 if (parameter_index > 0) {
3051 boost::shared_ptr<Processor> p = r->nth_plugin (plugin);
3054 c = boost::dynamic_pointer_cast<ARDOUR::AutomationControl>(
3055 p->control(Evoral::Parameter(PluginAutomation, 0, parameter_index)));
3060 case ControllableDescriptor::SendGain:
3062 uint32_t send = desc.target (0);
3064 /* revert to zero-based counting */
3070 boost::shared_ptr<Processor> p = r->nth_send (send);
3073 boost::shared_ptr<Send> s = boost::dynamic_pointer_cast<Send>(p);
3074 boost::shared_ptr<Amp> a = s->amp();
3077 c = s->amp()->gain_control();
3084 /* relax and return a null pointer */
3092 Session::add_instant_xml (XMLNode& node, bool write_to_config)
3095 Stateful::add_instant_xml (node, _path);
3098 if (write_to_config) {
3099 Config->add_instant_xml (node);
3104 Session::instant_xml (const string& node_name)
3106 return Stateful::instant_xml (node_name, _path);
3110 Session::save_history (string snapshot_name)
3118 if (!Config->get_save_history() || Config->get_saved_history_depth() < 0 ||
3119 (_history.undo_depth() == 0 && _history.redo_depth() == 0)) {
3123 if (snapshot_name.empty()) {
3124 snapshot_name = _current_snapshot_name;
3127 const string history_filename = legalize_for_path (snapshot_name) + history_suffix;
3128 const string backup_filename = history_filename + backup_suffix;
3129 const std::string xml_path(Glib::build_filename (_session_dir->root_path(), history_filename));
3130 const std::string backup_path(Glib::build_filename (_session_dir->root_path(), backup_filename));
3132 if (Glib::file_test (xml_path, Glib::FILE_TEST_EXISTS)) {
3133 if (::g_rename (xml_path.c_str(), backup_path.c_str()) != 0) {
3134 error << _("could not backup old history file, current history not saved") << endmsg;
3139 tree.set_root (&_history.get_state (Config->get_saved_history_depth()));
3141 if (!tree.write (xml_path))
3143 error << string_compose (_("history could not be saved to %1"), xml_path) << endmsg;
3145 if (g_remove (xml_path.c_str()) != 0) {
3146 error << string_compose(_("Could not remove history file at path \"%1\" (%2)"),
3147 xml_path, g_strerror (errno)) << endmsg;
3149 if (::g_rename (backup_path.c_str(), xml_path.c_str()) != 0) {
3150 error << string_compose (_("could not restore history file from backup %1 (%2)"),
3151 backup_path, g_strerror (errno)) << endmsg;
3161 Session::restore_history (string snapshot_name)
3165 if (snapshot_name.empty()) {
3166 snapshot_name = _current_snapshot_name;
3169 const std::string xml_filename = legalize_for_path (snapshot_name) + history_suffix;
3170 const std::string xml_path(Glib::build_filename (_session_dir->root_path(), xml_filename));
3172 info << "Loading history from " << xml_path << endmsg;
3174 if (!Glib::file_test (xml_path, Glib::FILE_TEST_EXISTS)) {
3175 info << string_compose (_("%1: no history file \"%2\" for this session."),
3176 _name, xml_path) << endmsg;
3180 if (!tree.read (xml_path)) {
3181 error << string_compose (_("Could not understand session history file \"%1\""),
3182 xml_path) << endmsg;
3189 for (XMLNodeConstIterator it = tree.root()->children().begin(); it != tree.root()->children().end(); it++) {
3192 UndoTransaction* ut = new UndoTransaction ();
3195 ut->set_name(t->property("name")->value());
3196 stringstream ss(t->property("tv-sec")->value());
3198 ss.str(t->property("tv-usec")->value());
3200 ut->set_timestamp(tv);
3202 for (XMLNodeConstIterator child_it = t->children().begin();
3203 child_it != t->children().end(); child_it++)
3205 XMLNode *n = *child_it;
3208 if (n->name() == "MementoCommand" ||
3209 n->name() == "MementoUndoCommand" ||
3210 n->name() == "MementoRedoCommand") {
3212 if ((c = memento_command_factory(n))) {
3216 } else if (n->name() == "NoteDiffCommand") {
3217 PBD::ID id (n->property("midi-source")->value());
3218 boost::shared_ptr<MidiSource> midi_source =
3219 boost::dynamic_pointer_cast<MidiSource, Source>(source_by_id(id));
3221 ut->add_command (new MidiModel::NoteDiffCommand(midi_source->model(), *n));
3223 error << _("Failed to downcast MidiSource for NoteDiffCommand") << endmsg;
3226 } else if (n->name() == "SysExDiffCommand") {
3228 PBD::ID id (n->property("midi-source")->value());
3229 boost::shared_ptr<MidiSource> midi_source =
3230 boost::dynamic_pointer_cast<MidiSource, Source>(source_by_id(id));
3232 ut->add_command (new MidiModel::SysExDiffCommand (midi_source->model(), *n));
3234 error << _("Failed to downcast MidiSource for SysExDiffCommand") << endmsg;
3237 } else if (n->name() == "PatchChangeDiffCommand") {
3239 PBD::ID id (n->property("midi-source")->value());
3240 boost::shared_ptr<MidiSource> midi_source =
3241 boost::dynamic_pointer_cast<MidiSource, Source>(source_by_id(id));
3243 ut->add_command (new MidiModel::PatchChangeDiffCommand (midi_source->model(), *n));
3245 error << _("Failed to downcast MidiSource for PatchChangeDiffCommand") << endmsg;
3248 } else if (n->name() == "StatefulDiffCommand") {
3249 if ((c = stateful_diff_command_factory (n))) {
3250 ut->add_command (c);
3253 error << string_compose(_("Couldn't figure out how to make a Command out of a %1 XMLNode."), n->name()) << endmsg;
3264 Session::config_changed (std::string p, bool ours)
3270 if (p == "seamless-loop") {
3272 } else if (p == "rf-speed") {
3274 } else if (p == "auto-loop") {
3276 } else if (p == "auto-input") {
3278 if (Config->get_monitoring_model() == HardwareMonitoring && transport_rolling()) {
3279 /* auto-input only makes a difference if we're rolling */
3280 set_track_monitor_input_status (!config.get_auto_input());
3283 } else if (p == "punch-in") {
3287 if ((location = _locations->auto_punch_location()) != 0) {
3289 if (config.get_punch_in ()) {
3290 replace_event (SessionEvent::PunchIn, location->start());
3292 remove_event (location->start(), SessionEvent::PunchIn);
3296 } else if (p == "punch-out") {
3300 if ((location = _locations->auto_punch_location()) != 0) {
3302 if (config.get_punch_out()) {
3303 replace_event (SessionEvent::PunchOut, location->end());
3305 clear_events (SessionEvent::PunchOut);
3309 } else if (p == "edit-mode") {
3311 Glib::Threads::Mutex::Lock lm (playlists->lock);
3313 for (SessionPlaylists::List::iterator i = playlists->playlists.begin(); i != playlists->playlists.end(); ++i) {
3314 (*i)->set_edit_mode (Config->get_edit_mode ());
3317 } else if (p == "use-video-sync") {
3319 waiting_for_sync_offset = config.get_use_video_sync();
3321 } else if (p == "mmc-control") {
3323 //poke_midi_thread ();
3325 } else if (p == "mmc-device-id" || p == "mmc-receive-id" || p == "mmc-receive-device-id") {
3327 _mmc->set_receive_device_id (Config->get_mmc_receive_device_id());
3329 } else if (p == "mmc-send-id" || p == "mmc-send-device-id") {
3331 _mmc->set_send_device_id (Config->get_mmc_send_device_id());
3333 } else if (p == "midi-control") {
3335 //poke_midi_thread ();
3337 } else if (p == "raid-path") {
3339 setup_raid_path (config.get_raid_path());
3341 } else if (p == "timecode-format") {
3345 } else if (p == "video-pullup") {
3349 } else if (p == "seamless-loop") {
3351 if (play_loop && transport_rolling()) {
3352 // to reset diskstreams etc
3353 request_play_loop (true);
3356 } else if (p == "rf-speed") {
3358 cumulative_rf_motion = 0;
3361 } else if (p == "click-sound") {
3363 setup_click_sounds (1);
3365 } else if (p == "click-emphasis-sound") {
3367 setup_click_sounds (-1);
3369 } else if (p == "clicking") {
3371 if (Config->get_clicking()) {
3372 if (_click_io && click_data) { // don't require emphasis data
3379 } else if (p == "click-gain") {
3382 _click_gain->set_gain (Config->get_click_gain(), this);
3385 } else if (p == "send-mtc") {
3387 if (Config->get_send_mtc ()) {
3388 /* mark us ready to send */
3389 next_quarter_frame_to_send = 0;
3392 } else if (p == "send-mmc") {
3394 _mmc->enable_send (Config->get_send_mmc ());
3396 } else if (p == "midi-feedback") {
3398 session_midi_feedback = Config->get_midi_feedback();
3400 } else if (p == "jack-time-master") {
3402 engine().reset_timebase ();
3404 } else if (p == "native-file-header-format") {
3406 if (!first_file_header_format_reset) {
3407 reset_native_file_format ();
3410 first_file_header_format_reset = false;
3412 } else if (p == "native-file-data-format") {
3414 if (!first_file_data_format_reset) {
3415 reset_native_file_format ();
3418 first_file_data_format_reset = false;
3420 } else if (p == "external-sync") {
3421 if (!config.get_external_sync()) {
3422 drop_sync_source ();
3424 switch_to_sync_source (Config->get_sync_source());
3426 } else if (p == "denormal-model") {
3428 } else if (p == "history-depth") {
3429 set_history_depth (Config->get_history_depth());
3430 } else if (p == "remote-model") {
3431 /* XXX DO SOMETHING HERE TO TELL THE GUI THAT WE NEED
3434 } else if (p == "initial-program-change") {
3436 if (_mmc->output_port() && Config->get_initial_program_change() >= 0) {
3439 buf[0] = MIDI::program; // channel zero by default
3440 buf[1] = (Config->get_initial_program_change() & 0x7f);
3442 _mmc->output_port()->midimsg (buf, sizeof (buf), 0);
3444 } else if (p == "solo-mute-override") {
3445 // catch_up_on_solo_mute_override ();
3446 } else if (p == "listen-position" || p == "pfl-position") {
3447 listen_position_changed ();
3448 } else if (p == "solo-control-is-listen-control") {
3449 solo_control_mode_changed ();
3450 } else if (p == "timecode-offset" || p == "timecode-offset-negative") {
3451 last_timecode_valid = false;
3452 } else if (p == "playback-buffer-seconds") {
3453 AudioSource::allocate_working_buffers (frame_rate());
3454 } else if (p == "automation-thinning-factor") {
3455 Evoral::ControlList::set_thinning_factor (Config->get_automation_thinning_factor());
3456 } else if (p == "ltc-source-port") {
3457 reconnect_ltc_input ();
3458 } else if (p == "ltc-sink-port") {
3459 reconnect_ltc_output ();
3460 } else if (p == "timecode-generator-offset") {
3461 ltc_tx_parse_offset();
3468 Session::set_history_depth (uint32_t d)
3470 _history.set_depth (d);
3474 Session::load_diskstreams_2X (XMLNode const & node, int)
3477 XMLNodeConstIterator citer;
3479 clist = node.children();
3481 for (citer = clist.begin(); citer != clist.end(); ++citer) {
3484 /* diskstreams added automatically by DiskstreamCreated handler */
3485 if ((*citer)->name() == "AudioDiskstream" || (*citer)->name() == "DiskStream") {
3486 boost::shared_ptr<AudioDiskstream> dsp (new AudioDiskstream (*this, **citer));
3487 _diskstreams_2X.push_back (dsp);
3489 error << _("Session: unknown diskstream type in XML") << endmsg;
3493 catch (failed_constructor& err) {
3494 error << _("Session: could not load diskstream via XML state") << endmsg;
3502 /** Connect things to the MMC object */
3504 Session::setup_midi_machine_control ()
3506 _mmc = new MIDI::MachineControl;
3507 _mmc->set_ports (_midi_ports->mmc_input_port(), _midi_ports->mmc_output_port());
3509 _mmc->Play.connect_same_thread (*this, boost::bind (&Session::mmc_deferred_play, this, _1));
3510 _mmc->DeferredPlay.connect_same_thread (*this, boost::bind (&Session::mmc_deferred_play, this, _1));
3511 _mmc->Stop.connect_same_thread (*this, boost::bind (&Session::mmc_stop, this, _1));
3512 _mmc->FastForward.connect_same_thread (*this, boost::bind (&Session::mmc_fast_forward, this, _1));
3513 _mmc->Rewind.connect_same_thread (*this, boost::bind (&Session::mmc_rewind, this, _1));
3514 _mmc->Pause.connect_same_thread (*this, boost::bind (&Session::mmc_pause, this, _1));
3515 _mmc->RecordPause.connect_same_thread (*this, boost::bind (&Session::mmc_record_pause, this, _1));
3516 _mmc->RecordStrobe.connect_same_thread (*this, boost::bind (&Session::mmc_record_strobe, this, _1));
3517 _mmc->RecordExit.connect_same_thread (*this, boost::bind (&Session::mmc_record_exit, this, _1));
3518 _mmc->Locate.connect_same_thread (*this, boost::bind (&Session::mmc_locate, this, _1, _2));
3519 _mmc->Step.connect_same_thread (*this, boost::bind (&Session::mmc_step, this, _1, _2));
3520 _mmc->Shuttle.connect_same_thread (*this, boost::bind (&Session::mmc_shuttle, this, _1, _2, _3));
3521 _mmc->TrackRecordStatusChange.connect_same_thread (*this, boost::bind (&Session::mmc_record_enable, this, _1, _2, _3));
3523 /* also handle MIDI SPP because its so common */
3525 _mmc->SPPStart.connect_same_thread (*this, boost::bind (&Session::spp_start, this));
3526 _mmc->SPPContinue.connect_same_thread (*this, boost::bind (&Session::spp_continue, this));
3527 _mmc->SPPStop.connect_same_thread (*this, boost::bind (&Session::spp_stop, this));
3530 boost::shared_ptr<Controllable>
3531 Session::solo_cut_control() const
3533 /* the solo cut control is a bit of an anomaly, at least as of Febrary 2011. There are no other
3534 controls in Ardour that currently get presented to the user in the GUI that require
3535 access as a Controllable and are also NOT owned by some SessionObject (e.g. Route, or MonitorProcessor).
3537 its actually an RCConfiguration parameter, so we use a ProxyControllable to wrap
3538 it up as a Controllable. Changes to the Controllable will just map back to the RCConfiguration
3542 return _solo_cut_control;
3546 Session::rename (const std::string& new_name)
3548 string legal_name = legalize_for_path (new_name);
3554 string const old_sources_root = _session_dir->sources_root();
3559 * interchange subdirectory
3563 * Backup files are left unchanged and not renamed.
3566 /* pass one: not 100% safe check that the new directory names don't
3570 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
3575 /* this is a stupid hack because Glib::path_get_dirname() is
3576 * lexical-only, and so passing it /a/b/c/ gives a different
3577 * result than passing it /a/b/c ...
3580 if (oldstr[oldstr.length()-1] == G_DIR_SEPARATOR) {
3581 oldstr = oldstr.substr (0, oldstr.length() - 1);
3584 string base = Glib::path_get_dirname (oldstr);
3585 string p = Glib::path_get_basename (oldstr);
3587 newstr = Glib::build_filename (base, legal_name);
3589 if (Glib::file_test (newstr, Glib::FILE_TEST_EXISTS)) {
3596 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
3601 /* this is a stupid hack because Glib::path_get_dirname() is
3602 * lexical-only, and so passing it /a/b/c/ gives a different
3603 * result than passing it /a/b/c ...
3606 if (oldstr[oldstr.length()-1] == G_DIR_SEPARATOR) {
3607 oldstr = oldstr.substr (0, oldstr.length() - 1);
3610 string base = Glib::path_get_dirname (oldstr);
3611 string p = Glib::path_get_basename (oldstr);
3613 newstr = Glib::build_filename (base, legal_name);
3615 cerr << "Rename " << oldstr << " => " << newstr << endl;
3617 if (::g_rename (oldstr.c_str(), newstr.c_str()) != 0) {
3618 error << string_compose (_("renaming %s as %2 failed (%3)"), oldstr, newstr, g_strerror (errno)) << endmsg;
3623 (*_session_dir) = newstr;
3628 /* directory below interchange */
3630 v.push_back (newstr);
3631 v.push_back (interchange_dir_name);
3634 oldstr = Glib::build_filename (v);
3637 v.push_back (newstr);
3638 v.push_back (interchange_dir_name);
3639 v.push_back (legal_name);
3641 newstr = Glib::build_filename (v);
3643 cerr << "Rename " << oldstr << " => " << newstr << endl;
3645 if (::g_rename (oldstr.c_str(), newstr.c_str()) != 0) {
3646 error << string_compose (_("renaming %s as %2 failed (%3)"), oldstr, newstr, g_strerror (errno)) << endmsg;
3653 oldstr = Glib::build_filename (newpath, _current_snapshot_name) + statefile_suffix;
3654 newstr= Glib::build_filename (newpath, legal_name) + statefile_suffix;
3656 cerr << "Rename " << oldstr << " => " << newstr << endl;
3658 if (::g_rename (oldstr.c_str(), newstr.c_str()) != 0) {
3659 error << string_compose (_("renaming %s as %2 failed (%3)"), oldstr, newstr, g_strerror (errno)) << endmsg;
3666 oldstr = Glib::build_filename (newpath, _current_snapshot_name) + history_suffix;
3668 if (Glib::file_test (oldstr, Glib::FILE_TEST_EXISTS)) {
3669 newstr = Glib::build_filename (newpath, legal_name) + history_suffix;
3671 cerr << "Rename " << oldstr << " => " << newstr << endl;
3673 if (::g_rename (oldstr.c_str(), newstr.c_str()) != 0) {
3674 error << string_compose (_("renaming %s as %2 failed (%3)"), oldstr, newstr, g_strerror (errno)) << endmsg;
3679 /* update file source paths */
3681 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ++i) {
3682 boost::shared_ptr<FileSource> fs = boost::dynamic_pointer_cast<FileSource> (i->second);
3684 string p = fs->path ();
3685 boost::replace_all (p, old_sources_root, _session_dir->sources_root());
3690 /* remove old name from recent sessions */
3692 remove_recent_sessions (_path);
3695 _current_snapshot_name = new_name;
3698 /* re-add directory separator - reverse hack to oldstr above */
3699 if (_path[_path.length()-1] != G_DIR_SEPARATOR) {
3700 _path += G_DIR_SEPARATOR;
3705 /* save state again to get everything just right */
3707 save_state (_current_snapshot_name);
3710 /* add to recent sessions */
3712 store_recent_sessions (new_name, _path);
3718 Session::get_session_info_from_path (XMLTree& tree, const string& xmlpath)
3720 if (!Glib::file_test (xmlpath, Glib::FILE_TEST_EXISTS)) {
3724 if (!tree.read (xmlpath)) {
3732 Session::get_info_from_path (const string& xmlpath, float& sample_rate, SampleFormat& data_format)
3735 bool found_sr = false;
3736 bool found_data_format = false;
3738 if (get_session_info_from_path (tree, xmlpath)) {
3744 const XMLProperty* prop;
3745 if ((prop = tree.root()->property (X_("sample-rate"))) != 0) {
3746 sample_rate = atoi (prop->value());
3750 const XMLNodeList& children (tree.root()->children());
3751 for (XMLNodeList::const_iterator c = children.begin(); c != children.end(); ++c) {
3752 const XMLNode* child = *c;
3753 if (child->name() == "Config") {
3754 const XMLNodeList& options (child->children());
3755 for (XMLNodeList::const_iterator oc = options.begin(); oc != options.end(); ++oc) {
3756 const XMLNode* option = *oc;
3757 const XMLProperty* name = option->property("name");
3763 if (name->value() == "native-file-data-format") {
3764 const XMLProperty* value = option->property ("value");
3766 SampleFormat fmt = (SampleFormat) string_2_enum (option->property ("value")->value(), fmt);
3768 found_data_format = true;
3774 if (found_data_format) {
3779 return !(found_sr && found_data_format); // zero if they are both found
3782 typedef std::vector<boost::shared_ptr<FileSource> > SeveralFileSources;
3783 typedef std::map<std::string,SeveralFileSources> SourcePathMap;
3786 Session::bring_all_sources_into_session (boost::function<void(uint32_t,uint32_t,string)> callback)
3790 SourcePathMap source_path_map;
3792 boost::shared_ptr<AudioFileSource> afs;
3797 Glib::Threads::Mutex::Lock lm (source_lock);
3799 cerr << " total sources = " << sources.size();
3801 for (SourceMap::const_iterator i = sources.begin(); i != sources.end(); ++i) {
3802 boost::shared_ptr<FileSource> fs = boost::dynamic_pointer_cast<FileSource> (i->second);
3808 if (fs->within_session()) {
3809 cerr << "skip " << fs->name() << endl;
3813 if (source_path_map.find (fs->path()) != source_path_map.end()) {
3814 source_path_map[fs->path()].push_back (fs);
3816 SeveralFileSources v;
3818 source_path_map.insert (make_pair (fs->path(), v));
3824 cerr << " fsources = " << total << endl;
3826 for (SourcePathMap::iterator i = source_path_map.begin(); i != source_path_map.end(); ++i) {
3828 /* tell caller where we are */
3830 string old_path = i->first;
3832 callback (n, total, old_path);
3834 cerr << old_path << endl;
3838 switch (i->second.front()->type()) {
3839 case DataType::AUDIO:
3840 new_path = new_audio_source_path_for_embedded (old_path);
3843 case DataType::MIDI:
3847 cerr << "Move " << old_path << " => " << new_path << endl;
3849 if (!copy_file (old_path, new_path)) {
3850 cerr << "failed !\n";
3854 /* make sure we stop looking in the external
3855 dir/folder. Remember, this is an all-or-nothing
3856 operations, it doesn't merge just some files.
3858 remove_dir_from_search_path (Glib::path_get_dirname (old_path), i->second.front()->type());
3860 for (SeveralFileSources::iterator f = i->second.begin(); f != i->second.end(); ++f) {
3861 (*f)->set_path (new_path);
3866 save_state ("", false, false);