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/profile.h"
104 #include "ardour/proxy_controllable.h"
105 #include "ardour/recent_sessions.h"
106 #include "ardour/region_factory.h"
107 #include "ardour/route_group.h"
108 #include "ardour/send.h"
109 #include "ardour/session.h"
110 #include "ardour/session_directory.h"
111 #include "ardour/session_metadata.h"
112 #include "ardour/session_playlists.h"
113 #include "ardour/session_state_utils.h"
114 #include "ardour/silentfilesource.h"
115 #include "ardour/sndfilesource.h"
116 #include "ardour/source_factory.h"
117 #include "ardour/speakers.h"
118 #include "ardour/template_utils.h"
119 #include "ardour/tempo.h"
120 #include "ardour/ticker.h"
121 #include "ardour/user_bundle.h"
123 #include "control_protocol/control_protocol.h"
129 using namespace ARDOUR;
133 Session::pre_engine_init (string fullpath)
135 if (fullpath.empty()) {
137 throw failed_constructor();
140 /* discover canonical fullpath */
142 _path = canonical_path(fullpath);
145 if (Profile->get_trx() ) {
146 // Waves TracksLive has a usecase of session replacement with a new one.
147 // We should check session state file (<session_name>.ardour) existance
148 // to determine if the session is new or not
150 string full_session_name = Glib::build_filename( fullpath, _name );
151 full_session_name += statefile_suffix;
153 _is_new = !Glib::file_test (full_session_name, Glib::FileTest (G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR));
155 _is_new = !Glib::file_test (_path, Glib::FileTest (G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR));
158 /* finish initialization that can't be done in a normal C++ constructor
162 timerclear (&last_mmc_step);
163 g_atomic_int_set (&processing_prohibited, 0);
164 g_atomic_int_set (&_record_status, Disabled);
165 g_atomic_int_set (&_playback_load, 100);
166 g_atomic_int_set (&_capture_load, 100);
168 _all_route_group->set_active (true, this);
169 interpolation.add_channel_to (0, 0);
171 if (config.get_use_video_sync()) {
172 waiting_for_sync_offset = true;
174 waiting_for_sync_offset = false;
177 last_rr_session_dir = session_dirs.begin();
179 set_history_depth (Config->get_history_depth());
181 /* default: assume simple stereo speaker configuration */
183 _speakers->setup_default_speakers (2);
185 _solo_cut_control.reset (new ProxyControllable (_("solo cut control (dB)"), PBD::Controllable::GainLike,
186 boost::bind (&RCConfiguration::set_solo_mute_gain, Config, _1),
187 boost::bind (&RCConfiguration::get_solo_mute_gain, Config)));
188 add_controllable (_solo_cut_control);
190 /* These are all static "per-class" signals */
192 SourceFactory::SourceCreated.connect_same_thread (*this, boost::bind (&Session::add_source, this, _1));
193 PlaylistFactory::PlaylistCreated.connect_same_thread (*this, boost::bind (&Session::add_playlist, this, _1, _2));
194 AutomationList::AutomationListCreated.connect_same_thread (*this, boost::bind (&Session::add_automation_list, this, _1));
195 Controllable::Destroyed.connect_same_thread (*this, boost::bind (&Session::remove_controllable, this, _1));
196 IO::PortCountChanged.connect_same_thread (*this, boost::bind (&Session::ensure_buffers, this, _1));
198 /* stop IO objects from doing stuff until we're ready for them */
200 Delivery::disable_panners ();
201 IO::disable_connecting ();
203 AudioFileSource::set_peak_dir (_session_dir->peak_path());
207 Session::post_engine_init ()
209 BootMessage (_("Set block size and sample rate"));
211 set_block_size (_engine.samples_per_cycle());
212 set_frame_rate (_engine.sample_rate());
214 BootMessage (_("Using configuration"));
216 _midi_ports = new MidiPortManager;
218 MIDISceneChanger* msc;
220 _scene_changer = msc = new MIDISceneChanger (*this);
221 msc->set_input_port (scene_input_port());
222 msc->set_output_port (scene_out());
224 boost::function<framecnt_t(void)> timer_func (boost::bind (&Session::audible_frame, this));
225 boost::dynamic_pointer_cast<AsyncMIDIPort>(scene_in())->set_timer (timer_func);
227 setup_midi_machine_control ();
229 if (_butler->start_thread()) {
233 if (start_midi_thread ()) {
237 setup_click_sounds (0);
238 setup_midi_control ();
240 _engine.Halted.connect_same_thread (*this, boost::bind (&Session::engine_halted, this));
241 _engine.Xrun.connect_same_thread (*this, boost::bind (&Session::xrun_recovery, this));
244 /* tempo map requires sample rate knowledge */
247 _tempo_map = new TempoMap (_current_frame_rate);
248 _tempo_map->PropertyChanged.connect_same_thread (*this, boost::bind (&Session::tempo_map_changed, this, _1));
250 /* MidiClock requires a tempo map */
252 midi_clock = new MidiClockTicker ();
253 midi_clock->set_session (this);
255 /* crossfades require sample rate knowledge */
257 SndFileSource::setup_standard_crossfades (*this, frame_rate());
258 _engine.GraphReordered.connect_same_thread (*this, boost::bind (&Session::graph_reordered, this));
260 AudioDiskstream::allocate_working_buffers();
261 refresh_disk_space ();
263 /* we're finally ready to call set_state() ... all objects have
264 * been created, the engine is running.
268 if (set_state (*state_tree->root(), Stateful::loading_state_version)) {
272 // set_state() will call setup_raid_path(), but if it's a new session we need
273 // to call setup_raid_path() here.
274 setup_raid_path (_path);
279 boost::function<void (std::string)> ff (boost::bind (&Session::config_changed, this, _1, false));
280 boost::function<void (std::string)> ft (boost::bind (&Session::config_changed, this, _1, true));
282 Config->map_parameters (ff);
283 config.map_parameters (ft);
284 _butler->map_parameters ();
286 /* Reset all panners */
288 Delivery::reset_panners ();
290 /* this will cause the CPM to instantiate any protocols that are in use
291 * (or mandatory), which will pass it this Session, and then call
292 * set_state() on each instantiated protocol to match stored state.
295 ControlProtocolManager::instance().set_session (this);
297 /* This must be done after the ControlProtocolManager set_session above,
298 as it will set states for ports which the ControlProtocolManager creates.
301 // XXX set state of MIDI::Port's
302 // MidiPortManager::instance()->set_port_states (Config->midi_port_states ());
304 /* And this must be done after the MIDI::Manager::set_port_states as
305 * it will try to make connections whose details are loaded by set_port_states.
310 /* Let control protocols know that we are now all connected, so they
311 * could start talking to surfaces if they want to.
314 ControlProtocolManager::instance().midi_connectivity_established ();
316 if (_is_new && !no_auto_connect()) {
317 Glib::Threads::Mutex::Lock lm (AudioEngine::instance()->process_lock());
318 auto_connect_master_bus ();
321 _state_of_the_state = StateOfTheState (_state_of_the_state & ~(CannotSave|Dirty));
323 /* update latencies */
325 initialize_latencies ();
327 _locations->added.connect_same_thread (*this, boost::bind (&Session::location_added, this, _1));
328 _locations->removed.connect_same_thread (*this, boost::bind (&Session::location_removed, this, _1));
329 _locations->changed.connect_same_thread (*this, boost::bind (&Session::locations_changed, this));
331 } catch (AudioEngine::PortRegistrationFailure& err) {
332 /* handle this one in a different way than all others, so that its clear what happened */
333 error << err.what() << endmsg;
339 BootMessage (_("Reset Remote Controls"));
341 // send_full_time_code (0);
342 _engine.transport_locate (0);
344 send_immediate_mmc (MIDI::MachineControlCommand (MIDI::MachineControl::cmdMmcReset));
345 send_immediate_mmc (MIDI::MachineControlCommand (Timecode::Time ()));
347 MIDI::Name::MidiPatchManager::instance().set_session (this);
350 /* initial program change will be delivered later; see ::config_changed() */
352 _state_of_the_state = Clean;
354 Port::set_connecting_blocked (false);
356 DirtyChanged (); /* EMIT SIGNAL */
360 } else if (state_was_pending) {
362 remove_pending_capture_state ();
363 state_was_pending = false;
366 /* Now, finally, we can fill the playback buffers */
368 BootMessage (_("Filling playback buffers"));
370 boost::shared_ptr<RouteList> rl = routes.reader();
371 for (RouteList::iterator r = rl->begin(); r != rl->end(); ++r) {
372 boost::shared_ptr<Track> trk = boost::dynamic_pointer_cast<Track> (*r);
373 if (trk && !trk->hidden()) {
374 trk->seek (_transport_frame, true);
382 Session::session_loaded ()
386 _state_of_the_state = Clean;
388 DirtyChanged (); /* EMIT SIGNAL */
392 } else if (state_was_pending) {
394 remove_pending_capture_state ();
395 state_was_pending = false;
398 /* Now, finally, we can fill the playback buffers */
400 BootMessage (_("Filling playback buffers"));
401 force_locate (_transport_frame, false);
405 Session::raid_path () const
407 Searchpath raid_search_path;
409 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
410 raid_search_path += (*i).path;
413 return raid_search_path.to_string ();
417 Session::setup_raid_path (string path)
426 session_dirs.clear ();
428 Searchpath search_path(path);
429 Searchpath sound_search_path;
430 Searchpath midi_search_path;
432 for (Searchpath::const_iterator i = search_path.begin(); i != search_path.end(); ++i) {
434 sp.blocks = 0; // not needed
435 session_dirs.push_back (sp);
437 SessionDirectory sdir(sp.path);
439 sound_search_path += sdir.sound_path ();
440 midi_search_path += sdir.midi_path ();
443 // reset the round-robin soundfile path thingie
444 last_rr_session_dir = session_dirs.begin();
448 Session::path_is_within_session (const std::string& path)
450 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
451 if (PBD::path_is_within (i->path, path)) {
459 Session::ensure_subdirs ()
463 dir = session_directory().peak_path();
465 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
466 error << string_compose(_("Session: cannot create session peakfile folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
470 dir = session_directory().sound_path();
472 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
473 error << string_compose(_("Session: cannot create session sounds dir \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
477 dir = session_directory().midi_path();
479 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
480 error << string_compose(_("Session: cannot create session midi dir \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
484 dir = session_directory().dead_path();
486 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
487 error << string_compose(_("Session: cannot create session dead sounds folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
491 dir = session_directory().export_path();
493 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
494 error << string_compose(_("Session: cannot create session export folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
498 dir = analysis_dir ();
500 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
501 error << string_compose(_("Session: cannot create session analysis folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
505 dir = plugins_dir ();
507 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
508 error << string_compose(_("Session: cannot create session plugins folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
512 dir = externals_dir ();
514 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
515 error << string_compose(_("Session: cannot create session externals folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
522 /** @param session_template directory containing session template, or empty.
523 * Caller must not hold process lock.
526 Session::create (const string& session_template, BusProfile* bus_profile)
528 if (g_mkdir_with_parents (_path.c_str(), 0755) < 0) {
529 error << string_compose(_("Session: cannot create session folder \"%1\" (%2)"), _path, strerror (errno)) << endmsg;
533 if (ensure_subdirs ()) {
537 _writable = exists_and_writable (_path);
539 if (!session_template.empty()) {
540 std::string in_path = (ARDOUR::Profile->get_trx () ? session_template : session_template_dir_to_file (session_template));
542 ifstream in(in_path.c_str());
545 /* no need to call legalize_for_path() since the string
546 * in session_template is already a legal path name
548 string out_path = Glib::build_filename (_session_dir->root_path(), _name + statefile_suffix);
550 ofstream out(out_path.c_str());
556 if (!ARDOUR::Profile->get_trx()) {
557 /* Copy plugin state files from template to new session */
558 std::string template_plugins = Glib::build_filename (session_template, X_("plugins"));
559 copy_recurse (template_plugins, plugins_dir ());
565 error << string_compose (_("Could not open %1 for writing session template"), out_path)
571 error << string_compose (_("Could not open session template %1 for reading"), in_path)
578 if (Profile->get_trx()) {
580 /* set initial start + end point : ARDOUR::Session::session_end_shift long.
581 Remember that this is a brand new session. Sessions
582 loaded from saved state will get this range from the saved state.
585 set_session_range_location (0, 0);
587 /* Initial loop location, from absolute zero, length 10 seconds */
589 Location* loc = new Location (*this, 0, 10.0 * _engine.sample_rate(), _("Loop"), Location::IsAutoLoop);
590 _locations->add (loc, true);
591 set_auto_loop_location (loc);
594 _state_of_the_state = Clean;
596 /* set up Master Out and Control Out if necessary */
601 ChanCount count(DataType::AUDIO, bus_profile->master_out_channels);
603 // Waves Tracks: always create master bus for Tracks
604 if (ARDOUR::Profile->get_trx() || bus_profile->master_out_channels) {
605 boost::shared_ptr<Route> r (new Route (*this, _("Master"), Route::MasterOut, DataType::AUDIO));
609 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
610 // boost_debug_shared_ptr_mark_interesting (r.get(), "Route");
613 Glib::Threads::Mutex::Lock lm (AudioEngine::instance()->process_lock ());
614 r->input()->ensure_io (count, false, this);
615 r->output()->ensure_io (count, false, this);
621 /* prohibit auto-connect to master, because there isn't one */
622 bus_profile->output_ac = AutoConnectOption (bus_profile->output_ac & ~AutoConnectMaster);
626 add_routes (rl, false, false, false);
629 // Waves Tracks: Skip this. Always use autoconnection for Tracks
630 if (!ARDOUR::Profile->get_trx()) {
632 /* this allows the user to override settings with an environment variable.
635 if (no_auto_connect()) {
636 bus_profile->input_ac = AutoConnectOption (0);
637 bus_profile->output_ac = AutoConnectOption (0);
640 Config->set_input_auto_connect (bus_profile->input_ac);
641 Config->set_output_auto_connect (bus_profile->output_ac);
645 if (Config->get_use_monitor_bus() && bus_profile) {
646 add_monitor_section ();
653 Session::maybe_write_autosave()
655 if (dirty() && record_status() != Recording) {
656 save_state("", true);
661 Session::remove_pending_capture_state ()
663 std::string pending_state_file_path(_session_dir->root_path());
665 pending_state_file_path = Glib::build_filename (pending_state_file_path, legalize_for_path (_current_snapshot_name) + pending_suffix);
667 if (!Glib::file_test (pending_state_file_path, Glib::FILE_TEST_EXISTS)) return;
669 if (g_remove (pending_state_file_path.c_str()) != 0) {
670 error << string_compose(_("Could not remove pending capture state at path \"%1\" (%2)"),
671 pending_state_file_path, g_strerror (errno)) << endmsg;
675 /** Rename a state file.
676 * @param old_name Old snapshot name.
677 * @param new_name New snapshot name.
680 Session::rename_state (string old_name, string new_name)
682 if (old_name == _current_snapshot_name || old_name == _name) {
683 /* refuse to rename the current snapshot or the "main" one */
687 const string old_xml_filename = legalize_for_path (old_name) + statefile_suffix;
688 const string new_xml_filename = legalize_for_path (new_name) + statefile_suffix;
690 const std::string old_xml_path(Glib::build_filename (_session_dir->root_path(), old_xml_filename));
691 const std::string new_xml_path(Glib::build_filename (_session_dir->root_path(), new_xml_filename));
693 if (::g_rename (old_xml_path.c_str(), new_xml_path.c_str()) != 0) {
694 error << string_compose(_("could not rename snapshot %1 to %2 (%3)"),
695 old_name, new_name, g_strerror(errno)) << endmsg;
699 /** Remove a state file.
700 * @param snapshot_name Snapshot name.
703 Session::remove_state (string snapshot_name)
705 if (!_writable || snapshot_name == _current_snapshot_name || snapshot_name == _name) {
706 // refuse to remove the current snapshot or the "main" one
710 std::string xml_path(_session_dir->root_path());
712 xml_path = Glib::build_filename (xml_path, legalize_for_path (snapshot_name) + statefile_suffix);
714 if (!create_backup_file (xml_path)) {
715 // don't remove it if a backup can't be made
716 // create_backup_file will log the error.
721 if (g_remove (xml_path.c_str()) != 0) {
722 error << string_compose(_("Could not remove session file at path \"%1\" (%2)"),
723 xml_path, g_strerror (errno)) << endmsg;
727 /** @param snapshot_name Name to save under, without .ardour / .pending prefix */
729 Session::save_state (string snapshot_name, bool pending, bool switch_to_snapshot, bool template_only)
732 std::string xml_path(_session_dir->root_path());
734 /* prevent concurrent saves from different threads */
736 Glib::Threads::Mutex::Lock lm (save_state_lock);
738 if (!_writable || (_state_of_the_state & CannotSave)) {
742 if (g_atomic_int_get(&_suspend_save)) {
746 _save_queued = false;
748 if (!_engine.connected ()) {
749 error << string_compose (_("the %1 audio engine is not connected and state saving would lose all I/O connections. Session not saved"),
755 /* tell sources we're saving first, in case they write out to a new file
756 * which should be saved with the state rather than the old one */
757 for (SourceMap::const_iterator i = sources.begin(); i != sources.end(); ++i) {
759 i->second->session_saved();
760 } catch (Evoral::SMF::FileError& e) {
761 error << string_compose ("Could not write to MIDI file %1; MIDI data not saved.", e.file_name ()) << endmsg;
765 SessionSaveUnderway (); /* EMIT SIGNAL */
768 tree.set_root (&get_template());
770 tree.set_root (&get_state());
773 if (snapshot_name.empty()) {
774 snapshot_name = _current_snapshot_name;
775 } else if (switch_to_snapshot) {
776 _current_snapshot_name = snapshot_name;
781 /* proper save: use statefile_suffix (.ardour in English) */
783 xml_path = Glib::build_filename (xml_path, legalize_for_path (snapshot_name) + statefile_suffix);
785 /* make a backup copy of the old file */
787 if (Glib::file_test (xml_path, Glib::FILE_TEST_EXISTS) && !create_backup_file (xml_path)) {
788 // create_backup_file will log the error
794 /* pending save: use pending_suffix (.pending in English) */
795 xml_path = Glib::build_filename (xml_path, legalize_for_path (snapshot_name) + pending_suffix);
798 std::string tmp_path(_session_dir->root_path());
799 tmp_path = Glib::build_filename (tmp_path, legalize_for_path (snapshot_name) + temp_suffix);
801 cerr << "actually writing state to " << tmp_path << endl;
803 if (!tree.write (tmp_path)) {
804 error << string_compose (_("state could not be saved to %1"), tmp_path) << endmsg;
805 if (g_remove (tmp_path.c_str()) != 0) {
806 error << string_compose(_("Could not remove temporary session file at path \"%1\" (%2)"),
807 tmp_path, g_strerror (errno)) << endmsg;
813 cerr << "renaming state to " << xml_path << endl;
815 if (::g_rename (tmp_path.c_str(), xml_path.c_str()) != 0) {
816 error << string_compose (_("could not rename temporary session file %1 to %2 (%3)"),
817 tmp_path, xml_path, g_strerror(errno)) << endmsg;
818 if (g_remove (tmp_path.c_str()) != 0) {
819 error << string_compose(_("Could not remove temporary session file at path \"%1\" (%2)"),
820 tmp_path, g_strerror (errno)) << endmsg;
828 save_history (snapshot_name);
830 bool was_dirty = dirty();
832 _state_of_the_state = StateOfTheState (_state_of_the_state & ~Dirty);
835 DirtyChanged (); /* EMIT SIGNAL */
838 StateSaved (snapshot_name); /* EMIT SIGNAL */
845 Session::restore_state (string snapshot_name)
847 if (load_state (snapshot_name) == 0) {
848 set_state (*state_tree->root(), Stateful::loading_state_version);
855 Session::load_state (string snapshot_name)
860 state_was_pending = false;
862 /* check for leftover pending state from a crashed capture attempt */
864 std::string xmlpath(_session_dir->root_path());
865 xmlpath = Glib::build_filename (xmlpath, legalize_for_path (snapshot_name) + pending_suffix);
867 if (Glib::file_test (xmlpath, Glib::FILE_TEST_EXISTS)) {
869 /* there is pending state from a crashed capture attempt */
871 boost::optional<int> r = AskAboutPendingState();
872 if (r.get_value_or (1)) {
873 state_was_pending = true;
877 if (!state_was_pending) {
878 xmlpath = Glib::build_filename (_session_dir->root_path(), snapshot_name);
881 if (!Glib::file_test (xmlpath, Glib::FILE_TEST_EXISTS)) {
882 xmlpath = Glib::build_filename (_session_dir->root_path(), legalize_for_path (snapshot_name) + statefile_suffix);
883 if (!Glib::file_test (xmlpath, Glib::FILE_TEST_EXISTS)) {
884 error << string_compose(_("%1: session file \"%2\" doesn't exist!"), _name, xmlpath) << endmsg;
889 state_tree = new XMLTree;
893 _writable = exists_and_writable (xmlpath) && exists_and_writable(Glib::path_get_dirname(xmlpath));
895 if (!state_tree->read (xmlpath)) {
896 error << string_compose(_("Could not understand session file %1"), xmlpath) << endmsg;
902 XMLNode& root (*state_tree->root());
904 if (root.name() != X_("Session")) {
905 error << string_compose (_("Session file %1 is not a session"), xmlpath) << endmsg;
911 const XMLProperty* prop;
913 if ((prop = root.property ("version")) == 0) {
914 /* no version implies very old version of Ardour */
915 Stateful::loading_state_version = 1000;
917 if (prop->value().find ('.') != string::npos) {
918 /* old school version format */
919 if (prop->value()[0] == '2') {
920 Stateful::loading_state_version = 2000;
922 Stateful::loading_state_version = 3000;
925 Stateful::loading_state_version = atoi (prop->value());
929 if (Stateful::loading_state_version < CURRENT_SESSION_FILE_VERSION && _writable) {
931 std::string backup_path(_session_dir->root_path());
932 std::string backup_filename = string_compose ("%1-%2%3", legalize_for_path (snapshot_name), Stateful::loading_state_version, statefile_suffix);
933 backup_path = Glib::build_filename (backup_path, backup_filename);
935 // only create a backup for a given statefile version once
937 if (!Glib::file_test (backup_path, Glib::FILE_TEST_EXISTS)) {
939 VersionMismatch (xmlpath, backup_path);
941 if (!copy_file (xmlpath, backup_path)) {;
951 Session::load_options (const XMLNode& node)
953 LocaleGuard lg (X_("C"));
954 config.set_variables (node);
959 Session::save_default_options ()
961 return config.save_state();
971 Session::get_template()
973 /* if we don't disable rec-enable, diskstreams
974 will believe they need to store their capture
975 sources in their state node.
978 disable_record (false);
984 Session::state (bool full_state)
986 XMLNode* node = new XMLNode("Session");
990 snprintf(buf, sizeof(buf), "%d", CURRENT_SESSION_FILE_VERSION);
991 node->add_property("version", buf);
993 /* store configuration settings */
997 node->add_property ("name", _name);
998 snprintf (buf, sizeof (buf), "%" PRId64, _nominal_frame_rate);
999 node->add_property ("sample-rate", buf);
1001 if (session_dirs.size() > 1) {
1005 vector<space_and_path>::iterator i = session_dirs.begin();
1006 vector<space_and_path>::iterator next;
1008 ++i; /* skip the first one */
1012 while (i != session_dirs.end()) {
1016 if (next != session_dirs.end()) {
1017 p += G_SEARCHPATH_SEPARATOR;
1026 child = node->add_child ("Path");
1027 child->add_content (p);
1031 /* save the ID counter */
1033 snprintf (buf, sizeof (buf), "%" PRIu64, ID::counter());
1034 node->add_property ("id-counter", buf);
1036 /* save the event ID counter */
1038 snprintf (buf, sizeof (buf), "%d", Evoral::event_id_counter());
1039 node->add_property ("event-counter", buf);
1041 /* various options */
1043 list<XMLNode*> midi_port_nodes = _midi_ports->get_midi_port_states();
1044 if (!midi_port_nodes.empty()) {
1045 XMLNode* midi_port_stuff = new XMLNode ("MIDIPorts");
1046 for (list<XMLNode*>::const_iterator n = midi_port_nodes.begin(); n != midi_port_nodes.end(); ++n) {
1047 midi_port_stuff->add_child_nocopy (**n);
1049 node->add_child_nocopy (*midi_port_stuff);
1052 node->add_child_nocopy (config.get_variables ());
1054 node->add_child_nocopy (ARDOUR::SessionMetadata::Metadata()->get_state());
1056 child = node->add_child ("Sources");
1059 Glib::Threads::Mutex::Lock sl (source_lock);
1061 for (SourceMap::iterator siter = sources.begin(); siter != sources.end(); ++siter) {
1063 /* Don't save information about non-file Sources, or
1064 * about non-destructive file sources that are empty
1065 * and unused by any regions.
1068 boost::shared_ptr<FileSource> fs;
1070 if ((fs = boost::dynamic_pointer_cast<FileSource> (siter->second)) != 0) {
1072 if (!fs->destructive()) {
1073 if (fs->empty() && !fs->used()) {
1078 child->add_child_nocopy (siter->second->get_state());
1083 child = node->add_child ("Regions");
1086 Glib::Threads::Mutex::Lock rl (region_lock);
1087 const RegionFactory::RegionMap& region_map (RegionFactory::all_regions());
1088 for (RegionFactory::RegionMap::const_iterator i = region_map.begin(); i != region_map.end(); ++i) {
1089 boost::shared_ptr<Region> r = i->second;
1090 /* only store regions not attached to playlists */
1091 if (r->playlist() == 0) {
1092 if (boost::dynamic_pointer_cast<AudioRegion>(r)) {
1093 child->add_child_nocopy ((boost::dynamic_pointer_cast<AudioRegion>(r))->get_basic_state ());
1095 child->add_child_nocopy (r->get_state ());
1100 RegionFactory::CompoundAssociations& cassocs (RegionFactory::compound_associations());
1102 if (!cassocs.empty()) {
1103 XMLNode* ca = node->add_child (X_("CompoundAssociations"));
1105 for (RegionFactory::CompoundAssociations::iterator i = cassocs.begin(); i != cassocs.end(); ++i) {
1107 XMLNode* can = new XMLNode (X_("CompoundAssociation"));
1108 i->first->id().print (buf, sizeof (buf));
1109 can->add_property (X_("copy"), buf);
1110 i->second->id().print (buf, sizeof (buf));
1111 can->add_property (X_("original"), buf);
1112 ca->add_child_nocopy (*can);
1122 node->add_child_nocopy (_locations->get_state());
1125 Locations loc (*this);
1126 // for a template, just create a new Locations, populate it
1127 // with the default start and end, and get the state for that.
1128 Location* range = new Location (*this, 0, 0, _("session"), Location::IsSessionRange);
1129 range->set (max_framepos, 0);
1131 XMLNode& locations_state = loc.get_state();
1133 if (ARDOUR::Profile->get_trx() && _locations) {
1134 // For tracks we need stored the Auto Loop Range and all MIDI markers.
1135 for (Locations::LocationList::const_iterator i = _locations->list ().begin (); i != _locations->list ().end (); ++i) {
1136 if ((*i)->is_mark () || (*i)->is_auto_loop ()) {
1137 locations_state.add_child_nocopy ((*i)->get_state ());
1141 node->add_child_nocopy (locations_state);
1144 child = node->add_child ("Bundles");
1146 boost::shared_ptr<BundleList> bundles = _bundles.reader ();
1147 for (BundleList::iterator i = bundles->begin(); i != bundles->end(); ++i) {
1148 boost::shared_ptr<UserBundle> b = boost::dynamic_pointer_cast<UserBundle> (*i);
1150 child->add_child_nocopy (b->get_state());
1155 child = node->add_child ("Routes");
1157 boost::shared_ptr<RouteList> r = routes.reader ();
1159 RoutePublicOrderSorter cmp;
1160 RouteList public_order (*r);
1161 public_order.sort (cmp);
1163 /* the sort should have put control outs first */
1166 assert (_monitor_out == public_order.front());
1169 for (RouteList::iterator i = public_order.begin(); i != public_order.end(); ++i) {
1170 if (!(*i)->is_auditioner()) {
1172 child->add_child_nocopy ((*i)->get_state());
1174 child->add_child_nocopy ((*i)->get_template());
1180 playlists->add_state (node, full_state);
1182 child = node->add_child ("RouteGroups");
1183 for (list<RouteGroup *>::iterator i = _route_groups.begin(); i != _route_groups.end(); ++i) {
1184 child->add_child_nocopy ((*i)->get_state());
1188 XMLNode* gain_child = node->add_child ("Click");
1189 gain_child->add_child_nocopy (_click_io->state (full_state));
1190 gain_child->add_child_nocopy (_click_gain->state (full_state));
1194 XMLNode* ltc_input_child = node->add_child ("LTC-In");
1195 ltc_input_child->add_child_nocopy (_ltc_input->state (full_state));
1199 XMLNode* ltc_output_child = node->add_child ("LTC-Out");
1200 ltc_output_child->add_child_nocopy (_ltc_output->state (full_state));
1203 node->add_child_nocopy (_speakers->get_state());
1204 node->add_child_nocopy (_tempo_map->get_state());
1205 node->add_child_nocopy (get_control_protocol_state());
1208 node->add_child_copy (*_extra_xml);
1215 Session::get_control_protocol_state ()
1217 ControlProtocolManager& cpm (ControlProtocolManager::instance());
1218 return cpm.get_state();
1222 Session::set_state (const XMLNode& node, int version)
1226 const XMLProperty* prop;
1229 _state_of_the_state = StateOfTheState (_state_of_the_state|CannotSave);
1231 if (node.name() != X_("Session")) {
1232 fatal << _("programming error: Session: incorrect XML node sent to set_state()") << endmsg;
1236 if ((prop = node.property ("name")) != 0) {
1237 _name = prop->value ();
1240 if ((prop = node.property (X_("sample-rate"))) != 0) {
1242 _nominal_frame_rate = atoi (prop->value());
1244 if (_nominal_frame_rate != _current_frame_rate) {
1245 boost::optional<int> r = AskAboutSampleRateMismatch (_nominal_frame_rate, _current_frame_rate);
1246 if (r.get_value_or (0)) {
1252 setup_raid_path(_session_dir->root_path());
1254 if ((prop = node.property (X_("id-counter"))) != 0) {
1256 sscanf (prop->value().c_str(), "%" PRIu64, &x);
1257 ID::init_counter (x);
1259 /* old sessions used a timebased counter, so fake
1260 the startup ID counter based on a standard
1265 ID::init_counter (now);
1268 if ((prop = node.property (X_("event-counter"))) != 0) {
1269 Evoral::init_event_id_counter (atoi (prop->value()));
1273 if ((child = find_named_node (node, "MIDIPorts")) != 0) {
1274 _midi_ports->set_midi_port_states (child->children());
1277 IO::disable_connecting ();
1279 Stateful::save_extra_xml (node);
1281 if (((child = find_named_node (node, "Options")) != 0)) { /* old style */
1282 load_options (*child);
1283 } else if ((child = find_named_node (node, "Config")) != 0) { /* new style */
1284 load_options (*child);
1286 error << _("Session: XML state has no options section") << endmsg;
1289 if (version >= 3000) {
1290 if ((child = find_named_node (node, "Metadata")) == 0) {
1291 warning << _("Session: XML state has no metadata section") << endmsg;
1292 } else if ( ARDOUR::SessionMetadata::Metadata()->set_state (*child, version) ) {
1297 if ((child = find_named_node (node, X_("Speakers"))) != 0) {
1298 _speakers->set_state (*child, version);
1301 if ((child = find_named_node (node, "Sources")) == 0) {
1302 error << _("Session: XML state has no sources section") << endmsg;
1304 } else if (load_sources (*child)) {
1308 if ((child = find_named_node (node, "TempoMap")) == 0) {
1309 error << _("Session: XML state has no Tempo Map section") << endmsg;
1311 } else if (_tempo_map->set_state (*child, version)) {
1315 if ((child = find_named_node (node, "Locations")) == 0) {
1316 error << _("Session: XML state has no locations section") << endmsg;
1318 } else if (_locations->set_state (*child, version)) {
1322 locations_changed ();
1324 if (_session_range_location) {
1325 AudioFileSource::set_header_position_offset (_session_range_location->start());
1328 if ((child = find_named_node (node, "Regions")) == 0) {
1329 error << _("Session: XML state has no Regions section") << endmsg;
1331 } else if (load_regions (*child)) {
1335 if ((child = find_named_node (node, "Playlists")) == 0) {
1336 error << _("Session: XML state has no playlists section") << endmsg;
1338 } else if (playlists->load (*this, *child)) {
1342 if ((child = find_named_node (node, "UnusedPlaylists")) == 0) {
1344 } else if (playlists->load_unused (*this, *child)) {
1348 if ((child = find_named_node (node, "CompoundAssociations")) != 0) {
1349 if (load_compounds (*child)) {
1354 if (version >= 3000) {
1355 if ((child = find_named_node (node, "Bundles")) == 0) {
1356 warning << _("Session: XML state has no bundles section") << endmsg;
1359 /* We can't load Bundles yet as they need to be able
1360 to convert from port names to Port objects, which can't happen until
1362 _bundle_xml_node = new XMLNode (*child);
1366 if (version < 3000) {
1367 if ((child = find_named_node (node, X_("DiskStreams"))) == 0) {
1368 error << _("Session: XML state has no diskstreams section") << endmsg;
1370 } else if (load_diskstreams_2X (*child, version)) {
1375 if ((child = find_named_node (node, "Routes")) == 0) {
1376 error << _("Session: XML state has no routes section") << endmsg;
1378 } else if (load_routes (*child, version)) {
1382 /* our diskstreams list is no longer needed as they are now all owned by their Route */
1383 _diskstreams_2X.clear ();
1385 if (version >= 3000) {
1387 if ((child = find_named_node (node, "RouteGroups")) == 0) {
1388 error << _("Session: XML state has no route groups section") << endmsg;
1390 } else if (load_route_groups (*child, version)) {
1394 } else if (version < 3000) {
1396 if ((child = find_named_node (node, "EditGroups")) == 0) {
1397 error << _("Session: XML state has no edit groups section") << endmsg;
1399 } else if (load_route_groups (*child, version)) {
1403 if ((child = find_named_node (node, "MixGroups")) == 0) {
1404 error << _("Session: XML state has no mix groups section") << endmsg;
1406 } else if (load_route_groups (*child, version)) {
1411 if ((child = find_named_node (node, "Click")) == 0) {
1412 warning << _("Session: XML state has no click section") << endmsg;
1413 } else if (_click_io) {
1414 setup_click_state (&node);
1417 if ((child = find_named_node (node, ControlProtocolManager::state_node_name)) != 0) {
1418 ControlProtocolManager::instance().set_state (*child, version);
1421 update_route_record_state ();
1423 /* here beginneth the second phase ... */
1425 StateReady (); /* EMIT SIGNAL */
1438 Session::load_routes (const XMLNode& node, int version)
1441 XMLNodeConstIterator niter;
1442 RouteList new_routes;
1444 nlist = node.children();
1448 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1450 boost::shared_ptr<Route> route;
1451 if (version < 3000) {
1452 route = XMLRouteFactory_2X (**niter, version);
1454 route = XMLRouteFactory (**niter, version);
1458 error << _("Session: cannot create Route from XML description.") << endmsg;
1462 BootMessage (string_compose (_("Loaded track/bus %1"), route->name()));
1464 new_routes.push_back (route);
1467 BootMessage (_("Tracks/busses loaded; Adding to Session"));
1469 add_routes (new_routes, false, false, false);
1471 BootMessage (_("Finished adding tracks/busses"));
1476 boost::shared_ptr<Route>
1477 Session::XMLRouteFactory (const XMLNode& node, int version)
1479 boost::shared_ptr<Route> ret;
1481 if (node.name() != "Route") {
1485 XMLNode* ds_child = find_named_node (node, X_("Diskstream"));
1487 DataType type = DataType::AUDIO;
1488 const XMLProperty* prop = node.property("default-type");
1491 type = DataType (prop->value());
1494 assert (type != DataType::NIL);
1498 boost::shared_ptr<Track> track;
1500 if (type == DataType::AUDIO) {
1501 track.reset (new AudioTrack (*this, X_("toBeResetFroXML")));
1503 track.reset (new MidiTrack (*this, X_("toBeResetFroXML")));
1506 if (track->init()) {
1510 if (track->set_state (node, version)) {
1514 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
1515 // boost_debug_shared_ptr_mark_interesting (track.get(), "Track");
1520 enum Route::Flag flags = Route::Flag(0);
1521 const XMLProperty* prop = node.property("flags");
1523 flags = Route::Flag (string_2_enum (prop->value(), flags));
1526 boost::shared_ptr<Route> r (new Route (*this, X_("toBeResetFroXML"), flags));
1528 if (r->init () == 0 && r->set_state (node, version) == 0) {
1529 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
1530 // boost_debug_shared_ptr_mark_interesting (r.get(), "Route");
1539 boost::shared_ptr<Route>
1540 Session::XMLRouteFactory_2X (const XMLNode& node, int version)
1542 boost::shared_ptr<Route> ret;
1544 if (node.name() != "Route") {
1548 XMLProperty const * ds_prop = node.property (X_("diskstream-id"));
1550 ds_prop = node.property (X_("diskstream"));
1553 DataType type = DataType::AUDIO;
1554 const XMLProperty* prop = node.property("default-type");
1557 type = DataType (prop->value());
1560 assert (type != DataType::NIL);
1564 list<boost::shared_ptr<Diskstream> >::iterator i = _diskstreams_2X.begin ();
1565 while (i != _diskstreams_2X.end() && (*i)->id() != ds_prop->value()) {
1569 if (i == _diskstreams_2X.end()) {
1570 error << _("Could not find diskstream for route") << endmsg;
1571 return boost::shared_ptr<Route> ();
1574 boost::shared_ptr<Track> track;
1576 if (type == DataType::AUDIO) {
1577 track.reset (new AudioTrack (*this, X_("toBeResetFroXML")));
1579 track.reset (new MidiTrack (*this, X_("toBeResetFroXML")));
1582 if (track->init()) {
1586 if (track->set_state (node, version)) {
1590 track->set_diskstream (*i);
1592 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
1593 // boost_debug_shared_ptr_mark_interesting (track.get(), "Track");
1598 enum Route::Flag flags = Route::Flag(0);
1599 const XMLProperty* prop = node.property("flags");
1601 flags = Route::Flag (string_2_enum (prop->value(), flags));
1604 boost::shared_ptr<Route> r (new Route (*this, X_("toBeResetFroXML"), flags));
1606 if (r->init () == 0 && r->set_state (node, version) == 0) {
1607 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
1608 // boost_debug_shared_ptr_mark_interesting (r.get(), "Route");
1618 Session::load_regions (const XMLNode& node)
1621 XMLNodeConstIterator niter;
1622 boost::shared_ptr<Region> region;
1624 nlist = node.children();
1628 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1629 if ((region = XMLRegionFactory (**niter, false)) == 0) {
1630 error << _("Session: cannot create Region from XML description.");
1631 const XMLProperty *name = (**niter).property("name");
1634 error << " " << string_compose (_("Can not load state for region '%1'"), name->value());
1645 Session::load_compounds (const XMLNode& node)
1647 XMLNodeList calist = node.children();
1648 XMLNodeConstIterator caiter;
1649 XMLProperty *caprop;
1651 for (caiter = calist.begin(); caiter != calist.end(); ++caiter) {
1652 XMLNode* ca = *caiter;
1656 if ((caprop = ca->property (X_("original"))) == 0) {
1659 orig_id = caprop->value();
1661 if ((caprop = ca->property (X_("copy"))) == 0) {
1664 copy_id = caprop->value();
1666 boost::shared_ptr<Region> orig = RegionFactory::region_by_id (orig_id);
1667 boost::shared_ptr<Region> copy = RegionFactory::region_by_id (copy_id);
1669 if (!orig || !copy) {
1670 warning << string_compose (_("Regions in compound description not found (ID's %1 and %2): ignored"),
1676 RegionFactory::add_compound_association (orig, copy);
1683 Session::load_nested_sources (const XMLNode& node)
1686 XMLNodeConstIterator niter;
1688 nlist = node.children();
1690 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1691 if ((*niter)->name() == "Source") {
1693 /* it may already exist, so don't recreate it unnecessarily
1696 XMLProperty* prop = (*niter)->property (X_("id"));
1698 error << _("Nested source has no ID info in session file! (ignored)") << endmsg;
1702 ID source_id (prop->value());
1704 if (!source_by_id (source_id)) {
1707 SourceFactory::create (*this, **niter, true);
1709 catch (failed_constructor& err) {
1710 error << string_compose (_("Cannot reconstruct nested source for region %1"), name()) << endmsg;
1717 boost::shared_ptr<Region>
1718 Session::XMLRegionFactory (const XMLNode& node, bool full)
1720 const XMLProperty* type = node.property("type");
1724 const XMLNodeList& nlist = node.children();
1726 for (XMLNodeConstIterator niter = nlist.begin(); niter != nlist.end(); ++niter) {
1727 XMLNode *child = (*niter);
1728 if (child->name() == "NestedSource") {
1729 load_nested_sources (*child);
1733 if (!type || type->value() == "audio") {
1734 return boost::shared_ptr<Region>(XMLAudioRegionFactory (node, full));
1735 } else if (type->value() == "midi") {
1736 return boost::shared_ptr<Region>(XMLMidiRegionFactory (node, full));
1739 } catch (failed_constructor& err) {
1740 return boost::shared_ptr<Region> ();
1743 return boost::shared_ptr<Region> ();
1746 boost::shared_ptr<AudioRegion>
1747 Session::XMLAudioRegionFactory (const XMLNode& node, bool /*full*/)
1749 const XMLProperty* prop;
1750 boost::shared_ptr<Source> source;
1751 boost::shared_ptr<AudioSource> as;
1753 SourceList master_sources;
1754 uint32_t nchans = 1;
1757 if (node.name() != X_("Region")) {
1758 return boost::shared_ptr<AudioRegion>();
1761 if ((prop = node.property (X_("channels"))) != 0) {
1762 nchans = atoi (prop->value().c_str());
1765 if ((prop = node.property ("name")) == 0) {
1766 cerr << "no name for this region\n";
1770 if ((prop = node.property (X_("source-0"))) == 0) {
1771 if ((prop = node.property ("source")) == 0) {
1772 error << _("Session: XMLNode describing a AudioRegion is incomplete (no source)") << endmsg;
1773 return boost::shared_ptr<AudioRegion>();
1777 PBD::ID s_id (prop->value());
1779 if ((source = source_by_id (s_id)) == 0) {
1780 error << string_compose(_("Session: XMLNode describing a AudioRegion references an unknown source id =%1"), s_id) << endmsg;
1781 return boost::shared_ptr<AudioRegion>();
1784 as = boost::dynamic_pointer_cast<AudioSource>(source);
1786 error << string_compose(_("Session: XMLNode describing a AudioRegion references a non-audio source id =%1"), s_id) << endmsg;
1787 return boost::shared_ptr<AudioRegion>();
1790 sources.push_back (as);
1792 /* pickup other channels */
1794 for (uint32_t n=1; n < nchans; ++n) {
1795 snprintf (buf, sizeof(buf), X_("source-%d"), n);
1796 if ((prop = node.property (buf)) != 0) {
1798 PBD::ID id2 (prop->value());
1800 if ((source = source_by_id (id2)) == 0) {
1801 error << string_compose(_("Session: XMLNode describing a AudioRegion references an unknown source id =%1"), id2) << endmsg;
1802 return boost::shared_ptr<AudioRegion>();
1805 as = boost::dynamic_pointer_cast<AudioSource>(source);
1807 error << string_compose(_("Session: XMLNode describing a AudioRegion references a non-audio source id =%1"), id2) << endmsg;
1808 return boost::shared_ptr<AudioRegion>();
1810 sources.push_back (as);
1814 for (uint32_t n = 0; n < nchans; ++n) {
1815 snprintf (buf, sizeof(buf), X_("master-source-%d"), n);
1816 if ((prop = node.property (buf)) != 0) {
1818 PBD::ID id2 (prop->value());
1820 if ((source = source_by_id (id2)) == 0) {
1821 error << string_compose(_("Session: XMLNode describing a AudioRegion references an unknown source id =%1"), id2) << endmsg;
1822 return boost::shared_ptr<AudioRegion>();
1825 as = boost::dynamic_pointer_cast<AudioSource>(source);
1827 error << string_compose(_("Session: XMLNode describing a AudioRegion references a non-audio source id =%1"), id2) << endmsg;
1828 return boost::shared_ptr<AudioRegion>();
1830 master_sources.push_back (as);
1835 boost::shared_ptr<AudioRegion> region (boost::dynamic_pointer_cast<AudioRegion> (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());
1848 if (!master_sources.empty()) {
1849 if (master_sources.size() != nchans) {
1850 error << _("Session: XMLNode describing an AudioRegion is missing some master sources; ignored") << endmsg;
1852 region->set_master_sources (master_sources);
1860 catch (failed_constructor& err) {
1861 return boost::shared_ptr<AudioRegion>();
1865 boost::shared_ptr<MidiRegion>
1866 Session::XMLMidiRegionFactory (const XMLNode& node, bool /*full*/)
1868 const XMLProperty* prop;
1869 boost::shared_ptr<Source> source;
1870 boost::shared_ptr<MidiSource> ms;
1873 if (node.name() != X_("Region")) {
1874 return boost::shared_ptr<MidiRegion>();
1877 if ((prop = node.property ("name")) == 0) {
1878 cerr << "no name for this region\n";
1882 if ((prop = node.property (X_("source-0"))) == 0) {
1883 if ((prop = node.property ("source")) == 0) {
1884 error << _("Session: XMLNode describing a MidiRegion is incomplete (no source)") << endmsg;
1885 return boost::shared_ptr<MidiRegion>();
1889 PBD::ID s_id (prop->value());
1891 if ((source = source_by_id (s_id)) == 0) {
1892 error << string_compose(_("Session: XMLNode describing a MidiRegion references an unknown source id =%1"), s_id) << endmsg;
1893 return boost::shared_ptr<MidiRegion>();
1896 ms = boost::dynamic_pointer_cast<MidiSource>(source);
1898 error << string_compose(_("Session: XMLNode describing a MidiRegion references a non-midi source id =%1"), s_id) << endmsg;
1899 return boost::shared_ptr<MidiRegion>();
1902 sources.push_back (ms);
1905 boost::shared_ptr<MidiRegion> region (boost::dynamic_pointer_cast<MidiRegion> (RegionFactory::create (sources, node)));
1906 /* a final detail: this is the one and only place that we know how long missing files are */
1908 if (region->whole_file()) {
1909 for (SourceList::iterator sx = sources.begin(); sx != sources.end(); ++sx) {
1910 boost::shared_ptr<SilentFileSource> sfp = boost::dynamic_pointer_cast<SilentFileSource> (*sx);
1912 sfp->set_length (region->length());
1920 catch (failed_constructor& err) {
1921 return boost::shared_ptr<MidiRegion>();
1926 Session::get_sources_as_xml ()
1929 XMLNode* node = new XMLNode (X_("Sources"));
1930 Glib::Threads::Mutex::Lock lm (source_lock);
1932 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ++i) {
1933 node->add_child_nocopy (i->second->get_state());
1940 Session::reset_write_sources (bool mark_write_complete, bool force)
1942 boost::shared_ptr<RouteList> rl = routes.reader();
1943 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
1944 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
1946 _state_of_the_state = StateOfTheState (_state_of_the_state|InCleanup);
1947 tr->reset_write_sources(mark_write_complete, force);
1948 _state_of_the_state = StateOfTheState (_state_of_the_state & ~InCleanup);
1954 Session::load_sources (const XMLNode& node)
1957 XMLNodeConstIterator niter;
1958 boost::shared_ptr<Source> source; /* don't need this but it stops some
1959 * versions of gcc complaining about
1960 * discarded return values.
1963 nlist = node.children();
1967 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1970 if ((source = XMLSourceFactory (**niter)) == 0) {
1971 error << _("Session: cannot create Source from XML description.") << endmsg;
1974 } catch (MissingSource& err) {
1978 if (err.type == DataType::MIDI && Glib::path_is_absolute (err.path)) {
1979 error << string_compose (_("A external MIDI file is missing. %1 cannot currently recover from missing external MIDI files"),
1980 PROGRAM_NAME) << endmsg;
1984 if (!no_questions_about_missing_files) {
1985 user_choice = MissingFile (this, err.path, err.type).get_value_or (-1);
1990 switch (user_choice) {
1992 /* user added a new search location, so try again */
1997 /* user asked to quit the entire session load
2002 no_questions_about_missing_files = true;
2006 no_questions_about_missing_files = true;
2013 case DataType::AUDIO:
2014 source = SourceFactory::createSilent (*this, **niter, max_framecnt, _current_frame_rate);
2017 case DataType::MIDI:
2018 /* The MIDI file is actually missing so
2019 * just create a new one in the same
2020 * location. Do not announce its
2024 if (!Glib::path_is_absolute (err.path)) {
2025 fullpath = Glib::build_filename (source_search_path (DataType::MIDI).front(), err.path);
2027 /* this should be an unrecoverable error: we would be creating a MIDI file outside
2032 /* Note that we do not announce the source just yet - we need to reset its ID before we do that */
2033 source = SourceFactory::createWritable (DataType::MIDI, *this, fullpath, false, _current_frame_rate, false, false);
2034 /* reset ID to match the missing one */
2035 source->set_id (**niter);
2036 /* Now we can announce it */
2037 SourceFactory::SourceCreated (source);
2048 boost::shared_ptr<Source>
2049 Session::XMLSourceFactory (const XMLNode& node)
2051 if (node.name() != "Source") {
2052 return boost::shared_ptr<Source>();
2056 /* note: do peak building in another thread when loading session state */
2057 return SourceFactory::create (*this, node, true);
2060 catch (failed_constructor& err) {
2061 error << string_compose (_("Found a sound file that cannot be used by %1. Talk to the programmers."), PROGRAM_NAME) << endmsg;
2062 return boost::shared_ptr<Source>();
2067 Session::save_template (string template_name)
2069 if ((_state_of_the_state & CannotSave) || template_name.empty ()) {
2073 bool absolute_path = Glib::path_is_absolute (template_name);
2075 /* directory to put the template in */
2076 std::string template_dir_path;
2078 if (!absolute_path) {
2079 std::string user_template_dir(user_template_directory());
2081 if (g_mkdir_with_parents (user_template_dir.c_str(), 0755) != 0) {
2082 error << string_compose(_("Could not create templates directory \"%1\" (%2)"),
2083 user_template_dir, g_strerror (errno)) << endmsg;
2087 template_dir_path = Glib::build_filename (user_template_dir, template_name);
2089 template_dir_path = template_name;
2092 if (!ARDOUR::Profile->get_trx()) {
2093 if (Glib::file_test (template_dir_path, Glib::FILE_TEST_EXISTS)) {
2094 warning << string_compose(_("Template \"%1\" already exists - new version not created"),
2095 template_dir_path) << endmsg;
2099 if (g_mkdir_with_parents (template_dir_path.c_str(), 0755) != 0) {
2100 error << string_compose(_("Could not create directory for Session template\"%1\" (%2)"),
2101 template_dir_path, g_strerror (errno)) << endmsg;
2107 std::string template_file_path;
2109 if (ARDOUR::Profile->get_trx()) {
2110 template_file_path = template_name;
2112 if (absolute_path) {
2113 template_file_path = Glib::build_filename (template_dir_path, Glib::path_get_basename (template_dir_path) + template_suffix);
2115 template_file_path = Glib::build_filename (template_dir_path, template_name + template_suffix);
2119 SessionSaveUnderway (); /* EMIT SIGNAL */
2123 tree.set_root (&get_template());
2124 if (!tree.write (template_file_path)) {
2125 error << _("template not saved") << endmsg;
2129 if (!ARDOUR::Profile->get_trx()) {
2130 /* copy plugin state directory */
2132 std::string template_plugin_state_path (Glib::build_filename (template_dir_path, X_("plugins")));
2134 if (g_mkdir_with_parents (template_plugin_state_path.c_str(), 0755) != 0) {
2135 error << string_compose(_("Could not create directory for Session template plugin state\"%1\" (%2)"),
2136 template_plugin_state_path, g_strerror (errno)) << endmsg;
2139 copy_files (plugins_dir(), template_plugin_state_path);
2142 store_recent_templates (template_file_path);
2148 Session::refresh_disk_space ()
2150 #if __APPLE__ || (HAVE_SYS_VFS_H && HAVE_SYS_STATVFS_H)
2152 Glib::Threads::Mutex::Lock lm (space_lock);
2154 /* get freespace on every FS that is part of the session path */
2156 _total_free_4k_blocks = 0;
2157 _total_free_4k_blocks_uncertain = false;
2159 for (vector<space_and_path>::iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
2161 struct statfs statfsbuf;
2162 statfs (i->path.c_str(), &statfsbuf);
2164 double const scale = statfsbuf.f_bsize / 4096.0;
2166 /* See if this filesystem is read-only */
2167 struct statvfs statvfsbuf;
2168 statvfs (i->path.c_str(), &statvfsbuf);
2170 /* f_bavail can be 0 if it is undefined for whatever
2171 filesystem we are looking at; Samba shares mounted
2172 via GVFS are an example of this.
2174 if (statfsbuf.f_bavail == 0) {
2175 /* block count unknown */
2177 i->blocks_unknown = true;
2178 } else if (statvfsbuf.f_flag & ST_RDONLY) {
2179 /* read-only filesystem */
2181 i->blocks_unknown = false;
2183 /* read/write filesystem with known space */
2184 i->blocks = (uint32_t) floor (statfsbuf.f_bavail * scale);
2185 i->blocks_unknown = false;
2188 _total_free_4k_blocks += i->blocks;
2189 if (i->blocks_unknown) {
2190 _total_free_4k_blocks_uncertain = true;
2193 #elif defined PLATFORM_WINDOWS
2194 vector<string> scanned_volumes;
2195 vector<string>::iterator j;
2196 vector<space_and_path>::iterator i;
2197 DWORD nSectorsPerCluster, nBytesPerSector,
2198 nFreeClusters, nTotalClusters;
2202 _total_free_4k_blocks = 0;
2204 for (i = session_dirs.begin(); i != session_dirs.end(); i++) {
2205 strncpy (disk_drive, (*i).path.c_str(), 3);
2209 volume_found = false;
2210 if (0 != (GetDiskFreeSpace(disk_drive, &nSectorsPerCluster, &nBytesPerSector, &nFreeClusters, &nTotalClusters)))
2212 int64_t nBytesPerCluster = nBytesPerSector * nSectorsPerCluster;
2213 int64_t nFreeBytes = nBytesPerCluster * (int64_t)nFreeClusters;
2214 i->blocks = (uint32_t)(nFreeBytes / 4096);
2216 for (j = scanned_volumes.begin(); j != scanned_volumes.end(); j++) {
2217 if (0 == j->compare(disk_drive)) {
2218 volume_found = true;
2223 if (!volume_found) {
2224 scanned_volumes.push_back(disk_drive);
2225 _total_free_4k_blocks += i->blocks;
2230 if (0 == _total_free_4k_blocks) {
2231 strncpy (disk_drive, path().c_str(), 3);
2234 if (0 != (GetDiskFreeSpace(disk_drive, &nSectorsPerCluster, &nBytesPerSector, &nFreeClusters, &nTotalClusters)))
2236 int64_t nBytesPerCluster = nBytesPerSector * nSectorsPerCluster;
2237 int64_t nFreeBytes = nBytesPerCluster * (int64_t)nFreeClusters;
2238 _total_free_4k_blocks = (uint32_t)(nFreeBytes / 4096);
2245 Session::get_best_session_directory_for_new_audio ()
2247 vector<space_and_path>::iterator i;
2248 string result = _session_dir->root_path();
2250 /* handle common case without system calls */
2252 if (session_dirs.size() == 1) {
2256 /* OK, here's the algorithm we're following here:
2258 We want to select which directory to use for
2259 the next file source to be created. Ideally,
2260 we'd like to use a round-robin process so as to
2261 get maximum performance benefits from splitting
2262 the files across multiple disks.
2264 However, in situations without much diskspace, an
2265 RR approach may end up filling up a filesystem
2266 with new files while others still have space.
2267 Its therefore important to pay some attention to
2268 the freespace in the filesystem holding each
2269 directory as well. However, if we did that by
2270 itself, we'd keep creating new files in the file
2271 system with the most space until it was as full
2272 as all others, thus negating any performance
2273 benefits of this RAID-1 like approach.
2275 So, we use a user-configurable space threshold. If
2276 there are at least 2 filesystems with more than this
2277 much space available, we use RR selection between them.
2278 If not, then we pick the filesystem with the most space.
2280 This gets a good balance between the two
2284 refresh_disk_space ();
2286 int free_enough = 0;
2288 for (i = session_dirs.begin(); i != session_dirs.end(); ++i) {
2289 if ((*i).blocks * 4096 >= Config->get_disk_choice_space_threshold()) {
2294 if (free_enough >= 2) {
2295 /* use RR selection process, ensuring that the one
2299 i = last_rr_session_dir;
2302 if (++i == session_dirs.end()) {
2303 i = session_dirs.begin();
2306 if ((*i).blocks * 4096 >= Config->get_disk_choice_space_threshold()) {
2307 SessionDirectory sdir(i->path);
2308 if (sdir.create ()) {
2310 last_rr_session_dir = i;
2315 } while (i != last_rr_session_dir);
2319 /* pick FS with the most freespace (and that
2320 seems to actually work ...)
2323 vector<space_and_path> sorted;
2324 space_and_path_ascending_cmp cmp;
2326 sorted = session_dirs;
2327 sort (sorted.begin(), sorted.end(), cmp);
2329 for (i = sorted.begin(); i != sorted.end(); ++i) {
2330 SessionDirectory sdir(i->path);
2331 if (sdir.create ()) {
2333 last_rr_session_dir = i;
2343 Session::automation_dir () const
2345 return Glib::build_filename (_path, automation_dir_name);
2349 Session::analysis_dir () const
2351 return Glib::build_filename (_path, analysis_dir_name);
2355 Session::plugins_dir () const
2357 return Glib::build_filename (_path, plugins_dir_name);
2361 Session::externals_dir () const
2363 return Glib::build_filename (_path, externals_dir_name);
2367 Session::load_bundles (XMLNode const & node)
2369 XMLNodeList nlist = node.children();
2370 XMLNodeConstIterator niter;
2374 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2375 if ((*niter)->name() == "InputBundle") {
2376 add_bundle (boost::shared_ptr<UserBundle> (new UserBundle (**niter, true)));
2377 } else if ((*niter)->name() == "OutputBundle") {
2378 add_bundle (boost::shared_ptr<UserBundle> (new UserBundle (**niter, false)));
2380 error << string_compose(_("Unknown node \"%1\" found in Bundles list from session file"), (*niter)->name()) << endmsg;
2389 Session::load_route_groups (const XMLNode& node, int version)
2391 XMLNodeList nlist = node.children();
2392 XMLNodeConstIterator niter;
2396 if (version >= 3000) {
2398 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2399 if ((*niter)->name() == "RouteGroup") {
2400 RouteGroup* rg = new RouteGroup (*this, "");
2401 add_route_group (rg);
2402 rg->set_state (**niter, version);
2406 } else if (version < 3000) {
2408 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2409 if ((*niter)->name() == "EditGroup" || (*niter)->name() == "MixGroup") {
2410 RouteGroup* rg = new RouteGroup (*this, "");
2411 add_route_group (rg);
2412 rg->set_state (**niter, version);
2421 state_file_filter (const string &str, void* /*arg*/)
2423 return (str.length() > strlen(statefile_suffix) &&
2424 str.find (statefile_suffix) == (str.length() - strlen (statefile_suffix)));
2428 remove_end(string state)
2430 string statename(state);
2432 string::size_type start,end;
2433 if ((start = statename.find_last_of (G_DIR_SEPARATOR)) != string::npos) {
2434 statename = statename.substr (start+1);
2437 if ((end = statename.rfind(statefile_suffix)) == string::npos) {
2438 end = statename.length();
2441 return string(statename.substr (0, end));
2445 Session::possible_states (string path)
2447 vector<string> states;
2448 find_files_matching_filter (states, path, state_file_filter, 0, false, false);
2450 transform(states.begin(), states.end(), states.begin(), remove_end);
2452 sort (states.begin(), states.end());
2458 Session::possible_states () const
2460 return possible_states(_path);
2464 Session::add_route_group (RouteGroup* g)
2466 _route_groups.push_back (g);
2467 route_group_added (g); /* EMIT SIGNAL */
2469 g->RouteAdded.connect_same_thread (*this, boost::bind (&Session::route_added_to_route_group, this, _1, _2));
2470 g->RouteRemoved.connect_same_thread (*this, boost::bind (&Session::route_removed_from_route_group, this, _1, _2));
2471 g->PropertyChanged.connect_same_thread (*this, boost::bind (&Session::route_group_property_changed, this, g));
2477 Session::remove_route_group (RouteGroup& rg)
2479 list<RouteGroup*>::iterator i;
2481 if ((i = find (_route_groups.begin(), _route_groups.end(), &rg)) != _route_groups.end()) {
2482 _route_groups.erase (i);
2485 route_group_removed (); /* EMIT SIGNAL */
2489 /** Set a new order for our route groups, without adding or removing any.
2490 * @param groups Route group list in the new order.
2493 Session::reorder_route_groups (list<RouteGroup*> groups)
2495 _route_groups = groups;
2497 route_groups_reordered (); /* EMIT SIGNAL */
2503 Session::route_group_by_name (string name)
2505 list<RouteGroup *>::iterator i;
2507 for (i = _route_groups.begin(); i != _route_groups.end(); ++i) {
2508 if ((*i)->name() == name) {
2516 Session::all_route_group() const
2518 return *_all_route_group;
2522 Session::add_commands (vector<Command*> const & cmds)
2524 for (vector<Command*>::const_iterator i = cmds.begin(); i != cmds.end(); ++i) {
2530 Session::begin_reversible_command (const string& name)
2532 begin_reversible_command (g_quark_from_string (name.c_str ()));
2535 /** Begin a reversible command using a GQuark to identify it.
2536 * begin_reversible_command() and commit_reversible_command() calls may be nested,
2537 * but there must be as many begin...()s as there are commit...()s.
2540 Session::begin_reversible_command (GQuark q)
2542 /* If nested begin/commit pairs are used, we create just one UndoTransaction
2543 to hold all the commands that are committed. This keeps the order of
2544 commands correct in the history.
2547 if (_current_trans == 0) {
2548 /* start a new transaction */
2549 assert (_current_trans_quarks.empty ());
2550 _current_trans = new UndoTransaction();
2551 _current_trans->set_name (g_quark_to_string (q));
2554 _current_trans_quarks.push_front (q);
2558 Session::abort_reversible_command ()
2560 if (_current_trans != 0) {
2561 _current_trans->clear();
2562 delete _current_trans;
2564 _current_trans_quarks.clear();
2569 Session::commit_reversible_command (Command *cmd)
2571 assert (_current_trans);
2572 assert (!_current_trans_quarks.empty ());
2577 _current_trans->add_command (cmd);
2580 _current_trans_quarks.pop_front ();
2582 if (!_current_trans_quarks.empty ()) {
2583 /* the transaction we're committing is not the top-level one */
2587 if (_current_trans->empty()) {
2588 /* no commands were added to the transaction, so just get rid of it */
2589 delete _current_trans;
2594 gettimeofday (&now, 0);
2595 _current_trans->set_timestamp (now);
2597 _history.add (_current_trans);
2602 accept_all_audio_files (const string& path, void* /*arg*/)
2604 if (!Glib::file_test (path, Glib::FILE_TEST_IS_REGULAR)) {
2608 if (!AudioFileSource::safe_audio_file_extension (path)) {
2616 accept_all_midi_files (const string& path, void* /*arg*/)
2618 if (!Glib::file_test (path, Glib::FILE_TEST_IS_REGULAR)) {
2622 return ((path.length() > 4 && path.find (".mid") != (path.length() - 4)) ||
2623 (path.length() > 4 && path.find (".smf") != (path.length() - 4)) ||
2624 (path.length() > 5 && path.find (".midi") != (path.length() - 5)));
2628 accept_all_state_files (const string& path, void* /*arg*/)
2630 if (!Glib::file_test (path, Glib::FILE_TEST_IS_REGULAR)) {
2634 std::string const statefile_ext (statefile_suffix);
2635 if (path.length() >= statefile_ext.length()) {
2636 return (0 == path.compare (path.length() - statefile_ext.length(), statefile_ext.length(), statefile_ext));
2643 Session::find_all_sources (string path, set<string>& result)
2648 if (!tree.read (path)) {
2652 if ((node = find_named_node (*tree.root(), "Sources")) == 0) {
2657 XMLNodeConstIterator niter;
2659 nlist = node->children();
2663 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2667 if ((prop = (*niter)->property (X_("type"))) == 0) {
2671 DataType type (prop->value());
2673 if ((prop = (*niter)->property (X_("name"))) == 0) {
2677 if (Glib::path_is_absolute (prop->value())) {
2678 /* external file, ignore */
2686 if (FileSource::find (*this, type, prop->value(), true, is_new, chan, found_path)) {
2687 result.insert (found_path);
2695 Session::find_all_sources_across_snapshots (set<string>& result, bool exclude_this_snapshot)
2697 vector<string> state_files;
2699 string this_snapshot_path;
2705 if (ripped[ripped.length()-1] == G_DIR_SEPARATOR) {
2706 ripped = ripped.substr (0, ripped.length() - 1);
2709 find_files_matching_filter (state_files, ripped, accept_all_state_files, (void *) 0, true, true);
2711 if (state_files.empty()) {
2716 this_snapshot_path = _path;
2717 this_snapshot_path += legalize_for_path (_current_snapshot_name);
2718 this_snapshot_path += statefile_suffix;
2720 for (vector<string>::iterator i = state_files.begin(); i != state_files.end(); ++i) {
2722 if (exclude_this_snapshot && *i == this_snapshot_path) {
2726 if (find_all_sources (*i, result) < 0) {
2734 struct RegionCounter {
2735 typedef std::map<PBD::ID,boost::shared_ptr<AudioSource> > AudioSourceList;
2736 AudioSourceList::iterator iter;
2737 boost::shared_ptr<Region> region;
2740 RegionCounter() : count (0) {}
2744 Session::ask_about_playlist_deletion (boost::shared_ptr<Playlist> p)
2746 boost::optional<int> r = AskAboutPlaylistDeletion (p);
2747 return r.get_value_or (1);
2751 Session::cleanup_regions ()
2753 bool removed = false;
2754 const RegionFactory::RegionMap& regions (RegionFactory::regions());
2756 for (RegionFactory::RegionMap::const_iterator i = regions.begin(); i != regions.end(); ++i) {
2758 uint32_t used = playlists->region_use_count (i->second);
2760 if (used == 0 && !i->second->automatic ()) {
2762 RegionFactory::map_remove (i->second);
2767 // re-check to remove parent references of compound regions
2768 for (RegionFactory::RegionMap::const_iterator i = regions.begin(); i != regions.end(); ++i) {
2769 if (!(i->second->whole_file() && i->second->max_source_level() > 0)) {
2772 assert(boost::dynamic_pointer_cast<PlaylistSource>(i->second->source (0)) != 0);
2773 if (0 == playlists->region_use_count (i->second)) {
2774 RegionFactory::map_remove (i->second);
2779 /* dump the history list */
2786 Session::cleanup_sources (CleanupReport& rep)
2788 // FIXME: needs adaptation to midi
2790 vector<boost::shared_ptr<Source> > dead_sources;
2793 vector<string> candidates;
2794 vector<string> unused;
2795 set<string> all_sources;
2804 _state_of_the_state = (StateOfTheState) (_state_of_the_state | InCleanup);
2806 /* consider deleting all unused playlists */
2808 if (playlists->maybe_delete_unused (boost::bind (Session::ask_about_playlist_deletion, _1))) {
2813 /* sync the "all regions" property of each playlist with its current state
2816 playlists->sync_all_regions_with_regions ();
2818 /* find all un-used sources */
2823 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ) {
2825 SourceMap::iterator tmp;
2830 /* do not bother with files that are zero size, otherwise we remove the current "nascent"
2834 if (!i->second->used() && (i->second->length(i->second->timeline_position() > 0))) {
2835 dead_sources.push_back (i->second);
2836 i->second->drop_references ();
2842 /* build a list of all the possible audio directories for the session */
2844 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
2845 SessionDirectory sdir ((*i).path);
2846 asp += sdir.sound_path();
2848 audio_path += asp.to_string();
2851 /* build a list of all the possible midi directories for the session */
2853 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
2854 SessionDirectory sdir ((*i).path);
2855 msp += sdir.midi_path();
2857 midi_path += msp.to_string();
2859 find_files_matching_filter (candidates, audio_path, accept_all_audio_files, (void *) 0, true, true);
2860 find_files_matching_filter (candidates, midi_path, accept_all_midi_files, (void *) 0, true, true);
2862 /* find all sources, but don't use this snapshot because the
2863 state file on disk still references sources we may have already
2867 find_all_sources_across_snapshots (all_sources, true);
2869 /* add our current source list
2872 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ) {
2873 boost::shared_ptr<FileSource> fs;
2874 SourceMap::iterator tmp = i;
2877 if ((fs = boost::dynamic_pointer_cast<FileSource> (i->second)) != 0) {
2879 if (!fs->is_stub()) {
2881 if (playlists->source_use_count (fs) != 0) {
2882 all_sources.insert (fs->path());
2885 /* we might not remove this source from disk, because it may be used
2886 by other snapshots, but its not being used in this version
2887 so lets get rid of it now, along with any representative regions
2891 RegionFactory::remove_regions_using_source (i->second);
2893 // also remove source from all_sources
2895 for (set<string>::iterator j = all_sources.begin(); j != all_sources.end(); ++j) {
2896 spath = Glib::path_get_basename (*j);
2897 if (spath == i->second->name()) {
2898 all_sources.erase (j);
2911 for (vector<string>::iterator x = candidates.begin(); x != candidates.end(); ++x) {
2916 for (set<string>::iterator i = all_sources.begin(); i != all_sources.end(); ++i) {
2918 tmppath1 = canonical_path (spath);
2919 tmppath2 = canonical_path ((*i));
2921 if (tmppath1 == tmppath2) {
2928 unused.push_back (spath);
2932 /* now try to move all unused files into the "dead" directory(ies) */
2934 for (vector<string>::iterator x = unused.begin(); x != unused.end(); ++x) {
2935 struct stat statbuf;
2939 /* don't move the file across filesystems, just
2940 stick it in the `dead_dir_name' directory
2941 on whichever filesystem it was already on.
2944 if ((*x).find ("/sounds/") != string::npos) {
2946 /* old school, go up 1 level */
2948 newpath = Glib::path_get_dirname (*x); // "sounds"
2949 newpath = Glib::path_get_dirname (newpath); // "session-name"
2953 /* new school, go up 4 levels */
2955 newpath = Glib::path_get_dirname (*x); // "audiofiles" or "midifiles"
2956 newpath = Glib::path_get_dirname (newpath); // "session-name"
2957 newpath = Glib::path_get_dirname (newpath); // "interchange"
2958 newpath = Glib::path_get_dirname (newpath); // "session-dir"
2961 newpath = Glib::build_filename (newpath, dead_dir_name);
2963 if (g_mkdir_with_parents (newpath.c_str(), 0755) < 0) {
2964 error << string_compose(_("Session: cannot create dead file folder \"%1\" (%2)"), newpath, strerror (errno)) << endmsg;
2968 newpath = Glib::build_filename (newpath, Glib::path_get_basename ((*x)));
2970 if (Glib::file_test (newpath, Glib::FILE_TEST_EXISTS)) {
2972 /* the new path already exists, try versioning */
2974 char buf[PATH_MAX+1];
2978 snprintf (buf, sizeof (buf), "%s.%d", newpath.c_str(), version);
2981 while (Glib::file_test (newpath_v.c_str(), Glib::FILE_TEST_EXISTS) && version < 999) {
2982 snprintf (buf, sizeof (buf), "%s.%d", newpath.c_str(), ++version);
2986 if (version == 999) {
2987 error << string_compose (_("there are already 1000 files with names like %1; versioning discontinued"),
2991 newpath = newpath_v;
2996 /* it doesn't exist, or we can't read it or something */
3000 stat ((*x).c_str(), &statbuf);
3002 if (::rename ((*x).c_str(), newpath.c_str()) != 0) {
3003 error << string_compose (_("cannot rename unused file source from %1 to %2 (%3)"),
3004 (*x), newpath, strerror (errno))
3009 /* see if there an easy to find peakfile for this file, and remove it.
3012 string base = basename_nosuffix (*x);
3013 base += "%A"; /* this is what we add for the channel suffix of all native files,
3014 or for the first channel of embedded files. it will miss
3015 some peakfiles for other channels
3017 string peakpath = peak_path (base);
3019 if (Glib::file_test (peakpath.c_str(), Glib::FILE_TEST_EXISTS)) {
3020 if (::g_unlink (peakpath.c_str()) != 0) {
3021 error << string_compose (_("cannot remove peakfile %1 for %2 (%3)"),
3022 peakpath, _path, strerror (errno))
3024 /* try to back out */
3025 ::rename (newpath.c_str(), _path.c_str());
3030 rep.paths.push_back (*x);
3031 rep.space += statbuf.st_size;
3034 /* dump the history list */
3038 /* save state so we don't end up a session file
3039 referring to non-existent sources.
3046 _state_of_the_state = (StateOfTheState) (_state_of_the_state & ~InCleanup);
3052 Session::cleanup_trash_sources (CleanupReport& rep)
3054 // FIXME: needs adaptation for MIDI
3056 vector<space_and_path>::iterator i;
3062 for (i = session_dirs.begin(); i != session_dirs.end(); ++i) {
3064 dead_dir = Glib::build_filename ((*i).path, dead_dir_name);
3066 clear_directory (dead_dir, &rep.space, &rep.paths);
3073 Session::set_dirty ()
3075 /* never mark session dirty during loading */
3077 if (_state_of_the_state & Loading) {
3081 bool was_dirty = dirty();
3083 _state_of_the_state = StateOfTheState (_state_of_the_state | Dirty);
3087 DirtyChanged(); /* EMIT SIGNAL */
3093 Session::set_clean ()
3095 bool was_dirty = dirty();
3097 _state_of_the_state = Clean;
3101 DirtyChanged(); /* EMIT SIGNAL */
3106 Session::set_deletion_in_progress ()
3108 _state_of_the_state = StateOfTheState (_state_of_the_state | Deletion);
3112 Session::clear_deletion_in_progress ()
3114 _state_of_the_state = StateOfTheState (_state_of_the_state & (~Deletion));
3118 Session::add_controllable (boost::shared_ptr<Controllable> c)
3120 /* this adds a controllable to the list managed by the Session.
3121 this is a subset of those managed by the Controllable class
3122 itself, and represents the only ones whose state will be saved
3123 as part of the session.
3126 Glib::Threads::Mutex::Lock lm (controllables_lock);
3127 controllables.insert (c);
3130 struct null_deleter { void operator()(void const *) const {} };
3133 Session::remove_controllable (Controllable* c)
3135 if (_state_of_the_state & Deletion) {
3139 Glib::Threads::Mutex::Lock lm (controllables_lock);
3141 Controllables::iterator x = controllables.find (boost::shared_ptr<Controllable>(c, null_deleter()));
3143 if (x != controllables.end()) {
3144 controllables.erase (x);
3148 boost::shared_ptr<Controllable>
3149 Session::controllable_by_id (const PBD::ID& id)
3151 Glib::Threads::Mutex::Lock lm (controllables_lock);
3153 for (Controllables::iterator i = controllables.begin(); i != controllables.end(); ++i) {
3154 if ((*i)->id() == id) {
3159 return boost::shared_ptr<Controllable>();
3162 boost::shared_ptr<Controllable>
3163 Session::controllable_by_descriptor (const ControllableDescriptor& desc)
3165 boost::shared_ptr<Controllable> c;
3166 boost::shared_ptr<Route> r;
3168 switch (desc.top_level_type()) {
3169 case ControllableDescriptor::NamedRoute:
3171 std::string str = desc.top_level_name();
3172 if (str == "Master" || str == "master") {
3174 } else if (str == "control" || str == "listen") {
3177 r = route_by_name (desc.top_level_name());
3182 case ControllableDescriptor::RemoteControlID:
3183 r = route_by_remote_id (desc.rid());
3191 switch (desc.subtype()) {
3192 case ControllableDescriptor::Gain:
3193 c = r->gain_control ();
3196 case ControllableDescriptor::Trim:
3197 c = r->trim()->gain_control ();
3200 case ControllableDescriptor::Solo:
3201 c = r->solo_control();
3204 case ControllableDescriptor::Mute:
3205 c = r->mute_control();
3208 case ControllableDescriptor::Recenable:
3210 boost::shared_ptr<Track> t = boost::dynamic_pointer_cast<Track>(r);
3213 c = t->rec_enable_control ();
3218 case ControllableDescriptor::PanDirection:
3220 c = r->pannable()->pan_azimuth_control;
3224 case ControllableDescriptor::PanWidth:
3226 c = r->pannable()->pan_width_control;
3230 case ControllableDescriptor::PanElevation:
3232 c = r->pannable()->pan_elevation_control;
3236 case ControllableDescriptor::Balance:
3237 /* XXX simple pan control */
3240 case ControllableDescriptor::PluginParameter:
3242 uint32_t plugin = desc.target (0);
3243 uint32_t parameter_index = desc.target (1);
3245 /* revert to zero based counting */
3251 if (parameter_index > 0) {
3255 boost::shared_ptr<Processor> p = r->nth_plugin (plugin);
3258 c = boost::dynamic_pointer_cast<ARDOUR::AutomationControl>(
3259 p->control(Evoral::Parameter(PluginAutomation, 0, parameter_index)));
3264 case ControllableDescriptor::SendGain:
3266 uint32_t send = desc.target (0);
3268 /* revert to zero-based counting */
3274 boost::shared_ptr<Processor> p = r->nth_send (send);
3277 boost::shared_ptr<Send> s = boost::dynamic_pointer_cast<Send>(p);
3278 boost::shared_ptr<Amp> a = s->amp();
3281 c = s->amp()->gain_control();
3288 /* relax and return a null pointer */
3296 Session::add_instant_xml (XMLNode& node, bool write_to_config)
3299 Stateful::add_instant_xml (node, _path);
3302 if (write_to_config) {
3303 Config->add_instant_xml (node);
3308 Session::instant_xml (const string& node_name)
3310 return Stateful::instant_xml (node_name, _path);
3314 Session::save_history (string snapshot_name)
3322 if (!Config->get_save_history() || Config->get_saved_history_depth() < 0 ||
3323 (_history.undo_depth() == 0 && _history.redo_depth() == 0)) {
3327 if (snapshot_name.empty()) {
3328 snapshot_name = _current_snapshot_name;
3331 const string history_filename = legalize_for_path (snapshot_name) + history_suffix;
3332 const string backup_filename = history_filename + backup_suffix;
3333 const std::string xml_path(Glib::build_filename (_session_dir->root_path(), history_filename));
3334 const std::string backup_path(Glib::build_filename (_session_dir->root_path(), backup_filename));
3336 if (Glib::file_test (xml_path, Glib::FILE_TEST_EXISTS)) {
3337 if (::g_rename (xml_path.c_str(), backup_path.c_str()) != 0) {
3338 error << _("could not backup old history file, current history not saved") << endmsg;
3343 tree.set_root (&_history.get_state (Config->get_saved_history_depth()));
3345 if (!tree.write (xml_path))
3347 error << string_compose (_("history could not be saved to %1"), xml_path) << endmsg;
3349 if (g_remove (xml_path.c_str()) != 0) {
3350 error << string_compose(_("Could not remove history file at path \"%1\" (%2)"),
3351 xml_path, g_strerror (errno)) << endmsg;
3353 if (::g_rename (backup_path.c_str(), xml_path.c_str()) != 0) {
3354 error << string_compose (_("could not restore history file from backup %1 (%2)"),
3355 backup_path, g_strerror (errno)) << endmsg;
3365 Session::restore_history (string snapshot_name)
3369 if (snapshot_name.empty()) {
3370 snapshot_name = _current_snapshot_name;
3373 const std::string xml_filename = legalize_for_path (snapshot_name) + history_suffix;
3374 const std::string xml_path(Glib::build_filename (_session_dir->root_path(), xml_filename));
3376 info << "Loading history from " << xml_path << endmsg;
3378 if (!Glib::file_test (xml_path, Glib::FILE_TEST_EXISTS)) {
3379 info << string_compose (_("%1: no history file \"%2\" for this session."),
3380 _name, xml_path) << endmsg;
3384 if (!tree.read (xml_path)) {
3385 error << string_compose (_("Could not understand session history file \"%1\""),
3386 xml_path) << endmsg;
3393 for (XMLNodeConstIterator it = tree.root()->children().begin(); it != tree.root()->children().end(); it++) {
3396 UndoTransaction* ut = new UndoTransaction ();
3399 ut->set_name(t->property("name")->value());
3400 stringstream ss(t->property("tv-sec")->value());
3402 ss.str(t->property("tv-usec")->value());
3404 ut->set_timestamp(tv);
3406 for (XMLNodeConstIterator child_it = t->children().begin();
3407 child_it != t->children().end(); child_it++)
3409 XMLNode *n = *child_it;
3412 if (n->name() == "MementoCommand" ||
3413 n->name() == "MementoUndoCommand" ||
3414 n->name() == "MementoRedoCommand") {
3416 if ((c = memento_command_factory(n))) {
3420 } else if (n->name() == "NoteDiffCommand") {
3421 PBD::ID id (n->property("midi-source")->value());
3422 boost::shared_ptr<MidiSource> midi_source =
3423 boost::dynamic_pointer_cast<MidiSource, Source>(source_by_id(id));
3425 ut->add_command (new MidiModel::NoteDiffCommand(midi_source->model(), *n));
3427 error << _("Failed to downcast MidiSource for NoteDiffCommand") << endmsg;
3430 } else if (n->name() == "SysExDiffCommand") {
3432 PBD::ID id (n->property("midi-source")->value());
3433 boost::shared_ptr<MidiSource> midi_source =
3434 boost::dynamic_pointer_cast<MidiSource, Source>(source_by_id(id));
3436 ut->add_command (new MidiModel::SysExDiffCommand (midi_source->model(), *n));
3438 error << _("Failed to downcast MidiSource for SysExDiffCommand") << endmsg;
3441 } else if (n->name() == "PatchChangeDiffCommand") {
3443 PBD::ID id (n->property("midi-source")->value());
3444 boost::shared_ptr<MidiSource> midi_source =
3445 boost::dynamic_pointer_cast<MidiSource, Source>(source_by_id(id));
3447 ut->add_command (new MidiModel::PatchChangeDiffCommand (midi_source->model(), *n));
3449 error << _("Failed to downcast MidiSource for PatchChangeDiffCommand") << endmsg;
3452 } else if (n->name() == "StatefulDiffCommand") {
3453 if ((c = stateful_diff_command_factory (n))) {
3454 ut->add_command (c);
3457 error << string_compose(_("Couldn't figure out how to make a Command out of a %1 XMLNode."), n->name()) << endmsg;
3468 Session::config_changed (std::string p, bool ours)
3474 if (p == "seamless-loop") {
3476 } else if (p == "rf-speed") {
3478 } else if (p == "auto-loop") {
3480 } else if (p == "auto-input") {
3482 if (Config->get_monitoring_model() == HardwareMonitoring && transport_rolling()) {
3483 /* auto-input only makes a difference if we're rolling */
3484 set_track_monitor_input_status (!config.get_auto_input());
3487 } else if (p == "punch-in") {
3491 if ((location = _locations->auto_punch_location()) != 0) {
3493 if (config.get_punch_in ()) {
3494 replace_event (SessionEvent::PunchIn, location->start());
3496 remove_event (location->start(), SessionEvent::PunchIn);
3500 } else if (p == "punch-out") {
3504 if ((location = _locations->auto_punch_location()) != 0) {
3506 if (config.get_punch_out()) {
3507 replace_event (SessionEvent::PunchOut, location->end());
3509 clear_events (SessionEvent::PunchOut);
3513 } else if (p == "edit-mode") {
3515 Glib::Threads::Mutex::Lock lm (playlists->lock);
3517 for (SessionPlaylists::List::iterator i = playlists->playlists.begin(); i != playlists->playlists.end(); ++i) {
3518 (*i)->set_edit_mode (Config->get_edit_mode ());
3521 } else if (p == "use-video-sync") {
3523 waiting_for_sync_offset = config.get_use_video_sync();
3525 } else if (p == "mmc-control") {
3527 //poke_midi_thread ();
3529 } else if (p == "mmc-device-id" || p == "mmc-receive-id" || p == "mmc-receive-device-id") {
3531 _mmc->set_receive_device_id (Config->get_mmc_receive_device_id());
3533 } else if (p == "mmc-send-id" || p == "mmc-send-device-id") {
3535 _mmc->set_send_device_id (Config->get_mmc_send_device_id());
3537 } else if (p == "midi-control") {
3539 //poke_midi_thread ();
3541 } else if (p == "raid-path") {
3543 setup_raid_path (config.get_raid_path());
3545 } else if (p == "timecode-format") {
3549 } else if (p == "video-pullup") {
3553 } else if (p == "seamless-loop") {
3555 if (play_loop && transport_rolling()) {
3556 // to reset diskstreams etc
3557 request_play_loop (true);
3560 } else if (p == "rf-speed") {
3562 cumulative_rf_motion = 0;
3565 } else if (p == "click-sound") {
3567 setup_click_sounds (1);
3569 } else if (p == "click-emphasis-sound") {
3571 setup_click_sounds (-1);
3573 } else if (p == "clicking") {
3575 if (Config->get_clicking()) {
3576 if (_click_io && click_data) { // don't require emphasis data
3583 } else if (p == "click-gain") {
3586 _click_gain->set_gain (Config->get_click_gain(), this);
3589 } else if (p == "send-mtc") {
3591 if (Config->get_send_mtc ()) {
3592 /* mark us ready to send */
3593 next_quarter_frame_to_send = 0;
3596 } else if (p == "send-mmc") {
3598 _mmc->enable_send (Config->get_send_mmc ());
3600 } else if (p == "midi-feedback") {
3602 session_midi_feedback = Config->get_midi_feedback();
3604 } else if (p == "jack-time-master") {
3606 engine().reset_timebase ();
3608 } else if (p == "native-file-header-format") {
3610 if (!first_file_header_format_reset) {
3611 reset_native_file_format ();
3614 first_file_header_format_reset = false;
3616 } else if (p == "native-file-data-format") {
3618 if (!first_file_data_format_reset) {
3619 reset_native_file_format ();
3622 first_file_data_format_reset = false;
3624 } else if (p == "external-sync") {
3625 if (!config.get_external_sync()) {
3626 drop_sync_source ();
3628 switch_to_sync_source (Config->get_sync_source());
3630 } else if (p == "denormal-model") {
3632 } else if (p == "history-depth") {
3633 set_history_depth (Config->get_history_depth());
3634 } else if (p == "remote-model") {
3635 /* XXX DO SOMETHING HERE TO TELL THE GUI THAT WE NEED
3638 } else if (p == "initial-program-change") {
3640 if (_mmc->output_port() && Config->get_initial_program_change() >= 0) {
3643 buf[0] = MIDI::program; // channel zero by default
3644 buf[1] = (Config->get_initial_program_change() & 0x7f);
3646 _mmc->output_port()->midimsg (buf, sizeof (buf), 0);
3648 } else if (p == "solo-mute-override") {
3649 // catch_up_on_solo_mute_override ();
3650 } else if (p == "listen-position" || p == "pfl-position") {
3651 listen_position_changed ();
3652 } else if (p == "solo-control-is-listen-control") {
3653 solo_control_mode_changed ();
3654 } else if (p == "solo-mute-gain") {
3655 _solo_cut_control->Changed();
3656 } else if (p == "timecode-offset" || p == "timecode-offset-negative") {
3657 last_timecode_valid = false;
3658 } else if (p == "playback-buffer-seconds") {
3659 AudioSource::allocate_working_buffers (frame_rate());
3660 } else if (p == "ltc-source-port") {
3661 reconnect_ltc_input ();
3662 } else if (p == "ltc-sink-port") {
3663 reconnect_ltc_output ();
3664 } else if (p == "timecode-generator-offset") {
3665 ltc_tx_parse_offset();
3666 } else if (p == "auto-return-target-list") {
3667 follow_playhead_priority ();
3674 Session::set_history_depth (uint32_t d)
3676 _history.set_depth (d);
3680 Session::load_diskstreams_2X (XMLNode const & node, int)
3683 XMLNodeConstIterator citer;
3685 clist = node.children();
3687 for (citer = clist.begin(); citer != clist.end(); ++citer) {
3690 /* diskstreams added automatically by DiskstreamCreated handler */
3691 if ((*citer)->name() == "AudioDiskstream" || (*citer)->name() == "DiskStream") {
3692 boost::shared_ptr<AudioDiskstream> dsp (new AudioDiskstream (*this, **citer));
3693 _diskstreams_2X.push_back (dsp);
3695 error << _("Session: unknown diskstream type in XML") << endmsg;
3699 catch (failed_constructor& err) {
3700 error << _("Session: could not load diskstream via XML state") << endmsg;
3708 /** Connect things to the MMC object */
3710 Session::setup_midi_machine_control ()
3712 _mmc = new MIDI::MachineControl;
3713 _mmc->set_ports (_midi_ports->mmc_input_port(), _midi_ports->mmc_output_port());
3715 _mmc->Play.connect_same_thread (*this, boost::bind (&Session::mmc_deferred_play, this, _1));
3716 _mmc->DeferredPlay.connect_same_thread (*this, boost::bind (&Session::mmc_deferred_play, this, _1));
3717 _mmc->Stop.connect_same_thread (*this, boost::bind (&Session::mmc_stop, this, _1));
3718 _mmc->FastForward.connect_same_thread (*this, boost::bind (&Session::mmc_fast_forward, this, _1));
3719 _mmc->Rewind.connect_same_thread (*this, boost::bind (&Session::mmc_rewind, this, _1));
3720 _mmc->Pause.connect_same_thread (*this, boost::bind (&Session::mmc_pause, this, _1));
3721 _mmc->RecordPause.connect_same_thread (*this, boost::bind (&Session::mmc_record_pause, this, _1));
3722 _mmc->RecordStrobe.connect_same_thread (*this, boost::bind (&Session::mmc_record_strobe, this, _1));
3723 _mmc->RecordExit.connect_same_thread (*this, boost::bind (&Session::mmc_record_exit, this, _1));
3724 _mmc->Locate.connect_same_thread (*this, boost::bind (&Session::mmc_locate, this, _1, _2));
3725 _mmc->Step.connect_same_thread (*this, boost::bind (&Session::mmc_step, this, _1, _2));
3726 _mmc->Shuttle.connect_same_thread (*this, boost::bind (&Session::mmc_shuttle, this, _1, _2, _3));
3727 _mmc->TrackRecordStatusChange.connect_same_thread (*this, boost::bind (&Session::mmc_record_enable, this, _1, _2, _3));
3729 /* also handle MIDI SPP because its so common */
3731 _mmc->SPPStart.connect_same_thread (*this, boost::bind (&Session::spp_start, this));
3732 _mmc->SPPContinue.connect_same_thread (*this, boost::bind (&Session::spp_continue, this));
3733 _mmc->SPPStop.connect_same_thread (*this, boost::bind (&Session::spp_stop, this));
3736 boost::shared_ptr<Controllable>
3737 Session::solo_cut_control() const
3739 /* the solo cut control is a bit of an anomaly, at least as of Febrary 2011. There are no other
3740 controls in Ardour that currently get presented to the user in the GUI that require
3741 access as a Controllable and are also NOT owned by some SessionObject (e.g. Route, or MonitorProcessor).
3743 its actually an RCConfiguration parameter, so we use a ProxyControllable to wrap
3744 it up as a Controllable. Changes to the Controllable will just map back to the RCConfiguration
3748 return _solo_cut_control;
3752 Session::rename (const std::string& new_name)
3754 string legal_name = legalize_for_path (new_name);
3760 string const old_sources_root = _session_dir->sources_root();
3762 if (!_writable || (_state_of_the_state & CannotSave)) {
3763 error << _("Cannot rename read-only session.") << endmsg;
3764 return 0; // don't show "messed up" warning
3766 if (record_status() == Recording) {
3767 error << _("Cannot rename session while recording") << endmsg;
3768 return 0; // don't show "messed up" warning
3771 StateProtector stp (this);
3776 * interchange subdirectory
3780 * Backup files are left unchanged and not renamed.
3783 /* Windows requires that we close all files before attempting the
3784 * rename. This works on other platforms, but isn't necessary there.
3785 * Leave it in place for all platforms though, since it may help
3786 * catch issues that could arise if the way Source files work ever
3787 * change (since most developers are not using Windows).
3790 for (SourceMap::const_iterator i = sources.begin(); i != sources.end(); ++i) {
3791 boost::shared_ptr<FileSource> fs = boost::dynamic_pointer_cast<FileSource> (i->second);
3797 /* pass one: not 100% safe check that the new directory names don't
3801 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
3805 /* this is a stupid hack because Glib::path_get_dirname() is
3806 * lexical-only, and so passing it /a/b/c/ gives a different
3807 * result than passing it /a/b/c ...
3810 if (oldstr[oldstr.length()-1] == G_DIR_SEPARATOR) {
3811 oldstr = oldstr.substr (0, oldstr.length() - 1);
3814 string base = Glib::path_get_dirname (oldstr);
3816 newstr = Glib::build_filename (base, legal_name);
3818 cerr << "Looking for " << newstr << endl;
3820 if (Glib::file_test (newstr, Glib::FILE_TEST_EXISTS)) {
3821 cerr << " exists\n";
3830 for (vector<space_and_path>::iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
3836 /* this is a stupid hack because Glib::path_get_dirname() is
3837 * lexical-only, and so passing it /a/b/c/ gives a different
3838 * result than passing it /a/b/c ...
3841 if (oldstr[oldstr.length()-1] == G_DIR_SEPARATOR) {
3842 oldstr = oldstr.substr (0, oldstr.length() - 1);
3845 string base = Glib::path_get_dirname (oldstr);
3846 newstr = Glib::build_filename (base, legal_name);
3848 cerr << "for " << oldstr << " new dir = " << newstr << endl;
3850 cerr << "Rename " << oldstr << " => " << newstr << endl;
3851 if (::g_rename (oldstr.c_str(), newstr.c_str()) != 0) {
3852 cerr << string_compose (_("renaming %s as %2 failed (%3)"), oldstr, newstr, g_strerror (errno)) << endl;
3853 error << string_compose (_("renaming %s as %2 failed (%3)"), oldstr, newstr, g_strerror (errno)) << endmsg;
3857 /* Reset path in "session dirs" */
3862 /* reset primary SessionDirectory object */
3865 (*_session_dir) = newstr;
3870 /* now rename directory below session_dir/interchange */
3872 string old_interchange_dir;
3873 string new_interchange_dir;
3875 /* use newstr here because we renamed the path
3876 * (folder/directory) that used to be oldstr to newstr above
3879 v.push_back (newstr);
3880 v.push_back (interchange_dir_name);
3881 v.push_back (Glib::path_get_basename (oldstr));
3883 old_interchange_dir = Glib::build_filename (v);
3886 v.push_back (newstr);
3887 v.push_back (interchange_dir_name);
3888 v.push_back (legal_name);
3890 new_interchange_dir = Glib::build_filename (v);
3892 cerr << "Rename " << old_interchange_dir << " => " << new_interchange_dir << endl;
3894 if (::g_rename (old_interchange_dir.c_str(), new_interchange_dir.c_str()) != 0) {
3895 cerr << string_compose (_("renaming %s as %2 failed (%3)"),
3896 old_interchange_dir, new_interchange_dir,
3899 error << string_compose (_("renaming %s as %2 failed (%3)"),
3900 old_interchange_dir, new_interchange_dir,
3909 oldstr = Glib::build_filename (new_path, _current_snapshot_name + statefile_suffix);
3910 newstr= Glib::build_filename (new_path, legal_name + statefile_suffix);
3912 cerr << "Rename " << oldstr << " => " << newstr << endl;
3914 if (::g_rename (oldstr.c_str(), newstr.c_str()) != 0) {
3915 cerr << string_compose (_("renaming %1 as %2 failed (%3)"), oldstr, newstr, g_strerror (errno)) << endl;
3916 error << string_compose (_("renaming %1 as %2 failed (%3)"), oldstr, newstr, g_strerror (errno)) << endmsg;
3922 oldstr = Glib::build_filename (new_path, _current_snapshot_name) + history_suffix;
3924 if (Glib::file_test (oldstr, Glib::FILE_TEST_EXISTS)) {
3925 newstr = Glib::build_filename (new_path, legal_name) + history_suffix;
3927 cerr << "Rename " << oldstr << " => " << newstr << endl;
3929 if (::g_rename (oldstr.c_str(), newstr.c_str()) != 0) {
3930 cerr << string_compose (_("renaming %1 as %2 failed (%3)"), oldstr, newstr, g_strerror (errno)) << endl;
3931 error << string_compose (_("renaming %1 as %2 failed (%3)"), oldstr, newstr, g_strerror (errno)) << endmsg;
3936 /* remove old name from recent sessions */
3937 remove_recent_sessions (_path);
3940 /* update file source paths */
3942 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ++i) {
3943 boost::shared_ptr<FileSource> fs = boost::dynamic_pointer_cast<FileSource> (i->second);
3945 string p = fs->path ();
3946 boost::replace_all (p, old_sources_root, _session_dir->sources_root());
3948 SourceFactory::setup_peakfile(i->second, true);
3952 _current_snapshot_name = new_name;
3957 /* save state again to get everything just right */
3959 save_state (_current_snapshot_name);
3961 /* add to recent sessions */
3963 store_recent_sessions (new_name, _path);
3969 Session::get_session_info_from_path (XMLTree& tree, const string& xmlpath)
3971 if (!Glib::file_test (xmlpath, Glib::FILE_TEST_EXISTS)) {
3975 if (!tree.read (xmlpath)) {
3983 Session::get_info_from_path (const string& xmlpath, float& sample_rate, SampleFormat& data_format)
3986 bool found_sr = false;
3987 bool found_data_format = false;
3989 if (get_session_info_from_path (tree, xmlpath)) {
3995 const XMLProperty* prop;
3996 if ((prop = tree.root()->property (X_("sample-rate"))) != 0) {
3997 sample_rate = atoi (prop->value());
4001 const XMLNodeList& children (tree.root()->children());
4002 for (XMLNodeList::const_iterator c = children.begin(); c != children.end(); ++c) {
4003 const XMLNode* child = *c;
4004 if (child->name() == "Config") {
4005 const XMLNodeList& options (child->children());
4006 for (XMLNodeList::const_iterator oc = options.begin(); oc != options.end(); ++oc) {
4007 const XMLNode* option = *oc;
4008 const XMLProperty* name = option->property("name");
4014 if (name->value() == "native-file-data-format") {
4015 const XMLProperty* value = option->property ("value");
4017 SampleFormat fmt = (SampleFormat) string_2_enum (option->property ("value")->value(), fmt);
4019 found_data_format = true;
4025 if (found_data_format) {
4030 return !(found_sr && found_data_format); // zero if they are both found
4033 typedef std::vector<boost::shared_ptr<FileSource> > SeveralFileSources;
4034 typedef std::map<std::string,SeveralFileSources> SourcePathMap;
4037 Session::bring_all_sources_into_session (boost::function<void(uint32_t,uint32_t,string)> callback)
4041 SourcePathMap source_path_map;
4043 boost::shared_ptr<AudioFileSource> afs;
4048 Glib::Threads::Mutex::Lock lm (source_lock);
4050 cerr << " total sources = " << sources.size();
4052 for (SourceMap::const_iterator i = sources.begin(); i != sources.end(); ++i) {
4053 boost::shared_ptr<FileSource> fs = boost::dynamic_pointer_cast<FileSource> (i->second);
4059 if (fs->within_session()) {
4063 if (source_path_map.find (fs->path()) != source_path_map.end()) {
4064 source_path_map[fs->path()].push_back (fs);
4066 SeveralFileSources v;
4068 source_path_map.insert (make_pair (fs->path(), v));
4074 cerr << " fsources = " << total << endl;
4076 for (SourcePathMap::iterator i = source_path_map.begin(); i != source_path_map.end(); ++i) {
4078 /* tell caller where we are */
4080 string old_path = i->first;
4082 callback (n, total, old_path);
4084 cerr << old_path << endl;
4088 switch (i->second.front()->type()) {
4089 case DataType::AUDIO:
4090 new_path = new_audio_source_path_for_embedded (old_path);
4093 case DataType::MIDI:
4094 /* XXX not implemented yet */
4098 if (new_path.empty()) {
4102 cerr << "Move " << old_path << " => " << new_path << endl;
4104 if (!copy_file (old_path, new_path)) {
4105 cerr << "failed !\n";
4109 /* make sure we stop looking in the external
4110 dir/folder. Remember, this is an all-or-nothing
4111 operations, it doesn't merge just some files.
4113 remove_dir_from_search_path (Glib::path_get_dirname (old_path), i->second.front()->type());
4115 for (SeveralFileSources::iterator f = i->second.begin(); f != i->second.end(); ++f) {
4116 (*f)->set_path (new_path);
4121 save_state ("", false, false);
4127 bool accept_all_files (string const &, void *)
4133 Session::save_as_bring_callback (uint32_t,uint32_t,string)
4135 /* 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.
4140 make_new_media_path (string old_path, string new_session_folder, string new_session_path)
4142 /* typedir is the "midifiles" or "audiofiles" etc. part of the path. */
4144 string typedir = Glib::path_get_basename (Glib::path_get_dirname (old_path));
4146 v.push_back (new_session_folder); /* full path */
4147 v.push_back (interchange_dir_name);
4148 v.push_back (new_session_path); /* just one directory/folder */
4149 v.push_back (typedir);
4150 v.push_back (Glib::path_get_basename (old_path));
4152 return Glib::build_filename (v);
4156 Session::save_as (SaveAs& saveas)
4158 vector<string> files;
4159 string current_folder = Glib::path_get_dirname (_path);
4160 string new_folder = legalize_for_path (saveas.new_name);
4161 string to_dir = Glib::build_filename (saveas.new_parent_folder, new_folder);
4162 int64_t total_bytes = 0;
4166 int32_t internal_file_cnt = 0;
4168 vector<string> do_not_copy_extensions;
4169 do_not_copy_extensions.push_back (statefile_suffix);
4170 do_not_copy_extensions.push_back (pending_suffix);
4171 do_not_copy_extensions.push_back (backup_suffix);
4172 do_not_copy_extensions.push_back (temp_suffix);
4173 do_not_copy_extensions.push_back (history_suffix);
4175 /* get total size */
4177 for (vector<space_and_path>::const_iterator sd = session_dirs.begin(); sd != session_dirs.end(); ++sd) {
4179 /* need to clear this because
4180 * find_files_matching_filter() is cumulative
4185 find_files_matching_filter (files, (*sd).path, accept_all_files, 0, false, true, true);
4187 all += files.size();
4189 for (vector<string>::iterator i = files.begin(); i != files.end(); ++i) {
4191 g_stat ((*i).c_str(), &gsb);
4192 total_bytes += gsb.st_size;
4196 /* save old values so we can switch back if we are not switching to the new session */
4198 string old_path = _path;
4199 string old_name = _name;
4200 string old_snapshot = _current_snapshot_name;
4201 string old_sd = _session_dir->root_path();
4202 vector<string> old_search_path[DataType::num_types];
4203 string old_config_search_path[DataType::num_types];
4205 old_search_path[DataType::AUDIO] = source_search_path (DataType::AUDIO);
4206 old_search_path[DataType::MIDI] = source_search_path (DataType::MIDI);
4207 old_config_search_path[DataType::AUDIO] = config.get_audio_search_path ();
4208 old_config_search_path[DataType::MIDI] = config.get_midi_search_path ();
4210 /* switch session directory */
4212 (*_session_dir) = to_dir;
4214 /* create new tree */
4216 if (!_session_dir->create()) {
4217 saveas.failure_message = string_compose (_("Cannot create new session folder %1"), to_dir);
4222 /* copy all relevant files. Find each location in session_dirs,
4223 * and copy files from there to target.
4226 for (vector<space_and_path>::const_iterator sd = session_dirs.begin(); sd != session_dirs.end(); ++sd) {
4228 /* need to clear this because
4229 * find_files_matching_filter() is cumulative
4234 const size_t prefix_len = (*sd).path.size();
4236 /* Work just on the files within this session dir */
4238 find_files_matching_filter (files, (*sd).path, accept_all_files, 0, false, true, true);
4240 /* add dir separator to protect against collisions with
4241 * track names (e.g. track named "audiofiles" or
4245 static const std::string audiofile_dir_string = string (sound_dir_name) + G_DIR_SEPARATOR;
4246 static const std::string midifile_dir_string = string (midi_dir_name) + G_DIR_SEPARATOR;
4247 static const std::string analysis_dir_string = analysis_dir() + G_DIR_SEPARATOR;
4249 /* copy all the files. Handling is different for media files
4250 than others because of the *silly* subtree we have below the interchange
4251 folder. That really was a bad idea, but I'm not fixing it as part of
4252 implementing ::save_as().
4255 for (vector<string>::iterator i = files.begin(); i != files.end(); ++i) {
4257 std::string from = *i;
4260 string filename = Glib::path_get_basename (from);
4261 std::transform (filename.begin(), filename.end(), filename.begin(), ::toupper);
4262 if (filename == ".DS_STORE") {
4267 if (from.find (audiofile_dir_string) != string::npos) {
4269 /* audio file: only copy if asked */
4271 if (saveas.include_media && saveas.copy_media) {
4273 string to = make_new_media_path (*i, to_dir, new_folder);
4275 info << "media file copying from " << from << " to " << to << endmsg;
4277 if (!copy_file (from, to)) {
4278 throw Glib::FileError (Glib::FileError::IO_ERROR,
4279 string_compose(_("\ncopying \"%1\" failed !"), from));
4283 /* we found media files inside the session folder */
4285 internal_file_cnt++;
4287 } else if (from.find (midifile_dir_string) != string::npos) {
4289 /* midi file: always copy unless
4290 * creating an empty new session
4293 if (saveas.include_media) {
4295 string to = make_new_media_path (*i, to_dir, new_folder);
4297 info << "media file copying from " << from << " to " << to << endmsg;
4299 if (!copy_file (from, to)) {
4300 throw Glib::FileError (Glib::FileError::IO_ERROR, "copy failed");
4304 /* we found media files inside the session folder */
4306 internal_file_cnt++;
4308 } else if (from.find (analysis_dir_string) != string::npos) {
4310 /* make sure analysis dir exists in
4311 * new session folder, but we're not
4312 * copying analysis files here, see
4316 (void) g_mkdir_with_parents (analysis_dir().c_str(), 775);
4321 /* normal non-media file. Don't copy state, history, etc.
4324 bool do_copy = true;
4326 for (vector<string>::iterator v = do_not_copy_extensions.begin(); v != do_not_copy_extensions.end(); ++v) {
4327 if ((from.length() > (*v).length()) && (from.find (*v) == from.length() - (*v).length())) {
4328 /* end of filename matches extension, do not copy file */
4334 if (!saveas.copy_media && from.find (peakfile_suffix) != string::npos) {
4335 /* don't copy peakfiles if
4336 * we're not copying media
4342 string to = Glib::build_filename (to_dir, from.substr (prefix_len));
4344 info << "attempting to make directory/folder " << to << endmsg;
4346 if (g_mkdir_with_parents (Glib::path_get_dirname (to).c_str(), 0755)) {
4347 throw Glib::FileError (Glib::FileError::IO_ERROR, "cannot create required directory");
4350 info << "attempting to copy " << from << " to " << to << endmsg;
4352 if (!copy_file (from, to)) {
4353 throw Glib::FileError (Glib::FileError::IO_ERROR,
4354 string_compose(_("\ncopying \"%1\" failed !"), from));
4359 /* measure file size even if we're not going to copy so that our Progress
4360 signals are correct, since we included these do-not-copy files
4361 in the computation of the total size and file count.
4365 g_stat (from.c_str(), &gsb);
4366 copied += gsb.st_size;
4369 double fraction = (double) copied / total_bytes;
4371 bool keep_going = true;
4373 if (saveas.copy_media) {
4375 /* no need or expectation of this if
4376 * media is not being copied, because
4377 * it will be fast(ish).
4380 /* tell someone "X percent, file M of N"; M is one-based */
4382 boost::optional<bool> res = saveas.Progress (fraction, cnt, all);
4390 throw Glib::FileError (Glib::FileError::FAILED, "copy cancelled");
4396 /* copy optional folders, if any */
4398 string old = plugins_dir ();
4399 if (Glib::file_test (old, Glib::FILE_TEST_EXISTS)) {
4400 string newdir = Glib::build_filename (to_dir, Glib::path_get_basename (old));
4401 copy_files (old, newdir);
4404 old = externals_dir ();
4405 if (Glib::file_test (old, Glib::FILE_TEST_EXISTS)) {
4406 string newdir = Glib::build_filename (to_dir, Glib::path_get_basename (old));
4407 copy_files (old, newdir);
4410 old = automation_dir ();
4411 if (Glib::file_test (old, Glib::FILE_TEST_EXISTS)) {
4412 string newdir = Glib::build_filename (to_dir, Glib::path_get_basename (old));
4413 copy_files (old, newdir);
4416 if (saveas.include_media) {
4418 if (saveas.copy_media) {
4419 #ifndef PLATFORM_WINDOWS
4420 /* There are problems with analysis files on
4421 * Windows, because they used a colon in their
4422 * names as late as 4.0. Colons are not legal
4423 * under Windows even if NTFS allows them.
4425 * This is a tricky problem to solve so for
4426 * just don't copy these files. They will be
4427 * regenerated as-needed anyway, subject to the
4428 * existing issue that the filenames will be
4429 * rejected by Windows, which is a separate
4430 * problem (though related).
4433 /* only needed if we are copying media, since the
4434 * analysis data refers to media data
4437 old = analysis_dir ();
4438 if (Glib::file_test (old, Glib::FILE_TEST_EXISTS)) {
4439 string newdir = Glib::build_filename (to_dir, "analysis");
4440 copy_files (old, newdir);
4442 #endif /* PLATFORM_WINDOWS */
4448 _current_snapshot_name = saveas.new_name;
4449 _name = saveas.new_name;
4451 if (saveas.include_media && !saveas.copy_media) {
4453 /* reset search paths of the new session (which we're pretending to be right now) to
4454 include the original session search path, so we can still find all audio.
4457 if (internal_file_cnt) {
4458 for (vector<string>::iterator s = old_search_path[DataType::AUDIO].begin(); s != old_search_path[DataType::AUDIO].end(); ++s) {
4459 ensure_search_path_includes (*s, DataType::AUDIO);
4460 cerr << "be sure to include " << *s << " for audio" << endl;
4463 /* we do not do this for MIDI because we copy
4464 all MIDI files if saveas.include_media is
4470 bool was_dirty = dirty ();
4472 save_state ("", false, false, !saveas.include_media);
4473 save_default_options ();
4475 if (saveas.copy_media && saveas.copy_external) {
4476 if (bring_all_sources_into_session (boost::bind (&Session::save_as_bring_callback, this, _1, _2, _3))) {
4477 throw Glib::FileError (Glib::FileError::NO_SPACE_LEFT, "consolidate failed");
4481 saveas.final_session_folder_name = _path;
4483 store_recent_sessions (_name, _path);
4485 if (!saveas.switch_to) {
4487 /* switch back to the way things were */
4491 _current_snapshot_name = old_snapshot;
4493 (*_session_dir) = old_sd;
4499 if (internal_file_cnt) {
4500 /* reset these to their original values */
4501 config.set_audio_search_path (old_config_search_path[DataType::AUDIO]);
4502 config.set_midi_search_path (old_config_search_path[DataType::MIDI]);
4507 /* prune session dirs, and update disk space statistics
4512 session_dirs.clear ();
4513 session_dirs.push_back (sp);
4514 refresh_disk_space ();
4516 /* ensure that all existing tracks reset their current capture source paths
4518 reset_write_sources (true, true);
4520 /* the copying above was based on actually discovering files, not just iterating over the sources list.
4521 But if we're going to switch to the new (copied) session, we need to change the paths in the sources also.
4524 for (SourceMap::const_iterator i = sources.begin(); i != sources.end(); ++i) {
4525 boost::shared_ptr<FileSource> fs = boost::dynamic_pointer_cast<FileSource> (i->second);
4531 if (fs->within_session()) {
4532 string newpath = make_new_media_path (fs->path(), to_dir, new_folder);
4533 fs->set_path (newpath);
4538 } catch (Glib::FileError& e) {
4540 saveas.failure_message = e.what();
4542 /* recursively remove all the directories */
4544 remove_directory (to_dir);
4552 saveas.failure_message = _("unknown reason");
4554 /* recursively remove all the directories */
4556 remove_directory (to_dir);