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"
30 #include <cstdio> /* snprintf(3) ... grrr */
42 #include <sys/param.h>
43 #include <sys/mount.h>
46 #ifdef HAVE_SYS_STATVFS_H
47 #include <sys/statvfs.h>
51 #include "pbd/gstdio_compat.h"
54 #include <glibmm/threads.h>
55 #include <glibmm/fileutils.h>
57 #include <boost/algorithm/string.hpp>
59 #include "midi++/mmc.h"
60 #include "midi++/port.h"
62 #include "evoral/SMF.hpp"
64 #include "pbd/basename.h"
65 #include "pbd/controllable_descriptor.h"
66 #include "pbd/debug.h"
67 #include "pbd/enumwriter.h"
68 #include "pbd/error.h"
69 #include "pbd/file_utils.h"
70 #include "pbd/pathexpand.h"
71 #include "pbd/pthread_utils.h"
72 #include "pbd/stacktrace.h"
73 #include "pbd/convert.h"
74 #include "pbd/localtime_r.h"
75 #include "pbd/unwind.h"
77 #include "ardour/amp.h"
78 #include "ardour/async_midi_port.h"
79 #include "ardour/audio_diskstream.h"
80 #include "ardour/audio_track.h"
81 #include "ardour/audioengine.h"
82 #include "ardour/audiofilesource.h"
83 #include "ardour/audioregion.h"
84 #include "ardour/automation_control.h"
85 #include "ardour/boost_debug.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"
122 #include "ardour/vca.h"
123 #include "ardour/vca_manager.h"
125 #include "control_protocol/control_protocol.h"
127 #include "LuaBridge/LuaBridge.h"
133 using namespace ARDOUR;
136 #define DEBUG_UNDO_HISTORY(msg) DEBUG_TRACE (PBD::DEBUG::UndoHistory, string_compose ("%1: %2\n", __LINE__, msg));
139 Session::pre_engine_init (string fullpath)
141 if (fullpath.empty()) {
143 throw failed_constructor();
146 /* discover canonical fullpath */
148 _path = canonical_path(fullpath);
151 if (Profile->get_trx() ) {
152 // Waves TracksLive has a usecase of session replacement with a new one.
153 // We should check session state file (<session_name>.ardour) existance
154 // to determine if the session is new or not
156 string full_session_name = Glib::build_filename( fullpath, _name );
157 full_session_name += statefile_suffix;
159 _is_new = !Glib::file_test (full_session_name, Glib::FileTest (G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR));
161 _is_new = !Glib::file_test (_path, Glib::FileTest (G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR));
164 /* finish initialization that can't be done in a normal C++ constructor
168 timerclear (&last_mmc_step);
169 g_atomic_int_set (&processing_prohibited, 0);
170 g_atomic_int_set (&_record_status, Disabled);
171 g_atomic_int_set (&_playback_load, 100);
172 g_atomic_int_set (&_capture_load, 100);
174 _all_route_group->set_active (true, this);
175 interpolation.add_channel_to (0, 0);
176 _vca_manager = new VCAManager (*this);
178 if (config.get_use_video_sync()) {
179 waiting_for_sync_offset = true;
181 waiting_for_sync_offset = false;
184 last_rr_session_dir = session_dirs.begin();
186 set_history_depth (Config->get_history_depth());
188 /* default: assume simple stereo speaker configuration */
190 _speakers->setup_default_speakers (2);
192 _solo_cut_control.reset (new ProxyControllable (_("solo cut control (dB)"), PBD::Controllable::GainLike,
193 boost::bind (&RCConfiguration::set_solo_mute_gain, Config, _1),
194 boost::bind (&RCConfiguration::get_solo_mute_gain, Config)));
195 add_controllable (_solo_cut_control);
197 /* These are all static "per-class" signals */
199 SourceFactory::SourceCreated.connect_same_thread (*this, boost::bind (&Session::add_source, this, _1));
200 PlaylistFactory::PlaylistCreated.connect_same_thread (*this, boost::bind (&Session::add_playlist, this, _1, _2));
201 AutomationList::AutomationListCreated.connect_same_thread (*this, boost::bind (&Session::add_automation_list, this, _1));
202 Controllable::Destroyed.connect_same_thread (*this, boost::bind (&Session::remove_controllable, this, _1));
203 IO::PortCountChanged.connect_same_thread (*this, boost::bind (&Session::ensure_buffers, this, _1));
205 /* stop IO objects from doing stuff until we're ready for them */
207 Delivery::disable_panners ();
208 IO::disable_connecting ();
212 Session::post_engine_init ()
214 BootMessage (_("Set block size and sample rate"));
216 set_block_size (_engine.samples_per_cycle());
217 set_frame_rate (_engine.sample_rate());
219 BootMessage (_("Using configuration"));
221 _midi_ports = new MidiPortManager;
223 MIDISceneChanger* msc;
225 _scene_changer = msc = new MIDISceneChanger (*this);
226 msc->set_input_port (boost::dynamic_pointer_cast<MidiPort>(scene_input_port()));
227 msc->set_output_port (boost::dynamic_pointer_cast<MidiPort>(scene_output_port()));
229 boost::function<framecnt_t(void)> timer_func (boost::bind (&Session::audible_frame, this));
230 boost::dynamic_pointer_cast<AsyncMIDIPort>(scene_input_port())->set_timer (timer_func);
232 setup_midi_machine_control ();
234 if (_butler->start_thread()) {
238 if (start_midi_thread ()) {
242 setup_click_sounds (0);
243 setup_midi_control ();
245 _engine.Halted.connect_same_thread (*this, boost::bind (&Session::engine_halted, this));
246 _engine.Xrun.connect_same_thread (*this, boost::bind (&Session::xrun_recovery, this));
249 /* tempo map requires sample rate knowledge */
252 _tempo_map = new TempoMap (_current_frame_rate);
253 _tempo_map->PropertyChanged.connect_same_thread (*this, boost::bind (&Session::tempo_map_changed, this, _1));
254 _tempo_map->MetricPositionChanged.connect_same_thread (*this, boost::bind (&Session::gui_tempo_map_changed, this));
256 /* MidiClock requires a tempo map */
259 midi_clock = new MidiClockTicker ();
260 midi_clock->set_session (this);
262 /* crossfades require sample rate knowledge */
264 SndFileSource::setup_standard_crossfades (*this, frame_rate());
265 _engine.GraphReordered.connect_same_thread (*this, boost::bind (&Session::graph_reordered, this));
267 AudioDiskstream::allocate_working_buffers();
268 refresh_disk_space ();
270 /* we're finally ready to call set_state() ... all objects have
271 * been created, the engine is running.
275 if (set_state (*state_tree->root(), Stateful::loading_state_version)) {
279 // set_state() will call setup_raid_path(), but if it's a new session we need
280 // to call setup_raid_path() here.
281 setup_raid_path (_path);
286 boost::function<void (std::string)> ff (boost::bind (&Session::config_changed, this, _1, false));
287 boost::function<void (std::string)> ft (boost::bind (&Session::config_changed, this, _1, true));
289 Config->map_parameters (ff);
290 config.map_parameters (ft);
291 _butler->map_parameters ();
293 /* Reset all panners */
295 Delivery::reset_panners ();
297 /* this will cause the CPM to instantiate any protocols that are in use
298 * (or mandatory), which will pass it this Session, and then call
299 * set_state() on each instantiated protocol to match stored state.
302 ControlProtocolManager::instance().set_session (this);
304 /* This must be done after the ControlProtocolManager set_session above,
305 as it will set states for ports which the ControlProtocolManager creates.
308 // XXX set state of MIDI::Port's
309 // MidiPortManager::instance()->set_port_states (Config->midi_port_states ());
311 /* And this must be done after the MIDI::Manager::set_port_states as
312 * it will try to make connections whose details are loaded by set_port_states.
317 /* Let control protocols know that we are now all connected, so they
318 * could start talking to surfaces if they want to.
321 ControlProtocolManager::instance().midi_connectivity_established ();
323 if (_is_new && !no_auto_connect()) {
324 Glib::Threads::Mutex::Lock lm (AudioEngine::instance()->process_lock());
325 auto_connect_master_bus ();
328 _state_of_the_state = StateOfTheState (_state_of_the_state & ~(CannotSave|Dirty));
330 /* update latencies */
332 initialize_latencies ();
334 _locations->added.connect_same_thread (*this, boost::bind (&Session::location_added, this, _1));
335 _locations->removed.connect_same_thread (*this, boost::bind (&Session::location_removed, this, _1));
336 _locations->changed.connect_same_thread (*this, boost::bind (&Session::locations_changed, this));
338 } catch (AudioEngine::PortRegistrationFailure& err) {
339 /* handle this one in a different way than all others, so that its clear what happened */
340 error << err.what() << endmsg;
346 BootMessage (_("Reset Remote Controls"));
348 // send_full_time_code (0);
349 _engine.transport_locate (0);
351 send_immediate_mmc (MIDI::MachineControlCommand (MIDI::MachineControl::cmdMmcReset));
352 send_immediate_mmc (MIDI::MachineControlCommand (Timecode::Time ()));
354 MIDI::Name::MidiPatchManager::instance().add_search_path (session_directory().midi_patch_path() );
357 /* initial program change will be delivered later; see ::config_changed() */
359 _state_of_the_state = Clean;
361 Port::set_connecting_blocked (false);
363 DirtyChanged (); /* EMIT SIGNAL */
367 } else if (state_was_pending) {
369 remove_pending_capture_state ();
370 state_was_pending = false;
373 /* Now, finally, we can fill the playback buffers */
375 BootMessage (_("Filling playback buffers"));
377 boost::shared_ptr<RouteList> rl = routes.reader();
378 for (RouteList::iterator r = rl->begin(); r != rl->end(); ++r) {
379 boost::shared_ptr<Track> trk = boost::dynamic_pointer_cast<Track> (*r);
380 if (trk && !trk->hidden()) {
381 trk->seek (_transport_frame, true);
389 Session::session_loaded ()
393 _state_of_the_state = Clean;
395 DirtyChanged (); /* EMIT SIGNAL */
399 } else if (state_was_pending) {
401 remove_pending_capture_state ();
402 state_was_pending = false;
405 /* Now, finally, we can fill the playback buffers */
407 BootMessage (_("Filling playback buffers"));
408 force_locate (_transport_frame, false);
412 Session::raid_path () const
414 Searchpath raid_search_path;
416 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
417 raid_search_path += (*i).path;
420 return raid_search_path.to_string ();
424 Session::setup_raid_path (string path)
433 session_dirs.clear ();
435 Searchpath search_path(path);
436 Searchpath sound_search_path;
437 Searchpath midi_search_path;
439 for (Searchpath::const_iterator i = search_path.begin(); i != search_path.end(); ++i) {
441 sp.blocks = 0; // not needed
442 session_dirs.push_back (sp);
444 SessionDirectory sdir(sp.path);
446 sound_search_path += sdir.sound_path ();
447 midi_search_path += sdir.midi_path ();
450 // reset the round-robin soundfile path thingie
451 last_rr_session_dir = session_dirs.begin();
455 Session::path_is_within_session (const std::string& path)
457 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
458 if (PBD::path_is_within (i->path, path)) {
466 Session::ensure_subdirs ()
470 dir = session_directory().peak_path();
472 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
473 error << string_compose(_("Session: cannot create session peakfile folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
477 dir = session_directory().sound_path();
479 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
480 error << string_compose(_("Session: cannot create session sounds dir \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
484 dir = session_directory().midi_path();
486 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
487 error << string_compose(_("Session: cannot create session midi dir \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
491 dir = session_directory().dead_path();
493 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
494 error << string_compose(_("Session: cannot create session dead sounds folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
498 dir = session_directory().export_path();
500 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
501 error << string_compose(_("Session: cannot create session export folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
505 dir = analysis_dir ();
507 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
508 error << string_compose(_("Session: cannot create session analysis folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
512 dir = plugins_dir ();
514 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
515 error << string_compose(_("Session: cannot create session plugins folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
519 dir = externals_dir ();
521 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
522 error << string_compose(_("Session: cannot create session externals folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
529 /** @param session_template directory containing session template, or empty.
530 * Caller must not hold process lock.
533 Session::create (const string& session_template, BusProfile* bus_profile)
535 if (g_mkdir_with_parents (_path.c_str(), 0755) < 0) {
536 error << string_compose(_("Session: cannot create session folder \"%1\" (%2)"), _path, strerror (errno)) << endmsg;
540 if (ensure_subdirs ()) {
544 _writable = exists_and_writable (_path);
546 if (!session_template.empty()) {
547 string in_path = (ARDOUR::Profile->get_trx () ? session_template : session_template_dir_to_file (session_template));
549 FILE* in = g_fopen (in_path.c_str(), "rb");
552 /* no need to call legalize_for_path() since the string
553 * in session_template is already a legal path name
555 string out_path = Glib::build_filename (_session_dir->root_path(), _name + statefile_suffix);
557 FILE* out = g_fopen (out_path.c_str(), "wb");
561 stringstream new_session;
564 size_t charsRead = fread (buf, sizeof(char), 1024, in);
567 error << string_compose (_("Error reading session template file %1 (%2)"), in_path, strerror (errno)) << endmsg;
572 if (charsRead == 0) {
575 new_session.write (buf, charsRead);
579 string file_contents = new_session.str();
580 size_t writeSize = file_contents.length();
581 if (fwrite (file_contents.c_str(), sizeof(char), writeSize, out) != writeSize) {
582 error << string_compose (_("Error writing session template file %1 (%2)"), out_path, strerror (errno)) << endmsg;
590 if (!ARDOUR::Profile->get_trx()) {
591 /* Copy plugin state files from template to new session */
592 std::string template_plugins = Glib::build_filename (session_template, X_("plugins"));
593 copy_recurse (template_plugins, plugins_dir ());
599 error << string_compose (_("Could not open %1 for writing session template"), out_path)
606 error << string_compose (_("Could not open session template %1 for reading"), in_path)
613 if (Profile->get_trx()) {
615 /* set initial start + end point : ARDOUR::Session::session_end_shift long.
616 Remember that this is a brand new session. Sessions
617 loaded from saved state will get this range from the saved state.
620 set_session_range_location (0, 0);
622 /* Initial loop location, from absolute zero, length 10 seconds */
624 Location* loc = new Location (*this, 0, 10.0 * _engine.sample_rate(), _("Loop"), Location::IsAutoLoop);
625 _locations->add (loc, true);
626 set_auto_loop_location (loc);
629 _state_of_the_state = Clean;
631 /* set up Master Out and Monitor Out if necessary */
636 ChanCount count(DataType::AUDIO, bus_profile->master_out_channels);
638 // Waves Tracks: always create master bus for Tracks
639 if (ARDOUR::Profile->get_trx() || bus_profile->master_out_channels) {
640 boost::shared_ptr<Route> r (new Route (*this, _("Master"), PresentationInfo::MasterOut, DataType::AUDIO));
648 Glib::Threads::Mutex::Lock lm (AudioEngine::instance()->process_lock ());
649 r->input()->ensure_io (count, false, this);
650 r->output()->ensure_io (count, false, this);
656 /* prohibit auto-connect to master, because there isn't one */
657 bus_profile->output_ac = AutoConnectOption (bus_profile->output_ac & ~AutoConnectMaster);
661 add_routes (rl, false, false, false, PresentationInfo::max_order);
664 // Waves Tracks: Skip this. Always use autoconnection for Tracks
665 if (!ARDOUR::Profile->get_trx()) {
667 /* this allows the user to override settings with an environment variable.
670 if (no_auto_connect()) {
671 bus_profile->input_ac = AutoConnectOption (0);
672 bus_profile->output_ac = AutoConnectOption (0);
675 Config->set_input_auto_connect (bus_profile->input_ac);
676 Config->set_output_auto_connect (bus_profile->output_ac);
680 if (Config->get_use_monitor_bus() && bus_profile) {
681 add_monitor_section ();
688 Session::maybe_write_autosave()
690 if (dirty() && record_status() != Recording) {
691 save_state("", true);
696 Session::remove_pending_capture_state ()
698 std::string pending_state_file_path(_session_dir->root_path());
700 pending_state_file_path = Glib::build_filename (pending_state_file_path, legalize_for_path (_current_snapshot_name) + pending_suffix);
702 if (!Glib::file_test (pending_state_file_path, Glib::FILE_TEST_EXISTS)) return;
704 if (g_remove (pending_state_file_path.c_str()) != 0) {
705 error << string_compose(_("Could not remove pending capture state at path \"%1\" (%2)"),
706 pending_state_file_path, g_strerror (errno)) << endmsg;
710 /** Rename a state file.
711 * @param old_name Old snapshot name.
712 * @param new_name New snapshot name.
715 Session::rename_state (string old_name, string new_name)
717 if (old_name == _current_snapshot_name || old_name == _name) {
718 /* refuse to rename the current snapshot or the "main" one */
722 const string old_xml_filename = legalize_for_path (old_name) + statefile_suffix;
723 const string new_xml_filename = legalize_for_path (new_name) + statefile_suffix;
725 const std::string old_xml_path(Glib::build_filename (_session_dir->root_path(), old_xml_filename));
726 const std::string new_xml_path(Glib::build_filename (_session_dir->root_path(), new_xml_filename));
728 if (::g_rename (old_xml_path.c_str(), new_xml_path.c_str()) != 0) {
729 error << string_compose(_("could not rename snapshot %1 to %2 (%3)"),
730 old_name, new_name, g_strerror(errno)) << endmsg;
734 /** Remove a state file.
735 * @param snapshot_name Snapshot name.
738 Session::remove_state (string snapshot_name)
740 if (!_writable || snapshot_name == _current_snapshot_name || snapshot_name == _name) {
741 // refuse to remove the current snapshot or the "main" one
745 std::string xml_path(_session_dir->root_path());
747 xml_path = Glib::build_filename (xml_path, legalize_for_path (snapshot_name) + statefile_suffix);
749 if (!create_backup_file (xml_path)) {
750 // don't remove it if a backup can't be made
751 // create_backup_file will log the error.
756 if (g_remove (xml_path.c_str()) != 0) {
757 error << string_compose(_("Could not remove session file at path \"%1\" (%2)"),
758 xml_path, g_strerror (errno)) << endmsg;
762 /** @param snapshot_name Name to save under, without .ardour / .pending prefix */
764 Session::save_state (string snapshot_name, bool pending, bool switch_to_snapshot, bool template_only)
766 DEBUG_TRACE (DEBUG::Locale, string_compose ("Session::save_state locale '%1'\n", setlocale (LC_NUMERIC, NULL)));
769 std::string xml_path(_session_dir->root_path());
771 /* prevent concurrent saves from different threads */
773 Glib::Threads::Mutex::Lock lm (save_state_lock);
775 if (!_writable || (_state_of_the_state & CannotSave)) {
779 if (g_atomic_int_get(&_suspend_save)) {
783 _save_queued = false;
785 if (!_engine.connected ()) {
786 error << string_compose (_("the %1 audio engine is not connected and state saving would lose all I/O connections. Session not saved"),
793 const int64_t save_start_time = g_get_monotonic_time();
796 /* tell sources we're saving first, in case they write out to a new file
797 * which should be saved with the state rather than the old one */
798 for (SourceMap::const_iterator i = sources.begin(); i != sources.end(); ++i) {
800 i->second->session_saved();
801 } catch (Evoral::SMF::FileError& e) {
802 error << string_compose ("Could not write to MIDI file %1; MIDI data not saved.", e.file_name ()) << endmsg;
806 SessionSaveUnderway (); /* EMIT SIGNAL */
808 bool mark_as_clean = true;
810 if (!snapshot_name.empty() && !switch_to_snapshot) {
811 mark_as_clean = false;
815 mark_as_clean = false;
816 tree.set_root (&get_template());
818 tree.set_root (&get_state());
821 if (snapshot_name.empty()) {
822 snapshot_name = _current_snapshot_name;
823 } else if (switch_to_snapshot) {
824 set_snapshot_name (snapshot_name);
827 assert (!snapshot_name.empty());
831 /* proper save: use statefile_suffix (.ardour in English) */
833 xml_path = Glib::build_filename (xml_path, legalize_for_path (snapshot_name) + statefile_suffix);
835 /* make a backup copy of the old file */
837 if (Glib::file_test (xml_path, Glib::FILE_TEST_EXISTS) && !create_backup_file (xml_path)) {
838 // create_backup_file will log the error
844 /* pending save: use pending_suffix (.pending in English) */
845 xml_path = Glib::build_filename (xml_path, legalize_for_path (snapshot_name) + pending_suffix);
848 std::string tmp_path(_session_dir->root_path());
849 tmp_path = Glib::build_filename (tmp_path, legalize_for_path (snapshot_name) + temp_suffix);
851 cerr << "actually writing state to " << tmp_path << endl;
853 if (!tree.write (tmp_path)) {
854 error << string_compose (_("state could not be saved to %1"), tmp_path) << endmsg;
855 if (g_remove (tmp_path.c_str()) != 0) {
856 error << string_compose(_("Could not remove temporary session file at path \"%1\" (%2)"),
857 tmp_path, g_strerror (errno)) << endmsg;
863 cerr << "renaming state to " << xml_path << endl;
865 if (::g_rename (tmp_path.c_str(), xml_path.c_str()) != 0) {
866 error << string_compose (_("could not rename temporary session file %1 to %2 (%3)"),
867 tmp_path, xml_path, g_strerror(errno)) << endmsg;
868 if (g_remove (tmp_path.c_str()) != 0) {
869 error << string_compose(_("Could not remove temporary session file at path \"%1\" (%2)"),
870 tmp_path, g_strerror (errno)) << endmsg;
878 save_history (snapshot_name);
881 bool was_dirty = dirty();
883 _state_of_the_state = StateOfTheState (_state_of_the_state & ~Dirty);
886 DirtyChanged (); /* EMIT SIGNAL */
890 StateSaved (snapshot_name); /* EMIT SIGNAL */
894 const int64_t elapsed_time_us = g_get_monotonic_time() - save_start_time;
895 cerr << "saved state in " << fixed << setprecision (1) << elapsed_time_us / 1000. << " ms\n";
901 Session::restore_state (string snapshot_name)
903 if (load_state (snapshot_name) == 0) {
904 set_state (*state_tree->root(), Stateful::loading_state_version);
911 Session::load_state (string snapshot_name)
916 state_was_pending = false;
918 /* check for leftover pending state from a crashed capture attempt */
920 std::string xmlpath(_session_dir->root_path());
921 xmlpath = Glib::build_filename (xmlpath, legalize_for_path (snapshot_name) + pending_suffix);
923 if (Glib::file_test (xmlpath, Glib::FILE_TEST_EXISTS)) {
925 /* there is pending state from a crashed capture attempt */
927 boost::optional<int> r = AskAboutPendingState();
928 if (r.get_value_or (1)) {
929 state_was_pending = true;
933 if (!state_was_pending) {
934 xmlpath = Glib::build_filename (_session_dir->root_path(), snapshot_name);
937 if (!Glib::file_test (xmlpath, Glib::FILE_TEST_EXISTS)) {
938 xmlpath = Glib::build_filename (_session_dir->root_path(), legalize_for_path (snapshot_name) + statefile_suffix);
939 if (!Glib::file_test (xmlpath, Glib::FILE_TEST_EXISTS)) {
940 error << string_compose(_("%1: session file \"%2\" doesn't exist!"), _name, xmlpath) << endmsg;
945 state_tree = new XMLTree;
949 _writable = exists_and_writable (xmlpath) && exists_and_writable(Glib::path_get_dirname(xmlpath));
951 if (!state_tree->read (xmlpath)) {
952 error << string_compose(_("Could not understand session file %1"), xmlpath) << endmsg;
958 XMLNode const & root (*state_tree->root());
960 if (root.name() != X_("Session")) {
961 error << string_compose (_("Session file %1 is not a session"), xmlpath) << endmsg;
967 XMLProperty const * prop;
969 if ((prop = root.property ("version")) == 0) {
970 /* no version implies very old version of Ardour */
971 Stateful::loading_state_version = 1000;
973 if (prop->value().find ('.') != string::npos) {
974 /* old school version format */
975 if (prop->value()[0] == '2') {
976 Stateful::loading_state_version = 2000;
978 Stateful::loading_state_version = 3000;
981 Stateful::loading_state_version = atoi (prop->value());
985 if (Stateful::loading_state_version < CURRENT_SESSION_FILE_VERSION && _writable) {
987 std::string backup_path(_session_dir->root_path());
988 std::string backup_filename = string_compose ("%1-%2%3", legalize_for_path (snapshot_name), Stateful::loading_state_version, statefile_suffix);
989 backup_path = Glib::build_filename (backup_path, backup_filename);
991 // only create a backup for a given statefile version once
993 if (!Glib::file_test (backup_path, Glib::FILE_TEST_EXISTS)) {
995 VersionMismatch (xmlpath, backup_path);
997 if (!copy_file (xmlpath, backup_path)) {;
1003 save_snapshot_name (snapshot_name);
1009 Session::load_options (const XMLNode& node)
1012 config.set_variables (node);
1017 Session::save_default_options ()
1019 return config.save_state();
1023 Session::get_state()
1029 Session::get_template()
1031 /* if we don't disable rec-enable, diskstreams
1032 will believe they need to store their capture
1033 sources in their state node.
1036 disable_record (false);
1038 return state(false);
1042 Session::state (bool full_state)
1045 XMLNode* node = new XMLNode("Session");
1049 snprintf(buf, sizeof(buf), "%d", CURRENT_SESSION_FILE_VERSION);
1050 node->add_property("version", buf);
1052 /* store configuration settings */
1056 node->add_property ("name", _name);
1057 snprintf (buf, sizeof (buf), "%" PRId64, _base_frame_rate);
1058 node->add_property ("sample-rate", buf);
1060 if (session_dirs.size() > 1) {
1064 vector<space_and_path>::iterator i = session_dirs.begin();
1065 vector<space_and_path>::iterator next;
1067 ++i; /* skip the first one */
1071 while (i != session_dirs.end()) {
1075 if (next != session_dirs.end()) {
1076 p += G_SEARCHPATH_SEPARATOR;
1085 child = node->add_child ("Path");
1086 child->add_content (p);
1090 /* save the ID counter */
1092 snprintf (buf, sizeof (buf), "%" PRIu64, ID::counter());
1093 node->add_property ("id-counter", buf);
1095 snprintf (buf, sizeof (buf), "%u", name_id_counter ());
1096 node->add_property ("name-counter", buf);
1098 /* save the event ID counter */
1100 snprintf (buf, sizeof (buf), "%d", Evoral::event_id_counter());
1101 node->add_property ("event-counter", buf);
1103 /* save the VCA counter */
1105 snprintf (buf, sizeof (buf), "%" PRIu32, VCA::get_next_vca_number());
1106 node->add_property ("vca-counter", buf);
1108 /* various options */
1110 list<XMLNode*> midi_port_nodes = _midi_ports->get_midi_port_states();
1111 if (!midi_port_nodes.empty()) {
1112 XMLNode* midi_port_stuff = new XMLNode ("MIDIPorts");
1113 for (list<XMLNode*>::const_iterator n = midi_port_nodes.begin(); n != midi_port_nodes.end(); ++n) {
1114 midi_port_stuff->add_child_nocopy (**n);
1116 node->add_child_nocopy (*midi_port_stuff);
1119 node->add_child_nocopy (config.get_variables ());
1121 node->add_child_nocopy (ARDOUR::SessionMetadata::Metadata()->get_state());
1123 child = node->add_child ("Sources");
1126 Glib::Threads::Mutex::Lock sl (source_lock);
1128 for (SourceMap::iterator siter = sources.begin(); siter != sources.end(); ++siter) {
1130 /* Don't save information about non-file Sources, or
1131 * about non-destructive file sources that are empty
1132 * and unused by any regions.
1135 boost::shared_ptr<FileSource> fs;
1137 if ((fs = boost::dynamic_pointer_cast<FileSource> (siter->second)) != 0) {
1139 if (!fs->destructive()) {
1140 if (fs->empty() && !fs->used()) {
1145 child->add_child_nocopy (siter->second->get_state());
1150 child = node->add_child ("Regions");
1153 Glib::Threads::Mutex::Lock rl (region_lock);
1154 const RegionFactory::RegionMap& region_map (RegionFactory::all_regions());
1155 for (RegionFactory::RegionMap::const_iterator i = region_map.begin(); i != region_map.end(); ++i) {
1156 boost::shared_ptr<Region> r = i->second;
1157 /* only store regions not attached to playlists */
1158 if (r->playlist() == 0) {
1159 if (boost::dynamic_pointer_cast<AudioRegion>(r)) {
1160 child->add_child_nocopy ((boost::dynamic_pointer_cast<AudioRegion>(r))->get_basic_state ());
1162 child->add_child_nocopy (r->get_state ());
1167 RegionFactory::CompoundAssociations& cassocs (RegionFactory::compound_associations());
1169 if (!cassocs.empty()) {
1170 XMLNode* ca = node->add_child (X_("CompoundAssociations"));
1172 for (RegionFactory::CompoundAssociations::iterator i = cassocs.begin(); i != cassocs.end(); ++i) {
1174 XMLNode* can = new XMLNode (X_("CompoundAssociation"));
1175 i->first->id().print (buf, sizeof (buf));
1176 can->add_property (X_("copy"), buf);
1177 i->second->id().print (buf, sizeof (buf));
1178 can->add_property (X_("original"), buf);
1179 ca->add_child_nocopy (*can);
1189 node->add_child_nocopy (_locations->get_state());
1192 Locations loc (*this);
1193 // for a template, just create a new Locations, populate it
1194 // with the default start and end, and get the state for that.
1195 Location* range = new Location (*this, 0, 0, _("session"), Location::IsSessionRange);
1196 range->set (max_framepos, 0);
1198 XMLNode& locations_state = loc.get_state();
1200 if (ARDOUR::Profile->get_trx() && _locations) {
1201 // For tracks we need stored the Auto Loop Range and all MIDI markers.
1202 for (Locations::LocationList::const_iterator i = _locations->list ().begin (); i != _locations->list ().end (); ++i) {
1203 if ((*i)->is_mark () || (*i)->is_auto_loop ()) {
1204 locations_state.add_child_nocopy ((*i)->get_state ());
1208 node->add_child_nocopy (locations_state);
1211 child = node->add_child ("Bundles");
1213 boost::shared_ptr<BundleList> bundles = _bundles.reader ();
1214 for (BundleList::iterator i = bundles->begin(); i != bundles->end(); ++i) {
1215 boost::shared_ptr<UserBundle> b = boost::dynamic_pointer_cast<UserBundle> (*i);
1217 child->add_child_nocopy (b->get_state());
1222 node->add_child_nocopy (_vca_manager->get_state());
1224 child = node->add_child ("Routes");
1226 boost::shared_ptr<RouteList> r = routes.reader ();
1228 RoutePublicOrderSorter cmp;
1229 RouteList public_order (*r);
1230 public_order.sort (cmp);
1232 /* the sort should have put control outs first */
1235 assert (_monitor_out == public_order.front());
1238 for (RouteList::iterator i = public_order.begin(); i != public_order.end(); ++i) {
1239 if (!(*i)->is_auditioner()) {
1241 child->add_child_nocopy ((*i)->get_state());
1243 child->add_child_nocopy ((*i)->get_template());
1249 playlists->add_state (node, full_state);
1251 child = node->add_child ("RouteGroups");
1252 for (list<RouteGroup *>::iterator i = _route_groups.begin(); i != _route_groups.end(); ++i) {
1253 child->add_child_nocopy ((*i)->get_state());
1257 XMLNode* gain_child = node->add_child ("Click");
1258 gain_child->add_child_nocopy (_click_io->state (full_state));
1259 gain_child->add_child_nocopy (_click_gain->state (full_state));
1263 XMLNode* ltc_input_child = node->add_child ("LTC-In");
1264 ltc_input_child->add_child_nocopy (_ltc_input->state (full_state));
1268 XMLNode* ltc_output_child = node->add_child ("LTC-Out");
1269 ltc_output_child->add_child_nocopy (_ltc_output->state (full_state));
1272 node->add_child_nocopy (_speakers->get_state());
1273 node->add_child_nocopy (_tempo_map->get_state());
1274 node->add_child_nocopy (get_control_protocol_state());
1277 node->add_child_copy (*_extra_xml);
1281 Glib::Threads::Mutex::Lock lm (lua_lock);
1284 luabridge::LuaRef savedstate ((*_lua_save)());
1285 saved = savedstate.cast<std::string>();
1287 lua.collect_garbage ();
1290 gchar* b64 = g_base64_encode ((const guchar*)saved.c_str (), saved.size ());
1291 std::string b64s (b64);
1294 XMLNode* script_node = new XMLNode (X_("Script"));
1295 script_node->add_property (X_("lua"), LUA_VERSION);
1296 script_node->add_content (b64s);
1297 node->add_child_nocopy (*script_node);
1304 Session::get_control_protocol_state ()
1306 ControlProtocolManager& cpm (ControlProtocolManager::instance());
1307 return cpm.get_state();
1311 Session::set_state (const XMLNode& node, int version)
1316 XMLProperty const * prop;
1319 _state_of_the_state = StateOfTheState (_state_of_the_state|CannotSave);
1321 if (node.name() != X_("Session")) {
1322 fatal << _("programming error: Session: incorrect XML node sent to set_state()") << endmsg;
1326 if ((prop = node.property ("name")) != 0) {
1327 _name = prop->value ();
1330 if ((prop = node.property (X_("sample-rate"))) != 0) {
1332 _base_frame_rate = atoi (prop->value());
1333 _nominal_frame_rate = _base_frame_rate;
1335 assert (AudioEngine::instance()->running ());
1336 if (_base_frame_rate != AudioEngine::instance()->sample_rate ()) {
1337 boost::optional<int> r = AskAboutSampleRateMismatch (_base_frame_rate, _current_frame_rate);
1338 if (r.get_value_or (0)) {
1344 setup_raid_path(_session_dir->root_path());
1346 if ((prop = node.property (X_("id-counter"))) != 0) {
1348 sscanf (prop->value().c_str(), "%" PRIu64, &x);
1349 ID::init_counter (x);
1351 /* old sessions used a timebased counter, so fake
1352 the startup ID counter based on a standard
1357 ID::init_counter (now);
1360 if ((prop = node.property (X_("name-counter"))) != 0) {
1361 init_name_id_counter (atoi (prop->value()));
1364 if ((prop = node.property (X_("event-counter"))) != 0) {
1365 Evoral::init_event_id_counter (atoi (prop->value()));
1368 if ((prop = node.property (X_("vca-counter"))) != 0) {
1370 sscanf (prop->value().c_str(), "%" PRIu32, &x);
1371 VCA::set_next_vca_number (x);
1373 VCA::set_next_vca_number (1);
1376 if ((child = find_named_node (node, "MIDIPorts")) != 0) {
1377 _midi_ports->set_midi_port_states (child->children());
1380 IO::disable_connecting ();
1382 Stateful::save_extra_xml (node);
1384 if (((child = find_named_node (node, "Options")) != 0)) { /* old style */
1385 load_options (*child);
1386 } else if ((child = find_named_node (node, "Config")) != 0) { /* new style */
1387 load_options (*child);
1389 error << _("Session: XML state has no options section") << endmsg;
1392 if (version >= 3000) {
1393 if ((child = find_named_node (node, "Metadata")) == 0) {
1394 warning << _("Session: XML state has no metadata section") << endmsg;
1395 } else if ( ARDOUR::SessionMetadata::Metadata()->set_state (*child, version) ) {
1400 if ((child = find_named_node (node, X_("Speakers"))) != 0) {
1401 _speakers->set_state (*child, version);
1404 if ((child = find_named_node (node, "Sources")) == 0) {
1405 error << _("Session: XML state has no sources section") << endmsg;
1407 } else if (load_sources (*child)) {
1411 if ((child = find_named_node (node, "TempoMap")) == 0) {
1412 error << _("Session: XML state has no Tempo Map section") << endmsg;
1414 } else if (_tempo_map->set_state (*child, version)) {
1418 if ((child = find_named_node (node, "Locations")) == 0) {
1419 error << _("Session: XML state has no locations section") << endmsg;
1421 } else if (_locations->set_state (*child, version)) {
1425 locations_changed ();
1427 if (_session_range_location) {
1428 AudioFileSource::set_header_position_offset (_session_range_location->start());
1431 if ((child = find_named_node (node, "Regions")) == 0) {
1432 error << _("Session: XML state has no Regions section") << endmsg;
1434 } else if (load_regions (*child)) {
1438 if ((child = find_named_node (node, "Playlists")) == 0) {
1439 error << _("Session: XML state has no playlists section") << endmsg;
1441 } else if (playlists->load (*this, *child)) {
1445 if ((child = find_named_node (node, "UnusedPlaylists")) == 0) {
1447 } else if (playlists->load_unused (*this, *child)) {
1451 if ((child = find_named_node (node, "CompoundAssociations")) != 0) {
1452 if (load_compounds (*child)) {
1457 if (version >= 3000) {
1458 if ((child = find_named_node (node, "Bundles")) == 0) {
1459 warning << _("Session: XML state has no bundles section") << endmsg;
1462 /* We can't load Bundles yet as they need to be able
1463 to convert from port names to Port objects, which can't happen until
1465 _bundle_xml_node = new XMLNode (*child);
1469 if (version < 3000) {
1470 if ((child = find_named_node (node, X_("DiskStreams"))) == 0) {
1471 error << _("Session: XML state has no diskstreams section") << endmsg;
1473 } else if (load_diskstreams_2X (*child, version)) {
1478 if ((child = find_named_node (node, VCAManager::xml_node_name)) != 0) {
1479 _vca_manager->set_state (*child, version);
1482 if ((child = find_named_node (node, "Routes")) == 0) {
1483 error << _("Session: XML state has no routes section") << endmsg;
1485 } else if (load_routes (*child, version)) {
1489 /* Now that we have Routes and masters loaded, connect them if appropriate */
1491 Slavable::Assign (_vca_manager); /* EMIT SIGNAL */
1493 /* our diskstreams list is no longer needed as they are now all owned by their Route */
1494 _diskstreams_2X.clear ();
1496 if (version >= 3000) {
1498 if ((child = find_named_node (node, "RouteGroups")) == 0) {
1499 error << _("Session: XML state has no route groups section") << endmsg;
1501 } else if (load_route_groups (*child, version)) {
1505 } else if (version < 3000) {
1507 if ((child = find_named_node (node, "EditGroups")) == 0) {
1508 error << _("Session: XML state has no edit groups section") << endmsg;
1510 } else if (load_route_groups (*child, version)) {
1514 if ((child = find_named_node (node, "MixGroups")) == 0) {
1515 error << _("Session: XML state has no mix groups section") << endmsg;
1517 } else if (load_route_groups (*child, version)) {
1522 if ((child = find_named_node (node, "Click")) == 0) {
1523 warning << _("Session: XML state has no click section") << endmsg;
1524 } else if (_click_io) {
1525 setup_click_state (&node);
1528 if ((child = find_named_node (node, ControlProtocolManager::state_node_name)) != 0) {
1529 ControlProtocolManager::instance().set_state (*child, version);
1532 if ((child = find_named_node (node, "Script"))) {
1533 for (XMLNodeList::const_iterator n = child->children ().begin (); n != child->children ().end (); ++n) {
1534 if (!(*n)->is_content ()) { continue; }
1536 guchar* buf = g_base64_decode ((*n)->content ().c_str (), &size);
1538 Glib::Threads::Mutex::Lock lm (lua_lock);
1539 (*_lua_load)(std::string ((const char*)buf, size));
1540 } catch (luabridge::LuaException const& e) {
1541 cerr << "LuaException:" << e.what () << endl;
1547 update_route_record_state ();
1549 /* here beginneth the second phase ... */
1550 set_snapshot_name (_current_snapshot_name);
1552 StateReady (); /* EMIT SIGNAL */
1565 Session::load_routes (const XMLNode& node, int version)
1568 XMLNodeConstIterator niter;
1569 RouteList new_routes;
1571 nlist = node.children();
1575 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1577 boost::shared_ptr<Route> route;
1578 if (version < 3000) {
1579 route = XMLRouteFactory_2X (**niter, version);
1581 route = XMLRouteFactory (**niter, version);
1585 error << _("Session: cannot create Route from XML description.") << endmsg;
1589 BootMessage (string_compose (_("Loaded track/bus %1"), route->name()));
1591 new_routes.push_back (route);
1594 BootMessage (_("Tracks/busses loaded; Adding to Session"));
1596 add_routes (new_routes, false, false, false, PresentationInfo::max_order);
1598 BootMessage (_("Finished adding tracks/busses"));
1603 boost::shared_ptr<Route>
1604 Session::XMLRouteFactory (const XMLNode& node, int version)
1606 boost::shared_ptr<Route> ret;
1608 if (node.name() != "Route") {
1612 XMLNode* ds_child = find_named_node (node, X_("Diskstream"));
1614 DataType type = DataType::AUDIO;
1615 XMLProperty const * prop = node.property("default-type");
1618 type = DataType (prop->value());
1621 assert (type != DataType::NIL);
1625 boost::shared_ptr<Track> track;
1627 if (type == DataType::AUDIO) {
1628 track.reset (new AudioTrack (*this, X_("toBeResetFroXML")));
1630 track.reset (new MidiTrack (*this, X_("toBeResetFroXML")));
1633 if (track->init()) {
1637 if (track->set_state (node, version)) {
1641 BOOST_MARK_TRACK (track);
1645 PresentationInfo::Flag flags = PresentationInfo::get_flags (node);
1646 boost::shared_ptr<Route> r (new Route (*this, X_("toBeResetFroXML"), flags));
1648 if (r->init () == 0 && r->set_state (node, version) == 0) {
1649 BOOST_MARK_ROUTE (r);
1657 boost::shared_ptr<Route>
1658 Session::XMLRouteFactory_2X (const XMLNode& node, int version)
1660 boost::shared_ptr<Route> ret;
1662 if (node.name() != "Route") {
1666 XMLProperty const * ds_prop = node.property (X_("diskstream-id"));
1668 ds_prop = node.property (X_("diskstream"));
1671 DataType type = DataType::AUDIO;
1672 XMLProperty const * prop = node.property("default-type");
1675 type = DataType (prop->value());
1678 assert (type != DataType::NIL);
1682 list<boost::shared_ptr<Diskstream> >::iterator i = _diskstreams_2X.begin ();
1683 while (i != _diskstreams_2X.end() && (*i)->id() != ds_prop->value()) {
1687 if (i == _diskstreams_2X.end()) {
1688 error << _("Could not find diskstream for route") << endmsg;
1689 return boost::shared_ptr<Route> ();
1692 boost::shared_ptr<Track> track;
1694 if (type == DataType::AUDIO) {
1695 track.reset (new AudioTrack (*this, X_("toBeResetFroXML")));
1697 track.reset (new MidiTrack (*this, X_("toBeResetFroXML")));
1700 if (track->init()) {
1704 if (track->set_state (node, version)) {
1708 track->set_diskstream (*i);
1710 BOOST_MARK_TRACK (track);
1714 PresentationInfo::Flag flags = PresentationInfo::get_flags (node);
1715 boost::shared_ptr<Route> r (new Route (*this, X_("toBeResetFroXML"), flags));
1717 if (r->init () == 0 && r->set_state (node, version) == 0) {
1718 BOOST_MARK_ROUTE (r);
1727 Session::load_regions (const XMLNode& node)
1730 XMLNodeConstIterator niter;
1731 boost::shared_ptr<Region> region;
1733 nlist = node.children();
1737 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1738 if ((region = XMLRegionFactory (**niter, false)) == 0) {
1739 error << _("Session: cannot create Region from XML description.");
1740 XMLProperty const * name = (**niter).property("name");
1743 error << " " << string_compose (_("Can not load state for region '%1'"), name->value());
1754 Session::load_compounds (const XMLNode& node)
1756 XMLNodeList calist = node.children();
1757 XMLNodeConstIterator caiter;
1758 XMLProperty const * caprop;
1760 for (caiter = calist.begin(); caiter != calist.end(); ++caiter) {
1761 XMLNode* ca = *caiter;
1765 if ((caprop = ca->property (X_("original"))) == 0) {
1768 orig_id = caprop->value();
1770 if ((caprop = ca->property (X_("copy"))) == 0) {
1773 copy_id = caprop->value();
1775 boost::shared_ptr<Region> orig = RegionFactory::region_by_id (orig_id);
1776 boost::shared_ptr<Region> copy = RegionFactory::region_by_id (copy_id);
1778 if (!orig || !copy) {
1779 warning << string_compose (_("Regions in compound description not found (ID's %1 and %2): ignored"),
1785 RegionFactory::add_compound_association (orig, copy);
1792 Session::load_nested_sources (const XMLNode& node)
1795 XMLNodeConstIterator niter;
1797 nlist = node.children();
1799 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1800 if ((*niter)->name() == "Source") {
1802 /* it may already exist, so don't recreate it unnecessarily
1805 XMLProperty const * prop = (*niter)->property (X_("id"));
1807 error << _("Nested source has no ID info in session file! (ignored)") << endmsg;
1811 ID source_id (prop->value());
1813 if (!source_by_id (source_id)) {
1816 SourceFactory::create (*this, **niter, true);
1818 catch (failed_constructor& err) {
1819 error << string_compose (_("Cannot reconstruct nested source for region %1"), name()) << endmsg;
1826 boost::shared_ptr<Region>
1827 Session::XMLRegionFactory (const XMLNode& node, bool full)
1829 XMLProperty const * type = node.property("type");
1833 const XMLNodeList& nlist = node.children();
1835 for (XMLNodeConstIterator niter = nlist.begin(); niter != nlist.end(); ++niter) {
1836 XMLNode *child = (*niter);
1837 if (child->name() == "NestedSource") {
1838 load_nested_sources (*child);
1842 if (!type || type->value() == "audio") {
1843 return boost::shared_ptr<Region>(XMLAudioRegionFactory (node, full));
1844 } else if (type->value() == "midi") {
1845 return boost::shared_ptr<Region>(XMLMidiRegionFactory (node, full));
1848 } catch (failed_constructor& err) {
1849 return boost::shared_ptr<Region> ();
1852 return boost::shared_ptr<Region> ();
1855 boost::shared_ptr<AudioRegion>
1856 Session::XMLAudioRegionFactory (const XMLNode& node, bool /*full*/)
1858 XMLProperty const * prop;
1859 boost::shared_ptr<Source> source;
1860 boost::shared_ptr<AudioSource> as;
1862 SourceList master_sources;
1863 uint32_t nchans = 1;
1866 if (node.name() != X_("Region")) {
1867 return boost::shared_ptr<AudioRegion>();
1870 if ((prop = node.property (X_("channels"))) != 0) {
1871 nchans = atoi (prop->value().c_str());
1874 if ((prop = node.property ("name")) == 0) {
1875 cerr << "no name for this region\n";
1879 if ((prop = node.property (X_("source-0"))) == 0) {
1880 if ((prop = node.property ("source")) == 0) {
1881 error << _("Session: XMLNode describing a AudioRegion is incomplete (no source)") << endmsg;
1882 return boost::shared_ptr<AudioRegion>();
1886 PBD::ID s_id (prop->value());
1888 if ((source = source_by_id (s_id)) == 0) {
1889 error << string_compose(_("Session: XMLNode describing a AudioRegion references an unknown source id =%1"), s_id) << endmsg;
1890 return boost::shared_ptr<AudioRegion>();
1893 as = boost::dynamic_pointer_cast<AudioSource>(source);
1895 error << string_compose(_("Session: XMLNode describing a AudioRegion references a non-audio source id =%1"), s_id) << endmsg;
1896 return boost::shared_ptr<AudioRegion>();
1899 sources.push_back (as);
1901 /* pickup other channels */
1903 for (uint32_t n=1; n < nchans; ++n) {
1904 snprintf (buf, sizeof(buf), X_("source-%d"), n);
1905 if ((prop = node.property (buf)) != 0) {
1907 PBD::ID id2 (prop->value());
1909 if ((source = source_by_id (id2)) == 0) {
1910 error << string_compose(_("Session: XMLNode describing a AudioRegion references an unknown source id =%1"), id2) << endmsg;
1911 return boost::shared_ptr<AudioRegion>();
1914 as = boost::dynamic_pointer_cast<AudioSource>(source);
1916 error << string_compose(_("Session: XMLNode describing a AudioRegion references a non-audio source id =%1"), id2) << endmsg;
1917 return boost::shared_ptr<AudioRegion>();
1919 sources.push_back (as);
1923 for (uint32_t n = 0; n < nchans; ++n) {
1924 snprintf (buf, sizeof(buf), X_("master-source-%d"), n);
1925 if ((prop = node.property (buf)) != 0) {
1927 PBD::ID id2 (prop->value());
1929 if ((source = source_by_id (id2)) == 0) {
1930 error << string_compose(_("Session: XMLNode describing a AudioRegion references an unknown source id =%1"), id2) << endmsg;
1931 return boost::shared_ptr<AudioRegion>();
1934 as = boost::dynamic_pointer_cast<AudioSource>(source);
1936 error << string_compose(_("Session: XMLNode describing a AudioRegion references a non-audio source id =%1"), id2) << endmsg;
1937 return boost::shared_ptr<AudioRegion>();
1939 master_sources.push_back (as);
1944 boost::shared_ptr<AudioRegion> region (boost::dynamic_pointer_cast<AudioRegion> (RegionFactory::create (sources, node)));
1946 /* a final detail: this is the one and only place that we know how long missing files are */
1948 if (region->whole_file()) {
1949 for (SourceList::iterator sx = sources.begin(); sx != sources.end(); ++sx) {
1950 boost::shared_ptr<SilentFileSource> sfp = boost::dynamic_pointer_cast<SilentFileSource> (*sx);
1952 sfp->set_length (region->length());
1957 if (!master_sources.empty()) {
1958 if (master_sources.size() != nchans) {
1959 error << _("Session: XMLNode describing an AudioRegion is missing some master sources; ignored") << endmsg;
1961 region->set_master_sources (master_sources);
1969 catch (failed_constructor& err) {
1970 return boost::shared_ptr<AudioRegion>();
1974 boost::shared_ptr<MidiRegion>
1975 Session::XMLMidiRegionFactory (const XMLNode& node, bool /*full*/)
1977 XMLProperty const * prop;
1978 boost::shared_ptr<Source> source;
1979 boost::shared_ptr<MidiSource> ms;
1982 if (node.name() != X_("Region")) {
1983 return boost::shared_ptr<MidiRegion>();
1986 if ((prop = node.property ("name")) == 0) {
1987 cerr << "no name for this region\n";
1991 if ((prop = node.property (X_("source-0"))) == 0) {
1992 if ((prop = node.property ("source")) == 0) {
1993 error << _("Session: XMLNode describing a MidiRegion is incomplete (no source)") << endmsg;
1994 return boost::shared_ptr<MidiRegion>();
1998 PBD::ID s_id (prop->value());
2000 if ((source = source_by_id (s_id)) == 0) {
2001 error << string_compose(_("Session: XMLNode describing a MidiRegion references an unknown source id =%1"), s_id) << endmsg;
2002 return boost::shared_ptr<MidiRegion>();
2005 ms = boost::dynamic_pointer_cast<MidiSource>(source);
2007 error << string_compose(_("Session: XMLNode describing a MidiRegion references a non-midi source id =%1"), s_id) << endmsg;
2008 return boost::shared_ptr<MidiRegion>();
2011 sources.push_back (ms);
2014 boost::shared_ptr<MidiRegion> region (boost::dynamic_pointer_cast<MidiRegion> (RegionFactory::create (sources, node)));
2015 /* a final detail: this is the one and only place that we know how long missing files are */
2017 if (region->whole_file()) {
2018 for (SourceList::iterator sx = sources.begin(); sx != sources.end(); ++sx) {
2019 boost::shared_ptr<SilentFileSource> sfp = boost::dynamic_pointer_cast<SilentFileSource> (*sx);
2021 sfp->set_length (region->length());
2029 catch (failed_constructor& err) {
2030 return boost::shared_ptr<MidiRegion>();
2035 Session::get_sources_as_xml ()
2038 XMLNode* node = new XMLNode (X_("Sources"));
2039 Glib::Threads::Mutex::Lock lm (source_lock);
2041 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ++i) {
2042 node->add_child_nocopy (i->second->get_state());
2049 Session::reset_write_sources (bool mark_write_complete, bool force)
2051 boost::shared_ptr<RouteList> rl = routes.reader();
2052 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
2053 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
2055 _state_of_the_state = StateOfTheState (_state_of_the_state|InCleanup);
2056 tr->reset_write_sources(mark_write_complete, force);
2057 _state_of_the_state = StateOfTheState (_state_of_the_state & ~InCleanup);
2063 Session::load_sources (const XMLNode& node)
2066 XMLNodeConstIterator niter;
2067 boost::shared_ptr<Source> source; /* don't need this but it stops some
2068 * versions of gcc complaining about
2069 * discarded return values.
2072 nlist = node.children();
2076 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2079 if ((source = XMLSourceFactory (**niter)) == 0) {
2080 error << _("Session: cannot create Source from XML description.") << endmsg;
2083 } catch (MissingSource& err) {
2087 if (err.type == DataType::MIDI && Glib::path_is_absolute (err.path)) {
2088 error << string_compose (_("A external MIDI file is missing. %1 cannot currently recover from missing external MIDI files"),
2089 PROGRAM_NAME) << endmsg;
2093 if (!no_questions_about_missing_files) {
2094 user_choice = MissingFile (this, err.path, err.type).get_value_or (-1);
2099 switch (user_choice) {
2101 /* user added a new search location, so try again */
2106 /* user asked to quit the entire session load
2111 no_questions_about_missing_files = true;
2115 no_questions_about_missing_files = true;
2122 case DataType::AUDIO:
2123 source = SourceFactory::createSilent (*this, **niter, max_framecnt, _current_frame_rate);
2126 case DataType::MIDI:
2127 /* The MIDI file is actually missing so
2128 * just create a new one in the same
2129 * location. Do not announce its
2133 if (!Glib::path_is_absolute (err.path)) {
2134 fullpath = Glib::build_filename (source_search_path (DataType::MIDI).front(), err.path);
2136 /* this should be an unrecoverable error: we would be creating a MIDI file outside
2141 /* Note that we do not announce the source just yet - we need to reset its ID before we do that */
2142 source = SourceFactory::createWritable (DataType::MIDI, *this, fullpath, false, _current_frame_rate, false, false);
2143 /* reset ID to match the missing one */
2144 source->set_id (**niter);
2145 /* Now we can announce it */
2146 SourceFactory::SourceCreated (source);
2157 boost::shared_ptr<Source>
2158 Session::XMLSourceFactory (const XMLNode& node)
2160 if (node.name() != "Source") {
2161 return boost::shared_ptr<Source>();
2165 /* note: do peak building in another thread when loading session state */
2166 return SourceFactory::create (*this, node, true);
2169 catch (failed_constructor& err) {
2170 error << string_compose (_("Found a sound file that cannot be used by %1. Talk to the programmers."), PROGRAM_NAME) << endmsg;
2171 return boost::shared_ptr<Source>();
2176 Session::save_template (string template_name, bool replace_existing)
2178 if ((_state_of_the_state & CannotSave) || template_name.empty ()) {
2182 bool absolute_path = Glib::path_is_absolute (template_name);
2184 /* directory to put the template in */
2185 std::string template_dir_path;
2187 if (!absolute_path) {
2188 std::string user_template_dir(user_template_directory());
2190 if (g_mkdir_with_parents (user_template_dir.c_str(), 0755) != 0) {
2191 error << string_compose(_("Could not create templates directory \"%1\" (%2)"),
2192 user_template_dir, g_strerror (errno)) << endmsg;
2196 template_dir_path = Glib::build_filename (user_template_dir, template_name);
2198 template_dir_path = template_name;
2201 if (!ARDOUR::Profile->get_trx()) {
2202 if (!replace_existing && Glib::file_test (template_dir_path, Glib::FILE_TEST_EXISTS)) {
2203 warning << string_compose(_("Template \"%1\" already exists - new version not created"),
2204 template_dir_path) << endmsg;
2208 if (g_mkdir_with_parents (template_dir_path.c_str(), 0755) != 0) {
2209 error << string_compose(_("Could not create directory for Session template\"%1\" (%2)"),
2210 template_dir_path, g_strerror (errno)) << endmsg;
2216 std::string template_file_path;
2218 if (ARDOUR::Profile->get_trx()) {
2219 template_file_path = template_name;
2221 if (absolute_path) {
2222 template_file_path = Glib::build_filename (template_dir_path, Glib::path_get_basename (template_dir_path) + template_suffix);
2224 template_file_path = Glib::build_filename (template_dir_path, template_name + template_suffix);
2228 SessionSaveUnderway (); /* EMIT SIGNAL */
2233 PBD::Unwinder<std::string> uw (_template_state_dir, template_dir_path);
2234 tree.set_root (&get_template());
2237 if (!tree.write (template_file_path)) {
2238 error << _("template not saved") << endmsg;
2242 store_recent_templates (template_file_path);
2248 Session::refresh_disk_space ()
2250 #if __APPLE__ || (HAVE_SYS_VFS_H && HAVE_SYS_STATVFS_H)
2252 Glib::Threads::Mutex::Lock lm (space_lock);
2254 /* get freespace on every FS that is part of the session path */
2256 _total_free_4k_blocks = 0;
2257 _total_free_4k_blocks_uncertain = false;
2259 for (vector<space_and_path>::iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
2261 struct statfs statfsbuf;
2262 statfs (i->path.c_str(), &statfsbuf);
2264 double const scale = statfsbuf.f_bsize / 4096.0;
2266 /* See if this filesystem is read-only */
2267 struct statvfs statvfsbuf;
2268 statvfs (i->path.c_str(), &statvfsbuf);
2270 /* f_bavail can be 0 if it is undefined for whatever
2271 filesystem we are looking at; Samba shares mounted
2272 via GVFS are an example of this.
2274 if (statfsbuf.f_bavail == 0) {
2275 /* block count unknown */
2277 i->blocks_unknown = true;
2278 } else if (statvfsbuf.f_flag & ST_RDONLY) {
2279 /* read-only filesystem */
2281 i->blocks_unknown = false;
2283 /* read/write filesystem with known space */
2284 i->blocks = (uint32_t) floor (statfsbuf.f_bavail * scale);
2285 i->blocks_unknown = false;
2288 _total_free_4k_blocks += i->blocks;
2289 if (i->blocks_unknown) {
2290 _total_free_4k_blocks_uncertain = true;
2293 #elif defined PLATFORM_WINDOWS
2294 vector<string> scanned_volumes;
2295 vector<string>::iterator j;
2296 vector<space_and_path>::iterator i;
2297 DWORD nSectorsPerCluster, nBytesPerSector,
2298 nFreeClusters, nTotalClusters;
2302 _total_free_4k_blocks = 0;
2304 for (i = session_dirs.begin(); i != session_dirs.end(); i++) {
2305 strncpy (disk_drive, (*i).path.c_str(), 3);
2309 volume_found = false;
2310 if (0 != (GetDiskFreeSpace(disk_drive, &nSectorsPerCluster, &nBytesPerSector, &nFreeClusters, &nTotalClusters)))
2312 int64_t nBytesPerCluster = nBytesPerSector * nSectorsPerCluster;
2313 int64_t nFreeBytes = nBytesPerCluster * (int64_t)nFreeClusters;
2314 i->blocks = (uint32_t)(nFreeBytes / 4096);
2316 for (j = scanned_volumes.begin(); j != scanned_volumes.end(); j++) {
2317 if (0 == j->compare(disk_drive)) {
2318 volume_found = true;
2323 if (!volume_found) {
2324 scanned_volumes.push_back(disk_drive);
2325 _total_free_4k_blocks += i->blocks;
2330 if (0 == _total_free_4k_blocks) {
2331 strncpy (disk_drive, path().c_str(), 3);
2334 if (0 != (GetDiskFreeSpace(disk_drive, &nSectorsPerCluster, &nBytesPerSector, &nFreeClusters, &nTotalClusters)))
2336 int64_t nBytesPerCluster = nBytesPerSector * nSectorsPerCluster;
2337 int64_t nFreeBytes = nBytesPerCluster * (int64_t)nFreeClusters;
2338 _total_free_4k_blocks = (uint32_t)(nFreeBytes / 4096);
2345 Session::get_best_session_directory_for_new_audio ()
2347 vector<space_and_path>::iterator i;
2348 string result = _session_dir->root_path();
2350 /* handle common case without system calls */
2352 if (session_dirs.size() == 1) {
2356 /* OK, here's the algorithm we're following here:
2358 We want to select which directory to use for
2359 the next file source to be created. Ideally,
2360 we'd like to use a round-robin process so as to
2361 get maximum performance benefits from splitting
2362 the files across multiple disks.
2364 However, in situations without much diskspace, an
2365 RR approach may end up filling up a filesystem
2366 with new files while others still have space.
2367 Its therefore important to pay some attention to
2368 the freespace in the filesystem holding each
2369 directory as well. However, if we did that by
2370 itself, we'd keep creating new files in the file
2371 system with the most space until it was as full
2372 as all others, thus negating any performance
2373 benefits of this RAID-1 like approach.
2375 So, we use a user-configurable space threshold. If
2376 there are at least 2 filesystems with more than this
2377 much space available, we use RR selection between them.
2378 If not, then we pick the filesystem with the most space.
2380 This gets a good balance between the two
2384 refresh_disk_space ();
2386 int free_enough = 0;
2388 for (i = session_dirs.begin(); i != session_dirs.end(); ++i) {
2389 if ((*i).blocks * 4096 >= Config->get_disk_choice_space_threshold()) {
2394 if (free_enough >= 2) {
2395 /* use RR selection process, ensuring that the one
2399 i = last_rr_session_dir;
2402 if (++i == session_dirs.end()) {
2403 i = session_dirs.begin();
2406 if ((*i).blocks * 4096 >= Config->get_disk_choice_space_threshold()) {
2407 SessionDirectory sdir(i->path);
2408 if (sdir.create ()) {
2410 last_rr_session_dir = i;
2415 } while (i != last_rr_session_dir);
2419 /* pick FS with the most freespace (and that
2420 seems to actually work ...)
2423 vector<space_and_path> sorted;
2424 space_and_path_ascending_cmp cmp;
2426 sorted = session_dirs;
2427 sort (sorted.begin(), sorted.end(), cmp);
2429 for (i = sorted.begin(); i != sorted.end(); ++i) {
2430 SessionDirectory sdir(i->path);
2431 if (sdir.create ()) {
2433 last_rr_session_dir = i;
2443 Session::automation_dir () const
2445 return Glib::build_filename (_path, automation_dir_name);
2449 Session::analysis_dir () const
2451 return Glib::build_filename (_path, analysis_dir_name);
2455 Session::plugins_dir () const
2457 return Glib::build_filename (_path, plugins_dir_name);
2461 Session::externals_dir () const
2463 return Glib::build_filename (_path, externals_dir_name);
2467 Session::load_bundles (XMLNode const & node)
2469 XMLNodeList nlist = node.children();
2470 XMLNodeConstIterator niter;
2474 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2475 if ((*niter)->name() == "InputBundle") {
2476 add_bundle (boost::shared_ptr<UserBundle> (new UserBundle (**niter, true)));
2477 } else if ((*niter)->name() == "OutputBundle") {
2478 add_bundle (boost::shared_ptr<UserBundle> (new UserBundle (**niter, false)));
2480 error << string_compose(_("Unknown node \"%1\" found in Bundles list from session file"), (*niter)->name()) << endmsg;
2489 Session::load_route_groups (const XMLNode& node, int version)
2491 XMLNodeList nlist = node.children();
2492 XMLNodeConstIterator niter;
2496 if (version >= 3000) {
2498 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2499 if ((*niter)->name() == "RouteGroup") {
2500 RouteGroup* rg = new RouteGroup (*this, "");
2501 add_route_group (rg);
2502 rg->set_state (**niter, version);
2506 } else if (version < 3000) {
2508 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2509 if ((*niter)->name() == "EditGroup" || (*niter)->name() == "MixGroup") {
2510 RouteGroup* rg = new RouteGroup (*this, "");
2511 add_route_group (rg);
2512 rg->set_state (**niter, version);
2521 state_file_filter (const string &str, void* /*arg*/)
2523 return (str.length() > strlen(statefile_suffix) &&
2524 str.find (statefile_suffix) == (str.length() - strlen (statefile_suffix)));
2528 remove_end(string state)
2530 string statename(state);
2532 string::size_type start,end;
2533 if ((start = statename.find_last_of (G_DIR_SEPARATOR)) != string::npos) {
2534 statename = statename.substr (start+1);
2537 if ((end = statename.rfind(statefile_suffix)) == string::npos) {
2538 end = statename.length();
2541 return string(statename.substr (0, end));
2545 Session::possible_states (string path)
2547 vector<string> states;
2548 find_files_matching_filter (states, path, state_file_filter, 0, false, false);
2550 transform(states.begin(), states.end(), states.begin(), remove_end);
2552 sort (states.begin(), states.end());
2558 Session::possible_states () const
2560 return possible_states(_path);
2564 Session::add_route_group (RouteGroup* g)
2566 _route_groups.push_back (g);
2567 route_group_added (g); /* EMIT SIGNAL */
2569 g->RouteAdded.connect_same_thread (*this, boost::bind (&Session::route_added_to_route_group, this, _1, _2));
2570 g->RouteRemoved.connect_same_thread (*this, boost::bind (&Session::route_removed_from_route_group, this, _1, _2));
2571 g->PropertyChanged.connect_same_thread (*this, boost::bind (&Session::route_group_property_changed, this, g));
2577 Session::remove_route_group (RouteGroup& rg)
2579 list<RouteGroup*>::iterator i;
2581 if ((i = find (_route_groups.begin(), _route_groups.end(), &rg)) != _route_groups.end()) {
2582 _route_groups.erase (i);
2585 route_group_removed (); /* EMIT SIGNAL */
2589 /** Set a new order for our route groups, without adding or removing any.
2590 * @param groups Route group list in the new order.
2593 Session::reorder_route_groups (list<RouteGroup*> groups)
2595 _route_groups = groups;
2597 route_groups_reordered (); /* EMIT SIGNAL */
2603 Session::route_group_by_name (string name)
2605 list<RouteGroup *>::iterator i;
2607 for (i = _route_groups.begin(); i != _route_groups.end(); ++i) {
2608 if ((*i)->name() == name) {
2616 Session::all_route_group() const
2618 return *_all_route_group;
2622 Session::add_commands (vector<Command*> const & cmds)
2624 for (vector<Command*>::const_iterator i = cmds.begin(); i != cmds.end(); ++i) {
2630 Session::add_command (Command* const cmd)
2632 assert (_current_trans);
2633 DEBUG_UNDO_HISTORY (
2634 string_compose ("Current Undo Transaction %1, adding command: %2",
2635 _current_trans->name (),
2637 _current_trans->add_command (cmd);
2640 PBD::StatefulDiffCommand*
2641 Session::add_stateful_diff_command (boost::shared_ptr<PBD::StatefulDestructible> sfd)
2643 PBD::StatefulDiffCommand* cmd = new PBD::StatefulDiffCommand (sfd);
2649 Session::begin_reversible_command (const string& name)
2651 begin_reversible_command (g_quark_from_string (name.c_str ()));
2654 /** Begin a reversible command using a GQuark to identify it.
2655 * begin_reversible_command() and commit_reversible_command() calls may be nested,
2656 * but there must be as many begin...()s as there are commit...()s.
2659 Session::begin_reversible_command (GQuark q)
2661 /* If nested begin/commit pairs are used, we create just one UndoTransaction
2662 to hold all the commands that are committed. This keeps the order of
2663 commands correct in the history.
2666 if (_current_trans == 0) {
2667 DEBUG_UNDO_HISTORY (string_compose (
2668 "Begin Reversible Command, new transaction: %1", g_quark_to_string (q)));
2670 /* start a new transaction */
2671 assert (_current_trans_quarks.empty ());
2672 _current_trans = new UndoTransaction();
2673 _current_trans->set_name (g_quark_to_string (q));
2675 DEBUG_UNDO_HISTORY (
2676 string_compose ("Begin Reversible Command, current transaction: %1",
2677 _current_trans->name ()));
2680 _current_trans_quarks.push_front (q);
2684 Session::abort_reversible_command ()
2686 if (_current_trans != 0) {
2687 DEBUG_UNDO_HISTORY (
2688 string_compose ("Abort Reversible Command: %1", _current_trans->name ()));
2689 _current_trans->clear();
2690 delete _current_trans;
2692 _current_trans_quarks.clear();
2697 Session::commit_reversible_command (Command *cmd)
2699 assert (_current_trans);
2700 assert (!_current_trans_quarks.empty ());
2705 DEBUG_UNDO_HISTORY (
2706 string_compose ("Current Undo Transaction %1, adding command: %2",
2707 _current_trans->name (),
2709 _current_trans->add_command (cmd);
2712 DEBUG_UNDO_HISTORY (
2713 string_compose ("Commit Reversible Command, current transaction: %1",
2714 _current_trans->name ()));
2716 _current_trans_quarks.pop_front ();
2718 if (!_current_trans_quarks.empty ()) {
2719 DEBUG_UNDO_HISTORY (
2720 string_compose ("Commit Reversible Command, transaction is not "
2721 "top-level, current transaction: %1",
2722 _current_trans->name ()));
2723 /* the transaction we're committing is not the top-level one */
2727 if (_current_trans->empty()) {
2728 /* no commands were added to the transaction, so just get rid of it */
2729 DEBUG_UNDO_HISTORY (
2730 string_compose ("Commit Reversible Command, No commands were "
2731 "added to current transaction: %1",
2732 _current_trans->name ()));
2733 delete _current_trans;
2738 gettimeofday (&now, 0);
2739 _current_trans->set_timestamp (now);
2741 _history.add (_current_trans);
2746 accept_all_audio_files (const string& path, void* /*arg*/)
2748 if (!Glib::file_test (path, Glib::FILE_TEST_IS_REGULAR)) {
2752 if (!AudioFileSource::safe_audio_file_extension (path)) {
2760 accept_all_midi_files (const string& path, void* /*arg*/)
2762 if (!Glib::file_test (path, Glib::FILE_TEST_IS_REGULAR)) {
2766 return ((path.length() > 4 && path.find (".mid") != (path.length() - 4)) ||
2767 (path.length() > 4 && path.find (".smf") != (path.length() - 4)) ||
2768 (path.length() > 5 && path.find (".midi") != (path.length() - 5)));
2772 accept_all_state_files (const string& path, void* /*arg*/)
2774 if (!Glib::file_test (path, Glib::FILE_TEST_IS_REGULAR)) {
2778 std::string const statefile_ext (statefile_suffix);
2779 if (path.length() >= statefile_ext.length()) {
2780 return (0 == path.compare (path.length() - statefile_ext.length(), statefile_ext.length(), statefile_ext));
2787 Session::find_all_sources (string path, set<string>& result)
2792 if (!tree.read (path)) {
2796 if ((node = find_named_node (*tree.root(), "Sources")) == 0) {
2801 XMLNodeConstIterator niter;
2803 nlist = node->children();
2807 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2809 XMLProperty const * prop;
2811 if ((prop = (*niter)->property (X_("type"))) == 0) {
2815 DataType type (prop->value());
2817 if ((prop = (*niter)->property (X_("name"))) == 0) {
2821 if (Glib::path_is_absolute (prop->value())) {
2822 /* external file, ignore */
2830 if (FileSource::find (*this, type, prop->value(), true, is_new, chan, found_path)) {
2831 result.insert (found_path);
2839 Session::find_all_sources_across_snapshots (set<string>& result, bool exclude_this_snapshot)
2841 vector<string> state_files;
2843 string this_snapshot_path;
2849 if (ripped[ripped.length()-1] == G_DIR_SEPARATOR) {
2850 ripped = ripped.substr (0, ripped.length() - 1);
2853 find_files_matching_filter (state_files, ripped, accept_all_state_files, (void *) 0, true, true);
2855 if (state_files.empty()) {
2860 this_snapshot_path = _path;
2861 this_snapshot_path += legalize_for_path (_current_snapshot_name);
2862 this_snapshot_path += statefile_suffix;
2864 for (vector<string>::iterator i = state_files.begin(); i != state_files.end(); ++i) {
2866 if (exclude_this_snapshot && *i == this_snapshot_path) {
2870 if (find_all_sources (*i, result) < 0) {
2878 struct RegionCounter {
2879 typedef std::map<PBD::ID,boost::shared_ptr<AudioSource> > AudioSourceList;
2880 AudioSourceList::iterator iter;
2881 boost::shared_ptr<Region> region;
2884 RegionCounter() : count (0) {}
2888 Session::ask_about_playlist_deletion (boost::shared_ptr<Playlist> p)
2890 boost::optional<int> r = AskAboutPlaylistDeletion (p);
2891 return r.get_value_or (1);
2895 Session::cleanup_regions ()
2897 bool removed = false;
2898 const RegionFactory::RegionMap& regions (RegionFactory::regions());
2900 for (RegionFactory::RegionMap::const_iterator i = regions.begin(); i != regions.end();) {
2902 uint32_t used = playlists->region_use_count (i->second);
2904 if (used == 0 && !i->second->automatic ()) {
2905 boost::weak_ptr<Region> w = i->second;
2908 RegionFactory::map_remove (w);
2915 // re-check to remove parent references of compound regions
2916 for (RegionFactory::RegionMap::const_iterator i = regions.begin(); i != regions.end();) {
2917 if (!(i->second->whole_file() && i->second->max_source_level() > 0)) {
2921 assert(boost::dynamic_pointer_cast<PlaylistSource>(i->second->source (0)) != 0);
2922 if (0 == playlists->region_use_count (i->second)) {
2923 boost::weak_ptr<Region> w = i->second;
2925 RegionFactory::map_remove (w);
2932 /* dump the history list */
2939 Session::can_cleanup_peakfiles () const
2941 if (deletion_in_progress()) {
2944 if (!_writable || (_state_of_the_state & CannotSave)) {
2945 warning << _("Cannot cleanup peak-files for read-only session.") << endmsg;
2948 if (record_status() == Recording) {
2949 error << _("Cannot cleanup peak-files while recording") << endmsg;
2956 Session::cleanup_peakfiles ()
2958 Glib::Threads::Mutex::Lock lm (peak_cleanup_lock, Glib::Threads::TRY_LOCK);
2963 assert (can_cleanup_peakfiles ());
2964 assert (!peaks_cleanup_in_progres());
2966 _state_of_the_state = StateOfTheState (_state_of_the_state | PeakCleanup);
2968 int timeout = 5000; // 5 seconds
2969 while (!SourceFactory::files_with_peaks.empty()) {
2970 Glib::usleep (1000);
2971 if (--timeout < 0) {
2972 warning << _("Timeout waiting for peak-file creation to terminate before cleanup, please try again later.") << endmsg;
2973 _state_of_the_state = StateOfTheState (_state_of_the_state & (~PeakCleanup));
2978 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ++i) {
2979 boost::shared_ptr<AudioSource> as;
2980 if ((as = boost::dynamic_pointer_cast<AudioSource> (i->second)) != 0) {
2981 as->close_peakfile();
2985 PBD::clear_directory (session_directory().peak_path());
2987 _state_of_the_state = StateOfTheState (_state_of_the_state & (~PeakCleanup));
2989 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ++i) {
2990 boost::shared_ptr<AudioSource> as;
2991 if ((as = boost::dynamic_pointer_cast<AudioSource> (i->second)) != 0) {
2992 SourceFactory::setup_peakfile(as, true);
2999 Session::cleanup_sources (CleanupReport& rep)
3001 // FIXME: needs adaptation to midi
3003 vector<boost::shared_ptr<Source> > dead_sources;
3006 vector<string> candidates;
3007 vector<string> unused;
3008 set<string> all_sources;
3017 _state_of_the_state = (StateOfTheState) (_state_of_the_state | InCleanup);
3019 /* this is mostly for windows which doesn't allow file
3020 * renaming if the file is in use. But we don't special
3021 * case it because we need to know if this causes
3022 * problems, and the easiest way to notice that is to
3023 * keep it in place for all platforms.
3026 request_stop (false);
3028 _butler->wait_until_finished ();
3030 /* consider deleting all unused playlists */
3032 if (playlists->maybe_delete_unused (boost::bind (Session::ask_about_playlist_deletion, _1))) {
3037 /* sync the "all regions" property of each playlist with its current state
3040 playlists->sync_all_regions_with_regions ();
3042 /* find all un-used sources */
3047 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ) {
3049 SourceMap::iterator tmp;
3054 /* do not bother with files that are zero size, otherwise we remove the current "nascent"
3058 if (!i->second->used() && (i->second->length(i->second->timeline_position() > 0))) {
3059 dead_sources.push_back (i->second);
3060 i->second->drop_references ();
3066 /* build a list of all the possible audio directories for the session */
3068 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
3069 SessionDirectory sdir ((*i).path);
3070 asp += sdir.sound_path();
3072 audio_path += asp.to_string();
3075 /* build a list of all the possible midi directories for the session */
3077 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
3078 SessionDirectory sdir ((*i).path);
3079 msp += sdir.midi_path();
3081 midi_path += msp.to_string();
3083 find_files_matching_filter (candidates, audio_path, accept_all_audio_files, (void *) 0, true, true);
3084 find_files_matching_filter (candidates, midi_path, accept_all_midi_files, (void *) 0, true, true);
3086 /* find all sources, but don't use this snapshot because the
3087 state file on disk still references sources we may have already
3091 find_all_sources_across_snapshots (all_sources, true);
3093 /* add our current source list
3096 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ) {
3097 boost::shared_ptr<FileSource> fs;
3098 SourceMap::iterator tmp = i;
3101 if ((fs = boost::dynamic_pointer_cast<FileSource> (i->second)) != 0) {
3103 /* this is mostly for windows which doesn't allow file
3104 * renaming if the file is in use. But we don't special
3105 * case it because we need to know if this causes
3106 * problems, and the easiest way to notice that is to
3107 * keep it in place for all platforms.
3112 if (!fs->is_stub()) {
3114 if (playlists->source_use_count (fs) != 0) {
3115 all_sources.insert (fs->path());
3118 /* we might not remove this source from disk, because it may be used
3119 by other snapshots, but its not being used in this version
3120 so lets get rid of it now, along with any representative regions
3124 RegionFactory::remove_regions_using_source (i->second);
3126 // also remove source from all_sources
3128 for (set<string>::iterator j = all_sources.begin(); j != all_sources.end(); ++j) {
3129 spath = Glib::path_get_basename (*j);
3130 if (spath == i->second->name()) {
3131 all_sources.erase (j);
3144 for (vector<string>::iterator x = candidates.begin(); x != candidates.end(); ++x) {
3149 for (set<string>::iterator i = all_sources.begin(); i != all_sources.end(); ++i) {
3151 tmppath1 = canonical_path (spath);
3152 tmppath2 = canonical_path ((*i));
3154 if (tmppath1 == tmppath2) {
3161 unused.push_back (spath);
3165 /* now try to move all unused files into the "dead" directory(ies) */
3167 for (vector<string>::iterator x = unused.begin(); x != unused.end(); ++x) {
3172 /* don't move the file across filesystems, just
3173 stick it in the `dead_dir_name' directory
3174 on whichever filesystem it was already on.
3177 if ((*x).find ("/sounds/") != string::npos) {
3179 /* old school, go up 1 level */
3181 newpath = Glib::path_get_dirname (*x); // "sounds"
3182 newpath = Glib::path_get_dirname (newpath); // "session-name"
3186 /* new school, go up 4 levels */
3188 newpath = Glib::path_get_dirname (*x); // "audiofiles" or "midifiles"
3189 newpath = Glib::path_get_dirname (newpath); // "session-name"
3190 newpath = Glib::path_get_dirname (newpath); // "interchange"
3191 newpath = Glib::path_get_dirname (newpath); // "session-dir"
3194 newpath = Glib::build_filename (newpath, dead_dir_name);
3196 if (g_mkdir_with_parents (newpath.c_str(), 0755) < 0) {
3197 error << string_compose(_("Session: cannot create dead file folder \"%1\" (%2)"), newpath, strerror (errno)) << endmsg;
3201 newpath = Glib::build_filename (newpath, Glib::path_get_basename ((*x)));
3203 if (Glib::file_test (newpath, Glib::FILE_TEST_EXISTS)) {
3205 /* the new path already exists, try versioning */
3207 char buf[PATH_MAX+1];
3211 snprintf (buf, sizeof (buf), "%s.%d", newpath.c_str(), version);
3214 while (Glib::file_test (newpath_v.c_str(), Glib::FILE_TEST_EXISTS) && version < 999) {
3215 snprintf (buf, sizeof (buf), "%s.%d", newpath.c_str(), ++version);
3219 if (version == 999) {
3220 error << string_compose (_("there are already 1000 files with names like %1; versioning discontinued"),
3224 newpath = newpath_v;
3229 /* it doesn't exist, or we can't read it or something */
3233 g_stat ((*x).c_str(), &statbuf);
3235 if (::rename ((*x).c_str(), newpath.c_str()) != 0) {
3236 error << string_compose (_("cannot rename unused file source from %1 to %2 (%3)"),
3237 (*x), newpath, strerror (errno))
3242 /* see if there an easy to find peakfile for this file, and remove it.
3245 string base = Glib::path_get_basename (*x);
3246 base += "%A"; /* this is what we add for the channel suffix of all native files,
3247 or for the first channel of embedded files. it will miss
3248 some peakfiles for other channels
3250 string peakpath = construct_peak_filepath (base);
3252 if (Glib::file_test (peakpath.c_str(), Glib::FILE_TEST_EXISTS)) {
3253 if (::g_unlink (peakpath.c_str()) != 0) {
3254 error << string_compose (_("cannot remove peakfile %1 for %2 (%3)"),
3255 peakpath, _path, strerror (errno))
3257 /* try to back out */
3258 ::rename (newpath.c_str(), _path.c_str());
3263 rep.paths.push_back (*x);
3264 rep.space += statbuf.st_size;
3267 /* dump the history list */
3271 /* save state so we don't end up a session file
3272 referring to non-existent sources.
3279 _state_of_the_state = (StateOfTheState) (_state_of_the_state & ~InCleanup);
3285 Session::cleanup_trash_sources (CleanupReport& rep)
3287 // FIXME: needs adaptation for MIDI
3289 vector<space_and_path>::iterator i;
3295 for (i = session_dirs.begin(); i != session_dirs.end(); ++i) {
3297 dead_dir = Glib::build_filename ((*i).path, dead_dir_name);
3299 clear_directory (dead_dir, &rep.space, &rep.paths);
3306 Session::set_dirty ()
3308 /* never mark session dirty during loading */
3310 if (_state_of_the_state & Loading) {
3314 bool was_dirty = dirty();
3316 _state_of_the_state = StateOfTheState (_state_of_the_state | Dirty);
3320 DirtyChanged(); /* EMIT SIGNAL */
3326 Session::set_clean ()
3328 bool was_dirty = dirty();
3330 _state_of_the_state = Clean;
3334 DirtyChanged(); /* EMIT SIGNAL */
3339 Session::set_deletion_in_progress ()
3341 _state_of_the_state = StateOfTheState (_state_of_the_state | Deletion);
3345 Session::clear_deletion_in_progress ()
3347 _state_of_the_state = StateOfTheState (_state_of_the_state & (~Deletion));
3351 Session::add_controllable (boost::shared_ptr<Controllable> c)
3353 /* this adds a controllable to the list managed by the Session.
3354 this is a subset of those managed by the Controllable class
3355 itself, and represents the only ones whose state will be saved
3356 as part of the session.
3359 Glib::Threads::Mutex::Lock lm (controllables_lock);
3360 controllables.insert (c);
3363 struct null_deleter { void operator()(void const *) const {} };
3366 Session::remove_controllable (Controllable* c)
3368 if (_state_of_the_state & Deletion) {
3372 Glib::Threads::Mutex::Lock lm (controllables_lock);
3374 Controllables::iterator x = controllables.find (boost::shared_ptr<Controllable>(c, null_deleter()));
3376 if (x != controllables.end()) {
3377 controllables.erase (x);
3381 boost::shared_ptr<Controllable>
3382 Session::controllable_by_id (const PBD::ID& id)
3384 Glib::Threads::Mutex::Lock lm (controllables_lock);
3386 for (Controllables::iterator i = controllables.begin(); i != controllables.end(); ++i) {
3387 if ((*i)->id() == id) {
3392 return boost::shared_ptr<Controllable>();
3395 boost::shared_ptr<Controllable>
3396 Session::controllable_by_descriptor (const ControllableDescriptor& desc)
3398 boost::shared_ptr<Controllable> c;
3399 boost::shared_ptr<Route> r;
3401 switch (desc.top_level_type()) {
3402 case ControllableDescriptor::NamedRoute:
3404 std::string str = desc.top_level_name();
3405 if (str == "Master" || str == "master") {
3407 } else if (str == "control" || str == "listen") {
3410 r = route_by_name (desc.top_level_name());
3415 case ControllableDescriptor::RemoteControlID:
3416 r = get_remote_nth_route (desc.rid());
3419 case ControllableDescriptor::SelectionCount:
3420 r = route_by_selected_count (desc.selection_id());
3428 switch (desc.subtype()) {
3429 case ControllableDescriptor::Gain:
3430 c = r->gain_control ();
3433 case ControllableDescriptor::Trim:
3434 c = r->trim()->gain_control ();
3437 case ControllableDescriptor::Solo:
3438 c = r->solo_control();
3441 case ControllableDescriptor::Mute:
3442 c = r->mute_control();
3445 case ControllableDescriptor::Recenable:
3447 boost::shared_ptr<Track> t = boost::dynamic_pointer_cast<Track>(r);
3450 c = t->rec_enable_control ();
3455 case ControllableDescriptor::PanDirection:
3456 c = r->pan_azimuth_control();
3459 case ControllableDescriptor::PanWidth:
3460 c = r->pan_width_control();
3463 case ControllableDescriptor::PanElevation:
3464 c = r->pan_elevation_control();
3467 case ControllableDescriptor::Balance:
3468 /* XXX simple pan control */
3471 case ControllableDescriptor::PluginParameter:
3473 uint32_t plugin = desc.target (0);
3474 uint32_t parameter_index = desc.target (1);
3476 /* revert to zero based counting */
3482 if (parameter_index > 0) {
3486 boost::shared_ptr<Processor> p = r->nth_plugin (plugin);
3489 c = boost::dynamic_pointer_cast<ARDOUR::AutomationControl>(
3490 p->control(Evoral::Parameter(PluginAutomation, 0, parameter_index)));
3495 case ControllableDescriptor::SendGain: {
3496 uint32_t send = desc.target (0);
3500 c = r->send_level_controllable (send);
3505 /* relax and return a null pointer */
3513 Session::add_instant_xml (XMLNode& node, bool write_to_config)
3516 Stateful::add_instant_xml (node, _path);
3519 if (write_to_config) {
3520 Config->add_instant_xml (node);
3525 Session::instant_xml (const string& node_name)
3527 return Stateful::instant_xml (node_name, _path);
3531 Session::save_history (string snapshot_name)
3539 if (!Config->get_save_history() || Config->get_saved_history_depth() < 0 ||
3540 (_history.undo_depth() == 0 && _history.redo_depth() == 0)) {
3544 if (snapshot_name.empty()) {
3545 snapshot_name = _current_snapshot_name;
3548 const string history_filename = legalize_for_path (snapshot_name) + history_suffix;
3549 const string backup_filename = history_filename + backup_suffix;
3550 const std::string xml_path(Glib::build_filename (_session_dir->root_path(), history_filename));
3551 const std::string backup_path(Glib::build_filename (_session_dir->root_path(), backup_filename));
3553 if (Glib::file_test (xml_path, Glib::FILE_TEST_EXISTS)) {
3554 if (::g_rename (xml_path.c_str(), backup_path.c_str()) != 0) {
3555 error << _("could not backup old history file, current history not saved") << endmsg;
3560 tree.set_root (&_history.get_state (Config->get_saved_history_depth()));
3562 if (!tree.write (xml_path))
3564 error << string_compose (_("history could not be saved to %1"), xml_path) << endmsg;
3566 if (g_remove (xml_path.c_str()) != 0) {
3567 error << string_compose(_("Could not remove history file at path \"%1\" (%2)"),
3568 xml_path, g_strerror (errno)) << endmsg;
3570 if (::g_rename (backup_path.c_str(), xml_path.c_str()) != 0) {
3571 error << string_compose (_("could not restore history file from backup %1 (%2)"),
3572 backup_path, g_strerror (errno)) << endmsg;
3582 Session::restore_history (string snapshot_name)
3586 if (snapshot_name.empty()) {
3587 snapshot_name = _current_snapshot_name;
3590 const std::string xml_filename = legalize_for_path (snapshot_name) + history_suffix;
3591 const std::string xml_path(Glib::build_filename (_session_dir->root_path(), xml_filename));
3593 info << "Loading history from " << xml_path << endmsg;
3595 if (!Glib::file_test (xml_path, Glib::FILE_TEST_EXISTS)) {
3596 info << string_compose (_("%1: no history file \"%2\" for this session."),
3597 _name, xml_path) << endmsg;
3601 if (!tree.read (xml_path)) {
3602 error << string_compose (_("Could not understand session history file \"%1\""),
3603 xml_path) << endmsg;
3610 for (XMLNodeConstIterator it = tree.root()->children().begin(); it != tree.root()->children().end(); it++) {
3613 UndoTransaction* ut = new UndoTransaction ();
3616 ut->set_name(t->property("name")->value());
3617 stringstream ss(t->property("tv-sec")->value());
3619 ss.str(t->property("tv-usec")->value());
3621 ut->set_timestamp(tv);
3623 for (XMLNodeConstIterator child_it = t->children().begin();
3624 child_it != t->children().end(); child_it++)
3626 XMLNode *n = *child_it;
3629 if (n->name() == "MementoCommand" ||
3630 n->name() == "MementoUndoCommand" ||
3631 n->name() == "MementoRedoCommand") {
3633 if ((c = memento_command_factory(n))) {
3637 } else if (n->name() == "NoteDiffCommand") {
3638 PBD::ID id (n->property("midi-source")->value());
3639 boost::shared_ptr<MidiSource> midi_source =
3640 boost::dynamic_pointer_cast<MidiSource, Source>(source_by_id(id));
3642 ut->add_command (new MidiModel::NoteDiffCommand(midi_source->model(), *n));
3644 error << _("Failed to downcast MidiSource for NoteDiffCommand") << endmsg;
3647 } else if (n->name() == "SysExDiffCommand") {
3649 PBD::ID id (n->property("midi-source")->value());
3650 boost::shared_ptr<MidiSource> midi_source =
3651 boost::dynamic_pointer_cast<MidiSource, Source>(source_by_id(id));
3653 ut->add_command (new MidiModel::SysExDiffCommand (midi_source->model(), *n));
3655 error << _("Failed to downcast MidiSource for SysExDiffCommand") << endmsg;
3658 } else if (n->name() == "PatchChangeDiffCommand") {
3660 PBD::ID id (n->property("midi-source")->value());
3661 boost::shared_ptr<MidiSource> midi_source =
3662 boost::dynamic_pointer_cast<MidiSource, Source>(source_by_id(id));
3664 ut->add_command (new MidiModel::PatchChangeDiffCommand (midi_source->model(), *n));
3666 error << _("Failed to downcast MidiSource for PatchChangeDiffCommand") << endmsg;
3669 } else if (n->name() == "StatefulDiffCommand") {
3670 if ((c = stateful_diff_command_factory (n))) {
3671 ut->add_command (c);
3674 error << string_compose(_("Couldn't figure out how to make a Command out of a %1 XMLNode."), n->name()) << endmsg;
3685 Session::config_changed (std::string p, bool ours)
3691 if (p == "seamless-loop") {
3693 } else if (p == "rf-speed") {
3695 } else if (p == "auto-loop") {
3697 } else if (p == "auto-input") {
3699 if (Config->get_monitoring_model() == HardwareMonitoring && transport_rolling()) {
3700 /* auto-input only makes a difference if we're rolling */
3701 set_track_monitor_input_status (!config.get_auto_input());
3704 } else if (p == "punch-in") {
3708 if ((location = _locations->auto_punch_location()) != 0) {
3710 if (config.get_punch_in ()) {
3711 replace_event (SessionEvent::PunchIn, location->start());
3713 remove_event (location->start(), SessionEvent::PunchIn);
3717 } else if (p == "punch-out") {
3721 if ((location = _locations->auto_punch_location()) != 0) {
3723 if (config.get_punch_out()) {
3724 replace_event (SessionEvent::PunchOut, location->end());
3726 clear_events (SessionEvent::PunchOut);
3730 } else if (p == "edit-mode") {
3732 Glib::Threads::Mutex::Lock lm (playlists->lock);
3734 for (SessionPlaylists::List::iterator i = playlists->playlists.begin(); i != playlists->playlists.end(); ++i) {
3735 (*i)->set_edit_mode (Config->get_edit_mode ());
3738 } else if (p == "use-video-sync") {
3740 waiting_for_sync_offset = config.get_use_video_sync();
3742 } else if (p == "mmc-control") {
3744 //poke_midi_thread ();
3746 } else if (p == "mmc-device-id" || p == "mmc-receive-id" || p == "mmc-receive-device-id") {
3748 _mmc->set_receive_device_id (Config->get_mmc_receive_device_id());
3750 } else if (p == "mmc-send-id" || p == "mmc-send-device-id") {
3752 _mmc->set_send_device_id (Config->get_mmc_send_device_id());
3754 } else if (p == "midi-control") {
3756 //poke_midi_thread ();
3758 } else if (p == "raid-path") {
3760 setup_raid_path (config.get_raid_path());
3762 } else if (p == "timecode-format") {
3766 } else if (p == "video-pullup") {
3770 } else if (p == "seamless-loop") {
3772 if (play_loop && transport_rolling()) {
3773 // to reset diskstreams etc
3774 request_play_loop (true);
3777 } else if (p == "rf-speed") {
3779 cumulative_rf_motion = 0;
3782 } else if (p == "click-sound") {
3784 setup_click_sounds (1);
3786 } else if (p == "click-emphasis-sound") {
3788 setup_click_sounds (-1);
3790 } else if (p == "clicking") {
3792 if (Config->get_clicking()) {
3793 if (_click_io && click_data) { // don't require emphasis data
3800 } else if (p == "click-gain") {
3803 _click_gain->gain_control()->set_value (Config->get_click_gain(), Controllable::NoGroup);
3806 } else if (p == "send-mtc") {
3808 if (Config->get_send_mtc ()) {
3809 /* mark us ready to send */
3810 next_quarter_frame_to_send = 0;
3813 } else if (p == "send-mmc") {
3815 _mmc->enable_send (Config->get_send_mmc ());
3817 } else if (p == "midi-feedback") {
3819 session_midi_feedback = Config->get_midi_feedback();
3821 } else if (p == "jack-time-master") {
3823 engine().reset_timebase ();
3825 } else if (p == "native-file-header-format") {
3827 if (!first_file_header_format_reset) {
3828 reset_native_file_format ();
3831 first_file_header_format_reset = false;
3833 } else if (p == "native-file-data-format") {
3835 if (!first_file_data_format_reset) {
3836 reset_native_file_format ();
3839 first_file_data_format_reset = false;
3841 } else if (p == "external-sync") {
3842 if (!config.get_external_sync()) {
3843 drop_sync_source ();
3845 switch_to_sync_source (Config->get_sync_source());
3847 } else if (p == "denormal-model") {
3849 } else if (p == "history-depth") {
3850 set_history_depth (Config->get_history_depth());
3851 } else if (p == "remote-model") {
3852 /* XXX DO SOMETHING HERE TO TELL THE GUI THAT WE NEED
3855 } else if (p == "initial-program-change") {
3857 if (_mmc->output_port() && Config->get_initial_program_change() >= 0) {
3860 buf[0] = MIDI::program; // channel zero by default
3861 buf[1] = (Config->get_initial_program_change() & 0x7f);
3863 _mmc->output_port()->midimsg (buf, sizeof (buf), 0);
3865 } else if (p == "solo-mute-override") {
3866 // catch_up_on_solo_mute_override ();
3867 } else if (p == "listen-position" || p == "pfl-position") {
3868 listen_position_changed ();
3869 } else if (p == "solo-control-is-listen-control") {
3870 solo_control_mode_changed ();
3871 } else if (p == "solo-mute-gain") {
3872 _solo_cut_control->Changed (true, Controllable::NoGroup);
3873 } else if (p == "timecode-offset" || p == "timecode-offset-negative") {
3874 last_timecode_valid = false;
3875 } else if (p == "playback-buffer-seconds") {
3876 AudioSource::allocate_working_buffers (frame_rate());
3877 } else if (p == "ltc-source-port") {
3878 reconnect_ltc_input ();
3879 } else if (p == "ltc-sink-port") {
3880 reconnect_ltc_output ();
3881 } else if (p == "timecode-generator-offset") {
3882 ltc_tx_parse_offset();
3883 } else if (p == "auto-return-target-list") {
3884 follow_playhead_priority ();
3891 Session::set_history_depth (uint32_t d)
3893 _history.set_depth (d);
3897 Session::load_diskstreams_2X (XMLNode const & node, int)
3900 XMLNodeConstIterator citer;
3902 clist = node.children();
3904 for (citer = clist.begin(); citer != clist.end(); ++citer) {
3907 /* diskstreams added automatically by DiskstreamCreated handler */
3908 if ((*citer)->name() == "AudioDiskstream" || (*citer)->name() == "DiskStream") {
3909 boost::shared_ptr<AudioDiskstream> dsp (new AudioDiskstream (*this, **citer));
3910 _diskstreams_2X.push_back (dsp);
3912 error << _("Session: unknown diskstream type in XML") << endmsg;
3916 catch (failed_constructor& err) {
3917 error << _("Session: could not load diskstream via XML state") << endmsg;
3925 /** Connect things to the MMC object */
3927 Session::setup_midi_machine_control ()
3929 _mmc = new MIDI::MachineControl;
3931 boost::shared_ptr<AsyncMIDIPort> async_in = boost::dynamic_pointer_cast<AsyncMIDIPort> (_midi_ports->mmc_input_port());
3932 boost::shared_ptr<AsyncMIDIPort> async_out = boost::dynamic_pointer_cast<AsyncMIDIPort> (_midi_ports->mmc_output_port());
3934 if (!async_out || !async_out) {
3938 /* XXXX argh, passing raw pointers back into libmidi++ */
3940 MIDI::Port* mmc_in = async_in.get();
3941 MIDI::Port* mmc_out = async_out.get();
3943 _mmc->set_ports (mmc_in, mmc_out);
3945 _mmc->Play.connect_same_thread (*this, boost::bind (&Session::mmc_deferred_play, this, _1));
3946 _mmc->DeferredPlay.connect_same_thread (*this, boost::bind (&Session::mmc_deferred_play, this, _1));
3947 _mmc->Stop.connect_same_thread (*this, boost::bind (&Session::mmc_stop, this, _1));
3948 _mmc->FastForward.connect_same_thread (*this, boost::bind (&Session::mmc_fast_forward, this, _1));
3949 _mmc->Rewind.connect_same_thread (*this, boost::bind (&Session::mmc_rewind, this, _1));
3950 _mmc->Pause.connect_same_thread (*this, boost::bind (&Session::mmc_pause, this, _1));
3951 _mmc->RecordPause.connect_same_thread (*this, boost::bind (&Session::mmc_record_pause, this, _1));
3952 _mmc->RecordStrobe.connect_same_thread (*this, boost::bind (&Session::mmc_record_strobe, this, _1));
3953 _mmc->RecordExit.connect_same_thread (*this, boost::bind (&Session::mmc_record_exit, this, _1));
3954 _mmc->Locate.connect_same_thread (*this, boost::bind (&Session::mmc_locate, this, _1, _2));
3955 _mmc->Step.connect_same_thread (*this, boost::bind (&Session::mmc_step, this, _1, _2));
3956 _mmc->Shuttle.connect_same_thread (*this, boost::bind (&Session::mmc_shuttle, this, _1, _2, _3));
3957 _mmc->TrackRecordStatusChange.connect_same_thread (*this, boost::bind (&Session::mmc_record_enable, this, _1, _2, _3));
3959 /* also handle MIDI SPP because its so common */
3961 _mmc->SPPStart.connect_same_thread (*this, boost::bind (&Session::spp_start, this));
3962 _mmc->SPPContinue.connect_same_thread (*this, boost::bind (&Session::spp_continue, this));
3963 _mmc->SPPStop.connect_same_thread (*this, boost::bind (&Session::spp_stop, this));
3966 boost::shared_ptr<Controllable>
3967 Session::solo_cut_control() const
3969 /* the solo cut control is a bit of an anomaly, at least as of Febrary 2011. There are no other
3970 controls in Ardour that currently get presented to the user in the GUI that require
3971 access as a Controllable and are also NOT owned by some SessionObject (e.g. Route, or MonitorProcessor).
3973 its actually an RCConfiguration parameter, so we use a ProxyControllable to wrap
3974 it up as a Controllable. Changes to the Controllable will just map back to the RCConfiguration
3978 return _solo_cut_control;
3982 Session::save_snapshot_name (const std::string & n)
3984 /* assure Stateful::_instant_xml is loaded
3985 * add_instant_xml() only adds to existing data and defaults
3986 * to use an empty Tree otherwise
3988 instant_xml ("LastUsedSnapshot");
3990 XMLNode* last_used_snapshot = new XMLNode ("LastUsedSnapshot");
3991 last_used_snapshot->add_property ("name", string(n));
3992 add_instant_xml (*last_used_snapshot, false);
3996 Session::set_snapshot_name (const std::string & n)
3998 _current_snapshot_name = n;
3999 save_snapshot_name (n);
4003 Session::rename (const std::string& new_name)
4005 string legal_name = legalize_for_path (new_name);
4011 string const old_sources_root = _session_dir->sources_root();
4013 if (!_writable || (_state_of_the_state & CannotSave)) {
4014 error << _("Cannot rename read-only session.") << endmsg;
4015 return 0; // don't show "messed up" warning
4017 if (record_status() == Recording) {
4018 error << _("Cannot rename session while recording") << endmsg;
4019 return 0; // don't show "messed up" warning
4022 StateProtector stp (this);
4027 * interchange subdirectory
4031 * Backup files are left unchanged and not renamed.
4034 /* Windows requires that we close all files before attempting the
4035 * rename. This works on other platforms, but isn't necessary there.
4036 * Leave it in place for all platforms though, since it may help
4037 * catch issues that could arise if the way Source files work ever
4038 * change (since most developers are not using Windows).
4041 for (SourceMap::const_iterator i = sources.begin(); i != sources.end(); ++i) {
4042 boost::shared_ptr<FileSource> fs = boost::dynamic_pointer_cast<FileSource> (i->second);
4048 /* pass one: not 100% safe check that the new directory names don't
4052 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
4056 /* this is a stupid hack because Glib::path_get_dirname() is
4057 * lexical-only, and so passing it /a/b/c/ gives a different
4058 * result than passing it /a/b/c ...
4061 if (oldstr[oldstr.length()-1] == G_DIR_SEPARATOR) {
4062 oldstr = oldstr.substr (0, oldstr.length() - 1);
4065 string base = Glib::path_get_dirname (oldstr);
4067 newstr = Glib::build_filename (base, legal_name);
4069 cerr << "Looking for " << newstr << endl;
4071 if (Glib::file_test (newstr, Glib::FILE_TEST_EXISTS)) {
4072 cerr << " exists\n";
4081 for (vector<space_and_path>::iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
4087 /* this is a stupid hack because Glib::path_get_dirname() is
4088 * lexical-only, and so passing it /a/b/c/ gives a different
4089 * result than passing it /a/b/c ...
4092 if (oldstr[oldstr.length()-1] == G_DIR_SEPARATOR) {
4093 oldstr = oldstr.substr (0, oldstr.length() - 1);
4096 string base = Glib::path_get_dirname (oldstr);
4097 newstr = Glib::build_filename (base, legal_name);
4099 cerr << "for " << oldstr << " new dir = " << newstr << endl;
4101 cerr << "Rename " << oldstr << " => " << newstr << endl;
4102 if (::g_rename (oldstr.c_str(), newstr.c_str()) != 0) {
4103 cerr << string_compose (_("renaming %s as %2 failed (%3)"), oldstr, newstr, g_strerror (errno)) << endl;
4104 error << string_compose (_("renaming %s as %2 failed (%3)"), oldstr, newstr, g_strerror (errno)) << endmsg;
4108 /* Reset path in "session dirs" */
4113 /* reset primary SessionDirectory object */
4116 (*_session_dir) = newstr;
4121 /* now rename directory below session_dir/interchange */
4123 string old_interchange_dir;
4124 string new_interchange_dir;
4126 /* use newstr here because we renamed the path
4127 * (folder/directory) that used to be oldstr to newstr above
4130 v.push_back (newstr);
4131 v.push_back (interchange_dir_name);
4132 v.push_back (Glib::path_get_basename (oldstr));
4134 old_interchange_dir = Glib::build_filename (v);
4137 v.push_back (newstr);
4138 v.push_back (interchange_dir_name);
4139 v.push_back (legal_name);
4141 new_interchange_dir = Glib::build_filename (v);
4143 cerr << "Rename " << old_interchange_dir << " => " << new_interchange_dir << endl;
4145 if (::g_rename (old_interchange_dir.c_str(), new_interchange_dir.c_str()) != 0) {
4146 cerr << string_compose (_("renaming %s as %2 failed (%3)"),
4147 old_interchange_dir, new_interchange_dir,
4150 error << string_compose (_("renaming %s as %2 failed (%3)"),
4151 old_interchange_dir, new_interchange_dir,
4160 oldstr = Glib::build_filename (new_path, _current_snapshot_name + statefile_suffix);
4161 newstr= Glib::build_filename (new_path, legal_name + statefile_suffix);
4163 cerr << "Rename " << oldstr << " => " << newstr << endl;
4165 if (::g_rename (oldstr.c_str(), newstr.c_str()) != 0) {
4166 cerr << string_compose (_("renaming %1 as %2 failed (%3)"), oldstr, newstr, g_strerror (errno)) << endl;
4167 error << string_compose (_("renaming %1 as %2 failed (%3)"), oldstr, newstr, g_strerror (errno)) << endmsg;
4173 oldstr = Glib::build_filename (new_path, _current_snapshot_name) + history_suffix;
4175 if (Glib::file_test (oldstr, Glib::FILE_TEST_EXISTS)) {
4176 newstr = Glib::build_filename (new_path, legal_name) + history_suffix;
4178 cerr << "Rename " << oldstr << " => " << newstr << endl;
4180 if (::g_rename (oldstr.c_str(), newstr.c_str()) != 0) {
4181 cerr << string_compose (_("renaming %1 as %2 failed (%3)"), oldstr, newstr, g_strerror (errno)) << endl;
4182 error << string_compose (_("renaming %1 as %2 failed (%3)"), oldstr, newstr, g_strerror (errno)) << endmsg;
4187 /* remove old name from recent sessions */
4188 remove_recent_sessions (_path);
4191 /* update file source paths */
4193 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ++i) {
4194 boost::shared_ptr<FileSource> fs = boost::dynamic_pointer_cast<FileSource> (i->second);
4196 string p = fs->path ();
4197 boost::replace_all (p, old_sources_root, _session_dir->sources_root());
4199 SourceFactory::setup_peakfile(i->second, true);
4203 set_snapshot_name (new_name);
4208 /* save state again to get everything just right */
4210 save_state (_current_snapshot_name);
4212 /* add to recent sessions */
4214 store_recent_sessions (new_name, _path);
4220 Session::get_session_info_from_path (XMLTree& tree, const string& xmlpath)
4222 if (!Glib::file_test (xmlpath, Glib::FILE_TEST_EXISTS)) {
4226 if (!tree.read (xmlpath)) {
4234 Session::get_info_from_path (const string& xmlpath, float& sample_rate, SampleFormat& data_format)
4237 bool found_sr = false;
4238 bool found_data_format = false;
4240 if (get_session_info_from_path (tree, xmlpath)) {
4246 XMLProperty const * prop;
4247 XMLNode const * root (tree.root());
4249 if ((prop = root->property (X_("sample-rate"))) != 0) {
4250 sample_rate = atoi (prop->value());
4254 const XMLNodeList& children (root->children());
4255 for (XMLNodeList::const_iterator c = children.begin(); c != children.end(); ++c) {
4256 const XMLNode* child = *c;
4257 if (child->name() == "Config") {
4258 const XMLNodeList& options (child->children());
4259 for (XMLNodeList::const_iterator oc = options.begin(); oc != options.end(); ++oc) {
4260 XMLNode const * option = *oc;
4261 XMLProperty const * name = option->property("name");
4267 if (name->value() == "native-file-data-format") {
4268 XMLProperty const * value = option->property ("value");
4270 SampleFormat fmt = (SampleFormat) string_2_enum (option->property ("value")->value(), fmt);
4272 found_data_format = true;
4278 if (found_data_format) {
4283 return !(found_sr && found_data_format); // zero if they are both found
4287 Session::get_snapshot_from_instant (const std::string& session_dir)
4289 std::string instant_xml_path = Glib::build_filename (session_dir, "instant.xml");
4291 if (!Glib::file_test (instant_xml_path, Glib::FILE_TEST_EXISTS)) {
4296 if (!tree.read (instant_xml_path)) {
4300 XMLProperty const * prop;
4301 XMLNode *last_used_snapshot = tree.root()->child("LastUsedSnapshot");
4302 if (last_used_snapshot && (prop = last_used_snapshot->property ("name")) != 0) {
4303 return prop->value();
4309 typedef std::vector<boost::shared_ptr<FileSource> > SeveralFileSources;
4310 typedef std::map<std::string,SeveralFileSources> SourcePathMap;
4313 Session::bring_all_sources_into_session (boost::function<void(uint32_t,uint32_t,string)> callback)
4317 SourcePathMap source_path_map;
4319 boost::shared_ptr<AudioFileSource> afs;
4324 Glib::Threads::Mutex::Lock lm (source_lock);
4326 cerr << " total sources = " << sources.size();
4328 for (SourceMap::const_iterator i = sources.begin(); i != sources.end(); ++i) {
4329 boost::shared_ptr<FileSource> fs = boost::dynamic_pointer_cast<FileSource> (i->second);
4335 if (fs->within_session()) {
4339 if (source_path_map.find (fs->path()) != source_path_map.end()) {
4340 source_path_map[fs->path()].push_back (fs);
4342 SeveralFileSources v;
4344 source_path_map.insert (make_pair (fs->path(), v));
4350 cerr << " fsources = " << total << endl;
4352 for (SourcePathMap::iterator i = source_path_map.begin(); i != source_path_map.end(); ++i) {
4354 /* tell caller where we are */
4356 string old_path = i->first;
4358 callback (n, total, old_path);
4360 cerr << old_path << endl;
4364 switch (i->second.front()->type()) {
4365 case DataType::AUDIO:
4366 new_path = new_audio_source_path_for_embedded (old_path);
4369 case DataType::MIDI:
4370 /* XXX not implemented yet */
4374 if (new_path.empty()) {
4378 cerr << "Move " << old_path << " => " << new_path << endl;
4380 if (!copy_file (old_path, new_path)) {
4381 cerr << "failed !\n";
4385 /* make sure we stop looking in the external
4386 dir/folder. Remember, this is an all-or-nothing
4387 operations, it doesn't merge just some files.
4389 remove_dir_from_search_path (Glib::path_get_dirname (old_path), i->second.front()->type());
4391 for (SeveralFileSources::iterator f = i->second.begin(); f != i->second.end(); ++f) {
4392 (*f)->set_path (new_path);
4397 save_state ("", false, false);
4403 bool accept_all_files (string const &, void *)
4409 Session::save_as_bring_callback (uint32_t,uint32_t,string)
4411 /* 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.
4416 make_new_media_path (string old_path, string new_session_folder, string new_session_path)
4418 /* typedir is the "midifiles" or "audiofiles" etc. part of the path. */
4420 string typedir = Glib::path_get_basename (Glib::path_get_dirname (old_path));
4422 v.push_back (new_session_folder); /* full path */
4423 v.push_back (interchange_dir_name);
4424 v.push_back (new_session_path); /* just one directory/folder */
4425 v.push_back (typedir);
4426 v.push_back (Glib::path_get_basename (old_path));
4428 return Glib::build_filename (v);
4432 Session::save_as (SaveAs& saveas)
4434 vector<string> files;
4435 string current_folder = Glib::path_get_dirname (_path);
4436 string new_folder = legalize_for_path (saveas.new_name);
4437 string to_dir = Glib::build_filename (saveas.new_parent_folder, new_folder);
4438 int64_t total_bytes = 0;
4442 int32_t internal_file_cnt = 0;
4444 vector<string> do_not_copy_extensions;
4445 do_not_copy_extensions.push_back (statefile_suffix);
4446 do_not_copy_extensions.push_back (pending_suffix);
4447 do_not_copy_extensions.push_back (backup_suffix);
4448 do_not_copy_extensions.push_back (temp_suffix);
4449 do_not_copy_extensions.push_back (history_suffix);
4451 /* get total size */
4453 for (vector<space_and_path>::const_iterator sd = session_dirs.begin(); sd != session_dirs.end(); ++sd) {
4455 /* need to clear this because
4456 * find_files_matching_filter() is cumulative
4461 find_files_matching_filter (files, (*sd).path, accept_all_files, 0, false, true, true);
4463 all += files.size();
4465 for (vector<string>::iterator i = files.begin(); i != files.end(); ++i) {
4467 g_stat ((*i).c_str(), &gsb);
4468 total_bytes += gsb.st_size;
4472 /* save old values so we can switch back if we are not switching to the new session */
4474 string old_path = _path;
4475 string old_name = _name;
4476 string old_snapshot = _current_snapshot_name;
4477 string old_sd = _session_dir->root_path();
4478 vector<string> old_search_path[DataType::num_types];
4479 string old_config_search_path[DataType::num_types];
4481 old_search_path[DataType::AUDIO] = source_search_path (DataType::AUDIO);
4482 old_search_path[DataType::MIDI] = source_search_path (DataType::MIDI);
4483 old_config_search_path[DataType::AUDIO] = config.get_audio_search_path ();
4484 old_config_search_path[DataType::MIDI] = config.get_midi_search_path ();
4486 /* switch session directory */
4488 (*_session_dir) = to_dir;
4490 /* create new tree */
4492 if (!_session_dir->create()) {
4493 saveas.failure_message = string_compose (_("Cannot create new session folder %1"), to_dir);
4498 /* copy all relevant files. Find each location in session_dirs,
4499 * and copy files from there to target.
4502 for (vector<space_and_path>::const_iterator sd = session_dirs.begin(); sd != session_dirs.end(); ++sd) {
4504 /* need to clear this because
4505 * find_files_matching_filter() is cumulative
4510 const size_t prefix_len = (*sd).path.size();
4512 /* Work just on the files within this session dir */
4514 find_files_matching_filter (files, (*sd).path, accept_all_files, 0, false, true, true);
4516 /* add dir separator to protect against collisions with
4517 * track names (e.g. track named "audiofiles" or
4521 static const std::string audiofile_dir_string = string (sound_dir_name) + G_DIR_SEPARATOR;
4522 static const std::string midifile_dir_string = string (midi_dir_name) + G_DIR_SEPARATOR;
4523 static const std::string analysis_dir_string = analysis_dir() + G_DIR_SEPARATOR;
4525 /* copy all the files. Handling is different for media files
4526 than others because of the *silly* subtree we have below the interchange
4527 folder. That really was a bad idea, but I'm not fixing it as part of
4528 implementing ::save_as().
4531 for (vector<string>::iterator i = files.begin(); i != files.end(); ++i) {
4533 std::string from = *i;
4536 string filename = Glib::path_get_basename (from);
4537 std::transform (filename.begin(), filename.end(), filename.begin(), ::toupper);
4538 if (filename == ".DS_STORE") {
4543 if (from.find (audiofile_dir_string) != string::npos) {
4545 /* audio file: only copy if asked */
4547 if (saveas.include_media && saveas.copy_media) {
4549 string to = make_new_media_path (*i, to_dir, new_folder);
4551 info << "media file copying from " << from << " to " << to << endmsg;
4553 if (!copy_file (from, to)) {
4554 throw Glib::FileError (Glib::FileError::IO_ERROR,
4555 string_compose(_("\ncopying \"%1\" failed !"), from));
4559 /* we found media files inside the session folder */
4561 internal_file_cnt++;
4563 } else if (from.find (midifile_dir_string) != string::npos) {
4565 /* midi file: always copy unless
4566 * creating an empty new session
4569 if (saveas.include_media) {
4571 string to = make_new_media_path (*i, to_dir, new_folder);
4573 info << "media file copying from " << from << " to " << to << endmsg;
4575 if (!copy_file (from, to)) {
4576 throw Glib::FileError (Glib::FileError::IO_ERROR, "copy failed");
4580 /* we found media files inside the session folder */
4582 internal_file_cnt++;
4584 } else if (from.find (analysis_dir_string) != string::npos) {
4586 /* make sure analysis dir exists in
4587 * new session folder, but we're not
4588 * copying analysis files here, see
4592 (void) g_mkdir_with_parents (analysis_dir().c_str(), 775);
4597 /* normal non-media file. Don't copy state, history, etc.
4600 bool do_copy = true;
4602 for (vector<string>::iterator v = do_not_copy_extensions.begin(); v != do_not_copy_extensions.end(); ++v) {
4603 if ((from.length() > (*v).length()) && (from.find (*v) == from.length() - (*v).length())) {
4604 /* end of filename matches extension, do not copy file */
4610 if (!saveas.copy_media && from.find (peakfile_suffix) != string::npos) {
4611 /* don't copy peakfiles if
4612 * we're not copying media
4618 string to = Glib::build_filename (to_dir, from.substr (prefix_len));
4620 info << "attempting to make directory/folder " << to << endmsg;
4622 if (g_mkdir_with_parents (Glib::path_get_dirname (to).c_str(), 0755)) {
4623 throw Glib::FileError (Glib::FileError::IO_ERROR, "cannot create required directory");
4626 info << "attempting to copy " << from << " to " << to << endmsg;
4628 if (!copy_file (from, to)) {
4629 throw Glib::FileError (Glib::FileError::IO_ERROR,
4630 string_compose(_("\ncopying \"%1\" failed !"), from));
4635 /* measure file size even if we're not going to copy so that our Progress
4636 signals are correct, since we included these do-not-copy files
4637 in the computation of the total size and file count.
4641 g_stat (from.c_str(), &gsb);
4642 copied += gsb.st_size;
4645 double fraction = (double) copied / total_bytes;
4647 bool keep_going = true;
4649 if (saveas.copy_media) {
4651 /* no need or expectation of this if
4652 * media is not being copied, because
4653 * it will be fast(ish).
4656 /* tell someone "X percent, file M of N"; M is one-based */
4658 boost::optional<bool> res = saveas.Progress (fraction, cnt, all);
4666 throw Glib::FileError (Glib::FileError::FAILED, "copy cancelled");
4672 /* copy optional folders, if any */
4674 string old = plugins_dir ();
4675 if (Glib::file_test (old, Glib::FILE_TEST_EXISTS)) {
4676 string newdir = Glib::build_filename (to_dir, Glib::path_get_basename (old));
4677 copy_files (old, newdir);
4680 old = externals_dir ();
4681 if (Glib::file_test (old, Glib::FILE_TEST_EXISTS)) {
4682 string newdir = Glib::build_filename (to_dir, Glib::path_get_basename (old));
4683 copy_files (old, newdir);
4686 old = automation_dir ();
4687 if (Glib::file_test (old, Glib::FILE_TEST_EXISTS)) {
4688 string newdir = Glib::build_filename (to_dir, Glib::path_get_basename (old));
4689 copy_files (old, newdir);
4692 if (saveas.include_media) {
4694 if (saveas.copy_media) {
4695 #ifndef PLATFORM_WINDOWS
4696 /* There are problems with analysis files on
4697 * Windows, because they used a colon in their
4698 * names as late as 4.0. Colons are not legal
4699 * under Windows even if NTFS allows them.
4701 * This is a tricky problem to solve so for
4702 * just don't copy these files. They will be
4703 * regenerated as-needed anyway, subject to the
4704 * existing issue that the filenames will be
4705 * rejected by Windows, which is a separate
4706 * problem (though related).
4709 /* only needed if we are copying media, since the
4710 * analysis data refers to media data
4713 old = analysis_dir ();
4714 if (Glib::file_test (old, Glib::FILE_TEST_EXISTS)) {
4715 string newdir = Glib::build_filename (to_dir, "analysis");
4716 copy_files (old, newdir);
4718 #endif /* PLATFORM_WINDOWS */
4724 set_snapshot_name (saveas.new_name);
4725 _name = saveas.new_name;
4727 if (saveas.include_media && !saveas.copy_media) {
4729 /* reset search paths of the new session (which we're pretending to be right now) to
4730 include the original session search path, so we can still find all audio.
4733 if (internal_file_cnt) {
4734 for (vector<string>::iterator s = old_search_path[DataType::AUDIO].begin(); s != old_search_path[DataType::AUDIO].end(); ++s) {
4735 ensure_search_path_includes (*s, DataType::AUDIO);
4736 cerr << "be sure to include " << *s << " for audio" << endl;
4739 /* we do not do this for MIDI because we copy
4740 all MIDI files if saveas.include_media is
4746 bool was_dirty = dirty ();
4748 save_state ("", false, false, !saveas.include_media);
4749 save_default_options ();
4751 if (saveas.copy_media && saveas.copy_external) {
4752 if (bring_all_sources_into_session (boost::bind (&Session::save_as_bring_callback, this, _1, _2, _3))) {
4753 throw Glib::FileError (Glib::FileError::NO_SPACE_LEFT, "consolidate failed");
4757 saveas.final_session_folder_name = _path;
4759 store_recent_sessions (_name, _path);
4761 if (!saveas.switch_to) {
4763 /* switch back to the way things were */
4767 set_snapshot_name (old_snapshot);
4769 (*_session_dir) = old_sd;
4775 if (internal_file_cnt) {
4776 /* reset these to their original values */
4777 config.set_audio_search_path (old_config_search_path[DataType::AUDIO]);
4778 config.set_midi_search_path (old_config_search_path[DataType::MIDI]);
4783 /* prune session dirs, and update disk space statistics
4788 session_dirs.clear ();
4789 session_dirs.push_back (sp);
4790 refresh_disk_space ();
4792 /* ensure that all existing tracks reset their current capture source paths
4794 reset_write_sources (true, true);
4796 /* the copying above was based on actually discovering files, not just iterating over the sources list.
4797 But if we're going to switch to the new (copied) session, we need to change the paths in the sources also.
4800 for (SourceMap::const_iterator i = sources.begin(); i != sources.end(); ++i) {
4801 boost::shared_ptr<FileSource> fs = boost::dynamic_pointer_cast<FileSource> (i->second);
4807 if (fs->within_session()) {
4808 string newpath = make_new_media_path (fs->path(), to_dir, new_folder);
4809 fs->set_path (newpath);
4814 } catch (Glib::FileError& e) {
4816 saveas.failure_message = e.what();
4818 /* recursively remove all the directories */
4820 remove_directory (to_dir);
4828 saveas.failure_message = _("unknown reason");
4830 /* recursively remove all the directories */
4832 remove_directory (to_dir);