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 */
241 _tempo_map = new TempoMap (_current_frame_rate);
242 _tempo_map->PropertyChanged.connect_same_thread (*this, boost::bind (&Session::tempo_map_changed, this, _1));
244 /* MidiClock requires a tempo map */
246 midi_clock = new MidiClockTicker ();
247 midi_clock->set_session (this);
249 /* crossfades require sample rate knowledge */
251 SndFileSource::setup_standard_crossfades (*this, frame_rate());
252 _engine.GraphReordered.connect_same_thread (*this, boost::bind (&Session::graph_reordered, this));
254 AudioDiskstream::allocate_working_buffers();
255 refresh_disk_space ();
257 /* we're finally ready to call set_state() ... all objects have
258 * been created, the engine is running.
262 if (set_state (*state_tree->root(), Stateful::loading_state_version)) {
266 // set_state() will call setup_raid_path(), but if it's a new session we need
267 // to call setup_raid_path() here.
268 setup_raid_path (_path);
273 boost::function<void (std::string)> ff (boost::bind (&Session::config_changed, this, _1, false));
274 boost::function<void (std::string)> ft (boost::bind (&Session::config_changed, this, _1, true));
276 Config->map_parameters (ff);
277 config.map_parameters (ft);
279 /* Reset all panners */
281 Delivery::reset_panners ();
283 /* this will cause the CPM to instantiate any protocols that are in use
284 * (or mandatory), which will pass it this Session, and then call
285 * set_state() on each instantiated protocol to match stored state.
288 ControlProtocolManager::instance().set_session (this);
290 /* This must be done after the ControlProtocolManager set_session above,
291 as it will set states for ports which the ControlProtocolManager creates.
294 // XXX set state of MIDI::Port's
295 // MidiPortManager::instance()->set_port_states (Config->midi_port_states ());
297 /* And this must be done after the MIDI::Manager::set_port_states as
298 * it will try to make connections whose details are loaded by set_port_states.
303 /* Let control protocols know that we are now all connected, so they
304 * could start talking to surfaces if they want to.
307 ControlProtocolManager::instance().midi_connectivity_established ();
309 if (_is_new && !no_auto_connect()) {
310 Glib::Threads::Mutex::Lock lm (AudioEngine::instance()->process_lock());
311 auto_connect_master_bus ();
314 _state_of_the_state = StateOfTheState (_state_of_the_state & ~(CannotSave|Dirty));
316 /* update latencies */
318 initialize_latencies ();
320 _locations->added.connect_same_thread (*this, boost::bind (&Session::location_added, this, _1));
321 _locations->removed.connect_same_thread (*this, boost::bind (&Session::location_removed, this, _1));
322 _locations->changed.connect_same_thread (*this, boost::bind (&Session::locations_changed, this));
324 } catch (AudioEngine::PortRegistrationFailure& err) {
325 /* handle this one in a different way than all others, so that its clear what happened */
326 error << err.what() << endmsg;
332 BootMessage (_("Reset Remote Controls"));
334 // send_full_time_code (0);
335 _engine.transport_locate (0);
337 send_immediate_mmc (MIDI::MachineControlCommand (MIDI::MachineControl::cmdMmcReset));
338 send_immediate_mmc (MIDI::MachineControlCommand (Timecode::Time ()));
340 MIDI::Name::MidiPatchManager::instance().set_session (this);
343 /* initial program change will be delivered later; see ::config_changed() */
345 _state_of_the_state = Clean;
347 Port::set_connecting_blocked (false);
349 DirtyChanged (); /* EMIT SIGNAL */
353 } else if (state_was_pending) {
355 remove_pending_capture_state ();
356 state_was_pending = false;
363 Session::raid_path () const
365 Searchpath raid_search_path;
367 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
368 raid_search_path += (*i).path;
371 return raid_search_path.to_string ();
375 Session::setup_raid_path (string path)
384 session_dirs.clear ();
386 Searchpath search_path(path);
387 Searchpath sound_search_path;
388 Searchpath midi_search_path;
390 for (Searchpath::const_iterator i = search_path.begin(); i != search_path.end(); ++i) {
392 sp.blocks = 0; // not needed
393 session_dirs.push_back (sp);
395 SessionDirectory sdir(sp.path);
397 sound_search_path += sdir.sound_path ();
398 midi_search_path += sdir.midi_path ();
401 // reset the round-robin soundfile path thingie
402 last_rr_session_dir = session_dirs.begin();
406 Session::path_is_within_session (const std::string& path)
408 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
409 if (PBD::path_is_within (i->path, path)) {
417 Session::ensure_subdirs ()
421 dir = session_directory().peak_path();
423 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
424 error << string_compose(_("Session: cannot create session peakfile folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
428 dir = session_directory().sound_path();
430 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
431 error << string_compose(_("Session: cannot create session sounds dir \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
435 dir = session_directory().midi_path();
437 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
438 error << string_compose(_("Session: cannot create session midi dir \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
442 dir = session_directory().dead_path();
444 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
445 error << string_compose(_("Session: cannot create session dead sounds folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
449 dir = session_directory().export_path();
451 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
452 error << string_compose(_("Session: cannot create session export folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
456 dir = analysis_dir ();
458 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
459 error << string_compose(_("Session: cannot create session analysis folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
463 dir = plugins_dir ();
465 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
466 error << string_compose(_("Session: cannot create session plugins folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
470 dir = externals_dir ();
472 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
473 error << string_compose(_("Session: cannot create session externals folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
480 /** @param session_template directory containing session template, or empty.
481 * Caller must not hold process lock.
484 Session::create (const string& session_template, BusProfile* bus_profile)
486 if (g_mkdir_with_parents (_path.c_str(), 0755) < 0) {
487 error << string_compose(_("Session: cannot create session folder \"%1\" (%2)"), _path, strerror (errno)) << endmsg;
491 if (ensure_subdirs ()) {
495 _writable = exists_and_writable (_path);
497 if (!session_template.empty()) {
498 std::string in_path = session_template_dir_to_file (session_template);
500 ifstream in(in_path.c_str());
503 /* no need to call legalize_for_path() since the string
504 * in session_template is already a legal path name
506 string out_path = Glib::build_filename (_session_dir->root_path(), _name + statefile_suffix);
508 ofstream out(out_path.c_str());
514 /* Copy plugin state files from template to new session */
515 std::string template_plugins = Glib::build_filename (session_template, X_("plugins"));
516 copy_recurse (template_plugins, plugins_dir ());
521 error << string_compose (_("Could not open %1 for writing session template"), out_path)
527 error << string_compose (_("Could not open session template %1 for reading"), in_path)
534 /* set initial start + end point */
536 _state_of_the_state = Clean;
538 /* set up Master Out and Control Out if necessary */
543 ChanCount count(DataType::AUDIO, bus_profile->master_out_channels);
545 if (bus_profile->master_out_channels) {
546 boost::shared_ptr<Route> r (new Route (*this, _("Master"), Route::MasterOut, DataType::AUDIO));
550 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
551 // boost_debug_shared_ptr_mark_interesting (r.get(), "Route");
554 Glib::Threads::Mutex::Lock lm (AudioEngine::instance()->process_lock ());
555 r->input()->ensure_io (count, false, this);
556 r->output()->ensure_io (count, false, this);
562 /* prohibit auto-connect to master, because there isn't one */
563 bus_profile->output_ac = AutoConnectOption (bus_profile->output_ac & ~AutoConnectMaster);
567 add_routes (rl, false, false, false);
570 /* this allows the user to override settings with an environment variable.
573 if (no_auto_connect()) {
574 bus_profile->input_ac = AutoConnectOption (0);
575 bus_profile->output_ac = AutoConnectOption (0);
578 Config->set_input_auto_connect (bus_profile->input_ac);
579 Config->set_output_auto_connect (bus_profile->output_ac);
582 if (Config->get_use_monitor_bus() && bus_profile) {
583 add_monitor_section ();
590 Session::maybe_write_autosave()
592 if (dirty() && record_status() != Recording) {
593 save_state("", true);
598 Session::remove_pending_capture_state ()
600 std::string pending_state_file_path(_session_dir->root_path());
602 pending_state_file_path = Glib::build_filename (pending_state_file_path, legalize_for_path (_current_snapshot_name) + pending_suffix);
604 if (!Glib::file_test (pending_state_file_path, Glib::FILE_TEST_EXISTS)) return;
606 if (g_remove (pending_state_file_path.c_str()) != 0) {
607 error << string_compose(_("Could not remove pending capture state at path \"%1\" (%2)"),
608 pending_state_file_path, g_strerror (errno)) << endmsg;
612 /** Rename a state file.
613 * @param old_name Old snapshot name.
614 * @param new_name New snapshot name.
617 Session::rename_state (string old_name, string new_name)
619 if (old_name == _current_snapshot_name || old_name == _name) {
620 /* refuse to rename the current snapshot or the "main" one */
624 const string old_xml_filename = legalize_for_path (old_name) + statefile_suffix;
625 const string new_xml_filename = legalize_for_path (new_name) + statefile_suffix;
627 const std::string old_xml_path(Glib::build_filename (_session_dir->root_path(), old_xml_filename));
628 const std::string new_xml_path(Glib::build_filename (_session_dir->root_path(), new_xml_filename));
630 if (::g_rename (old_xml_path.c_str(), new_xml_path.c_str()) != 0) {
631 error << string_compose(_("could not rename snapshot %1 to %2 (%3)"),
632 old_name, new_name, g_strerror(errno)) << endmsg;
636 /** Remove a state file.
637 * @param snapshot_name Snapshot name.
640 Session::remove_state (string snapshot_name)
642 if (!_writable || snapshot_name == _current_snapshot_name || snapshot_name == _name) {
643 // refuse to remove the current snapshot or the "main" one
647 std::string xml_path(_session_dir->root_path());
649 xml_path = Glib::build_filename (xml_path, legalize_for_path (snapshot_name) + statefile_suffix);
651 if (!create_backup_file (xml_path)) {
652 // don't remove it if a backup can't be made
653 // create_backup_file will log the error.
658 if (g_remove (xml_path.c_str()) != 0) {
659 error << string_compose(_("Could not remove session file at path \"%1\" (%2)"),
660 xml_path, g_strerror (errno)) << endmsg;
664 /** @param snapshot_name Name to save under, without .ardour / .pending prefix */
666 Session::save_state (string snapshot_name, bool pending, bool switch_to_snapshot)
669 std::string xml_path(_session_dir->root_path());
671 /* prevent concurrent saves from different threads */
673 Glib::Threads::Mutex::Lock lm (save_state_lock);
675 if (!_writable || (_state_of_the_state & CannotSave)) {
679 if (g_atomic_int_get(&_suspend_save)) {
683 _save_queued = false;
685 if (!_engine.connected ()) {
686 error << string_compose (_("the %1 audio engine is not connected and state saving would lose all I/O connections. Session not saved"),
692 /* tell sources we're saving first, in case they write out to a new file
693 * which should be saved with the state rather than the old one */
694 for (SourceMap::const_iterator i = sources.begin(); i != sources.end(); ++i) {
696 i->second->session_saved();
697 } catch (Evoral::SMF::FileError& e) {
698 error << string_compose ("Could not write to MIDI file %1; MIDI data not saved.", e.file_name ()) << endmsg;
702 SessionSaveUnderway (); /* EMIT SIGNAL */
704 tree.set_root (&get_state());
706 if (snapshot_name.empty()) {
707 snapshot_name = _current_snapshot_name;
708 } else if (switch_to_snapshot) {
709 _current_snapshot_name = snapshot_name;
714 /* proper save: use statefile_suffix (.ardour in English) */
716 xml_path = Glib::build_filename (xml_path, legalize_for_path (snapshot_name) + statefile_suffix);
718 /* make a backup copy of the old file */
720 if (Glib::file_test (xml_path, Glib::FILE_TEST_EXISTS) && !create_backup_file (xml_path)) {
721 // create_backup_file will log the error
727 /* pending save: use pending_suffix (.pending in English) */
728 xml_path = Glib::build_filename (xml_path, legalize_for_path (snapshot_name) + pending_suffix);
731 std::string tmp_path(_session_dir->root_path());
732 tmp_path = Glib::build_filename (tmp_path, legalize_for_path (snapshot_name) + temp_suffix);
734 // cerr << "actually writing state to " << xml_path << endl;
736 if (!tree.write (tmp_path)) {
737 error << string_compose (_("state could not be saved to %1"), tmp_path) << endmsg;
738 if (g_remove (tmp_path.c_str()) != 0) {
739 error << string_compose(_("Could not remove temporary session file at path \"%1\" (%2)"),
740 tmp_path, g_strerror (errno)) << endmsg;
746 if (::g_rename (tmp_path.c_str(), xml_path.c_str()) != 0) {
747 error << string_compose (_("could not rename temporary session file %1 to %2 (%3)"),
748 tmp_path, xml_path, g_strerror(errno)) << endmsg;
749 if (g_remove (tmp_path.c_str()) != 0) {
750 error << string_compose(_("Could not remove temporary session file at path \"%1\" (%2)"),
751 tmp_path, g_strerror (errno)) << endmsg;
759 save_history (snapshot_name);
761 bool was_dirty = dirty();
763 _state_of_the_state = StateOfTheState (_state_of_the_state & ~Dirty);
766 DirtyChanged (); /* EMIT SIGNAL */
769 StateSaved (snapshot_name); /* EMIT SIGNAL */
776 Session::restore_state (string snapshot_name)
778 if (load_state (snapshot_name) == 0) {
779 set_state (*state_tree->root(), Stateful::loading_state_version);
786 Session::load_state (string snapshot_name)
791 state_was_pending = false;
793 /* check for leftover pending state from a crashed capture attempt */
795 std::string xmlpath(_session_dir->root_path());
796 xmlpath = Glib::build_filename (xmlpath, legalize_for_path (snapshot_name) + pending_suffix);
798 if (Glib::file_test (xmlpath, Glib::FILE_TEST_EXISTS)) {
800 /* there is pending state from a crashed capture attempt */
802 boost::optional<int> r = AskAboutPendingState();
803 if (r.get_value_or (1)) {
804 state_was_pending = true;
808 if (!state_was_pending) {
809 xmlpath = Glib::build_filename (_session_dir->root_path(), snapshot_name);
812 if (!Glib::file_test (xmlpath, Glib::FILE_TEST_EXISTS)) {
813 xmlpath = Glib::build_filename (_session_dir->root_path(), legalize_for_path (snapshot_name) + statefile_suffix);
814 if (!Glib::file_test (xmlpath, Glib::FILE_TEST_EXISTS)) {
815 error << string_compose(_("%1: session file \"%2\" doesn't exist!"), _name, xmlpath) << endmsg;
820 state_tree = new XMLTree;
824 _writable = exists_and_writable (xmlpath) && exists_and_writable(Glib::path_get_dirname(xmlpath));
826 if (!state_tree->read (xmlpath)) {
827 error << string_compose(_("Could not understand session file %1"), xmlpath) << endmsg;
833 XMLNode& root (*state_tree->root());
835 if (root.name() != X_("Session")) {
836 error << string_compose (_("Session file %1 is not a session"), xmlpath) << endmsg;
842 const XMLProperty* prop;
844 if ((prop = root.property ("version")) == 0) {
845 /* no version implies very old version of Ardour */
846 Stateful::loading_state_version = 1000;
848 if (prop->value().find ('.') != string::npos) {
849 /* old school version format */
850 if (prop->value()[0] == '2') {
851 Stateful::loading_state_version = 2000;
853 Stateful::loading_state_version = 3000;
856 Stateful::loading_state_version = atoi (prop->value());
860 if (Stateful::loading_state_version < CURRENT_SESSION_FILE_VERSION && _writable) {
862 std::string backup_path(_session_dir->root_path());
863 std::string backup_filename = string_compose ("%1-%2%3", legalize_for_path (snapshot_name), Stateful::loading_state_version, statefile_suffix);
864 backup_path = Glib::build_filename (backup_path, backup_filename);
866 // only create a backup for a given statefile version once
868 if (!Glib::file_test (backup_path, Glib::FILE_TEST_EXISTS)) {
870 VersionMismatch (xmlpath, backup_path);
872 if (!copy_file (xmlpath, backup_path)) {;
882 Session::load_options (const XMLNode& node)
884 LocaleGuard lg (X_("C"));
885 config.set_variables (node);
890 Session::save_default_options ()
892 return config.save_state();
902 Session::get_template()
904 /* if we don't disable rec-enable, diskstreams
905 will believe they need to store their capture
906 sources in their state node.
909 disable_record (false);
915 Session::state (bool full_state)
917 XMLNode* node = new XMLNode("Session");
921 snprintf(buf, sizeof(buf), "%d", CURRENT_SESSION_FILE_VERSION);
922 node->add_property("version", buf);
924 /* store configuration settings */
928 node->add_property ("name", _name);
929 snprintf (buf, sizeof (buf), "%" PRId64, _nominal_frame_rate);
930 node->add_property ("sample-rate", buf);
932 if (session_dirs.size() > 1) {
936 vector<space_and_path>::iterator i = session_dirs.begin();
937 vector<space_and_path>::iterator next;
939 ++i; /* skip the first one */
943 while (i != session_dirs.end()) {
947 if (next != session_dirs.end()) {
948 p += G_SEARCHPATH_SEPARATOR;
957 child = node->add_child ("Path");
958 child->add_content (p);
962 /* save the ID counter */
964 snprintf (buf, sizeof (buf), "%" PRIu64, ID::counter());
965 node->add_property ("id-counter", buf);
967 /* save the event ID counter */
969 snprintf (buf, sizeof (buf), "%d", Evoral::event_id_counter());
970 node->add_property ("event-counter", buf);
972 /* various options */
974 list<XMLNode*> midi_port_nodes = _midi_ports->get_midi_port_states();
975 if (!midi_port_nodes.empty()) {
976 XMLNode* midi_port_stuff = new XMLNode ("MIDIPorts");
977 for (list<XMLNode*>::const_iterator n = midi_port_nodes.begin(); n != midi_port_nodes.end(); ++n) {
978 midi_port_stuff->add_child_nocopy (**n);
980 node->add_child_nocopy (*midi_port_stuff);
983 node->add_child_nocopy (config.get_variables ());
985 node->add_child_nocopy (ARDOUR::SessionMetadata::Metadata()->get_state());
987 child = node->add_child ("Sources");
990 Glib::Threads::Mutex::Lock sl (source_lock);
992 for (SourceMap::iterator siter = sources.begin(); siter != sources.end(); ++siter) {
994 /* Don't save information about non-file Sources, or
995 * about non-destructive file sources that are empty
996 * and unused by any regions.
999 boost::shared_ptr<FileSource> fs;
1001 if ((fs = boost::dynamic_pointer_cast<FileSource> (siter->second)) != 0) {
1003 if (!fs->destructive()) {
1004 if (fs->empty() && !fs->used()) {
1009 child->add_child_nocopy (siter->second->get_state());
1014 child = node->add_child ("Regions");
1017 Glib::Threads::Mutex::Lock rl (region_lock);
1018 const RegionFactory::RegionMap& region_map (RegionFactory::all_regions());
1019 for (RegionFactory::RegionMap::const_iterator i = region_map.begin(); i != region_map.end(); ++i) {
1020 boost::shared_ptr<Region> r = i->second;
1021 /* only store regions not attached to playlists */
1022 if (r->playlist() == 0) {
1023 if (boost::dynamic_pointer_cast<AudioRegion>(r)) {
1024 child->add_child_nocopy ((boost::dynamic_pointer_cast<AudioRegion>(r))->get_basic_state ());
1026 child->add_child_nocopy (r->get_state ());
1031 RegionFactory::CompoundAssociations& cassocs (RegionFactory::compound_associations());
1033 if (!cassocs.empty()) {
1034 XMLNode* ca = node->add_child (X_("CompoundAssociations"));
1036 for (RegionFactory::CompoundAssociations::iterator i = cassocs.begin(); i != cassocs.end(); ++i) {
1038 XMLNode* can = new XMLNode (X_("CompoundAssociation"));
1039 i->first->id().print (buf, sizeof (buf));
1040 can->add_property (X_("copy"), buf);
1041 i->second->id().print (buf, sizeof (buf));
1042 can->add_property (X_("original"), buf);
1043 ca->add_child_nocopy (*can);
1049 node->add_child_nocopy (_locations->get_state());
1051 // for a template, just create a new Locations, populate it
1052 // with the default start and end, and get the state for that.
1053 Locations loc (*this);
1054 Location* range = new Location (*this, 0, 0, _("session"), Location::IsSessionRange);
1055 range->set (max_framepos, 0);
1057 node->add_child_nocopy (loc.get_state());
1060 child = node->add_child ("Bundles");
1062 boost::shared_ptr<BundleList> bundles = _bundles.reader ();
1063 for (BundleList::iterator i = bundles->begin(); i != bundles->end(); ++i) {
1064 boost::shared_ptr<UserBundle> b = boost::dynamic_pointer_cast<UserBundle> (*i);
1066 child->add_child_nocopy (b->get_state());
1071 child = node->add_child ("Routes");
1073 boost::shared_ptr<RouteList> r = routes.reader ();
1075 RoutePublicOrderSorter cmp;
1076 RouteList public_order (*r);
1077 public_order.sort (cmp);
1079 /* the sort should have put control outs first */
1082 assert (_monitor_out == public_order.front());
1085 for (RouteList::iterator i = public_order.begin(); i != public_order.end(); ++i) {
1086 if (!(*i)->is_auditioner()) {
1088 child->add_child_nocopy ((*i)->get_state());
1090 child->add_child_nocopy ((*i)->get_template());
1096 playlists->add_state (node, full_state);
1098 child = node->add_child ("RouteGroups");
1099 for (list<RouteGroup *>::iterator i = _route_groups.begin(); i != _route_groups.end(); ++i) {
1100 child->add_child_nocopy ((*i)->get_state());
1104 XMLNode* gain_child = node->add_child ("Click");
1105 gain_child->add_child_nocopy (_click_io->state (full_state));
1106 gain_child->add_child_nocopy (_click_gain->state (full_state));
1110 XMLNode* ltc_input_child = node->add_child ("LTC-In");
1111 ltc_input_child->add_child_nocopy (_ltc_input->state (full_state));
1115 XMLNode* ltc_output_child = node->add_child ("LTC-Out");
1116 ltc_output_child->add_child_nocopy (_ltc_output->state (full_state));
1119 node->add_child_nocopy (_speakers->get_state());
1120 node->add_child_nocopy (_tempo_map->get_state());
1121 node->add_child_nocopy (get_control_protocol_state());
1124 node->add_child_copy (*_extra_xml);
1131 Session::get_control_protocol_state ()
1133 ControlProtocolManager& cpm (ControlProtocolManager::instance());
1134 return cpm.get_state();
1138 Session::set_state (const XMLNode& node, int version)
1142 const XMLProperty* prop;
1145 _state_of_the_state = StateOfTheState (_state_of_the_state|CannotSave);
1147 if (node.name() != X_("Session")) {
1148 fatal << _("programming error: Session: incorrect XML node sent to set_state()") << endmsg;
1152 if ((prop = node.property ("name")) != 0) {
1153 _name = prop->value ();
1156 if ((prop = node.property (X_("sample-rate"))) != 0) {
1158 _nominal_frame_rate = atoi (prop->value());
1160 if (_nominal_frame_rate != _current_frame_rate) {
1161 boost::optional<int> r = AskAboutSampleRateMismatch (_nominal_frame_rate, _current_frame_rate);
1162 if (r.get_value_or (0)) {
1168 setup_raid_path(_session_dir->root_path());
1170 if ((prop = node.property (X_("id-counter"))) != 0) {
1172 sscanf (prop->value().c_str(), "%" PRIu64, &x);
1173 ID::init_counter (x);
1175 /* old sessions used a timebased counter, so fake
1176 the startup ID counter based on a standard
1181 ID::init_counter (now);
1184 if ((prop = node.property (X_("event-counter"))) != 0) {
1185 Evoral::init_event_id_counter (atoi (prop->value()));
1189 if ((child = find_named_node (node, "MIDIPorts")) != 0) {
1190 _midi_ports->set_midi_port_states (child->children());
1193 IO::disable_connecting ();
1195 Stateful::save_extra_xml (node);
1197 if (((child = find_named_node (node, "Options")) != 0)) { /* old style */
1198 load_options (*child);
1199 } else if ((child = find_named_node (node, "Config")) != 0) { /* new style */
1200 load_options (*child);
1202 error << _("Session: XML state has no options section") << endmsg;
1205 if (version >= 3000) {
1206 if ((child = find_named_node (node, "Metadata")) == 0) {
1207 warning << _("Session: XML state has no metadata section") << endmsg;
1208 } else if ( ARDOUR::SessionMetadata::Metadata()->set_state (*child, version) ) {
1213 if ((child = find_named_node (node, X_("Speakers"))) != 0) {
1214 _speakers->set_state (*child, version);
1217 if ((child = find_named_node (node, "Sources")) == 0) {
1218 error << _("Session: XML state has no sources section") << endmsg;
1220 } else if (load_sources (*child)) {
1224 if ((child = find_named_node (node, "TempoMap")) == 0) {
1225 error << _("Session: XML state has no Tempo Map section") << endmsg;
1227 } else if (_tempo_map->set_state (*child, version)) {
1231 if ((child = find_named_node (node, "Locations")) == 0) {
1232 error << _("Session: XML state has no locations section") << endmsg;
1234 } else if (_locations->set_state (*child, version)) {
1238 locations_changed ();
1240 if (_session_range_location) {
1241 AudioFileSource::set_header_position_offset (_session_range_location->start());
1244 if ((child = find_named_node (node, "Regions")) == 0) {
1245 error << _("Session: XML state has no Regions section") << endmsg;
1247 } else if (load_regions (*child)) {
1251 if ((child = find_named_node (node, "Playlists")) == 0) {
1252 error << _("Session: XML state has no playlists section") << endmsg;
1254 } else if (playlists->load (*this, *child)) {
1258 if ((child = find_named_node (node, "UnusedPlaylists")) == 0) {
1260 } else if (playlists->load_unused (*this, *child)) {
1264 if ((child = find_named_node (node, "CompoundAssociations")) != 0) {
1265 if (load_compounds (*child)) {
1270 if (version >= 3000) {
1271 if ((child = find_named_node (node, "Bundles")) == 0) {
1272 warning << _("Session: XML state has no bundles section") << endmsg;
1275 /* We can't load Bundles yet as they need to be able
1276 to convert from port names to Port objects, which can't happen until
1278 _bundle_xml_node = new XMLNode (*child);
1282 if (version < 3000) {
1283 if ((child = find_named_node (node, X_("DiskStreams"))) == 0) {
1284 error << _("Session: XML state has no diskstreams section") << endmsg;
1286 } else if (load_diskstreams_2X (*child, version)) {
1291 if ((child = find_named_node (node, "Routes")) == 0) {
1292 error << _("Session: XML state has no routes section") << endmsg;
1294 } else if (load_routes (*child, version)) {
1298 /* our diskstreams list is no longer needed as they are now all owned by their Route */
1299 _diskstreams_2X.clear ();
1301 if (version >= 3000) {
1303 if ((child = find_named_node (node, "RouteGroups")) == 0) {
1304 error << _("Session: XML state has no route groups section") << endmsg;
1306 } else if (load_route_groups (*child, version)) {
1310 } else if (version < 3000) {
1312 if ((child = find_named_node (node, "EditGroups")) == 0) {
1313 error << _("Session: XML state has no edit groups section") << endmsg;
1315 } else if (load_route_groups (*child, version)) {
1319 if ((child = find_named_node (node, "MixGroups")) == 0) {
1320 error << _("Session: XML state has no mix groups section") << endmsg;
1322 } else if (load_route_groups (*child, version)) {
1327 if ((child = find_named_node (node, "Click")) == 0) {
1328 warning << _("Session: XML state has no click section") << endmsg;
1329 } else if (_click_io) {
1330 setup_click_state (&node);
1333 if ((child = find_named_node (node, ControlProtocolManager::state_node_name)) != 0) {
1334 ControlProtocolManager::instance().set_state (*child, version);
1337 update_have_rec_enabled_track ();
1339 /* here beginneth the second phase ... */
1341 StateReady (); /* EMIT SIGNAL */
1354 Session::load_routes (const XMLNode& node, int version)
1357 XMLNodeConstIterator niter;
1358 RouteList new_routes;
1360 nlist = node.children();
1364 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1366 boost::shared_ptr<Route> route;
1367 if (version < 3000) {
1368 route = XMLRouteFactory_2X (**niter, version);
1370 route = XMLRouteFactory (**niter, version);
1374 error << _("Session: cannot create Route from XML description.") << endmsg;
1378 BootMessage (string_compose (_("Loaded track/bus %1"), route->name()));
1380 new_routes.push_back (route);
1383 BootMessage (_("Tracks/busses loaded; Adding to Session"));
1385 add_routes (new_routes, false, false, false);
1387 BootMessage (_("Finished adding tracks/busses"));
1392 boost::shared_ptr<Route>
1393 Session::XMLRouteFactory (const XMLNode& node, int version)
1395 boost::shared_ptr<Route> ret;
1397 if (node.name() != "Route") {
1401 XMLNode* ds_child = find_named_node (node, X_("Diskstream"));
1403 DataType type = DataType::AUDIO;
1404 const XMLProperty* prop = node.property("default-type");
1407 type = DataType (prop->value());
1410 assert (type != DataType::NIL);
1414 boost::shared_ptr<Track> track;
1416 if (type == DataType::AUDIO) {
1417 track.reset (new AudioTrack (*this, X_("toBeResetFroXML")));
1419 track.reset (new MidiTrack (*this, X_("toBeResetFroXML")));
1422 if (track->init()) {
1426 if (track->set_state (node, version)) {
1430 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
1431 // boost_debug_shared_ptr_mark_interesting (track.get(), "Track");
1436 enum Route::Flag flags = Route::Flag(0);
1437 const XMLProperty* prop = node.property("flags");
1439 flags = Route::Flag (string_2_enum (prop->value(), flags));
1442 boost::shared_ptr<Route> r (new Route (*this, X_("toBeResetFroXML"), flags));
1444 if (r->init () == 0 && r->set_state (node, version) == 0) {
1445 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
1446 // boost_debug_shared_ptr_mark_interesting (r.get(), "Route");
1455 boost::shared_ptr<Route>
1456 Session::XMLRouteFactory_2X (const XMLNode& node, int version)
1458 boost::shared_ptr<Route> ret;
1460 if (node.name() != "Route") {
1464 XMLProperty const * ds_prop = node.property (X_("diskstream-id"));
1466 ds_prop = node.property (X_("diskstream"));
1469 DataType type = DataType::AUDIO;
1470 const XMLProperty* prop = node.property("default-type");
1473 type = DataType (prop->value());
1476 assert (type != DataType::NIL);
1480 list<boost::shared_ptr<Diskstream> >::iterator i = _diskstreams_2X.begin ();
1481 while (i != _diskstreams_2X.end() && (*i)->id() != ds_prop->value()) {
1485 if (i == _diskstreams_2X.end()) {
1486 error << _("Could not find diskstream for route") << endmsg;
1487 return boost::shared_ptr<Route> ();
1490 boost::shared_ptr<Track> track;
1492 if (type == DataType::AUDIO) {
1493 track.reset (new AudioTrack (*this, X_("toBeResetFroXML")));
1495 track.reset (new MidiTrack (*this, X_("toBeResetFroXML")));
1498 if (track->init()) {
1502 if (track->set_state (node, version)) {
1506 track->set_diskstream (*i);
1508 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
1509 // boost_debug_shared_ptr_mark_interesting (track.get(), "Track");
1514 enum Route::Flag flags = Route::Flag(0);
1515 const XMLProperty* prop = node.property("flags");
1517 flags = Route::Flag (string_2_enum (prop->value(), flags));
1520 boost::shared_ptr<Route> r (new Route (*this, X_("toBeResetFroXML"), flags));
1522 if (r->init () == 0 && r->set_state (node, version) == 0) {
1523 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
1524 // boost_debug_shared_ptr_mark_interesting (r.get(), "Route");
1534 Session::load_regions (const XMLNode& node)
1537 XMLNodeConstIterator niter;
1538 boost::shared_ptr<Region> region;
1540 nlist = node.children();
1544 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1545 if ((region = XMLRegionFactory (**niter, false)) == 0) {
1546 error << _("Session: cannot create Region from XML description.");
1547 const XMLProperty *name = (**niter).property("name");
1550 error << " " << string_compose (_("Can not load state for region '%1'"), name->value());
1561 Session::load_compounds (const XMLNode& node)
1563 XMLNodeList calist = node.children();
1564 XMLNodeConstIterator caiter;
1565 XMLProperty *caprop;
1567 for (caiter = calist.begin(); caiter != calist.end(); ++caiter) {
1568 XMLNode* ca = *caiter;
1572 if ((caprop = ca->property (X_("original"))) == 0) {
1575 orig_id = caprop->value();
1577 if ((caprop = ca->property (X_("copy"))) == 0) {
1580 copy_id = caprop->value();
1582 boost::shared_ptr<Region> orig = RegionFactory::region_by_id (orig_id);
1583 boost::shared_ptr<Region> copy = RegionFactory::region_by_id (copy_id);
1585 if (!orig || !copy) {
1586 warning << string_compose (_("Regions in compound description not found (ID's %1 and %2): ignored"),
1592 RegionFactory::add_compound_association (orig, copy);
1599 Session::load_nested_sources (const XMLNode& node)
1602 XMLNodeConstIterator niter;
1604 nlist = node.children();
1606 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1607 if ((*niter)->name() == "Source") {
1609 /* it may already exist, so don't recreate it unnecessarily
1612 XMLProperty* prop = (*niter)->property (X_("id"));
1614 error << _("Nested source has no ID info in session file! (ignored)") << endmsg;
1618 ID source_id (prop->value());
1620 if (!source_by_id (source_id)) {
1623 SourceFactory::create (*this, **niter, true);
1625 catch (failed_constructor& err) {
1626 error << string_compose (_("Cannot reconstruct nested source for region %1"), name()) << endmsg;
1633 boost::shared_ptr<Region>
1634 Session::XMLRegionFactory (const XMLNode& node, bool full)
1636 const XMLProperty* type = node.property("type");
1640 const XMLNodeList& nlist = node.children();
1642 for (XMLNodeConstIterator niter = nlist.begin(); niter != nlist.end(); ++niter) {
1643 XMLNode *child = (*niter);
1644 if (child->name() == "NestedSource") {
1645 load_nested_sources (*child);
1649 if (!type || type->value() == "audio") {
1650 return boost::shared_ptr<Region>(XMLAudioRegionFactory (node, full));
1651 } else if (type->value() == "midi") {
1652 return boost::shared_ptr<Region>(XMLMidiRegionFactory (node, full));
1655 } catch (failed_constructor& err) {
1656 return boost::shared_ptr<Region> ();
1659 return boost::shared_ptr<Region> ();
1662 boost::shared_ptr<AudioRegion>
1663 Session::XMLAudioRegionFactory (const XMLNode& node, bool /*full*/)
1665 const XMLProperty* prop;
1666 boost::shared_ptr<Source> source;
1667 boost::shared_ptr<AudioSource> as;
1669 SourceList master_sources;
1670 uint32_t nchans = 1;
1673 if (node.name() != X_("Region")) {
1674 return boost::shared_ptr<AudioRegion>();
1677 if ((prop = node.property (X_("channels"))) != 0) {
1678 nchans = atoi (prop->value().c_str());
1681 if ((prop = node.property ("name")) == 0) {
1682 cerr << "no name for this region\n";
1686 if ((prop = node.property (X_("source-0"))) == 0) {
1687 if ((prop = node.property ("source")) == 0) {
1688 error << _("Session: XMLNode describing a AudioRegion is incomplete (no source)") << endmsg;
1689 return boost::shared_ptr<AudioRegion>();
1693 PBD::ID s_id (prop->value());
1695 if ((source = source_by_id (s_id)) == 0) {
1696 error << string_compose(_("Session: XMLNode describing a AudioRegion references an unknown source id =%1"), s_id) << endmsg;
1697 return boost::shared_ptr<AudioRegion>();
1700 as = boost::dynamic_pointer_cast<AudioSource>(source);
1702 error << string_compose(_("Session: XMLNode describing a AudioRegion references a non-audio source id =%1"), s_id) << endmsg;
1703 return boost::shared_ptr<AudioRegion>();
1706 sources.push_back (as);
1708 /* pickup other channels */
1710 for (uint32_t n=1; n < nchans; ++n) {
1711 snprintf (buf, sizeof(buf), X_("source-%d"), n);
1712 if ((prop = node.property (buf)) != 0) {
1714 PBD::ID id2 (prop->value());
1716 if ((source = source_by_id (id2)) == 0) {
1717 error << string_compose(_("Session: XMLNode describing a AudioRegion references an unknown source id =%1"), id2) << endmsg;
1718 return boost::shared_ptr<AudioRegion>();
1721 as = boost::dynamic_pointer_cast<AudioSource>(source);
1723 error << string_compose(_("Session: XMLNode describing a AudioRegion references a non-audio source id =%1"), id2) << endmsg;
1724 return boost::shared_ptr<AudioRegion>();
1726 sources.push_back (as);
1730 for (uint32_t n = 0; n < nchans; ++n) {
1731 snprintf (buf, sizeof(buf), X_("master-source-%d"), n);
1732 if ((prop = node.property (buf)) != 0) {
1734 PBD::ID id2 (prop->value());
1736 if ((source = source_by_id (id2)) == 0) {
1737 error << string_compose(_("Session: XMLNode describing a AudioRegion references an unknown source id =%1"), id2) << endmsg;
1738 return boost::shared_ptr<AudioRegion>();
1741 as = boost::dynamic_pointer_cast<AudioSource>(source);
1743 error << string_compose(_("Session: XMLNode describing a AudioRegion references a non-audio source id =%1"), id2) << endmsg;
1744 return boost::shared_ptr<AudioRegion>();
1746 master_sources.push_back (as);
1751 boost::shared_ptr<AudioRegion> region (boost::dynamic_pointer_cast<AudioRegion> (RegionFactory::create (sources, node)));
1753 /* a final detail: this is the one and only place that we know how long missing files are */
1755 if (region->whole_file()) {
1756 for (SourceList::iterator sx = sources.begin(); sx != sources.end(); ++sx) {
1757 boost::shared_ptr<SilentFileSource> sfp = boost::dynamic_pointer_cast<SilentFileSource> (*sx);
1759 sfp->set_length (region->length());
1764 if (!master_sources.empty()) {
1765 if (master_sources.size() != nchans) {
1766 error << _("Session: XMLNode describing an AudioRegion is missing some master sources; ignored") << endmsg;
1768 region->set_master_sources (master_sources);
1776 catch (failed_constructor& err) {
1777 return boost::shared_ptr<AudioRegion>();
1781 boost::shared_ptr<MidiRegion>
1782 Session::XMLMidiRegionFactory (const XMLNode& node, bool /*full*/)
1784 const XMLProperty* prop;
1785 boost::shared_ptr<Source> source;
1786 boost::shared_ptr<MidiSource> ms;
1789 if (node.name() != X_("Region")) {
1790 return boost::shared_ptr<MidiRegion>();
1793 if ((prop = node.property ("name")) == 0) {
1794 cerr << "no name for this region\n";
1798 if ((prop = node.property (X_("source-0"))) == 0) {
1799 if ((prop = node.property ("source")) == 0) {
1800 error << _("Session: XMLNode describing a MidiRegion is incomplete (no source)") << endmsg;
1801 return boost::shared_ptr<MidiRegion>();
1805 PBD::ID s_id (prop->value());
1807 if ((source = source_by_id (s_id)) == 0) {
1808 error << string_compose(_("Session: XMLNode describing a MidiRegion references an unknown source id =%1"), s_id) << endmsg;
1809 return boost::shared_ptr<MidiRegion>();
1812 ms = boost::dynamic_pointer_cast<MidiSource>(source);
1814 error << string_compose(_("Session: XMLNode describing a MidiRegion references a non-midi source id =%1"), s_id) << endmsg;
1815 return boost::shared_ptr<MidiRegion>();
1818 sources.push_back (ms);
1821 boost::shared_ptr<MidiRegion> region (boost::dynamic_pointer_cast<MidiRegion> (RegionFactory::create (sources, node)));
1822 /* a final detail: this is the one and only place that we know how long missing files are */
1824 if (region->whole_file()) {
1825 for (SourceList::iterator sx = sources.begin(); sx != sources.end(); ++sx) {
1826 boost::shared_ptr<SilentFileSource> sfp = boost::dynamic_pointer_cast<SilentFileSource> (*sx);
1828 sfp->set_length (region->length());
1836 catch (failed_constructor& err) {
1837 return boost::shared_ptr<MidiRegion>();
1842 Session::get_sources_as_xml ()
1845 XMLNode* node = new XMLNode (X_("Sources"));
1846 Glib::Threads::Mutex::Lock lm (source_lock);
1848 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ++i) {
1849 node->add_child_nocopy (i->second->get_state());
1856 Session::load_sources (const XMLNode& node)
1859 XMLNodeConstIterator niter;
1860 boost::shared_ptr<Source> source; /* don't need this but it stops some
1861 * versions of gcc complaining about
1862 * discarded return values.
1865 nlist = node.children();
1869 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1872 if ((source = XMLSourceFactory (**niter)) == 0) {
1873 error << _("Session: cannot create Source from XML description.") << endmsg;
1876 } catch (MissingSource& err) {
1880 if (err.type == DataType::MIDI && Glib::path_is_absolute (err.path)) {
1881 error << string_compose (_("A external MIDI file is missing. %1 cannot currently recover from missing external MIDI files"),
1882 PROGRAM_NAME) << endmsg;
1886 if (!no_questions_about_missing_files) {
1887 user_choice = MissingFile (this, err.path, err.type).get_value_or (-1);
1892 switch (user_choice) {
1894 /* user added a new search location, so try again */
1899 /* user asked to quit the entire session load
1904 no_questions_about_missing_files = true;
1908 no_questions_about_missing_files = true;
1915 case DataType::AUDIO:
1916 source = SourceFactory::createSilent (*this, **niter, max_framecnt, _current_frame_rate);
1919 case DataType::MIDI:
1920 /* The MIDI file is actually missing so
1921 * just create a new one in the same
1922 * location. Do not announce its
1926 if (!Glib::path_is_absolute (err.path)) {
1927 fullpath = Glib::build_filename (source_search_path (DataType::MIDI).front(), err.path);
1929 /* this should be an unrecoverable error: we would be creating a MIDI file outside
1934 /* Note that we do not announce the source just yet - we need to reset its ID before we do that */
1935 source = SourceFactory::createWritable (DataType::MIDI, *this, fullpath, false, _current_frame_rate, false, false);
1936 /* reset ID to match the missing one */
1937 source->set_id (**niter);
1938 /* Now we can announce it */
1939 SourceFactory::SourceCreated (source);
1950 boost::shared_ptr<Source>
1951 Session::XMLSourceFactory (const XMLNode& node)
1953 if (node.name() != "Source") {
1954 return boost::shared_ptr<Source>();
1958 /* note: do peak building in another thread when loading session state */
1959 return SourceFactory::create (*this, node, true);
1962 catch (failed_constructor& err) {
1963 error << string_compose (_("Found a sound file that cannot be used by %1. Talk to the programmers."), PROGRAM_NAME) << endmsg;
1964 return boost::shared_ptr<Source>();
1969 Session::save_template (string template_name)
1973 if (_state_of_the_state & CannotSave) {
1977 std::string user_template_dir(user_template_directory());
1979 if (g_mkdir_with_parents (user_template_dir.c_str(), 0755) != 0) {
1980 error << string_compose(_("Could not create templates directory \"%1\" (%2)"),
1981 user_template_dir, g_strerror (errno)) << endmsg;
1985 tree.set_root (&get_template());
1987 std::string template_dir_path(user_template_dir);
1989 /* directory to put the template in */
1990 template_dir_path = Glib::build_filename (template_dir_path, template_name);
1992 if (Glib::file_test (template_dir_path, Glib::FILE_TEST_EXISTS)) {
1993 warning << string_compose(_("Template \"%1\" already exists - new version not created"),
1994 template_dir_path) << endmsg;
1998 if (g_mkdir_with_parents (template_dir_path.c_str(), 0755) != 0) {
1999 error << string_compose(_("Could not create directory for Session template\"%1\" (%2)"),
2000 template_dir_path, g_strerror (errno)) << endmsg;
2005 std::string template_file_path(template_dir_path);
2006 template_file_path = Glib::build_filename (template_file_path, template_name + template_suffix);
2008 if (!tree.write (template_file_path)) {
2009 error << _("template not saved") << endmsg;
2013 /* copy plugin state directory */
2015 std::string template_plugin_state_path(template_dir_path);
2016 template_plugin_state_path = Glib::build_filename (template_plugin_state_path, X_("plugins"));
2018 if (g_mkdir_with_parents (template_plugin_state_path.c_str(), 0755) != 0) {
2019 error << string_compose(_("Could not create directory for Session template plugin state\"%1\" (%2)"),
2020 template_plugin_state_path, g_strerror (errno)) << endmsg;
2024 copy_recurse (plugins_dir(), template_plugin_state_path);
2030 Session::refresh_disk_space ()
2032 #if __APPLE__ || (HAVE_SYS_VFS_H && HAVE_SYS_STATVFS_H)
2034 Glib::Threads::Mutex::Lock lm (space_lock);
2036 /* get freespace on every FS that is part of the session path */
2038 _total_free_4k_blocks = 0;
2039 _total_free_4k_blocks_uncertain = false;
2041 for (vector<space_and_path>::iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
2043 struct statfs statfsbuf;
2044 statfs (i->path.c_str(), &statfsbuf);
2046 double const scale = statfsbuf.f_bsize / 4096.0;
2048 /* See if this filesystem is read-only */
2049 struct statvfs statvfsbuf;
2050 statvfs (i->path.c_str(), &statvfsbuf);
2052 /* f_bavail can be 0 if it is undefined for whatever
2053 filesystem we are looking at; Samba shares mounted
2054 via GVFS are an example of this.
2056 if (statfsbuf.f_bavail == 0) {
2057 /* block count unknown */
2059 i->blocks_unknown = true;
2060 } else if (statvfsbuf.f_flag & ST_RDONLY) {
2061 /* read-only filesystem */
2063 i->blocks_unknown = false;
2065 /* read/write filesystem with known space */
2066 i->blocks = (uint32_t) floor (statfsbuf.f_bavail * scale);
2067 i->blocks_unknown = false;
2070 _total_free_4k_blocks += i->blocks;
2071 if (i->blocks_unknown) {
2072 _total_free_4k_blocks_uncertain = true;
2075 #elif defined PLATFORM_WINDOWS
2076 vector<string> scanned_volumes;
2077 vector<string>::iterator j;
2078 vector<space_and_path>::iterator i;
2079 DWORD nSectorsPerCluster, nBytesPerSector,
2080 nFreeClusters, nTotalClusters;
2084 _total_free_4k_blocks = 0;
2086 for (i = session_dirs.begin(); i != session_dirs.end(); i++) {
2087 strncpy (disk_drive, (*i).path.c_str(), 3);
2091 volume_found = false;
2092 if (0 != (GetDiskFreeSpace(disk_drive, &nSectorsPerCluster, &nBytesPerSector, &nFreeClusters, &nTotalClusters)))
2094 int64_t nBytesPerCluster = nBytesPerSector * nSectorsPerCluster;
2095 int64_t nFreeBytes = nBytesPerCluster * (int64_t)nFreeClusters;
2096 i->blocks = (uint32_t)(nFreeBytes / 4096);
2098 for (j = scanned_volumes.begin(); j != scanned_volumes.end(); j++) {
2099 if (0 == j->compare(disk_drive)) {
2100 volume_found = true;
2105 if (!volume_found) {
2106 scanned_volumes.push_back(disk_drive);
2107 _total_free_4k_blocks += i->blocks;
2112 if (0 == _total_free_4k_blocks) {
2113 strncpy (disk_drive, path().c_str(), 3);
2116 if (0 != (GetDiskFreeSpace(disk_drive, &nSectorsPerCluster, &nBytesPerSector, &nFreeClusters, &nTotalClusters)))
2118 int64_t nBytesPerCluster = nBytesPerSector * nSectorsPerCluster;
2119 int64_t nFreeBytes = nBytesPerCluster * (int64_t)nFreeClusters;
2120 _total_free_4k_blocks = (uint32_t)(nFreeBytes / 4096);
2127 Session::get_best_session_directory_for_new_audio ()
2129 vector<space_and_path>::iterator i;
2130 string result = _session_dir->root_path();
2132 /* handle common case without system calls */
2134 if (session_dirs.size() == 1) {
2138 /* OK, here's the algorithm we're following here:
2140 We want to select which directory to use for
2141 the next file source to be created. Ideally,
2142 we'd like to use a round-robin process so as to
2143 get maximum performance benefits from splitting
2144 the files across multiple disks.
2146 However, in situations without much diskspace, an
2147 RR approach may end up filling up a filesystem
2148 with new files while others still have space.
2149 Its therefore important to pay some attention to
2150 the freespace in the filesystem holding each
2151 directory as well. However, if we did that by
2152 itself, we'd keep creating new files in the file
2153 system with the most space until it was as full
2154 as all others, thus negating any performance
2155 benefits of this RAID-1 like approach.
2157 So, we use a user-configurable space threshold. If
2158 there are at least 2 filesystems with more than this
2159 much space available, we use RR selection between them.
2160 If not, then we pick the filesystem with the most space.
2162 This gets a good balance between the two
2166 refresh_disk_space ();
2168 int free_enough = 0;
2170 for (i = session_dirs.begin(); i != session_dirs.end(); ++i) {
2171 if ((*i).blocks * 4096 >= Config->get_disk_choice_space_threshold()) {
2176 if (free_enough >= 2) {
2177 /* use RR selection process, ensuring that the one
2181 i = last_rr_session_dir;
2184 if (++i == session_dirs.end()) {
2185 i = session_dirs.begin();
2188 if ((*i).blocks * 4096 >= Config->get_disk_choice_space_threshold()) {
2189 SessionDirectory sdir(i->path);
2190 if (sdir.create ()) {
2192 last_rr_session_dir = i;
2197 } while (i != last_rr_session_dir);
2201 /* pick FS with the most freespace (and that
2202 seems to actually work ...)
2205 vector<space_and_path> sorted;
2206 space_and_path_ascending_cmp cmp;
2208 sorted = session_dirs;
2209 sort (sorted.begin(), sorted.end(), cmp);
2211 for (i = sorted.begin(); i != sorted.end(); ++i) {
2212 SessionDirectory sdir(i->path);
2213 if (sdir.create ()) {
2215 last_rr_session_dir = i;
2225 Session::automation_dir () const
2227 return Glib::build_filename (_path, "automation");
2231 Session::analysis_dir () const
2233 return Glib::build_filename (_path, "analysis");
2237 Session::plugins_dir () const
2239 return Glib::build_filename (_path, "plugins");
2243 Session::externals_dir () const
2245 return Glib::build_filename (_path, "externals");
2249 Session::load_bundles (XMLNode const & node)
2251 XMLNodeList nlist = node.children();
2252 XMLNodeConstIterator niter;
2256 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2257 if ((*niter)->name() == "InputBundle") {
2258 add_bundle (boost::shared_ptr<UserBundle> (new UserBundle (**niter, true)));
2259 } else if ((*niter)->name() == "OutputBundle") {
2260 add_bundle (boost::shared_ptr<UserBundle> (new UserBundle (**niter, false)));
2262 error << string_compose(_("Unknown node \"%1\" found in Bundles list from session file"), (*niter)->name()) << endmsg;
2271 Session::load_route_groups (const XMLNode& node, int version)
2273 XMLNodeList nlist = node.children();
2274 XMLNodeConstIterator niter;
2278 if (version >= 3000) {
2280 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2281 if ((*niter)->name() == "RouteGroup") {
2282 RouteGroup* rg = new RouteGroup (*this, "");
2283 add_route_group (rg);
2284 rg->set_state (**niter, version);
2288 } else if (version < 3000) {
2290 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2291 if ((*niter)->name() == "EditGroup" || (*niter)->name() == "MixGroup") {
2292 RouteGroup* rg = new RouteGroup (*this, "");
2293 add_route_group (rg);
2294 rg->set_state (**niter, version);
2303 state_file_filter (const string &str, void* /*arg*/)
2305 return (str.length() > strlen(statefile_suffix) &&
2306 str.find (statefile_suffix) == (str.length() - strlen (statefile_suffix)));
2310 remove_end(string state)
2312 string statename(state);
2314 string::size_type start,end;
2315 if ((start = statename.find_last_of (G_DIR_SEPARATOR)) != string::npos) {
2316 statename = statename.substr (start+1);
2319 if ((end = statename.rfind(statefile_suffix)) == string::npos) {
2320 end = statename.length();
2323 return string(statename.substr (0, end));
2327 Session::possible_states (string path)
2329 vector<string> states;
2330 find_files_matching_filter (states, path, state_file_filter, 0, false, false);
2332 transform(states.begin(), states.end(), states.begin(), remove_end);
2334 sort (states.begin(), states.end());
2340 Session::possible_states () const
2342 return possible_states(_path);
2346 Session::add_route_group (RouteGroup* g)
2348 _route_groups.push_back (g);
2349 route_group_added (g); /* EMIT SIGNAL */
2351 g->RouteAdded.connect_same_thread (*this, boost::bind (&Session::route_added_to_route_group, this, _1, _2));
2352 g->RouteRemoved.connect_same_thread (*this, boost::bind (&Session::route_removed_from_route_group, this, _1, _2));
2353 g->PropertyChanged.connect_same_thread (*this, boost::bind (&Session::route_group_property_changed, this, g));
2359 Session::remove_route_group (RouteGroup& rg)
2361 list<RouteGroup*>::iterator i;
2363 if ((i = find (_route_groups.begin(), _route_groups.end(), &rg)) != _route_groups.end()) {
2364 _route_groups.erase (i);
2367 route_group_removed (); /* EMIT SIGNAL */
2371 /** Set a new order for our route groups, without adding or removing any.
2372 * @param groups Route group list in the new order.
2375 Session::reorder_route_groups (list<RouteGroup*> groups)
2377 _route_groups = groups;
2379 route_groups_reordered (); /* EMIT SIGNAL */
2385 Session::route_group_by_name (string name)
2387 list<RouteGroup *>::iterator i;
2389 for (i = _route_groups.begin(); i != _route_groups.end(); ++i) {
2390 if ((*i)->name() == name) {
2398 Session::all_route_group() const
2400 return *_all_route_group;
2404 Session::add_commands (vector<Command*> const & cmds)
2406 for (vector<Command*>::const_iterator i = cmds.begin(); i != cmds.end(); ++i) {
2412 Session::begin_reversible_command (const string& name)
2414 begin_reversible_command (g_quark_from_string (name.c_str ()));
2417 /** Begin a reversible command using a GQuark to identify it.
2418 * begin_reversible_command() and commit_reversible_command() calls may be nested,
2419 * but there must be as many begin...()s as there are commit...()s.
2422 Session::begin_reversible_command (GQuark q)
2424 /* If nested begin/commit pairs are used, we create just one UndoTransaction
2425 to hold all the commands that are committed. This keeps the order of
2426 commands correct in the history.
2429 if (_current_trans == 0) {
2430 /* start a new transaction */
2431 assert (_current_trans_quarks.empty ());
2432 _current_trans = new UndoTransaction();
2433 _current_trans->set_name (g_quark_to_string (q));
2436 _current_trans_quarks.push_front (q);
2440 Session::abort_reversible_command ()
2442 if (_current_trans != 0) {
2443 _current_trans->clear();
2444 delete _current_trans;
2446 _current_trans_quarks.clear();
2451 Session::commit_reversible_command (Command *cmd)
2453 assert (_current_trans);
2454 assert (!_current_trans_quarks.empty ());
2459 _current_trans->add_command (cmd);
2462 _current_trans_quarks.pop_front ();
2464 if (!_current_trans_quarks.empty ()) {
2465 /* the transaction we're committing is not the top-level one */
2469 if (_current_trans->empty()) {
2470 /* no commands were added to the transaction, so just get rid of it */
2471 delete _current_trans;
2476 gettimeofday (&now, 0);
2477 _current_trans->set_timestamp (now);
2479 _history.add (_current_trans);
2484 accept_all_audio_files (const string& path, void* /*arg*/)
2486 if (!Glib::file_test (path, Glib::FILE_TEST_IS_REGULAR)) {
2490 if (!AudioFileSource::safe_audio_file_extension (path)) {
2498 accept_all_midi_files (const string& path, void* /*arg*/)
2500 if (!Glib::file_test (path, Glib::FILE_TEST_IS_REGULAR)) {
2504 return ((path.length() > 4 && path.find (".mid") != (path.length() - 4)) ||
2505 (path.length() > 4 && path.find (".smf") != (path.length() - 4)) ||
2506 (path.length() > 5 && path.find (".midi") != (path.length() - 5)));
2510 accept_all_state_files (const string& path, void* /*arg*/)
2512 if (!Glib::file_test (path, Glib::FILE_TEST_IS_REGULAR)) {
2516 std::string const statefile_ext (statefile_suffix);
2517 if (path.length() >= statefile_ext.length()) {
2518 return (0 == path.compare (path.length() - statefile_ext.length(), statefile_ext.length(), statefile_ext));
2525 Session::find_all_sources (string path, set<string>& result)
2530 if (!tree.read (path)) {
2534 if ((node = find_named_node (*tree.root(), "Sources")) == 0) {
2539 XMLNodeConstIterator niter;
2541 nlist = node->children();
2545 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2549 if ((prop = (*niter)->property (X_("type"))) == 0) {
2553 DataType type (prop->value());
2555 if ((prop = (*niter)->property (X_("name"))) == 0) {
2559 if (Glib::path_is_absolute (prop->value())) {
2560 /* external file, ignore */
2568 if (FileSource::find (*this, type, prop->value(), true, is_new, chan, found_path)) {
2569 result.insert (found_path);
2577 Session::find_all_sources_across_snapshots (set<string>& result, bool exclude_this_snapshot)
2579 vector<string> state_files;
2581 string this_snapshot_path;
2587 if (ripped[ripped.length()-1] == G_DIR_SEPARATOR) {
2588 ripped = ripped.substr (0, ripped.length() - 1);
2591 find_files_matching_filter (state_files, ripped, accept_all_state_files, (void *) 0, true, true);
2593 if (state_files.empty()) {
2598 this_snapshot_path = _path;
2599 this_snapshot_path += legalize_for_path (_current_snapshot_name);
2600 this_snapshot_path += statefile_suffix;
2602 for (vector<string>::iterator i = state_files.begin(); i != state_files.end(); ++i) {
2604 if (exclude_this_snapshot && *i == this_snapshot_path) {
2608 if (find_all_sources (*i, result) < 0) {
2616 struct RegionCounter {
2617 typedef std::map<PBD::ID,boost::shared_ptr<AudioSource> > AudioSourceList;
2618 AudioSourceList::iterator iter;
2619 boost::shared_ptr<Region> region;
2622 RegionCounter() : count (0) {}
2626 Session::ask_about_playlist_deletion (boost::shared_ptr<Playlist> p)
2628 boost::optional<int> r = AskAboutPlaylistDeletion (p);
2629 return r.get_value_or (1);
2633 Session::cleanup_regions ()
2635 bool removed = false;
2636 const RegionFactory::RegionMap& regions (RegionFactory::regions());
2638 for (RegionFactory::RegionMap::const_iterator i = regions.begin(); i != regions.end(); ++i) {
2640 uint32_t used = playlists->region_use_count (i->second);
2642 if (used == 0 && !i->second->automatic ()) {
2644 RegionFactory::map_remove (i->second);
2649 // re-check to remove parent references of compound regions
2650 for (RegionFactory::RegionMap::const_iterator i = regions.begin(); i != regions.end(); ++i) {
2651 if (!(i->second->whole_file() && i->second->max_source_level() > 0)) {
2654 assert(boost::dynamic_pointer_cast<PlaylistSource>(i->second->source (0)) != 0);
2655 if (0 == playlists->region_use_count (i->second)) {
2656 RegionFactory::map_remove (i->second);
2661 /* dump the history list */
2668 Session::cleanup_sources (CleanupReport& rep)
2670 // FIXME: needs adaptation to midi
2672 vector<boost::shared_ptr<Source> > dead_sources;
2675 vector<string> candidates;
2676 vector<string> unused;
2677 set<string> all_sources;
2686 _state_of_the_state = (StateOfTheState) (_state_of_the_state | InCleanup);
2688 /* consider deleting all unused playlists */
2690 if (playlists->maybe_delete_unused (boost::bind (Session::ask_about_playlist_deletion, _1))) {
2695 /* sync the "all regions" property of each playlist with its current state
2698 playlists->sync_all_regions_with_regions ();
2700 /* find all un-used sources */
2705 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ) {
2707 SourceMap::iterator tmp;
2712 /* do not bother with files that are zero size, otherwise we remove the current "nascent"
2716 if (!i->second->used() && (i->second->length(i->second->timeline_position() > 0))) {
2717 dead_sources.push_back (i->second);
2718 i->second->drop_references ();
2724 /* build a list of all the possible audio directories for the session */
2726 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
2727 SessionDirectory sdir ((*i).path);
2728 asp += sdir.sound_path();
2730 audio_path += asp.to_string();
2733 /* build a list of all the possible midi directories for the session */
2735 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
2736 SessionDirectory sdir ((*i).path);
2737 msp += sdir.midi_path();
2739 midi_path += msp.to_string();
2741 find_files_matching_filter (candidates, audio_path, accept_all_audio_files, (void *) 0, true, true);
2742 find_files_matching_filter (candidates, midi_path, accept_all_midi_files, (void *) 0, true, true);
2744 /* find all sources, but don't use this snapshot because the
2745 state file on disk still references sources we may have already
2749 find_all_sources_across_snapshots (all_sources, true);
2751 /* add our current source list
2754 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ) {
2755 boost::shared_ptr<FileSource> fs;
2756 SourceMap::iterator tmp = i;
2759 if ((fs = boost::dynamic_pointer_cast<FileSource> (i->second)) != 0) {
2761 if (!fs->is_stub()) {
2763 if (playlists->source_use_count (fs) != 0) {
2764 all_sources.insert (fs->path());
2767 /* we might not remove this source from disk, because it may be used
2768 by other snapshots, but its not being used in this version
2769 so lets get rid of it now, along with any representative regions
2773 RegionFactory::remove_regions_using_source (i->second);
2782 for (vector<string>::iterator x = candidates.begin(); x != candidates.end(); ++x) {
2787 for (set<string>::iterator i = all_sources.begin(); i != all_sources.end(); ++i) {
2789 tmppath1 = canonical_path (spath);
2790 tmppath2 = canonical_path ((*i));
2792 if (tmppath1 == tmppath2) {
2799 unused.push_back (spath);
2803 /* now try to move all unused files into the "dead" directory(ies) */
2805 for (vector<string>::iterator x = unused.begin(); x != unused.end(); ++x) {
2806 struct stat statbuf;
2810 /* don't move the file across filesystems, just
2811 stick it in the `dead_dir_name' directory
2812 on whichever filesystem it was already on.
2815 if ((*x).find ("/sounds/") != string::npos) {
2817 /* old school, go up 1 level */
2819 newpath = Glib::path_get_dirname (*x); // "sounds"
2820 newpath = Glib::path_get_dirname (newpath); // "session-name"
2824 /* new school, go up 4 levels */
2826 newpath = Glib::path_get_dirname (*x); // "audiofiles" or "midifiles"
2827 newpath = Glib::path_get_dirname (newpath); // "session-name"
2828 newpath = Glib::path_get_dirname (newpath); // "interchange"
2829 newpath = Glib::path_get_dirname (newpath); // "session-dir"
2832 newpath = Glib::build_filename (newpath, dead_dir_name);
2834 if (g_mkdir_with_parents (newpath.c_str(), 0755) < 0) {
2835 error << string_compose(_("Session: cannot create dead file folder \"%1\" (%2)"), newpath, strerror (errno)) << endmsg;
2839 newpath = Glib::build_filename (newpath, Glib::path_get_basename ((*x)));
2841 if (Glib::file_test (newpath, Glib::FILE_TEST_EXISTS)) {
2843 /* the new path already exists, try versioning */
2845 char buf[PATH_MAX+1];
2849 snprintf (buf, sizeof (buf), "%s.%d", newpath.c_str(), version);
2852 while (Glib::file_test (newpath_v.c_str(), Glib::FILE_TEST_EXISTS) && version < 999) {
2853 snprintf (buf, sizeof (buf), "%s.%d", newpath.c_str(), ++version);
2857 if (version == 999) {
2858 error << string_compose (_("there are already 1000 files with names like %1; versioning discontinued"),
2862 newpath = newpath_v;
2867 /* it doesn't exist, or we can't read it or something */
2871 stat ((*x).c_str(), &statbuf);
2873 if (::rename ((*x).c_str(), newpath.c_str()) != 0) {
2874 error << string_compose (_("cannot rename unused file source from %1 to %2 (%3)"),
2875 (*x), newpath, strerror (errno))
2880 /* see if there an easy to find peakfile for this file, and remove it.
2883 string base = basename_nosuffix (*x);
2884 base += "%A"; /* this is what we add for the channel suffix of all native files,
2885 or for the first channel of embedded files. it will miss
2886 some peakfiles for other channels
2888 string peakpath = peak_path (base);
2890 if (Glib::file_test (peakpath.c_str(), Glib::FILE_TEST_EXISTS)) {
2891 if (::g_unlink (peakpath.c_str()) != 0) {
2892 error << string_compose (_("cannot remove peakfile %1 for %2 (%3)"),
2893 peakpath, _path, strerror (errno))
2895 /* try to back out */
2896 ::rename (newpath.c_str(), _path.c_str());
2901 rep.paths.push_back (*x);
2902 rep.space += statbuf.st_size;
2905 /* dump the history list */
2909 /* save state so we don't end up a session file
2910 referring to non-existent sources.
2917 _state_of_the_state = (StateOfTheState) (_state_of_the_state & ~InCleanup);
2923 Session::cleanup_trash_sources (CleanupReport& rep)
2925 // FIXME: needs adaptation for MIDI
2927 vector<space_and_path>::iterator i;
2933 for (i = session_dirs.begin(); i != session_dirs.end(); ++i) {
2935 dead_dir = Glib::build_filename ((*i).path, dead_dir_name);
2937 clear_directory (dead_dir, &rep.space, &rep.paths);
2944 Session::set_dirty ()
2946 /* never mark session dirty during loading */
2948 if (_state_of_the_state & Loading) {
2952 bool was_dirty = dirty();
2954 _state_of_the_state = StateOfTheState (_state_of_the_state | Dirty);
2958 DirtyChanged(); /* EMIT SIGNAL */
2964 Session::set_clean ()
2966 bool was_dirty = dirty();
2968 _state_of_the_state = Clean;
2972 DirtyChanged(); /* EMIT SIGNAL */
2977 Session::set_deletion_in_progress ()
2979 _state_of_the_state = StateOfTheState (_state_of_the_state | Deletion);
2983 Session::clear_deletion_in_progress ()
2985 _state_of_the_state = StateOfTheState (_state_of_the_state & (~Deletion));
2989 Session::add_controllable (boost::shared_ptr<Controllable> c)
2991 /* this adds a controllable to the list managed by the Session.
2992 this is a subset of those managed by the Controllable class
2993 itself, and represents the only ones whose state will be saved
2994 as part of the session.
2997 Glib::Threads::Mutex::Lock lm (controllables_lock);
2998 controllables.insert (c);
3001 struct null_deleter { void operator()(void const *) const {} };
3004 Session::remove_controllable (Controllable* c)
3006 if (_state_of_the_state & Deletion) {
3010 Glib::Threads::Mutex::Lock lm (controllables_lock);
3012 Controllables::iterator x = controllables.find (boost::shared_ptr<Controllable>(c, null_deleter()));
3014 if (x != controllables.end()) {
3015 controllables.erase (x);
3019 boost::shared_ptr<Controllable>
3020 Session::controllable_by_id (const PBD::ID& id)
3022 Glib::Threads::Mutex::Lock lm (controllables_lock);
3024 for (Controllables::iterator i = controllables.begin(); i != controllables.end(); ++i) {
3025 if ((*i)->id() == id) {
3030 return boost::shared_ptr<Controllable>();
3033 boost::shared_ptr<Controllable>
3034 Session::controllable_by_descriptor (const ControllableDescriptor& desc)
3036 boost::shared_ptr<Controllable> c;
3037 boost::shared_ptr<Route> r;
3039 switch (desc.top_level_type()) {
3040 case ControllableDescriptor::NamedRoute:
3042 std::string str = desc.top_level_name();
3043 if (str == "Master" || str == "master") {
3045 } else if (str == "control" || str == "listen") {
3048 r = route_by_name (desc.top_level_name());
3053 case ControllableDescriptor::RemoteControlID:
3054 r = route_by_remote_id (desc.rid());
3062 switch (desc.subtype()) {
3063 case ControllableDescriptor::Gain:
3064 c = r->gain_control ();
3067 case ControllableDescriptor::Solo:
3068 c = r->solo_control();
3071 case ControllableDescriptor::Mute:
3072 c = r->mute_control();
3075 case ControllableDescriptor::Recenable:
3077 boost::shared_ptr<Track> t = boost::dynamic_pointer_cast<Track>(r);
3080 c = t->rec_enable_control ();
3085 case ControllableDescriptor::PanDirection:
3087 c = r->pannable()->pan_azimuth_control;
3091 case ControllableDescriptor::PanWidth:
3093 c = r->pannable()->pan_width_control;
3097 case ControllableDescriptor::PanElevation:
3099 c = r->pannable()->pan_elevation_control;
3103 case ControllableDescriptor::Balance:
3104 /* XXX simple pan control */
3107 case ControllableDescriptor::PluginParameter:
3109 uint32_t plugin = desc.target (0);
3110 uint32_t parameter_index = desc.target (1);
3112 /* revert to zero based counting */
3118 if (parameter_index > 0) {
3122 boost::shared_ptr<Processor> p = r->nth_plugin (plugin);
3125 c = boost::dynamic_pointer_cast<ARDOUR::AutomationControl>(
3126 p->control(Evoral::Parameter(PluginAutomation, 0, parameter_index)));
3131 case ControllableDescriptor::SendGain:
3133 uint32_t send = desc.target (0);
3135 /* revert to zero-based counting */
3141 boost::shared_ptr<Processor> p = r->nth_send (send);
3144 boost::shared_ptr<Send> s = boost::dynamic_pointer_cast<Send>(p);
3145 boost::shared_ptr<Amp> a = s->amp();
3148 c = s->amp()->gain_control();
3155 /* relax and return a null pointer */
3163 Session::add_instant_xml (XMLNode& node, bool write_to_config)
3166 Stateful::add_instant_xml (node, _path);
3169 if (write_to_config) {
3170 Config->add_instant_xml (node);
3175 Session::instant_xml (const string& node_name)
3177 return Stateful::instant_xml (node_name, _path);
3181 Session::save_history (string snapshot_name)
3189 if (!Config->get_save_history() || Config->get_saved_history_depth() < 0 ||
3190 (_history.undo_depth() == 0 && _history.redo_depth() == 0)) {
3194 if (snapshot_name.empty()) {
3195 snapshot_name = _current_snapshot_name;
3198 const string history_filename = legalize_for_path (snapshot_name) + history_suffix;
3199 const string backup_filename = history_filename + backup_suffix;
3200 const std::string xml_path(Glib::build_filename (_session_dir->root_path(), history_filename));
3201 const std::string backup_path(Glib::build_filename (_session_dir->root_path(), backup_filename));
3203 if (Glib::file_test (xml_path, Glib::FILE_TEST_EXISTS)) {
3204 if (::g_rename (xml_path.c_str(), backup_path.c_str()) != 0) {
3205 error << _("could not backup old history file, current history not saved") << endmsg;
3210 tree.set_root (&_history.get_state (Config->get_saved_history_depth()));
3212 if (!tree.write (xml_path))
3214 error << string_compose (_("history could not be saved to %1"), xml_path) << endmsg;
3216 if (g_remove (xml_path.c_str()) != 0) {
3217 error << string_compose(_("Could not remove history file at path \"%1\" (%2)"),
3218 xml_path, g_strerror (errno)) << endmsg;
3220 if (::g_rename (backup_path.c_str(), xml_path.c_str()) != 0) {
3221 error << string_compose (_("could not restore history file from backup %1 (%2)"),
3222 backup_path, g_strerror (errno)) << endmsg;
3232 Session::restore_history (string snapshot_name)
3236 if (snapshot_name.empty()) {
3237 snapshot_name = _current_snapshot_name;
3240 const std::string xml_filename = legalize_for_path (snapshot_name) + history_suffix;
3241 const std::string xml_path(Glib::build_filename (_session_dir->root_path(), xml_filename));
3243 info << "Loading history from " << xml_path << endmsg;
3245 if (!Glib::file_test (xml_path, Glib::FILE_TEST_EXISTS)) {
3246 info << string_compose (_("%1: no history file \"%2\" for this session."),
3247 _name, xml_path) << endmsg;
3251 if (!tree.read (xml_path)) {
3252 error << string_compose (_("Could not understand session history file \"%1\""),
3253 xml_path) << endmsg;
3260 for (XMLNodeConstIterator it = tree.root()->children().begin(); it != tree.root()->children().end(); it++) {
3263 UndoTransaction* ut = new UndoTransaction ();
3266 ut->set_name(t->property("name")->value());
3267 stringstream ss(t->property("tv-sec")->value());
3269 ss.str(t->property("tv-usec")->value());
3271 ut->set_timestamp(tv);
3273 for (XMLNodeConstIterator child_it = t->children().begin();
3274 child_it != t->children().end(); child_it++)
3276 XMLNode *n = *child_it;
3279 if (n->name() == "MementoCommand" ||
3280 n->name() == "MementoUndoCommand" ||
3281 n->name() == "MementoRedoCommand") {
3283 if ((c = memento_command_factory(n))) {
3287 } else if (n->name() == "NoteDiffCommand") {
3288 PBD::ID id (n->property("midi-source")->value());
3289 boost::shared_ptr<MidiSource> midi_source =
3290 boost::dynamic_pointer_cast<MidiSource, Source>(source_by_id(id));
3292 ut->add_command (new MidiModel::NoteDiffCommand(midi_source->model(), *n));
3294 error << _("Failed to downcast MidiSource for NoteDiffCommand") << endmsg;
3297 } else if (n->name() == "SysExDiffCommand") {
3299 PBD::ID id (n->property("midi-source")->value());
3300 boost::shared_ptr<MidiSource> midi_source =
3301 boost::dynamic_pointer_cast<MidiSource, Source>(source_by_id(id));
3303 ut->add_command (new MidiModel::SysExDiffCommand (midi_source->model(), *n));
3305 error << _("Failed to downcast MidiSource for SysExDiffCommand") << endmsg;
3308 } else if (n->name() == "PatchChangeDiffCommand") {
3310 PBD::ID id (n->property("midi-source")->value());
3311 boost::shared_ptr<MidiSource> midi_source =
3312 boost::dynamic_pointer_cast<MidiSource, Source>(source_by_id(id));
3314 ut->add_command (new MidiModel::PatchChangeDiffCommand (midi_source->model(), *n));
3316 error << _("Failed to downcast MidiSource for PatchChangeDiffCommand") << endmsg;
3319 } else if (n->name() == "StatefulDiffCommand") {
3320 if ((c = stateful_diff_command_factory (n))) {
3321 ut->add_command (c);
3324 error << string_compose(_("Couldn't figure out how to make a Command out of a %1 XMLNode."), n->name()) << endmsg;
3335 Session::config_changed (std::string p, bool ours)
3341 if (p == "seamless-loop") {
3343 } else if (p == "rf-speed") {
3345 } else if (p == "auto-loop") {
3347 } else if (p == "auto-input") {
3349 if (Config->get_monitoring_model() == HardwareMonitoring && transport_rolling()) {
3350 /* auto-input only makes a difference if we're rolling */
3351 set_track_monitor_input_status (!config.get_auto_input());
3354 } else if (p == "punch-in") {
3358 if ((location = _locations->auto_punch_location()) != 0) {
3360 if (config.get_punch_in ()) {
3361 replace_event (SessionEvent::PunchIn, location->start());
3363 remove_event (location->start(), SessionEvent::PunchIn);
3367 } else if (p == "punch-out") {
3371 if ((location = _locations->auto_punch_location()) != 0) {
3373 if (config.get_punch_out()) {
3374 replace_event (SessionEvent::PunchOut, location->end());
3376 clear_events (SessionEvent::PunchOut);
3380 } else if (p == "edit-mode") {
3382 Glib::Threads::Mutex::Lock lm (playlists->lock);
3384 for (SessionPlaylists::List::iterator i = playlists->playlists.begin(); i != playlists->playlists.end(); ++i) {
3385 (*i)->set_edit_mode (Config->get_edit_mode ());
3388 } else if (p == "use-video-sync") {
3390 waiting_for_sync_offset = config.get_use_video_sync();
3392 } else if (p == "mmc-control") {
3394 //poke_midi_thread ();
3396 } else if (p == "mmc-device-id" || p == "mmc-receive-id" || p == "mmc-receive-device-id") {
3398 _mmc->set_receive_device_id (Config->get_mmc_receive_device_id());
3400 } else if (p == "mmc-send-id" || p == "mmc-send-device-id") {
3402 _mmc->set_send_device_id (Config->get_mmc_send_device_id());
3404 } else if (p == "midi-control") {
3406 //poke_midi_thread ();
3408 } else if (p == "raid-path") {
3410 setup_raid_path (config.get_raid_path());
3412 } else if (p == "timecode-format") {
3416 } else if (p == "video-pullup") {
3420 } else if (p == "seamless-loop") {
3422 if (play_loop && transport_rolling()) {
3423 // to reset diskstreams etc
3424 request_play_loop (true);
3427 } else if (p == "rf-speed") {
3429 cumulative_rf_motion = 0;
3432 } else if (p == "click-sound") {
3434 setup_click_sounds (1);
3436 } else if (p == "click-emphasis-sound") {
3438 setup_click_sounds (-1);
3440 } else if (p == "clicking") {
3442 if (Config->get_clicking()) {
3443 if (_click_io && click_data) { // don't require emphasis data
3450 } else if (p == "click-gain") {
3453 _click_gain->set_gain (Config->get_click_gain(), this);
3456 } else if (p == "send-mtc") {
3458 if (Config->get_send_mtc ()) {
3459 /* mark us ready to send */
3460 next_quarter_frame_to_send = 0;
3463 } else if (p == "send-mmc") {
3465 _mmc->enable_send (Config->get_send_mmc ());
3467 } else if (p == "midi-feedback") {
3469 session_midi_feedback = Config->get_midi_feedback();
3471 } else if (p == "jack-time-master") {
3473 engine().reset_timebase ();
3475 } else if (p == "native-file-header-format") {
3477 if (!first_file_header_format_reset) {
3478 reset_native_file_format ();
3481 first_file_header_format_reset = false;
3483 } else if (p == "native-file-data-format") {
3485 if (!first_file_data_format_reset) {
3486 reset_native_file_format ();
3489 first_file_data_format_reset = false;
3491 } else if (p == "external-sync") {
3492 if (!config.get_external_sync()) {
3493 drop_sync_source ();
3495 switch_to_sync_source (Config->get_sync_source());
3497 } else if (p == "denormal-model") {
3499 } else if (p == "history-depth") {
3500 set_history_depth (Config->get_history_depth());
3501 } else if (p == "remote-model") {
3502 /* XXX DO SOMETHING HERE TO TELL THE GUI THAT WE NEED
3505 } else if (p == "initial-program-change") {
3507 if (_mmc->output_port() && Config->get_initial_program_change() >= 0) {
3510 buf[0] = MIDI::program; // channel zero by default
3511 buf[1] = (Config->get_initial_program_change() & 0x7f);
3513 _mmc->output_port()->midimsg (buf, sizeof (buf), 0);
3515 } else if (p == "solo-mute-override") {
3516 // catch_up_on_solo_mute_override ();
3517 } else if (p == "listen-position" || p == "pfl-position") {
3518 listen_position_changed ();
3519 } else if (p == "solo-control-is-listen-control") {
3520 solo_control_mode_changed ();
3521 } else if (p == "solo-mute-gain") {
3522 _solo_cut_control->Changed();
3523 } else if (p == "timecode-offset" || p == "timecode-offset-negative") {
3524 last_timecode_valid = false;
3525 } else if (p == "playback-buffer-seconds") {
3526 AudioSource::allocate_working_buffers (frame_rate());
3527 } else if (p == "ltc-source-port") {
3528 reconnect_ltc_input ();
3529 } else if (p == "ltc-sink-port") {
3530 reconnect_ltc_output ();
3531 } else if (p == "timecode-generator-offset") {
3532 ltc_tx_parse_offset();
3539 Session::set_history_depth (uint32_t d)
3541 _history.set_depth (d);
3545 Session::load_diskstreams_2X (XMLNode const & node, int)
3548 XMLNodeConstIterator citer;
3550 clist = node.children();
3552 for (citer = clist.begin(); citer != clist.end(); ++citer) {
3555 /* diskstreams added automatically by DiskstreamCreated handler */
3556 if ((*citer)->name() == "AudioDiskstream" || (*citer)->name() == "DiskStream") {
3557 boost::shared_ptr<AudioDiskstream> dsp (new AudioDiskstream (*this, **citer));
3558 _diskstreams_2X.push_back (dsp);
3560 error << _("Session: unknown diskstream type in XML") << endmsg;
3564 catch (failed_constructor& err) {
3565 error << _("Session: could not load diskstream via XML state") << endmsg;
3573 /** Connect things to the MMC object */
3575 Session::setup_midi_machine_control ()
3577 _mmc = new MIDI::MachineControl;
3578 _mmc->set_ports (_midi_ports->mmc_input_port(), _midi_ports->mmc_output_port());
3580 _mmc->Play.connect_same_thread (*this, boost::bind (&Session::mmc_deferred_play, this, _1));
3581 _mmc->DeferredPlay.connect_same_thread (*this, boost::bind (&Session::mmc_deferred_play, this, _1));
3582 _mmc->Stop.connect_same_thread (*this, boost::bind (&Session::mmc_stop, this, _1));
3583 _mmc->FastForward.connect_same_thread (*this, boost::bind (&Session::mmc_fast_forward, this, _1));
3584 _mmc->Rewind.connect_same_thread (*this, boost::bind (&Session::mmc_rewind, this, _1));
3585 _mmc->Pause.connect_same_thread (*this, boost::bind (&Session::mmc_pause, this, _1));
3586 _mmc->RecordPause.connect_same_thread (*this, boost::bind (&Session::mmc_record_pause, this, _1));
3587 _mmc->RecordStrobe.connect_same_thread (*this, boost::bind (&Session::mmc_record_strobe, this, _1));
3588 _mmc->RecordExit.connect_same_thread (*this, boost::bind (&Session::mmc_record_exit, this, _1));
3589 _mmc->Locate.connect_same_thread (*this, boost::bind (&Session::mmc_locate, this, _1, _2));
3590 _mmc->Step.connect_same_thread (*this, boost::bind (&Session::mmc_step, this, _1, _2));
3591 _mmc->Shuttle.connect_same_thread (*this, boost::bind (&Session::mmc_shuttle, this, _1, _2, _3));
3592 _mmc->TrackRecordStatusChange.connect_same_thread (*this, boost::bind (&Session::mmc_record_enable, this, _1, _2, _3));
3594 /* also handle MIDI SPP because its so common */
3596 _mmc->SPPStart.connect_same_thread (*this, boost::bind (&Session::spp_start, this));
3597 _mmc->SPPContinue.connect_same_thread (*this, boost::bind (&Session::spp_continue, this));
3598 _mmc->SPPStop.connect_same_thread (*this, boost::bind (&Session::spp_stop, this));
3601 boost::shared_ptr<Controllable>
3602 Session::solo_cut_control() const
3604 /* the solo cut control is a bit of an anomaly, at least as of Febrary 2011. There are no other
3605 controls in Ardour that currently get presented to the user in the GUI that require
3606 access as a Controllable and are also NOT owned by some SessionObject (e.g. Route, or MonitorProcessor).
3608 its actually an RCConfiguration parameter, so we use a ProxyControllable to wrap
3609 it up as a Controllable. Changes to the Controllable will just map back to the RCConfiguration
3613 return _solo_cut_control;
3617 Session::rename (const std::string& new_name)
3619 string legal_name = legalize_for_path (new_name);
3625 string const old_sources_root = _session_dir->sources_root();
3627 if (!_writable || (_state_of_the_state & CannotSave)) {
3628 error << _("Cannot rename read-only session.") << endmsg;
3629 return 0; // don't show "messed up" warning
3631 if (record_status() == Recording) {
3632 error << _("Cannot rename session while recording") << endmsg;
3633 return 0; // don't show "messed up" warning
3636 StateProtector stp (this);
3641 * interchange subdirectory
3645 * Backup files are left unchanged and not renamed.
3648 /* pass one: not 100% safe check that the new directory names don't
3652 vector<space_and_path> new_session_dirs;
3654 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
3659 /* this is a stupid hack because Glib::path_get_dirname() is
3660 * lexical-only, and so passing it /a/b/c/ gives a different
3661 * result than passing it /a/b/c ...
3664 if (oldstr[oldstr.length()-1] == G_DIR_SEPARATOR) {
3665 oldstr = oldstr.substr (0, oldstr.length() - 1);
3668 string base = Glib::path_get_dirname (oldstr);
3669 string p = Glib::path_get_basename (oldstr);
3671 newstr = Glib::build_filename (base, legal_name);
3673 if (Glib::file_test (newstr, Glib::FILE_TEST_EXISTS)) {
3679 sp.blocks = 0; // not needed
3680 new_session_dirs.push_back(sp);
3685 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
3690 /* this is a stupid hack because Glib::path_get_dirname() is
3691 * lexical-only, and so passing it /a/b/c/ gives a different
3692 * result than passing it /a/b/c ...
3695 if (oldstr[oldstr.length()-1] == G_DIR_SEPARATOR) {
3696 oldstr = oldstr.substr (0, oldstr.length() - 1);
3699 string base = Glib::path_get_dirname (oldstr);
3700 string p = Glib::path_get_basename (oldstr);
3702 newstr = Glib::build_filename (base, legal_name);
3704 cerr << "Rename " << oldstr << " => " << newstr << endl;
3706 if (::g_rename (oldstr.c_str(), newstr.c_str()) != 0) {
3707 error << string_compose (_("renaming %1 as %2 failed (%3)"), oldstr, newstr, g_strerror (errno)) << endmsg;
3712 (*_session_dir) = newstr;
3717 /* directory below interchange */
3719 v.push_back (newstr);
3720 v.push_back (interchange_dir_name);
3723 oldstr = Glib::build_filename (v);
3726 v.push_back (newstr);
3727 v.push_back (interchange_dir_name);
3728 v.push_back (legal_name);
3730 newstr = Glib::build_filename (v);
3732 cerr << "Rename " << oldstr << " => " << newstr << endl;
3734 if (::g_rename (oldstr.c_str(), newstr.c_str()) != 0) {
3735 error << string_compose (_("renaming %1 as %2 failed (%3)"), oldstr, newstr, g_strerror (errno)) << endmsg;
3740 session_dirs = new_session_dirs;
3744 oldstr = Glib::build_filename (newpath, _current_snapshot_name) + statefile_suffix;
3745 newstr= Glib::build_filename (newpath, legal_name) + statefile_suffix;
3747 cerr << "Rename " << oldstr << " => " << newstr << endl;
3749 if (::g_rename (oldstr.c_str(), newstr.c_str()) != 0) {
3750 error << string_compose (_("renaming %1 as %2 failed (%3)"), oldstr, newstr, g_strerror (errno)) << endmsg;
3757 oldstr = Glib::build_filename (newpath, _current_snapshot_name) + history_suffix;
3759 if (Glib::file_test (oldstr, Glib::FILE_TEST_EXISTS)) {
3760 newstr = Glib::build_filename (newpath, legal_name) + history_suffix;
3762 cerr << "Rename " << oldstr << " => " << newstr << endl;
3764 if (::g_rename (oldstr.c_str(), newstr.c_str()) != 0) {
3765 error << string_compose (_("renaming %1 as %2 failed (%3)"), oldstr, newstr, g_strerror (errno)) << endmsg;
3770 /* update file source paths */
3772 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ++i) {
3773 boost::shared_ptr<FileSource> fs = boost::dynamic_pointer_cast<FileSource> (i->second);
3775 string p = fs->path ();
3776 boost::replace_all (p, old_sources_root, _session_dir->sources_root());
3778 SourceFactory::setup_peakfile(i->second, true);
3782 /* remove old name from recent sessions */
3784 remove_recent_sessions (_path);
3787 _current_snapshot_name = new_name;
3790 /* re-add directory separator - reverse hack to oldstr above */
3791 if (_path[_path.length()-1] != G_DIR_SEPARATOR) {
3792 _path += G_DIR_SEPARATOR;
3797 /* save state again to get everything just right */
3799 save_state (_current_snapshot_name);
3802 /* add to recent sessions */
3804 store_recent_sessions (new_name, _path);
3810 Session::get_session_info_from_path (XMLTree& tree, const string& xmlpath)
3812 if (!Glib::file_test (xmlpath, Glib::FILE_TEST_EXISTS)) {
3816 if (!tree.read (xmlpath)) {
3824 Session::get_info_from_path (const string& xmlpath, float& sample_rate, SampleFormat& data_format)
3827 bool found_sr = false;
3828 bool found_data_format = false;
3830 if (get_session_info_from_path (tree, xmlpath)) {
3836 const XMLProperty* prop;
3837 if ((prop = tree.root()->property (X_("sample-rate"))) != 0) {
3838 sample_rate = atoi (prop->value());
3842 const XMLNodeList& children (tree.root()->children());
3843 for (XMLNodeList::const_iterator c = children.begin(); c != children.end(); ++c) {
3844 const XMLNode* child = *c;
3845 if (child->name() == "Config") {
3846 const XMLNodeList& options (child->children());
3847 for (XMLNodeList::const_iterator oc = options.begin(); oc != options.end(); ++oc) {
3848 const XMLNode* option = *oc;
3849 const XMLProperty* name = option->property("name");
3855 if (name->value() == "native-file-data-format") {
3856 const XMLProperty* value = option->property ("value");
3858 SampleFormat fmt = (SampleFormat) string_2_enum (option->property ("value")->value(), fmt);
3860 found_data_format = true;
3866 if (found_data_format) {
3871 return !(found_sr && found_data_format); // zero if they are both found
3874 typedef std::vector<boost::shared_ptr<FileSource> > SeveralFileSources;
3875 typedef std::map<std::string,SeveralFileSources> SourcePathMap;
3878 Session::bring_all_sources_into_session (boost::function<void(uint32_t,uint32_t,string)> callback)
3882 SourcePathMap source_path_map;
3884 boost::shared_ptr<AudioFileSource> afs;
3889 Glib::Threads::Mutex::Lock lm (source_lock);
3891 cerr << " total sources = " << sources.size();
3893 for (SourceMap::const_iterator i = sources.begin(); i != sources.end(); ++i) {
3894 boost::shared_ptr<FileSource> fs = boost::dynamic_pointer_cast<FileSource> (i->second);
3900 if (fs->within_session()) {
3901 cerr << "skip " << fs->name() << endl;
3905 if (source_path_map.find (fs->path()) != source_path_map.end()) {
3906 source_path_map[fs->path()].push_back (fs);
3908 SeveralFileSources v;
3910 source_path_map.insert (make_pair (fs->path(), v));
3916 cerr << " fsources = " << total << endl;
3918 for (SourcePathMap::iterator i = source_path_map.begin(); i != source_path_map.end(); ++i) {
3920 /* tell caller where we are */
3922 string old_path = i->first;
3924 callback (n, total, old_path);
3926 cerr << old_path << endl;
3930 switch (i->second.front()->type()) {
3931 case DataType::AUDIO:
3932 new_path = new_audio_source_path_for_embedded (old_path);
3935 case DataType::MIDI:
3939 cerr << "Move " << old_path << " => " << new_path << endl;
3941 if (!copy_file (old_path, new_path)) {
3942 cerr << "failed !\n";
3946 /* make sure we stop looking in the external
3947 dir/folder. Remember, this is an all-or-nothing
3948 operations, it doesn't merge just some files.
3950 remove_dir_from_search_path (Glib::path_get_dirname (old_path), i->second.front()->type());
3952 for (SeveralFileSources::iterator f = i->second.begin(); f != i->second.end(); ++f) {
3953 (*f)->set_path (new_path);
3958 save_state ("", false, false);