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>
57 #include <glibmm/fileutils.h>
59 #include <boost/algorithm/string.hpp>
61 #include "midi++/mmc.h"
62 #include "midi++/port.h"
64 #include "evoral/SMF.hpp"
66 #include "pbd/boost_debug.h"
67 #include "pbd/basename.h"
68 #include "pbd/controllable_descriptor.h"
69 #include "pbd/enumwriter.h"
70 #include "pbd/error.h"
71 #include "pbd/file_utils.h"
72 #include "pbd/pathexpand.h"
73 #include "pbd/pthread_utils.h"
74 #include "pbd/stacktrace.h"
75 #include "pbd/convert.h"
76 #include "pbd/localtime_r.h"
78 #include "ardour/amp.h"
79 #include "ardour/async_midi_port.h"
80 #include "ardour/audio_diskstream.h"
81 #include "ardour/audio_track.h"
82 #include "ardour/audioengine.h"
83 #include "ardour/audiofilesource.h"
84 #include "ardour/audioregion.h"
85 #include "ardour/automation_control.h"
86 #include "ardour/butler.h"
87 #include "ardour/control_protocol_manager.h"
88 #include "ardour/directory_names.h"
89 #include "ardour/filename_extensions.h"
90 #include "ardour/graph.h"
91 #include "ardour/location.h"
92 #include "ardour/midi_model.h"
93 #include "ardour/midi_patch_manager.h"
94 #include "ardour/midi_region.h"
95 #include "ardour/midi_scene_changer.h"
96 #include "ardour/midi_source.h"
97 #include "ardour/midi_track.h"
98 #include "ardour/pannable.h"
99 #include "ardour/playlist_factory.h"
100 #include "ardour/playlist_source.h"
101 #include "ardour/port.h"
102 #include "ardour/processor.h"
103 #include "ardour/proxy_controllable.h"
104 #include "ardour/recent_sessions.h"
105 #include "ardour/region_factory.h"
106 #include "ardour/route_group.h"
107 #include "ardour/send.h"
108 #include "ardour/session.h"
109 #include "ardour/session_directory.h"
110 #include "ardour/session_metadata.h"
111 #include "ardour/session_playlists.h"
112 #include "ardour/session_state_utils.h"
113 #include "ardour/silentfilesource.h"
114 #include "ardour/sndfilesource.h"
115 #include "ardour/source_factory.h"
116 #include "ardour/speakers.h"
117 #include "ardour/template_utils.h"
118 #include "ardour/tempo.h"
119 #include "ardour/ticker.h"
120 #include "ardour/user_bundle.h"
122 #include "control_protocol/control_protocol.h"
128 using namespace ARDOUR;
132 Session::pre_engine_init (string fullpath)
134 if (fullpath.empty()) {
136 throw failed_constructor();
139 /* discover canonical fullpath */
141 _path = canonical_path(fullpath);
145 _is_new = !Glib::file_test (_path, Glib::FileTest (G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR));
147 /* finish initialization that can't be done in a normal C++ constructor
151 timerclear (&last_mmc_step);
152 g_atomic_int_set (&processing_prohibited, 0);
153 g_atomic_int_set (&_record_status, Disabled);
154 g_atomic_int_set (&_playback_load, 100);
155 g_atomic_int_set (&_capture_load, 100);
157 _all_route_group->set_active (true, this);
158 interpolation.add_channel_to (0, 0);
160 if (config.get_use_video_sync()) {
161 waiting_for_sync_offset = true;
163 waiting_for_sync_offset = false;
166 last_rr_session_dir = session_dirs.begin();
168 set_history_depth (Config->get_history_depth());
170 /* default: assume simple stereo speaker configuration */
172 _speakers->setup_default_speakers (2);
174 _solo_cut_control.reset (new ProxyControllable (_("solo cut control (dB)"), PBD::Controllable::GainLike,
175 boost::bind (&RCConfiguration::set_solo_mute_gain, Config, _1),
176 boost::bind (&RCConfiguration::get_solo_mute_gain, Config)));
177 add_controllable (_solo_cut_control);
179 /* These are all static "per-class" signals */
181 SourceFactory::SourceCreated.connect_same_thread (*this, boost::bind (&Session::add_source, this, _1));
182 PlaylistFactory::PlaylistCreated.connect_same_thread (*this, boost::bind (&Session::add_playlist, this, _1, _2));
183 AutomationList::AutomationListCreated.connect_same_thread (*this, boost::bind (&Session::add_automation_list, this, _1));
184 Controllable::Destroyed.connect_same_thread (*this, boost::bind (&Session::remove_controllable, this, _1));
185 IO::PortCountChanged.connect_same_thread (*this, boost::bind (&Session::ensure_buffers, this, _1));
187 /* stop IO objects from doing stuff until we're ready for them */
189 Delivery::disable_panners ();
190 IO::disable_connecting ();
192 AudioFileSource::set_peak_dir (_session_dir->peak_path());
196 Session::post_engine_init ()
198 BootMessage (_("Set block size and sample rate"));
200 set_block_size (_engine.samples_per_cycle());
201 set_frame_rate (_engine.sample_rate());
203 BootMessage (_("Using configuration"));
205 _midi_ports = new MidiPortManager;
207 MIDISceneChanger* msc;
209 _scene_changer = msc = new MIDISceneChanger (*this);
210 msc->set_input_port (scene_input_port());
211 msc->set_output_port (scene_out());
213 boost::function<framecnt_t(void)> timer_func (boost::bind (&Session::audible_frame, this));
214 boost::dynamic_pointer_cast<AsyncMIDIPort>(scene_in())->set_timer (timer_func);
216 setup_midi_machine_control ();
218 if (_butler->start_thread()) {
222 if (start_midi_thread ()) {
226 setup_click_sounds (0);
227 setup_midi_control ();
229 _engine.Halted.connect_same_thread (*this, boost::bind (&Session::engine_halted, this));
230 _engine.Xrun.connect_same_thread (*this, boost::bind (&Session::xrun_recovery, this));
233 /* tempo map requires sample rate knowledge */
236 _tempo_map = new TempoMap (_current_frame_rate);
237 _tempo_map->PropertyChanged.connect_same_thread (*this, boost::bind (&Session::tempo_map_changed, this, _1));
239 /* MidiClock requires a tempo map */
241 midi_clock = new MidiClockTicker ();
242 midi_clock->set_session (this);
244 /* crossfades require sample rate knowledge */
246 SndFileSource::setup_standard_crossfades (*this, frame_rate());
247 _engine.GraphReordered.connect_same_thread (*this, boost::bind (&Session::graph_reordered, this));
249 AudioDiskstream::allocate_working_buffers();
250 refresh_disk_space ();
252 /* we're finally ready to call set_state() ... all objects have
253 * been created, the engine is running.
257 if (set_state (*state_tree->root(), Stateful::loading_state_version)) {
261 // set_state() will call setup_raid_path(), but if it's a new session we need
262 // to call setup_raid_path() here.
263 setup_raid_path (_path);
268 boost::function<void (std::string)> ff (boost::bind (&Session::config_changed, this, _1, false));
269 boost::function<void (std::string)> ft (boost::bind (&Session::config_changed, this, _1, true));
271 Config->map_parameters (ff);
272 config.map_parameters (ft);
274 /* Reset all panners */
276 Delivery::reset_panners ();
278 /* this will cause the CPM to instantiate any protocols that are in use
279 * (or mandatory), which will pass it this Session, and then call
280 * set_state() on each instantiated protocol to match stored state.
283 ControlProtocolManager::instance().set_session (this);
285 /* This must be done after the ControlProtocolManager set_session above,
286 as it will set states for ports which the ControlProtocolManager creates.
289 // XXX set state of MIDI::Port's
290 // MidiPortManager::instance()->set_port_states (Config->midi_port_states ());
292 /* And this must be done after the MIDI::Manager::set_port_states as
293 * it will try to make connections whose details are loaded by set_port_states.
298 /* Let control protocols know that we are now all connected, so they
299 * could start talking to surfaces if they want to.
302 ControlProtocolManager::instance().midi_connectivity_established ();
304 if (_is_new && !no_auto_connect()) {
305 Glib::Threads::Mutex::Lock lm (AudioEngine::instance()->process_lock());
306 auto_connect_master_bus ();
309 _state_of_the_state = StateOfTheState (_state_of_the_state & ~(CannotSave|Dirty));
311 /* update latencies */
313 initialize_latencies ();
315 _locations->added.connect_same_thread (*this, boost::bind (&Session::location_added, this, _1));
316 _locations->removed.connect_same_thread (*this, boost::bind (&Session::location_removed, this, _1));
317 _locations->changed.connect_same_thread (*this, boost::bind (&Session::locations_changed, this));
319 } catch (AudioEngine::PortRegistrationFailure& err) {
320 /* handle this one in a different way than all others, so that its clear what happened */
321 error << err.what() << endmsg;
327 BootMessage (_("Reset Remote Controls"));
329 // send_full_time_code (0);
330 _engine.transport_locate (0);
332 send_immediate_mmc (MIDI::MachineControlCommand (MIDI::MachineControl::cmdMmcReset));
333 send_immediate_mmc (MIDI::MachineControlCommand (Timecode::Time ()));
335 MIDI::Name::MidiPatchManager::instance().set_session (this);
338 /* initial program change will be delivered later; see ::config_changed() */
340 _state_of_the_state = Clean;
342 Port::set_connecting_blocked (false);
344 DirtyChanged (); /* EMIT SIGNAL */
348 } else if (state_was_pending) {
350 remove_pending_capture_state ();
351 state_was_pending = false;
358 Session::raid_path () const
360 Searchpath raid_search_path;
362 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
363 raid_search_path += (*i).path;
366 return raid_search_path.to_string ();
370 Session::setup_raid_path (string path)
379 session_dirs.clear ();
381 Searchpath search_path(path);
382 Searchpath sound_search_path;
383 Searchpath midi_search_path;
385 for (Searchpath::const_iterator i = search_path.begin(); i != search_path.end(); ++i) {
387 sp.blocks = 0; // not needed
388 session_dirs.push_back (sp);
390 SessionDirectory sdir(sp.path);
392 sound_search_path += sdir.sound_path ();
393 midi_search_path += sdir.midi_path ();
396 // reset the round-robin soundfile path thingie
397 last_rr_session_dir = session_dirs.begin();
401 Session::path_is_within_session (const std::string& path)
403 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
404 if (PBD::path_is_within (i->path, path)) {
412 Session::ensure_subdirs ()
416 dir = session_directory().peak_path();
418 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
419 error << string_compose(_("Session: cannot create session peakfile folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
423 dir = session_directory().sound_path();
425 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
426 error << string_compose(_("Session: cannot create session sounds dir \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
430 dir = session_directory().midi_path();
432 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
433 error << string_compose(_("Session: cannot create session midi dir \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
437 dir = session_directory().dead_path();
439 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
440 error << string_compose(_("Session: cannot create session dead sounds folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
444 dir = session_directory().export_path();
446 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
447 error << string_compose(_("Session: cannot create session export folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
451 dir = analysis_dir ();
453 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
454 error << string_compose(_("Session: cannot create session analysis folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
458 dir = plugins_dir ();
460 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
461 error << string_compose(_("Session: cannot create session plugins folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
465 dir = externals_dir ();
467 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
468 error << string_compose(_("Session: cannot create session externals folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
475 /** @param session_template directory containing session template, or empty.
476 * Caller must not hold process lock.
479 Session::create (const string& session_template, BusProfile* bus_profile)
481 if (g_mkdir_with_parents (_path.c_str(), 0755) < 0) {
482 error << string_compose(_("Session: cannot create session folder \"%1\" (%2)"), _path, strerror (errno)) << endmsg;
486 if (ensure_subdirs ()) {
490 _writable = exists_and_writable (_path);
492 if (!session_template.empty()) {
493 std::string in_path = session_template_dir_to_file (session_template);
495 ifstream in(in_path.c_str());
498 /* no need to call legalize_for_path() since the string
499 * in session_template is already a legal path name
501 string out_path = Glib::build_filename (_session_dir->root_path(), _name + statefile_suffix);
503 ofstream out(out_path.c_str());
509 /* Copy plugin state files from template to new session */
510 std::string template_plugins = Glib::build_filename (session_template, X_("plugins"));
511 copy_recurse (template_plugins, plugins_dir ());
516 error << string_compose (_("Could not open %1 for writing session template"), out_path)
522 error << string_compose (_("Could not open session template %1 for reading"), in_path)
529 /* set initial start + end point */
531 _state_of_the_state = Clean;
533 /* set up Master Out and Control Out if necessary */
538 ChanCount count(DataType::AUDIO, bus_profile->master_out_channels);
540 if (bus_profile->master_out_channels) {
541 boost::shared_ptr<Route> r (new Route (*this, _("Master"), Route::MasterOut, DataType::AUDIO));
545 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
546 // boost_debug_shared_ptr_mark_interesting (r.get(), "Route");
549 Glib::Threads::Mutex::Lock lm (AudioEngine::instance()->process_lock ());
550 r->input()->ensure_io (count, false, this);
551 r->output()->ensure_io (count, false, this);
557 /* prohibit auto-connect to master, because there isn't one */
558 bus_profile->output_ac = AutoConnectOption (bus_profile->output_ac & ~AutoConnectMaster);
562 add_routes (rl, false, false, false);
565 /* this allows the user to override settings with an environment variable.
568 if (no_auto_connect()) {
569 bus_profile->input_ac = AutoConnectOption (0);
570 bus_profile->output_ac = AutoConnectOption (0);
573 Config->set_input_auto_connect (bus_profile->input_ac);
574 Config->set_output_auto_connect (bus_profile->output_ac);
577 if (Config->get_use_monitor_bus() && bus_profile) {
578 add_monitor_section ();
585 Session::maybe_write_autosave()
587 if (dirty() && record_status() != Recording) {
588 save_state("", true);
593 Session::remove_pending_capture_state ()
595 std::string pending_state_file_path(_session_dir->root_path());
597 pending_state_file_path = Glib::build_filename (pending_state_file_path, legalize_for_path (_current_snapshot_name) + pending_suffix);
599 if (!Glib::file_test (pending_state_file_path, Glib::FILE_TEST_EXISTS)) return;
601 if (g_remove (pending_state_file_path.c_str()) != 0) {
602 error << string_compose(_("Could not remove pending capture state at path \"%1\" (%2)"),
603 pending_state_file_path, g_strerror (errno)) << endmsg;
607 /** Rename a state file.
608 * @param old_name Old snapshot name.
609 * @param new_name New snapshot name.
612 Session::rename_state (string old_name, string new_name)
614 if (old_name == _current_snapshot_name || old_name == _name) {
615 /* refuse to rename the current snapshot or the "main" one */
619 const string old_xml_filename = legalize_for_path (old_name) + statefile_suffix;
620 const string new_xml_filename = legalize_for_path (new_name) + statefile_suffix;
622 const std::string old_xml_path(Glib::build_filename (_session_dir->root_path(), old_xml_filename));
623 const std::string new_xml_path(Glib::build_filename (_session_dir->root_path(), new_xml_filename));
625 if (::g_rename (old_xml_path.c_str(), new_xml_path.c_str()) != 0) {
626 error << string_compose(_("could not rename snapshot %1 to %2 (%3)"),
627 old_name, new_name, g_strerror(errno)) << endmsg;
631 /** Remove a state file.
632 * @param snapshot_name Snapshot name.
635 Session::remove_state (string snapshot_name)
637 if (!_writable || snapshot_name == _current_snapshot_name || snapshot_name == _name) {
638 // refuse to remove the current snapshot or the "main" one
642 std::string xml_path(_session_dir->root_path());
644 xml_path = Glib::build_filename (xml_path, legalize_for_path (snapshot_name) + statefile_suffix);
646 if (!create_backup_file (xml_path)) {
647 // don't remove it if a backup can't be made
648 // create_backup_file will log the error.
653 if (g_remove (xml_path.c_str()) != 0) {
654 error << string_compose(_("Could not remove session file at path \"%1\" (%2)"),
655 xml_path, g_strerror (errno)) << endmsg;
659 /** @param snapshot_name Name to save under, without .ardour / .pending prefix */
661 Session::save_state (string snapshot_name, bool pending, bool switch_to_snapshot, bool template_only)
664 std::string xml_path(_session_dir->root_path());
666 /* prevent concurrent saves from different threads */
668 Glib::Threads::Mutex::Lock lm (save_state_lock);
670 if (!_writable || (_state_of_the_state & CannotSave)) {
674 if (g_atomic_int_get(&_suspend_save)) {
678 _save_queued = false;
680 if (!_engine.connected ()) {
681 error << string_compose (_("the %1 audio engine is not connected and state saving would lose all I/O connections. Session not saved"),
687 /* tell sources we're saving first, in case they write out to a new file
688 * which should be saved with the state rather than the old one */
689 for (SourceMap::const_iterator i = sources.begin(); i != sources.end(); ++i) {
691 i->second->session_saved();
692 } catch (Evoral::SMF::FileError& e) {
693 error << string_compose ("Could not write to MIDI file %1; MIDI data not saved.", e.file_name ()) << endmsg;
697 SessionSaveUnderway (); /* EMIT SIGNAL */
700 tree.set_root (&get_template());
702 tree.set_root (&get_state());
705 if (snapshot_name.empty()) {
706 snapshot_name = _current_snapshot_name;
707 } else if (switch_to_snapshot) {
708 _current_snapshot_name = snapshot_name;
713 /* proper save: use statefile_suffix (.ardour in English) */
715 xml_path = Glib::build_filename (xml_path, legalize_for_path (snapshot_name) + statefile_suffix);
717 /* make a backup copy of the old file */
719 if (Glib::file_test (xml_path, Glib::FILE_TEST_EXISTS) && !create_backup_file (xml_path)) {
720 // create_backup_file will log the error
726 /* pending save: use pending_suffix (.pending in English) */
727 xml_path = Glib::build_filename (xml_path, legalize_for_path (snapshot_name) + pending_suffix);
730 std::string tmp_path(_session_dir->root_path());
731 tmp_path = Glib::build_filename (tmp_path, legalize_for_path (snapshot_name) + temp_suffix);
733 cerr << "actually writing state to " << tmp_path << endl;
735 if (!tree.write (tmp_path)) {
736 error << string_compose (_("state could not be saved to %1"), tmp_path) << endmsg;
737 if (g_remove (tmp_path.c_str()) != 0) {
738 error << string_compose(_("Could not remove temporary session file at path \"%1\" (%2)"),
739 tmp_path, g_strerror (errno)) << endmsg;
745 cerr << "renaming state to " << xml_path << endl;
747 if (::g_rename (tmp_path.c_str(), xml_path.c_str()) != 0) {
748 error << string_compose (_("could not rename temporary session file %1 to %2 (%3)"),
749 tmp_path, xml_path, g_strerror(errno)) << endmsg;
750 if (g_remove (tmp_path.c_str()) != 0) {
751 error << string_compose(_("Could not remove temporary session file at path \"%1\" (%2)"),
752 tmp_path, g_strerror (errno)) << endmsg;
760 save_history (snapshot_name);
762 bool was_dirty = dirty();
764 _state_of_the_state = StateOfTheState (_state_of_the_state & ~Dirty);
767 DirtyChanged (); /* EMIT SIGNAL */
770 StateSaved (snapshot_name); /* EMIT SIGNAL */
777 Session::restore_state (string snapshot_name)
779 if (load_state (snapshot_name) == 0) {
780 set_state (*state_tree->root(), Stateful::loading_state_version);
787 Session::load_state (string snapshot_name)
792 state_was_pending = false;
794 /* check for leftover pending state from a crashed capture attempt */
796 std::string xmlpath(_session_dir->root_path());
797 xmlpath = Glib::build_filename (xmlpath, legalize_for_path (snapshot_name) + pending_suffix);
799 if (Glib::file_test (xmlpath, Glib::FILE_TEST_EXISTS)) {
801 /* there is pending state from a crashed capture attempt */
803 boost::optional<int> r = AskAboutPendingState();
804 if (r.get_value_or (1)) {
805 state_was_pending = true;
809 if (!state_was_pending) {
810 xmlpath = Glib::build_filename (_session_dir->root_path(), snapshot_name);
813 if (!Glib::file_test (xmlpath, Glib::FILE_TEST_EXISTS)) {
814 xmlpath = Glib::build_filename (_session_dir->root_path(), legalize_for_path (snapshot_name) + statefile_suffix);
815 if (!Glib::file_test (xmlpath, Glib::FILE_TEST_EXISTS)) {
816 error << string_compose(_("%1: session file \"%2\" doesn't exist!"), _name, xmlpath) << endmsg;
821 state_tree = new XMLTree;
825 _writable = exists_and_writable (xmlpath) && exists_and_writable(Glib::path_get_dirname(xmlpath));
827 if (!state_tree->read (xmlpath)) {
828 error << string_compose(_("Could not understand session file %1"), xmlpath) << endmsg;
834 XMLNode& root (*state_tree->root());
836 if (root.name() != X_("Session")) {
837 error << string_compose (_("Session file %1 is not a session"), xmlpath) << endmsg;
843 const XMLProperty* prop;
845 if ((prop = root.property ("version")) == 0) {
846 /* no version implies very old version of Ardour */
847 Stateful::loading_state_version = 1000;
849 if (prop->value().find ('.') != string::npos) {
850 /* old school version format */
851 if (prop->value()[0] == '2') {
852 Stateful::loading_state_version = 2000;
854 Stateful::loading_state_version = 3000;
857 Stateful::loading_state_version = atoi (prop->value());
861 if (Stateful::loading_state_version < CURRENT_SESSION_FILE_VERSION && _writable) {
863 std::string backup_path(_session_dir->root_path());
864 std::string backup_filename = string_compose ("%1-%2%3", legalize_for_path (snapshot_name), Stateful::loading_state_version, statefile_suffix);
865 backup_path = Glib::build_filename (backup_path, backup_filename);
867 // only create a backup for a given statefile version once
869 if (!Glib::file_test (backup_path, Glib::FILE_TEST_EXISTS)) {
871 VersionMismatch (xmlpath, backup_path);
873 if (!copy_file (xmlpath, backup_path)) {;
883 Session::load_options (const XMLNode& node)
885 LocaleGuard lg (X_("C"));
886 config.set_variables (node);
891 Session::save_default_options ()
893 return config.save_state();
903 Session::get_template()
905 /* if we don't disable rec-enable, diskstreams
906 will believe they need to store their capture
907 sources in their state node.
910 disable_record (false);
916 Session::state (bool full_state)
918 XMLNode* node = new XMLNode("Session");
922 snprintf(buf, sizeof(buf), "%d", CURRENT_SESSION_FILE_VERSION);
923 node->add_property("version", buf);
925 /* store configuration settings */
929 node->add_property ("name", _name);
930 snprintf (buf, sizeof (buf), "%" PRId64, _nominal_frame_rate);
931 node->add_property ("sample-rate", buf);
933 if (session_dirs.size() > 1) {
937 vector<space_and_path>::iterator i = session_dirs.begin();
938 vector<space_and_path>::iterator next;
940 ++i; /* skip the first one */
944 while (i != session_dirs.end()) {
948 if (next != session_dirs.end()) {
949 p += G_SEARCHPATH_SEPARATOR;
958 child = node->add_child ("Path");
959 child->add_content (p);
963 /* save the ID counter */
965 snprintf (buf, sizeof (buf), "%" PRIu64, ID::counter());
966 node->add_property ("id-counter", buf);
968 /* save the event ID counter */
970 snprintf (buf, sizeof (buf), "%d", Evoral::event_id_counter());
971 node->add_property ("event-counter", buf);
973 /* various options */
975 list<XMLNode*> midi_port_nodes = _midi_ports->get_midi_port_states();
976 if (!midi_port_nodes.empty()) {
977 XMLNode* midi_port_stuff = new XMLNode ("MIDIPorts");
978 for (list<XMLNode*>::const_iterator n = midi_port_nodes.begin(); n != midi_port_nodes.end(); ++n) {
979 midi_port_stuff->add_child_nocopy (**n);
981 node->add_child_nocopy (*midi_port_stuff);
984 node->add_child_nocopy (config.get_variables ());
986 node->add_child_nocopy (ARDOUR::SessionMetadata::Metadata()->get_state());
988 child = node->add_child ("Sources");
991 Glib::Threads::Mutex::Lock sl (source_lock);
993 for (SourceMap::iterator siter = sources.begin(); siter != sources.end(); ++siter) {
995 /* Don't save information about non-file Sources, or
996 * about non-destructive file sources that are empty
997 * and unused by any regions.
1000 boost::shared_ptr<FileSource> fs;
1002 if ((fs = boost::dynamic_pointer_cast<FileSource> (siter->second)) != 0) {
1004 if (!fs->destructive()) {
1005 if (fs->empty() && !fs->used()) {
1010 child->add_child_nocopy (siter->second->get_state());
1015 child = node->add_child ("Regions");
1018 Glib::Threads::Mutex::Lock rl (region_lock);
1019 const RegionFactory::RegionMap& region_map (RegionFactory::all_regions());
1020 for (RegionFactory::RegionMap::const_iterator i = region_map.begin(); i != region_map.end(); ++i) {
1021 boost::shared_ptr<Region> r = i->second;
1022 /* only store regions not attached to playlists */
1023 if (r->playlist() == 0) {
1024 if (boost::dynamic_pointer_cast<AudioRegion>(r)) {
1025 child->add_child_nocopy ((boost::dynamic_pointer_cast<AudioRegion>(r))->get_basic_state ());
1027 child->add_child_nocopy (r->get_state ());
1032 RegionFactory::CompoundAssociations& cassocs (RegionFactory::compound_associations());
1034 if (!cassocs.empty()) {
1035 XMLNode* ca = node->add_child (X_("CompoundAssociations"));
1037 for (RegionFactory::CompoundAssociations::iterator i = cassocs.begin(); i != cassocs.end(); ++i) {
1039 XMLNode* can = new XMLNode (X_("CompoundAssociation"));
1040 i->first->id().print (buf, sizeof (buf));
1041 can->add_property (X_("copy"), buf);
1042 i->second->id().print (buf, sizeof (buf));
1043 can->add_property (X_("original"), buf);
1044 ca->add_child_nocopy (*can);
1054 node->add_child_nocopy (_locations->get_state());
1057 Locations loc (*this);
1058 // for a template, just create a new Locations, populate it
1059 // with the default start and end, and get the state for that.
1060 Location* range = new Location (*this, 0, 0, _("session"), Location::IsSessionRange);
1061 range->set (max_framepos, 0);
1063 XMLNode& locations_state = loc.get_state();
1065 if (ARDOUR::Profile->get_trx() && _locations) {
1066 for (Locations::LocationList::const_iterator i = _locations->list ().begin (); i != _locations->list ().end (); ++i) {
1067 if ((*i)->is_mark () || (*i)->is_auto_loop ()) {
1068 locations_state.add_child_nocopy ((*i)->get_state ());
1072 node->add_child_nocopy (locations_state);
1075 child = node->add_child ("Bundles");
1077 boost::shared_ptr<BundleList> bundles = _bundles.reader ();
1078 for (BundleList::iterator i = bundles->begin(); i != bundles->end(); ++i) {
1079 boost::shared_ptr<UserBundle> b = boost::dynamic_pointer_cast<UserBundle> (*i);
1081 child->add_child_nocopy (b->get_state());
1086 child = node->add_child ("Routes");
1088 boost::shared_ptr<RouteList> r = routes.reader ();
1090 RoutePublicOrderSorter cmp;
1091 RouteList public_order (*r);
1092 public_order.sort (cmp);
1094 /* the sort should have put control outs first */
1097 assert (_monitor_out == public_order.front());
1100 for (RouteList::iterator i = public_order.begin(); i != public_order.end(); ++i) {
1101 if (!(*i)->is_auditioner()) {
1103 child->add_child_nocopy ((*i)->get_state());
1105 child->add_child_nocopy ((*i)->get_template());
1111 playlists->add_state (node, full_state);
1113 child = node->add_child ("RouteGroups");
1114 for (list<RouteGroup *>::iterator i = _route_groups.begin(); i != _route_groups.end(); ++i) {
1115 child->add_child_nocopy ((*i)->get_state());
1119 XMLNode* gain_child = node->add_child ("Click");
1120 gain_child->add_child_nocopy (_click_io->state (full_state));
1121 gain_child->add_child_nocopy (_click_gain->state (full_state));
1125 XMLNode* ltc_input_child = node->add_child ("LTC-In");
1126 ltc_input_child->add_child_nocopy (_ltc_input->state (full_state));
1130 XMLNode* ltc_output_child = node->add_child ("LTC-Out");
1131 ltc_output_child->add_child_nocopy (_ltc_output->state (full_state));
1134 node->add_child_nocopy (_speakers->get_state());
1135 node->add_child_nocopy (_tempo_map->get_state());
1136 node->add_child_nocopy (get_control_protocol_state());
1139 node->add_child_copy (*_extra_xml);
1146 Session::get_control_protocol_state ()
1148 ControlProtocolManager& cpm (ControlProtocolManager::instance());
1149 return cpm.get_state();
1153 Session::set_state (const XMLNode& node, int version)
1157 const XMLProperty* prop;
1160 _state_of_the_state = StateOfTheState (_state_of_the_state|CannotSave);
1162 if (node.name() != X_("Session")) {
1163 fatal << _("programming error: Session: incorrect XML node sent to set_state()") << endmsg;
1167 if ((prop = node.property ("name")) != 0) {
1168 _name = prop->value ();
1171 if ((prop = node.property (X_("sample-rate"))) != 0) {
1173 _nominal_frame_rate = atoi (prop->value());
1175 if (_nominal_frame_rate != _current_frame_rate) {
1176 boost::optional<int> r = AskAboutSampleRateMismatch (_nominal_frame_rate, _current_frame_rate);
1177 if (r.get_value_or (0)) {
1183 setup_raid_path(_session_dir->root_path());
1185 if ((prop = node.property (X_("id-counter"))) != 0) {
1187 sscanf (prop->value().c_str(), "%" PRIu64, &x);
1188 ID::init_counter (x);
1190 /* old sessions used a timebased counter, so fake
1191 the startup ID counter based on a standard
1196 ID::init_counter (now);
1199 if ((prop = node.property (X_("event-counter"))) != 0) {
1200 Evoral::init_event_id_counter (atoi (prop->value()));
1204 if ((child = find_named_node (node, "MIDIPorts")) != 0) {
1205 _midi_ports->set_midi_port_states (child->children());
1208 IO::disable_connecting ();
1210 Stateful::save_extra_xml (node);
1212 if (((child = find_named_node (node, "Options")) != 0)) { /* old style */
1213 load_options (*child);
1214 } else if ((child = find_named_node (node, "Config")) != 0) { /* new style */
1215 load_options (*child);
1217 error << _("Session: XML state has no options section") << endmsg;
1220 if (version >= 3000) {
1221 if ((child = find_named_node (node, "Metadata")) == 0) {
1222 warning << _("Session: XML state has no metadata section") << endmsg;
1223 } else if ( ARDOUR::SessionMetadata::Metadata()->set_state (*child, version) ) {
1228 if ((child = find_named_node (node, X_("Speakers"))) != 0) {
1229 _speakers->set_state (*child, version);
1232 if ((child = find_named_node (node, "Sources")) == 0) {
1233 error << _("Session: XML state has no sources section") << endmsg;
1235 } else if (load_sources (*child)) {
1239 if ((child = find_named_node (node, "TempoMap")) == 0) {
1240 error << _("Session: XML state has no Tempo Map section") << endmsg;
1242 } else if (_tempo_map->set_state (*child, version)) {
1246 if ((child = find_named_node (node, "Locations")) == 0) {
1247 error << _("Session: XML state has no locations section") << endmsg;
1249 } else if (_locations->set_state (*child, version)) {
1253 locations_changed ();
1255 if (_session_range_location) {
1256 AudioFileSource::set_header_position_offset (_session_range_location->start());
1259 if ((child = find_named_node (node, "Regions")) == 0) {
1260 error << _("Session: XML state has no Regions section") << endmsg;
1262 } else if (load_regions (*child)) {
1266 if ((child = find_named_node (node, "Playlists")) == 0) {
1267 error << _("Session: XML state has no playlists section") << endmsg;
1269 } else if (playlists->load (*this, *child)) {
1273 if ((child = find_named_node (node, "UnusedPlaylists")) == 0) {
1275 } else if (playlists->load_unused (*this, *child)) {
1279 if ((child = find_named_node (node, "CompoundAssociations")) != 0) {
1280 if (load_compounds (*child)) {
1285 if (version >= 3000) {
1286 if ((child = find_named_node (node, "Bundles")) == 0) {
1287 warning << _("Session: XML state has no bundles section") << endmsg;
1290 /* We can't load Bundles yet as they need to be able
1291 to convert from port names to Port objects, which can't happen until
1293 _bundle_xml_node = new XMLNode (*child);
1297 if (version < 3000) {
1298 if ((child = find_named_node (node, X_("DiskStreams"))) == 0) {
1299 error << _("Session: XML state has no diskstreams section") << endmsg;
1301 } else if (load_diskstreams_2X (*child, version)) {
1306 if ((child = find_named_node (node, "Routes")) == 0) {
1307 error << _("Session: XML state has no routes section") << endmsg;
1309 } else if (load_routes (*child, version)) {
1313 /* our diskstreams list is no longer needed as they are now all owned by their Route */
1314 _diskstreams_2X.clear ();
1316 if (version >= 3000) {
1318 if ((child = find_named_node (node, "RouteGroups")) == 0) {
1319 error << _("Session: XML state has no route groups section") << endmsg;
1321 } else if (load_route_groups (*child, version)) {
1325 } else if (version < 3000) {
1327 if ((child = find_named_node (node, "EditGroups")) == 0) {
1328 error << _("Session: XML state has no edit groups section") << endmsg;
1330 } else if (load_route_groups (*child, version)) {
1334 if ((child = find_named_node (node, "MixGroups")) == 0) {
1335 error << _("Session: XML state has no mix groups section") << endmsg;
1337 } else if (load_route_groups (*child, version)) {
1342 if ((child = find_named_node (node, "Click")) == 0) {
1343 warning << _("Session: XML state has no click section") << endmsg;
1344 } else if (_click_io) {
1345 setup_click_state (&node);
1348 if ((child = find_named_node (node, ControlProtocolManager::state_node_name)) != 0) {
1349 ControlProtocolManager::instance().set_state (*child, version);
1352 update_have_rec_enabled_track ();
1354 /* here beginneth the second phase ... */
1356 StateReady (); /* EMIT SIGNAL */
1369 Session::load_routes (const XMLNode& node, int version)
1372 XMLNodeConstIterator niter;
1373 RouteList new_routes;
1375 nlist = node.children();
1379 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1381 boost::shared_ptr<Route> route;
1382 if (version < 3000) {
1383 route = XMLRouteFactory_2X (**niter, version);
1385 route = XMLRouteFactory (**niter, version);
1389 error << _("Session: cannot create Route from XML description.") << endmsg;
1393 BootMessage (string_compose (_("Loaded track/bus %1"), route->name()));
1395 new_routes.push_back (route);
1398 BootMessage (_("Tracks/busses loaded; Adding to Session"));
1400 add_routes (new_routes, false, false, false);
1402 BootMessage (_("Finished adding tracks/busses"));
1407 boost::shared_ptr<Route>
1408 Session::XMLRouteFactory (const XMLNode& node, int version)
1410 boost::shared_ptr<Route> ret;
1412 if (node.name() != "Route") {
1416 XMLNode* ds_child = find_named_node (node, X_("Diskstream"));
1418 DataType type = DataType::AUDIO;
1419 const XMLProperty* prop = node.property("default-type");
1422 type = DataType (prop->value());
1425 assert (type != DataType::NIL);
1429 boost::shared_ptr<Track> track;
1431 if (type == DataType::AUDIO) {
1432 track.reset (new AudioTrack (*this, X_("toBeResetFroXML")));
1434 track.reset (new MidiTrack (*this, X_("toBeResetFroXML")));
1437 if (track->init()) {
1441 if (track->set_state (node, version)) {
1445 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
1446 // boost_debug_shared_ptr_mark_interesting (track.get(), "Track");
1451 enum Route::Flag flags = Route::Flag(0);
1452 const XMLProperty* prop = node.property("flags");
1454 flags = Route::Flag (string_2_enum (prop->value(), flags));
1457 boost::shared_ptr<Route> r (new Route (*this, X_("toBeResetFroXML"), flags));
1459 if (r->init () == 0 && r->set_state (node, version) == 0) {
1460 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
1461 // boost_debug_shared_ptr_mark_interesting (r.get(), "Route");
1470 boost::shared_ptr<Route>
1471 Session::XMLRouteFactory_2X (const XMLNode& node, int version)
1473 boost::shared_ptr<Route> ret;
1475 if (node.name() != "Route") {
1479 XMLProperty const * ds_prop = node.property (X_("diskstream-id"));
1481 ds_prop = node.property (X_("diskstream"));
1484 DataType type = DataType::AUDIO;
1485 const XMLProperty* prop = node.property("default-type");
1488 type = DataType (prop->value());
1491 assert (type != DataType::NIL);
1495 list<boost::shared_ptr<Diskstream> >::iterator i = _diskstreams_2X.begin ();
1496 while (i != _diskstreams_2X.end() && (*i)->id() != ds_prop->value()) {
1500 if (i == _diskstreams_2X.end()) {
1501 error << _("Could not find diskstream for route") << endmsg;
1502 return boost::shared_ptr<Route> ();
1505 boost::shared_ptr<Track> track;
1507 if (type == DataType::AUDIO) {
1508 track.reset (new AudioTrack (*this, X_("toBeResetFroXML")));
1510 track.reset (new MidiTrack (*this, X_("toBeResetFroXML")));
1513 if (track->init()) {
1517 if (track->set_state (node, version)) {
1521 track->set_diskstream (*i);
1523 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
1524 // boost_debug_shared_ptr_mark_interesting (track.get(), "Track");
1529 enum Route::Flag flags = Route::Flag(0);
1530 const XMLProperty* prop = node.property("flags");
1532 flags = Route::Flag (string_2_enum (prop->value(), flags));
1535 boost::shared_ptr<Route> r (new Route (*this, X_("toBeResetFroXML"), flags));
1537 if (r->init () == 0 && r->set_state (node, version) == 0) {
1538 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
1539 // boost_debug_shared_ptr_mark_interesting (r.get(), "Route");
1549 Session::load_regions (const XMLNode& node)
1552 XMLNodeConstIterator niter;
1553 boost::shared_ptr<Region> region;
1555 nlist = node.children();
1559 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1560 if ((region = XMLRegionFactory (**niter, false)) == 0) {
1561 error << _("Session: cannot create Region from XML description.");
1562 const XMLProperty *name = (**niter).property("name");
1565 error << " " << string_compose (_("Can not load state for region '%1'"), name->value());
1576 Session::load_compounds (const XMLNode& node)
1578 XMLNodeList calist = node.children();
1579 XMLNodeConstIterator caiter;
1580 XMLProperty *caprop;
1582 for (caiter = calist.begin(); caiter != calist.end(); ++caiter) {
1583 XMLNode* ca = *caiter;
1587 if ((caprop = ca->property (X_("original"))) == 0) {
1590 orig_id = caprop->value();
1592 if ((caprop = ca->property (X_("copy"))) == 0) {
1595 copy_id = caprop->value();
1597 boost::shared_ptr<Region> orig = RegionFactory::region_by_id (orig_id);
1598 boost::shared_ptr<Region> copy = RegionFactory::region_by_id (copy_id);
1600 if (!orig || !copy) {
1601 warning << string_compose (_("Regions in compound description not found (ID's %1 and %2): ignored"),
1607 RegionFactory::add_compound_association (orig, copy);
1614 Session::load_nested_sources (const XMLNode& node)
1617 XMLNodeConstIterator niter;
1619 nlist = node.children();
1621 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1622 if ((*niter)->name() == "Source") {
1624 /* it may already exist, so don't recreate it unnecessarily
1627 XMLProperty* prop = (*niter)->property (X_("id"));
1629 error << _("Nested source has no ID info in session file! (ignored)") << endmsg;
1633 ID source_id (prop->value());
1635 if (!source_by_id (source_id)) {
1638 SourceFactory::create (*this, **niter, true);
1640 catch (failed_constructor& err) {
1641 error << string_compose (_("Cannot reconstruct nested source for region %1"), name()) << endmsg;
1648 boost::shared_ptr<Region>
1649 Session::XMLRegionFactory (const XMLNode& node, bool full)
1651 const XMLProperty* type = node.property("type");
1655 const XMLNodeList& nlist = node.children();
1657 for (XMLNodeConstIterator niter = nlist.begin(); niter != nlist.end(); ++niter) {
1658 XMLNode *child = (*niter);
1659 if (child->name() == "NestedSource") {
1660 load_nested_sources (*child);
1664 if (!type || type->value() == "audio") {
1665 return boost::shared_ptr<Region>(XMLAudioRegionFactory (node, full));
1666 } else if (type->value() == "midi") {
1667 return boost::shared_ptr<Region>(XMLMidiRegionFactory (node, full));
1670 } catch (failed_constructor& err) {
1671 return boost::shared_ptr<Region> ();
1674 return boost::shared_ptr<Region> ();
1677 boost::shared_ptr<AudioRegion>
1678 Session::XMLAudioRegionFactory (const XMLNode& node, bool /*full*/)
1680 const XMLProperty* prop;
1681 boost::shared_ptr<Source> source;
1682 boost::shared_ptr<AudioSource> as;
1684 SourceList master_sources;
1685 uint32_t nchans = 1;
1688 if (node.name() != X_("Region")) {
1689 return boost::shared_ptr<AudioRegion>();
1692 if ((prop = node.property (X_("channels"))) != 0) {
1693 nchans = atoi (prop->value().c_str());
1696 if ((prop = node.property ("name")) == 0) {
1697 cerr << "no name for this region\n";
1701 if ((prop = node.property (X_("source-0"))) == 0) {
1702 if ((prop = node.property ("source")) == 0) {
1703 error << _("Session: XMLNode describing a AudioRegion is incomplete (no source)") << endmsg;
1704 return boost::shared_ptr<AudioRegion>();
1708 PBD::ID s_id (prop->value());
1710 if ((source = source_by_id (s_id)) == 0) {
1711 error << string_compose(_("Session: XMLNode describing a AudioRegion references an unknown source id =%1"), s_id) << endmsg;
1712 return boost::shared_ptr<AudioRegion>();
1715 as = boost::dynamic_pointer_cast<AudioSource>(source);
1717 error << string_compose(_("Session: XMLNode describing a AudioRegion references a non-audio source id =%1"), s_id) << endmsg;
1718 return boost::shared_ptr<AudioRegion>();
1721 sources.push_back (as);
1723 /* pickup other channels */
1725 for (uint32_t n=1; n < nchans; ++n) {
1726 snprintf (buf, sizeof(buf), X_("source-%d"), n);
1727 if ((prop = node.property (buf)) != 0) {
1729 PBD::ID id2 (prop->value());
1731 if ((source = source_by_id (id2)) == 0) {
1732 error << string_compose(_("Session: XMLNode describing a AudioRegion references an unknown source id =%1"), id2) << endmsg;
1733 return boost::shared_ptr<AudioRegion>();
1736 as = boost::dynamic_pointer_cast<AudioSource>(source);
1738 error << string_compose(_("Session: XMLNode describing a AudioRegion references a non-audio source id =%1"), id2) << endmsg;
1739 return boost::shared_ptr<AudioRegion>();
1741 sources.push_back (as);
1745 for (uint32_t n = 0; n < nchans; ++n) {
1746 snprintf (buf, sizeof(buf), X_("master-source-%d"), n);
1747 if ((prop = node.property (buf)) != 0) {
1749 PBD::ID id2 (prop->value());
1751 if ((source = source_by_id (id2)) == 0) {
1752 error << string_compose(_("Session: XMLNode describing a AudioRegion references an unknown source id =%1"), id2) << endmsg;
1753 return boost::shared_ptr<AudioRegion>();
1756 as = boost::dynamic_pointer_cast<AudioSource>(source);
1758 error << string_compose(_("Session: XMLNode describing a AudioRegion references a non-audio source id =%1"), id2) << endmsg;
1759 return boost::shared_ptr<AudioRegion>();
1761 master_sources.push_back (as);
1766 boost::shared_ptr<AudioRegion> region (boost::dynamic_pointer_cast<AudioRegion> (RegionFactory::create (sources, node)));
1768 /* a final detail: this is the one and only place that we know how long missing files are */
1770 if (region->whole_file()) {
1771 for (SourceList::iterator sx = sources.begin(); sx != sources.end(); ++sx) {
1772 boost::shared_ptr<SilentFileSource> sfp = boost::dynamic_pointer_cast<SilentFileSource> (*sx);
1774 sfp->set_length (region->length());
1779 if (!master_sources.empty()) {
1780 if (master_sources.size() != nchans) {
1781 error << _("Session: XMLNode describing an AudioRegion is missing some master sources; ignored") << endmsg;
1783 region->set_master_sources (master_sources);
1791 catch (failed_constructor& err) {
1792 return boost::shared_ptr<AudioRegion>();
1796 boost::shared_ptr<MidiRegion>
1797 Session::XMLMidiRegionFactory (const XMLNode& node, bool /*full*/)
1799 const XMLProperty* prop;
1800 boost::shared_ptr<Source> source;
1801 boost::shared_ptr<MidiSource> ms;
1804 if (node.name() != X_("Region")) {
1805 return boost::shared_ptr<MidiRegion>();
1808 if ((prop = node.property ("name")) == 0) {
1809 cerr << "no name for this region\n";
1813 if ((prop = node.property (X_("source-0"))) == 0) {
1814 if ((prop = node.property ("source")) == 0) {
1815 error << _("Session: XMLNode describing a MidiRegion is incomplete (no source)") << endmsg;
1816 return boost::shared_ptr<MidiRegion>();
1820 PBD::ID s_id (prop->value());
1822 if ((source = source_by_id (s_id)) == 0) {
1823 error << string_compose(_("Session: XMLNode describing a MidiRegion references an unknown source id =%1"), s_id) << endmsg;
1824 return boost::shared_ptr<MidiRegion>();
1827 ms = boost::dynamic_pointer_cast<MidiSource>(source);
1829 error << string_compose(_("Session: XMLNode describing a MidiRegion references a non-midi source id =%1"), s_id) << endmsg;
1830 return boost::shared_ptr<MidiRegion>();
1833 sources.push_back (ms);
1836 boost::shared_ptr<MidiRegion> region (boost::dynamic_pointer_cast<MidiRegion> (RegionFactory::create (sources, node)));
1837 /* a final detail: this is the one and only place that we know how long missing files are */
1839 if (region->whole_file()) {
1840 for (SourceList::iterator sx = sources.begin(); sx != sources.end(); ++sx) {
1841 boost::shared_ptr<SilentFileSource> sfp = boost::dynamic_pointer_cast<SilentFileSource> (*sx);
1843 sfp->set_length (region->length());
1851 catch (failed_constructor& err) {
1852 return boost::shared_ptr<MidiRegion>();
1857 Session::get_sources_as_xml ()
1860 XMLNode* node = new XMLNode (X_("Sources"));
1861 Glib::Threads::Mutex::Lock lm (source_lock);
1863 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ++i) {
1864 node->add_child_nocopy (i->second->get_state());
1871 Session::reset_write_sources (bool mark_write_complete, bool force)
1873 boost::shared_ptr<RouteList> rl = routes.reader();
1874 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
1875 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
1878 // block state saving
1879 _state_of_the_state = StateOfTheState (_state_of_the_state|InCleanup);
1880 tr->reset_write_sources(mark_write_complete, force);
1881 _state_of_the_state = StateOfTheState (_state_of_the_state & ~InCleanup);
1887 Session::load_sources (const XMLNode& node)
1890 XMLNodeConstIterator niter;
1891 boost::shared_ptr<Source> source; /* don't need this but it stops some
1892 * versions of gcc complaining about
1893 * discarded return values.
1896 nlist = node.children();
1900 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1903 if ((source = XMLSourceFactory (**niter)) == 0) {
1904 error << _("Session: cannot create Source from XML description.") << endmsg;
1907 } catch (MissingSource& err) {
1911 if (err.type == DataType::MIDI && Glib::path_is_absolute (err.path)) {
1912 error << string_compose (_("A external MIDI file is missing. %1 cannot currently recover from missing external MIDI files"),
1913 PROGRAM_NAME) << endmsg;
1917 if (!no_questions_about_missing_files) {
1918 user_choice = MissingFile (this, err.path, err.type).get_value_or (-1);
1923 switch (user_choice) {
1925 /* user added a new search location, so try again */
1930 /* user asked to quit the entire session load
1935 no_questions_about_missing_files = true;
1939 no_questions_about_missing_files = true;
1946 case DataType::AUDIO:
1947 source = SourceFactory::createSilent (*this, **niter, max_framecnt, _current_frame_rate);
1950 case DataType::MIDI:
1951 /* The MIDI file is actually missing so
1952 * just create a new one in the same
1953 * location. Do not announce its
1957 if (!Glib::path_is_absolute (err.path)) {
1958 fullpath = Glib::build_filename (source_search_path (DataType::MIDI).front(), err.path);
1960 /* this should be an unrecoverable error: we would be creating a MIDI file outside
1965 /* Note that we do not announce the source just yet - we need to reset its ID before we do that */
1966 source = SourceFactory::createWritable (DataType::MIDI, *this, fullpath, false, _current_frame_rate, false, false);
1967 /* reset ID to match the missing one */
1968 source->set_id (**niter);
1969 /* Now we can announce it */
1970 SourceFactory::SourceCreated (source);
1981 boost::shared_ptr<Source>
1982 Session::XMLSourceFactory (const XMLNode& node)
1984 if (node.name() != "Source") {
1985 return boost::shared_ptr<Source>();
1989 /* note: do peak building in another thread when loading session state */
1990 return SourceFactory::create (*this, node, true);
1993 catch (failed_constructor& err) {
1994 error << string_compose (_("Found a sound file that cannot be used by %1. Talk to the programmers."), PROGRAM_NAME) << endmsg;
1995 return boost::shared_ptr<Source>();
2000 Session::save_template (string template_name)
2002 if ((_state_of_the_state & CannotSave) || template_name.empty ()) {
2006 bool absolute_path = Glib::path_is_absolute (template_name);
2008 /* directory to put the template in */
2009 std::string template_dir_path;
2011 if (!absolute_path) {
2012 std::string user_template_dir(user_template_directory());
2014 if (g_mkdir_with_parents (user_template_dir.c_str(), 0755) != 0) {
2015 error << string_compose(_("Could not create templates directory \"%1\" (%2)"),
2016 user_template_dir, g_strerror (errno)) << endmsg;
2020 template_dir_path = Glib::build_filename (user_template_dir, template_name);
2022 template_dir_path = template_name;
2025 if (Glib::file_test (template_dir_path, Glib::FILE_TEST_EXISTS)) {
2026 warning << string_compose(_("Template \"%1\" already exists - new version not created"),
2027 template_dir_path) << endmsg;
2031 if (g_mkdir_with_parents (template_dir_path.c_str(), 0755) != 0) {
2032 error << string_compose(_("Could not create directory for Session template\"%1\" (%2)"),
2033 template_dir_path, g_strerror (errno)) << endmsg;
2038 std::string template_file_path;
2039 if (absolute_path) {
2040 template_file_path = Glib::build_filename (template_dir_path, Glib::path_get_basename (template_dir_path) + template_suffix);
2042 template_file_path = Glib::build_filename (template_dir_path, template_name + template_suffix);
2045 SessionSaveUnderway (); /* EMIT SIGNAL */
2049 tree.set_root (&get_template());
2050 if (!tree.write (template_file_path)) {
2051 error << _("template not saved") << endmsg;
2055 /* copy plugin state directory */
2057 std::string template_plugin_state_path (Glib::build_filename (template_dir_path, X_("plugins")));
2059 if (g_mkdir_with_parents (template_plugin_state_path.c_str(), 0755) != 0) {
2060 error << string_compose(_("Could not create directory for Session template plugin state\"%1\" (%2)"),
2061 template_plugin_state_path, g_strerror (errno)) << endmsg;
2065 copy_recurse (plugins_dir(), template_plugin_state_path);
2071 Session::refresh_disk_space ()
2073 #if __APPLE__ || (HAVE_SYS_VFS_H && HAVE_SYS_STATVFS_H)
2075 Glib::Threads::Mutex::Lock lm (space_lock);
2077 /* get freespace on every FS that is part of the session path */
2079 _total_free_4k_blocks = 0;
2080 _total_free_4k_blocks_uncertain = false;
2082 for (vector<space_and_path>::iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
2084 struct statfs statfsbuf;
2085 statfs (i->path.c_str(), &statfsbuf);
2087 double const scale = statfsbuf.f_bsize / 4096.0;
2089 /* See if this filesystem is read-only */
2090 struct statvfs statvfsbuf;
2091 statvfs (i->path.c_str(), &statvfsbuf);
2093 /* f_bavail can be 0 if it is undefined for whatever
2094 filesystem we are looking at; Samba shares mounted
2095 via GVFS are an example of this.
2097 if (statfsbuf.f_bavail == 0) {
2098 /* block count unknown */
2100 i->blocks_unknown = true;
2101 } else if (statvfsbuf.f_flag & ST_RDONLY) {
2102 /* read-only filesystem */
2104 i->blocks_unknown = false;
2106 /* read/write filesystem with known space */
2107 i->blocks = (uint32_t) floor (statfsbuf.f_bavail * scale);
2108 i->blocks_unknown = false;
2111 _total_free_4k_blocks += i->blocks;
2112 if (i->blocks_unknown) {
2113 _total_free_4k_blocks_uncertain = true;
2116 #elif defined PLATFORM_WINDOWS
2117 vector<string> scanned_volumes;
2118 vector<string>::iterator j;
2119 vector<space_and_path>::iterator i;
2120 DWORD nSectorsPerCluster, nBytesPerSector,
2121 nFreeClusters, nTotalClusters;
2125 _total_free_4k_blocks = 0;
2127 for (i = session_dirs.begin(); i != session_dirs.end(); i++) {
2128 strncpy (disk_drive, (*i).path.c_str(), 3);
2132 volume_found = false;
2133 if (0 != (GetDiskFreeSpace(disk_drive, &nSectorsPerCluster, &nBytesPerSector, &nFreeClusters, &nTotalClusters)))
2135 int64_t nBytesPerCluster = nBytesPerSector * nSectorsPerCluster;
2136 int64_t nFreeBytes = nBytesPerCluster * (int64_t)nFreeClusters;
2137 i->blocks = (uint32_t)(nFreeBytes / 4096);
2139 for (j = scanned_volumes.begin(); j != scanned_volumes.end(); j++) {
2140 if (0 == j->compare(disk_drive)) {
2141 volume_found = true;
2146 if (!volume_found) {
2147 scanned_volumes.push_back(disk_drive);
2148 _total_free_4k_blocks += i->blocks;
2153 if (0 == _total_free_4k_blocks) {
2154 strncpy (disk_drive, path().c_str(), 3);
2157 if (0 != (GetDiskFreeSpace(disk_drive, &nSectorsPerCluster, &nBytesPerSector, &nFreeClusters, &nTotalClusters)))
2159 int64_t nBytesPerCluster = nBytesPerSector * nSectorsPerCluster;
2160 int64_t nFreeBytes = nBytesPerCluster * (int64_t)nFreeClusters;
2161 _total_free_4k_blocks = (uint32_t)(nFreeBytes / 4096);
2168 Session::get_best_session_directory_for_new_audio ()
2170 vector<space_and_path>::iterator i;
2171 string result = _session_dir->root_path();
2173 /* handle common case without system calls */
2175 if (session_dirs.size() == 1) {
2179 /* OK, here's the algorithm we're following here:
2181 We want to select which directory to use for
2182 the next file source to be created. Ideally,
2183 we'd like to use a round-robin process so as to
2184 get maximum performance benefits from splitting
2185 the files across multiple disks.
2187 However, in situations without much diskspace, an
2188 RR approach may end up filling up a filesystem
2189 with new files while others still have space.
2190 Its therefore important to pay some attention to
2191 the freespace in the filesystem holding each
2192 directory as well. However, if we did that by
2193 itself, we'd keep creating new files in the file
2194 system with the most space until it was as full
2195 as all others, thus negating any performance
2196 benefits of this RAID-1 like approach.
2198 So, we use a user-configurable space threshold. If
2199 there are at least 2 filesystems with more than this
2200 much space available, we use RR selection between them.
2201 If not, then we pick the filesystem with the most space.
2203 This gets a good balance between the two
2207 refresh_disk_space ();
2209 int free_enough = 0;
2211 for (i = session_dirs.begin(); i != session_dirs.end(); ++i) {
2212 if ((*i).blocks * 4096 >= Config->get_disk_choice_space_threshold()) {
2217 if (free_enough >= 2) {
2218 /* use RR selection process, ensuring that the one
2222 i = last_rr_session_dir;
2225 if (++i == session_dirs.end()) {
2226 i = session_dirs.begin();
2229 if ((*i).blocks * 4096 >= Config->get_disk_choice_space_threshold()) {
2230 SessionDirectory sdir(i->path);
2231 if (sdir.create ()) {
2233 last_rr_session_dir = i;
2238 } while (i != last_rr_session_dir);
2242 /* pick FS with the most freespace (and that
2243 seems to actually work ...)
2246 vector<space_and_path> sorted;
2247 space_and_path_ascending_cmp cmp;
2249 sorted = session_dirs;
2250 sort (sorted.begin(), sorted.end(), cmp);
2252 for (i = sorted.begin(); i != sorted.end(); ++i) {
2253 SessionDirectory sdir(i->path);
2254 if (sdir.create ()) {
2256 last_rr_session_dir = i;
2266 Session::automation_dir () const
2268 return Glib::build_filename (_path, "automation");
2272 Session::analysis_dir () const
2274 return Glib::build_filename (_path, "analysis");
2278 Session::plugins_dir () const
2280 return Glib::build_filename (_path, "plugins");
2284 Session::externals_dir () const
2286 return Glib::build_filename (_path, "externals");
2290 Session::load_bundles (XMLNode const & node)
2292 XMLNodeList nlist = node.children();
2293 XMLNodeConstIterator niter;
2297 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2298 if ((*niter)->name() == "InputBundle") {
2299 add_bundle (boost::shared_ptr<UserBundle> (new UserBundle (**niter, true)));
2300 } else if ((*niter)->name() == "OutputBundle") {
2301 add_bundle (boost::shared_ptr<UserBundle> (new UserBundle (**niter, false)));
2303 error << string_compose(_("Unknown node \"%1\" found in Bundles list from session file"), (*niter)->name()) << endmsg;
2312 Session::load_route_groups (const XMLNode& node, int version)
2314 XMLNodeList nlist = node.children();
2315 XMLNodeConstIterator niter;
2319 if (version >= 3000) {
2321 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2322 if ((*niter)->name() == "RouteGroup") {
2323 RouteGroup* rg = new RouteGroup (*this, "");
2324 add_route_group (rg);
2325 rg->set_state (**niter, version);
2329 } else if (version < 3000) {
2331 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2332 if ((*niter)->name() == "EditGroup" || (*niter)->name() == "MixGroup") {
2333 RouteGroup* rg = new RouteGroup (*this, "");
2334 add_route_group (rg);
2335 rg->set_state (**niter, version);
2344 state_file_filter (const string &str, void* /*arg*/)
2346 return (str.length() > strlen(statefile_suffix) &&
2347 str.find (statefile_suffix) == (str.length() - strlen (statefile_suffix)));
2351 remove_end(string state)
2353 string statename(state);
2355 string::size_type start,end;
2356 if ((start = statename.find_last_of (G_DIR_SEPARATOR)) != string::npos) {
2357 statename = statename.substr (start+1);
2360 if ((end = statename.rfind(statefile_suffix)) == string::npos) {
2361 end = statename.length();
2364 return string(statename.substr (0, end));
2368 Session::possible_states (string path)
2370 vector<string> states;
2371 find_files_matching_filter (states, path, state_file_filter, 0, false, false);
2373 transform(states.begin(), states.end(), states.begin(), remove_end);
2375 sort (states.begin(), states.end());
2381 Session::possible_states () const
2383 return possible_states(_path);
2387 Session::add_route_group (RouteGroup* g)
2389 _route_groups.push_back (g);
2390 route_group_added (g); /* EMIT SIGNAL */
2392 g->RouteAdded.connect_same_thread (*this, boost::bind (&Session::route_added_to_route_group, this, _1, _2));
2393 g->RouteRemoved.connect_same_thread (*this, boost::bind (&Session::route_removed_from_route_group, this, _1, _2));
2394 g->PropertyChanged.connect_same_thread (*this, boost::bind (&Session::route_group_property_changed, this, g));
2400 Session::remove_route_group (RouteGroup& rg)
2402 list<RouteGroup*>::iterator i;
2404 if ((i = find (_route_groups.begin(), _route_groups.end(), &rg)) != _route_groups.end()) {
2405 _route_groups.erase (i);
2408 route_group_removed (); /* EMIT SIGNAL */
2412 /** Set a new order for our route groups, without adding or removing any.
2413 * @param groups Route group list in the new order.
2416 Session::reorder_route_groups (list<RouteGroup*> groups)
2418 _route_groups = groups;
2420 route_groups_reordered (); /* EMIT SIGNAL */
2426 Session::route_group_by_name (string name)
2428 list<RouteGroup *>::iterator i;
2430 for (i = _route_groups.begin(); i != _route_groups.end(); ++i) {
2431 if ((*i)->name() == name) {
2439 Session::all_route_group() const
2441 return *_all_route_group;
2445 Session::add_commands (vector<Command*> const & cmds)
2447 for (vector<Command*>::const_iterator i = cmds.begin(); i != cmds.end(); ++i) {
2453 Session::begin_reversible_command (const string& name)
2455 begin_reversible_command (g_quark_from_string (name.c_str ()));
2458 /** Begin a reversible command using a GQuark to identify it.
2459 * begin_reversible_command() and commit_reversible_command() calls may be nested,
2460 * but there must be as many begin...()s as there are commit...()s.
2463 Session::begin_reversible_command (GQuark q)
2465 /* If nested begin/commit pairs are used, we create just one UndoTransaction
2466 to hold all the commands that are committed. This keeps the order of
2467 commands correct in the history.
2470 if (_current_trans == 0) {
2471 /* start a new transaction */
2472 assert (_current_trans_quarks.empty ());
2473 _current_trans = new UndoTransaction();
2474 _current_trans->set_name (g_quark_to_string (q));
2477 _current_trans_quarks.push_front (q);
2481 Session::abort_reversible_command ()
2483 if (_current_trans != 0) {
2484 _current_trans->clear();
2485 delete _current_trans;
2487 _current_trans_quarks.clear();
2492 Session::commit_reversible_command (Command *cmd)
2494 assert (_current_trans);
2495 assert (!_current_trans_quarks.empty ());
2500 _current_trans->add_command (cmd);
2503 _current_trans_quarks.pop_front ();
2505 if (!_current_trans_quarks.empty ()) {
2506 /* the transaction we're committing is not the top-level one */
2510 if (_current_trans->empty()) {
2511 /* no commands were added to the transaction, so just get rid of it */
2512 delete _current_trans;
2517 gettimeofday (&now, 0);
2518 _current_trans->set_timestamp (now);
2520 _history.add (_current_trans);
2525 accept_all_audio_files (const string& path, void* /*arg*/)
2527 if (!Glib::file_test (path, Glib::FILE_TEST_IS_REGULAR)) {
2531 if (!AudioFileSource::safe_audio_file_extension (path)) {
2539 accept_all_midi_files (const string& path, void* /*arg*/)
2541 if (!Glib::file_test (path, Glib::FILE_TEST_IS_REGULAR)) {
2545 return ((path.length() > 4 && path.find (".mid") != (path.length() - 4)) ||
2546 (path.length() > 4 && path.find (".smf") != (path.length() - 4)) ||
2547 (path.length() > 5 && path.find (".midi") != (path.length() - 5)));
2551 accept_all_state_files (const string& path, void* /*arg*/)
2553 if (!Glib::file_test (path, Glib::FILE_TEST_IS_REGULAR)) {
2557 std::string const statefile_ext (statefile_suffix);
2558 if (path.length() >= statefile_ext.length()) {
2559 return (0 == path.compare (path.length() - statefile_ext.length(), statefile_ext.length(), statefile_ext));
2566 Session::find_all_sources (string path, set<string>& result)
2571 if (!tree.read (path)) {
2575 if ((node = find_named_node (*tree.root(), "Sources")) == 0) {
2580 XMLNodeConstIterator niter;
2582 nlist = node->children();
2586 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2590 if ((prop = (*niter)->property (X_("type"))) == 0) {
2594 DataType type (prop->value());
2596 if ((prop = (*niter)->property (X_("name"))) == 0) {
2600 if (Glib::path_is_absolute (prop->value())) {
2601 /* external file, ignore */
2609 if (FileSource::find (*this, type, prop->value(), true, is_new, chan, found_path)) {
2610 result.insert (found_path);
2618 Session::find_all_sources_across_snapshots (set<string>& result, bool exclude_this_snapshot)
2620 vector<string> state_files;
2622 string this_snapshot_path;
2628 if (ripped[ripped.length()-1] == G_DIR_SEPARATOR) {
2629 ripped = ripped.substr (0, ripped.length() - 1);
2632 find_files_matching_filter (state_files, ripped, accept_all_state_files, (void *) 0, true, true);
2634 if (state_files.empty()) {
2639 this_snapshot_path = _path;
2640 this_snapshot_path += legalize_for_path (_current_snapshot_name);
2641 this_snapshot_path += statefile_suffix;
2643 for (vector<string>::iterator i = state_files.begin(); i != state_files.end(); ++i) {
2645 if (exclude_this_snapshot && *i == this_snapshot_path) {
2649 if (find_all_sources (*i, result) < 0) {
2657 struct RegionCounter {
2658 typedef std::map<PBD::ID,boost::shared_ptr<AudioSource> > AudioSourceList;
2659 AudioSourceList::iterator iter;
2660 boost::shared_ptr<Region> region;
2663 RegionCounter() : count (0) {}
2667 Session::ask_about_playlist_deletion (boost::shared_ptr<Playlist> p)
2669 boost::optional<int> r = AskAboutPlaylistDeletion (p);
2670 return r.get_value_or (1);
2674 Session::cleanup_regions ()
2676 bool removed = false;
2677 const RegionFactory::RegionMap& regions (RegionFactory::regions());
2679 for (RegionFactory::RegionMap::const_iterator i = regions.begin(); i != regions.end(); ++i) {
2681 uint32_t used = playlists->region_use_count (i->second);
2683 if (used == 0 && !i->second->automatic ()) {
2685 RegionFactory::map_remove (i->second);
2690 // re-check to remove parent references of compound regions
2691 for (RegionFactory::RegionMap::const_iterator i = regions.begin(); i != regions.end(); ++i) {
2692 if (!(i->second->whole_file() && i->second->max_source_level() > 0)) {
2695 assert(boost::dynamic_pointer_cast<PlaylistSource>(i->second->source (0)) != 0);
2696 if (0 == playlists->region_use_count (i->second)) {
2697 RegionFactory::map_remove (i->second);
2702 /* dump the history list */
2709 Session::cleanup_sources (CleanupReport& rep)
2711 // FIXME: needs adaptation to midi
2713 vector<boost::shared_ptr<Source> > dead_sources;
2716 vector<string> candidates;
2717 vector<string> unused;
2718 set<string> all_sources;
2727 _state_of_the_state = (StateOfTheState) (_state_of_the_state | InCleanup);
2729 /* consider deleting all unused playlists */
2731 if (playlists->maybe_delete_unused (boost::bind (Session::ask_about_playlist_deletion, _1))) {
2736 /* sync the "all regions" property of each playlist with its current state
2739 playlists->sync_all_regions_with_regions ();
2741 /* find all un-used sources */
2746 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ) {
2748 SourceMap::iterator tmp;
2753 /* do not bother with files that are zero size, otherwise we remove the current "nascent"
2757 if (!i->second->used() && (i->second->length(i->second->timeline_position() > 0))) {
2758 dead_sources.push_back (i->second);
2759 i->second->drop_references ();
2765 /* build a list of all the possible audio directories for the session */
2767 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
2768 SessionDirectory sdir ((*i).path);
2769 asp += sdir.sound_path();
2771 audio_path += asp.to_string();
2774 /* build a list of all the possible midi directories for the session */
2776 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
2777 SessionDirectory sdir ((*i).path);
2778 msp += sdir.midi_path();
2780 midi_path += msp.to_string();
2782 find_files_matching_filter (candidates, audio_path, accept_all_audio_files, (void *) 0, true, true);
2783 find_files_matching_filter (candidates, midi_path, accept_all_midi_files, (void *) 0, true, true);
2785 /* find all sources, but don't use this snapshot because the
2786 state file on disk still references sources we may have already
2790 find_all_sources_across_snapshots (all_sources, true);
2792 /* add our current source list
2795 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ) {
2796 boost::shared_ptr<FileSource> fs;
2797 SourceMap::iterator tmp = i;
2800 if ((fs = boost::dynamic_pointer_cast<FileSource> (i->second)) != 0) {
2802 if (!fs->is_stub()) {
2804 if (playlists->source_use_count (fs) != 0) {
2805 all_sources.insert (fs->path());
2808 /* we might not remove this source from disk, because it may be used
2809 by other snapshots, but its not being used in this version
2810 so lets get rid of it now, along with any representative regions
2814 RegionFactory::remove_regions_using_source (i->second);
2817 // also remove source from all_sources
2819 for (set<string>::iterator j = all_sources.begin(); j != all_sources.end(); ++j) {
2820 spath = Glib::path_get_basename (*j);
2821 if ( spath == i->second->name () ) {
2822 all_sources.erase (j);
2833 for (vector<string>::iterator x = candidates.begin(); x != candidates.end(); ++x) {
2838 for (set<string>::iterator i = all_sources.begin(); i != all_sources.end(); ++i) {
2840 tmppath1 = canonical_path (spath);
2841 tmppath2 = canonical_path ((*i));
2843 if (tmppath1 == tmppath2) {
2850 unused.push_back (spath);
2854 /* now try to move all unused files into the "dead" directory(ies) */
2856 for (vector<string>::iterator x = unused.begin(); x != unused.end(); ++x) {
2857 struct stat statbuf;
2861 /* don't move the file across filesystems, just
2862 stick it in the `dead_dir_name' directory
2863 on whichever filesystem it was already on.
2866 if ((*x).find ("/sounds/") != string::npos) {
2868 /* old school, go up 1 level */
2870 newpath = Glib::path_get_dirname (*x); // "sounds"
2871 newpath = Glib::path_get_dirname (newpath); // "session-name"
2875 /* new school, go up 4 levels */
2877 newpath = Glib::path_get_dirname (*x); // "audiofiles" or "midifiles"
2878 newpath = Glib::path_get_dirname (newpath); // "session-name"
2879 newpath = Glib::path_get_dirname (newpath); // "interchange"
2880 newpath = Glib::path_get_dirname (newpath); // "session-dir"
2883 newpath = Glib::build_filename (newpath, dead_dir_name);
2885 if (g_mkdir_with_parents (newpath.c_str(), 0755) < 0) {
2886 error << string_compose(_("Session: cannot create dead file folder \"%1\" (%2)"), newpath, strerror (errno)) << endmsg;
2890 newpath = Glib::build_filename (newpath, Glib::path_get_basename ((*x)));
2892 if (Glib::file_test (newpath, Glib::FILE_TEST_EXISTS)) {
2894 /* the new path already exists, try versioning */
2896 char buf[PATH_MAX+1];
2900 snprintf (buf, sizeof (buf), "%s.%d", newpath.c_str(), version);
2903 while (Glib::file_test (newpath_v.c_str(), Glib::FILE_TEST_EXISTS) && version < 999) {
2904 snprintf (buf, sizeof (buf), "%s.%d", newpath.c_str(), ++version);
2908 if (version == 999) {
2909 error << string_compose (_("there are already 1000 files with names like %1; versioning discontinued"),
2913 newpath = newpath_v;
2918 /* it doesn't exist, or we can't read it or something */
2922 stat ((*x).c_str(), &statbuf);
2924 if (::rename ((*x).c_str(), newpath.c_str()) != 0) {
2925 error << string_compose (_("cannot rename unused file source from %1 to %2 (%3)"),
2926 (*x), newpath, strerror (errno))
2931 /* see if there an easy to find peakfile for this file, and remove it.
2934 string base = basename_nosuffix (*x);
2935 base += "%A"; /* this is what we add for the channel suffix of all native files,
2936 or for the first channel of embedded files. it will miss
2937 some peakfiles for other channels
2939 string peakpath = peak_path (base);
2941 if (Glib::file_test (peakpath.c_str(), Glib::FILE_TEST_EXISTS)) {
2942 if (::g_unlink (peakpath.c_str()) != 0) {
2943 error << string_compose (_("cannot remove peakfile %1 for %2 (%3)"),
2944 peakpath, _path, strerror (errno))
2946 /* try to back out */
2947 ::rename (newpath.c_str(), _path.c_str());
2952 rep.paths.push_back (*x);
2953 rep.space += statbuf.st_size;
2956 /* dump the history list */
2960 /* save state so we don't end up a session file
2961 referring to non-existent sources.
2968 _state_of_the_state = (StateOfTheState) (_state_of_the_state & ~InCleanup);
2974 Session::cleanup_trash_sources (CleanupReport& rep)
2976 // FIXME: needs adaptation for MIDI
2978 vector<space_and_path>::iterator i;
2984 for (i = session_dirs.begin(); i != session_dirs.end(); ++i) {
2986 dead_dir = Glib::build_filename ((*i).path, dead_dir_name);
2988 clear_directory (dead_dir, &rep.space, &rep.paths);
2995 Session::set_dirty ()
2997 /* never mark session dirty during loading */
2999 if (_state_of_the_state & Loading) {
3003 bool was_dirty = dirty();
3005 _state_of_the_state = StateOfTheState (_state_of_the_state | Dirty);
3009 DirtyChanged(); /* EMIT SIGNAL */
3015 Session::set_clean ()
3017 bool was_dirty = dirty();
3019 _state_of_the_state = Clean;
3023 DirtyChanged(); /* EMIT SIGNAL */
3028 Session::set_deletion_in_progress ()
3030 _state_of_the_state = StateOfTheState (_state_of_the_state | Deletion);
3034 Session::clear_deletion_in_progress ()
3036 _state_of_the_state = StateOfTheState (_state_of_the_state & (~Deletion));
3040 Session::add_controllable (boost::shared_ptr<Controllable> c)
3042 /* this adds a controllable to the list managed by the Session.
3043 this is a subset of those managed by the Controllable class
3044 itself, and represents the only ones whose state will be saved
3045 as part of the session.
3048 Glib::Threads::Mutex::Lock lm (controllables_lock);
3049 controllables.insert (c);
3052 struct null_deleter { void operator()(void const *) const {} };
3055 Session::remove_controllable (Controllable* c)
3057 if (_state_of_the_state & Deletion) {
3061 Glib::Threads::Mutex::Lock lm (controllables_lock);
3063 Controllables::iterator x = controllables.find (boost::shared_ptr<Controllable>(c, null_deleter()));
3065 if (x != controllables.end()) {
3066 controllables.erase (x);
3070 boost::shared_ptr<Controllable>
3071 Session::controllable_by_id (const PBD::ID& id)
3073 Glib::Threads::Mutex::Lock lm (controllables_lock);
3075 for (Controllables::iterator i = controllables.begin(); i != controllables.end(); ++i) {
3076 if ((*i)->id() == id) {
3081 return boost::shared_ptr<Controllable>();
3084 boost::shared_ptr<Controllable>
3085 Session::controllable_by_descriptor (const ControllableDescriptor& desc)
3087 boost::shared_ptr<Controllable> c;
3088 boost::shared_ptr<Route> r;
3090 switch (desc.top_level_type()) {
3091 case ControllableDescriptor::NamedRoute:
3093 std::string str = desc.top_level_name();
3094 if (str == "Master" || str == "master") {
3096 } else if (str == "control" || str == "listen") {
3099 r = route_by_name (desc.top_level_name());
3104 case ControllableDescriptor::RemoteControlID:
3105 r = route_by_remote_id (desc.rid());
3113 switch (desc.subtype()) {
3114 case ControllableDescriptor::Gain:
3115 c = r->gain_control ();
3118 case ControllableDescriptor::Trim:
3119 c = r->trim()->gain_control ();
3122 case ControllableDescriptor::Solo:
3123 c = r->solo_control();
3126 case ControllableDescriptor::Mute:
3127 c = r->mute_control();
3130 case ControllableDescriptor::Recenable:
3132 boost::shared_ptr<Track> t = boost::dynamic_pointer_cast<Track>(r);
3135 c = t->rec_enable_control ();
3140 case ControllableDescriptor::PanDirection:
3142 c = r->pannable()->pan_azimuth_control;
3146 case ControllableDescriptor::PanWidth:
3148 c = r->pannable()->pan_width_control;
3152 case ControllableDescriptor::PanElevation:
3154 c = r->pannable()->pan_elevation_control;
3158 case ControllableDescriptor::Balance:
3159 /* XXX simple pan control */
3162 case ControllableDescriptor::PluginParameter:
3164 uint32_t plugin = desc.target (0);
3165 uint32_t parameter_index = desc.target (1);
3167 /* revert to zero based counting */
3173 if (parameter_index > 0) {
3177 boost::shared_ptr<Processor> p = r->nth_plugin (plugin);
3180 c = boost::dynamic_pointer_cast<ARDOUR::AutomationControl>(
3181 p->control(Evoral::Parameter(PluginAutomation, 0, parameter_index)));
3186 case ControllableDescriptor::SendGain:
3188 uint32_t send = desc.target (0);
3190 /* revert to zero-based counting */
3196 boost::shared_ptr<Processor> p = r->nth_send (send);
3199 boost::shared_ptr<Send> s = boost::dynamic_pointer_cast<Send>(p);
3200 boost::shared_ptr<Amp> a = s->amp();
3203 c = s->amp()->gain_control();
3210 /* relax and return a null pointer */
3218 Session::add_instant_xml (XMLNode& node, bool write_to_config)
3221 Stateful::add_instant_xml (node, _path);
3224 if (write_to_config) {
3225 Config->add_instant_xml (node);
3230 Session::instant_xml (const string& node_name)
3232 return Stateful::instant_xml (node_name, _path);
3236 Session::save_history (string snapshot_name)
3244 if (!Config->get_save_history() || Config->get_saved_history_depth() < 0 ||
3245 (_history.undo_depth() == 0 && _history.redo_depth() == 0)) {
3249 if (snapshot_name.empty()) {
3250 snapshot_name = _current_snapshot_name;
3253 const string history_filename = legalize_for_path (snapshot_name) + history_suffix;
3254 const string backup_filename = history_filename + backup_suffix;
3255 const std::string xml_path(Glib::build_filename (_session_dir->root_path(), history_filename));
3256 const std::string backup_path(Glib::build_filename (_session_dir->root_path(), backup_filename));
3258 if (Glib::file_test (xml_path, Glib::FILE_TEST_EXISTS)) {
3259 if (::g_rename (xml_path.c_str(), backup_path.c_str()) != 0) {
3260 error << _("could not backup old history file, current history not saved") << endmsg;
3265 tree.set_root (&_history.get_state (Config->get_saved_history_depth()));
3267 if (!tree.write (xml_path))
3269 error << string_compose (_("history could not be saved to %1"), xml_path) << endmsg;
3271 if (g_remove (xml_path.c_str()) != 0) {
3272 error << string_compose(_("Could not remove history file at path \"%1\" (%2)"),
3273 xml_path, g_strerror (errno)) << endmsg;
3275 if (::g_rename (backup_path.c_str(), xml_path.c_str()) != 0) {
3276 error << string_compose (_("could not restore history file from backup %1 (%2)"),
3277 backup_path, g_strerror (errno)) << endmsg;
3287 Session::restore_history (string snapshot_name)
3291 if (snapshot_name.empty()) {
3292 snapshot_name = _current_snapshot_name;
3295 const std::string xml_filename = legalize_for_path (snapshot_name) + history_suffix;
3296 const std::string xml_path(Glib::build_filename (_session_dir->root_path(), xml_filename));
3298 info << "Loading history from " << xml_path << endmsg;
3300 if (!Glib::file_test (xml_path, Glib::FILE_TEST_EXISTS)) {
3301 info << string_compose (_("%1: no history file \"%2\" for this session."),
3302 _name, xml_path) << endmsg;
3306 if (!tree.read (xml_path)) {
3307 error << string_compose (_("Could not understand session history file \"%1\""),
3308 xml_path) << endmsg;
3315 for (XMLNodeConstIterator it = tree.root()->children().begin(); it != tree.root()->children().end(); it++) {
3318 UndoTransaction* ut = new UndoTransaction ();
3321 ut->set_name(t->property("name")->value());
3322 stringstream ss(t->property("tv-sec")->value());
3324 ss.str(t->property("tv-usec")->value());
3326 ut->set_timestamp(tv);
3328 for (XMLNodeConstIterator child_it = t->children().begin();
3329 child_it != t->children().end(); child_it++)
3331 XMLNode *n = *child_it;
3334 if (n->name() == "MementoCommand" ||
3335 n->name() == "MementoUndoCommand" ||
3336 n->name() == "MementoRedoCommand") {
3338 if ((c = memento_command_factory(n))) {
3342 } else if (n->name() == "NoteDiffCommand") {
3343 PBD::ID id (n->property("midi-source")->value());
3344 boost::shared_ptr<MidiSource> midi_source =
3345 boost::dynamic_pointer_cast<MidiSource, Source>(source_by_id(id));
3347 ut->add_command (new MidiModel::NoteDiffCommand(midi_source->model(), *n));
3349 error << _("Failed to downcast MidiSource for NoteDiffCommand") << endmsg;
3352 } else if (n->name() == "SysExDiffCommand") {
3354 PBD::ID id (n->property("midi-source")->value());
3355 boost::shared_ptr<MidiSource> midi_source =
3356 boost::dynamic_pointer_cast<MidiSource, Source>(source_by_id(id));
3358 ut->add_command (new MidiModel::SysExDiffCommand (midi_source->model(), *n));
3360 error << _("Failed to downcast MidiSource for SysExDiffCommand") << endmsg;
3363 } else if (n->name() == "PatchChangeDiffCommand") {
3365 PBD::ID id (n->property("midi-source")->value());
3366 boost::shared_ptr<MidiSource> midi_source =
3367 boost::dynamic_pointer_cast<MidiSource, Source>(source_by_id(id));
3369 ut->add_command (new MidiModel::PatchChangeDiffCommand (midi_source->model(), *n));
3371 error << _("Failed to downcast MidiSource for PatchChangeDiffCommand") << endmsg;
3374 } else if (n->name() == "StatefulDiffCommand") {
3375 if ((c = stateful_diff_command_factory (n))) {
3376 ut->add_command (c);
3379 error << string_compose(_("Couldn't figure out how to make a Command out of a %1 XMLNode."), n->name()) << endmsg;
3390 Session::config_changed (std::string p, bool ours)
3396 if (p == "seamless-loop") {
3398 } else if (p == "rf-speed") {
3400 } else if (p == "auto-loop") {
3402 } else if (p == "auto-input") {
3404 if (Config->get_monitoring_model() == HardwareMonitoring && transport_rolling()) {
3405 /* auto-input only makes a difference if we're rolling */
3406 set_track_monitor_input_status (!config.get_auto_input());
3409 } else if (p == "punch-in") {
3413 if ((location = _locations->auto_punch_location()) != 0) {
3415 if (config.get_punch_in ()) {
3416 replace_event (SessionEvent::PunchIn, location->start());
3418 remove_event (location->start(), SessionEvent::PunchIn);
3422 } else if (p == "punch-out") {
3426 if ((location = _locations->auto_punch_location()) != 0) {
3428 if (config.get_punch_out()) {
3429 replace_event (SessionEvent::PunchOut, location->end());
3431 clear_events (SessionEvent::PunchOut);
3435 } else if (p == "edit-mode") {
3437 Glib::Threads::Mutex::Lock lm (playlists->lock);
3439 for (SessionPlaylists::List::iterator i = playlists->playlists.begin(); i != playlists->playlists.end(); ++i) {
3440 (*i)->set_edit_mode (Config->get_edit_mode ());
3443 } else if (p == "use-video-sync") {
3445 waiting_for_sync_offset = config.get_use_video_sync();
3447 } else if (p == "mmc-control") {
3449 //poke_midi_thread ();
3451 } else if (p == "mmc-device-id" || p == "mmc-receive-id" || p == "mmc-receive-device-id") {
3453 _mmc->set_receive_device_id (Config->get_mmc_receive_device_id());
3455 } else if (p == "mmc-send-id" || p == "mmc-send-device-id") {
3457 _mmc->set_send_device_id (Config->get_mmc_send_device_id());
3459 } else if (p == "midi-control") {
3461 //poke_midi_thread ();
3463 } else if (p == "raid-path") {
3465 setup_raid_path (config.get_raid_path());
3467 } else if (p == "timecode-format") {
3471 } else if (p == "video-pullup") {
3475 } else if (p == "seamless-loop") {
3477 if (play_loop && transport_rolling()) {
3478 // to reset diskstreams etc
3479 request_play_loop (true);
3482 } else if (p == "rf-speed") {
3484 cumulative_rf_motion = 0;
3487 } else if (p == "click-sound") {
3489 setup_click_sounds (1);
3491 } else if (p == "click-emphasis-sound") {
3493 setup_click_sounds (-1);
3495 } else if (p == "clicking") {
3497 if (Config->get_clicking()) {
3498 if (_click_io && click_data) { // don't require emphasis data
3505 } else if (p == "click-gain") {
3508 _click_gain->set_gain (Config->get_click_gain(), this);
3511 } else if (p == "send-mtc") {
3513 if (Config->get_send_mtc ()) {
3514 /* mark us ready to send */
3515 next_quarter_frame_to_send = 0;
3518 } else if (p == "send-mmc") {
3520 _mmc->enable_send (Config->get_send_mmc ());
3522 } else if (p == "midi-feedback") {
3524 session_midi_feedback = Config->get_midi_feedback();
3526 } else if (p == "jack-time-master") {
3528 engine().reset_timebase ();
3530 } else if (p == "native-file-header-format") {
3532 if (!first_file_header_format_reset) {
3533 reset_native_file_format ();
3536 first_file_header_format_reset = false;
3538 } else if (p == "native-file-data-format") {
3540 if (!first_file_data_format_reset) {
3541 reset_native_file_format ();
3544 first_file_data_format_reset = false;
3546 } else if (p == "external-sync") {
3547 if (!config.get_external_sync()) {
3548 drop_sync_source ();
3550 switch_to_sync_source (Config->get_sync_source());
3552 } else if (p == "denormal-model") {
3554 } else if (p == "history-depth") {
3555 set_history_depth (Config->get_history_depth());
3556 } else if (p == "remote-model") {
3557 /* XXX DO SOMETHING HERE TO TELL THE GUI THAT WE NEED
3560 } else if (p == "initial-program-change") {
3562 if (_mmc->output_port() && Config->get_initial_program_change() >= 0) {
3565 buf[0] = MIDI::program; // channel zero by default
3566 buf[1] = (Config->get_initial_program_change() & 0x7f);
3568 _mmc->output_port()->midimsg (buf, sizeof (buf), 0);
3570 } else if (p == "solo-mute-override") {
3571 // catch_up_on_solo_mute_override ();
3572 } else if (p == "listen-position" || p == "pfl-position") {
3573 listen_position_changed ();
3574 } else if (p == "solo-control-is-listen-control") {
3575 solo_control_mode_changed ();
3576 } else if (p == "solo-mute-gain") {
3577 _solo_cut_control->Changed();
3578 } else if (p == "timecode-offset" || p == "timecode-offset-negative") {
3579 last_timecode_valid = false;
3580 } else if (p == "playback-buffer-seconds") {
3581 AudioSource::allocate_working_buffers (frame_rate());
3582 } else if (p == "ltc-source-port") {
3583 reconnect_ltc_input ();
3584 } else if (p == "ltc-sink-port") {
3585 reconnect_ltc_output ();
3586 } else if (p == "timecode-generator-offset") {
3587 ltc_tx_parse_offset();
3594 Session::set_history_depth (uint32_t d)
3596 _history.set_depth (d);
3600 Session::load_diskstreams_2X (XMLNode const & node, int)
3603 XMLNodeConstIterator citer;
3605 clist = node.children();
3607 for (citer = clist.begin(); citer != clist.end(); ++citer) {
3610 /* diskstreams added automatically by DiskstreamCreated handler */
3611 if ((*citer)->name() == "AudioDiskstream" || (*citer)->name() == "DiskStream") {
3612 boost::shared_ptr<AudioDiskstream> dsp (new AudioDiskstream (*this, **citer));
3613 _diskstreams_2X.push_back (dsp);
3615 error << _("Session: unknown diskstream type in XML") << endmsg;
3619 catch (failed_constructor& err) {
3620 error << _("Session: could not load diskstream via XML state") << endmsg;
3628 /** Connect things to the MMC object */
3630 Session::setup_midi_machine_control ()
3632 _mmc = new MIDI::MachineControl;
3633 _mmc->set_ports (_midi_ports->mmc_input_port(), _midi_ports->mmc_output_port());
3635 _mmc->Play.connect_same_thread (*this, boost::bind (&Session::mmc_deferred_play, this, _1));
3636 _mmc->DeferredPlay.connect_same_thread (*this, boost::bind (&Session::mmc_deferred_play, this, _1));
3637 _mmc->Stop.connect_same_thread (*this, boost::bind (&Session::mmc_stop, this, _1));
3638 _mmc->FastForward.connect_same_thread (*this, boost::bind (&Session::mmc_fast_forward, this, _1));
3639 _mmc->Rewind.connect_same_thread (*this, boost::bind (&Session::mmc_rewind, this, _1));
3640 _mmc->Pause.connect_same_thread (*this, boost::bind (&Session::mmc_pause, this, _1));
3641 _mmc->RecordPause.connect_same_thread (*this, boost::bind (&Session::mmc_record_pause, this, _1));
3642 _mmc->RecordStrobe.connect_same_thread (*this, boost::bind (&Session::mmc_record_strobe, this, _1));
3643 _mmc->RecordExit.connect_same_thread (*this, boost::bind (&Session::mmc_record_exit, this, _1));
3644 _mmc->Locate.connect_same_thread (*this, boost::bind (&Session::mmc_locate, this, _1, _2));
3645 _mmc->Step.connect_same_thread (*this, boost::bind (&Session::mmc_step, this, _1, _2));
3646 _mmc->Shuttle.connect_same_thread (*this, boost::bind (&Session::mmc_shuttle, this, _1, _2, _3));
3647 _mmc->TrackRecordStatusChange.connect_same_thread (*this, boost::bind (&Session::mmc_record_enable, this, _1, _2, _3));
3649 /* also handle MIDI SPP because its so common */
3651 _mmc->SPPStart.connect_same_thread (*this, boost::bind (&Session::spp_start, this));
3652 _mmc->SPPContinue.connect_same_thread (*this, boost::bind (&Session::spp_continue, this));
3653 _mmc->SPPStop.connect_same_thread (*this, boost::bind (&Session::spp_stop, this));
3656 boost::shared_ptr<Controllable>
3657 Session::solo_cut_control() const
3659 /* the solo cut control is a bit of an anomaly, at least as of Febrary 2011. There are no other
3660 controls in Ardour that currently get presented to the user in the GUI that require
3661 access as a Controllable and are also NOT owned by some SessionObject (e.g. Route, or MonitorProcessor).
3663 its actually an RCConfiguration parameter, so we use a ProxyControllable to wrap
3664 it up as a Controllable. Changes to the Controllable will just map back to the RCConfiguration
3668 return _solo_cut_control;
3672 Session::rename (const std::string& new_name)
3674 string legal_name = legalize_for_path (new_name);
3680 string const old_sources_root = _session_dir->sources_root();
3682 if (!_writable || (_state_of_the_state & CannotSave)) {
3683 error << _("Cannot rename read-only session.") << endmsg;
3684 return 0; // don't show "messed up" warning
3686 if (record_status() == Recording) {
3687 error << _("Cannot rename session while recording") << endmsg;
3688 return 0; // don't show "messed up" warning
3691 StateProtector stp (this);
3696 * interchange subdirectory
3700 * Backup files are left unchanged and not renamed.
3703 /* Windows requires that we close all files before attempting the
3704 * rename. This works on other platforms, but isn't necessary there.
3705 * Leave it in place for all platforms though, since it may help
3706 * catch issues that could arise if the way Source files work ever
3707 * change (since most developers are not using Windows).
3710 for (SourceMap::const_iterator i = sources.begin(); i != sources.end(); ++i) {
3711 boost::shared_ptr<FileSource> fs = boost::dynamic_pointer_cast<FileSource> (i->second);
3717 /* pass one: not 100% safe check that the new directory names don't
3721 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
3725 /* this is a stupid hack because Glib::path_get_dirname() is
3726 * lexical-only, and so passing it /a/b/c/ gives a different
3727 * result than passing it /a/b/c ...
3730 if (oldstr[oldstr.length()-1] == G_DIR_SEPARATOR) {
3731 oldstr = oldstr.substr (0, oldstr.length() - 1);
3734 string base = Glib::path_get_dirname (oldstr);
3736 newstr = Glib::build_filename (base, legal_name);
3738 cerr << "Looking for " << newstr << endl;
3740 if (Glib::file_test (newstr, Glib::FILE_TEST_EXISTS)) {
3741 cerr << " exists\n";
3750 for (vector<space_and_path>::iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
3756 /* this is a stupid hack because Glib::path_get_dirname() is
3757 * lexical-only, and so passing it /a/b/c/ gives a different
3758 * result than passing it /a/b/c ...
3761 if (oldstr[oldstr.length()-1] == G_DIR_SEPARATOR) {
3762 oldstr = oldstr.substr (0, oldstr.length() - 1);
3765 string base = Glib::path_get_dirname (oldstr);
3766 newstr = Glib::build_filename (base, legal_name);
3768 cerr << "for " << oldstr << " new dir = " << newstr << endl;
3770 cerr << "Rename " << oldstr << " => " << newstr << endl;
3771 if (::g_rename (oldstr.c_str(), newstr.c_str()) != 0) {
3772 cerr << string_compose (_("renaming %s as %2 failed (%3)"), oldstr, newstr, g_strerror (errno)) << endl;
3773 error << string_compose (_("renaming %s as %2 failed (%3)"), oldstr, newstr, g_strerror (errno)) << endmsg;
3777 /* Reset path in "session dirs" */
3782 /* reset primary SessionDirectory object */
3785 (*_session_dir) = newstr;
3790 /* now rename directory below session_dir/interchange */
3792 string old_interchange_dir;
3793 string new_interchange_dir;
3795 /* use newstr here because we renamed the path
3796 * (folder/directory) that used to be oldstr to newstr above
3799 v.push_back (newstr);
3800 v.push_back (interchange_dir_name);
3801 v.push_back (Glib::path_get_basename (oldstr));
3803 old_interchange_dir = Glib::build_filename (v);
3806 v.push_back (newstr);
3807 v.push_back (interchange_dir_name);
3808 v.push_back (legal_name);
3810 new_interchange_dir = Glib::build_filename (v);
3812 cerr << "Rename " << old_interchange_dir << " => " << new_interchange_dir << endl;
3814 if (::g_rename (old_interchange_dir.c_str(), new_interchange_dir.c_str()) != 0) {
3815 cerr << string_compose (_("renaming %s as %2 failed (%3)"),
3816 old_interchange_dir, new_interchange_dir,
3819 error << string_compose (_("renaming %s as %2 failed (%3)"),
3820 old_interchange_dir, new_interchange_dir,
3829 oldstr = Glib::build_filename (new_path, _current_snapshot_name + statefile_suffix);
3830 newstr= Glib::build_filename (new_path, legal_name + statefile_suffix);
3832 cerr << "Rename " << oldstr << " => " << newstr << endl;
3834 if (::g_rename (oldstr.c_str(), newstr.c_str()) != 0) {
3835 cerr << string_compose (_("renaming %1 as %2 failed (%3)"), oldstr, newstr, g_strerror (errno)) << endl;
3836 error << string_compose (_("renaming %1 as %2 failed (%3)"), oldstr, newstr, g_strerror (errno)) << endmsg;
3842 oldstr = Glib::build_filename (new_path, _current_snapshot_name) + history_suffix;
3844 if (Glib::file_test (oldstr, Glib::FILE_TEST_EXISTS)) {
3845 newstr = Glib::build_filename (new_path, legal_name) + history_suffix;
3847 cerr << "Rename " << oldstr << " => " << newstr << endl;
3849 if (::g_rename (oldstr.c_str(), newstr.c_str()) != 0) {
3850 cerr << string_compose (_("renaming %1 as %2 failed (%3)"), oldstr, newstr, g_strerror (errno)) << endl;
3851 error << string_compose (_("renaming %1 as %2 failed (%3)"), oldstr, newstr, g_strerror (errno)) << endmsg;
3856 /* remove old name from recent sessions */
3857 remove_recent_sessions (_path);
3860 /* update file source paths */
3862 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ++i) {
3863 boost::shared_ptr<FileSource> fs = boost::dynamic_pointer_cast<FileSource> (i->second);
3865 string p = fs->path ();
3866 boost::replace_all (p, old_sources_root, _session_dir->sources_root());
3868 SourceFactory::setup_peakfile(i->second, true);
3872 _current_snapshot_name = new_name;
3877 /* save state again to get everything just right */
3879 save_state (_current_snapshot_name);
3881 /* add to recent sessions */
3883 store_recent_sessions (new_name, _path);
3889 Session::get_session_info_from_path (XMLTree& tree, const string& xmlpath)
3891 if (!Glib::file_test (xmlpath, Glib::FILE_TEST_EXISTS)) {
3895 if (!tree.read (xmlpath)) {
3903 Session::get_info_from_path (const string& xmlpath, float& sample_rate, SampleFormat& data_format)
3906 bool found_sr = false;
3907 bool found_data_format = false;
3909 if (get_session_info_from_path (tree, xmlpath)) {
3915 const XMLProperty* prop;
3916 if ((prop = tree.root()->property (X_("sample-rate"))) != 0) {
3917 sample_rate = atoi (prop->value());
3921 const XMLNodeList& children (tree.root()->children());
3922 for (XMLNodeList::const_iterator c = children.begin(); c != children.end(); ++c) {
3923 const XMLNode* child = *c;
3924 if (child->name() == "Config") {
3925 const XMLNodeList& options (child->children());
3926 for (XMLNodeList::const_iterator oc = options.begin(); oc != options.end(); ++oc) {
3927 const XMLNode* option = *oc;
3928 const XMLProperty* name = option->property("name");
3934 if (name->value() == "native-file-data-format") {
3935 const XMLProperty* value = option->property ("value");
3937 SampleFormat fmt = (SampleFormat) string_2_enum (option->property ("value")->value(), fmt);
3939 found_data_format = true;
3945 if (found_data_format) {
3950 return !(found_sr && found_data_format); // zero if they are both found
3953 typedef std::vector<boost::shared_ptr<FileSource> > SeveralFileSources;
3954 typedef std::map<std::string,SeveralFileSources> SourcePathMap;
3957 Session::bring_all_sources_into_session (boost::function<void(uint32_t,uint32_t,string)> callback)
3961 SourcePathMap source_path_map;
3963 boost::shared_ptr<AudioFileSource> afs;
3968 Glib::Threads::Mutex::Lock lm (source_lock);
3970 cerr << " total sources = " << sources.size();
3972 for (SourceMap::const_iterator i = sources.begin(); i != sources.end(); ++i) {
3973 boost::shared_ptr<FileSource> fs = boost::dynamic_pointer_cast<FileSource> (i->second);
3979 if (fs->within_session()) {
3983 if (source_path_map.find (fs->path()) != source_path_map.end()) {
3984 source_path_map[fs->path()].push_back (fs);
3986 SeveralFileSources v;
3988 source_path_map.insert (make_pair (fs->path(), v));
3994 cerr << " fsources = " << total << endl;
3996 for (SourcePathMap::iterator i = source_path_map.begin(); i != source_path_map.end(); ++i) {
3998 /* tell caller where we are */
4000 string old_path = i->first;
4002 callback (n, total, old_path);
4004 cerr << old_path << endl;
4008 switch (i->second.front()->type()) {
4009 case DataType::AUDIO:
4010 new_path = new_audio_source_path_for_embedded (old_path);
4013 case DataType::MIDI:
4014 /* XXX not implemented yet */
4018 if (new_path.empty()) {
4022 cerr << "Move " << old_path << " => " << new_path << endl;
4024 if (!copy_file (old_path, new_path)) {
4025 cerr << "failed !\n";
4029 /* make sure we stop looking in the external
4030 dir/folder. Remember, this is an all-or-nothing
4031 operations, it doesn't merge just some files.
4033 remove_dir_from_search_path (Glib::path_get_dirname (old_path), i->second.front()->type());
4035 for (SeveralFileSources::iterator f = i->second.begin(); f != i->second.end(); ++f) {
4036 (*f)->set_path (new_path);
4041 save_state ("", false, false);
4047 bool accept_all_files (string const &, void *)
4053 Session::save_as_bring_callback (uint32_t,uint32_t,string)
4055 /* It would be good if this did something useful vis-a-vis save-as, but the arguments doesn't provide the correct information right now to do this.
4060 make_new_media_path (string old_path, string new_session_folder, string new_session_path)
4062 /* typedir is the "midifiles" or "audiofiles" etc. part of the path. */
4064 string typedir = Glib::path_get_basename (Glib::path_get_dirname (old_path));
4066 v.push_back (new_session_folder); /* full path */
4067 v.push_back (interchange_dir_name);
4068 v.push_back (new_session_path); /* just one directory/folder */
4069 v.push_back (typedir);
4070 v.push_back (Glib::path_get_basename (old_path));
4072 return Glib::build_filename (v);
4076 Session::save_as (SaveAs& saveas)
4078 vector<string> files;
4079 string current_folder = Glib::path_get_dirname (_path);
4080 string new_folder = legalize_for_path (saveas.new_name);
4081 string to_dir = Glib::build_filename (saveas.new_parent_folder, new_folder);
4082 int64_t total_bytes = 0;
4086 int32_t internal_file_cnt = 0;
4088 vector<string> do_not_copy_extensions;
4089 do_not_copy_extensions.push_back (statefile_suffix);
4090 do_not_copy_extensions.push_back (pending_suffix);
4091 do_not_copy_extensions.push_back (backup_suffix);
4092 do_not_copy_extensions.push_back (temp_suffix);
4093 do_not_copy_extensions.push_back (history_suffix);
4095 /* get total size */
4097 for (vector<space_and_path>::const_iterator sd = session_dirs.begin(); sd != session_dirs.end(); ++sd) {
4099 /* need to clear this because
4100 * find_files_matching_filter() is cumulative
4105 find_files_matching_filter (files, (*sd).path, accept_all_files, 0, false, true, true);
4107 all += files.size();
4109 for (vector<string>::iterator i = files.begin(); i != files.end(); ++i) {
4111 g_stat ((*i).c_str(), &gsb);
4112 total_bytes += gsb.st_size;
4116 /* save old values so we can switch back if we are not switching to the new session */
4118 string old_path = _path;
4119 string old_name = _name;
4120 string old_snapshot = _current_snapshot_name;
4121 string old_sd = _session_dir->root_path();
4122 vector<string> old_search_path[DataType::num_types];
4123 string old_config_search_path[DataType::num_types];
4125 old_search_path[DataType::AUDIO] = source_search_path (DataType::AUDIO);
4126 old_search_path[DataType::MIDI] = source_search_path (DataType::MIDI);
4127 old_config_search_path[DataType::AUDIO] = config.get_audio_search_path ();
4128 old_config_search_path[DataType::MIDI] = config.get_midi_search_path ();
4130 /* switch session directory */
4132 (*_session_dir) = to_dir;
4134 /* create new tree */
4136 if (!_session_dir->create()) {
4137 saveas.failure_message = string_compose (_("Cannot create new session folder %1"), to_dir);
4142 /* copy all relevant files. Find each location in session_dirs,
4143 * and copy files from there to target.
4146 for (vector<space_and_path>::const_iterator sd = session_dirs.begin(); sd != session_dirs.end(); ++sd) {
4148 /* need to clear this because
4149 * find_files_matching_filter() is cumulative
4154 const size_t prefix_len = (*sd).path.size();
4156 /* Work just on the files within this session dir */
4158 find_files_matching_filter (files, (*sd).path, accept_all_files, 0, false, true, true);
4160 /* add dir separator to protect against collisions with
4161 * track names (e.g. track named "audiofiles" or
4165 static const std::string audiofile_dir_string = string (sound_dir_name) + G_DIR_SEPARATOR;
4166 static const std::string midifile_dir_string = string (midi_dir_name) + G_DIR_SEPARATOR;
4167 static const std::string analysis_dir_string = analysis_dir() + G_DIR_SEPARATOR;
4169 /* copy all the files. Handling is different for media files
4170 than others because of the *silly* subtree we have below the interchange
4171 folder. That really was a bad idea, but I'm not fixing it as part of
4172 implementing ::save_as().
4175 for (vector<string>::iterator i = files.begin(); i != files.end(); ++i) {
4177 std::string from = *i;
4179 if ((*i).find (audiofile_dir_string) != string::npos) {
4181 /* audio file: only copy if asked */
4183 if (saveas.include_media && saveas.copy_media) {
4185 string to = make_new_media_path (*i, to_dir, new_folder);
4187 info << "media file copying from " << from << " to " << to << endmsg;
4189 if (!copy_file (from, to)) {
4190 throw Glib::FileError (Glib::FileError::IO_ERROR, "copy failed");
4194 /* we found media files inside the session folder */
4196 internal_file_cnt++;
4198 } else if ((*i).find (midifile_dir_string) != string::npos) {
4200 /* midi file: always copy unless
4201 * creating an empty new session
4204 if (saveas.include_media) {
4206 string to = make_new_media_path (*i, to_dir, new_folder);
4208 info << "media file copying from " << from << " to " << to << endmsg;
4210 if (!copy_file (from, to)) {
4211 throw Glib::FileError (Glib::FileError::IO_ERROR, "copy failed");
4215 /* we found media files inside the session folder */
4217 internal_file_cnt++;
4219 } else if ((*i).find (analysis_dir_string) != string::npos) {
4221 /* make sure analysis dir exists in
4222 * new session folder, but we're not
4223 * copying analysis files here, see
4227 (void) g_mkdir_with_parents (analysis_dir().c_str(), 775);
4232 /* normal non-media file. Don't copy state, history, etc.
4235 bool do_copy = true;
4237 for (vector<string>::iterator v = do_not_copy_extensions.begin(); v != do_not_copy_extensions.end(); ++v) {
4238 if (((*i).length() > (*v).length()) && ((*i).find (*v) == (*i).length() - (*v).length())) {
4239 /* end of filename matches extension, do not copy file */
4245 if (!saveas.copy_media && (*i).find (peakfile_suffix) != string::npos) {
4246 /* don't copy peakfiles if
4247 * we're not copying media
4253 string to = Glib::build_filename (to_dir, (*i).substr (prefix_len));
4255 info << "attempting to make directory/folder " << to << endmsg;
4257 if (g_mkdir_with_parents (Glib::path_get_dirname (to).c_str(), 0755)) {
4258 throw Glib::FileError (Glib::FileError::IO_ERROR, "cannot create required directory");
4261 info << "attempting to copy " << from << " to " << to << endmsg;
4263 if (!copy_file (from, to)) {
4264 throw Glib::FileError (Glib::FileError::IO_ERROR, "copy failed");
4269 /* measure file size even if we're not going to copy so that our Progress
4270 signals are correct, since we included these do-not-copy files
4271 in the computation of the total size and file count.
4275 g_stat ((*i).c_str(), &gsb);
4276 copied += gsb.st_size;
4279 double fraction = (double) copied / total_bytes;
4281 bool keep_going = true;
4283 if (saveas.copy_media) {
4285 /* no need or expectation of this if
4286 * media is not being copied, because
4287 * it will be fast(ish).
4290 /* tell someone "X percent, file M of N"; M is one-based */
4292 boost::optional<bool> res = saveas.Progress (fraction, cnt, all);
4300 throw Glib::FileError (Glib::FileError::FAILED, "copy cancelled");
4306 /* copy optional folders, if any */
4308 string old = plugins_dir ();
4309 if (Glib::file_test (old, Glib::FILE_TEST_EXISTS)) {
4310 string newdir = Glib::build_filename (to_dir, Glib::path_get_basename (old));
4311 copy_files (old, newdir);
4314 old = externals_dir ();
4315 if (Glib::file_test (old, Glib::FILE_TEST_EXISTS)) {
4316 string newdir = Glib::build_filename (to_dir, Glib::path_get_basename (old));
4317 copy_files (old, newdir);
4320 old = automation_dir ();
4321 if (Glib::file_test (old, Glib::FILE_TEST_EXISTS)) {
4322 string newdir = Glib::build_filename (to_dir, Glib::path_get_basename (old));
4323 copy_files (old, newdir);
4326 if (saveas.include_media) {
4328 if (saveas.copy_media) {
4329 #ifndef PLATFORM_WINDOWS
4330 /* There are problems with analysis files on
4331 * Windows, because they used a colon in their
4332 * names as late as 4.0. Colons are not legal
4333 * under Windows even if NTFS allows them.
4335 * This is a tricky problem to solve so for
4336 * just don't copy these files. They will be
4337 * regenerated as-needed anyway, subject to the
4338 * existing issue that the filenames will be
4339 * rejected by Windows, which is a separate
4340 * problem (though related).
4343 /* only needed if we are copying media, since the
4344 * analysis data refers to media data
4347 old = analysis_dir ();
4348 if (Glib::file_test (old, Glib::FILE_TEST_EXISTS)) {
4349 string newdir = Glib::build_filename (to_dir, "analysis");
4350 copy_files (old, newdir);
4352 #endif /* PLATFORM_WINDOWS */
4358 _current_snapshot_name = saveas.new_name;
4359 _name = saveas.new_name;
4361 if (saveas.include_media && !saveas.copy_media) {
4363 /* reset search paths of the new session (which we're pretending to be right now) to
4364 include the original session search path, so we can still find all audio.
4367 if (internal_file_cnt) {
4368 for (vector<string>::iterator s = old_search_path[DataType::AUDIO].begin(); s != old_search_path[DataType::AUDIO].end(); ++s) {
4369 ensure_search_path_includes (*s, DataType::AUDIO);
4372 /* we do not do this for MIDI because we copy
4373 all MIDI files if saveas.include_media is
4379 bool was_dirty = dirty ();
4381 save_state ("", false, false, !saveas.include_media);
4382 save_default_options ();
4384 if (saveas.copy_media && saveas.copy_external) {
4385 if (bring_all_sources_into_session (boost::bind (&Session::save_as_bring_callback, this, _1, _2, _3))) {
4386 throw Glib::FileError (Glib::FileError::NO_SPACE_LEFT, "consolidate failed");
4390 saveas.final_session_folder_name = _path;
4392 if (!saveas.switch_to) {
4394 /* switch back to the way things were */
4398 _current_snapshot_name = old_snapshot;
4400 (*_session_dir) = old_sd;
4406 if (internal_file_cnt) {
4407 /* reset these to their original values */
4408 config.set_audio_search_path (old_config_search_path[DataType::AUDIO]);
4409 config.set_midi_search_path (old_config_search_path[DataType::MIDI]);
4414 /* prune session dirs, and update disk space statistics
4419 session_dirs.clear ();
4420 session_dirs.push_back (sp);
4421 refresh_disk_space ();
4423 /* ensure that all existing tracks reset their current capture source paths
4425 reset_write_sources (true, true);
4427 /* the copying above was based on actually discovering files, not just iterating over the sources list.
4428 But if we're going to switch to the new (copied) session, we need to change the paths in the sources also.
4431 for (SourceMap::const_iterator i = sources.begin(); i != sources.end(); ++i) {
4432 boost::shared_ptr<FileSource> fs = boost::dynamic_pointer_cast<FileSource> (i->second);
4438 if (fs->within_session()) {
4439 string newpath = make_new_media_path (fs->path(), to_dir, new_folder);
4440 fs->set_path (newpath);
4445 } catch (Glib::FileError& e) {
4447 saveas.failure_message = e.what();
4449 /* recursively remove all the directories */
4451 remove_directory (to_dir);
4459 saveas.failure_message = _("unknown reason");
4461 /* recursively remove all the directories */
4463 remove_directory (to_dir);