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 SessionSaveUnderway (); /* 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_("C"));
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 BootMessage (_("Tracks/busses loaded; Adding to Session"));
1384 add_routes (new_routes, false, false, false);
1386 BootMessage (_("Finished adding tracks/busses"));
1391 boost::shared_ptr<Route>
1392 Session::XMLRouteFactory (const XMLNode& node, int version)
1394 boost::shared_ptr<Route> ret;
1396 if (node.name() != "Route") {
1400 XMLNode* ds_child = find_named_node (node, X_("Diskstream"));
1402 DataType type = DataType::AUDIO;
1403 const XMLProperty* prop = node.property("default-type");
1406 type = DataType (prop->value());
1409 assert (type != DataType::NIL);
1413 boost::shared_ptr<Track> track;
1415 if (type == DataType::AUDIO) {
1416 track.reset (new AudioTrack (*this, X_("toBeResetFroXML")));
1418 track.reset (new MidiTrack (*this, X_("toBeResetFroXML")));
1421 if (track->init()) {
1425 if (track->set_state (node, version)) {
1429 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
1430 // boost_debug_shared_ptr_mark_interesting (track.get(), "Track");
1435 enum Route::Flag flags = Route::Flag(0);
1436 const XMLProperty* prop = node.property("flags");
1438 flags = Route::Flag (string_2_enum (prop->value(), flags));
1441 boost::shared_ptr<Route> r (new Route (*this, X_("toBeResetFroXML"), flags));
1443 if (r->init () == 0 && r->set_state (node, version) == 0) {
1444 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
1445 // boost_debug_shared_ptr_mark_interesting (r.get(), "Route");
1454 boost::shared_ptr<Route>
1455 Session::XMLRouteFactory_2X (const XMLNode& node, int version)
1457 boost::shared_ptr<Route> ret;
1459 if (node.name() != "Route") {
1463 XMLProperty const * ds_prop = node.property (X_("diskstream-id"));
1465 ds_prop = node.property (X_("diskstream"));
1468 DataType type = DataType::AUDIO;
1469 const XMLProperty* prop = node.property("default-type");
1472 type = DataType (prop->value());
1475 assert (type != DataType::NIL);
1479 list<boost::shared_ptr<Diskstream> >::iterator i = _diskstreams_2X.begin ();
1480 while (i != _diskstreams_2X.end() && (*i)->id() != ds_prop->value()) {
1484 if (i == _diskstreams_2X.end()) {
1485 error << _("Could not find diskstream for route") << endmsg;
1486 return boost::shared_ptr<Route> ();
1489 boost::shared_ptr<Track> track;
1491 if (type == DataType::AUDIO) {
1492 track.reset (new AudioTrack (*this, X_("toBeResetFroXML")));
1494 track.reset (new MidiTrack (*this, X_("toBeResetFroXML")));
1497 if (track->init()) {
1501 if (track->set_state (node, version)) {
1505 track->set_diskstream (*i);
1507 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
1508 // boost_debug_shared_ptr_mark_interesting (track.get(), "Track");
1513 enum Route::Flag flags = Route::Flag(0);
1514 const XMLProperty* prop = node.property("flags");
1516 flags = Route::Flag (string_2_enum (prop->value(), flags));
1519 boost::shared_ptr<Route> r (new Route (*this, X_("toBeResetFroXML"), flags));
1521 if (r->init () == 0 && r->set_state (node, version) == 0) {
1522 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
1523 // boost_debug_shared_ptr_mark_interesting (r.get(), "Route");
1533 Session::load_regions (const XMLNode& node)
1536 XMLNodeConstIterator niter;
1537 boost::shared_ptr<Region> region;
1539 nlist = node.children();
1543 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1544 if ((region = XMLRegionFactory (**niter, false)) == 0) {
1545 error << _("Session: cannot create Region from XML description.");
1546 const XMLProperty *name = (**niter).property("name");
1549 error << " " << string_compose (_("Can not load state for region '%1'"), name->value());
1560 Session::load_compounds (const XMLNode& node)
1562 XMLNodeList calist = node.children();
1563 XMLNodeConstIterator caiter;
1564 XMLProperty *caprop;
1566 for (caiter = calist.begin(); caiter != calist.end(); ++caiter) {
1567 XMLNode* ca = *caiter;
1571 if ((caprop = ca->property (X_("original"))) == 0) {
1574 orig_id = caprop->value();
1576 if ((caprop = ca->property (X_("copy"))) == 0) {
1579 copy_id = caprop->value();
1581 boost::shared_ptr<Region> orig = RegionFactory::region_by_id (orig_id);
1582 boost::shared_ptr<Region> copy = RegionFactory::region_by_id (copy_id);
1584 if (!orig || !copy) {
1585 warning << string_compose (_("Regions in compound description not found (ID's %1 and %2): ignored"),
1591 RegionFactory::add_compound_association (orig, copy);
1598 Session::load_nested_sources (const XMLNode& node)
1601 XMLNodeConstIterator niter;
1603 nlist = node.children();
1605 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1606 if ((*niter)->name() == "Source") {
1608 /* it may already exist, so don't recreate it unnecessarily
1611 XMLProperty* prop = (*niter)->property (X_("id"));
1613 error << _("Nested source has no ID info in session file! (ignored)") << endmsg;
1617 ID source_id (prop->value());
1619 if (!source_by_id (source_id)) {
1622 SourceFactory::create (*this, **niter, true);
1624 catch (failed_constructor& err) {
1625 error << string_compose (_("Cannot reconstruct nested source for region %1"), name()) << endmsg;
1632 boost::shared_ptr<Region>
1633 Session::XMLRegionFactory (const XMLNode& node, bool full)
1635 const XMLProperty* type = node.property("type");
1639 const XMLNodeList& nlist = node.children();
1641 for (XMLNodeConstIterator niter = nlist.begin(); niter != nlist.end(); ++niter) {
1642 XMLNode *child = (*niter);
1643 if (child->name() == "NestedSource") {
1644 load_nested_sources (*child);
1648 if (!type || type->value() == "audio") {
1649 return boost::shared_ptr<Region>(XMLAudioRegionFactory (node, full));
1650 } else if (type->value() == "midi") {
1651 return boost::shared_ptr<Region>(XMLMidiRegionFactory (node, full));
1654 } catch (failed_constructor& err) {
1655 return boost::shared_ptr<Region> ();
1658 return boost::shared_ptr<Region> ();
1661 boost::shared_ptr<AudioRegion>
1662 Session::XMLAudioRegionFactory (const XMLNode& node, bool /*full*/)
1664 const XMLProperty* prop;
1665 boost::shared_ptr<Source> source;
1666 boost::shared_ptr<AudioSource> as;
1668 SourceList master_sources;
1669 uint32_t nchans = 1;
1672 if (node.name() != X_("Region")) {
1673 return boost::shared_ptr<AudioRegion>();
1676 if ((prop = node.property (X_("channels"))) != 0) {
1677 nchans = atoi (prop->value().c_str());
1680 if ((prop = node.property ("name")) == 0) {
1681 cerr << "no name for this region\n";
1685 if ((prop = node.property (X_("source-0"))) == 0) {
1686 if ((prop = node.property ("source")) == 0) {
1687 error << _("Session: XMLNode describing a AudioRegion is incomplete (no source)") << endmsg;
1688 return boost::shared_ptr<AudioRegion>();
1692 PBD::ID s_id (prop->value());
1694 if ((source = source_by_id (s_id)) == 0) {
1695 error << string_compose(_("Session: XMLNode describing a AudioRegion references an unknown source id =%1"), s_id) << endmsg;
1696 return boost::shared_ptr<AudioRegion>();
1699 as = boost::dynamic_pointer_cast<AudioSource>(source);
1701 error << string_compose(_("Session: XMLNode describing a AudioRegion references a non-audio source id =%1"), s_id) << endmsg;
1702 return boost::shared_ptr<AudioRegion>();
1705 sources.push_back (as);
1707 /* pickup other channels */
1709 for (uint32_t n=1; n < nchans; ++n) {
1710 snprintf (buf, sizeof(buf), X_("source-%d"), n);
1711 if ((prop = node.property (buf)) != 0) {
1713 PBD::ID id2 (prop->value());
1715 if ((source = source_by_id (id2)) == 0) {
1716 error << string_compose(_("Session: XMLNode describing a AudioRegion references an unknown source id =%1"), id2) << endmsg;
1717 return boost::shared_ptr<AudioRegion>();
1720 as = boost::dynamic_pointer_cast<AudioSource>(source);
1722 error << string_compose(_("Session: XMLNode describing a AudioRegion references a non-audio source id =%1"), id2) << endmsg;
1723 return boost::shared_ptr<AudioRegion>();
1725 sources.push_back (as);
1729 for (uint32_t n = 0; n < nchans; ++n) {
1730 snprintf (buf, sizeof(buf), X_("master-source-%d"), n);
1731 if ((prop = node.property (buf)) != 0) {
1733 PBD::ID id2 (prop->value());
1735 if ((source = source_by_id (id2)) == 0) {
1736 error << string_compose(_("Session: XMLNode describing a AudioRegion references an unknown source id =%1"), id2) << endmsg;
1737 return boost::shared_ptr<AudioRegion>();
1740 as = boost::dynamic_pointer_cast<AudioSource>(source);
1742 error << string_compose(_("Session: XMLNode describing a AudioRegion references a non-audio source id =%1"), id2) << endmsg;
1743 return boost::shared_ptr<AudioRegion>();
1745 master_sources.push_back (as);
1750 boost::shared_ptr<AudioRegion> region (boost::dynamic_pointer_cast<AudioRegion> (RegionFactory::create (sources, node)));
1752 /* a final detail: this is the one and only place that we know how long missing files are */
1754 if (region->whole_file()) {
1755 for (SourceList::iterator sx = sources.begin(); sx != sources.end(); ++sx) {
1756 boost::shared_ptr<SilentFileSource> sfp = boost::dynamic_pointer_cast<SilentFileSource> (*sx);
1758 sfp->set_length (region->length());
1763 if (!master_sources.empty()) {
1764 if (master_sources.size() != nchans) {
1765 error << _("Session: XMLNode describing an AudioRegion is missing some master sources; ignored") << endmsg;
1767 region->set_master_sources (master_sources);
1775 catch (failed_constructor& err) {
1776 return boost::shared_ptr<AudioRegion>();
1780 boost::shared_ptr<MidiRegion>
1781 Session::XMLMidiRegionFactory (const XMLNode& node, bool /*full*/)
1783 const XMLProperty* prop;
1784 boost::shared_ptr<Source> source;
1785 boost::shared_ptr<MidiSource> ms;
1788 if (node.name() != X_("Region")) {
1789 return boost::shared_ptr<MidiRegion>();
1792 if ((prop = node.property ("name")) == 0) {
1793 cerr << "no name for this region\n";
1797 if ((prop = node.property (X_("source-0"))) == 0) {
1798 if ((prop = node.property ("source")) == 0) {
1799 error << _("Session: XMLNode describing a MidiRegion is incomplete (no source)") << endmsg;
1800 return boost::shared_ptr<MidiRegion>();
1804 PBD::ID s_id (prop->value());
1806 if ((source = source_by_id (s_id)) == 0) {
1807 error << string_compose(_("Session: XMLNode describing a MidiRegion references an unknown source id =%1"), s_id) << endmsg;
1808 return boost::shared_ptr<MidiRegion>();
1811 ms = boost::dynamic_pointer_cast<MidiSource>(source);
1813 error << string_compose(_("Session: XMLNode describing a MidiRegion references a non-midi source id =%1"), s_id) << endmsg;
1814 return boost::shared_ptr<MidiRegion>();
1817 sources.push_back (ms);
1820 boost::shared_ptr<MidiRegion> region (boost::dynamic_pointer_cast<MidiRegion> (RegionFactory::create (sources, node)));
1821 /* a final detail: this is the one and only place that we know how long missing files are */
1823 if (region->whole_file()) {
1824 for (SourceList::iterator sx = sources.begin(); sx != sources.end(); ++sx) {
1825 boost::shared_ptr<SilentFileSource> sfp = boost::dynamic_pointer_cast<SilentFileSource> (*sx);
1827 sfp->set_length (region->length());
1835 catch (failed_constructor& err) {
1836 return boost::shared_ptr<MidiRegion>();
1841 Session::get_sources_as_xml ()
1844 XMLNode* node = new XMLNode (X_("Sources"));
1845 Glib::Threads::Mutex::Lock lm (source_lock);
1847 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ++i) {
1848 node->add_child_nocopy (i->second->get_state());
1855 Session::load_sources (const XMLNode& node)
1858 XMLNodeConstIterator niter;
1859 boost::shared_ptr<Source> source; /* don't need this but it stops some
1860 * versions of gcc complaining about
1861 * discarded return values.
1864 nlist = node.children();
1868 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1871 if ((source = XMLSourceFactory (**niter)) == 0) {
1872 error << _("Session: cannot create Source from XML description.") << endmsg;
1875 } catch (MissingSource& err) {
1879 if (err.type == DataType::MIDI && Glib::path_is_absolute (err.path)) {
1880 error << string_compose (_("A external MIDI file is missing. %1 cannot currently recover from missing external MIDI files"),
1881 PROGRAM_NAME) << endmsg;
1885 if (!no_questions_about_missing_files) {
1886 user_choice = MissingFile (this, err.path, err.type).get_value_or (-1);
1891 switch (user_choice) {
1893 /* user added a new search location, so try again */
1898 /* user asked to quit the entire session load
1903 no_questions_about_missing_files = true;
1907 no_questions_about_missing_files = true;
1914 case DataType::AUDIO:
1915 source = SourceFactory::createSilent (*this, **niter, max_framecnt, _current_frame_rate);
1918 case DataType::MIDI:
1919 /* The MIDI file is actually missing so
1920 * just create a new one in the same
1921 * location. Do not announce its
1925 if (!Glib::path_is_absolute (err.path)) {
1926 fullpath = Glib::build_filename (source_search_path (DataType::MIDI).front(), err.path);
1928 /* this should be an unrecoverable error: we would be creating a MIDI file outside
1933 /* Note that we do not announce the source just yet - we need to reset its ID before we do that */
1934 source = SourceFactory::createWritable (DataType::MIDI, *this, fullpath, false, _current_frame_rate, false, false);
1935 /* reset ID to match the missing one */
1936 source->set_id (**niter);
1937 /* Now we can announce it */
1938 SourceFactory::SourceCreated (source);
1949 boost::shared_ptr<Source>
1950 Session::XMLSourceFactory (const XMLNode& node)
1952 if (node.name() != "Source") {
1953 return boost::shared_ptr<Source>();
1957 /* note: do peak building in another thread when loading session state */
1958 return SourceFactory::create (*this, node, true);
1961 catch (failed_constructor& err) {
1962 error << string_compose (_("Found a sound file that cannot be used by %1. Talk to the programmers."), PROGRAM_NAME) << endmsg;
1963 return boost::shared_ptr<Source>();
1968 Session::save_template (string template_name)
1972 if (_state_of_the_state & CannotSave) {
1976 std::string user_template_dir(user_template_directory());
1978 if (g_mkdir_with_parents (user_template_dir.c_str(), 0755) != 0) {
1979 error << string_compose(_("Could not create templates directory \"%1\" (%2)"),
1980 user_template_dir, g_strerror (errno)) << endmsg;
1984 tree.set_root (&get_template());
1986 std::string template_dir_path(user_template_dir);
1988 /* directory to put the template in */
1989 template_dir_path = Glib::build_filename (template_dir_path, template_name);
1991 if (Glib::file_test (template_dir_path, Glib::FILE_TEST_EXISTS)) {
1992 warning << string_compose(_("Template \"%1\" already exists - new version not created"),
1993 template_dir_path) << endmsg;
1997 if (g_mkdir_with_parents (template_dir_path.c_str(), 0755) != 0) {
1998 error << string_compose(_("Could not create directory for Session template\"%1\" (%2)"),
1999 template_dir_path, g_strerror (errno)) << endmsg;
2004 std::string template_file_path(template_dir_path);
2005 template_file_path = Glib::build_filename (template_file_path, template_name + template_suffix);
2007 if (!tree.write (template_file_path)) {
2008 error << _("template not saved") << endmsg;
2012 /* copy plugin state directory */
2014 std::string template_plugin_state_path(template_dir_path);
2015 template_plugin_state_path = Glib::build_filename (template_plugin_state_path, X_("plugins"));
2017 if (g_mkdir_with_parents (template_plugin_state_path.c_str(), 0755) != 0) {
2018 error << string_compose(_("Could not create directory for Session template plugin state\"%1\" (%2)"),
2019 template_plugin_state_path, g_strerror (errno)) << endmsg;
2023 copy_recurse (plugins_dir(), template_plugin_state_path);
2029 Session::refresh_disk_space ()
2031 #if __APPLE__ || (HAVE_SYS_VFS_H && HAVE_SYS_STATVFS_H)
2033 Glib::Threads::Mutex::Lock lm (space_lock);
2035 /* get freespace on every FS that is part of the session path */
2037 _total_free_4k_blocks = 0;
2038 _total_free_4k_blocks_uncertain = false;
2040 for (vector<space_and_path>::iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
2042 struct statfs statfsbuf;
2043 statfs (i->path.c_str(), &statfsbuf);
2045 double const scale = statfsbuf.f_bsize / 4096.0;
2047 /* See if this filesystem is read-only */
2048 struct statvfs statvfsbuf;
2049 statvfs (i->path.c_str(), &statvfsbuf);
2051 /* f_bavail can be 0 if it is undefined for whatever
2052 filesystem we are looking at; Samba shares mounted
2053 via GVFS are an example of this.
2055 if (statfsbuf.f_bavail == 0) {
2056 /* block count unknown */
2058 i->blocks_unknown = true;
2059 } else if (statvfsbuf.f_flag & ST_RDONLY) {
2060 /* read-only filesystem */
2062 i->blocks_unknown = false;
2064 /* read/write filesystem with known space */
2065 i->blocks = (uint32_t) floor (statfsbuf.f_bavail * scale);
2066 i->blocks_unknown = false;
2069 _total_free_4k_blocks += i->blocks;
2070 if (i->blocks_unknown) {
2071 _total_free_4k_blocks_uncertain = true;
2074 #elif defined (COMPILER_MSVC)
2075 vector<string> scanned_volumes;
2076 vector<string>::iterator j;
2077 vector<space_and_path>::iterator i;
2078 DWORD nSectorsPerCluster, nBytesPerSector,
2079 nFreeClusters, nTotalClusters;
2083 _total_free_4k_blocks = 0;
2085 for (i = session_dirs.begin(); i != session_dirs.end(); i++) {
2086 strncpy (disk_drive, (*i).path.c_str(), 3);
2090 volume_found = false;
2091 if (0 != (GetDiskFreeSpace(disk_drive, &nSectorsPerCluster, &nBytesPerSector, &nFreeClusters, &nTotalClusters)))
2093 int64_t nBytesPerCluster = nBytesPerSector * nSectorsPerCluster;
2094 int64_t nFreeBytes = nBytesPerCluster * (int64_t)nFreeClusters;
2095 i->blocks = (uint32_t)(nFreeBytes / 4096);
2097 for (j = scanned_volumes.begin(); j != scanned_volumes.end(); j++) {
2098 if (0 == j->compare(disk_drive)) {
2099 volume_found = true;
2104 if (!volume_found) {
2105 scanned_volumes.push_back(disk_drive);
2106 _total_free_4k_blocks += i->blocks;
2111 if (0 == _total_free_4k_blocks) {
2112 strncpy (disk_drive, path().c_str(), 3);
2115 if (0 != (GetDiskFreeSpace(disk_drive, &nSectorsPerCluster, &nBytesPerSector, &nFreeClusters, &nTotalClusters)))
2117 int64_t nBytesPerCluster = nBytesPerSector * nSectorsPerCluster;
2118 int64_t nFreeBytes = nBytesPerCluster * (int64_t)nFreeClusters;
2119 _total_free_4k_blocks = (uint32_t)(nFreeBytes / 4096);
2126 Session::get_best_session_directory_for_new_audio ()
2128 vector<space_and_path>::iterator i;
2129 string result = _session_dir->root_path();
2131 /* handle common case without system calls */
2133 if (session_dirs.size() == 1) {
2137 /* OK, here's the algorithm we're following here:
2139 We want to select which directory to use for
2140 the next file source to be created. Ideally,
2141 we'd like to use a round-robin process so as to
2142 get maximum performance benefits from splitting
2143 the files across multiple disks.
2145 However, in situations without much diskspace, an
2146 RR approach may end up filling up a filesystem
2147 with new files while others still have space.
2148 Its therefore important to pay some attention to
2149 the freespace in the filesystem holding each
2150 directory as well. However, if we did that by
2151 itself, we'd keep creating new files in the file
2152 system with the most space until it was as full
2153 as all others, thus negating any performance
2154 benefits of this RAID-1 like approach.
2156 So, we use a user-configurable space threshold. If
2157 there are at least 2 filesystems with more than this
2158 much space available, we use RR selection between them.
2159 If not, then we pick the filesystem with the most space.
2161 This gets a good balance between the two
2165 refresh_disk_space ();
2167 int free_enough = 0;
2169 for (i = session_dirs.begin(); i != session_dirs.end(); ++i) {
2170 if ((*i).blocks * 4096 >= Config->get_disk_choice_space_threshold()) {
2175 if (free_enough >= 2) {
2176 /* use RR selection process, ensuring that the one
2180 i = last_rr_session_dir;
2183 if (++i == session_dirs.end()) {
2184 i = session_dirs.begin();
2187 if ((*i).blocks * 4096 >= Config->get_disk_choice_space_threshold()) {
2188 SessionDirectory sdir(i->path);
2189 if (sdir.create ()) {
2191 last_rr_session_dir = i;
2196 } while (i != last_rr_session_dir);
2200 /* pick FS with the most freespace (and that
2201 seems to actually work ...)
2204 vector<space_and_path> sorted;
2205 space_and_path_ascending_cmp cmp;
2207 sorted = session_dirs;
2208 sort (sorted.begin(), sorted.end(), cmp);
2210 for (i = sorted.begin(); i != sorted.end(); ++i) {
2211 SessionDirectory sdir(i->path);
2212 if (sdir.create ()) {
2214 last_rr_session_dir = i;
2224 Session::automation_dir () const
2226 return Glib::build_filename (_path, "automation");
2230 Session::analysis_dir () const
2232 return Glib::build_filename (_path, "analysis");
2236 Session::plugins_dir () const
2238 return Glib::build_filename (_path, "plugins");
2242 Session::externals_dir () const
2244 return Glib::build_filename (_path, "externals");
2248 Session::load_bundles (XMLNode const & node)
2250 XMLNodeList nlist = node.children();
2251 XMLNodeConstIterator niter;
2255 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2256 if ((*niter)->name() == "InputBundle") {
2257 add_bundle (boost::shared_ptr<UserBundle> (new UserBundle (**niter, true)));
2258 } else if ((*niter)->name() == "OutputBundle") {
2259 add_bundle (boost::shared_ptr<UserBundle> (new UserBundle (**niter, false)));
2261 error << string_compose(_("Unknown node \"%1\" found in Bundles list from session file"), (*niter)->name()) << endmsg;
2270 Session::load_route_groups (const XMLNode& node, int version)
2272 XMLNodeList nlist = node.children();
2273 XMLNodeConstIterator niter;
2277 if (version >= 3000) {
2279 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2280 if ((*niter)->name() == "RouteGroup") {
2281 RouteGroup* rg = new RouteGroup (*this, "");
2282 add_route_group (rg);
2283 rg->set_state (**niter, version);
2287 } else if (version < 3000) {
2289 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2290 if ((*niter)->name() == "EditGroup" || (*niter)->name() == "MixGroup") {
2291 RouteGroup* rg = new RouteGroup (*this, "");
2292 add_route_group (rg);
2293 rg->set_state (**niter, version);
2302 state_file_filter (const string &str, void* /*arg*/)
2304 return (str.length() > strlen(statefile_suffix) &&
2305 str.find (statefile_suffix) == (str.length() - strlen (statefile_suffix)));
2309 remove_end(string state)
2311 string statename(state);
2313 string::size_type start,end;
2314 if ((start = statename.find_last_of (G_DIR_SEPARATOR)) != string::npos) {
2315 statename = statename.substr (start+1);
2318 if ((end = statename.rfind(statefile_suffix)) == string::npos) {
2319 end = statename.length();
2322 return string(statename.substr (0, end));
2326 Session::possible_states (string path)
2328 vector<string> states;
2329 find_files_matching_filter (states, path, state_file_filter, 0, false, false);
2331 transform(states.begin(), states.end(), states.begin(), remove_end);
2333 sort (states.begin(), states.end());
2339 Session::possible_states () const
2341 return possible_states(_path);
2345 Session::add_route_group (RouteGroup* g)
2347 _route_groups.push_back (g);
2348 route_group_added (g); /* EMIT SIGNAL */
2350 g->RouteAdded.connect_same_thread (*this, boost::bind (&Session::route_added_to_route_group, this, _1, _2));
2351 g->RouteRemoved.connect_same_thread (*this, boost::bind (&Session::route_removed_from_route_group, this, _1, _2));
2352 g->PropertyChanged.connect_same_thread (*this, boost::bind (&Session::route_group_property_changed, this, g));
2358 Session::remove_route_group (RouteGroup& rg)
2360 list<RouteGroup*>::iterator i;
2362 if ((i = find (_route_groups.begin(), _route_groups.end(), &rg)) != _route_groups.end()) {
2363 _route_groups.erase (i);
2366 route_group_removed (); /* EMIT SIGNAL */
2370 /** Set a new order for our route groups, without adding or removing any.
2371 * @param groups Route group list in the new order.
2374 Session::reorder_route_groups (list<RouteGroup*> groups)
2376 _route_groups = groups;
2378 route_groups_reordered (); /* EMIT SIGNAL */
2384 Session::route_group_by_name (string name)
2386 list<RouteGroup *>::iterator i;
2388 for (i = _route_groups.begin(); i != _route_groups.end(); ++i) {
2389 if ((*i)->name() == name) {
2397 Session::all_route_group() const
2399 return *_all_route_group;
2403 Session::add_commands (vector<Command*> const & cmds)
2405 for (vector<Command*>::const_iterator i = cmds.begin(); i != cmds.end(); ++i) {
2411 Session::begin_reversible_command (const string& name)
2413 begin_reversible_command (g_quark_from_string (name.c_str ()));
2416 /** Begin a reversible command using a GQuark to identify it.
2417 * begin_reversible_command() and commit_reversible_command() calls may be nested,
2418 * but there must be as many begin...()s as there are commit...()s.
2421 Session::begin_reversible_command (GQuark q)
2423 /* If nested begin/commit pairs are used, we create just one UndoTransaction
2424 to hold all the commands that are committed. This keeps the order of
2425 commands correct in the history.
2428 if (_current_trans == 0) {
2429 /* start a new transaction */
2430 assert (_current_trans_quarks.empty ());
2431 _current_trans = new UndoTransaction();
2432 _current_trans->set_name (g_quark_to_string (q));
2435 _current_trans_quarks.push_front (q);
2439 Session::abort_reversible_command ()
2441 if (_current_trans != 0) {
2442 _current_trans->clear();
2443 delete _current_trans;
2445 _current_trans_quarks.clear();
2450 Session::commit_reversible_command (Command *cmd)
2452 assert (_current_trans);
2453 assert (!_current_trans_quarks.empty ());
2458 _current_trans->add_command (cmd);
2461 _current_trans_quarks.pop_front ();
2463 if (!_current_trans_quarks.empty ()) {
2464 /* the transaction we're committing is not the top-level one */
2468 if (_current_trans->empty()) {
2469 /* no commands were added to the transaction, so just get rid of it */
2470 delete _current_trans;
2475 gettimeofday (&now, 0);
2476 _current_trans->set_timestamp (now);
2478 _history.add (_current_trans);
2483 accept_all_audio_files (const string& path, void* /*arg*/)
2485 if (!Glib::file_test (path, Glib::FILE_TEST_IS_REGULAR)) {
2489 if (!AudioFileSource::safe_audio_file_extension (path)) {
2497 accept_all_midi_files (const string& path, void* /*arg*/)
2499 if (!Glib::file_test (path, Glib::FILE_TEST_IS_REGULAR)) {
2503 return ((path.length() > 4 && path.find (".mid") != (path.length() - 4)) ||
2504 (path.length() > 4 && path.find (".smf") != (path.length() - 4)) ||
2505 (path.length() > 5 && path.find (".midi") != (path.length() - 5)));
2509 accept_all_state_files (const string& path, void* /*arg*/)
2511 if (!Glib::file_test (path, Glib::FILE_TEST_IS_REGULAR)) {
2515 std::string const statefile_ext (statefile_suffix);
2516 if (path.length() >= statefile_ext.length()) {
2517 return (0 == path.compare (path.length() - statefile_ext.length(), statefile_ext.length(), statefile_ext));
2524 Session::find_all_sources (string path, set<string>& result)
2529 if (!tree.read (path)) {
2533 if ((node = find_named_node (*tree.root(), "Sources")) == 0) {
2538 XMLNodeConstIterator niter;
2540 nlist = node->children();
2544 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2548 if ((prop = (*niter)->property (X_("type"))) == 0) {
2552 DataType type (prop->value());
2554 if ((prop = (*niter)->property (X_("name"))) == 0) {
2558 if (Glib::path_is_absolute (prop->value())) {
2559 /* external file, ignore */
2567 if (FileSource::find (*this, type, prop->value(), true, is_new, chan, found_path)) {
2568 result.insert (found_path);
2576 Session::find_all_sources_across_snapshots (set<string>& result, bool exclude_this_snapshot)
2578 vector<string> state_files;
2580 string this_snapshot_path;
2586 if (ripped[ripped.length()-1] == G_DIR_SEPARATOR) {
2587 ripped = ripped.substr (0, ripped.length() - 1);
2590 find_files_matching_filter (state_files, ripped, accept_all_state_files, (void *) 0, true, true);
2592 if (state_files.empty()) {
2597 this_snapshot_path = _path;
2598 this_snapshot_path += legalize_for_path (_current_snapshot_name);
2599 this_snapshot_path += statefile_suffix;
2601 for (vector<string>::iterator i = state_files.begin(); i != state_files.end(); ++i) {
2603 if (exclude_this_snapshot && *i == this_snapshot_path) {
2607 if (find_all_sources (*i, result) < 0) {
2615 struct RegionCounter {
2616 typedef std::map<PBD::ID,boost::shared_ptr<AudioSource> > AudioSourceList;
2617 AudioSourceList::iterator iter;
2618 boost::shared_ptr<Region> region;
2621 RegionCounter() : count (0) {}
2625 Session::ask_about_playlist_deletion (boost::shared_ptr<Playlist> p)
2627 boost::optional<int> r = AskAboutPlaylistDeletion (p);
2628 return r.get_value_or (1);
2632 Session::cleanup_regions ()
2634 bool removed = false;
2635 const RegionFactory::RegionMap& regions (RegionFactory::regions());
2637 for (RegionFactory::RegionMap::const_iterator i = regions.begin(); i != regions.end(); ++i) {
2639 uint32_t used = playlists->region_use_count (i->second);
2641 if (used == 0 && !i->second->automatic ()) {
2643 RegionFactory::map_remove (i->second);
2648 // re-check to remove parent references of compound regions
2649 for (RegionFactory::RegionMap::const_iterator i = regions.begin(); i != regions.end(); ++i) {
2650 if (!(i->second->whole_file() && i->second->max_source_level() > 0)) {
2653 assert(boost::dynamic_pointer_cast<PlaylistSource>(i->second->source (0)) != 0);
2654 if (0 == playlists->region_use_count (i->second)) {
2655 RegionFactory::map_remove (i->second);
2660 /* dump the history list */
2667 Session::cleanup_sources (CleanupReport& rep)
2669 // FIXME: needs adaptation to midi
2671 vector<boost::shared_ptr<Source> > dead_sources;
2674 vector<string> candidates;
2675 vector<string> unused;
2676 set<string> all_sources;
2685 _state_of_the_state = (StateOfTheState) (_state_of_the_state | InCleanup);
2687 /* consider deleting all unused playlists */
2689 if (playlists->maybe_delete_unused (boost::bind (Session::ask_about_playlist_deletion, _1))) {
2694 /* sync the "all regions" property of each playlist with its current state
2697 playlists->sync_all_regions_with_regions ();
2699 /* find all un-used sources */
2704 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ) {
2706 SourceMap::iterator tmp;
2711 /* do not bother with files that are zero size, otherwise we remove the current "nascent"
2715 if (!i->second->used() && (i->second->length(i->second->timeline_position() > 0))) {
2716 dead_sources.push_back (i->second);
2717 i->second->drop_references ();
2723 /* build a list of all the possible audio directories for the session */
2725 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
2726 SessionDirectory sdir ((*i).path);
2727 asp += sdir.sound_path();
2729 audio_path += asp.to_string();
2732 /* build a list of all the possible midi directories for the session */
2734 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
2735 SessionDirectory sdir ((*i).path);
2736 msp += sdir.midi_path();
2738 midi_path += msp.to_string();
2740 find_files_matching_filter (candidates, audio_path, accept_all_audio_files, (void *) 0, true, true);
2741 find_files_matching_filter (candidates, midi_path, accept_all_midi_files, (void *) 0, true, true);
2743 /* find all sources, but don't use this snapshot because the
2744 state file on disk still references sources we may have already
2748 find_all_sources_across_snapshots (all_sources, true);
2750 /* add our current source list
2753 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ) {
2754 boost::shared_ptr<FileSource> fs;
2755 SourceMap::iterator tmp = i;
2758 if ((fs = boost::dynamic_pointer_cast<FileSource> (i->second)) != 0) {
2760 if (!fs->is_stub()) {
2762 if (playlists->source_use_count (fs) != 0) {
2763 all_sources.insert (fs->path());
2766 /* we might not remove this source from disk, because it may be used
2767 by other snapshots, but its not being used in this version
2768 so lets get rid of it now, along with any representative regions
2772 RegionFactory::remove_regions_using_source (i->second);
2781 for (vector<string>::iterator x = candidates.begin(); x != candidates.end(); ++x) {
2786 for (set<string>::iterator i = all_sources.begin(); i != all_sources.end(); ++i) {
2788 tmppath1 = canonical_path (spath);
2789 tmppath2 = canonical_path ((*i));
2791 if (tmppath1 == tmppath2) {
2798 unused.push_back (spath);
2802 /* now try to move all unused files into the "dead" directory(ies) */
2804 for (vector<string>::iterator x = unused.begin(); x != unused.end(); ++x) {
2805 struct stat statbuf;
2809 /* don't move the file across filesystems, just
2810 stick it in the `dead_dir_name' directory
2811 on whichever filesystem it was already on.
2814 if ((*x).find ("/sounds/") != string::npos) {
2816 /* old school, go up 1 level */
2818 newpath = Glib::path_get_dirname (*x); // "sounds"
2819 newpath = Glib::path_get_dirname (newpath); // "session-name"
2823 /* new school, go up 4 levels */
2825 newpath = Glib::path_get_dirname (*x); // "audiofiles" or "midifiles"
2826 newpath = Glib::path_get_dirname (newpath); // "session-name"
2827 newpath = Glib::path_get_dirname (newpath); // "interchange"
2828 newpath = Glib::path_get_dirname (newpath); // "session-dir"
2831 newpath = Glib::build_filename (newpath, dead_dir_name);
2833 if (g_mkdir_with_parents (newpath.c_str(), 0755) < 0) {
2834 error << string_compose(_("Session: cannot create dead file folder \"%1\" (%2)"), newpath, strerror (errno)) << endmsg;
2838 newpath = Glib::build_filename (newpath, Glib::path_get_basename ((*x)));
2840 if (Glib::file_test (newpath, Glib::FILE_TEST_EXISTS)) {
2842 /* the new path already exists, try versioning */
2844 char buf[PATH_MAX+1];
2848 snprintf (buf, sizeof (buf), "%s.%d", newpath.c_str(), version);
2851 while (Glib::file_test (newpath_v.c_str(), Glib::FILE_TEST_EXISTS) && version < 999) {
2852 snprintf (buf, sizeof (buf), "%s.%d", newpath.c_str(), ++version);
2856 if (version == 999) {
2857 error << string_compose (_("there are already 1000 files with names like %1; versioning discontinued"),
2861 newpath = newpath_v;
2866 /* it doesn't exist, or we can't read it or something */
2870 stat ((*x).c_str(), &statbuf);
2872 if (::rename ((*x).c_str(), newpath.c_str()) != 0) {
2873 error << string_compose (_("cannot rename unused file source from %1 to %2 (%3)"),
2874 (*x), newpath, strerror (errno))
2879 /* see if there an easy to find peakfile for this file, and remove it.
2882 string base = basename_nosuffix (*x);
2883 base += "%A"; /* this is what we add for the channel suffix of all native files,
2884 or for the first channel of embedded files. it will miss
2885 some peakfiles for other channels
2887 string peakpath = peak_path (base);
2889 if (Glib::file_test (peakpath.c_str(), Glib::FILE_TEST_EXISTS)) {
2890 if (::g_unlink (peakpath.c_str()) != 0) {
2891 error << string_compose (_("cannot remove peakfile %1 for %2 (%3)"),
2892 peakpath, _path, strerror (errno))
2894 /* try to back out */
2895 ::rename (newpath.c_str(), _path.c_str());
2900 rep.paths.push_back (*x);
2901 rep.space += statbuf.st_size;
2904 /* dump the history list */
2908 /* save state so we don't end up a session file
2909 referring to non-existent sources.
2916 _state_of_the_state = (StateOfTheState) (_state_of_the_state & ~InCleanup);
2922 Session::cleanup_trash_sources (CleanupReport& rep)
2924 // FIXME: needs adaptation for MIDI
2926 vector<space_and_path>::iterator i;
2932 for (i = session_dirs.begin(); i != session_dirs.end(); ++i) {
2934 dead_dir = Glib::build_filename ((*i).path, dead_dir_name);
2936 clear_directory (dead_dir, &rep.space, &rep.paths);
2943 Session::set_dirty ()
2945 /* never mark session dirty during loading */
2947 if (_state_of_the_state & Loading) {
2951 bool was_dirty = dirty();
2953 _state_of_the_state = StateOfTheState (_state_of_the_state | Dirty);
2957 DirtyChanged(); /* EMIT SIGNAL */
2963 Session::set_clean ()
2965 bool was_dirty = dirty();
2967 _state_of_the_state = Clean;
2971 DirtyChanged(); /* EMIT SIGNAL */
2976 Session::set_deletion_in_progress ()
2978 _state_of_the_state = StateOfTheState (_state_of_the_state | Deletion);
2982 Session::clear_deletion_in_progress ()
2984 _state_of_the_state = StateOfTheState (_state_of_the_state & (~Deletion));
2988 Session::add_controllable (boost::shared_ptr<Controllable> c)
2990 /* this adds a controllable to the list managed by the Session.
2991 this is a subset of those managed by the Controllable class
2992 itself, and represents the only ones whose state will be saved
2993 as part of the session.
2996 Glib::Threads::Mutex::Lock lm (controllables_lock);
2997 controllables.insert (c);
3000 struct null_deleter { void operator()(void const *) const {} };
3003 Session::remove_controllable (Controllable* c)
3005 if (_state_of_the_state & Deletion) {
3009 Glib::Threads::Mutex::Lock lm (controllables_lock);
3011 Controllables::iterator x = controllables.find (boost::shared_ptr<Controllable>(c, null_deleter()));
3013 if (x != controllables.end()) {
3014 controllables.erase (x);
3018 boost::shared_ptr<Controllable>
3019 Session::controllable_by_id (const PBD::ID& id)
3021 Glib::Threads::Mutex::Lock lm (controllables_lock);
3023 for (Controllables::iterator i = controllables.begin(); i != controllables.end(); ++i) {
3024 if ((*i)->id() == id) {
3029 return boost::shared_ptr<Controllable>();
3032 boost::shared_ptr<Controllable>
3033 Session::controllable_by_descriptor (const ControllableDescriptor& desc)
3035 boost::shared_ptr<Controllable> c;
3036 boost::shared_ptr<Route> r;
3038 switch (desc.top_level_type()) {
3039 case ControllableDescriptor::NamedRoute:
3041 std::string str = desc.top_level_name();
3042 if (str == "Master" || str == "master") {
3044 } else if (str == "control" || str == "listen") {
3047 r = route_by_name (desc.top_level_name());
3052 case ControllableDescriptor::RemoteControlID:
3053 r = route_by_remote_id (desc.rid());
3061 switch (desc.subtype()) {
3062 case ControllableDescriptor::Gain:
3063 c = r->gain_control ();
3066 case ControllableDescriptor::Solo:
3067 c = r->solo_control();
3070 case ControllableDescriptor::Mute:
3071 c = r->mute_control();
3074 case ControllableDescriptor::Recenable:
3076 boost::shared_ptr<Track> t = boost::dynamic_pointer_cast<Track>(r);
3079 c = t->rec_enable_control ();
3084 case ControllableDescriptor::PanDirection:
3086 c = r->pannable()->pan_azimuth_control;
3090 case ControllableDescriptor::PanWidth:
3092 c = r->pannable()->pan_width_control;
3096 case ControllableDescriptor::PanElevation:
3098 c = r->pannable()->pan_elevation_control;
3102 case ControllableDescriptor::Balance:
3103 /* XXX simple pan control */
3106 case ControllableDescriptor::PluginParameter:
3108 uint32_t plugin = desc.target (0);
3109 uint32_t parameter_index = desc.target (1);
3111 /* revert to zero based counting */
3117 if (parameter_index > 0) {
3121 boost::shared_ptr<Processor> p = r->nth_plugin (plugin);
3124 c = boost::dynamic_pointer_cast<ARDOUR::AutomationControl>(
3125 p->control(Evoral::Parameter(PluginAutomation, 0, parameter_index)));
3130 case ControllableDescriptor::SendGain:
3132 uint32_t send = desc.target (0);
3134 /* revert to zero-based counting */
3140 boost::shared_ptr<Processor> p = r->nth_send (send);
3143 boost::shared_ptr<Send> s = boost::dynamic_pointer_cast<Send>(p);
3144 boost::shared_ptr<Amp> a = s->amp();
3147 c = s->amp()->gain_control();
3154 /* relax and return a null pointer */
3162 Session::add_instant_xml (XMLNode& node, bool write_to_config)
3165 Stateful::add_instant_xml (node, _path);
3168 if (write_to_config) {
3169 Config->add_instant_xml (node);
3174 Session::instant_xml (const string& node_name)
3176 return Stateful::instant_xml (node_name, _path);
3180 Session::save_history (string snapshot_name)
3188 if (!Config->get_save_history() || Config->get_saved_history_depth() < 0 ||
3189 (_history.undo_depth() == 0 && _history.redo_depth() == 0)) {
3193 if (snapshot_name.empty()) {
3194 snapshot_name = _current_snapshot_name;
3197 const string history_filename = legalize_for_path (snapshot_name) + history_suffix;
3198 const string backup_filename = history_filename + backup_suffix;
3199 const std::string xml_path(Glib::build_filename (_session_dir->root_path(), history_filename));
3200 const std::string backup_path(Glib::build_filename (_session_dir->root_path(), backup_filename));
3202 if (Glib::file_test (xml_path, Glib::FILE_TEST_EXISTS)) {
3203 if (::g_rename (xml_path.c_str(), backup_path.c_str()) != 0) {
3204 error << _("could not backup old history file, current history not saved") << endmsg;
3209 tree.set_root (&_history.get_state (Config->get_saved_history_depth()));
3211 if (!tree.write (xml_path))
3213 error << string_compose (_("history could not be saved to %1"), xml_path) << endmsg;
3215 if (g_remove (xml_path.c_str()) != 0) {
3216 error << string_compose(_("Could not remove history file at path \"%1\" (%2)"),
3217 xml_path, g_strerror (errno)) << endmsg;
3219 if (::g_rename (backup_path.c_str(), xml_path.c_str()) != 0) {
3220 error << string_compose (_("could not restore history file from backup %1 (%2)"),
3221 backup_path, g_strerror (errno)) << endmsg;
3231 Session::restore_history (string snapshot_name)
3235 if (snapshot_name.empty()) {
3236 snapshot_name = _current_snapshot_name;
3239 const std::string xml_filename = legalize_for_path (snapshot_name) + history_suffix;
3240 const std::string xml_path(Glib::build_filename (_session_dir->root_path(), xml_filename));
3242 info << "Loading history from " << xml_path << endmsg;
3244 if (!Glib::file_test (xml_path, Glib::FILE_TEST_EXISTS)) {
3245 info << string_compose (_("%1: no history file \"%2\" for this session."),
3246 _name, xml_path) << endmsg;
3250 if (!tree.read (xml_path)) {
3251 error << string_compose (_("Could not understand session history file \"%1\""),
3252 xml_path) << endmsg;
3259 for (XMLNodeConstIterator it = tree.root()->children().begin(); it != tree.root()->children().end(); it++) {
3262 UndoTransaction* ut = new UndoTransaction ();
3265 ut->set_name(t->property("name")->value());
3266 stringstream ss(t->property("tv-sec")->value());
3268 ss.str(t->property("tv-usec")->value());
3270 ut->set_timestamp(tv);
3272 for (XMLNodeConstIterator child_it = t->children().begin();
3273 child_it != t->children().end(); child_it++)
3275 XMLNode *n = *child_it;
3278 if (n->name() == "MementoCommand" ||
3279 n->name() == "MementoUndoCommand" ||
3280 n->name() == "MementoRedoCommand") {
3282 if ((c = memento_command_factory(n))) {
3286 } else if (n->name() == "NoteDiffCommand") {
3287 PBD::ID id (n->property("midi-source")->value());
3288 boost::shared_ptr<MidiSource> midi_source =
3289 boost::dynamic_pointer_cast<MidiSource, Source>(source_by_id(id));
3291 ut->add_command (new MidiModel::NoteDiffCommand(midi_source->model(), *n));
3293 error << _("Failed to downcast MidiSource for NoteDiffCommand") << endmsg;
3296 } else if (n->name() == "SysExDiffCommand") {
3298 PBD::ID id (n->property("midi-source")->value());
3299 boost::shared_ptr<MidiSource> midi_source =
3300 boost::dynamic_pointer_cast<MidiSource, Source>(source_by_id(id));
3302 ut->add_command (new MidiModel::SysExDiffCommand (midi_source->model(), *n));
3304 error << _("Failed to downcast MidiSource for SysExDiffCommand") << endmsg;
3307 } else if (n->name() == "PatchChangeDiffCommand") {
3309 PBD::ID id (n->property("midi-source")->value());
3310 boost::shared_ptr<MidiSource> midi_source =
3311 boost::dynamic_pointer_cast<MidiSource, Source>(source_by_id(id));
3313 ut->add_command (new MidiModel::PatchChangeDiffCommand (midi_source->model(), *n));
3315 error << _("Failed to downcast MidiSource for PatchChangeDiffCommand") << endmsg;
3318 } else if (n->name() == "StatefulDiffCommand") {
3319 if ((c = stateful_diff_command_factory (n))) {
3320 ut->add_command (c);
3323 error << string_compose(_("Couldn't figure out how to make a Command out of a %1 XMLNode."), n->name()) << endmsg;
3334 Session::config_changed (std::string p, bool ours)
3340 if (p == "seamless-loop") {
3342 } else if (p == "rf-speed") {
3344 } else if (p == "auto-loop") {
3346 } else if (p == "auto-input") {
3348 if (Config->get_monitoring_model() == HardwareMonitoring && transport_rolling()) {
3349 /* auto-input only makes a difference if we're rolling */
3350 set_track_monitor_input_status (!config.get_auto_input());
3353 } else if (p == "punch-in") {
3357 if ((location = _locations->auto_punch_location()) != 0) {
3359 if (config.get_punch_in ()) {
3360 replace_event (SessionEvent::PunchIn, location->start());
3362 remove_event (location->start(), SessionEvent::PunchIn);
3366 } else if (p == "punch-out") {
3370 if ((location = _locations->auto_punch_location()) != 0) {
3372 if (config.get_punch_out()) {
3373 replace_event (SessionEvent::PunchOut, location->end());
3375 clear_events (SessionEvent::PunchOut);
3379 } else if (p == "edit-mode") {
3381 Glib::Threads::Mutex::Lock lm (playlists->lock);
3383 for (SessionPlaylists::List::iterator i = playlists->playlists.begin(); i != playlists->playlists.end(); ++i) {
3384 (*i)->set_edit_mode (Config->get_edit_mode ());
3387 } else if (p == "use-video-sync") {
3389 waiting_for_sync_offset = config.get_use_video_sync();
3391 } else if (p == "mmc-control") {
3393 //poke_midi_thread ();
3395 } else if (p == "mmc-device-id" || p == "mmc-receive-id" || p == "mmc-receive-device-id") {
3397 _mmc->set_receive_device_id (Config->get_mmc_receive_device_id());
3399 } else if (p == "mmc-send-id" || p == "mmc-send-device-id") {
3401 _mmc->set_send_device_id (Config->get_mmc_send_device_id());
3403 } else if (p == "midi-control") {
3405 //poke_midi_thread ();
3407 } else if (p == "raid-path") {
3409 setup_raid_path (config.get_raid_path());
3411 } else if (p == "timecode-format") {
3415 } else if (p == "video-pullup") {
3419 } else if (p == "seamless-loop") {
3421 if (play_loop && transport_rolling()) {
3422 // to reset diskstreams etc
3423 request_play_loop (true);
3426 } else if (p == "rf-speed") {
3428 cumulative_rf_motion = 0;
3431 } else if (p == "click-sound") {
3433 setup_click_sounds (1);
3435 } else if (p == "click-emphasis-sound") {
3437 setup_click_sounds (-1);
3439 } else if (p == "clicking") {
3441 if (Config->get_clicking()) {
3442 if (_click_io && click_data) { // don't require emphasis data
3449 } else if (p == "click-gain") {
3452 _click_gain->set_gain (Config->get_click_gain(), this);
3455 } else if (p == "send-mtc") {
3457 if (Config->get_send_mtc ()) {
3458 /* mark us ready to send */
3459 next_quarter_frame_to_send = 0;
3462 } else if (p == "send-mmc") {
3464 _mmc->enable_send (Config->get_send_mmc ());
3466 } else if (p == "midi-feedback") {
3468 session_midi_feedback = Config->get_midi_feedback();
3470 } else if (p == "jack-time-master") {
3472 engine().reset_timebase ();
3474 } else if (p == "native-file-header-format") {
3476 if (!first_file_header_format_reset) {
3477 reset_native_file_format ();
3480 first_file_header_format_reset = false;
3482 } else if (p == "native-file-data-format") {
3484 if (!first_file_data_format_reset) {
3485 reset_native_file_format ();
3488 first_file_data_format_reset = false;
3490 } else if (p == "external-sync") {
3491 if (!config.get_external_sync()) {
3492 drop_sync_source ();
3494 switch_to_sync_source (Config->get_sync_source());
3496 } else if (p == "denormal-model") {
3498 } else if (p == "history-depth") {
3499 set_history_depth (Config->get_history_depth());
3500 } else if (p == "remote-model") {
3501 /* XXX DO SOMETHING HERE TO TELL THE GUI THAT WE NEED
3504 } else if (p == "initial-program-change") {
3506 if (_mmc->output_port() && Config->get_initial_program_change() >= 0) {
3509 buf[0] = MIDI::program; // channel zero by default
3510 buf[1] = (Config->get_initial_program_change() & 0x7f);
3512 _mmc->output_port()->midimsg (buf, sizeof (buf), 0);
3514 } else if (p == "solo-mute-override") {
3515 // catch_up_on_solo_mute_override ();
3516 } else if (p == "listen-position" || p == "pfl-position") {
3517 listen_position_changed ();
3518 } else if (p == "solo-control-is-listen-control") {
3519 solo_control_mode_changed ();
3520 } else if (p == "solo-mute-gain") {
3521 _solo_cut_control->Changed();
3522 } else if (p == "timecode-offset" || p == "timecode-offset-negative") {
3523 last_timecode_valid = false;
3524 } else if (p == "playback-buffer-seconds") {
3525 AudioSource::allocate_working_buffers (frame_rate());
3526 } else if (p == "ltc-source-port") {
3527 reconnect_ltc_input ();
3528 } else if (p == "ltc-sink-port") {
3529 reconnect_ltc_output ();
3530 } else if (p == "timecode-generator-offset") {
3531 ltc_tx_parse_offset();
3538 Session::set_history_depth (uint32_t d)
3540 _history.set_depth (d);
3544 Session::load_diskstreams_2X (XMLNode const & node, int)
3547 XMLNodeConstIterator citer;
3549 clist = node.children();
3551 for (citer = clist.begin(); citer != clist.end(); ++citer) {
3554 /* diskstreams added automatically by DiskstreamCreated handler */
3555 if ((*citer)->name() == "AudioDiskstream" || (*citer)->name() == "DiskStream") {
3556 boost::shared_ptr<AudioDiskstream> dsp (new AudioDiskstream (*this, **citer));
3557 _diskstreams_2X.push_back (dsp);
3559 error << _("Session: unknown diskstream type in XML") << endmsg;
3563 catch (failed_constructor& err) {
3564 error << _("Session: could not load diskstream via XML state") << endmsg;
3572 /** Connect things to the MMC object */
3574 Session::setup_midi_machine_control ()
3576 _mmc = new MIDI::MachineControl;
3577 _mmc->set_ports (_midi_ports->mmc_input_port(), _midi_ports->mmc_output_port());
3579 _mmc->Play.connect_same_thread (*this, boost::bind (&Session::mmc_deferred_play, this, _1));
3580 _mmc->DeferredPlay.connect_same_thread (*this, boost::bind (&Session::mmc_deferred_play, this, _1));
3581 _mmc->Stop.connect_same_thread (*this, boost::bind (&Session::mmc_stop, this, _1));
3582 _mmc->FastForward.connect_same_thread (*this, boost::bind (&Session::mmc_fast_forward, this, _1));
3583 _mmc->Rewind.connect_same_thread (*this, boost::bind (&Session::mmc_rewind, this, _1));
3584 _mmc->Pause.connect_same_thread (*this, boost::bind (&Session::mmc_pause, this, _1));
3585 _mmc->RecordPause.connect_same_thread (*this, boost::bind (&Session::mmc_record_pause, this, _1));
3586 _mmc->RecordStrobe.connect_same_thread (*this, boost::bind (&Session::mmc_record_strobe, this, _1));
3587 _mmc->RecordExit.connect_same_thread (*this, boost::bind (&Session::mmc_record_exit, this, _1));
3588 _mmc->Locate.connect_same_thread (*this, boost::bind (&Session::mmc_locate, this, _1, _2));
3589 _mmc->Step.connect_same_thread (*this, boost::bind (&Session::mmc_step, this, _1, _2));
3590 _mmc->Shuttle.connect_same_thread (*this, boost::bind (&Session::mmc_shuttle, this, _1, _2, _3));
3591 _mmc->TrackRecordStatusChange.connect_same_thread (*this, boost::bind (&Session::mmc_record_enable, this, _1, _2, _3));
3593 /* also handle MIDI SPP because its so common */
3595 _mmc->SPPStart.connect_same_thread (*this, boost::bind (&Session::spp_start, this));
3596 _mmc->SPPContinue.connect_same_thread (*this, boost::bind (&Session::spp_continue, this));
3597 _mmc->SPPStop.connect_same_thread (*this, boost::bind (&Session::spp_stop, this));
3600 boost::shared_ptr<Controllable>
3601 Session::solo_cut_control() const
3603 /* the solo cut control is a bit of an anomaly, at least as of Febrary 2011. There are no other
3604 controls in Ardour that currently get presented to the user in the GUI that require
3605 access as a Controllable and are also NOT owned by some SessionObject (e.g. Route, or MonitorProcessor).
3607 its actually an RCConfiguration parameter, so we use a ProxyControllable to wrap
3608 it up as a Controllable. Changes to the Controllable will just map back to the RCConfiguration
3612 return _solo_cut_control;
3616 Session::rename (const std::string& new_name)
3618 string legal_name = legalize_for_path (new_name);
3624 string const old_sources_root = _session_dir->sources_root();
3629 * interchange subdirectory
3633 * Backup files are left unchanged and not renamed.
3636 /* pass one: not 100% safe check that the new directory names don't
3640 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
3645 /* this is a stupid hack because Glib::path_get_dirname() is
3646 * lexical-only, and so passing it /a/b/c/ gives a different
3647 * result than passing it /a/b/c ...
3650 if (oldstr[oldstr.length()-1] == G_DIR_SEPARATOR) {
3651 oldstr = oldstr.substr (0, oldstr.length() - 1);
3654 string base = Glib::path_get_dirname (oldstr);
3655 string p = Glib::path_get_basename (oldstr);
3657 newstr = Glib::build_filename (base, legal_name);
3659 if (Glib::file_test (newstr, Glib::FILE_TEST_EXISTS)) {
3666 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
3671 /* this is a stupid hack because Glib::path_get_dirname() is
3672 * lexical-only, and so passing it /a/b/c/ gives a different
3673 * result than passing it /a/b/c ...
3676 if (oldstr[oldstr.length()-1] == G_DIR_SEPARATOR) {
3677 oldstr = oldstr.substr (0, oldstr.length() - 1);
3680 string base = Glib::path_get_dirname (oldstr);
3681 string p = Glib::path_get_basename (oldstr);
3683 newstr = Glib::build_filename (base, legal_name);
3685 cerr << "Rename " << oldstr << " => " << newstr << endl;
3687 if (::g_rename (oldstr.c_str(), newstr.c_str()) != 0) {
3688 error << string_compose (_("renaming %s as %2 failed (%3)"), oldstr, newstr, g_strerror (errno)) << endmsg;
3693 (*_session_dir) = newstr;
3698 /* directory below interchange */
3700 v.push_back (newstr);
3701 v.push_back (interchange_dir_name);
3704 oldstr = Glib::build_filename (v);
3707 v.push_back (newstr);
3708 v.push_back (interchange_dir_name);
3709 v.push_back (legal_name);
3711 newstr = Glib::build_filename (v);
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) + statefile_suffix;
3724 newstr= Glib::build_filename (newpath, legal_name) + statefile_suffix;
3726 cerr << "Rename " << oldstr << " => " << newstr << endl;
3728 if (::g_rename (oldstr.c_str(), newstr.c_str()) != 0) {
3729 error << string_compose (_("renaming %s as %2 failed (%3)"), oldstr, newstr, g_strerror (errno)) << endmsg;
3736 oldstr = Glib::build_filename (newpath, _current_snapshot_name) + history_suffix;
3738 if (Glib::file_test (oldstr, Glib::FILE_TEST_EXISTS)) {
3739 newstr = Glib::build_filename (newpath, legal_name) + history_suffix;
3741 cerr << "Rename " << oldstr << " => " << newstr << endl;
3743 if (::g_rename (oldstr.c_str(), newstr.c_str()) != 0) {
3744 error << string_compose (_("renaming %s as %2 failed (%3)"), oldstr, newstr, g_strerror (errno)) << endmsg;
3749 /* update file source paths */
3751 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ++i) {
3752 boost::shared_ptr<FileSource> fs = boost::dynamic_pointer_cast<FileSource> (i->second);
3754 string p = fs->path ();
3755 boost::replace_all (p, old_sources_root, _session_dir->sources_root());
3760 /* remove old name from recent sessions */
3762 remove_recent_sessions (_path);
3765 _current_snapshot_name = new_name;
3768 /* re-add directory separator - reverse hack to oldstr above */
3769 if (_path[_path.length()-1] != G_DIR_SEPARATOR) {
3770 _path += G_DIR_SEPARATOR;
3775 /* save state again to get everything just right */
3777 save_state (_current_snapshot_name);
3780 /* add to recent sessions */
3782 store_recent_sessions (new_name, _path);
3788 Session::get_session_info_from_path (XMLTree& tree, const string& xmlpath)
3790 if (!Glib::file_test (xmlpath, Glib::FILE_TEST_EXISTS)) {
3794 if (!tree.read (xmlpath)) {
3802 Session::get_info_from_path (const string& xmlpath, float& sample_rate, SampleFormat& data_format)
3805 bool found_sr = false;
3806 bool found_data_format = false;
3808 if (get_session_info_from_path (tree, xmlpath)) {
3814 const XMLProperty* prop;
3815 if ((prop = tree.root()->property (X_("sample-rate"))) != 0) {
3816 sample_rate = atoi (prop->value());
3820 const XMLNodeList& children (tree.root()->children());
3821 for (XMLNodeList::const_iterator c = children.begin(); c != children.end(); ++c) {
3822 const XMLNode* child = *c;
3823 if (child->name() == "Config") {
3824 const XMLNodeList& options (child->children());
3825 for (XMLNodeList::const_iterator oc = options.begin(); oc != options.end(); ++oc) {
3826 const XMLNode* option = *oc;
3827 const XMLProperty* name = option->property("name");
3833 if (name->value() == "native-file-data-format") {
3834 const XMLProperty* value = option->property ("value");
3836 SampleFormat fmt = (SampleFormat) string_2_enum (option->property ("value")->value(), fmt);
3838 found_data_format = true;
3844 if (found_data_format) {
3849 return !(found_sr && found_data_format); // zero if they are both found
3852 typedef std::vector<boost::shared_ptr<FileSource> > SeveralFileSources;
3853 typedef std::map<std::string,SeveralFileSources> SourcePathMap;
3856 Session::bring_all_sources_into_session (boost::function<void(uint32_t,uint32_t,string)> callback)
3860 SourcePathMap source_path_map;
3862 boost::shared_ptr<AudioFileSource> afs;
3867 Glib::Threads::Mutex::Lock lm (source_lock);
3869 cerr << " total sources = " << sources.size();
3871 for (SourceMap::const_iterator i = sources.begin(); i != sources.end(); ++i) {
3872 boost::shared_ptr<FileSource> fs = boost::dynamic_pointer_cast<FileSource> (i->second);
3878 if (fs->within_session()) {
3879 cerr << "skip " << fs->name() << endl;
3883 if (source_path_map.find (fs->path()) != source_path_map.end()) {
3884 source_path_map[fs->path()].push_back (fs);
3886 SeveralFileSources v;
3888 source_path_map.insert (make_pair (fs->path(), v));
3894 cerr << " fsources = " << total << endl;
3896 for (SourcePathMap::iterator i = source_path_map.begin(); i != source_path_map.end(); ++i) {
3898 /* tell caller where we are */
3900 string old_path = i->first;
3902 callback (n, total, old_path);
3904 cerr << old_path << endl;
3908 switch (i->second.front()->type()) {
3909 case DataType::AUDIO:
3910 new_path = new_audio_source_path_for_embedded (old_path);
3913 case DataType::MIDI:
3917 cerr << "Move " << old_path << " => " << new_path << endl;
3919 if (!copy_file (old_path, new_path)) {
3920 cerr << "failed !\n";
3924 /* make sure we stop looking in the external
3925 dir/folder. Remember, this is an all-or-nothing
3926 operations, it doesn't merge just some files.
3928 remove_dir_from_search_path (Glib::path_get_dirname (old_path), i->second.front()->type());
3930 for (SeveralFileSources::iterator f = i->second.begin(); f != i->second.end(); ++f) {
3931 (*f)->set_path (new_path);
3936 save_state ("", false, false);