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);
2894 // also remove source from all_sources
2896 for (set<string>::iterator j = all_sources.begin(); j != all_sources.end(); ++j) {
2897 spath = Glib::path_get_basename (*j);
2898 if ( spath == i->second->name () ) {
2899 all_sources.erase (j);
2910 for (vector<string>::iterator x = candidates.begin(); x != candidates.end(); ++x) {
2915 for (set<string>::iterator i = all_sources.begin(); i != all_sources.end(); ++i) {
2917 tmppath1 = canonical_path (spath);
2918 tmppath2 = canonical_path ((*i));
2920 if (tmppath1 == tmppath2) {
2927 unused.push_back (spath);
2931 /* now try to move all unused files into the "dead" directory(ies) */
2933 for (vector<string>::iterator x = unused.begin(); x != unused.end(); ++x) {
2934 struct stat statbuf;
2938 /* don't move the file across filesystems, just
2939 stick it in the `dead_dir_name' directory
2940 on whichever filesystem it was already on.
2943 if ((*x).find ("/sounds/") != string::npos) {
2945 /* old school, go up 1 level */
2947 newpath = Glib::path_get_dirname (*x); // "sounds"
2948 newpath = Glib::path_get_dirname (newpath); // "session-name"
2952 /* new school, go up 4 levels */
2954 newpath = Glib::path_get_dirname (*x); // "audiofiles" or "midifiles"
2955 newpath = Glib::path_get_dirname (newpath); // "session-name"
2956 newpath = Glib::path_get_dirname (newpath); // "interchange"
2957 newpath = Glib::path_get_dirname (newpath); // "session-dir"
2960 newpath = Glib::build_filename (newpath, dead_dir_name);
2962 if (g_mkdir_with_parents (newpath.c_str(), 0755) < 0) {
2963 error << string_compose(_("Session: cannot create dead file folder \"%1\" (%2)"), newpath, strerror (errno)) << endmsg;
2967 newpath = Glib::build_filename (newpath, Glib::path_get_basename ((*x)));
2969 if (Glib::file_test (newpath, Glib::FILE_TEST_EXISTS)) {
2971 /* the new path already exists, try versioning */
2973 char buf[PATH_MAX+1];
2977 snprintf (buf, sizeof (buf), "%s.%d", newpath.c_str(), version);
2980 while (Glib::file_test (newpath_v.c_str(), Glib::FILE_TEST_EXISTS) && version < 999) {
2981 snprintf (buf, sizeof (buf), "%s.%d", newpath.c_str(), ++version);
2985 if (version == 999) {
2986 error << string_compose (_("there are already 1000 files with names like %1; versioning discontinued"),
2990 newpath = newpath_v;
2995 /* it doesn't exist, or we can't read it or something */
2999 stat ((*x).c_str(), &statbuf);
3001 if (::rename ((*x).c_str(), newpath.c_str()) != 0) {
3002 error << string_compose (_("cannot rename unused file source from %1 to %2 (%3)"),
3003 (*x), newpath, strerror (errno))
3008 /* see if there an easy to find peakfile for this file, and remove it.
3011 string base = basename_nosuffix (*x);
3012 base += "%A"; /* this is what we add for the channel suffix of all native files,
3013 or for the first channel of embedded files. it will miss
3014 some peakfiles for other channels
3016 string peakpath = peak_path (base);
3018 if (Glib::file_test (peakpath.c_str(), Glib::FILE_TEST_EXISTS)) {
3019 if (::g_unlink (peakpath.c_str()) != 0) {
3020 error << string_compose (_("cannot remove peakfile %1 for %2 (%3)"),
3021 peakpath, _path, strerror (errno))
3023 /* try to back out */
3024 ::rename (newpath.c_str(), _path.c_str());
3029 rep.paths.push_back (*x);
3030 rep.space += statbuf.st_size;
3033 /* dump the history list */
3037 /* save state so we don't end up a session file
3038 referring to non-existent sources.
3045 _state_of_the_state = (StateOfTheState) (_state_of_the_state & ~InCleanup);
3051 Session::cleanup_trash_sources (CleanupReport& rep)
3053 // FIXME: needs adaptation for MIDI
3055 vector<space_and_path>::iterator i;
3061 for (i = session_dirs.begin(); i != session_dirs.end(); ++i) {
3063 dead_dir = Glib::build_filename ((*i).path, dead_dir_name);
3065 clear_directory (dead_dir, &rep.space, &rep.paths);
3072 Session::set_dirty ()
3074 /* never mark session dirty during loading */
3076 if (_state_of_the_state & Loading) {
3080 bool was_dirty = dirty();
3082 _state_of_the_state = StateOfTheState (_state_of_the_state | Dirty);
3086 DirtyChanged(); /* EMIT SIGNAL */
3092 Session::set_clean ()
3094 bool was_dirty = dirty();
3096 _state_of_the_state = Clean;
3100 DirtyChanged(); /* EMIT SIGNAL */
3105 Session::set_deletion_in_progress ()
3107 _state_of_the_state = StateOfTheState (_state_of_the_state | Deletion);
3111 Session::clear_deletion_in_progress ()
3113 _state_of_the_state = StateOfTheState (_state_of_the_state & (~Deletion));
3117 Session::add_controllable (boost::shared_ptr<Controllable> c)
3119 /* this adds a controllable to the list managed by the Session.
3120 this is a subset of those managed by the Controllable class
3121 itself, and represents the only ones whose state will be saved
3122 as part of the session.
3125 Glib::Threads::Mutex::Lock lm (controllables_lock);
3126 controllables.insert (c);
3129 struct null_deleter { void operator()(void const *) const {} };
3132 Session::remove_controllable (Controllable* c)
3134 if (_state_of_the_state & Deletion) {
3138 Glib::Threads::Mutex::Lock lm (controllables_lock);
3140 Controllables::iterator x = controllables.find (boost::shared_ptr<Controllable>(c, null_deleter()));
3142 if (x != controllables.end()) {
3143 controllables.erase (x);
3147 boost::shared_ptr<Controllable>
3148 Session::controllable_by_id (const PBD::ID& id)
3150 Glib::Threads::Mutex::Lock lm (controllables_lock);
3152 for (Controllables::iterator i = controllables.begin(); i != controllables.end(); ++i) {
3153 if ((*i)->id() == id) {
3158 return boost::shared_ptr<Controllable>();
3161 boost::shared_ptr<Controllable>
3162 Session::controllable_by_descriptor (const ControllableDescriptor& desc)
3164 boost::shared_ptr<Controllable> c;
3165 boost::shared_ptr<Route> r;
3167 switch (desc.top_level_type()) {
3168 case ControllableDescriptor::NamedRoute:
3170 std::string str = desc.top_level_name();
3171 if (str == "Master" || str == "master") {
3173 } else if (str == "control" || str == "listen") {
3176 r = route_by_name (desc.top_level_name());
3181 case ControllableDescriptor::RemoteControlID:
3182 r = route_by_remote_id (desc.rid());
3190 switch (desc.subtype()) {
3191 case ControllableDescriptor::Gain:
3192 c = r->gain_control ();
3195 case ControllableDescriptor::Trim:
3196 c = r->trim()->gain_control ();
3199 case ControllableDescriptor::Solo:
3200 c = r->solo_control();
3203 case ControllableDescriptor::Mute:
3204 c = r->mute_control();
3207 case ControllableDescriptor::Recenable:
3209 boost::shared_ptr<Track> t = boost::dynamic_pointer_cast<Track>(r);
3212 c = t->rec_enable_control ();
3217 case ControllableDescriptor::PanDirection:
3219 c = r->pannable()->pan_azimuth_control;
3223 case ControllableDescriptor::PanWidth:
3225 c = r->pannable()->pan_width_control;
3229 case ControllableDescriptor::PanElevation:
3231 c = r->pannable()->pan_elevation_control;
3235 case ControllableDescriptor::Balance:
3236 /* XXX simple pan control */
3239 case ControllableDescriptor::PluginParameter:
3241 uint32_t plugin = desc.target (0);
3242 uint32_t parameter_index = desc.target (1);
3244 /* revert to zero based counting */
3250 if (parameter_index > 0) {
3254 boost::shared_ptr<Processor> p = r->nth_plugin (plugin);
3257 c = boost::dynamic_pointer_cast<ARDOUR::AutomationControl>(
3258 p->control(Evoral::Parameter(PluginAutomation, 0, parameter_index)));
3263 case ControllableDescriptor::SendGain:
3265 uint32_t send = desc.target (0);
3267 /* revert to zero-based counting */
3273 boost::shared_ptr<Processor> p = r->nth_send (send);
3276 boost::shared_ptr<Send> s = boost::dynamic_pointer_cast<Send>(p);
3277 boost::shared_ptr<Amp> a = s->amp();
3280 c = s->amp()->gain_control();
3287 /* relax and return a null pointer */
3295 Session::add_instant_xml (XMLNode& node, bool write_to_config)
3298 Stateful::add_instant_xml (node, _path);
3301 if (write_to_config) {
3302 Config->add_instant_xml (node);
3307 Session::instant_xml (const string& node_name)
3309 return Stateful::instant_xml (node_name, _path);
3313 Session::save_history (string snapshot_name)
3321 if (!Config->get_save_history() || Config->get_saved_history_depth() < 0 ||
3322 (_history.undo_depth() == 0 && _history.redo_depth() == 0)) {
3326 if (snapshot_name.empty()) {
3327 snapshot_name = _current_snapshot_name;
3330 const string history_filename = legalize_for_path (snapshot_name) + history_suffix;
3331 const string backup_filename = history_filename + backup_suffix;
3332 const std::string xml_path(Glib::build_filename (_session_dir->root_path(), history_filename));
3333 const std::string backup_path(Glib::build_filename (_session_dir->root_path(), backup_filename));
3335 if (Glib::file_test (xml_path, Glib::FILE_TEST_EXISTS)) {
3336 if (::g_rename (xml_path.c_str(), backup_path.c_str()) != 0) {
3337 error << _("could not backup old history file, current history not saved") << endmsg;
3342 tree.set_root (&_history.get_state (Config->get_saved_history_depth()));
3344 if (!tree.write (xml_path))
3346 error << string_compose (_("history could not be saved to %1"), xml_path) << endmsg;
3348 if (g_remove (xml_path.c_str()) != 0) {
3349 error << string_compose(_("Could not remove history file at path \"%1\" (%2)"),
3350 xml_path, g_strerror (errno)) << endmsg;
3352 if (::g_rename (backup_path.c_str(), xml_path.c_str()) != 0) {
3353 error << string_compose (_("could not restore history file from backup %1 (%2)"),
3354 backup_path, g_strerror (errno)) << endmsg;
3364 Session::restore_history (string snapshot_name)
3368 if (snapshot_name.empty()) {
3369 snapshot_name = _current_snapshot_name;
3372 const std::string xml_filename = legalize_for_path (snapshot_name) + history_suffix;
3373 const std::string xml_path(Glib::build_filename (_session_dir->root_path(), xml_filename));
3375 info << "Loading history from " << xml_path << endmsg;
3377 if (!Glib::file_test (xml_path, Glib::FILE_TEST_EXISTS)) {
3378 info << string_compose (_("%1: no history file \"%2\" for this session."),
3379 _name, xml_path) << endmsg;
3383 if (!tree.read (xml_path)) {
3384 error << string_compose (_("Could not understand session history file \"%1\""),
3385 xml_path) << endmsg;
3392 for (XMLNodeConstIterator it = tree.root()->children().begin(); it != tree.root()->children().end(); it++) {
3395 UndoTransaction* ut = new UndoTransaction ();
3398 ut->set_name(t->property("name")->value());
3399 stringstream ss(t->property("tv-sec")->value());
3401 ss.str(t->property("tv-usec")->value());
3403 ut->set_timestamp(tv);
3405 for (XMLNodeConstIterator child_it = t->children().begin();
3406 child_it != t->children().end(); child_it++)
3408 XMLNode *n = *child_it;
3411 if (n->name() == "MementoCommand" ||
3412 n->name() == "MementoUndoCommand" ||
3413 n->name() == "MementoRedoCommand") {
3415 if ((c = memento_command_factory(n))) {
3419 } else if (n->name() == "NoteDiffCommand") {
3420 PBD::ID id (n->property("midi-source")->value());
3421 boost::shared_ptr<MidiSource> midi_source =
3422 boost::dynamic_pointer_cast<MidiSource, Source>(source_by_id(id));
3424 ut->add_command (new MidiModel::NoteDiffCommand(midi_source->model(), *n));
3426 error << _("Failed to downcast MidiSource for NoteDiffCommand") << endmsg;
3429 } else if (n->name() == "SysExDiffCommand") {
3431 PBD::ID id (n->property("midi-source")->value());
3432 boost::shared_ptr<MidiSource> midi_source =
3433 boost::dynamic_pointer_cast<MidiSource, Source>(source_by_id(id));
3435 ut->add_command (new MidiModel::SysExDiffCommand (midi_source->model(), *n));
3437 error << _("Failed to downcast MidiSource for SysExDiffCommand") << endmsg;
3440 } else if (n->name() == "PatchChangeDiffCommand") {
3442 PBD::ID id (n->property("midi-source")->value());
3443 boost::shared_ptr<MidiSource> midi_source =
3444 boost::dynamic_pointer_cast<MidiSource, Source>(source_by_id(id));
3446 ut->add_command (new MidiModel::PatchChangeDiffCommand (midi_source->model(), *n));
3448 error << _("Failed to downcast MidiSource for PatchChangeDiffCommand") << endmsg;
3451 } else if (n->name() == "StatefulDiffCommand") {
3452 if ((c = stateful_diff_command_factory (n))) {
3453 ut->add_command (c);
3456 error << string_compose(_("Couldn't figure out how to make a Command out of a %1 XMLNode."), n->name()) << endmsg;
3467 Session::config_changed (std::string p, bool ours)
3473 if (p == "seamless-loop") {
3475 } else if (p == "rf-speed") {
3477 } else if (p == "auto-loop") {
3479 } else if (p == "auto-input") {
3481 if (Config->get_monitoring_model() == HardwareMonitoring && transport_rolling()) {
3482 /* auto-input only makes a difference if we're rolling */
3483 set_track_monitor_input_status (!config.get_auto_input());
3486 } else if (p == "punch-in") {
3490 if ((location = _locations->auto_punch_location()) != 0) {
3492 if (config.get_punch_in ()) {
3493 replace_event (SessionEvent::PunchIn, location->start());
3495 remove_event (location->start(), SessionEvent::PunchIn);
3499 } else if (p == "punch-out") {
3503 if ((location = _locations->auto_punch_location()) != 0) {
3505 if (config.get_punch_out()) {
3506 replace_event (SessionEvent::PunchOut, location->end());
3508 clear_events (SessionEvent::PunchOut);
3512 } else if (p == "edit-mode") {
3514 Glib::Threads::Mutex::Lock lm (playlists->lock);
3516 for (SessionPlaylists::List::iterator i = playlists->playlists.begin(); i != playlists->playlists.end(); ++i) {
3517 (*i)->set_edit_mode (Config->get_edit_mode ());
3520 } else if (p == "use-video-sync") {
3522 waiting_for_sync_offset = config.get_use_video_sync();
3524 } else if (p == "mmc-control") {
3526 //poke_midi_thread ();
3528 } else if (p == "mmc-device-id" || p == "mmc-receive-id" || p == "mmc-receive-device-id") {
3530 _mmc->set_receive_device_id (Config->get_mmc_receive_device_id());
3532 } else if (p == "mmc-send-id" || p == "mmc-send-device-id") {
3534 _mmc->set_send_device_id (Config->get_mmc_send_device_id());
3536 } else if (p == "midi-control") {
3538 //poke_midi_thread ();
3540 } else if (p == "raid-path") {
3542 setup_raid_path (config.get_raid_path());
3544 } else if (p == "timecode-format") {
3548 } else if (p == "video-pullup") {
3552 } else if (p == "seamless-loop") {
3554 if (play_loop && transport_rolling()) {
3555 // to reset diskstreams etc
3556 request_play_loop (true);
3559 } else if (p == "rf-speed") {
3561 cumulative_rf_motion = 0;
3564 } else if (p == "click-sound") {
3566 setup_click_sounds (1);
3568 } else if (p == "click-emphasis-sound") {
3570 setup_click_sounds (-1);
3572 } else if (p == "clicking") {
3574 if (Config->get_clicking()) {
3575 if (_click_io && click_data) { // don't require emphasis data
3582 } else if (p == "click-gain") {
3585 _click_gain->set_gain (Config->get_click_gain(), this);
3588 } else if (p == "send-mtc") {
3590 if (Config->get_send_mtc ()) {
3591 /* mark us ready to send */
3592 next_quarter_frame_to_send = 0;
3595 } else if (p == "send-mmc") {
3597 _mmc->enable_send (Config->get_send_mmc ());
3599 } else if (p == "midi-feedback") {
3601 session_midi_feedback = Config->get_midi_feedback();
3603 } else if (p == "jack-time-master") {
3605 engine().reset_timebase ();
3607 } else if (p == "native-file-header-format") {
3609 if (!first_file_header_format_reset) {
3610 reset_native_file_format ();
3613 first_file_header_format_reset = false;
3615 } else if (p == "native-file-data-format") {
3617 if (!first_file_data_format_reset) {
3618 reset_native_file_format ();
3621 first_file_data_format_reset = false;
3623 } else if (p == "external-sync") {
3624 if (!config.get_external_sync()) {
3625 drop_sync_source ();
3627 switch_to_sync_source (Config->get_sync_source());
3629 } else if (p == "denormal-model") {
3631 } else if (p == "history-depth") {
3632 set_history_depth (Config->get_history_depth());
3633 } else if (p == "remote-model") {
3634 /* XXX DO SOMETHING HERE TO TELL THE GUI THAT WE NEED
3637 } else if (p == "initial-program-change") {
3639 if (_mmc->output_port() && Config->get_initial_program_change() >= 0) {
3642 buf[0] = MIDI::program; // channel zero by default
3643 buf[1] = (Config->get_initial_program_change() & 0x7f);
3645 _mmc->output_port()->midimsg (buf, sizeof (buf), 0);
3647 } else if (p == "solo-mute-override") {
3648 // catch_up_on_solo_mute_override ();
3649 } else if (p == "listen-position" || p == "pfl-position") {
3650 listen_position_changed ();
3651 } else if (p == "solo-control-is-listen-control") {
3652 solo_control_mode_changed ();
3653 } else if (p == "solo-mute-gain") {
3654 _solo_cut_control->Changed();
3655 } else if (p == "timecode-offset" || p == "timecode-offset-negative") {
3656 last_timecode_valid = false;
3657 } else if (p == "playback-buffer-seconds") {
3658 AudioSource::allocate_working_buffers (frame_rate());
3659 } else if (p == "ltc-source-port") {
3660 reconnect_ltc_input ();
3661 } else if (p == "ltc-sink-port") {
3662 reconnect_ltc_output ();
3663 } else if (p == "timecode-generator-offset") {
3664 ltc_tx_parse_offset();
3665 } else if (p == "auto-return-target-list") {
3666 follow_playhead_priority ();
3673 Session::set_history_depth (uint32_t d)
3675 _history.set_depth (d);
3679 Session::load_diskstreams_2X (XMLNode const & node, int)
3682 XMLNodeConstIterator citer;
3684 clist = node.children();
3686 for (citer = clist.begin(); citer != clist.end(); ++citer) {
3689 /* diskstreams added automatically by DiskstreamCreated handler */
3690 if ((*citer)->name() == "AudioDiskstream" || (*citer)->name() == "DiskStream") {
3691 boost::shared_ptr<AudioDiskstream> dsp (new AudioDiskstream (*this, **citer));
3692 _diskstreams_2X.push_back (dsp);
3694 error << _("Session: unknown diskstream type in XML") << endmsg;
3698 catch (failed_constructor& err) {
3699 error << _("Session: could not load diskstream via XML state") << endmsg;
3707 /** Connect things to the MMC object */
3709 Session::setup_midi_machine_control ()
3711 _mmc = new MIDI::MachineControl;
3712 _mmc->set_ports (_midi_ports->mmc_input_port(), _midi_ports->mmc_output_port());
3714 _mmc->Play.connect_same_thread (*this, boost::bind (&Session::mmc_deferred_play, this, _1));
3715 _mmc->DeferredPlay.connect_same_thread (*this, boost::bind (&Session::mmc_deferred_play, this, _1));
3716 _mmc->Stop.connect_same_thread (*this, boost::bind (&Session::mmc_stop, this, _1));
3717 _mmc->FastForward.connect_same_thread (*this, boost::bind (&Session::mmc_fast_forward, this, _1));
3718 _mmc->Rewind.connect_same_thread (*this, boost::bind (&Session::mmc_rewind, this, _1));
3719 _mmc->Pause.connect_same_thread (*this, boost::bind (&Session::mmc_pause, this, _1));
3720 _mmc->RecordPause.connect_same_thread (*this, boost::bind (&Session::mmc_record_pause, this, _1));
3721 _mmc->RecordStrobe.connect_same_thread (*this, boost::bind (&Session::mmc_record_strobe, this, _1));
3722 _mmc->RecordExit.connect_same_thread (*this, boost::bind (&Session::mmc_record_exit, this, _1));
3723 _mmc->Locate.connect_same_thread (*this, boost::bind (&Session::mmc_locate, this, _1, _2));
3724 _mmc->Step.connect_same_thread (*this, boost::bind (&Session::mmc_step, this, _1, _2));
3725 _mmc->Shuttle.connect_same_thread (*this, boost::bind (&Session::mmc_shuttle, this, _1, _2, _3));
3726 _mmc->TrackRecordStatusChange.connect_same_thread (*this, boost::bind (&Session::mmc_record_enable, this, _1, _2, _3));
3728 /* also handle MIDI SPP because its so common */
3730 _mmc->SPPStart.connect_same_thread (*this, boost::bind (&Session::spp_start, this));
3731 _mmc->SPPContinue.connect_same_thread (*this, boost::bind (&Session::spp_continue, this));
3732 _mmc->SPPStop.connect_same_thread (*this, boost::bind (&Session::spp_stop, this));
3735 boost::shared_ptr<Controllable>
3736 Session::solo_cut_control() const
3738 /* the solo cut control is a bit of an anomaly, at least as of Febrary 2011. There are no other
3739 controls in Ardour that currently get presented to the user in the GUI that require
3740 access as a Controllable and are also NOT owned by some SessionObject (e.g. Route, or MonitorProcessor).
3742 its actually an RCConfiguration parameter, so we use a ProxyControllable to wrap
3743 it up as a Controllable. Changes to the Controllable will just map back to the RCConfiguration
3747 return _solo_cut_control;
3751 Session::rename (const std::string& new_name)
3753 string legal_name = legalize_for_path (new_name);
3759 string const old_sources_root = _session_dir->sources_root();
3761 if (!_writable || (_state_of_the_state & CannotSave)) {
3762 error << _("Cannot rename read-only session.") << endmsg;
3763 return 0; // don't show "messed up" warning
3765 if (record_status() == Recording) {
3766 error << _("Cannot rename session while recording") << endmsg;
3767 return 0; // don't show "messed up" warning
3770 StateProtector stp (this);
3775 * interchange subdirectory
3779 * Backup files are left unchanged and not renamed.
3782 /* Windows requires that we close all files before attempting the
3783 * rename. This works on other platforms, but isn't necessary there.
3784 * Leave it in place for all platforms though, since it may help
3785 * catch issues that could arise if the way Source files work ever
3786 * change (since most developers are not using Windows).
3789 for (SourceMap::const_iterator i = sources.begin(); i != sources.end(); ++i) {
3790 boost::shared_ptr<FileSource> fs = boost::dynamic_pointer_cast<FileSource> (i->second);
3796 /* pass one: not 100% safe check that the new directory names don't
3800 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
3804 /* this is a stupid hack because Glib::path_get_dirname() is
3805 * lexical-only, and so passing it /a/b/c/ gives a different
3806 * result than passing it /a/b/c ...
3809 if (oldstr[oldstr.length()-1] == G_DIR_SEPARATOR) {
3810 oldstr = oldstr.substr (0, oldstr.length() - 1);
3813 string base = Glib::path_get_dirname (oldstr);
3815 newstr = Glib::build_filename (base, legal_name);
3817 cerr << "Looking for " << newstr << endl;
3819 if (Glib::file_test (newstr, Glib::FILE_TEST_EXISTS)) {
3820 cerr << " exists\n";
3829 for (vector<space_and_path>::iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
3835 /* this is a stupid hack because Glib::path_get_dirname() is
3836 * lexical-only, and so passing it /a/b/c/ gives a different
3837 * result than passing it /a/b/c ...
3840 if (oldstr[oldstr.length()-1] == G_DIR_SEPARATOR) {
3841 oldstr = oldstr.substr (0, oldstr.length() - 1);
3844 string base = Glib::path_get_dirname (oldstr);
3845 newstr = Glib::build_filename (base, legal_name);
3847 cerr << "for " << oldstr << " new dir = " << newstr << endl;
3849 cerr << "Rename " << oldstr << " => " << newstr << endl;
3850 if (::g_rename (oldstr.c_str(), newstr.c_str()) != 0) {
3851 cerr << string_compose (_("renaming %s as %2 failed (%3)"), oldstr, newstr, g_strerror (errno)) << endl;
3852 error << string_compose (_("renaming %s as %2 failed (%3)"), oldstr, newstr, g_strerror (errno)) << endmsg;
3856 /* Reset path in "session dirs" */
3861 /* reset primary SessionDirectory object */
3864 (*_session_dir) = newstr;
3869 /* now rename directory below session_dir/interchange */
3871 string old_interchange_dir;
3872 string new_interchange_dir;
3874 /* use newstr here because we renamed the path
3875 * (folder/directory) that used to be oldstr to newstr above
3878 v.push_back (newstr);
3879 v.push_back (interchange_dir_name);
3880 v.push_back (Glib::path_get_basename (oldstr));
3882 old_interchange_dir = Glib::build_filename (v);
3885 v.push_back (newstr);
3886 v.push_back (interchange_dir_name);
3887 v.push_back (legal_name);
3889 new_interchange_dir = Glib::build_filename (v);
3891 cerr << "Rename " << old_interchange_dir << " => " << new_interchange_dir << endl;
3893 if (::g_rename (old_interchange_dir.c_str(), new_interchange_dir.c_str()) != 0) {
3894 cerr << string_compose (_("renaming %s as %2 failed (%3)"),
3895 old_interchange_dir, new_interchange_dir,
3898 error << string_compose (_("renaming %s as %2 failed (%3)"),
3899 old_interchange_dir, new_interchange_dir,
3908 oldstr = Glib::build_filename (new_path, _current_snapshot_name + statefile_suffix);
3909 newstr= Glib::build_filename (new_path, legal_name + statefile_suffix);
3911 cerr << "Rename " << oldstr << " => " << newstr << endl;
3913 if (::g_rename (oldstr.c_str(), newstr.c_str()) != 0) {
3914 cerr << string_compose (_("renaming %1 as %2 failed (%3)"), oldstr, newstr, g_strerror (errno)) << endl;
3915 error << string_compose (_("renaming %1 as %2 failed (%3)"), oldstr, newstr, g_strerror (errno)) << endmsg;
3921 oldstr = Glib::build_filename (new_path, _current_snapshot_name) + history_suffix;
3923 if (Glib::file_test (oldstr, Glib::FILE_TEST_EXISTS)) {
3924 newstr = Glib::build_filename (new_path, legal_name) + history_suffix;
3926 cerr << "Rename " << oldstr << " => " << newstr << endl;
3928 if (::g_rename (oldstr.c_str(), newstr.c_str()) != 0) {
3929 cerr << string_compose (_("renaming %1 as %2 failed (%3)"), oldstr, newstr, g_strerror (errno)) << endl;
3930 error << string_compose (_("renaming %1 as %2 failed (%3)"), oldstr, newstr, g_strerror (errno)) << endmsg;
3935 /* remove old name from recent sessions */
3936 remove_recent_sessions (_path);
3939 /* update file source paths */
3941 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ++i) {
3942 boost::shared_ptr<FileSource> fs = boost::dynamic_pointer_cast<FileSource> (i->second);
3944 string p = fs->path ();
3945 boost::replace_all (p, old_sources_root, _session_dir->sources_root());
3947 SourceFactory::setup_peakfile(i->second, true);
3951 _current_snapshot_name = new_name;
3956 /* save state again to get everything just right */
3958 save_state (_current_snapshot_name);
3960 /* add to recent sessions */
3962 store_recent_sessions (new_name, _path);
3968 Session::get_session_info_from_path (XMLTree& tree, const string& xmlpath)
3970 if (!Glib::file_test (xmlpath, Glib::FILE_TEST_EXISTS)) {
3974 if (!tree.read (xmlpath)) {
3982 Session::get_info_from_path (const string& xmlpath, float& sample_rate, SampleFormat& data_format)
3985 bool found_sr = false;
3986 bool found_data_format = false;
3988 if (get_session_info_from_path (tree, xmlpath)) {
3994 const XMLProperty* prop;
3995 if ((prop = tree.root()->property (X_("sample-rate"))) != 0) {
3996 sample_rate = atoi (prop->value());
4000 const XMLNodeList& children (tree.root()->children());
4001 for (XMLNodeList::const_iterator c = children.begin(); c != children.end(); ++c) {
4002 const XMLNode* child = *c;
4003 if (child->name() == "Config") {
4004 const XMLNodeList& options (child->children());
4005 for (XMLNodeList::const_iterator oc = options.begin(); oc != options.end(); ++oc) {
4006 const XMLNode* option = *oc;
4007 const XMLProperty* name = option->property("name");
4013 if (name->value() == "native-file-data-format") {
4014 const XMLProperty* value = option->property ("value");
4016 SampleFormat fmt = (SampleFormat) string_2_enum (option->property ("value")->value(), fmt);
4018 found_data_format = true;
4024 if (found_data_format) {
4029 return !(found_sr && found_data_format); // zero if they are both found
4032 typedef std::vector<boost::shared_ptr<FileSource> > SeveralFileSources;
4033 typedef std::map<std::string,SeveralFileSources> SourcePathMap;
4036 Session::bring_all_sources_into_session (boost::function<void(uint32_t,uint32_t,string)> callback)
4040 SourcePathMap source_path_map;
4042 boost::shared_ptr<AudioFileSource> afs;
4047 Glib::Threads::Mutex::Lock lm (source_lock);
4049 cerr << " total sources = " << sources.size();
4051 for (SourceMap::const_iterator i = sources.begin(); i != sources.end(); ++i) {
4052 boost::shared_ptr<FileSource> fs = boost::dynamic_pointer_cast<FileSource> (i->second);
4058 if (fs->within_session()) {
4062 if (source_path_map.find (fs->path()) != source_path_map.end()) {
4063 source_path_map[fs->path()].push_back (fs);
4065 SeveralFileSources v;
4067 source_path_map.insert (make_pair (fs->path(), v));
4073 cerr << " fsources = " << total << endl;
4075 for (SourcePathMap::iterator i = source_path_map.begin(); i != source_path_map.end(); ++i) {
4077 /* tell caller where we are */
4079 string old_path = i->first;
4081 callback (n, total, old_path);
4083 cerr << old_path << endl;
4087 switch (i->second.front()->type()) {
4088 case DataType::AUDIO:
4089 new_path = new_audio_source_path_for_embedded (old_path);
4092 case DataType::MIDI:
4093 /* XXX not implemented yet */
4097 if (new_path.empty()) {
4101 cerr << "Move " << old_path << " => " << new_path << endl;
4103 if (!copy_file (old_path, new_path)) {
4104 cerr << "failed !\n";
4108 /* make sure we stop looking in the external
4109 dir/folder. Remember, this is an all-or-nothing
4110 operations, it doesn't merge just some files.
4112 remove_dir_from_search_path (Glib::path_get_dirname (old_path), i->second.front()->type());
4114 for (SeveralFileSources::iterator f = i->second.begin(); f != i->second.end(); ++f) {
4115 (*f)->set_path (new_path);
4120 save_state ("", false, false);
4126 bool accept_all_files (string const &, void *)
4132 Session::save_as_bring_callback (uint32_t,uint32_t,string)
4134 /* 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.
4139 make_new_media_path (string old_path, string new_session_folder, string new_session_path)
4141 /* typedir is the "midifiles" or "audiofiles" etc. part of the path. */
4143 string typedir = Glib::path_get_basename (Glib::path_get_dirname (old_path));
4145 v.push_back (new_session_folder); /* full path */
4146 v.push_back (interchange_dir_name);
4147 v.push_back (new_session_path); /* just one directory/folder */
4148 v.push_back (typedir);
4149 v.push_back (Glib::path_get_basename (old_path));
4151 return Glib::build_filename (v);
4155 Session::save_as (SaveAs& saveas)
4157 vector<string> files;
4158 string current_folder = Glib::path_get_dirname (_path);
4159 string new_folder = legalize_for_path (saveas.new_name);
4160 string to_dir = Glib::build_filename (saveas.new_parent_folder, new_folder);
4161 int64_t total_bytes = 0;
4165 int32_t internal_file_cnt = 0;
4167 vector<string> do_not_copy_extensions;
4168 do_not_copy_extensions.push_back (statefile_suffix);
4169 do_not_copy_extensions.push_back (pending_suffix);
4170 do_not_copy_extensions.push_back (backup_suffix);
4171 do_not_copy_extensions.push_back (temp_suffix);
4172 do_not_copy_extensions.push_back (history_suffix);
4174 /* get total size */
4176 for (vector<space_and_path>::const_iterator sd = session_dirs.begin(); sd != session_dirs.end(); ++sd) {
4178 /* need to clear this because
4179 * find_files_matching_filter() is cumulative
4184 find_files_matching_filter (files, (*sd).path, accept_all_files, 0, false, true, true);
4186 all += files.size();
4188 for (vector<string>::iterator i = files.begin(); i != files.end(); ++i) {
4190 g_stat ((*i).c_str(), &gsb);
4191 total_bytes += gsb.st_size;
4195 /* save old values so we can switch back if we are not switching to the new session */
4197 string old_path = _path;
4198 string old_name = _name;
4199 string old_snapshot = _current_snapshot_name;
4200 string old_sd = _session_dir->root_path();
4201 vector<string> old_search_path[DataType::num_types];
4202 string old_config_search_path[DataType::num_types];
4204 old_search_path[DataType::AUDIO] = source_search_path (DataType::AUDIO);
4205 old_search_path[DataType::MIDI] = source_search_path (DataType::MIDI);
4206 old_config_search_path[DataType::AUDIO] = config.get_audio_search_path ();
4207 old_config_search_path[DataType::MIDI] = config.get_midi_search_path ();
4209 /* switch session directory */
4211 (*_session_dir) = to_dir;
4213 /* create new tree */
4215 if (!_session_dir->create()) {
4216 saveas.failure_message = string_compose (_("Cannot create new session folder %1"), to_dir);
4221 /* copy all relevant files. Find each location in session_dirs,
4222 * and copy files from there to target.
4225 for (vector<space_and_path>::const_iterator sd = session_dirs.begin(); sd != session_dirs.end(); ++sd) {
4227 /* need to clear this because
4228 * find_files_matching_filter() is cumulative
4233 const size_t prefix_len = (*sd).path.size();
4235 /* Work just on the files within this session dir */
4237 find_files_matching_filter (files, (*sd).path, accept_all_files, 0, false, true, true);
4239 /* add dir separator to protect against collisions with
4240 * track names (e.g. track named "audiofiles" or
4244 static const std::string audiofile_dir_string = string (sound_dir_name) + G_DIR_SEPARATOR;
4245 static const std::string midifile_dir_string = string (midi_dir_name) + G_DIR_SEPARATOR;
4246 static const std::string analysis_dir_string = analysis_dir() + G_DIR_SEPARATOR;
4248 /* copy all the files. Handling is different for media files
4249 than others because of the *silly* subtree we have below the interchange
4250 folder. That really was a bad idea, but I'm not fixing it as part of
4251 implementing ::save_as().
4254 for (vector<string>::iterator i = files.begin(); i != files.end(); ++i) {
4256 std::string from = *i;
4259 string filename = Glib::path_get_basename (from);
4260 std::transform (filename.begin(), filename.end(), filename.begin(), ::toupper);
4261 if (filename == ".DS_STORE") {
4266 if (from.find (audiofile_dir_string) != string::npos) {
4268 /* audio file: only copy if asked */
4270 if (saveas.include_media && saveas.copy_media) {
4272 string to = make_new_media_path (*i, to_dir, new_folder);
4274 info << "media file copying from " << from << " to " << to << endmsg;
4276 if (!copy_file (from, to)) {
4277 throw Glib::FileError (Glib::FileError::IO_ERROR,
4278 string_compose(_("\ncopying \"%1\" failed !"), from));
4282 /* we found media files inside the session folder */
4284 internal_file_cnt++;
4286 } else if (from.find (midifile_dir_string) != string::npos) {
4288 /* midi file: always copy unless
4289 * creating an empty new session
4292 if (saveas.include_media) {
4294 string to = make_new_media_path (*i, to_dir, new_folder);
4296 info << "media file copying from " << from << " to " << to << endmsg;
4298 if (!copy_file (from, to)) {
4299 throw Glib::FileError (Glib::FileError::IO_ERROR, "copy failed");
4303 /* we found media files inside the session folder */
4305 internal_file_cnt++;
4307 } else if (from.find (analysis_dir_string) != string::npos) {
4309 /* make sure analysis dir exists in
4310 * new session folder, but we're not
4311 * copying analysis files here, see
4315 (void) g_mkdir_with_parents (analysis_dir().c_str(), 775);
4320 /* normal non-media file. Don't copy state, history, etc.
4323 bool do_copy = true;
4325 for (vector<string>::iterator v = do_not_copy_extensions.begin(); v != do_not_copy_extensions.end(); ++v) {
4326 if ((from.length() > (*v).length()) && (from.find (*v) == from.length() - (*v).length())) {
4327 /* end of filename matches extension, do not copy file */
4333 if (!saveas.copy_media && from.find (peakfile_suffix) != string::npos) {
4334 /* don't copy peakfiles if
4335 * we're not copying media
4341 string to = Glib::build_filename (to_dir, from.substr (prefix_len));
4343 info << "attempting to make directory/folder " << to << endmsg;
4345 if (g_mkdir_with_parents (Glib::path_get_dirname (to).c_str(), 0755)) {
4346 throw Glib::FileError (Glib::FileError::IO_ERROR, "cannot create required directory");
4349 info << "attempting to copy " << from << " to " << to << endmsg;
4351 if (!copy_file (from, to)) {
4352 throw Glib::FileError (Glib::FileError::IO_ERROR,
4353 string_compose(_("\ncopying \"%1\" failed !"), from));
4358 /* measure file size even if we're not going to copy so that our Progress
4359 signals are correct, since we included these do-not-copy files
4360 in the computation of the total size and file count.
4364 g_stat (from.c_str(), &gsb);
4365 copied += gsb.st_size;
4368 double fraction = (double) copied / total_bytes;
4370 bool keep_going = true;
4372 if (saveas.copy_media) {
4374 /* no need or expectation of this if
4375 * media is not being copied, because
4376 * it will be fast(ish).
4379 /* tell someone "X percent, file M of N"; M is one-based */
4381 boost::optional<bool> res = saveas.Progress (fraction, cnt, all);
4389 throw Glib::FileError (Glib::FileError::FAILED, "copy cancelled");
4395 /* copy optional folders, if any */
4397 string old = plugins_dir ();
4398 if (Glib::file_test (old, Glib::FILE_TEST_EXISTS)) {
4399 string newdir = Glib::build_filename (to_dir, Glib::path_get_basename (old));
4400 copy_files (old, newdir);
4403 old = externals_dir ();
4404 if (Glib::file_test (old, Glib::FILE_TEST_EXISTS)) {
4405 string newdir = Glib::build_filename (to_dir, Glib::path_get_basename (old));
4406 copy_files (old, newdir);
4409 old = automation_dir ();
4410 if (Glib::file_test (old, Glib::FILE_TEST_EXISTS)) {
4411 string newdir = Glib::build_filename (to_dir, Glib::path_get_basename (old));
4412 copy_files (old, newdir);
4415 if (saveas.include_media) {
4417 if (saveas.copy_media) {
4418 #ifndef PLATFORM_WINDOWS
4419 /* There are problems with analysis files on
4420 * Windows, because they used a colon in their
4421 * names as late as 4.0. Colons are not legal
4422 * under Windows even if NTFS allows them.
4424 * This is a tricky problem to solve so for
4425 * just don't copy these files. They will be
4426 * regenerated as-needed anyway, subject to the
4427 * existing issue that the filenames will be
4428 * rejected by Windows, which is a separate
4429 * problem (though related).
4432 /* only needed if we are copying media, since the
4433 * analysis data refers to media data
4436 old = analysis_dir ();
4437 if (Glib::file_test (old, Glib::FILE_TEST_EXISTS)) {
4438 string newdir = Glib::build_filename (to_dir, "analysis");
4439 copy_files (old, newdir);
4441 #endif /* PLATFORM_WINDOWS */
4447 _current_snapshot_name = saveas.new_name;
4448 _name = saveas.new_name;
4450 if (saveas.include_media && !saveas.copy_media) {
4452 /* reset search paths of the new session (which we're pretending to be right now) to
4453 include the original session search path, so we can still find all audio.
4456 if (internal_file_cnt) {
4457 for (vector<string>::iterator s = old_search_path[DataType::AUDIO].begin(); s != old_search_path[DataType::AUDIO].end(); ++s) {
4458 ensure_search_path_includes (*s, DataType::AUDIO);
4459 cerr << "be sure to include " << *s << " for audio" << endl;
4462 /* we do not do this for MIDI because we copy
4463 all MIDI files if saveas.include_media is
4469 bool was_dirty = dirty ();
4471 save_state ("", false, false, !saveas.include_media);
4472 save_default_options ();
4474 if (saveas.copy_media && saveas.copy_external) {
4475 if (bring_all_sources_into_session (boost::bind (&Session::save_as_bring_callback, this, _1, _2, _3))) {
4476 throw Glib::FileError (Glib::FileError::NO_SPACE_LEFT, "consolidate failed");
4480 saveas.final_session_folder_name = _path;
4482 store_recent_sessions (_name, _path);
4484 if (!saveas.switch_to) {
4486 /* switch back to the way things were */
4490 _current_snapshot_name = old_snapshot;
4492 (*_session_dir) = old_sd;
4498 if (internal_file_cnt) {
4499 /* reset these to their original values */
4500 config.set_audio_search_path (old_config_search_path[DataType::AUDIO]);
4501 config.set_midi_search_path (old_config_search_path[DataType::MIDI]);
4506 /* prune session dirs, and update disk space statistics
4511 session_dirs.clear ();
4512 session_dirs.push_back (sp);
4513 refresh_disk_space ();
4515 /* ensure that all existing tracks reset their current capture source paths
4517 reset_write_sources (true, true);
4519 /* the copying above was based on actually discovering files, not just iterating over the sources list.
4520 But if we're going to switch to the new (copied) session, we need to change the paths in the sources also.
4523 for (SourceMap::const_iterator i = sources.begin(); i != sources.end(); ++i) {
4524 boost::shared_ptr<FileSource> fs = boost::dynamic_pointer_cast<FileSource> (i->second);
4530 if (fs->within_session()) {
4531 string newpath = make_new_media_path (fs->path(), to_dir, new_folder);
4532 fs->set_path (newpath);
4537 } catch (Glib::FileError& e) {
4539 saveas.failure_message = e.what();
4541 /* recursively remove all the directories */
4543 remove_directory (to_dir);
4551 saveas.failure_message = _("unknown reason");
4553 /* recursively remove all the directories */
4555 remove_directory (to_dir);