2 Copyright (C) 1999-2013 Paul Davis
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 #include "libardour-config.h"
31 #include <cstdio> /* snprintf(3) ... grrr */
44 #include <sys/param.h>
45 #include <sys/mount.h>
48 #ifdef HAVE_SYS_STATVFS_H
49 #include <sys/statvfs.h>
53 #include <glib/gstdio.h>
56 #include <glibmm/threads.h>
58 #include <boost/algorithm/string.hpp>
60 #include "midi++/mmc.h"
61 #include "midi++/port.h"
63 #include "evoral/SMF.hpp"
65 #include "pbd/boost_debug.h"
66 #include "pbd/basename.h"
67 #include "pbd/controllable_descriptor.h"
68 #include "pbd/enumwriter.h"
69 #include "pbd/error.h"
70 #include "pbd/file_utils.h"
71 #include "pbd/pathexpand.h"
72 #include "pbd/pthread_utils.h"
73 #include "pbd/stacktrace.h"
74 #include "pbd/convert.h"
75 #include "pbd/localtime_r.h"
77 #include "ardour/amp.h"
78 #include "ardour/async_midi_port.h"
79 #include "ardour/audio_diskstream.h"
80 #include "ardour/audio_track.h"
81 #include "ardour/audioengine.h"
82 #include "ardour/audiofilesource.h"
83 #include "ardour/audioregion.h"
84 #include "ardour/automation_control.h"
85 #include "ardour/butler.h"
86 #include "ardour/control_protocol_manager.h"
87 #include "ardour/directory_names.h"
88 #include "ardour/filename_extensions.h"
89 #include "ardour/graph.h"
90 #include "ardour/location.h"
91 #include "ardour/midi_model.h"
92 #include "ardour/midi_patch_manager.h"
93 #include "ardour/midi_region.h"
94 #include "ardour/midi_scene_changer.h"
95 #include "ardour/midi_source.h"
96 #include "ardour/midi_track.h"
97 #include "ardour/pannable.h"
98 #include "ardour/playlist_factory.h"
99 #include "ardour/playlist_source.h"
100 #include "ardour/port.h"
101 #include "ardour/processor.h"
102 #include "ardour/proxy_controllable.h"
103 #include "ardour/recent_sessions.h"
104 #include "ardour/region_factory.h"
105 #include "ardour/route_group.h"
106 #include "ardour/send.h"
107 #include "ardour/session.h"
108 #include "ardour/session_directory.h"
109 #include "ardour/session_metadata.h"
110 #include "ardour/session_playlists.h"
111 #include "ardour/session_state_utils.h"
112 #include "ardour/silentfilesource.h"
113 #include "ardour/sndfilesource.h"
114 #include "ardour/source_factory.h"
115 #include "ardour/speakers.h"
116 #include "ardour/template_utils.h"
117 #include "ardour/tempo.h"
118 #include "ardour/ticker.h"
119 #include "ardour/user_bundle.h"
121 #include "control_protocol/control_protocol.h"
127 using namespace ARDOUR;
131 Session::pre_engine_init (string fullpath)
133 if (fullpath.empty()) {
135 throw failed_constructor();
138 /* discover canonical fullpath */
140 _path = canonical_path(fullpath);
142 /* we require _path to end with a dir separator */
144 if (_path[_path.length()-1] != G_DIR_SEPARATOR) {
145 _path += G_DIR_SEPARATOR;
150 _is_new = !Glib::file_test (_path, Glib::FileTest (G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR));
152 /* finish initialization that can't be done in a normal C++ constructor
156 timerclear (&last_mmc_step);
157 g_atomic_int_set (&processing_prohibited, 0);
158 g_atomic_int_set (&_record_status, Disabled);
159 g_atomic_int_set (&_playback_load, 100);
160 g_atomic_int_set (&_capture_load, 100);
162 _all_route_group->set_active (true, this);
163 interpolation.add_channel_to (0, 0);
165 if (config.get_use_video_sync()) {
166 waiting_for_sync_offset = true;
168 waiting_for_sync_offset = false;
171 last_rr_session_dir = session_dirs.begin();
173 set_history_depth (Config->get_history_depth());
175 /* default: assume simple stereo speaker configuration */
177 _speakers->setup_default_speakers (2);
179 _solo_cut_control.reset (new ProxyControllable (_("solo cut control (dB)"), PBD::Controllable::GainLike,
180 boost::bind (&RCConfiguration::set_solo_mute_gain, Config, _1),
181 boost::bind (&RCConfiguration::get_solo_mute_gain, Config)));
182 add_controllable (_solo_cut_control);
184 /* These are all static "per-class" signals */
186 SourceFactory::SourceCreated.connect_same_thread (*this, boost::bind (&Session::add_source, this, _1));
187 PlaylistFactory::PlaylistCreated.connect_same_thread (*this, boost::bind (&Session::add_playlist, this, _1, _2));
188 AutomationList::AutomationListCreated.connect_same_thread (*this, boost::bind (&Session::add_automation_list, this, _1));
189 Controllable::Destroyed.connect_same_thread (*this, boost::bind (&Session::remove_controllable, this, _1));
190 IO::PortCountChanged.connect_same_thread (*this, boost::bind (&Session::ensure_buffers, this, _1));
192 /* stop IO objects from doing stuff until we're ready for them */
194 Delivery::disable_panners ();
195 IO::disable_connecting ();
197 AudioFileSource::set_peak_dir (_session_dir->peak_path());
201 Session::post_engine_init ()
203 BootMessage (_("Set block size and sample rate"));
205 set_block_size (_engine.samples_per_cycle());
206 set_frame_rate (_engine.sample_rate());
208 BootMessage (_("Using configuration"));
210 _midi_ports = new MidiPortManager;
212 MIDISceneChanger* msc;
214 _scene_changer = msc = new MIDISceneChanger (*this);
215 msc->set_input_port (scene_input_port());
216 msc->set_output_port (scene_out());
218 boost::function<framecnt_t(void)> timer_func (boost::bind (&Session::audible_frame, this));
219 boost::dynamic_pointer_cast<AsyncMIDIPort>(scene_in())->set_timer (timer_func);
221 setup_midi_machine_control ();
223 if (_butler->start_thread()) {
227 if (start_midi_thread ()) {
231 setup_click_sounds (0);
232 setup_midi_control ();
234 _engine.Halted.connect_same_thread (*this, boost::bind (&Session::engine_halted, this));
235 _engine.Xrun.connect_same_thread (*this, boost::bind (&Session::xrun_recovery, this));
238 /* tempo map requires sample rate knowledge */
240 _tempo_map = new TempoMap (_current_frame_rate);
241 _tempo_map->PropertyChanged.connect_same_thread (*this, boost::bind (&Session::tempo_map_changed, this, _1));
243 /* MidiClock requires a tempo map */
245 midi_clock = new MidiClockTicker ();
246 midi_clock->set_session (this);
248 /* crossfades require sample rate knowledge */
250 SndFileSource::setup_standard_crossfades (*this, frame_rate());
251 _engine.GraphReordered.connect_same_thread (*this, boost::bind (&Session::graph_reordered, this));
253 AudioDiskstream::allocate_working_buffers();
254 refresh_disk_space ();
256 /* we're finally ready to call set_state() ... all objects have
257 * been created, the engine is running.
261 if (set_state (*state_tree->root(), Stateful::loading_state_version)) {
265 // set_state() will call setup_raid_path(), but if it's a new session we need
266 // to call setup_raid_path() here.
267 setup_raid_path (_path);
272 boost::function<void (std::string)> ff (boost::bind (&Session::config_changed, this, _1, false));
273 boost::function<void (std::string)> ft (boost::bind (&Session::config_changed, this, _1, true));
275 Config->map_parameters (ff);
276 config.map_parameters (ft);
278 /* Reset all panners */
280 Delivery::reset_panners ();
282 /* this will cause the CPM to instantiate any protocols that are in use
283 * (or mandatory), which will pass it this Session, and then call
284 * set_state() on each instantiated protocol to match stored state.
287 ControlProtocolManager::instance().set_session (this);
289 /* This must be done after the ControlProtocolManager set_session above,
290 as it will set states for ports which the ControlProtocolManager creates.
293 // XXX set state of MIDI::Port's
294 // MidiPortManager::instance()->set_port_states (Config->midi_port_states ());
296 /* And this must be done after the MIDI::Manager::set_port_states as
297 * it will try to make connections whose details are loaded by set_port_states.
302 /* Let control protocols know that we are now all connected, so they
303 * could start talking to surfaces if they want to.
306 ControlProtocolManager::instance().midi_connectivity_established ();
308 if (_is_new && !no_auto_connect()) {
309 Glib::Threads::Mutex::Lock lm (AudioEngine::instance()->process_lock());
310 auto_connect_master_bus ();
313 _state_of_the_state = StateOfTheState (_state_of_the_state & ~(CannotSave|Dirty));
315 /* update latencies */
317 initialize_latencies ();
319 _locations->added.connect_same_thread (*this, boost::bind (&Session::location_added, this, _1));
320 _locations->removed.connect_same_thread (*this, boost::bind (&Session::location_removed, this, _1));
321 _locations->changed.connect_same_thread (*this, boost::bind (&Session::locations_changed, this));
323 } catch (AudioEngine::PortRegistrationFailure& err) {
324 /* handle this one in a different way than all others, so that its clear what happened */
325 error << err.what() << endmsg;
331 BootMessage (_("Reset Remote Controls"));
333 // send_full_time_code (0);
334 _engine.transport_locate (0);
336 send_immediate_mmc (MIDI::MachineControlCommand (MIDI::MachineControl::cmdMmcReset));
337 send_immediate_mmc (MIDI::MachineControlCommand (Timecode::Time ()));
339 MIDI::Name::MidiPatchManager::instance().set_session (this);
342 /* initial program change will be delivered later; see ::config_changed() */
344 _state_of_the_state = Clean;
346 Port::set_connecting_blocked (false);
348 DirtyChanged (); /* EMIT SIGNAL */
352 } else if (state_was_pending) {
354 remove_pending_capture_state ();
355 state_was_pending = false;
362 Session::raid_path () const
364 Searchpath raid_search_path;
366 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
367 raid_search_path += (*i).path;
370 return raid_search_path.to_string ();
374 Session::setup_raid_path (string path)
383 session_dirs.clear ();
385 Searchpath search_path(path);
386 Searchpath sound_search_path;
387 Searchpath midi_search_path;
389 for (Searchpath::const_iterator i = search_path.begin(); i != search_path.end(); ++i) {
391 sp.blocks = 0; // not needed
392 session_dirs.push_back (sp);
394 SessionDirectory sdir(sp.path);
396 sound_search_path += sdir.sound_path ();
397 midi_search_path += sdir.midi_path ();
400 // reset the round-robin soundfile path thingie
401 last_rr_session_dir = session_dirs.begin();
405 Session::path_is_within_session (const std::string& path)
407 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
408 if (PBD::path_is_within (i->path, path)) {
416 Session::ensure_subdirs ()
420 dir = session_directory().peak_path();
422 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
423 error << string_compose(_("Session: cannot create session peakfile folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
427 dir = session_directory().sound_path();
429 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
430 error << string_compose(_("Session: cannot create session sounds dir \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
434 dir = session_directory().midi_path();
436 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
437 error << string_compose(_("Session: cannot create session midi dir \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
441 dir = session_directory().dead_path();
443 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
444 error << string_compose(_("Session: cannot create session dead sounds folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
448 dir = session_directory().export_path();
450 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
451 error << string_compose(_("Session: cannot create session export folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
455 dir = analysis_dir ();
457 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
458 error << string_compose(_("Session: cannot create session analysis folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
462 dir = plugins_dir ();
464 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
465 error << string_compose(_("Session: cannot create session plugins folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
469 dir = externals_dir ();
471 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
472 error << string_compose(_("Session: cannot create session externals folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
479 /** @param session_template directory containing session template, or empty.
480 * Caller must not hold process lock.
483 Session::create (const string& session_template, BusProfile* bus_profile)
485 if (g_mkdir_with_parents (_path.c_str(), 0755) < 0) {
486 error << string_compose(_("Session: cannot create session folder \"%1\" (%2)"), _path, strerror (errno)) << endmsg;
490 if (ensure_subdirs ()) {
494 _writable = exists_and_writable (_path);
496 if (!session_template.empty()) {
497 std::string in_path = session_template_dir_to_file (session_template);
499 ifstream in(in_path.c_str());
502 /* no need to call legalize_for_path() since the string
503 * in session_template is already a legal path name
505 string out_path = Glib::build_filename (_session_dir->root_path(), _name + statefile_suffix);
507 ofstream out(out_path.c_str());
513 /* Copy plugin state files from template to new session */
514 std::string template_plugins = Glib::build_filename (session_template, X_("plugins"));
515 copy_recurse (template_plugins, plugins_dir ());
520 error << string_compose (_("Could not open %1 for writing session template"), out_path)
526 error << string_compose (_("Could not open session template %1 for reading"), in_path)
533 /* set initial start + end point */
535 _state_of_the_state = Clean;
537 /* set up Master Out and Control Out if necessary */
542 ChanCount count(DataType::AUDIO, bus_profile->master_out_channels);
544 if (bus_profile->master_out_channels) {
545 boost::shared_ptr<Route> r (new Route (*this, _("Master"), Route::MasterOut, DataType::AUDIO));
549 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
550 // boost_debug_shared_ptr_mark_interesting (r.get(), "Route");
553 Glib::Threads::Mutex::Lock lm (AudioEngine::instance()->process_lock ());
554 r->input()->ensure_io (count, false, this);
555 r->output()->ensure_io (count, false, this);
561 /* prohibit auto-connect to master, because there isn't one */
562 bus_profile->output_ac = AutoConnectOption (bus_profile->output_ac & ~AutoConnectMaster);
566 add_routes (rl, false, false, false);
569 /* this allows the user to override settings with an environment variable.
572 if (no_auto_connect()) {
573 bus_profile->input_ac = AutoConnectOption (0);
574 bus_profile->output_ac = AutoConnectOption (0);
577 Config->set_input_auto_connect (bus_profile->input_ac);
578 Config->set_output_auto_connect (bus_profile->output_ac);
581 if (Config->get_use_monitor_bus() && bus_profile) {
582 add_monitor_section ();
589 Session::maybe_write_autosave()
591 if (dirty() && record_status() != Recording) {
592 save_state("", true);
597 Session::remove_pending_capture_state ()
599 std::string pending_state_file_path(_session_dir->root_path());
601 pending_state_file_path = Glib::build_filename (pending_state_file_path, legalize_for_path (_current_snapshot_name) + pending_suffix);
603 if (!Glib::file_test (pending_state_file_path, Glib::FILE_TEST_EXISTS)) return;
605 if (g_remove (pending_state_file_path.c_str()) != 0) {
606 error << string_compose(_("Could not remove pending capture state at path \"%1\" (%2)"),
607 pending_state_file_path, g_strerror (errno)) << endmsg;
611 /** Rename a state file.
612 * @param old_name Old snapshot name.
613 * @param new_name New snapshot name.
616 Session::rename_state (string old_name, string new_name)
618 if (old_name == _current_snapshot_name || old_name == _name) {
619 /* refuse to rename the current snapshot or the "main" one */
623 const string old_xml_filename = legalize_for_path (old_name) + statefile_suffix;
624 const string new_xml_filename = legalize_for_path (new_name) + statefile_suffix;
626 const std::string old_xml_path(Glib::build_filename (_session_dir->root_path(), old_xml_filename));
627 const std::string new_xml_path(Glib::build_filename (_session_dir->root_path(), new_xml_filename));
629 if (::g_rename (old_xml_path.c_str(), new_xml_path.c_str()) != 0) {
630 error << string_compose(_("could not rename snapshot %1 to %2 (%3)"),
631 old_name, new_name, g_strerror(errno)) << endmsg;
635 /** Remove a state file.
636 * @param snapshot_name Snapshot name.
639 Session::remove_state (string snapshot_name)
641 if (!_writable || snapshot_name == _current_snapshot_name || snapshot_name == _name) {
642 // refuse to remove the current snapshot or the "main" one
646 std::string xml_path(_session_dir->root_path());
648 xml_path = Glib::build_filename (xml_path, legalize_for_path (snapshot_name) + statefile_suffix);
650 if (!create_backup_file (xml_path)) {
651 // don't remove it if a backup can't be made
652 // create_backup_file will log the error.
657 if (g_remove (xml_path.c_str()) != 0) {
658 error << string_compose(_("Could not remove session file at path \"%1\" (%2)"),
659 xml_path, g_strerror (errno)) << endmsg;
663 /** @param snapshot_name Name to save under, without .ardour / .pending prefix */
665 Session::save_state (string snapshot_name, bool pending, bool switch_to_snapshot)
668 std::string xml_path(_session_dir->root_path());
670 /* prevent concurrent saves from different threads */
672 Glib::Threads::Mutex::Lock lm (save_state_lock);
674 if (!_writable || (_state_of_the_state & CannotSave)) {
678 if (g_atomic_int_get(&_suspend_save)) {
682 _save_queued = false;
684 if (!_engine.connected ()) {
685 error << string_compose (_("the %1 audio engine is not connected and state saving would lose all I/O connections. Session not saved"),
691 /* tell sources we're saving first, in case they write out to a new file
692 * which should be saved with the state rather than the old one */
693 for (SourceMap::const_iterator i = sources.begin(); i != sources.end(); ++i) {
695 i->second->session_saved();
696 } catch (Evoral::SMF::FileError& e) {
697 error << string_compose ("Could not write to MIDI file %1; MIDI data not saved.", e.file_name ()) << endmsg;
701 SaveSession (); /* EMIT SIGNAL */
703 tree.set_root (&get_state());
705 if (snapshot_name.empty()) {
706 snapshot_name = _current_snapshot_name;
707 } else if (switch_to_snapshot) {
708 _current_snapshot_name = snapshot_name;
713 /* proper save: use statefile_suffix (.ardour in English) */
715 xml_path = Glib::build_filename (xml_path, legalize_for_path (snapshot_name) + statefile_suffix);
717 /* make a backup copy of the old file */
719 if (Glib::file_test (xml_path, Glib::FILE_TEST_EXISTS) && !create_backup_file (xml_path)) {
720 // create_backup_file will log the error
726 /* pending save: use pending_suffix (.pending in English) */
727 xml_path = Glib::build_filename (xml_path, legalize_for_path (snapshot_name) + pending_suffix);
730 std::string tmp_path(_session_dir->root_path());
731 tmp_path = Glib::build_filename (tmp_path, legalize_for_path (snapshot_name) + temp_suffix);
733 // cerr << "actually writing state to " << xml_path << endl;
735 if (!tree.write (tmp_path)) {
736 error << string_compose (_("state could not be saved to %1"), tmp_path) << endmsg;
737 if (g_remove (tmp_path.c_str()) != 0) {
738 error << string_compose(_("Could not remove temporary session file at path \"%1\" (%2)"),
739 tmp_path, g_strerror (errno)) << endmsg;
745 if (::g_rename (tmp_path.c_str(), xml_path.c_str()) != 0) {
746 error << string_compose (_("could not rename temporary session file %1 to %2 (%3)"),
747 tmp_path, xml_path, g_strerror(errno)) << endmsg;
748 if (g_remove (tmp_path.c_str()) != 0) {
749 error << string_compose(_("Could not remove temporary session file at path \"%1\" (%2)"),
750 tmp_path, g_strerror (errno)) << endmsg;
758 save_history (snapshot_name);
760 bool was_dirty = dirty();
762 _state_of_the_state = StateOfTheState (_state_of_the_state & ~Dirty);
765 DirtyChanged (); /* EMIT SIGNAL */
768 StateSaved (snapshot_name); /* EMIT SIGNAL */
775 Session::restore_state (string snapshot_name)
777 if (load_state (snapshot_name) == 0) {
778 set_state (*state_tree->root(), Stateful::loading_state_version);
785 Session::load_state (string snapshot_name)
790 state_was_pending = false;
792 /* check for leftover pending state from a crashed capture attempt */
794 std::string xmlpath(_session_dir->root_path());
795 xmlpath = Glib::build_filename (xmlpath, legalize_for_path (snapshot_name) + pending_suffix);
797 if (Glib::file_test (xmlpath, Glib::FILE_TEST_EXISTS)) {
799 /* there is pending state from a crashed capture attempt */
801 boost::optional<int> r = AskAboutPendingState();
802 if (r.get_value_or (1)) {
803 state_was_pending = true;
807 if (!state_was_pending) {
808 xmlpath = Glib::build_filename (_session_dir->root_path(), snapshot_name);
811 if (!Glib::file_test (xmlpath, Glib::FILE_TEST_EXISTS)) {
812 xmlpath = Glib::build_filename (_session_dir->root_path(), legalize_for_path (snapshot_name) + statefile_suffix);
813 if (!Glib::file_test (xmlpath, Glib::FILE_TEST_EXISTS)) {
814 error << string_compose(_("%1: session file \"%2\" doesn't exist!"), _name, xmlpath) << endmsg;
819 state_tree = new XMLTree;
823 _writable = exists_and_writable (xmlpath) && exists_and_writable(Glib::path_get_dirname(xmlpath));
825 if (!state_tree->read (xmlpath)) {
826 error << string_compose(_("Could not understand session file %1"), xmlpath) << endmsg;
832 XMLNode& root (*state_tree->root());
834 if (root.name() != X_("Session")) {
835 error << string_compose (_("Session file %1 is not a session"), xmlpath) << endmsg;
841 const XMLProperty* prop;
843 if ((prop = root.property ("version")) == 0) {
844 /* no version implies very old version of Ardour */
845 Stateful::loading_state_version = 1000;
847 if (prop->value().find ('.') != string::npos) {
848 /* old school version format */
849 if (prop->value()[0] == '2') {
850 Stateful::loading_state_version = 2000;
852 Stateful::loading_state_version = 3000;
855 Stateful::loading_state_version = atoi (prop->value());
859 if (Stateful::loading_state_version < CURRENT_SESSION_FILE_VERSION && _writable) {
861 std::string backup_path(_session_dir->root_path());
862 std::string backup_filename = string_compose ("%1-%2%3", legalize_for_path (snapshot_name), Stateful::loading_state_version, statefile_suffix);
863 backup_path = Glib::build_filename (backup_path, backup_filename);
865 // only create a backup for a given statefile version once
867 if (!Glib::file_test (backup_path, Glib::FILE_TEST_EXISTS)) {
869 VersionMismatch (xmlpath, backup_path);
871 if (!copy_file (xmlpath, backup_path)) {;
881 Session::load_options (const XMLNode& node)
883 LocaleGuard lg (X_("POSIX"));
884 config.set_variables (node);
889 Session::save_default_options ()
891 return config.save_state();
901 Session::get_template()
903 /* if we don't disable rec-enable, diskstreams
904 will believe they need to store their capture
905 sources in their state node.
908 disable_record (false);
914 Session::state (bool full_state)
916 XMLNode* node = new XMLNode("Session");
920 snprintf(buf, sizeof(buf), "%d", CURRENT_SESSION_FILE_VERSION);
921 node->add_property("version", buf);
923 /* store configuration settings */
927 node->add_property ("name", _name);
928 snprintf (buf, sizeof (buf), "%" PRId64, _nominal_frame_rate);
929 node->add_property ("sample-rate", buf);
931 if (session_dirs.size() > 1) {
935 vector<space_and_path>::iterator i = session_dirs.begin();
936 vector<space_and_path>::iterator next;
938 ++i; /* skip the first one */
942 while (i != session_dirs.end()) {
946 if (next != session_dirs.end()) {
947 p += G_SEARCHPATH_SEPARATOR;
956 child = node->add_child ("Path");
957 child->add_content (p);
961 /* save the ID counter */
963 snprintf (buf, sizeof (buf), "%" PRIu64, ID::counter());
964 node->add_property ("id-counter", buf);
966 /* save the event ID counter */
968 snprintf (buf, sizeof (buf), "%d", Evoral::event_id_counter());
969 node->add_property ("event-counter", buf);
971 /* various options */
973 list<XMLNode*> midi_port_nodes = _midi_ports->get_midi_port_states();
974 if (!midi_port_nodes.empty()) {
975 XMLNode* midi_port_stuff = new XMLNode ("MIDIPorts");
976 for (list<XMLNode*>::const_iterator n = midi_port_nodes.begin(); n != midi_port_nodes.end(); ++n) {
977 midi_port_stuff->add_child_nocopy (**n);
979 node->add_child_nocopy (*midi_port_stuff);
982 node->add_child_nocopy (config.get_variables ());
984 node->add_child_nocopy (ARDOUR::SessionMetadata::Metadata()->get_state());
986 child = node->add_child ("Sources");
989 Glib::Threads::Mutex::Lock sl (source_lock);
991 for (SourceMap::iterator siter = sources.begin(); siter != sources.end(); ++siter) {
993 /* Don't save information about non-file Sources, or
994 * about non-destructive file sources that are empty
995 * and unused by any regions.
998 boost::shared_ptr<FileSource> fs;
1000 if ((fs = boost::dynamic_pointer_cast<FileSource> (siter->second)) != 0) {
1002 if (!fs->destructive()) {
1003 if (fs->empty() && !fs->used()) {
1008 child->add_child_nocopy (siter->second->get_state());
1013 child = node->add_child ("Regions");
1016 Glib::Threads::Mutex::Lock rl (region_lock);
1017 const RegionFactory::RegionMap& region_map (RegionFactory::all_regions());
1018 for (RegionFactory::RegionMap::const_iterator i = region_map.begin(); i != region_map.end(); ++i) {
1019 boost::shared_ptr<Region> r = i->second;
1020 /* only store regions not attached to playlists */
1021 if (r->playlist() == 0) {
1022 if (boost::dynamic_pointer_cast<AudioRegion>(r)) {
1023 child->add_child_nocopy ((boost::dynamic_pointer_cast<AudioRegion>(r))->get_basic_state ());
1025 child->add_child_nocopy (r->get_state ());
1030 RegionFactory::CompoundAssociations& cassocs (RegionFactory::compound_associations());
1032 if (!cassocs.empty()) {
1033 XMLNode* ca = node->add_child (X_("CompoundAssociations"));
1035 for (RegionFactory::CompoundAssociations::iterator i = cassocs.begin(); i != cassocs.end(); ++i) {
1037 XMLNode* can = new XMLNode (X_("CompoundAssociation"));
1038 i->first->id().print (buf, sizeof (buf));
1039 can->add_property (X_("copy"), buf);
1040 i->second->id().print (buf, sizeof (buf));
1041 can->add_property (X_("original"), buf);
1042 ca->add_child_nocopy (*can);
1048 node->add_child_nocopy (_locations->get_state());
1050 // for a template, just create a new Locations, populate it
1051 // with the default start and end, and get the state for that.
1052 Locations loc (*this);
1053 Location* range = new Location (*this, 0, 0, _("session"), Location::IsSessionRange);
1054 range->set (max_framepos, 0);
1056 node->add_child_nocopy (loc.get_state());
1059 child = node->add_child ("Bundles");
1061 boost::shared_ptr<BundleList> bundles = _bundles.reader ();
1062 for (BundleList::iterator i = bundles->begin(); i != bundles->end(); ++i) {
1063 boost::shared_ptr<UserBundle> b = boost::dynamic_pointer_cast<UserBundle> (*i);
1065 child->add_child_nocopy (b->get_state());
1070 child = node->add_child ("Routes");
1072 boost::shared_ptr<RouteList> r = routes.reader ();
1074 RoutePublicOrderSorter cmp;
1075 RouteList public_order (*r);
1076 public_order.sort (cmp);
1078 /* the sort should have put control outs first */
1081 assert (_monitor_out == public_order.front());
1084 for (RouteList::iterator i = public_order.begin(); i != public_order.end(); ++i) {
1085 if (!(*i)->is_auditioner()) {
1087 child->add_child_nocopy ((*i)->get_state());
1089 child->add_child_nocopy ((*i)->get_template());
1095 playlists->add_state (node, full_state);
1097 child = node->add_child ("RouteGroups");
1098 for (list<RouteGroup *>::iterator i = _route_groups.begin(); i != _route_groups.end(); ++i) {
1099 child->add_child_nocopy ((*i)->get_state());
1103 XMLNode* gain_child = node->add_child ("Click");
1104 gain_child->add_child_nocopy (_click_io->state (full_state));
1105 gain_child->add_child_nocopy (_click_gain->state (full_state));
1109 XMLNode* ltc_input_child = node->add_child ("LTC-In");
1110 ltc_input_child->add_child_nocopy (_ltc_input->state (full_state));
1114 XMLNode* ltc_output_child = node->add_child ("LTC-Out");
1115 ltc_output_child->add_child_nocopy (_ltc_output->state (full_state));
1118 node->add_child_nocopy (_speakers->get_state());
1119 node->add_child_nocopy (_tempo_map->get_state());
1120 node->add_child_nocopy (get_control_protocol_state());
1123 node->add_child_copy (*_extra_xml);
1130 Session::get_control_protocol_state ()
1132 ControlProtocolManager& cpm (ControlProtocolManager::instance());
1133 return cpm.get_state();
1137 Session::set_state (const XMLNode& node, int version)
1141 const XMLProperty* prop;
1144 _state_of_the_state = StateOfTheState (_state_of_the_state|CannotSave);
1146 if (node.name() != X_("Session")) {
1147 fatal << _("programming error: Session: incorrect XML node sent to set_state()") << endmsg;
1151 if ((prop = node.property ("name")) != 0) {
1152 _name = prop->value ();
1155 if ((prop = node.property (X_("sample-rate"))) != 0) {
1157 _nominal_frame_rate = atoi (prop->value());
1159 if (_nominal_frame_rate != _current_frame_rate) {
1160 boost::optional<int> r = AskAboutSampleRateMismatch (_nominal_frame_rate, _current_frame_rate);
1161 if (r.get_value_or (0)) {
1167 setup_raid_path(_session_dir->root_path());
1169 if ((prop = node.property (X_("id-counter"))) != 0) {
1171 sscanf (prop->value().c_str(), "%" PRIu64, &x);
1172 ID::init_counter (x);
1174 /* old sessions used a timebased counter, so fake
1175 the startup ID counter based on a standard
1180 ID::init_counter (now);
1183 if ((prop = node.property (X_("event-counter"))) != 0) {
1184 Evoral::init_event_id_counter (atoi (prop->value()));
1188 if ((child = find_named_node (node, "MIDIPorts")) != 0) {
1189 _midi_ports->set_midi_port_states (child->children());
1192 IO::disable_connecting ();
1194 Stateful::save_extra_xml (node);
1196 if (((child = find_named_node (node, "Options")) != 0)) { /* old style */
1197 load_options (*child);
1198 } else if ((child = find_named_node (node, "Config")) != 0) { /* new style */
1199 load_options (*child);
1201 error << _("Session: XML state has no options section") << endmsg;
1204 if (version >= 3000) {
1205 if ((child = find_named_node (node, "Metadata")) == 0) {
1206 warning << _("Session: XML state has no metadata section") << endmsg;
1207 } else if ( ARDOUR::SessionMetadata::Metadata()->set_state (*child, version) ) {
1212 if ((child = find_named_node (node, X_("Speakers"))) != 0) {
1213 _speakers->set_state (*child, version);
1216 if ((child = find_named_node (node, "Sources")) == 0) {
1217 error << _("Session: XML state has no sources section") << endmsg;
1219 } else if (load_sources (*child)) {
1223 if ((child = find_named_node (node, "TempoMap")) == 0) {
1224 error << _("Session: XML state has no Tempo Map section") << endmsg;
1226 } else if (_tempo_map->set_state (*child, version)) {
1230 if ((child = find_named_node (node, "Locations")) == 0) {
1231 error << _("Session: XML state has no locations section") << endmsg;
1233 } else if (_locations->set_state (*child, version)) {
1237 locations_changed ();
1239 if (_session_range_location) {
1240 AudioFileSource::set_header_position_offset (_session_range_location->start());
1243 if ((child = find_named_node (node, "Regions")) == 0) {
1244 error << _("Session: XML state has no Regions section") << endmsg;
1246 } else if (load_regions (*child)) {
1250 if ((child = find_named_node (node, "Playlists")) == 0) {
1251 error << _("Session: XML state has no playlists section") << endmsg;
1253 } else if (playlists->load (*this, *child)) {
1257 if ((child = find_named_node (node, "UnusedPlaylists")) == 0) {
1259 } else if (playlists->load_unused (*this, *child)) {
1263 if ((child = find_named_node (node, "CompoundAssociations")) != 0) {
1264 if (load_compounds (*child)) {
1269 if (version >= 3000) {
1270 if ((child = find_named_node (node, "Bundles")) == 0) {
1271 warning << _("Session: XML state has no bundles section") << endmsg;
1274 /* We can't load Bundles yet as they need to be able
1275 to convert from port names to Port objects, which can't happen until
1277 _bundle_xml_node = new XMLNode (*child);
1281 if (version < 3000) {
1282 if ((child = find_named_node (node, X_("DiskStreams"))) == 0) {
1283 error << _("Session: XML state has no diskstreams section") << endmsg;
1285 } else if (load_diskstreams_2X (*child, version)) {
1290 if ((child = find_named_node (node, "Routes")) == 0) {
1291 error << _("Session: XML state has no routes section") << endmsg;
1293 } else if (load_routes (*child, version)) {
1297 /* our diskstreams list is no longer needed as they are now all owned by their Route */
1298 _diskstreams_2X.clear ();
1300 if (version >= 3000) {
1302 if ((child = find_named_node (node, "RouteGroups")) == 0) {
1303 error << _("Session: XML state has no route groups section") << endmsg;
1305 } else if (load_route_groups (*child, version)) {
1309 } else if (version < 3000) {
1311 if ((child = find_named_node (node, "EditGroups")) == 0) {
1312 error << _("Session: XML state has no edit groups section") << endmsg;
1314 } else if (load_route_groups (*child, version)) {
1318 if ((child = find_named_node (node, "MixGroups")) == 0) {
1319 error << _("Session: XML state has no mix groups section") << endmsg;
1321 } else if (load_route_groups (*child, version)) {
1326 if ((child = find_named_node (node, "Click")) == 0) {
1327 warning << _("Session: XML state has no click section") << endmsg;
1328 } else if (_click_io) {
1329 setup_click_state (&node);
1332 if ((child = find_named_node (node, ControlProtocolManager::state_node_name)) != 0) {
1333 ControlProtocolManager::instance().set_state (*child, version);
1336 update_have_rec_enabled_track ();
1338 /* here beginneth the second phase ... */
1340 StateReady (); /* EMIT SIGNAL */
1353 Session::load_routes (const XMLNode& node, int version)
1356 XMLNodeConstIterator niter;
1357 RouteList new_routes;
1359 nlist = node.children();
1363 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1365 boost::shared_ptr<Route> route;
1366 if (version < 3000) {
1367 route = XMLRouteFactory_2X (**niter, version);
1369 route = XMLRouteFactory (**niter, version);
1373 error << _("Session: cannot create Route from XML description.") << endmsg;
1377 BootMessage (string_compose (_("Loaded track/bus %1"), route->name()));
1379 new_routes.push_back (route);
1382 add_routes (new_routes, false, false, false);
1384 BootMessage (_("Finished loading tracks/busses."));
1389 boost::shared_ptr<Route>
1390 Session::XMLRouteFactory (const XMLNode& node, int version)
1392 boost::shared_ptr<Route> ret;
1394 if (node.name() != "Route") {
1398 XMLNode* ds_child = find_named_node (node, X_("Diskstream"));
1400 DataType type = DataType::AUDIO;
1401 const XMLProperty* prop = node.property("default-type");
1404 type = DataType (prop->value());
1407 assert (type != DataType::NIL);
1411 boost::shared_ptr<Track> track;
1413 if (type == DataType::AUDIO) {
1414 track.reset (new AudioTrack (*this, X_("toBeResetFroXML")));
1416 track.reset (new MidiTrack (*this, X_("toBeResetFroXML")));
1419 if (track->init()) {
1423 if (track->set_state (node, version)) {
1427 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
1428 // boost_debug_shared_ptr_mark_interesting (track.get(), "Track");
1433 enum Route::Flag flags = Route::Flag(0);
1434 const XMLProperty* prop = node.property("flags");
1436 flags = Route::Flag (string_2_enum (prop->value(), flags));
1439 boost::shared_ptr<Route> r (new Route (*this, X_("toBeResetFroXML"), flags));
1441 if (r->init () == 0 && r->set_state (node, version) == 0) {
1442 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
1443 // boost_debug_shared_ptr_mark_interesting (r.get(), "Route");
1452 boost::shared_ptr<Route>
1453 Session::XMLRouteFactory_2X (const XMLNode& node, int version)
1455 boost::shared_ptr<Route> ret;
1457 if (node.name() != "Route") {
1461 XMLProperty const * ds_prop = node.property (X_("diskstream-id"));
1463 ds_prop = node.property (X_("diskstream"));
1466 DataType type = DataType::AUDIO;
1467 const XMLProperty* prop = node.property("default-type");
1470 type = DataType (prop->value());
1473 assert (type != DataType::NIL);
1477 list<boost::shared_ptr<Diskstream> >::iterator i = _diskstreams_2X.begin ();
1478 while (i != _diskstreams_2X.end() && (*i)->id() != ds_prop->value()) {
1482 if (i == _diskstreams_2X.end()) {
1483 error << _("Could not find diskstream for route") << endmsg;
1484 return boost::shared_ptr<Route> ();
1487 boost::shared_ptr<Track> track;
1489 if (type == DataType::AUDIO) {
1490 track.reset (new AudioTrack (*this, X_("toBeResetFroXML")));
1492 track.reset (new MidiTrack (*this, X_("toBeResetFroXML")));
1495 if (track->init()) {
1499 if (track->set_state (node, version)) {
1503 track->set_diskstream (*i);
1505 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
1506 // boost_debug_shared_ptr_mark_interesting (track.get(), "Track");
1511 enum Route::Flag flags = Route::Flag(0);
1512 const XMLProperty* prop = node.property("flags");
1514 flags = Route::Flag (string_2_enum (prop->value(), flags));
1517 boost::shared_ptr<Route> r (new Route (*this, X_("toBeResetFroXML"), flags));
1519 if (r->init () == 0 && r->set_state (node, version) == 0) {
1520 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
1521 // boost_debug_shared_ptr_mark_interesting (r.get(), "Route");
1531 Session::load_regions (const XMLNode& node)
1534 XMLNodeConstIterator niter;
1535 boost::shared_ptr<Region> region;
1537 nlist = node.children();
1541 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1542 if ((region = XMLRegionFactory (**niter, false)) == 0) {
1543 error << _("Session: cannot create Region from XML description.");
1544 const XMLProperty *name = (**niter).property("name");
1547 error << " " << string_compose (_("Can not load state for region '%1'"), name->value());
1558 Session::load_compounds (const XMLNode& node)
1560 XMLNodeList calist = node.children();
1561 XMLNodeConstIterator caiter;
1562 XMLProperty *caprop;
1564 for (caiter = calist.begin(); caiter != calist.end(); ++caiter) {
1565 XMLNode* ca = *caiter;
1569 if ((caprop = ca->property (X_("original"))) == 0) {
1572 orig_id = caprop->value();
1574 if ((caprop = ca->property (X_("copy"))) == 0) {
1577 copy_id = caprop->value();
1579 boost::shared_ptr<Region> orig = RegionFactory::region_by_id (orig_id);
1580 boost::shared_ptr<Region> copy = RegionFactory::region_by_id (copy_id);
1582 if (!orig || !copy) {
1583 warning << string_compose (_("Regions in compound description not found (ID's %1 and %2): ignored"),
1589 RegionFactory::add_compound_association (orig, copy);
1596 Session::load_nested_sources (const XMLNode& node)
1599 XMLNodeConstIterator niter;
1601 nlist = node.children();
1603 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1604 if ((*niter)->name() == "Source") {
1606 /* it may already exist, so don't recreate it unnecessarily
1609 XMLProperty* prop = (*niter)->property (X_("id"));
1611 error << _("Nested source has no ID info in session file! (ignored)") << endmsg;
1615 ID source_id (prop->value());
1617 if (!source_by_id (source_id)) {
1620 SourceFactory::create (*this, **niter, true);
1622 catch (failed_constructor& err) {
1623 error << string_compose (_("Cannot reconstruct nested source for region %1"), name()) << endmsg;
1630 boost::shared_ptr<Region>
1631 Session::XMLRegionFactory (const XMLNode& node, bool full)
1633 const XMLProperty* type = node.property("type");
1637 const XMLNodeList& nlist = node.children();
1639 for (XMLNodeConstIterator niter = nlist.begin(); niter != nlist.end(); ++niter) {
1640 XMLNode *child = (*niter);
1641 if (child->name() == "NestedSource") {
1642 load_nested_sources (*child);
1646 if (!type || type->value() == "audio") {
1647 return boost::shared_ptr<Region>(XMLAudioRegionFactory (node, full));
1648 } else if (type->value() == "midi") {
1649 return boost::shared_ptr<Region>(XMLMidiRegionFactory (node, full));
1652 } catch (failed_constructor& err) {
1653 return boost::shared_ptr<Region> ();
1656 return boost::shared_ptr<Region> ();
1659 boost::shared_ptr<AudioRegion>
1660 Session::XMLAudioRegionFactory (const XMLNode& node, bool /*full*/)
1662 const XMLProperty* prop;
1663 boost::shared_ptr<Source> source;
1664 boost::shared_ptr<AudioSource> as;
1666 SourceList master_sources;
1667 uint32_t nchans = 1;
1670 if (node.name() != X_("Region")) {
1671 return boost::shared_ptr<AudioRegion>();
1674 if ((prop = node.property (X_("channels"))) != 0) {
1675 nchans = atoi (prop->value().c_str());
1678 if ((prop = node.property ("name")) == 0) {
1679 cerr << "no name for this region\n";
1683 if ((prop = node.property (X_("source-0"))) == 0) {
1684 if ((prop = node.property ("source")) == 0) {
1685 error << _("Session: XMLNode describing a AudioRegion is incomplete (no source)") << endmsg;
1686 return boost::shared_ptr<AudioRegion>();
1690 PBD::ID s_id (prop->value());
1692 if ((source = source_by_id (s_id)) == 0) {
1693 error << string_compose(_("Session: XMLNode describing a AudioRegion references an unknown source id =%1"), s_id) << endmsg;
1694 return boost::shared_ptr<AudioRegion>();
1697 as = boost::dynamic_pointer_cast<AudioSource>(source);
1699 error << string_compose(_("Session: XMLNode describing a AudioRegion references a non-audio source id =%1"), s_id) << endmsg;
1700 return boost::shared_ptr<AudioRegion>();
1703 sources.push_back (as);
1705 /* pickup other channels */
1707 for (uint32_t n=1; n < nchans; ++n) {
1708 snprintf (buf, sizeof(buf), X_("source-%d"), n);
1709 if ((prop = node.property (buf)) != 0) {
1711 PBD::ID id2 (prop->value());
1713 if ((source = source_by_id (id2)) == 0) {
1714 error << string_compose(_("Session: XMLNode describing a AudioRegion references an unknown source id =%1"), id2) << endmsg;
1715 return boost::shared_ptr<AudioRegion>();
1718 as = boost::dynamic_pointer_cast<AudioSource>(source);
1720 error << string_compose(_("Session: XMLNode describing a AudioRegion references a non-audio source id =%1"), id2) << endmsg;
1721 return boost::shared_ptr<AudioRegion>();
1723 sources.push_back (as);
1727 for (uint32_t n = 0; n < nchans; ++n) {
1728 snprintf (buf, sizeof(buf), X_("master-source-%d"), n);
1729 if ((prop = node.property (buf)) != 0) {
1731 PBD::ID id2 (prop->value());
1733 if ((source = source_by_id (id2)) == 0) {
1734 error << string_compose(_("Session: XMLNode describing a AudioRegion references an unknown source id =%1"), id2) << endmsg;
1735 return boost::shared_ptr<AudioRegion>();
1738 as = boost::dynamic_pointer_cast<AudioSource>(source);
1740 error << string_compose(_("Session: XMLNode describing a AudioRegion references a non-audio source id =%1"), id2) << endmsg;
1741 return boost::shared_ptr<AudioRegion>();
1743 master_sources.push_back (as);
1748 boost::shared_ptr<AudioRegion> region (boost::dynamic_pointer_cast<AudioRegion> (RegionFactory::create (sources, node)));
1750 /* a final detail: this is the one and only place that we know how long missing files are */
1752 if (region->whole_file()) {
1753 for (SourceList::iterator sx = sources.begin(); sx != sources.end(); ++sx) {
1754 boost::shared_ptr<SilentFileSource> sfp = boost::dynamic_pointer_cast<SilentFileSource> (*sx);
1756 sfp->set_length (region->length());
1761 if (!master_sources.empty()) {
1762 if (master_sources.size() != nchans) {
1763 error << _("Session: XMLNode describing an AudioRegion is missing some master sources; ignored") << endmsg;
1765 region->set_master_sources (master_sources);
1773 catch (failed_constructor& err) {
1774 return boost::shared_ptr<AudioRegion>();
1778 boost::shared_ptr<MidiRegion>
1779 Session::XMLMidiRegionFactory (const XMLNode& node, bool /*full*/)
1781 const XMLProperty* prop;
1782 boost::shared_ptr<Source> source;
1783 boost::shared_ptr<MidiSource> ms;
1786 if (node.name() != X_("Region")) {
1787 return boost::shared_ptr<MidiRegion>();
1790 if ((prop = node.property ("name")) == 0) {
1791 cerr << "no name for this region\n";
1795 if ((prop = node.property (X_("source-0"))) == 0) {
1796 if ((prop = node.property ("source")) == 0) {
1797 error << _("Session: XMLNode describing a MidiRegion is incomplete (no source)") << endmsg;
1798 return boost::shared_ptr<MidiRegion>();
1802 PBD::ID s_id (prop->value());
1804 if ((source = source_by_id (s_id)) == 0) {
1805 error << string_compose(_("Session: XMLNode describing a MidiRegion references an unknown source id =%1"), s_id) << endmsg;
1806 return boost::shared_ptr<MidiRegion>();
1809 ms = boost::dynamic_pointer_cast<MidiSource>(source);
1811 error << string_compose(_("Session: XMLNode describing a MidiRegion references a non-midi source id =%1"), s_id) << endmsg;
1812 return boost::shared_ptr<MidiRegion>();
1815 sources.push_back (ms);
1818 boost::shared_ptr<MidiRegion> region (boost::dynamic_pointer_cast<MidiRegion> (RegionFactory::create (sources, node)));
1819 /* a final detail: this is the one and only place that we know how long missing files are */
1821 if (region->whole_file()) {
1822 for (SourceList::iterator sx = sources.begin(); sx != sources.end(); ++sx) {
1823 boost::shared_ptr<SilentFileSource> sfp = boost::dynamic_pointer_cast<SilentFileSource> (*sx);
1825 sfp->set_length (region->length());
1833 catch (failed_constructor& err) {
1834 return boost::shared_ptr<MidiRegion>();
1839 Session::get_sources_as_xml ()
1842 XMLNode* node = new XMLNode (X_("Sources"));
1843 Glib::Threads::Mutex::Lock lm (source_lock);
1845 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ++i) {
1846 node->add_child_nocopy (i->second->get_state());
1853 Session::load_sources (const XMLNode& node)
1856 XMLNodeConstIterator niter;
1857 boost::shared_ptr<Source> source; /* don't need this but it stops some
1858 * versions of gcc complaining about
1859 * discarded return values.
1862 nlist = node.children();
1866 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1869 if ((source = XMLSourceFactory (**niter)) == 0) {
1870 error << _("Session: cannot create Source from XML description.") << endmsg;
1873 } catch (MissingSource& err) {
1877 if (err.type == DataType::MIDI && Glib::path_is_absolute (err.path)) {
1878 error << string_compose (_("A external MIDI file is missing. %1 cannot currently recover from missing external MIDI files"),
1879 PROGRAM_NAME) << endmsg;
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;
1912 case DataType::AUDIO:
1913 source = SourceFactory::createSilent (*this, **niter, max_framecnt, _current_frame_rate);
1916 case DataType::MIDI:
1917 /* The MIDI file is actually missing so
1918 * just create a new one in the same
1919 * location. Do not announce its
1923 if (!Glib::path_is_absolute (err.path)) {
1924 fullpath = Glib::build_filename (source_search_path (DataType::MIDI).front(), err.path);
1926 /* this should be an unrecoverable error: we would be creating a MIDI file outside
1931 /* Note that we do not announce the source just yet - we need to reset its ID before we do that */
1932 source = SourceFactory::createWritable (DataType::MIDI, *this, fullpath, false, _current_frame_rate, false, false);
1933 /* reset ID to match the missing one */
1934 source->set_id (**niter);
1935 /* Now we can announce it */
1936 SourceFactory::SourceCreated (source);
1947 boost::shared_ptr<Source>
1948 Session::XMLSourceFactory (const XMLNode& node)
1950 if (node.name() != "Source") {
1951 return boost::shared_ptr<Source>();
1955 /* note: do peak building in another thread when loading session state */
1956 return SourceFactory::create (*this, node, true);
1959 catch (failed_constructor& err) {
1960 error << string_compose (_("Found a sound file that cannot be used by %1. Talk to the programmers."), PROGRAM_NAME) << endmsg;
1961 return boost::shared_ptr<Source>();
1966 Session::save_template (string template_name)
1970 if (_state_of_the_state & CannotSave) {
1974 std::string user_template_dir(user_template_directory());
1976 if (g_mkdir_with_parents (user_template_dir.c_str(), 0755) != 0) {
1977 error << string_compose(_("Could not create templates directory \"%1\" (%2)"),
1978 user_template_dir, g_strerror (errno)) << endmsg;
1982 tree.set_root (&get_template());
1984 std::string template_dir_path(user_template_dir);
1986 /* directory to put the template in */
1987 template_dir_path = Glib::build_filename (template_dir_path, template_name);
1989 if (Glib::file_test (template_dir_path, Glib::FILE_TEST_EXISTS)) {
1990 warning << string_compose(_("Template \"%1\" already exists - new version not created"),
1991 template_dir_path) << endmsg;
1995 if (g_mkdir_with_parents (template_dir_path.c_str(), 0755) != 0) {
1996 error << string_compose(_("Could not create directory for Session template\"%1\" (%2)"),
1997 template_dir_path, g_strerror (errno)) << endmsg;
2002 std::string template_file_path(template_dir_path);
2003 template_file_path = Glib::build_filename (template_file_path, template_name + template_suffix);
2005 if (!tree.write (template_file_path)) {
2006 error << _("template not saved") << endmsg;
2010 /* copy plugin state directory */
2012 std::string template_plugin_state_path(template_dir_path);
2013 template_plugin_state_path = Glib::build_filename (template_plugin_state_path, X_("plugins"));
2015 if (g_mkdir_with_parents (template_plugin_state_path.c_str(), 0755) != 0) {
2016 error << string_compose(_("Could not create directory for Session template plugin state\"%1\" (%2)"),
2017 template_plugin_state_path, g_strerror (errno)) << endmsg;
2021 copy_recurse (plugins_dir(), template_plugin_state_path);
2027 Session::refresh_disk_space ()
2029 #if __APPLE__ || (HAVE_SYS_VFS_H && HAVE_SYS_STATVFS_H)
2031 Glib::Threads::Mutex::Lock lm (space_lock);
2033 /* get freespace on every FS that is part of the session path */
2035 _total_free_4k_blocks = 0;
2036 _total_free_4k_blocks_uncertain = false;
2038 for (vector<space_and_path>::iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
2040 struct statfs statfsbuf;
2041 statfs (i->path.c_str(), &statfsbuf);
2043 double const scale = statfsbuf.f_bsize / 4096.0;
2045 /* See if this filesystem is read-only */
2046 struct statvfs statvfsbuf;
2047 statvfs (i->path.c_str(), &statvfsbuf);
2049 /* f_bavail can be 0 if it is undefined for whatever
2050 filesystem we are looking at; Samba shares mounted
2051 via GVFS are an example of this.
2053 if (statfsbuf.f_bavail == 0) {
2054 /* block count unknown */
2056 i->blocks_unknown = true;
2057 } else if (statvfsbuf.f_flag & ST_RDONLY) {
2058 /* read-only filesystem */
2060 i->blocks_unknown = false;
2062 /* read/write filesystem with known space */
2063 i->blocks = (uint32_t) floor (statfsbuf.f_bavail * scale);
2064 i->blocks_unknown = false;
2067 _total_free_4k_blocks += i->blocks;
2068 if (i->blocks_unknown) {
2069 _total_free_4k_blocks_uncertain = true;
2072 #elif defined (COMPILER_MSVC)
2073 vector<string> scanned_volumes;
2074 vector<string>::iterator j;
2075 vector<space_and_path>::iterator i;
2076 DWORD nSectorsPerCluster, nBytesPerSector,
2077 nFreeClusters, nTotalClusters;
2081 _total_free_4k_blocks = 0;
2083 for (i = session_dirs.begin(); i != session_dirs.end(); i++) {
2084 strncpy (disk_drive, (*i).path.c_str(), 3);
2088 volume_found = false;
2089 if (0 != (GetDiskFreeSpace(disk_drive, &nSectorsPerCluster, &nBytesPerSector, &nFreeClusters, &nTotalClusters)))
2091 int64_t nBytesPerCluster = nBytesPerSector * nSectorsPerCluster;
2092 int64_t nFreeBytes = nBytesPerCluster * (int64_t)nFreeClusters;
2093 i->blocks = (uint32_t)(nFreeBytes / 4096);
2095 for (j = scanned_volumes.begin(); j != scanned_volumes.end(); j++) {
2096 if (0 == j->compare(disk_drive)) {
2097 volume_found = true;
2102 if (!volume_found) {
2103 scanned_volumes.push_back(disk_drive);
2104 _total_free_4k_blocks += i->blocks;
2109 if (0 == _total_free_4k_blocks) {
2110 strncpy (disk_drive, path().c_str(), 3);
2113 if (0 != (GetDiskFreeSpace(disk_drive, &nSectorsPerCluster, &nBytesPerSector, &nFreeClusters, &nTotalClusters)))
2115 int64_t nBytesPerCluster = nBytesPerSector * nSectorsPerCluster;
2116 int64_t nFreeBytes = nBytesPerCluster * (int64_t)nFreeClusters;
2117 _total_free_4k_blocks = (uint32_t)(nFreeBytes / 4096);
2124 Session::get_best_session_directory_for_new_audio ()
2126 vector<space_and_path>::iterator i;
2127 string result = _session_dir->root_path();
2129 /* handle common case without system calls */
2131 if (session_dirs.size() == 1) {
2135 /* OK, here's the algorithm we're following here:
2137 We want to select which directory to use for
2138 the next file source to be created. Ideally,
2139 we'd like to use a round-robin process so as to
2140 get maximum performance benefits from splitting
2141 the files across multiple disks.
2143 However, in situations without much diskspace, an
2144 RR approach may end up filling up a filesystem
2145 with new files while others still have space.
2146 Its therefore important to pay some attention to
2147 the freespace in the filesystem holding each
2148 directory as well. However, if we did that by
2149 itself, we'd keep creating new files in the file
2150 system with the most space until it was as full
2151 as all others, thus negating any performance
2152 benefits of this RAID-1 like approach.
2154 So, we use a user-configurable space threshold. If
2155 there are at least 2 filesystems with more than this
2156 much space available, we use RR selection between them.
2157 If not, then we pick the filesystem with the most space.
2159 This gets a good balance between the two
2163 refresh_disk_space ();
2165 int free_enough = 0;
2167 for (i = session_dirs.begin(); i != session_dirs.end(); ++i) {
2168 if ((*i).blocks * 4096 >= Config->get_disk_choice_space_threshold()) {
2173 if (free_enough >= 2) {
2174 /* use RR selection process, ensuring that the one
2178 i = last_rr_session_dir;
2181 if (++i == session_dirs.end()) {
2182 i = session_dirs.begin();
2185 if ((*i).blocks * 4096 >= Config->get_disk_choice_space_threshold()) {
2186 SessionDirectory sdir(i->path);
2187 if (sdir.create ()) {
2189 last_rr_session_dir = i;
2194 } while (i != last_rr_session_dir);
2198 /* pick FS with the most freespace (and that
2199 seems to actually work ...)
2202 vector<space_and_path> sorted;
2203 space_and_path_ascending_cmp cmp;
2205 sorted = session_dirs;
2206 sort (sorted.begin(), sorted.end(), cmp);
2208 for (i = sorted.begin(); i != sorted.end(); ++i) {
2209 SessionDirectory sdir(i->path);
2210 if (sdir.create ()) {
2212 last_rr_session_dir = i;
2222 Session::automation_dir () const
2224 return Glib::build_filename (_path, "automation");
2228 Session::analysis_dir () const
2230 return Glib::build_filename (_path, "analysis");
2234 Session::plugins_dir () const
2236 return Glib::build_filename (_path, "plugins");
2240 Session::externals_dir () const
2242 return Glib::build_filename (_path, "externals");
2246 Session::load_bundles (XMLNode const & node)
2248 XMLNodeList nlist = node.children();
2249 XMLNodeConstIterator niter;
2253 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2254 if ((*niter)->name() == "InputBundle") {
2255 add_bundle (boost::shared_ptr<UserBundle> (new UserBundle (**niter, true)));
2256 } else if ((*niter)->name() == "OutputBundle") {
2257 add_bundle (boost::shared_ptr<UserBundle> (new UserBundle (**niter, false)));
2259 error << string_compose(_("Unknown node \"%1\" found in Bundles list from session file"), (*niter)->name()) << endmsg;
2268 Session::load_route_groups (const XMLNode& node, int version)
2270 XMLNodeList nlist = node.children();
2271 XMLNodeConstIterator niter;
2275 if (version >= 3000) {
2277 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2278 if ((*niter)->name() == "RouteGroup") {
2279 RouteGroup* rg = new RouteGroup (*this, "");
2280 add_route_group (rg);
2281 rg->set_state (**niter, version);
2285 } else if (version < 3000) {
2287 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2288 if ((*niter)->name() == "EditGroup" || (*niter)->name() == "MixGroup") {
2289 RouteGroup* rg = new RouteGroup (*this, "");
2290 add_route_group (rg);
2291 rg->set_state (**niter, version);
2300 state_file_filter (const string &str, void* /*arg*/)
2302 return (str.length() > strlen(statefile_suffix) &&
2303 str.find (statefile_suffix) == (str.length() - strlen (statefile_suffix)));
2307 remove_end(string state)
2309 string statename(state);
2311 string::size_type start,end;
2312 if ((start = statename.find_last_of (G_DIR_SEPARATOR)) != string::npos) {
2313 statename = statename.substr (start+1);
2316 if ((end = statename.rfind(statefile_suffix)) == string::npos) {
2317 end = statename.length();
2320 return string(statename.substr (0, end));
2324 Session::possible_states (string path)
2326 vector<string> states;
2327 find_files_matching_filter (states, path, state_file_filter, 0, false, false);
2329 transform(states.begin(), states.end(), states.begin(), remove_end);
2331 sort (states.begin(), states.end());
2337 Session::possible_states () const
2339 return possible_states(_path);
2343 Session::add_route_group (RouteGroup* g)
2345 _route_groups.push_back (g);
2346 route_group_added (g); /* EMIT SIGNAL */
2348 g->RouteAdded.connect_same_thread (*this, boost::bind (&Session::route_added_to_route_group, this, _1, _2));
2349 g->RouteRemoved.connect_same_thread (*this, boost::bind (&Session::route_removed_from_route_group, this, _1, _2));
2350 g->PropertyChanged.connect_same_thread (*this, boost::bind (&Session::route_group_property_changed, this, g));
2356 Session::remove_route_group (RouteGroup& rg)
2358 list<RouteGroup*>::iterator i;
2360 if ((i = find (_route_groups.begin(), _route_groups.end(), &rg)) != _route_groups.end()) {
2361 _route_groups.erase (i);
2364 route_group_removed (); /* EMIT SIGNAL */
2368 /** Set a new order for our route groups, without adding or removing any.
2369 * @param groups Route group list in the new order.
2372 Session::reorder_route_groups (list<RouteGroup*> groups)
2374 _route_groups = groups;
2376 route_groups_reordered (); /* EMIT SIGNAL */
2382 Session::route_group_by_name (string name)
2384 list<RouteGroup *>::iterator i;
2386 for (i = _route_groups.begin(); i != _route_groups.end(); ++i) {
2387 if ((*i)->name() == name) {
2395 Session::all_route_group() const
2397 return *_all_route_group;
2401 Session::add_commands (vector<Command*> const & cmds)
2403 for (vector<Command*>::const_iterator i = cmds.begin(); i != cmds.end(); ++i) {
2409 Session::begin_reversible_command (const string& name)
2411 begin_reversible_command (g_quark_from_string (name.c_str ()));
2414 /** Begin a reversible command using a GQuark to identify it.
2415 * begin_reversible_command() and commit_reversible_command() calls may be nested,
2416 * but there must be as many begin...()s as there are commit...()s.
2419 Session::begin_reversible_command (GQuark q)
2421 /* If nested begin/commit pairs are used, we create just one UndoTransaction
2422 to hold all the commands that are committed. This keeps the order of
2423 commands correct in the history.
2426 if (_current_trans == 0) {
2427 /* start a new transaction */
2428 assert (_current_trans_quarks.empty ());
2429 _current_trans = new UndoTransaction();
2430 _current_trans->set_name (g_quark_to_string (q));
2433 _current_trans_quarks.push_front (q);
2437 Session::commit_reversible_command (Command *cmd)
2439 assert (_current_trans);
2440 assert (!_current_trans_quarks.empty ());
2445 _current_trans->add_command (cmd);
2448 _current_trans_quarks.pop_front ();
2450 if (!_current_trans_quarks.empty ()) {
2451 /* the transaction we're committing is not the top-level one */
2455 if (_current_trans->empty()) {
2456 /* no commands were added to the transaction, so just get rid of it */
2457 delete _current_trans;
2462 gettimeofday (&now, 0);
2463 _current_trans->set_timestamp (now);
2465 _history.add (_current_trans);
2470 accept_all_audio_files (const string& path, void* /*arg*/)
2472 if (!Glib::file_test (path, Glib::FILE_TEST_IS_REGULAR)) {
2476 if (!AudioFileSource::safe_audio_file_extension (path)) {
2484 accept_all_midi_files (const string& path, void* /*arg*/)
2486 if (!Glib::file_test (path, Glib::FILE_TEST_IS_REGULAR)) {
2490 return ((path.length() > 4 && path.find (".mid") != (path.length() - 4)) ||
2491 (path.length() > 4 && path.find (".smf") != (path.length() - 4)) ||
2492 (path.length() > 5 && path.find (".midi") != (path.length() - 5)));
2496 accept_all_state_files (const string& path, void* /*arg*/)
2498 if (!Glib::file_test (path, Glib::FILE_TEST_IS_REGULAR)) {
2502 std::string const statefile_ext (statefile_suffix);
2503 if (path.length() >= statefile_ext.length()) {
2504 return (0 == path.compare (path.length() - statefile_ext.length(), statefile_ext.length(), statefile_ext));
2511 Session::find_all_sources (string path, set<string>& result)
2516 if (!tree.read (path)) {
2520 if ((node = find_named_node (*tree.root(), "Sources")) == 0) {
2525 XMLNodeConstIterator niter;
2527 nlist = node->children();
2531 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2535 if ((prop = (*niter)->property (X_("type"))) == 0) {
2539 DataType type (prop->value());
2541 if ((prop = (*niter)->property (X_("name"))) == 0) {
2545 if (Glib::path_is_absolute (prop->value())) {
2546 /* external file, ignore */
2554 if (FileSource::find (*this, type, prop->value(), true, is_new, chan, found_path)) {
2555 result.insert (found_path);
2563 Session::find_all_sources_across_snapshots (set<string>& result, bool exclude_this_snapshot)
2565 vector<string> state_files;
2567 string this_snapshot_path;
2573 if (ripped[ripped.length()-1] == G_DIR_SEPARATOR) {
2574 ripped = ripped.substr (0, ripped.length() - 1);
2577 find_files_matching_filter (state_files, ripped, accept_all_state_files, (void *) 0, true, true);
2579 if (state_files.empty()) {
2584 this_snapshot_path = _path;
2585 this_snapshot_path += legalize_for_path (_current_snapshot_name);
2586 this_snapshot_path += statefile_suffix;
2588 for (vector<string>::iterator i = state_files.begin(); i != state_files.end(); ++i) {
2590 if (exclude_this_snapshot && *i == this_snapshot_path) {
2594 if (find_all_sources (*i, result) < 0) {
2602 struct RegionCounter {
2603 typedef std::map<PBD::ID,boost::shared_ptr<AudioSource> > AudioSourceList;
2604 AudioSourceList::iterator iter;
2605 boost::shared_ptr<Region> region;
2608 RegionCounter() : count (0) {}
2612 Session::ask_about_playlist_deletion (boost::shared_ptr<Playlist> p)
2614 boost::optional<int> r = AskAboutPlaylistDeletion (p);
2615 return r.get_value_or (1);
2619 Session::cleanup_regions ()
2621 bool removed = false;
2622 const RegionFactory::RegionMap& regions (RegionFactory::regions());
2624 for (RegionFactory::RegionMap::const_iterator i = regions.begin(); i != regions.end(); ++i) {
2626 uint32_t used = playlists->region_use_count (i->second);
2628 if (used == 0 && !i->second->automatic ()) {
2630 RegionFactory::map_remove (i->second);
2635 // re-check to remove parent references of compound regions
2636 for (RegionFactory::RegionMap::const_iterator i = regions.begin(); i != regions.end(); ++i) {
2637 if (!(i->second->whole_file() && i->second->max_source_level() > 0)) {
2640 assert(boost::dynamic_pointer_cast<PlaylistSource>(i->second->source (0)) != 0);
2641 if (0 == playlists->region_use_count (i->second)) {
2642 RegionFactory::map_remove (i->second);
2647 /* dump the history list */
2654 Session::cleanup_sources (CleanupReport& rep)
2656 // FIXME: needs adaptation to midi
2658 vector<boost::shared_ptr<Source> > dead_sources;
2661 vector<string> candidates;
2662 vector<string> unused;
2663 set<string> all_sources;
2672 _state_of_the_state = (StateOfTheState) (_state_of_the_state | InCleanup);
2674 /* consider deleting all unused playlists */
2676 if (playlists->maybe_delete_unused (boost::bind (Session::ask_about_playlist_deletion, _1))) {
2681 /* sync the "all regions" property of each playlist with its current state
2684 playlists->sync_all_regions_with_regions ();
2686 /* find all un-used sources */
2691 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ) {
2693 SourceMap::iterator tmp;
2698 /* do not bother with files that are zero size, otherwise we remove the current "nascent"
2702 if (!i->second->used() && (i->second->length(i->second->timeline_position() > 0))) {
2703 dead_sources.push_back (i->second);
2704 i->second->drop_references ();
2710 /* build a list of all the possible audio directories for the session */
2712 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
2713 SessionDirectory sdir ((*i).path);
2714 asp += sdir.sound_path();
2716 audio_path += asp.to_string();
2719 /* build a list of all the possible midi directories for the session */
2721 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
2722 SessionDirectory sdir ((*i).path);
2723 msp += sdir.midi_path();
2725 midi_path += msp.to_string();
2727 find_files_matching_filter (candidates, audio_path, accept_all_audio_files, (void *) 0, true, true);
2728 find_files_matching_filter (candidates, midi_path, accept_all_midi_files, (void *) 0, true, true);
2730 /* find all sources, but don't use this snapshot because the
2731 state file on disk still references sources we may have already
2735 find_all_sources_across_snapshots (all_sources, true);
2737 /* add our current source list
2740 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ) {
2741 boost::shared_ptr<FileSource> fs;
2742 SourceMap::iterator tmp = i;
2745 if ((fs = boost::dynamic_pointer_cast<FileSource> (i->second)) != 0) {
2747 if (!fs->is_stub()) {
2749 if (playlists->source_use_count (fs) != 0) {
2750 all_sources.insert (fs->path());
2753 /* we might not remove this source from disk, because it may be used
2754 by other snapshots, but its not being used in this version
2755 so lets get rid of it now, along with any representative regions
2759 RegionFactory::remove_regions_using_source (i->second);
2768 for (vector<string>::iterator x = candidates.begin(); x != candidates.end(); ++x) {
2773 for (set<string>::iterator i = all_sources.begin(); i != all_sources.end(); ++i) {
2775 tmppath1 = canonical_path (spath);
2776 tmppath2 = canonical_path ((*i));
2778 if (tmppath1 == tmppath2) {
2785 unused.push_back (spath);
2789 /* now try to move all unused files into the "dead" directory(ies) */
2791 for (vector<string>::iterator x = unused.begin(); x != unused.end(); ++x) {
2792 struct stat statbuf;
2796 /* don't move the file across filesystems, just
2797 stick it in the `dead_dir_name' directory
2798 on whichever filesystem it was already on.
2801 if ((*x).find ("/sounds/") != string::npos) {
2803 /* old school, go up 1 level */
2805 newpath = Glib::path_get_dirname (*x); // "sounds"
2806 newpath = Glib::path_get_dirname (newpath); // "session-name"
2810 /* new school, go up 4 levels */
2812 newpath = Glib::path_get_dirname (*x); // "audiofiles" or "midifiles"
2813 newpath = Glib::path_get_dirname (newpath); // "session-name"
2814 newpath = Glib::path_get_dirname (newpath); // "interchange"
2815 newpath = Glib::path_get_dirname (newpath); // "session-dir"
2818 newpath = Glib::build_filename (newpath, dead_dir_name);
2820 if (g_mkdir_with_parents (newpath.c_str(), 0755) < 0) {
2821 error << string_compose(_("Session: cannot create dead file folder \"%1\" (%2)"), newpath, strerror (errno)) << endmsg;
2825 newpath = Glib::build_filename (newpath, Glib::path_get_basename ((*x)));
2827 if (Glib::file_test (newpath, Glib::FILE_TEST_EXISTS)) {
2829 /* the new path already exists, try versioning */
2831 char buf[PATH_MAX+1];
2835 snprintf (buf, sizeof (buf), "%s.%d", newpath.c_str(), version);
2838 while (Glib::file_test (newpath_v.c_str(), Glib::FILE_TEST_EXISTS) && version < 999) {
2839 snprintf (buf, sizeof (buf), "%s.%d", newpath.c_str(), ++version);
2843 if (version == 999) {
2844 error << string_compose (_("there are already 1000 files with names like %1; versioning discontinued"),
2848 newpath = newpath_v;
2853 /* it doesn't exist, or we can't read it or something */
2857 stat ((*x).c_str(), &statbuf);
2859 if (::rename ((*x).c_str(), newpath.c_str()) != 0) {
2860 error << string_compose (_("cannot rename unused file source from %1 to %2 (%3)"),
2861 (*x), newpath, strerror (errno))
2866 /* see if there an easy to find peakfile for this file, and remove it.
2869 string base = basename_nosuffix (*x);
2870 base += "%A"; /* this is what we add for the channel suffix of all native files,
2871 or for the first channel of embedded files. it will miss
2872 some peakfiles for other channels
2874 string peakpath = peak_path (base);
2876 if (Glib::file_test (peakpath.c_str(), Glib::FILE_TEST_EXISTS)) {
2877 if (::g_unlink (peakpath.c_str()) != 0) {
2878 error << string_compose (_("cannot remove peakfile %1 for %2 (%3)"),
2879 peakpath, _path, strerror (errno))
2881 /* try to back out */
2882 ::rename (newpath.c_str(), _path.c_str());
2887 rep.paths.push_back (*x);
2888 rep.space += statbuf.st_size;
2891 /* dump the history list */
2895 /* save state so we don't end up a session file
2896 referring to non-existent sources.
2903 _state_of_the_state = (StateOfTheState) (_state_of_the_state & ~InCleanup);
2909 Session::cleanup_trash_sources (CleanupReport& rep)
2911 // FIXME: needs adaptation for MIDI
2913 vector<space_and_path>::iterator i;
2919 for (i = session_dirs.begin(); i != session_dirs.end(); ++i) {
2921 dead_dir = Glib::build_filename ((*i).path, dead_dir_name);
2923 clear_directory (dead_dir, &rep.space, &rep.paths);
2930 Session::set_dirty ()
2932 /* never mark session dirty during loading */
2934 if (_state_of_the_state & Loading) {
2938 bool was_dirty = dirty();
2940 _state_of_the_state = StateOfTheState (_state_of_the_state | Dirty);
2944 DirtyChanged(); /* EMIT SIGNAL */
2950 Session::set_clean ()
2952 bool was_dirty = dirty();
2954 _state_of_the_state = Clean;
2958 DirtyChanged(); /* EMIT SIGNAL */
2963 Session::set_deletion_in_progress ()
2965 _state_of_the_state = StateOfTheState (_state_of_the_state | Deletion);
2969 Session::clear_deletion_in_progress ()
2971 _state_of_the_state = StateOfTheState (_state_of_the_state & (~Deletion));
2975 Session::add_controllable (boost::shared_ptr<Controllable> c)
2977 /* this adds a controllable to the list managed by the Session.
2978 this is a subset of those managed by the Controllable class
2979 itself, and represents the only ones whose state will be saved
2980 as part of the session.
2983 Glib::Threads::Mutex::Lock lm (controllables_lock);
2984 controllables.insert (c);
2987 struct null_deleter { void operator()(void const *) const {} };
2990 Session::remove_controllable (Controllable* c)
2992 if (_state_of_the_state & Deletion) {
2996 Glib::Threads::Mutex::Lock lm (controllables_lock);
2998 Controllables::iterator x = controllables.find (boost::shared_ptr<Controllable>(c, null_deleter()));
3000 if (x != controllables.end()) {
3001 controllables.erase (x);
3005 boost::shared_ptr<Controllable>
3006 Session::controllable_by_id (const PBD::ID& id)
3008 Glib::Threads::Mutex::Lock lm (controllables_lock);
3010 for (Controllables::iterator i = controllables.begin(); i != controllables.end(); ++i) {
3011 if ((*i)->id() == id) {
3016 return boost::shared_ptr<Controllable>();
3019 boost::shared_ptr<Controllable>
3020 Session::controllable_by_descriptor (const ControllableDescriptor& desc)
3022 boost::shared_ptr<Controllable> c;
3023 boost::shared_ptr<Route> r;
3025 switch (desc.top_level_type()) {
3026 case ControllableDescriptor::NamedRoute:
3028 std::string str = desc.top_level_name();
3029 if (str == "Master" || str == "master") {
3031 } else if (str == "control" || str == "listen") {
3034 r = route_by_name (desc.top_level_name());
3039 case ControllableDescriptor::RemoteControlID:
3040 r = route_by_remote_id (desc.rid());
3048 switch (desc.subtype()) {
3049 case ControllableDescriptor::Gain:
3050 c = r->gain_control ();
3053 case ControllableDescriptor::Solo:
3054 c = r->solo_control();
3057 case ControllableDescriptor::Mute:
3058 c = r->mute_control();
3061 case ControllableDescriptor::Recenable:
3063 boost::shared_ptr<Track> t = boost::dynamic_pointer_cast<Track>(r);
3066 c = t->rec_enable_control ();
3071 case ControllableDescriptor::PanDirection:
3073 c = r->pannable()->pan_azimuth_control;
3077 case ControllableDescriptor::PanWidth:
3079 c = r->pannable()->pan_width_control;
3083 case ControllableDescriptor::PanElevation:
3085 c = r->pannable()->pan_elevation_control;
3089 case ControllableDescriptor::Balance:
3090 /* XXX simple pan control */
3093 case ControllableDescriptor::PluginParameter:
3095 uint32_t plugin = desc.target (0);
3096 uint32_t parameter_index = desc.target (1);
3098 /* revert to zero based counting */
3104 if (parameter_index > 0) {
3108 boost::shared_ptr<Processor> p = r->nth_plugin (plugin);
3111 c = boost::dynamic_pointer_cast<ARDOUR::AutomationControl>(
3112 p->control(Evoral::Parameter(PluginAutomation, 0, parameter_index)));
3117 case ControllableDescriptor::SendGain:
3119 uint32_t send = desc.target (0);
3121 /* revert to zero-based counting */
3127 boost::shared_ptr<Processor> p = r->nth_send (send);
3130 boost::shared_ptr<Send> s = boost::dynamic_pointer_cast<Send>(p);
3131 boost::shared_ptr<Amp> a = s->amp();
3134 c = s->amp()->gain_control();
3141 /* relax and return a null pointer */
3149 Session::add_instant_xml (XMLNode& node, bool write_to_config)
3152 Stateful::add_instant_xml (node, _path);
3155 if (write_to_config) {
3156 Config->add_instant_xml (node);
3161 Session::instant_xml (const string& node_name)
3163 return Stateful::instant_xml (node_name, _path);
3167 Session::save_history (string snapshot_name)
3175 if (!Config->get_save_history() || Config->get_saved_history_depth() < 0 ||
3176 (_history.undo_depth() == 0 && _history.redo_depth() == 0)) {
3180 if (snapshot_name.empty()) {
3181 snapshot_name = _current_snapshot_name;
3184 const string history_filename = legalize_for_path (snapshot_name) + history_suffix;
3185 const string backup_filename = history_filename + backup_suffix;
3186 const std::string xml_path(Glib::build_filename (_session_dir->root_path(), history_filename));
3187 const std::string backup_path(Glib::build_filename (_session_dir->root_path(), backup_filename));
3189 if (Glib::file_test (xml_path, Glib::FILE_TEST_EXISTS)) {
3190 if (::g_rename (xml_path.c_str(), backup_path.c_str()) != 0) {
3191 error << _("could not backup old history file, current history not saved") << endmsg;
3196 tree.set_root (&_history.get_state (Config->get_saved_history_depth()));
3198 if (!tree.write (xml_path))
3200 error << string_compose (_("history could not be saved to %1"), xml_path) << endmsg;
3202 if (g_remove (xml_path.c_str()) != 0) {
3203 error << string_compose(_("Could not remove history file at path \"%1\" (%2)"),
3204 xml_path, g_strerror (errno)) << endmsg;
3206 if (::g_rename (backup_path.c_str(), xml_path.c_str()) != 0) {
3207 error << string_compose (_("could not restore history file from backup %1 (%2)"),
3208 backup_path, g_strerror (errno)) << endmsg;
3218 Session::restore_history (string snapshot_name)
3222 if (snapshot_name.empty()) {
3223 snapshot_name = _current_snapshot_name;
3226 const std::string xml_filename = legalize_for_path (snapshot_name) + history_suffix;
3227 const std::string xml_path(Glib::build_filename (_session_dir->root_path(), xml_filename));
3229 info << "Loading history from " << xml_path << endmsg;
3231 if (!Glib::file_test (xml_path, Glib::FILE_TEST_EXISTS)) {
3232 info << string_compose (_("%1: no history file \"%2\" for this session."),
3233 _name, xml_path) << endmsg;
3237 if (!tree.read (xml_path)) {
3238 error << string_compose (_("Could not understand session history file \"%1\""),
3239 xml_path) << endmsg;
3246 for (XMLNodeConstIterator it = tree.root()->children().begin(); it != tree.root()->children().end(); it++) {
3249 UndoTransaction* ut = new UndoTransaction ();
3252 ut->set_name(t->property("name")->value());
3253 stringstream ss(t->property("tv-sec")->value());
3255 ss.str(t->property("tv-usec")->value());
3257 ut->set_timestamp(tv);
3259 for (XMLNodeConstIterator child_it = t->children().begin();
3260 child_it != t->children().end(); child_it++)
3262 XMLNode *n = *child_it;
3265 if (n->name() == "MementoCommand" ||
3266 n->name() == "MementoUndoCommand" ||
3267 n->name() == "MementoRedoCommand") {
3269 if ((c = memento_command_factory(n))) {
3273 } else if (n->name() == "NoteDiffCommand") {
3274 PBD::ID id (n->property("midi-source")->value());
3275 boost::shared_ptr<MidiSource> midi_source =
3276 boost::dynamic_pointer_cast<MidiSource, Source>(source_by_id(id));
3278 ut->add_command (new MidiModel::NoteDiffCommand(midi_source->model(), *n));
3280 error << _("Failed to downcast MidiSource for NoteDiffCommand") << endmsg;
3283 } else if (n->name() == "SysExDiffCommand") {
3285 PBD::ID id (n->property("midi-source")->value());
3286 boost::shared_ptr<MidiSource> midi_source =
3287 boost::dynamic_pointer_cast<MidiSource, Source>(source_by_id(id));
3289 ut->add_command (new MidiModel::SysExDiffCommand (midi_source->model(), *n));
3291 error << _("Failed to downcast MidiSource for SysExDiffCommand") << endmsg;
3294 } else if (n->name() == "PatchChangeDiffCommand") {
3296 PBD::ID id (n->property("midi-source")->value());
3297 boost::shared_ptr<MidiSource> midi_source =
3298 boost::dynamic_pointer_cast<MidiSource, Source>(source_by_id(id));
3300 ut->add_command (new MidiModel::PatchChangeDiffCommand (midi_source->model(), *n));
3302 error << _("Failed to downcast MidiSource for PatchChangeDiffCommand") << endmsg;
3305 } else if (n->name() == "StatefulDiffCommand") {
3306 if ((c = stateful_diff_command_factory (n))) {
3307 ut->add_command (c);
3310 error << string_compose(_("Couldn't figure out how to make a Command out of a %1 XMLNode."), n->name()) << endmsg;
3321 Session::config_changed (std::string p, bool ours)
3327 if (p == "seamless-loop") {
3329 } else if (p == "rf-speed") {
3331 } else if (p == "auto-loop") {
3333 } else if (p == "auto-input") {
3335 if (Config->get_monitoring_model() == HardwareMonitoring && transport_rolling()) {
3336 /* auto-input only makes a difference if we're rolling */
3337 set_track_monitor_input_status (!config.get_auto_input());
3340 } else if (p == "punch-in") {
3344 if ((location = _locations->auto_punch_location()) != 0) {
3346 if (config.get_punch_in ()) {
3347 replace_event (SessionEvent::PunchIn, location->start());
3349 remove_event (location->start(), SessionEvent::PunchIn);
3353 } else if (p == "punch-out") {
3357 if ((location = _locations->auto_punch_location()) != 0) {
3359 if (config.get_punch_out()) {
3360 replace_event (SessionEvent::PunchOut, location->end());
3362 clear_events (SessionEvent::PunchOut);
3366 } else if (p == "edit-mode") {
3368 Glib::Threads::Mutex::Lock lm (playlists->lock);
3370 for (SessionPlaylists::List::iterator i = playlists->playlists.begin(); i != playlists->playlists.end(); ++i) {
3371 (*i)->set_edit_mode (Config->get_edit_mode ());
3374 } else if (p == "use-video-sync") {
3376 waiting_for_sync_offset = config.get_use_video_sync();
3378 } else if (p == "mmc-control") {
3380 //poke_midi_thread ();
3382 } else if (p == "mmc-device-id" || p == "mmc-receive-id" || p == "mmc-receive-device-id") {
3384 _mmc->set_receive_device_id (Config->get_mmc_receive_device_id());
3386 } else if (p == "mmc-send-id" || p == "mmc-send-device-id") {
3388 _mmc->set_send_device_id (Config->get_mmc_send_device_id());
3390 } else if (p == "midi-control") {
3392 //poke_midi_thread ();
3394 } else if (p == "raid-path") {
3396 setup_raid_path (config.get_raid_path());
3398 } else if (p == "timecode-format") {
3402 } else if (p == "video-pullup") {
3406 } else if (p == "seamless-loop") {
3408 if (play_loop && transport_rolling()) {
3409 // to reset diskstreams etc
3410 request_play_loop (true);
3413 } else if (p == "rf-speed") {
3415 cumulative_rf_motion = 0;
3418 } else if (p == "click-sound") {
3420 setup_click_sounds (1);
3422 } else if (p == "click-emphasis-sound") {
3424 setup_click_sounds (-1);
3426 } else if (p == "clicking") {
3428 if (Config->get_clicking()) {
3429 if (_click_io && click_data) { // don't require emphasis data
3436 } else if (p == "click-gain") {
3439 _click_gain->set_gain (Config->get_click_gain(), this);
3442 } else if (p == "send-mtc") {
3444 if (Config->get_send_mtc ()) {
3445 /* mark us ready to send */
3446 next_quarter_frame_to_send = 0;
3449 } else if (p == "send-mmc") {
3451 _mmc->enable_send (Config->get_send_mmc ());
3453 } else if (p == "midi-feedback") {
3455 session_midi_feedback = Config->get_midi_feedback();
3457 } else if (p == "jack-time-master") {
3459 engine().reset_timebase ();
3461 } else if (p == "native-file-header-format") {
3463 if (!first_file_header_format_reset) {
3464 reset_native_file_format ();
3467 first_file_header_format_reset = false;
3469 } else if (p == "native-file-data-format") {
3471 if (!first_file_data_format_reset) {
3472 reset_native_file_format ();
3475 first_file_data_format_reset = false;
3477 } else if (p == "external-sync") {
3478 if (!config.get_external_sync()) {
3479 drop_sync_source ();
3481 switch_to_sync_source (Config->get_sync_source());
3483 } else if (p == "denormal-model") {
3485 } else if (p == "history-depth") {
3486 set_history_depth (Config->get_history_depth());
3487 } else if (p == "remote-model") {
3488 /* XXX DO SOMETHING HERE TO TELL THE GUI THAT WE NEED
3491 } else if (p == "initial-program-change") {
3493 if (_mmc->output_port() && Config->get_initial_program_change() >= 0) {
3496 buf[0] = MIDI::program; // channel zero by default
3497 buf[1] = (Config->get_initial_program_change() & 0x7f);
3499 _mmc->output_port()->midimsg (buf, sizeof (buf), 0);
3501 } else if (p == "solo-mute-override") {
3502 // catch_up_on_solo_mute_override ();
3503 } else if (p == "listen-position" || p == "pfl-position") {
3504 listen_position_changed ();
3505 } else if (p == "solo-control-is-listen-control") {
3506 solo_control_mode_changed ();
3507 } else if (p == "solo-mute-gain") {
3508 _solo_cut_control->Changed();
3509 } else if (p == "timecode-offset" || p == "timecode-offset-negative") {
3510 last_timecode_valid = false;
3511 } else if (p == "playback-buffer-seconds") {
3512 AudioSource::allocate_working_buffers (frame_rate());
3513 } else if (p == "ltc-source-port") {
3514 reconnect_ltc_input ();
3515 } else if (p == "ltc-sink-port") {
3516 reconnect_ltc_output ();
3517 } else if (p == "timecode-generator-offset") {
3518 ltc_tx_parse_offset();
3525 Session::set_history_depth (uint32_t d)
3527 _history.set_depth (d);
3531 Session::load_diskstreams_2X (XMLNode const & node, int)
3534 XMLNodeConstIterator citer;
3536 clist = node.children();
3538 for (citer = clist.begin(); citer != clist.end(); ++citer) {
3541 /* diskstreams added automatically by DiskstreamCreated handler */
3542 if ((*citer)->name() == "AudioDiskstream" || (*citer)->name() == "DiskStream") {
3543 boost::shared_ptr<AudioDiskstream> dsp (new AudioDiskstream (*this, **citer));
3544 _diskstreams_2X.push_back (dsp);
3546 error << _("Session: unknown diskstream type in XML") << endmsg;
3550 catch (failed_constructor& err) {
3551 error << _("Session: could not load diskstream via XML state") << endmsg;
3559 /** Connect things to the MMC object */
3561 Session::setup_midi_machine_control ()
3563 _mmc = new MIDI::MachineControl;
3564 _mmc->set_ports (_midi_ports->mmc_input_port(), _midi_ports->mmc_output_port());
3566 _mmc->Play.connect_same_thread (*this, boost::bind (&Session::mmc_deferred_play, this, _1));
3567 _mmc->DeferredPlay.connect_same_thread (*this, boost::bind (&Session::mmc_deferred_play, this, _1));
3568 _mmc->Stop.connect_same_thread (*this, boost::bind (&Session::mmc_stop, this, _1));
3569 _mmc->FastForward.connect_same_thread (*this, boost::bind (&Session::mmc_fast_forward, this, _1));
3570 _mmc->Rewind.connect_same_thread (*this, boost::bind (&Session::mmc_rewind, this, _1));
3571 _mmc->Pause.connect_same_thread (*this, boost::bind (&Session::mmc_pause, this, _1));
3572 _mmc->RecordPause.connect_same_thread (*this, boost::bind (&Session::mmc_record_pause, this, _1));
3573 _mmc->RecordStrobe.connect_same_thread (*this, boost::bind (&Session::mmc_record_strobe, this, _1));
3574 _mmc->RecordExit.connect_same_thread (*this, boost::bind (&Session::mmc_record_exit, this, _1));
3575 _mmc->Locate.connect_same_thread (*this, boost::bind (&Session::mmc_locate, this, _1, _2));
3576 _mmc->Step.connect_same_thread (*this, boost::bind (&Session::mmc_step, this, _1, _2));
3577 _mmc->Shuttle.connect_same_thread (*this, boost::bind (&Session::mmc_shuttle, this, _1, _2, _3));
3578 _mmc->TrackRecordStatusChange.connect_same_thread (*this, boost::bind (&Session::mmc_record_enable, this, _1, _2, _3));
3580 /* also handle MIDI SPP because its so common */
3582 _mmc->SPPStart.connect_same_thread (*this, boost::bind (&Session::spp_start, this));
3583 _mmc->SPPContinue.connect_same_thread (*this, boost::bind (&Session::spp_continue, this));
3584 _mmc->SPPStop.connect_same_thread (*this, boost::bind (&Session::spp_stop, this));
3587 boost::shared_ptr<Controllable>
3588 Session::solo_cut_control() const
3590 /* the solo cut control is a bit of an anomaly, at least as of Febrary 2011. There are no other
3591 controls in Ardour that currently get presented to the user in the GUI that require
3592 access as a Controllable and are also NOT owned by some SessionObject (e.g. Route, or MonitorProcessor).
3594 its actually an RCConfiguration parameter, so we use a ProxyControllable to wrap
3595 it up as a Controllable. Changes to the Controllable will just map back to the RCConfiguration
3599 return _solo_cut_control;
3603 Session::rename (const std::string& new_name)
3605 string legal_name = legalize_for_path (new_name);
3611 string const old_sources_root = _session_dir->sources_root();
3616 * interchange subdirectory
3620 * Backup files are left unchanged and not renamed.
3623 /* pass one: not 100% safe check that the new directory names don't
3627 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
3632 /* this is a stupid hack because Glib::path_get_dirname() is
3633 * lexical-only, and so passing it /a/b/c/ gives a different
3634 * result than passing it /a/b/c ...
3637 if (oldstr[oldstr.length()-1] == G_DIR_SEPARATOR) {
3638 oldstr = oldstr.substr (0, oldstr.length() - 1);
3641 string base = Glib::path_get_dirname (oldstr);
3642 string p = Glib::path_get_basename (oldstr);
3644 newstr = Glib::build_filename (base, legal_name);
3646 if (Glib::file_test (newstr, Glib::FILE_TEST_EXISTS)) {
3653 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
3658 /* this is a stupid hack because Glib::path_get_dirname() is
3659 * lexical-only, and so passing it /a/b/c/ gives a different
3660 * result than passing it /a/b/c ...
3663 if (oldstr[oldstr.length()-1] == G_DIR_SEPARATOR) {
3664 oldstr = oldstr.substr (0, oldstr.length() - 1);
3667 string base = Glib::path_get_dirname (oldstr);
3668 string p = Glib::path_get_basename (oldstr);
3670 newstr = Glib::build_filename (base, legal_name);
3672 cerr << "Rename " << oldstr << " => " << newstr << endl;
3674 if (::g_rename (oldstr.c_str(), newstr.c_str()) != 0) {
3675 error << string_compose (_("renaming %s as %2 failed (%3)"), oldstr, newstr, g_strerror (errno)) << endmsg;
3680 (*_session_dir) = newstr;
3685 /* directory below interchange */
3687 v.push_back (newstr);
3688 v.push_back (interchange_dir_name);
3691 oldstr = Glib::build_filename (v);
3694 v.push_back (newstr);
3695 v.push_back (interchange_dir_name);
3696 v.push_back (legal_name);
3698 newstr = Glib::build_filename (v);
3700 cerr << "Rename " << oldstr << " => " << newstr << endl;
3702 if (::g_rename (oldstr.c_str(), newstr.c_str()) != 0) {
3703 error << string_compose (_("renaming %s as %2 failed (%3)"), oldstr, newstr, g_strerror (errno)) << endmsg;
3710 oldstr = Glib::build_filename (newpath, _current_snapshot_name) + statefile_suffix;
3711 newstr= Glib::build_filename (newpath, legal_name) + statefile_suffix;
3713 cerr << "Rename " << oldstr << " => " << newstr << endl;
3715 if (::g_rename (oldstr.c_str(), newstr.c_str()) != 0) {
3716 error << string_compose (_("renaming %s as %2 failed (%3)"), oldstr, newstr, g_strerror (errno)) << endmsg;
3723 oldstr = Glib::build_filename (newpath, _current_snapshot_name) + history_suffix;
3725 if (Glib::file_test (oldstr, Glib::FILE_TEST_EXISTS)) {
3726 newstr = Glib::build_filename (newpath, legal_name) + history_suffix;
3728 cerr << "Rename " << oldstr << " => " << newstr << endl;
3730 if (::g_rename (oldstr.c_str(), newstr.c_str()) != 0) {
3731 error << string_compose (_("renaming %s as %2 failed (%3)"), oldstr, newstr, g_strerror (errno)) << endmsg;
3736 /* update file source paths */
3738 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ++i) {
3739 boost::shared_ptr<FileSource> fs = boost::dynamic_pointer_cast<FileSource> (i->second);
3741 string p = fs->path ();
3742 boost::replace_all (p, old_sources_root, _session_dir->sources_root());
3747 /* remove old name from recent sessions */
3749 remove_recent_sessions (_path);
3752 _current_snapshot_name = new_name;
3755 /* re-add directory separator - reverse hack to oldstr above */
3756 if (_path[_path.length()-1] != G_DIR_SEPARATOR) {
3757 _path += G_DIR_SEPARATOR;
3762 /* save state again to get everything just right */
3764 save_state (_current_snapshot_name);
3767 /* add to recent sessions */
3769 store_recent_sessions (new_name, _path);
3775 Session::get_session_info_from_path (XMLTree& tree, const string& xmlpath)
3777 if (!Glib::file_test (xmlpath, Glib::FILE_TEST_EXISTS)) {
3781 if (!tree.read (xmlpath)) {
3789 Session::get_info_from_path (const string& xmlpath, float& sample_rate, SampleFormat& data_format)
3792 bool found_sr = false;
3793 bool found_data_format = false;
3795 if (get_session_info_from_path (tree, xmlpath)) {
3801 const XMLProperty* prop;
3802 if ((prop = tree.root()->property (X_("sample-rate"))) != 0) {
3803 sample_rate = atoi (prop->value());
3807 const XMLNodeList& children (tree.root()->children());
3808 for (XMLNodeList::const_iterator c = children.begin(); c != children.end(); ++c) {
3809 const XMLNode* child = *c;
3810 if (child->name() == "Config") {
3811 const XMLNodeList& options (child->children());
3812 for (XMLNodeList::const_iterator oc = options.begin(); oc != options.end(); ++oc) {
3813 const XMLNode* option = *oc;
3814 const XMLProperty* name = option->property("name");
3820 if (name->value() == "native-file-data-format") {
3821 const XMLProperty* value = option->property ("value");
3823 SampleFormat fmt = (SampleFormat) string_2_enum (option->property ("value")->value(), fmt);
3825 found_data_format = true;
3831 if (found_data_format) {
3836 return !(found_sr && found_data_format); // zero if they are both found
3839 typedef std::vector<boost::shared_ptr<FileSource> > SeveralFileSources;
3840 typedef std::map<std::string,SeveralFileSources> SourcePathMap;
3843 Session::bring_all_sources_into_session (boost::function<void(uint32_t,uint32_t,string)> callback)
3847 SourcePathMap source_path_map;
3849 boost::shared_ptr<AudioFileSource> afs;
3854 Glib::Threads::Mutex::Lock lm (source_lock);
3856 cerr << " total sources = " << sources.size();
3858 for (SourceMap::const_iterator i = sources.begin(); i != sources.end(); ++i) {
3859 boost::shared_ptr<FileSource> fs = boost::dynamic_pointer_cast<FileSource> (i->second);
3865 if (fs->within_session()) {
3866 cerr << "skip " << fs->name() << endl;
3870 if (source_path_map.find (fs->path()) != source_path_map.end()) {
3871 source_path_map[fs->path()].push_back (fs);
3873 SeveralFileSources v;
3875 source_path_map.insert (make_pair (fs->path(), v));
3881 cerr << " fsources = " << total << endl;
3883 for (SourcePathMap::iterator i = source_path_map.begin(); i != source_path_map.end(); ++i) {
3885 /* tell caller where we are */
3887 string old_path = i->first;
3889 callback (n, total, old_path);
3891 cerr << old_path << endl;
3895 switch (i->second.front()->type()) {
3896 case DataType::AUDIO:
3897 new_path = new_audio_source_path_for_embedded (old_path);
3900 case DataType::MIDI:
3904 cerr << "Move " << old_path << " => " << new_path << endl;
3906 if (!copy_file (old_path, new_path)) {
3907 cerr << "failed !\n";
3911 /* make sure we stop looking in the external
3912 dir/folder. Remember, this is an all-or-nothing
3913 operations, it doesn't merge just some files.
3915 remove_dir_from_search_path (Glib::path_get_dirname (old_path), i->second.front()->type());
3917 for (SeveralFileSources::iterator f = i->second.begin(); f != i->second.end(); ++f) {
3918 (*f)->set_path (new_path);
3923 save_state ("", false, false);