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 */
1364 Session::load_routes (const XMLNode& node, int version)
1367 XMLNodeConstIterator niter;
1368 RouteList new_routes;
1370 nlist = node.children();
1374 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1376 boost::shared_ptr<Route> route;
1377 if (version < 3000) {
1378 route = XMLRouteFactory_2X (**niter, version);
1380 route = XMLRouteFactory (**niter, version);
1384 error << _("Session: cannot create Route from XML description.") << endmsg;
1388 BootMessage (string_compose (_("Loaded track/bus %1"), route->name()));
1390 new_routes.push_back (route);
1393 add_routes (new_routes, false, false, false);
1398 boost::shared_ptr<Route>
1399 Session::XMLRouteFactory (const XMLNode& node, int version)
1401 boost::shared_ptr<Route> ret;
1403 if (node.name() != "Route") {
1407 XMLNode* ds_child = find_named_node (node, X_("Diskstream"));
1409 DataType type = DataType::AUDIO;
1410 const XMLProperty* prop = node.property("default-type");
1413 type = DataType (prop->value());
1416 assert (type != DataType::NIL);
1420 boost::shared_ptr<Track> track;
1422 if (type == DataType::AUDIO) {
1423 track.reset (new AudioTrack (*this, X_("toBeResetFroXML")));
1425 track.reset (new MidiTrack (*this, X_("toBeResetFroXML")));
1428 if (track->init()) {
1432 if (track->set_state (node, version)) {
1436 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
1437 // boost_debug_shared_ptr_mark_interesting (track.get(), "Track");
1442 enum Route::Flag flags = Route::Flag(0);
1443 const XMLProperty* prop = node.property("flags");
1445 flags = Route::Flag (string_2_enum (prop->value(), flags));
1448 boost::shared_ptr<Route> r (new Route (*this, X_("toBeResetFroXML"), flags));
1450 if (r->init () == 0 && r->set_state (node, version) == 0) {
1451 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
1452 // boost_debug_shared_ptr_mark_interesting (r.get(), "Route");
1461 boost::shared_ptr<Route>
1462 Session::XMLRouteFactory_2X (const XMLNode& node, int version)
1464 boost::shared_ptr<Route> ret;
1466 if (node.name() != "Route") {
1470 XMLProperty const * ds_prop = node.property (X_("diskstream-id"));
1472 ds_prop = node.property (X_("diskstream"));
1475 DataType type = DataType::AUDIO;
1476 const XMLProperty* prop = node.property("default-type");
1479 type = DataType (prop->value());
1482 assert (type != DataType::NIL);
1486 list<boost::shared_ptr<Diskstream> >::iterator i = _diskstreams_2X.begin ();
1487 while (i != _diskstreams_2X.end() && (*i)->id() != ds_prop->value()) {
1491 if (i == _diskstreams_2X.end()) {
1492 error << _("Could not find diskstream for route") << endmsg;
1493 return boost::shared_ptr<Route> ();
1496 boost::shared_ptr<Track> track;
1498 if (type == DataType::AUDIO) {
1499 track.reset (new AudioTrack (*this, X_("toBeResetFroXML")));
1501 track.reset (new MidiTrack (*this, X_("toBeResetFroXML")));
1504 if (track->init()) {
1508 if (track->set_state (node, version)) {
1512 track->set_diskstream (*i);
1514 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
1515 // boost_debug_shared_ptr_mark_interesting (track.get(), "Track");
1520 enum Route::Flag flags = Route::Flag(0);
1521 const XMLProperty* prop = node.property("flags");
1523 flags = Route::Flag (string_2_enum (prop->value(), flags));
1526 boost::shared_ptr<Route> r (new Route (*this, X_("toBeResetFroXML"), flags));
1528 if (r->init () == 0 && r->set_state (node, version) == 0) {
1529 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
1530 // boost_debug_shared_ptr_mark_interesting (r.get(), "Route");
1540 Session::load_regions (const XMLNode& node)
1543 XMLNodeConstIterator niter;
1544 boost::shared_ptr<Region> region;
1546 nlist = node.children();
1550 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1551 if ((region = XMLRegionFactory (**niter, false)) == 0) {
1552 error << _("Session: cannot create Region from XML description.");
1553 const XMLProperty *name = (**niter).property("name");
1556 error << " " << string_compose (_("Can not load state for region '%1'"), name->value());
1567 Session::load_compounds (const XMLNode& node)
1569 XMLNodeList calist = node.children();
1570 XMLNodeConstIterator caiter;
1571 XMLProperty *caprop;
1573 for (caiter = calist.begin(); caiter != calist.end(); ++caiter) {
1574 XMLNode* ca = *caiter;
1578 if ((caprop = ca->property (X_("original"))) == 0) {
1581 orig_id = caprop->value();
1583 if ((caprop = ca->property (X_("copy"))) == 0) {
1586 copy_id = caprop->value();
1588 boost::shared_ptr<Region> orig = RegionFactory::region_by_id (orig_id);
1589 boost::shared_ptr<Region> copy = RegionFactory::region_by_id (copy_id);
1591 if (!orig || !copy) {
1592 warning << string_compose (_("Regions in compound description not found (ID's %1 and %2): ignored"),
1598 RegionFactory::add_compound_association (orig, copy);
1605 Session::load_nested_sources (const XMLNode& node)
1608 XMLNodeConstIterator niter;
1610 nlist = node.children();
1612 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1613 if ((*niter)->name() == "Source") {
1615 /* it may already exist, so don't recreate it unnecessarily
1618 XMLProperty* prop = (*niter)->property (X_("id"));
1620 error << _("Nested source has no ID info in session file! (ignored)") << endmsg;
1624 ID source_id (prop->value());
1626 if (!source_by_id (source_id)) {
1629 SourceFactory::create (*this, **niter, true);
1631 catch (failed_constructor& err) {
1632 error << string_compose (_("Cannot reconstruct nested source for region %1"), name()) << endmsg;
1639 boost::shared_ptr<Region>
1640 Session::XMLRegionFactory (const XMLNode& node, bool full)
1642 const XMLProperty* type = node.property("type");
1646 const XMLNodeList& nlist = node.children();
1648 for (XMLNodeConstIterator niter = nlist.begin(); niter != nlist.end(); ++niter) {
1649 XMLNode *child = (*niter);
1650 if (child->name() == "NestedSource") {
1651 load_nested_sources (*child);
1655 if (!type || type->value() == "audio") {
1656 return boost::shared_ptr<Region>(XMLAudioRegionFactory (node, full));
1657 } else if (type->value() == "midi") {
1658 return boost::shared_ptr<Region>(XMLMidiRegionFactory (node, full));
1661 } catch (failed_constructor& err) {
1662 return boost::shared_ptr<Region> ();
1665 return boost::shared_ptr<Region> ();
1668 boost::shared_ptr<AudioRegion>
1669 Session::XMLAudioRegionFactory (const XMLNode& node, bool /*full*/)
1671 const XMLProperty* prop;
1672 boost::shared_ptr<Source> source;
1673 boost::shared_ptr<AudioSource> as;
1675 SourceList master_sources;
1676 uint32_t nchans = 1;
1679 if (node.name() != X_("Region")) {
1680 return boost::shared_ptr<AudioRegion>();
1683 if ((prop = node.property (X_("channels"))) != 0) {
1684 nchans = atoi (prop->value().c_str());
1687 if ((prop = node.property ("name")) == 0) {
1688 cerr << "no name for this region\n";
1692 if ((prop = node.property (X_("source-0"))) == 0) {
1693 if ((prop = node.property ("source")) == 0) {
1694 error << _("Session: XMLNode describing a AudioRegion is incomplete (no source)") << endmsg;
1695 return boost::shared_ptr<AudioRegion>();
1699 PBD::ID s_id (prop->value());
1701 if ((source = source_by_id (s_id)) == 0) {
1702 error << string_compose(_("Session: XMLNode describing a AudioRegion references an unknown source id =%1"), s_id) << endmsg;
1703 return boost::shared_ptr<AudioRegion>();
1706 as = boost::dynamic_pointer_cast<AudioSource>(source);
1708 error << string_compose(_("Session: XMLNode describing a AudioRegion references a non-audio source id =%1"), s_id) << endmsg;
1709 return boost::shared_ptr<AudioRegion>();
1712 sources.push_back (as);
1714 /* pickup other channels */
1716 for (uint32_t n=1; n < nchans; ++n) {
1717 snprintf (buf, sizeof(buf), X_("source-%d"), n);
1718 if ((prop = node.property (buf)) != 0) {
1720 PBD::ID id2 (prop->value());
1722 if ((source = source_by_id (id2)) == 0) {
1723 error << string_compose(_("Session: XMLNode describing a AudioRegion references an unknown source id =%1"), id2) << endmsg;
1724 return boost::shared_ptr<AudioRegion>();
1727 as = boost::dynamic_pointer_cast<AudioSource>(source);
1729 error << string_compose(_("Session: XMLNode describing a AudioRegion references a non-audio source id =%1"), id2) << endmsg;
1730 return boost::shared_ptr<AudioRegion>();
1732 sources.push_back (as);
1736 for (uint32_t n = 0; n < nchans; ++n) {
1737 snprintf (buf, sizeof(buf), X_("master-source-%d"), n);
1738 if ((prop = node.property (buf)) != 0) {
1740 PBD::ID id2 (prop->value());
1742 if ((source = source_by_id (id2)) == 0) {
1743 error << string_compose(_("Session: XMLNode describing a AudioRegion references an unknown source id =%1"), id2) << endmsg;
1744 return boost::shared_ptr<AudioRegion>();
1747 as = boost::dynamic_pointer_cast<AudioSource>(source);
1749 error << string_compose(_("Session: XMLNode describing a AudioRegion references a non-audio source id =%1"), id2) << endmsg;
1750 return boost::shared_ptr<AudioRegion>();
1752 master_sources.push_back (as);
1757 boost::shared_ptr<AudioRegion> region (boost::dynamic_pointer_cast<AudioRegion> (RegionFactory::create (sources, node)));
1759 /* a final detail: this is the one and only place that we know how long missing files are */
1761 if (region->whole_file()) {
1762 for (SourceList::iterator sx = sources.begin(); sx != sources.end(); ++sx) {
1763 boost::shared_ptr<SilentFileSource> sfp = boost::dynamic_pointer_cast<SilentFileSource> (*sx);
1765 sfp->set_length (region->length());
1770 if (!master_sources.empty()) {
1771 if (master_sources.size() != nchans) {
1772 error << _("Session: XMLNode describing an AudioRegion is missing some master sources; ignored") << endmsg;
1774 region->set_master_sources (master_sources);
1782 catch (failed_constructor& err) {
1783 return boost::shared_ptr<AudioRegion>();
1787 boost::shared_ptr<MidiRegion>
1788 Session::XMLMidiRegionFactory (const XMLNode& node, bool /*full*/)
1790 const XMLProperty* prop;
1791 boost::shared_ptr<Source> source;
1792 boost::shared_ptr<MidiSource> ms;
1795 if (node.name() != X_("Region")) {
1796 return boost::shared_ptr<MidiRegion>();
1799 if ((prop = node.property ("name")) == 0) {
1800 cerr << "no name for this region\n";
1804 if ((prop = node.property (X_("source-0"))) == 0) {
1805 if ((prop = node.property ("source")) == 0) {
1806 error << _("Session: XMLNode describing a MidiRegion is incomplete (no source)") << endmsg;
1807 return boost::shared_ptr<MidiRegion>();
1811 PBD::ID s_id (prop->value());
1813 if ((source = source_by_id (s_id)) == 0) {
1814 error << string_compose(_("Session: XMLNode describing a MidiRegion references an unknown source id =%1"), s_id) << endmsg;
1815 return boost::shared_ptr<MidiRegion>();
1818 ms = boost::dynamic_pointer_cast<MidiSource>(source);
1820 error << string_compose(_("Session: XMLNode describing a MidiRegion references a non-midi source id =%1"), s_id) << endmsg;
1821 return boost::shared_ptr<MidiRegion>();
1824 sources.push_back (ms);
1827 boost::shared_ptr<MidiRegion> region (boost::dynamic_pointer_cast<MidiRegion> (RegionFactory::create (sources, node)));
1828 /* a final detail: this is the one and only place that we know how long missing files are */
1830 if (region->whole_file()) {
1831 for (SourceList::iterator sx = sources.begin(); sx != sources.end(); ++sx) {
1832 boost::shared_ptr<SilentFileSource> sfp = boost::dynamic_pointer_cast<SilentFileSource> (*sx);
1834 sfp->set_length (region->length());
1842 catch (failed_constructor& err) {
1843 return boost::shared_ptr<MidiRegion>();
1848 Session::get_sources_as_xml ()
1851 XMLNode* node = new XMLNode (X_("Sources"));
1852 Glib::Threads::Mutex::Lock lm (source_lock);
1854 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ++i) {
1855 node->add_child_nocopy (i->second->get_state());
1862 Session::load_sources (const XMLNode& node)
1865 XMLNodeConstIterator niter;
1866 boost::shared_ptr<Source> source;
1868 nlist = node.children();
1872 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1875 if ((source = XMLSourceFactory (**niter)) == 0) {
1876 error << _("Session: cannot create Source from XML description.") << endmsg;
1879 } catch (MissingSource& err) {
1883 if (!no_questions_about_missing_files) {
1884 user_choice = MissingFile (this, err.path, err.type).get_value_or (-1);
1889 switch (user_choice) {
1891 /* user added a new search location, so try again */
1896 /* user asked to quit the entire session load
1901 no_questions_about_missing_files = true;
1905 no_questions_about_missing_files = true;
1910 warning << _("A sound file is missing. It will be replaced by silence.") << endmsg;
1911 source = SourceFactory::createSilent (*this, **niter, max_framecnt, _current_frame_rate);
1920 boost::shared_ptr<Source>
1921 Session::XMLSourceFactory (const XMLNode& node)
1923 if (node.name() != "Source") {
1924 return boost::shared_ptr<Source>();
1928 /* note: do peak building in another thread when loading session state */
1929 return SourceFactory::create (*this, node, true);
1932 catch (failed_constructor& err) {
1933 error << string_compose (_("Found a sound file that cannot be used by %1. Talk to the progammers."), PROGRAM_NAME) << endmsg;
1934 return boost::shared_ptr<Source>();
1939 Session::save_template (string template_name)
1943 if (_state_of_the_state & CannotSave) {
1947 std::string user_template_dir(user_template_directory());
1949 if (g_mkdir_with_parents (user_template_dir.c_str(), 0755) != 0) {
1950 error << string_compose(_("Could not create templates directory \"%1\" (%2)"),
1951 user_template_dir, g_strerror (errno)) << endmsg;
1955 tree.set_root (&get_template());
1957 std::string template_dir_path(user_template_dir);
1959 /* directory to put the template in */
1960 template_dir_path = Glib::build_filename (template_dir_path, template_name);
1962 if (Glib::file_test (template_dir_path, Glib::FILE_TEST_EXISTS)) {
1963 warning << string_compose(_("Template \"%1\" already exists - new version not created"),
1964 template_dir_path) << endmsg;
1968 if (g_mkdir_with_parents (template_dir_path.c_str(), 0755) != 0) {
1969 error << string_compose(_("Could not create directory for Session template\"%1\" (%2)"),
1970 template_dir_path, g_strerror (errno)) << endmsg;
1975 std::string template_file_path(template_dir_path);
1976 template_file_path = Glib::build_filename (template_file_path, template_name + template_suffix);
1978 if (!tree.write (template_file_path)) {
1979 error << _("template not saved") << endmsg;
1983 /* copy plugin state directory */
1985 std::string template_plugin_state_path(template_dir_path);
1986 template_plugin_state_path = Glib::build_filename (template_plugin_state_path, X_("plugins"));
1988 if (g_mkdir_with_parents (template_plugin_state_path.c_str(), 0755) != 0) {
1989 error << string_compose(_("Could not create directory for Session template plugin state\"%1\" (%2)"),
1990 template_plugin_state_path, g_strerror (errno)) << endmsg;
1994 copy_files (plugins_dir(), template_plugin_state_path);
2000 Session::refresh_disk_space ()
2002 #if __APPLE__ || (HAVE_SYS_VFS_H && HAVE_SYS_STATVFS_H)
2004 Glib::Threads::Mutex::Lock lm (space_lock);
2006 /* get freespace on every FS that is part of the session path */
2008 _total_free_4k_blocks = 0;
2009 _total_free_4k_blocks_uncertain = false;
2011 for (vector<space_and_path>::iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
2013 struct statfs statfsbuf;
2014 statfs (i->path.c_str(), &statfsbuf);
2016 double const scale = statfsbuf.f_bsize / 4096.0;
2018 /* See if this filesystem is read-only */
2019 struct statvfs statvfsbuf;
2020 statvfs (i->path.c_str(), &statvfsbuf);
2022 /* f_bavail can be 0 if it is undefined for whatever
2023 filesystem we are looking at; Samba shares mounted
2024 via GVFS are an example of this.
2026 if (statfsbuf.f_bavail == 0) {
2027 /* block count unknown */
2029 i->blocks_unknown = true;
2030 } else if (statvfsbuf.f_flag & ST_RDONLY) {
2031 /* read-only filesystem */
2033 i->blocks_unknown = false;
2035 /* read/write filesystem with known space */
2036 i->blocks = (uint32_t) floor (statfsbuf.f_bavail * scale);
2037 i->blocks_unknown = false;
2040 _total_free_4k_blocks += i->blocks;
2041 if (i->blocks_unknown) {
2042 _total_free_4k_blocks_uncertain = true;
2045 #elif defined (COMPILER_MSVC)
2046 vector<string> scanned_volumes;
2047 vector<string>::iterator j;
2048 vector<space_and_path>::iterator i;
2049 DWORD nSectorsPerCluster, nBytesPerSector,
2050 nFreeClusters, nTotalClusters;
2054 _total_free_4k_blocks = 0;
2056 for (i = session_dirs.begin(); i != session_dirs.end(); i++) {
2057 strncpy (disk_drive, (*i).path.c_str(), 3);
2061 volume_found = false;
2062 if (0 != (GetDiskFreeSpace(disk_drive, &nSectorsPerCluster, &nBytesPerSector, &nFreeClusters, &nTotalClusters)))
2064 int64_t nBytesPerCluster = nBytesPerSector * nSectorsPerCluster;
2065 int64_t nFreeBytes = nBytesPerCluster * (int64_t)nFreeClusters;
2066 i->blocks = (uint32_t)(nFreeBytes / 4096);
2068 for (j = scanned_volumes.begin(); j != scanned_volumes.end(); j++) {
2069 if (0 == j->compare(disk_drive)) {
2070 volume_found = true;
2075 if (!volume_found) {
2076 scanned_volumes.push_back(disk_drive);
2077 _total_free_4k_blocks += i->blocks;
2082 if (0 == _total_free_4k_blocks) {
2083 strncpy (disk_drive, path().c_str(), 3);
2086 if (0 != (GetDiskFreeSpace(disk_drive, &nSectorsPerCluster, &nBytesPerSector, &nFreeClusters, &nTotalClusters)))
2088 int64_t nBytesPerCluster = nBytesPerSector * nSectorsPerCluster;
2089 int64_t nFreeBytes = nBytesPerCluster * (int64_t)nFreeClusters;
2090 _total_free_4k_blocks = (uint32_t)(nFreeBytes / 4096);
2097 Session::get_best_session_directory_for_new_audio ()
2099 vector<space_and_path>::iterator i;
2100 string result = _session_dir->root_path();
2102 /* handle common case without system calls */
2104 if (session_dirs.size() == 1) {
2108 /* OK, here's the algorithm we're following here:
2110 We want to select which directory to use for
2111 the next file source to be created. Ideally,
2112 we'd like to use a round-robin process so as to
2113 get maximum performance benefits from splitting
2114 the files across multiple disks.
2116 However, in situations without much diskspace, an
2117 RR approach may end up filling up a filesystem
2118 with new files while others still have space.
2119 Its therefore important to pay some attention to
2120 the freespace in the filesystem holding each
2121 directory as well. However, if we did that by
2122 itself, we'd keep creating new files in the file
2123 system with the most space until it was as full
2124 as all others, thus negating any performance
2125 benefits of this RAID-1 like approach.
2127 So, we use a user-configurable space threshold. If
2128 there are at least 2 filesystems with more than this
2129 much space available, we use RR selection between them.
2130 If not, then we pick the filesystem with the most space.
2132 This gets a good balance between the two
2136 refresh_disk_space ();
2138 int free_enough = 0;
2140 for (i = session_dirs.begin(); i != session_dirs.end(); ++i) {
2141 if ((*i).blocks * 4096 >= Config->get_disk_choice_space_threshold()) {
2146 if (free_enough >= 2) {
2147 /* use RR selection process, ensuring that the one
2151 i = last_rr_session_dir;
2154 if (++i == session_dirs.end()) {
2155 i = session_dirs.begin();
2158 if ((*i).blocks * 4096 >= Config->get_disk_choice_space_threshold()) {
2159 SessionDirectory sdir(i->path);
2160 if (sdir.create ()) {
2162 last_rr_session_dir = i;
2167 } while (i != last_rr_session_dir);
2171 /* pick FS with the most freespace (and that
2172 seems to actually work ...)
2175 vector<space_and_path> sorted;
2176 space_and_path_ascending_cmp cmp;
2178 sorted = session_dirs;
2179 sort (sorted.begin(), sorted.end(), cmp);
2181 for (i = sorted.begin(); i != sorted.end(); ++i) {
2182 SessionDirectory sdir(i->path);
2183 if (sdir.create ()) {
2185 last_rr_session_dir = i;
2195 Session::automation_dir () const
2197 return Glib::build_filename (_path, "automation");
2201 Session::analysis_dir () const
2203 return Glib::build_filename (_path, "analysis");
2207 Session::plugins_dir () const
2209 return Glib::build_filename (_path, "plugins");
2213 Session::externals_dir () const
2215 return Glib::build_filename (_path, "externals");
2219 Session::load_bundles (XMLNode const & node)
2221 XMLNodeList nlist = node.children();
2222 XMLNodeConstIterator niter;
2226 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2227 if ((*niter)->name() == "InputBundle") {
2228 add_bundle (boost::shared_ptr<UserBundle> (new UserBundle (**niter, true)));
2229 } else if ((*niter)->name() == "OutputBundle") {
2230 add_bundle (boost::shared_ptr<UserBundle> (new UserBundle (**niter, false)));
2232 error << string_compose(_("Unknown node \"%1\" found in Bundles list from session file"), (*niter)->name()) << endmsg;
2241 Session::load_route_groups (const XMLNode& node, int version)
2243 XMLNodeList nlist = node.children();
2244 XMLNodeConstIterator niter;
2248 if (version >= 3000) {
2250 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2251 if ((*niter)->name() == "RouteGroup") {
2252 RouteGroup* rg = new RouteGroup (*this, "");
2253 add_route_group (rg);
2254 rg->set_state (**niter, version);
2258 } else if (version < 3000) {
2260 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2261 if ((*niter)->name() == "EditGroup" || (*niter)->name() == "MixGroup") {
2262 RouteGroup* rg = new RouteGroup (*this, "");
2263 add_route_group (rg);
2264 rg->set_state (**niter, version);
2273 state_file_filter (const string &str, void* /*arg*/)
2275 return (str.length() > strlen(statefile_suffix) &&
2276 str.find (statefile_suffix) == (str.length() - strlen (statefile_suffix)));
2280 remove_end(string state)
2282 string statename(state);
2284 string::size_type start,end;
2285 if ((start = statename.find_last_of (G_DIR_SEPARATOR)) != string::npos) {
2286 statename = statename.substr (start+1);
2289 if ((end = statename.rfind(".ardour")) == string::npos) {
2290 end = statename.length();
2293 return string(statename.substr (0, end));
2297 Session::possible_states (string path)
2299 vector<string> states;
2300 find_files_matching_filter (states, path, state_file_filter, 0, false, false);
2302 transform(states.begin(), states.end(), states.begin(), remove_end);
2304 sort (states.begin(), states.end());
2310 Session::possible_states () const
2312 return possible_states(_path);
2316 Session::add_route_group (RouteGroup* g)
2318 _route_groups.push_back (g);
2319 route_group_added (g); /* EMIT SIGNAL */
2321 g->RouteAdded.connect_same_thread (*this, boost::bind (&Session::route_added_to_route_group, this, _1, _2));
2322 g->RouteRemoved.connect_same_thread (*this, boost::bind (&Session::route_removed_from_route_group, this, _1, _2));
2323 g->PropertyChanged.connect_same_thread (*this, boost::bind (&Session::route_group_property_changed, this, g));
2329 Session::remove_route_group (RouteGroup& rg)
2331 list<RouteGroup*>::iterator i;
2333 if ((i = find (_route_groups.begin(), _route_groups.end(), &rg)) != _route_groups.end()) {
2334 _route_groups.erase (i);
2337 route_group_removed (); /* EMIT SIGNAL */
2341 /** Set a new order for our route groups, without adding or removing any.
2342 * @param groups Route group list in the new order.
2345 Session::reorder_route_groups (list<RouteGroup*> groups)
2347 _route_groups = groups;
2349 route_groups_reordered (); /* EMIT SIGNAL */
2355 Session::route_group_by_name (string name)
2357 list<RouteGroup *>::iterator i;
2359 for (i = _route_groups.begin(); i != _route_groups.end(); ++i) {
2360 if ((*i)->name() == name) {
2368 Session::all_route_group() const
2370 return *_all_route_group;
2374 Session::add_commands (vector<Command*> const & cmds)
2376 for (vector<Command*>::const_iterator i = cmds.begin(); i != cmds.end(); ++i) {
2382 Session::begin_reversible_command (const string& name)
2384 begin_reversible_command (g_quark_from_string (name.c_str ()));
2387 /** Begin a reversible command using a GQuark to identify it.
2388 * begin_reversible_command() and commit_reversible_command() calls may be nested,
2389 * but there must be as many begin...()s as there are commit...()s.
2392 Session::begin_reversible_command (GQuark q)
2394 /* If nested begin/commit pairs are used, we create just one UndoTransaction
2395 to hold all the commands that are committed. This keeps the order of
2396 commands correct in the history.
2399 if (_current_trans == 0) {
2400 /* start a new transaction */
2401 assert (_current_trans_quarks.empty ());
2402 _current_trans = new UndoTransaction();
2403 _current_trans->set_name (g_quark_to_string (q));
2406 _current_trans_quarks.push_front (q);
2410 Session::commit_reversible_command (Command *cmd)
2412 assert (_current_trans);
2413 assert (!_current_trans_quarks.empty ());
2418 _current_trans->add_command (cmd);
2421 _current_trans_quarks.pop_front ();
2423 if (!_current_trans_quarks.empty ()) {
2424 /* the transaction we're committing is not the top-level one */
2428 if (_current_trans->empty()) {
2429 /* no commands were added to the transaction, so just get rid of it */
2430 delete _current_trans;
2435 gettimeofday (&now, 0);
2436 _current_trans->set_timestamp (now);
2438 _history.add (_current_trans);
2443 accept_all_audio_files (const string& path, void* /*arg*/)
2445 if (!Glib::file_test (path, Glib::FILE_TEST_IS_REGULAR)) {
2449 if (!AudioFileSource::safe_audio_file_extension (path)) {
2457 accept_all_midi_files (const string& path, void* /*arg*/)
2459 if (!Glib::file_test (path, Glib::FILE_TEST_IS_REGULAR)) {
2463 return ((path.length() > 4 && path.find (".mid") != (path.length() - 4)) ||
2464 (path.length() > 4 && path.find (".smf") != (path.length() - 4)) ||
2465 (path.length() > 5 && path.find (".midi") != (path.length() - 5)));
2469 accept_all_state_files (const string& path, void* /*arg*/)
2471 if (!Glib::file_test (path, Glib::FILE_TEST_IS_REGULAR)) {
2475 return (path.length() > 7 && path.find (".ardour") == (path.length() - 7));
2479 Session::find_all_sources (string path, set<string>& result)
2484 if (!tree.read (path)) {
2488 if ((node = find_named_node (*tree.root(), "Sources")) == 0) {
2493 XMLNodeConstIterator niter;
2495 nlist = node->children();
2499 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2503 if ((prop = (*niter)->property (X_("type"))) == 0) {
2507 DataType type (prop->value());
2509 if ((prop = (*niter)->property (X_("name"))) == 0) {
2513 if (Glib::path_is_absolute (prop->value())) {
2514 /* external file, ignore */
2522 if (FileSource::find (*this, type, prop->value(), true, is_new, chan, found_path)) {
2523 result.insert (found_path);
2531 Session::find_all_sources_across_snapshots (set<string>& result, bool exclude_this_snapshot)
2533 vector<string> state_files;
2535 string this_snapshot_path;
2541 if (ripped[ripped.length()-1] == G_DIR_SEPARATOR) {
2542 ripped = ripped.substr (0, ripped.length() - 1);
2545 find_files_matching_filter (state_files, ripped, accept_all_state_files, (void *) 0, true, true);
2547 if (state_files.empty()) {
2552 this_snapshot_path = _path;
2553 this_snapshot_path += legalize_for_path (_current_snapshot_name);
2554 this_snapshot_path += statefile_suffix;
2556 for (vector<string>::iterator i = state_files.begin(); i != state_files.end(); ++i) {
2558 if (exclude_this_snapshot && *i == this_snapshot_path) {
2562 if (find_all_sources (*i, result) < 0) {
2570 struct RegionCounter {
2571 typedef std::map<PBD::ID,boost::shared_ptr<AudioSource> > AudioSourceList;
2572 AudioSourceList::iterator iter;
2573 boost::shared_ptr<Region> region;
2576 RegionCounter() : count (0) {}
2580 Session::ask_about_playlist_deletion (boost::shared_ptr<Playlist> p)
2582 boost::optional<int> r = AskAboutPlaylistDeletion (p);
2583 return r.get_value_or (1);
2587 Session::cleanup_regions ()
2589 const RegionFactory::RegionMap& regions (RegionFactory::regions());
2591 for (RegionFactory::RegionMap::const_iterator i = regions.begin(); i != regions.end(); ++i) {
2593 uint32_t used = playlists->region_use_count (i->second);
2595 if (used == 0 && !i->second->automatic ()) {
2596 RegionFactory::map_remove (i->second);
2600 /* dump the history list */
2607 Session::cleanup_sources (CleanupReport& rep)
2609 // FIXME: needs adaptation to midi
2611 vector<boost::shared_ptr<Source> > dead_sources;
2614 vector<string> candidates;
2615 vector<string> unused;
2616 set<string> all_sources;
2625 _state_of_the_state = (StateOfTheState) (_state_of_the_state | InCleanup);
2627 /* consider deleting all unused playlists */
2629 if (playlists->maybe_delete_unused (boost::bind (Session::ask_about_playlist_deletion, _1))) {
2634 /* sync the "all regions" property of each playlist with its current state
2637 playlists->sync_all_regions_with_regions ();
2639 /* find all un-used sources */
2644 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ) {
2646 SourceMap::iterator tmp;
2651 /* do not bother with files that are zero size, otherwise we remove the current "nascent"
2655 if (!i->second->used() && (i->second->length(i->second->timeline_position() > 0))) {
2656 dead_sources.push_back (i->second);
2657 i->second->drop_references ();
2663 /* build a list of all the possible audio directories for the session */
2665 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
2666 SessionDirectory sdir ((*i).path);
2667 asp += sdir.sound_path();
2669 audio_path += asp.to_string();
2672 /* build a list of all the possible midi directories for the session */
2674 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
2675 SessionDirectory sdir ((*i).path);
2676 msp += sdir.midi_path();
2678 midi_path += msp.to_string();
2680 find_files_matching_filter (candidates, audio_path, accept_all_audio_files, (void *) 0, true, true);
2681 find_files_matching_filter (candidates, midi_path, accept_all_midi_files, (void *) 0, true, true);
2683 /* find all sources, but don't use this snapshot because the
2684 state file on disk still references sources we may have already
2688 find_all_sources_across_snapshots (all_sources, true);
2690 /* add our current source list
2693 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ) {
2694 boost::shared_ptr<FileSource> fs;
2695 SourceMap::iterator tmp = i;
2698 if ((fs = boost::dynamic_pointer_cast<FileSource> (i->second)) != 0) {
2700 if (!fs->is_stub()) {
2702 if (playlists->source_use_count (fs) != 0) {
2703 all_sources.insert (fs->path());
2706 /* we might not remove this source from disk, because it may be used
2707 by other snapshots, but its not being used in this version
2708 so lets get rid of it now, along with any representative regions
2712 RegionFactory::remove_regions_using_source (i->second);
2721 for (vector<string>::iterator x = candidates.begin(); x != candidates.end(); ++x) {
2726 for (set<string>::iterator i = all_sources.begin(); i != all_sources.end(); ++i) {
2728 tmppath1 = canonical_path (spath);
2729 tmppath2 = canonical_path ((*i));
2731 if (tmppath1 == tmppath2) {
2738 unused.push_back (spath);
2742 /* now try to move all unused files into the "dead" directory(ies) */
2744 for (vector<string>::iterator x = unused.begin(); x != unused.end(); ++x) {
2745 struct stat statbuf;
2749 /* don't move the file across filesystems, just
2750 stick it in the `dead_dir_name' directory
2751 on whichever filesystem it was already on.
2754 if ((*x).find ("/sounds/") != string::npos) {
2756 /* old school, go up 1 level */
2758 newpath = Glib::path_get_dirname (*x); // "sounds"
2759 newpath = Glib::path_get_dirname (newpath); // "session-name"
2763 /* new school, go up 4 levels */
2765 newpath = Glib::path_get_dirname (*x); // "audiofiles" or "midifiles"
2766 newpath = Glib::path_get_dirname (newpath); // "session-name"
2767 newpath = Glib::path_get_dirname (newpath); // "interchange"
2768 newpath = Glib::path_get_dirname (newpath); // "session-dir"
2771 newpath = Glib::build_filename (newpath, dead_dir_name);
2773 if (g_mkdir_with_parents (newpath.c_str(), 0755) < 0) {
2774 error << string_compose(_("Session: cannot create dead file folder \"%1\" (%2)"), newpath, strerror (errno)) << endmsg;
2778 newpath = Glib::build_filename (newpath, Glib::path_get_basename ((*x)));
2780 if (Glib::file_test (newpath, Glib::FILE_TEST_EXISTS)) {
2782 /* the new path already exists, try versioning */
2784 char buf[PATH_MAX+1];
2788 snprintf (buf, sizeof (buf), "%s.%d", newpath.c_str(), version);
2791 while (Glib::file_test (newpath_v.c_str(), Glib::FILE_TEST_EXISTS) && version < 999) {
2792 snprintf (buf, sizeof (buf), "%s.%d", newpath.c_str(), ++version);
2796 if (version == 999) {
2797 error << string_compose (_("there are already 1000 files with names like %1; versioning discontinued"),
2801 newpath = newpath_v;
2806 /* it doesn't exist, or we can't read it or something */
2810 stat ((*x).c_str(), &statbuf);
2812 if (::rename ((*x).c_str(), newpath.c_str()) != 0) {
2813 error << string_compose (_("cannot rename unused file source from %1 to %2 (%3)"),
2814 (*x), newpath, strerror (errno))
2819 /* see if there an easy to find peakfile for this file, and remove it.
2822 string base = basename_nosuffix (*x);
2823 base += "%A"; /* this is what we add for the channel suffix of all native files,
2824 or for the first channel of embedded files. it will miss
2825 some peakfiles for other channels
2827 string peakpath = peak_path (base);
2829 if (Glib::file_test (peakpath.c_str(), Glib::FILE_TEST_EXISTS)) {
2830 if (::g_unlink (peakpath.c_str()) != 0) {
2831 error << string_compose (_("cannot remove peakfile %1 for %2 (%3)"),
2832 peakpath, _path, strerror (errno))
2834 /* try to back out */
2835 ::rename (newpath.c_str(), _path.c_str());
2840 rep.paths.push_back (*x);
2841 rep.space += statbuf.st_size;
2844 /* dump the history list */
2848 /* save state so we don't end up a session file
2849 referring to non-existent sources.
2856 _state_of_the_state = (StateOfTheState) (_state_of_the_state & ~InCleanup);
2862 Session::cleanup_trash_sources (CleanupReport& rep)
2864 // FIXME: needs adaptation for MIDI
2866 vector<space_and_path>::iterator i;
2872 for (i = session_dirs.begin(); i != session_dirs.end(); ++i) {
2874 dead_dir = Glib::build_filename ((*i).path, dead_dir_name);
2876 clear_directory (dead_dir, &rep.space, &rep.paths);
2883 Session::set_dirty ()
2885 bool was_dirty = dirty();
2887 _state_of_the_state = StateOfTheState (_state_of_the_state | Dirty);
2891 DirtyChanged(); /* EMIT SIGNAL */
2897 Session::set_clean ()
2899 bool was_dirty = dirty();
2901 _state_of_the_state = Clean;
2905 DirtyChanged(); /* EMIT SIGNAL */
2910 Session::set_deletion_in_progress ()
2912 _state_of_the_state = StateOfTheState (_state_of_the_state | Deletion);
2916 Session::clear_deletion_in_progress ()
2918 _state_of_the_state = StateOfTheState (_state_of_the_state & (~Deletion));
2922 Session::add_controllable (boost::shared_ptr<Controllable> c)
2924 /* this adds a controllable to the list managed by the Session.
2925 this is a subset of those managed by the Controllable class
2926 itself, and represents the only ones whose state will be saved
2927 as part of the session.
2930 Glib::Threads::Mutex::Lock lm (controllables_lock);
2931 controllables.insert (c);
2934 struct null_deleter { void operator()(void const *) const {} };
2937 Session::remove_controllable (Controllable* c)
2939 if (_state_of_the_state & Deletion) {
2943 Glib::Threads::Mutex::Lock lm (controllables_lock);
2945 Controllables::iterator x = controllables.find (boost::shared_ptr<Controllable>(c, null_deleter()));
2947 if (x != controllables.end()) {
2948 controllables.erase (x);
2952 boost::shared_ptr<Controllable>
2953 Session::controllable_by_id (const PBD::ID& id)
2955 Glib::Threads::Mutex::Lock lm (controllables_lock);
2957 for (Controllables::iterator i = controllables.begin(); i != controllables.end(); ++i) {
2958 if ((*i)->id() == id) {
2963 return boost::shared_ptr<Controllable>();
2966 boost::shared_ptr<Controllable>
2967 Session::controllable_by_descriptor (const ControllableDescriptor& desc)
2969 boost::shared_ptr<Controllable> c;
2970 boost::shared_ptr<Route> r;
2972 switch (desc.top_level_type()) {
2973 case ControllableDescriptor::NamedRoute:
2975 std::string str = desc.top_level_name();
2976 if (str == "Master" || str == "master") {
2978 } else if (str == "control" || str == "listen") {
2981 r = route_by_name (desc.top_level_name());
2986 case ControllableDescriptor::RemoteControlID:
2987 r = route_by_remote_id (desc.rid());
2995 switch (desc.subtype()) {
2996 case ControllableDescriptor::Gain:
2997 c = r->gain_control ();
3000 case ControllableDescriptor::Solo:
3001 c = r->solo_control();
3004 case ControllableDescriptor::Mute:
3005 c = r->mute_control();
3008 case ControllableDescriptor::Recenable:
3010 boost::shared_ptr<Track> t = boost::dynamic_pointer_cast<Track>(r);
3013 c = t->rec_enable_control ();
3018 case ControllableDescriptor::PanDirection:
3020 c = r->pannable()->pan_azimuth_control;
3024 case ControllableDescriptor::PanWidth:
3026 c = r->pannable()->pan_width_control;
3030 case ControllableDescriptor::PanElevation:
3032 c = r->pannable()->pan_elevation_control;
3036 case ControllableDescriptor::Balance:
3037 /* XXX simple pan control */
3040 case ControllableDescriptor::PluginParameter:
3042 uint32_t plugin = desc.target (0);
3043 uint32_t parameter_index = desc.target (1);
3045 /* revert to zero based counting */
3051 if (parameter_index > 0) {
3055 boost::shared_ptr<Processor> p = r->nth_plugin (plugin);
3058 c = boost::dynamic_pointer_cast<ARDOUR::AutomationControl>(
3059 p->control(Evoral::Parameter(PluginAutomation, 0, parameter_index)));
3064 case ControllableDescriptor::SendGain:
3066 uint32_t send = desc.target (0);
3068 /* revert to zero-based counting */
3074 boost::shared_ptr<Processor> p = r->nth_send (send);
3077 boost::shared_ptr<Send> s = boost::dynamic_pointer_cast<Send>(p);
3078 boost::shared_ptr<Amp> a = s->amp();
3081 c = s->amp()->gain_control();
3088 /* relax and return a null pointer */
3096 Session::add_instant_xml (XMLNode& node, bool write_to_config)
3099 Stateful::add_instant_xml (node, _path);
3102 if (write_to_config) {
3103 Config->add_instant_xml (node);
3108 Session::instant_xml (const string& node_name)
3110 return Stateful::instant_xml (node_name, _path);
3114 Session::save_history (string snapshot_name)
3122 if (!Config->get_save_history() || Config->get_saved_history_depth() < 0 ||
3123 (_history.undo_depth() == 0 && _history.redo_depth() == 0)) {
3127 if (snapshot_name.empty()) {
3128 snapshot_name = _current_snapshot_name;
3131 const string history_filename = legalize_for_path (snapshot_name) + history_suffix;
3132 const string backup_filename = history_filename + backup_suffix;
3133 const std::string xml_path(Glib::build_filename (_session_dir->root_path(), history_filename));
3134 const std::string backup_path(Glib::build_filename (_session_dir->root_path(), backup_filename));
3136 if (Glib::file_test (xml_path, Glib::FILE_TEST_EXISTS)) {
3137 if (::g_rename (xml_path.c_str(), backup_path.c_str()) != 0) {
3138 error << _("could not backup old history file, current history not saved") << endmsg;
3143 tree.set_root (&_history.get_state (Config->get_saved_history_depth()));
3145 if (!tree.write (xml_path))
3147 error << string_compose (_("history could not be saved to %1"), xml_path) << endmsg;
3149 if (g_remove (xml_path.c_str()) != 0) {
3150 error << string_compose(_("Could not remove history file at path \"%1\" (%2)"),
3151 xml_path, g_strerror (errno)) << endmsg;
3153 if (::g_rename (backup_path.c_str(), xml_path.c_str()) != 0) {
3154 error << string_compose (_("could not restore history file from backup %1 (%2)"),
3155 backup_path, g_strerror (errno)) << endmsg;
3165 Session::restore_history (string snapshot_name)
3169 if (snapshot_name.empty()) {
3170 snapshot_name = _current_snapshot_name;
3173 const std::string xml_filename = legalize_for_path (snapshot_name) + history_suffix;
3174 const std::string xml_path(Glib::build_filename (_session_dir->root_path(), xml_filename));
3176 info << "Loading history from " << xml_path << endmsg;
3178 if (!Glib::file_test (xml_path, Glib::FILE_TEST_EXISTS)) {
3179 info << string_compose (_("%1: no history file \"%2\" for this session."),
3180 _name, xml_path) << endmsg;
3184 if (!tree.read (xml_path)) {
3185 error << string_compose (_("Could not understand session history file \"%1\""),
3186 xml_path) << endmsg;
3193 for (XMLNodeConstIterator it = tree.root()->children().begin(); it != tree.root()->children().end(); it++) {
3196 UndoTransaction* ut = new UndoTransaction ();
3199 ut->set_name(t->property("name")->value());
3200 stringstream ss(t->property("tv-sec")->value());
3202 ss.str(t->property("tv-usec")->value());
3204 ut->set_timestamp(tv);
3206 for (XMLNodeConstIterator child_it = t->children().begin();
3207 child_it != t->children().end(); child_it++)
3209 XMLNode *n = *child_it;
3212 if (n->name() == "MementoCommand" ||
3213 n->name() == "MementoUndoCommand" ||
3214 n->name() == "MementoRedoCommand") {
3216 if ((c = memento_command_factory(n))) {
3220 } else if (n->name() == "NoteDiffCommand") {
3221 PBD::ID id (n->property("midi-source")->value());
3222 boost::shared_ptr<MidiSource> midi_source =
3223 boost::dynamic_pointer_cast<MidiSource, Source>(source_by_id(id));
3225 ut->add_command (new MidiModel::NoteDiffCommand(midi_source->model(), *n));
3227 error << _("Failed to downcast MidiSource for NoteDiffCommand") << endmsg;
3230 } else if (n->name() == "SysExDiffCommand") {
3232 PBD::ID id (n->property("midi-source")->value());
3233 boost::shared_ptr<MidiSource> midi_source =
3234 boost::dynamic_pointer_cast<MidiSource, Source>(source_by_id(id));
3236 ut->add_command (new MidiModel::SysExDiffCommand (midi_source->model(), *n));
3238 error << _("Failed to downcast MidiSource for SysExDiffCommand") << endmsg;
3241 } else if (n->name() == "PatchChangeDiffCommand") {
3243 PBD::ID id (n->property("midi-source")->value());
3244 boost::shared_ptr<MidiSource> midi_source =
3245 boost::dynamic_pointer_cast<MidiSource, Source>(source_by_id(id));
3247 ut->add_command (new MidiModel::PatchChangeDiffCommand (midi_source->model(), *n));
3249 error << _("Failed to downcast MidiSource for PatchChangeDiffCommand") << endmsg;
3252 } else if (n->name() == "StatefulDiffCommand") {
3253 if ((c = stateful_diff_command_factory (n))) {
3254 ut->add_command (c);
3257 error << string_compose(_("Couldn't figure out how to make a Command out of a %1 XMLNode."), n->name()) << endmsg;
3268 Session::config_changed (std::string p, bool ours)
3274 if (p == "seamless-loop") {
3276 } else if (p == "rf-speed") {
3278 } else if (p == "auto-loop") {
3280 } else if (p == "auto-input") {
3282 if (Config->get_monitoring_model() == HardwareMonitoring && transport_rolling()) {
3283 /* auto-input only makes a difference if we're rolling */
3284 set_track_monitor_input_status (!config.get_auto_input());
3287 } else if (p == "punch-in") {
3291 if ((location = _locations->auto_punch_location()) != 0) {
3293 if (config.get_punch_in ()) {
3294 replace_event (SessionEvent::PunchIn, location->start());
3296 remove_event (location->start(), SessionEvent::PunchIn);
3300 } else if (p == "punch-out") {
3304 if ((location = _locations->auto_punch_location()) != 0) {
3306 if (config.get_punch_out()) {
3307 replace_event (SessionEvent::PunchOut, location->end());
3309 clear_events (SessionEvent::PunchOut);
3313 } else if (p == "edit-mode") {
3315 Glib::Threads::Mutex::Lock lm (playlists->lock);
3317 for (SessionPlaylists::List::iterator i = playlists->playlists.begin(); i != playlists->playlists.end(); ++i) {
3318 (*i)->set_edit_mode (Config->get_edit_mode ());
3321 } else if (p == "use-video-sync") {
3323 waiting_for_sync_offset = config.get_use_video_sync();
3325 } else if (p == "mmc-control") {
3327 //poke_midi_thread ();
3329 } else if (p == "mmc-device-id" || p == "mmc-receive-id" || p == "mmc-receive-device-id") {
3331 _mmc->set_receive_device_id (Config->get_mmc_receive_device_id());
3333 } else if (p == "mmc-send-id" || p == "mmc-send-device-id") {
3335 _mmc->set_send_device_id (Config->get_mmc_send_device_id());
3337 } else if (p == "midi-control") {
3339 //poke_midi_thread ();
3341 } else if (p == "raid-path") {
3343 setup_raid_path (config.get_raid_path());
3345 } else if (p == "timecode-format") {
3349 } else if (p == "video-pullup") {
3353 } else if (p == "seamless-loop") {
3355 if (play_loop && transport_rolling()) {
3356 // to reset diskstreams etc
3357 request_play_loop (true);
3360 } else if (p == "rf-speed") {
3362 cumulative_rf_motion = 0;
3365 } else if (p == "click-sound") {
3367 setup_click_sounds (1);
3369 } else if (p == "click-emphasis-sound") {
3371 setup_click_sounds (-1);
3373 } else if (p == "clicking") {
3375 if (Config->get_clicking()) {
3376 if (_click_io && click_data) { // don't require emphasis data
3383 } else if (p == "click-gain") {
3386 _click_gain->set_gain (Config->get_click_gain(), this);
3389 } else if (p == "send-mtc") {
3391 if (Config->get_send_mtc ()) {
3392 /* mark us ready to send */
3393 next_quarter_frame_to_send = 0;
3396 } else if (p == "send-mmc") {
3398 _mmc->enable_send (Config->get_send_mmc ());
3400 } else if (p == "midi-feedback") {
3402 session_midi_feedback = Config->get_midi_feedback();
3404 } else if (p == "jack-time-master") {
3406 engine().reset_timebase ();
3408 } else if (p == "native-file-header-format") {
3410 if (!first_file_header_format_reset) {
3411 reset_native_file_format ();
3414 first_file_header_format_reset = false;
3416 } else if (p == "native-file-data-format") {
3418 if (!first_file_data_format_reset) {
3419 reset_native_file_format ();
3422 first_file_data_format_reset = false;
3424 } else if (p == "external-sync") {
3425 if (!config.get_external_sync()) {
3426 drop_sync_source ();
3428 switch_to_sync_source (Config->get_sync_source());
3430 } else if (p == "denormal-model") {
3432 } else if (p == "history-depth") {
3433 set_history_depth (Config->get_history_depth());
3434 } else if (p == "remote-model") {
3435 /* XXX DO SOMETHING HERE TO TELL THE GUI THAT WE NEED
3438 } else if (p == "initial-program-change") {
3440 if (_mmc->output_port() && Config->get_initial_program_change() >= 0) {
3443 buf[0] = MIDI::program; // channel zero by default
3444 buf[1] = (Config->get_initial_program_change() & 0x7f);
3446 _mmc->output_port()->midimsg (buf, sizeof (buf), 0);
3448 } else if (p == "solo-mute-override") {
3449 // catch_up_on_solo_mute_override ();
3450 } else if (p == "listen-position" || p == "pfl-position") {
3451 listen_position_changed ();
3452 } else if (p == "solo-control-is-listen-control") {
3453 solo_control_mode_changed ();
3454 } else if (p == "timecode-offset" || p == "timecode-offset-negative") {
3455 last_timecode_valid = false;
3456 } else if (p == "playback-buffer-seconds") {
3457 AudioSource::allocate_working_buffers (frame_rate());
3458 } else if (p == "automation-thinning-factor") {
3459 Evoral::ControlList::set_thinning_factor (Config->get_automation_thinning_factor());
3460 } else if (p == "ltc-source-port") {
3461 reconnect_ltc_input ();
3462 } else if (p == "ltc-sink-port") {
3463 reconnect_ltc_output ();
3464 } else if (p == "timecode-generator-offset") {
3465 ltc_tx_parse_offset();
3472 Session::set_history_depth (uint32_t d)
3474 _history.set_depth (d);
3478 Session::load_diskstreams_2X (XMLNode const & node, int)
3481 XMLNodeConstIterator citer;
3483 clist = node.children();
3485 for (citer = clist.begin(); citer != clist.end(); ++citer) {
3488 /* diskstreams added automatically by DiskstreamCreated handler */
3489 if ((*citer)->name() == "AudioDiskstream" || (*citer)->name() == "DiskStream") {
3490 boost::shared_ptr<AudioDiskstream> dsp (new AudioDiskstream (*this, **citer));
3491 _diskstreams_2X.push_back (dsp);
3493 error << _("Session: unknown diskstream type in XML") << endmsg;
3497 catch (failed_constructor& err) {
3498 error << _("Session: could not load diskstream via XML state") << endmsg;
3506 /** Connect things to the MMC object */
3508 Session::setup_midi_machine_control ()
3510 _mmc = new MIDI::MachineControl;
3511 _mmc->set_ports (_midi_ports->mmc_input_port(), _midi_ports->mmc_output_port());
3513 _mmc->Play.connect_same_thread (*this, boost::bind (&Session::mmc_deferred_play, this, _1));
3514 _mmc->DeferredPlay.connect_same_thread (*this, boost::bind (&Session::mmc_deferred_play, this, _1));
3515 _mmc->Stop.connect_same_thread (*this, boost::bind (&Session::mmc_stop, this, _1));
3516 _mmc->FastForward.connect_same_thread (*this, boost::bind (&Session::mmc_fast_forward, this, _1));
3517 _mmc->Rewind.connect_same_thread (*this, boost::bind (&Session::mmc_rewind, this, _1));
3518 _mmc->Pause.connect_same_thread (*this, boost::bind (&Session::mmc_pause, this, _1));
3519 _mmc->RecordPause.connect_same_thread (*this, boost::bind (&Session::mmc_record_pause, this, _1));
3520 _mmc->RecordStrobe.connect_same_thread (*this, boost::bind (&Session::mmc_record_strobe, this, _1));
3521 _mmc->RecordExit.connect_same_thread (*this, boost::bind (&Session::mmc_record_exit, this, _1));
3522 _mmc->Locate.connect_same_thread (*this, boost::bind (&Session::mmc_locate, this, _1, _2));
3523 _mmc->Step.connect_same_thread (*this, boost::bind (&Session::mmc_step, this, _1, _2));
3524 _mmc->Shuttle.connect_same_thread (*this, boost::bind (&Session::mmc_shuttle, this, _1, _2, _3));
3525 _mmc->TrackRecordStatusChange.connect_same_thread (*this, boost::bind (&Session::mmc_record_enable, this, _1, _2, _3));
3527 /* also handle MIDI SPP because its so common */
3529 _mmc->SPPStart.connect_same_thread (*this, boost::bind (&Session::spp_start, this));
3530 _mmc->SPPContinue.connect_same_thread (*this, boost::bind (&Session::spp_continue, this));
3531 _mmc->SPPStop.connect_same_thread (*this, boost::bind (&Session::spp_stop, this));
3534 boost::shared_ptr<Controllable>
3535 Session::solo_cut_control() const
3537 /* the solo cut control is a bit of an anomaly, at least as of Febrary 2011. There are no other
3538 controls in Ardour that currently get presented to the user in the GUI that require
3539 access as a Controllable and are also NOT owned by some SessionObject (e.g. Route, or MonitorProcessor).
3541 its actually an RCConfiguration parameter, so we use a ProxyControllable to wrap
3542 it up as a Controllable. Changes to the Controllable will just map back to the RCConfiguration
3546 return _solo_cut_control;
3550 Session::rename (const std::string& new_name)
3552 string legal_name = legalize_for_path (new_name);
3558 string const old_sources_root = _session_dir->sources_root();
3563 * interchange subdirectory
3567 * Backup files are left unchanged and not renamed.
3570 /* pass one: not 100% safe check that the new directory names don't
3574 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
3579 /* this is a stupid hack because Glib::path_get_dirname() is
3580 * lexical-only, and so passing it /a/b/c/ gives a different
3581 * result than passing it /a/b/c ...
3584 if (oldstr[oldstr.length()-1] == G_DIR_SEPARATOR) {
3585 oldstr = oldstr.substr (0, oldstr.length() - 1);
3588 string base = Glib::path_get_dirname (oldstr);
3589 string p = Glib::path_get_basename (oldstr);
3591 newstr = Glib::build_filename (base, legal_name);
3593 if (Glib::file_test (newstr, Glib::FILE_TEST_EXISTS)) {
3600 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
3605 /* this is a stupid hack because Glib::path_get_dirname() is
3606 * lexical-only, and so passing it /a/b/c/ gives a different
3607 * result than passing it /a/b/c ...
3610 if (oldstr[oldstr.length()-1] == G_DIR_SEPARATOR) {
3611 oldstr = oldstr.substr (0, oldstr.length() - 1);
3614 string base = Glib::path_get_dirname (oldstr);
3615 string p = Glib::path_get_basename (oldstr);
3617 newstr = Glib::build_filename (base, legal_name);
3619 cerr << "Rename " << oldstr << " => " << newstr << endl;
3621 if (::g_rename (oldstr.c_str(), newstr.c_str()) != 0) {
3622 error << string_compose (_("renaming %s as %2 failed (%3)"), oldstr, newstr, g_strerror (errno)) << endmsg;
3627 (*_session_dir) = newstr;
3632 /* directory below interchange */
3634 v.push_back (newstr);
3635 v.push_back (interchange_dir_name);
3638 oldstr = Glib::build_filename (v);
3641 v.push_back (newstr);
3642 v.push_back (interchange_dir_name);
3643 v.push_back (legal_name);
3645 newstr = Glib::build_filename (v);
3647 cerr << "Rename " << oldstr << " => " << newstr << endl;
3649 if (::g_rename (oldstr.c_str(), newstr.c_str()) != 0) {
3650 error << string_compose (_("renaming %s as %2 failed (%3)"), oldstr, newstr, g_strerror (errno)) << endmsg;
3657 oldstr = Glib::build_filename (newpath, _current_snapshot_name) + statefile_suffix;
3658 newstr= Glib::build_filename (newpath, legal_name) + statefile_suffix;
3660 cerr << "Rename " << oldstr << " => " << newstr << endl;
3662 if (::g_rename (oldstr.c_str(), newstr.c_str()) != 0) {
3663 error << string_compose (_("renaming %s as %2 failed (%3)"), oldstr, newstr, g_strerror (errno)) << endmsg;
3670 oldstr = Glib::build_filename (newpath, _current_snapshot_name) + history_suffix;
3672 if (Glib::file_test (oldstr, Glib::FILE_TEST_EXISTS)) {
3673 newstr = Glib::build_filename (newpath, legal_name) + history_suffix;
3675 cerr << "Rename " << oldstr << " => " << newstr << endl;
3677 if (::g_rename (oldstr.c_str(), newstr.c_str()) != 0) {
3678 error << string_compose (_("renaming %s as %2 failed (%3)"), oldstr, newstr, g_strerror (errno)) << endmsg;
3683 /* update file source paths */
3685 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ++i) {
3686 boost::shared_ptr<FileSource> fs = boost::dynamic_pointer_cast<FileSource> (i->second);
3688 string p = fs->path ();
3689 boost::replace_all (p, old_sources_root, _session_dir->sources_root());
3694 /* remove old name from recent sessions */
3696 remove_recent_sessions (_path);
3699 _current_snapshot_name = new_name;
3702 /* re-add directory separator - reverse hack to oldstr above */
3703 if (_path[_path.length()-1] != G_DIR_SEPARATOR) {
3704 _path += G_DIR_SEPARATOR;
3709 /* save state again to get everything just right */
3711 save_state (_current_snapshot_name);
3714 /* add to recent sessions */
3716 store_recent_sessions (new_name, _path);
3722 Session::get_session_info_from_path (XMLTree& tree, const string& xmlpath)
3724 if (!Glib::file_test (xmlpath, Glib::FILE_TEST_EXISTS)) {
3728 if (!tree.read (xmlpath)) {
3736 Session::get_info_from_path (const string& xmlpath, float& sample_rate, SampleFormat& data_format)
3739 bool found_sr = false;
3740 bool found_data_format = false;
3742 if (get_session_info_from_path (tree, xmlpath)) {
3748 const XMLProperty* prop;
3749 if ((prop = tree.root()->property (X_("sample-rate"))) != 0) {
3750 sample_rate = atoi (prop->value());
3754 const XMLNodeList& children (tree.root()->children());
3755 for (XMLNodeList::const_iterator c = children.begin(); c != children.end(); ++c) {
3756 const XMLNode* child = *c;
3757 if (child->name() == "Config") {
3758 const XMLNodeList& options (child->children());
3759 for (XMLNodeList::const_iterator oc = options.begin(); oc != options.end(); ++oc) {
3760 const XMLNode* option = *oc;
3761 const XMLProperty* name = option->property("name");
3767 if (name->value() == "native-file-data-format") {
3768 const XMLProperty* value = option->property ("value");
3770 SampleFormat fmt = (SampleFormat) string_2_enum (option->property ("value")->value(), fmt);
3772 found_data_format = true;
3778 if (found_data_format) {
3783 return !(found_sr && found_data_format); // zero if they are both found
3786 typedef std::vector<boost::shared_ptr<FileSource> > SeveralFileSources;
3787 typedef std::map<std::string,SeveralFileSources> SourcePathMap;
3790 Session::bring_all_sources_into_session (boost::function<void(uint32_t,uint32_t,string)> callback)
3794 SourcePathMap source_path_map;
3796 boost::shared_ptr<AudioFileSource> afs;
3801 Glib::Threads::Mutex::Lock lm (source_lock);
3803 cerr << " total sources = " << sources.size();
3805 for (SourceMap::const_iterator i = sources.begin(); i != sources.end(); ++i) {
3806 boost::shared_ptr<FileSource> fs = boost::dynamic_pointer_cast<FileSource> (i->second);
3812 if (fs->within_session()) {
3813 cerr << "skip " << fs->name() << endl;
3817 if (source_path_map.find (fs->path()) != source_path_map.end()) {
3818 source_path_map[fs->path()].push_back (fs);
3820 SeveralFileSources v;
3822 source_path_map.insert (make_pair (fs->path(), v));
3828 cerr << " fsources = " << total << endl;
3830 for (SourcePathMap::iterator i = source_path_map.begin(); i != source_path_map.end(); ++i) {
3832 /* tell caller where we are */
3834 string old_path = i->first;
3836 callback (n, total, old_path);
3838 cerr << old_path << endl;
3842 switch (i->second.front()->type()) {
3843 case DataType::AUDIO:
3844 new_path = new_audio_source_path_for_embedded (old_path);
3847 case DataType::MIDI:
3851 cerr << "Move " << old_path << " => " << new_path << endl;
3853 if (!copy_file (old_path, new_path)) {
3854 cerr << "failed !\n";
3858 /* make sure we stop looking in the external
3859 dir/folder. Remember, this is an all-or-nothing
3860 operations, it doesn't merge just some files.
3862 remove_dir_from_search_path (Glib::path_get_dirname (old_path), i->second.front()->type());
3864 for (SeveralFileSources::iterator f = i->second.begin(); f != i->second.end(); ++f) {
3865 (*f)->set_path (new_path);
3870 save_state ("", false, false);