2 Copyright (C) 1999-2002 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.
26 #include <sigc++/bind.h>
28 #include <cstdio> /* snprintf(3) ... grrr */
43 #include <sys/mount.h>
44 #include <sys/param.h>
49 #include <midi++/mmc.h>
50 #include <midi++/port.h>
51 #include <pbd/error.h>
53 #include <glibmm/thread.h>
54 #include <pbd/pathscanner.h>
55 #include <pbd/pthread_utils.h>
56 #include <pbd/strsplit.h>
58 #include <ardour/audioengine.h>
59 #include <ardour/configuration.h>
60 #include <ardour/session.h>
61 #include <ardour/buffer.h>
62 #include <ardour/audio_diskstream.h>
63 #include <ardour/midi_diskstream.h>
64 #include <ardour/utils.h>
65 #include <ardour/audioplaylist.h>
66 #include <ardour/audiofilesource.h>
67 #include <ardour/destructive_filesource.h>
68 #include <ardour/sndfile_helpers.h>
69 #include <ardour/auditioner.h>
70 #include <ardour/export.h>
71 #include <ardour/redirect.h>
72 #include <ardour/send.h>
73 #include <ardour/insert.h>
74 #include <ardour/connection.h>
75 #include <ardour/slave.h>
76 #include <ardour/tempo.h>
77 #include <ardour/audio_track.h>
78 #include <ardour/midi_track.h>
79 #include <ardour/cycle_timer.h>
80 #include <ardour/utils.h>
81 #include <ardour/named_selection.h>
82 #include <ardour/version.h>
83 #include <ardour/location.h>
84 #include <ardour/audioregion.h>
85 #include <ardour/crossfade.h>
86 #include <ardour/control_protocol_manager.h>
92 using namespace ARDOUR;
96 Session::first_stage_init (string fullpath, string snapshot_name)
98 if (fullpath.length() == 0) {
99 throw failed_constructor();
102 char buf[PATH_MAX+1];
103 if (!realpath(fullpath.c_str(), buf) && (errno != ENOENT)) {
104 error << string_compose(_("Could not use path %1 (%s)"), buf, strerror(errno)) << endmsg;
105 throw failed_constructor();
109 if (_path[_path.length()-1] != '/') {
113 /* these two are just provisional settings. set_state()
114 will likely override them.
117 _name = _current_snapshot_name = snapshot_name;
118 setup_raid_path (_path);
120 _current_frame_rate = _engine.frame_rate ();
121 _tempo_map = new TempoMap (_current_frame_rate);
122 _tempo_map->StateChanged.connect (mem_fun (*this, &Session::tempo_map_changed));
124 g_atomic_int_set (&processing_prohibited, 0);
127 _transport_speed = 0;
128 _last_transport_speed = 0;
129 transport_sub_state = 0;
130 _transport_frame = 0;
132 end_location = new Location (0, 0, _("end"), Location::Flags ((Location::IsMark|Location::IsEnd)));
133 start_location = new Location (0, 0, _("start"), Location::Flags ((Location::IsMark|Location::IsStart)));
134 _end_location_is_free = true;
135 g_atomic_int_set (&_record_status, Disabled);
140 seamless_loop = false;
141 loop_changing = false;
143 crossfades_active = false;
146 _last_roll_location = 0;
147 _last_record_location = 0;
148 pending_locate_frame = 0;
149 pending_locate_roll = false;
150 pending_locate_flush = false;
151 dstream_buffer_size = 0;
153 state_was_pending = false;
155 outbound_mtc_smpte_frame = 0;
156 next_quarter_frame_to_send = -1;
157 current_block_size = 0;
158 _solo_latched = true;
159 _solo_model = InverseMute;
160 solo_update_disabled = false;
161 currently_soloing = false;
162 _have_captured = false;
163 _worst_output_latency = 0;
164 _worst_input_latency = 0;
165 _worst_track_latency = 0;
166 _state_of_the_state = StateOfTheState(CannotSave|InitialConnecting|Loading);
169 butler_mixdown_buffer = 0;
170 butler_gain_buffer = 0;
174 post_transport_work = PostTransportWork (0);
175 g_atomic_int_set (&butler_should_do_transport_work, 0);
176 g_atomic_int_set (&butler_active, 0);
177 g_atomic_int_set (&_playback_load, 100);
178 g_atomic_int_set (&_capture_load, 100);
179 g_atomic_int_set (&_playback_load_min, 100);
180 g_atomic_int_set (&_capture_load_min, 100);
181 pending_audition_region = 0;
183 pending_edit_mode = _edit_mode;
185 input_auto_connect = AutoConnectOption (0);
186 output_auto_connect = AutoConnectOption (0);
187 waiting_to_start = false;
189 _gain_automation_buffer = 0;
190 _pan_automation_buffer = 0;
192 pending_abort = false;
193 layer_model = MoveAddHigher;
194 xfade_model = ShortCrossfade;
195 destructive_index = 0;
197 AudioDiskstream::allocate_working_buffers();
199 /* default short fade = 15ms */
201 Crossfade::set_short_xfade_length ((jack_nframes_t) floor ((15.0 * frame_rate()) / 1000.0));
202 DestructiveFileSource::setup_standard_crossfades (frame_rate());
204 last_mmc_step.tv_sec = 0;
205 last_mmc_step.tv_usec = 0;
208 preroll.type = AnyTime::Frames;
210 postroll.type = AnyTime::Frames;
213 /* click sounds are unset by default, which causes us to internal
214 waveforms for clicks.
218 click_requested = false;
220 click_emphasis_data = 0;
222 click_emphasis_length = 0;
224 process_function = &Session::process_with_events;
228 _smpte_offset_negative = true;
229 last_smpte_valid = false;
231 last_rr_session_dir = session_dirs.begin();
232 refresh_disk_space ();
234 // set_default_fade (0.2, 5.0); /* steepness, millisecs */
236 /* default configuration */
238 do_not_record_plugins = false;
239 over_length_short = 2;
240 over_length_long = 10;
241 send_midi_timecode = false;
242 send_midi_machine_control = false;
243 shuttle_speed_factor = 1.0;
244 shuttle_speed_threshold = 5;
246 _meter_hold = 100; // XXX unknown units: number of calls to meter::set()
247 _meter_falloff = 1.5f; // XXX unknown units: refresh_rate
253 average_slave_delta = 1800;
254 have_first_delta_accumulator = false;
255 delta_accumulator_cnt = 0;
256 slave_state = Stopped;
258 /* default SMPTE type is 30 FPS, non-drop */
260 set_smpte_type (30.0, false);
262 _engine.GraphReordered.connect (mem_fun (*this, &Session::graph_reordered));
264 /* These are all static "per-class" signals */
266 Region::CheckNewRegion.connect (mem_fun (*this, &Session::add_region));
267 AudioSource::AudioSourceCreated.connect (mem_fun (*this, &Session::add_audio_source));
268 Playlist::PlaylistCreated.connect (mem_fun (*this, &Session::add_playlist));
269 Redirect::RedirectCreated.connect (mem_fun (*this, &Session::add_redirect));
270 Diskstream::DiskstreamCreated.connect (mem_fun (*this, &Session::add_diskstream));
271 NamedSelection::NamedSelectionCreated.connect (mem_fun (*this, &Session::add_named_selection));
273 Controllable::Created.connect (mem_fun (*this, &Session::add_controllable));
274 Controllable::GoingAway.connect (mem_fun (*this, &Session::remove_controllable));
276 IO::MoreChannels.connect (mem_fun (*this, &Session::ensure_buffers));
278 /* stop IO objects from doing stuff until we're ready for them */
280 IO::disable_panners ();
281 IO::disable_ports ();
282 IO::disable_connecting ();
286 Session::second_stage_init (bool new_session)
288 AudioFileSource::set_peak_dir (peak_dir());
291 if (load_state (_current_snapshot_name)) {
294 remove_empty_sounds ();
297 if (start_butler_thread()) {
301 /*if (start_midi_thread ()) {
306 if (set_state (*state_tree->root())) {
311 /* we can't save till after ::when_engine_running() is called,
312 because otherwise we save state with no connections made.
313 therefore, we reset _state_of_the_state because ::set_state()
314 will have cleared it.
316 we also have to include Loading so that any events that get
317 generated between here and the end of ::when_engine_running()
318 will be processed directly rather than queued.
321 _state_of_the_state = StateOfTheState (_state_of_the_state|CannotSave|Loading);
323 // set_auto_input (true);
324 _locations.changed.connect (mem_fun (this, &Session::locations_changed));
325 _locations.added.connect (mem_fun (this, &Session::locations_added));
326 setup_click_sounds (0);
327 setup_midi_control ();
329 /* Pay attention ... */
331 _engine.Halted.connect (mem_fun (*this, &Session::engine_halted));
332 _engine.Xrun.connect (mem_fun (*this, &Session::xrun_recovery));
334 if (_engine.running()) {
335 when_engine_running();
337 first_time_running = _engine.Running.connect (mem_fun (*this, &Session::when_engine_running));
340 //send_full_time_code ();
341 _engine.transport_locate (0);
342 deliver_mmc (MIDI::MachineControl::cmdMmcReset, 0);
343 deliver_mmc (MIDI::MachineControl::cmdLocate, 0);
345 ControlProtocolManager::instance().set_session (*this);
348 _end_location_is_free = true;
350 _end_location_is_free = false;
357 Session::raid_path () const
361 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
366 return path.substr (0, path.length() - 1); // drop final colon
370 Session::set_raid_path (string path)
372 /* public-access to setup_raid_path() */
374 setup_raid_path (path);
378 Session::setup_raid_path (string path)
380 string::size_type colon;
384 string::size_type len = path.length();
389 if (path.length() == 0) {
393 session_dirs.clear ();
395 for (string::size_type n = 0; n < len; ++n) {
396 if (path[n] == ':') {
403 /* no multiple search path, just one location (common case) */
407 session_dirs.push_back (sp);
414 if (fspath[fspath.length()-1] != '/') {
417 fspath += sound_dir_name;
423 if (fspath[fspath.length()-1] != '/') {
426 fspath += tape_dir_name;
428 AudioFileSource::set_search_path (fspath);
435 while ((colon = remaining.find_first_of (':')) != string::npos) {
438 sp.path = remaining.substr (0, colon);
439 session_dirs.push_back (sp);
441 /* add sounds to file search path */
444 if (fspath[fspath.length()-1] != '/') {
447 fspath += sound_dir_name;
450 /* add tape dir to file search path */
453 if (fspath[fspath.length()-1] != '/') {
456 fspath += tape_dir_name;
459 remaining = remaining.substr (colon+1);
462 if (remaining.length()) {
469 if (fspath[fspath.length()-1] != '/') {
472 fspath += sound_dir_name;
476 if (fspath[fspath.length()-1] != '/') {
479 fspath += tape_dir_name;
481 session_dirs.push_back (sp);
484 /* set the AudioFileSource search path */
486 AudioFileSource::set_search_path (fspath);
488 /* reset the round-robin soundfile path thingie */
490 last_rr_session_dir = session_dirs.begin();
494 Session::create (bool& new_session, string* mix_template, jack_nframes_t initial_length)
498 if (mkdir (_path.c_str(), 0755) < 0) {
499 if (errno == EEXIST) {
502 error << string_compose(_("Session: cannot create session dir \"%1\" (%2)"), _path, strerror (errno)) << endmsg;
511 if (mkdir (dir.c_str(), 0755) < 0) {
512 if (errno != EEXIST) {
513 error << string_compose(_("Session: cannot create session peakfile dir \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
520 if (mkdir (dir.c_str(), 0755) < 0) {
521 if (errno != EEXIST) {
522 error << string_compose(_("Session: cannot create session sounds dir \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
529 if (mkdir (dir.c_str(), 0755) < 0) {
530 if (errno != EEXIST) {
531 error << string_compose(_("Session: cannot create session tape dir \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
536 dir = dead_sound_dir ();
538 if (mkdir (dir.c_str(), 0755) < 0) {
539 if (errno != EEXIST) {
540 error << string_compose(_("Session: cannot create session dead sounds dir \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
545 dir = automation_dir ();
547 if (mkdir (dir.c_str(), 0755) < 0) {
548 if (errno != EEXIST) {
549 error << string_compose(_("Session: cannot create session automation dir \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
555 /* check new_session so we don't overwrite an existing one */
559 std::string in_path = *mix_template;
561 ifstream in(in_path.c_str());
564 string out_path = _path;
566 out_path += _statefile_suffix;
568 ofstream out(out_path.c_str());
573 // okay, session is set up. Treat like normal saved
574 // session from now on.
580 error << string_compose (_("Could not open %1 for writing mix template"), out_path)
586 error << string_compose (_("Could not open mix template %1 for reading"), in_path)
593 warning << _("Session already exists. Not overwriting") << endmsg;
600 /* set initial start + end point */
602 start_location->set_end (0);
603 _locations.add (start_location);
605 end_location->set_end (initial_length);
606 _locations.add (end_location);
608 _state_of_the_state = Clean;
610 if (save_state (_current_snapshot_name)) {
611 save_history (_current_snapshot_name);
620 Session::load_diskstreams (const XMLNode& node)
623 XMLNodeConstIterator citer;
625 clist = node.children();
627 for (citer = clist.begin(); citer != clist.end(); ++citer) {
628 Diskstream* dstream = 0;
631 /* diskstreams added automatically by DiskstreamCreated handler */
632 if ((*citer)->name() == "AudioDiskstream" || (*citer)->name() == "DiskStream") {
633 dstream = new AudioDiskstream (*this, **citer);
634 } else if ((*citer)->name() == "MidiDiskstream") {
635 dstream = new MidiDiskstream (*this, **citer);
637 error << _("Session: unknown diskstream type in XML") << endmsg;
641 catch (failed_constructor& err) {
642 error << _("Session: could not load diskstream via XML state") << endmsg;
651 Session::remove_pending_capture_state ()
656 xml_path += _current_snapshot_name;
657 xml_path += _pending_suffix;
659 unlink (xml_path.c_str());
663 Session::save_state (string snapshot_name, bool pending)
669 if (_state_of_the_state & CannotSave) {
673 tree.set_root (&get_state());
675 if (snapshot_name.empty()) {
676 snapshot_name = _current_snapshot_name;
682 xml_path += snapshot_name;
683 xml_path += _statefile_suffix;
687 // Make backup of state file
689 if ((access (xml_path.c_str(), F_OK) == 0) &&
690 (rename(xml_path.c_str(), bak_path.c_str()))) {
691 error << _("could not backup old state file, current state not saved.") << endmsg;
698 xml_path += snapshot_name;
699 xml_path += _pending_suffix;
703 if (!tree.write (xml_path)) {
704 error << string_compose (_("state could not be saved to %1"), xml_path) << endmsg;
706 /* don't leave a corrupt file lying around if it is
710 if (unlink (xml_path.c_str())) {
711 error << string_compose (_("could not remove corrupt state file %1"), xml_path) << endmsg;
714 if (rename (bak_path.c_str(), xml_path.c_str())) {
715 error << string_compose (_("could not restore state file from backup %1"), bak_path) << endmsg;
725 bool was_dirty = dirty();
727 _state_of_the_state = StateOfTheState (_state_of_the_state & ~Dirty);
730 DirtyChanged (); /* EMIT SIGNAL */
733 StateSaved (snapshot_name); /* EMIT SIGNAL */
740 Session::restore_state (string snapshot_name)
742 if (load_state (snapshot_name) == 0) {
743 set_state (*state_tree->root());
750 Session::load_state (string snapshot_name)
759 state_was_pending = false;
761 /* check for leftover pending state from a crashed capture attempt */
764 xmlpath += snapshot_name;
765 xmlpath += _pending_suffix;
767 if (!access (xmlpath.c_str(), F_OK)) {
769 /* there is pending state from a crashed capture attempt */
771 if (AskAboutPendingState()) {
772 state_was_pending = true;
776 if (!state_was_pending) {
779 xmlpath += snapshot_name;
780 xmlpath += _statefile_suffix;
783 if (access (xmlpath.c_str(), F_OK)) {
784 error << string_compose(_("%1: session state information file \"%2\" doesn't exist!"), _name, xmlpath) << endmsg;
788 state_tree = new XMLTree;
792 if (state_tree->read (xmlpath)) {
795 error << string_compose(_("Could not understand ardour file %1"), xmlpath) << endmsg;
804 Session::load_options (const XMLNode& node)
808 bool have_fade_msecs = false;
809 bool have_fade_steepness = false;
810 float fade_msecs = 0;
811 float fade_steepness = 0;
812 SlaveSource slave_src = None;
814 LocaleGuard lg (X_("POSIX"));
816 if ((child = find_named_node (node, "input-auto-connect")) != 0) {
817 if ((prop = child->property ("val")) != 0) {
818 sscanf (prop->value().c_str(), "%x", &x);
819 input_auto_connect = AutoConnectOption (x);
823 if ((child = find_named_node (node, "output-auto-connect")) != 0) {
824 if ((prop = child->property ("val")) != 0) {
825 sscanf (prop->value().c_str(), "%x", &x);
826 output_auto_connect = AutoConnectOption (x);
830 if ((child = find_named_node (node, "slave")) != 0) {
831 if ((prop = child->property ("type")) != 0) {
832 if (prop->value() == "none") {
834 } else if (prop->value() == "mtc") {
836 } else if (prop->value() == "jack") {
839 set_slave_source (slave_src, 0);
843 /* we cannot set edit mode if we are loading a session,
844 because it might destroy the playlist's positioning
847 if ((child = find_named_node (node, "edit-mode")) != 0) {
848 if ((prop = child->property ("val")) != 0) {
849 if (prop->value() == "slide") {
850 pending_edit_mode = Slide;
851 } else if (prop->value() == "splice") {
852 pending_edit_mode = Splice;
857 if ((child = find_named_node (node, "send-midi-timecode")) != 0) {
858 if ((prop = child->property ("val")) != 0) {
859 bool x = (prop->value() == "yes");
860 send_mtc = !x; /* force change in value */
864 if ((child = find_named_node (node, "send-midi-machine-control")) != 0) {
865 if ((prop = child->property ("val")) != 0) {
866 bool x = (prop->value() == "yes");
867 send_mmc = !x; /* force change in value */
868 set_send_mmc (prop->value() == "yes");
871 if ((child = find_named_node (node, "max-level")) != 0) {
872 if ((prop = child->property ("val")) != 0) {
873 max_level = atoi (prop->value().c_str());
876 if ((child = find_named_node (node, "min-level")) != 0) {
877 if ((prop = child->property ("val")) != 0) {
878 min_level = atoi (prop->value().c_str());
881 if ((child = find_named_node (node, "meter-hold")) != 0) {
882 if ((prop = child->property ("val")) != 0) {
883 _meter_hold = atof (prop->value().c_str());
886 if ((child = find_named_node (node, "meter-falloff")) != 0) {
887 if ((prop = child->property ("val")) != 0) {
888 _meter_falloff = atof (prop->value().c_str());
891 if ((child = find_named_node (node, "long-over-length")) != 0) {
892 if ((prop = child->property ("val")) != 0) {
893 over_length_long = atoi (prop->value().c_str());
896 if ((child = find_named_node (node, "short-over-length")) != 0) {
897 if ((prop = child->property ("val")) != 0) {
898 over_length_short = atoi (prop->value().c_str());
901 if ((child = find_named_node (node, "shuttle-speed-factor")) != 0) {
902 if ((prop = child->property ("val")) != 0) {
903 shuttle_speed_factor = atof (prop->value().c_str());
906 if ((child = find_named_node (node, "shuttle-speed-threshold")) != 0) {
907 if ((prop = child->property ("val")) != 0) {
908 shuttle_speed_threshold = atof (prop->value().c_str());
911 if ((child = find_named_node (node, "rf-speed")) != 0) {
912 if ((prop = child->property ("val")) != 0) {
913 rf_speed = atof (prop->value().c_str());
916 if ((child = find_named_node (node, "smpte-frames-per-second")) != 0) {
917 if ((prop = child->property ("val")) != 0) {
918 set_smpte_type( atof (prop->value().c_str()), smpte_drop_frames );
921 if ((child = find_named_node (node, "smpte-drop-frames")) != 0) {
922 if ((prop = child->property ("val")) != 0) {
923 set_smpte_type( smpte_frames_per_second, (prop->value() == "yes") );
926 if ((child = find_named_node (node, "smpte-offset")) != 0) {
927 if ((prop = child->property ("val")) != 0) {
928 set_smpte_offset( atoi (prop->value().c_str()) );
931 if ((child = find_named_node (node, "smpte-offset-negative")) != 0) {
932 if ((prop = child->property ("val")) != 0) {
933 set_smpte_offset_negative( (prop->value() == "yes") );
936 if ((child = find_named_node (node, "click-sound")) != 0) {
937 if ((prop = child->property ("val")) != 0) {
938 click_sound = prop->value();
941 if ((child = find_named_node (node, "click-emphasis-sound")) != 0) {
942 if ((prop = child->property ("val")) != 0) {
943 click_emphasis_sound = prop->value();
947 if ((child = find_named_node (node, "solo-model")) != 0) {
948 if ((prop = child->property ("val")) != 0) {
949 if (prop->value() == "SoloBus")
950 _solo_model = SoloBus;
952 _solo_model = InverseMute;
956 /* BOOLEAN OPTIONS */
958 if ((child = find_named_node (node, "auto-play")) != 0) {
959 if ((prop = child->property ("val")) != 0) {
960 set_auto_play (prop->value() == "yes");
963 if ((child = find_named_node (node, "auto-input")) != 0) {
964 if ((prop = child->property ("val")) != 0) {
965 set_auto_input (prop->value() == "yes");
968 if ((child = find_named_node (node, "seamless-loop")) != 0) {
969 if ((prop = child->property ("val")) != 0) {
970 set_seamless_loop (prop->value() == "yes");
973 if ((child = find_named_node (node, "punch-in")) != 0) {
974 if ((prop = child->property ("val")) != 0) {
975 set_punch_in (prop->value() == "yes");
978 if ((child = find_named_node (node, "punch-out")) != 0) {
979 if ((prop = child->property ("val")) != 0) {
980 set_punch_out (prop->value() == "yes");
983 if ((child = find_named_node (node, "auto-return")) != 0) {
984 if ((prop = child->property ("val")) != 0) {
985 set_auto_return (prop->value() == "yes");
988 if ((child = find_named_node (node, "send-mtc")) != 0) {
989 if ((prop = child->property ("val")) != 0) {
990 set_send_mtc (prop->value() == "yes");
993 if ((child = find_named_node (node, "mmc-control")) != 0) {
994 if ((prop = child->property ("val")) != 0) {
995 set_mmc_control (prop->value() == "yes");
998 if ((child = find_named_node (node, "midi-control")) != 0) {
999 if ((prop = child->property ("val")) != 0) {
1000 set_midi_control (prop->value() == "yes");
1003 if ((child = find_named_node (node, "midi-feedback")) != 0) {
1004 if ((prop = child->property ("val")) != 0) {
1005 set_midi_feedback (prop->value() == "yes");
1008 // Legacy support for <recording-plugins>
1009 if ((child = find_named_node (node, "recording-plugins")) != 0) {
1010 if ((prop = child->property ("val")) != 0) {
1011 set_do_not_record_plugins (prop->value() == "no");
1014 if ((child = find_named_node (node, "do-not-record-plugins")) != 0) {
1015 if ((prop = child->property ("val")) != 0) {
1016 set_do_not_record_plugins (prop->value() == "yes");
1019 if ((child = find_named_node (node, "crossfades-active")) != 0) {
1020 if ((prop = child->property ("val")) != 0) {
1021 set_crossfades_active (prop->value() == "yes");
1024 if ((child = find_named_node (node, "audible-click")) != 0) {
1025 if ((prop = child->property ("val")) != 0) {
1026 set_clicking (prop->value() == "yes");
1030 if ((child = find_named_node (node, "end-marker-is-free")) != 0) {
1031 if ((prop = child->property ("val")) != 0) {
1032 _end_location_is_free = (prop->value() == "yes");
1036 if ((child = find_named_node (node, "layer-model")) != 0) {
1037 if ((prop = child->property ("val")) != 0) {
1038 if (prop->value() == X_("LaterHigher")) {
1039 set_layer_model (LaterHigher);
1040 } else if (prop->value() == X_("AddHigher")) {
1041 set_layer_model (AddHigher);
1043 set_layer_model (MoveAddHigher);
1048 if ((child = find_named_node (node, "xfade-model")) != 0) {
1049 if ((prop = child->property ("val")) != 0) {
1050 if (prop->value() == X_("Short")) {
1051 set_xfade_model (ShortCrossfade);
1053 set_xfade_model (FullCrossfade);
1058 if ((child = find_named_node (node, "short-xfade-length")) != 0) {
1059 if ((prop = child->property ("val")) != 0) {
1060 /* value is stored as a fractional seconds */
1061 float secs = atof (prop->value().c_str());
1062 Crossfade::set_short_xfade_length ((jack_nframes_t) floor (secs * frame_rate()));
1066 if ((child = find_named_node (node, "full-xfades-unmuted")) != 0) {
1067 if ((prop = child->property ("val")) != 0) {
1068 crossfades_active = (prop->value() == "yes");
1074 if ((child = find_named_node (node, "default-fade-steepness")) != 0) {
1075 if ((prop = child->property ("val")) != 0) {
1076 fade_steepness = atof (prop->value().c_str());
1077 have_fade_steepness = true;
1080 if ((child = find_named_node (node, "default-fade-msec")) != 0) {
1081 if ((prop = child->property ("val")) != 0) {
1082 fade_msecs = atof (prop->value().c_str());
1083 have_fade_msecs = true;
1087 if (have_fade_steepness || have_fade_msecs) {
1088 // set_default_fade (fade_steepness, fade_msecs);
1095 Session::get_options () const
1100 LocaleGuard lg (X_("POSIX"));
1102 opthead = new XMLNode ("Options");
1104 SlaveSource src = slave_source ();
1108 src_string = "none";
1114 src_string = "jack";
1117 child = opthead->add_child ("slave");
1118 child->add_property ("type", src_string);
1120 child = opthead->add_child ("send-midi-timecode");
1121 child->add_property ("val", send_midi_timecode?"yes":"no");
1123 child = opthead->add_child ("send-midi-machine-control");
1124 child->add_property ("val", send_midi_machine_control?"yes":"no");
1126 snprintf (buf, sizeof(buf)-1, "%x", (int) input_auto_connect);
1127 child = opthead->add_child ("input-auto-connect");
1128 child->add_property ("val", buf);
1130 snprintf (buf, sizeof(buf)-1, "%x", (int) output_auto_connect);
1131 child = opthead->add_child ("output-auto-connect");
1132 child->add_property ("val", buf);
1134 snprintf (buf, sizeof(buf)-1, "%d", max_level);
1135 child = opthead->add_child ("max-level");
1136 child->add_property ("val", buf);
1138 snprintf (buf, sizeof(buf)-1, "%d", min_level);
1139 child = opthead->add_child ("min-level");
1140 child->add_property ("val", buf);
1142 snprintf (buf, sizeof(buf)-1, "%f", _meter_hold);
1143 child = opthead->add_child ("meter-hold");
1144 child->add_property ("val", buf);
1146 snprintf (buf, sizeof(buf)-1, "%f", _meter_falloff);
1147 child = opthead->add_child ("meter-falloff");
1148 child->add_property ("val", buf);
1150 snprintf (buf, sizeof(buf)-1, "%u", over_length_long);
1151 child = opthead->add_child ("long-over-length");
1152 child->add_property ("val", buf);
1154 snprintf (buf, sizeof(buf)-1, "%u", over_length_short);
1155 child = opthead->add_child ("short-over-length");
1156 child->add_property ("val", buf);
1158 snprintf (buf, sizeof(buf)-1, "%f", shuttle_speed_factor);
1159 child = opthead->add_child ("shuttle-speed-factor");
1160 child->add_property ("val", buf);
1162 snprintf (buf, sizeof(buf)-1, "%f", shuttle_speed_threshold);
1163 child = opthead->add_child ("shuttle-speed-threshold");
1164 child->add_property ("val", buf);
1166 snprintf (buf, sizeof(buf)-1, "%f", rf_speed);
1167 child = opthead->add_child ("rf-speed");
1168 child->add_property ("val", buf);
1170 snprintf (buf, sizeof(buf)-1, "%.2f", smpte_frames_per_second);
1171 child = opthead->add_child ("smpte-frames-per-second");
1172 child->add_property ("val", buf);
1174 child = opthead->add_child ("smpte-drop-frames");
1175 child->add_property ("val", smpte_drop_frames ? "yes" : "no");
1177 snprintf (buf, sizeof(buf)-1, "%u", smpte_offset ());
1178 child = opthead->add_child ("smpte-offset");
1179 child->add_property ("val", buf);
1181 child = opthead->add_child ("smpte-offset-negative");
1182 child->add_property ("val", smpte_offset_negative () ? "yes" : "no");
1184 child = opthead->add_child ("edit-mode");
1185 switch (_edit_mode) {
1187 child->add_property ("val", "splice");
1191 child->add_property ("val", "slide");
1195 child = opthead->add_child ("auto-play");
1196 child->add_property ("val", get_auto_play () ? "yes" : "no");
1197 child = opthead->add_child ("auto-input");
1198 child->add_property ("val", get_auto_input () ? "yes" : "no");
1199 child = opthead->add_child ("seamless-loop");
1200 child->add_property ("val", get_seamless_loop () ? "yes" : "no");
1201 child = opthead->add_child ("punch-in");
1202 child->add_property ("val", get_punch_in () ? "yes" : "no");
1203 child = opthead->add_child ("punch-out");
1204 child->add_property ("val", get_punch_out () ? "yes" : "no");
1205 child = opthead->add_child ("all-safe");
1206 child->add_property ("val", get_all_safe () ? "yes" : "no");
1207 child = opthead->add_child ("auto-return");
1208 child->add_property ("val", get_auto_return () ? "yes" : "no");
1209 child = opthead->add_child ("mmc-control");
1210 child->add_property ("val", get_mmc_control () ? "yes" : "no");
1211 child = opthead->add_child ("midi-control");
1212 child->add_property ("val", get_midi_control () ? "yes" : "no");
1213 child = opthead->add_child ("midi-feedback");
1214 child->add_property ("val", get_midi_feedback () ? "yes" : "no");
1215 child = opthead->add_child ("do-not-record-plugins");
1216 child->add_property ("val", get_do_not_record_plugins () ? "yes" : "no");
1217 child = opthead->add_child ("auto-crossfade");
1218 child->add_property ("val", get_crossfades_active () ? "yes" : "no");
1219 child = opthead->add_child ("audible-click");
1220 child->add_property ("val", get_clicking () ? "yes" : "no");
1221 child = opthead->add_child ("end-marker-is-free");
1222 child->add_property ("val", _end_location_is_free ? "yes" : "no");
1224 if (click_sound.length()) {
1225 child = opthead->add_child ("click-sound");
1226 child->add_property ("val", click_sound);
1229 if (click_emphasis_sound.length()) {
1230 child = opthead->add_child ("click-emphasis-sound");
1231 child->add_property ("val", click_emphasis_sound);
1234 child = opthead->add_child ("solo-model");
1235 child->add_property ("val", _solo_model == SoloBus ? "SoloBus" : "InverseMute");
1237 child = opthead->add_child ("layer-model");
1238 switch (layer_model) {
1240 child->add_property ("val", X_("LaterHigher"));
1243 child->add_property ("val", X_("MoveAddHigher"));
1246 child->add_property ("val", X_("AddHigher"));
1250 child = opthead->add_child ("xfade-model");
1251 switch (xfade_model) {
1253 child->add_property ("val", X_("Full"));
1255 case ShortCrossfade:
1256 child->add_property ("val", X_("Short"));
1259 child = opthead->add_child ("short-xfade-length");
1260 /* store as fractions of a second */
1261 snprintf (buf, sizeof(buf)-1, "%f",
1262 (float) Crossfade::short_xfade_length() / frame_rate());
1263 child->add_property ("val", buf);
1265 child = opthead->add_child ("full-xfades-unmuted");
1266 child->add_property ("val", crossfades_active ? "yes" : "no");
1272 Session::get_state()
1278 Session::get_template()
1280 /* if we don't disable rec-enable, diskstreams
1281 will believe they need to store their capture
1282 sources in their state node.
1285 disable_record (false);
1287 return state(false);
1291 Session::state(bool full_state)
1293 XMLNode* node = new XMLNode("Session");
1296 // store libardour version, just in case
1298 snprintf(buf, sizeof(buf)-1, "%d.%d.%d",
1299 libardour_major_version, libardour_minor_version, libardour_micro_version);
1300 node->add_property("version", string(buf));
1302 /* store configuration settings */
1306 /* store the name */
1307 node->add_property ("name", _name);
1309 if (session_dirs.size() > 1) {
1313 vector<space_and_path>::iterator i = session_dirs.begin();
1314 vector<space_and_path>::iterator next;
1316 ++i; /* skip the first one */
1320 while (i != session_dirs.end()) {
1324 if (next != session_dirs.end()) {
1334 child = node->add_child ("Path");
1335 child->add_content (p);
1339 /* save the ID counter */
1341 snprintf (buf, sizeof (buf), "%" PRIu64, ID::counter());
1342 node->add_property ("id-counter", buf);
1344 /* various options */
1346 node->add_child_nocopy (get_options());
1348 child = node->add_child ("Sources");
1351 Glib::Mutex::Lock sl (audio_source_lock);
1353 for (AudioSourceList::iterator siter = audio_sources.begin(); siter != audio_sources.end(); ++siter) {
1355 /* Don't save information about AudioFileSources that are empty */
1357 AudioFileSource* fs;
1359 if ((fs = dynamic_cast<AudioFileSource*> (siter->second)) != 0) {
1360 DestructiveFileSource* dfs = dynamic_cast<DestructiveFileSource*> (fs);
1362 /* destructive file sources are OK if they are empty, because
1363 we will re-use them every time.
1367 if (fs->length() == 0) {
1373 child->add_child_nocopy (siter->second->get_state());
1377 child = node->add_child ("Regions");
1380 Glib::Mutex::Lock rl (region_lock);
1382 for (AudioRegionList::const_iterator i = audio_regions.begin(); i != audio_regions.end(); ++i) {
1384 /* only store regions not attached to playlists */
1386 if (i->second->playlist() == 0) {
1387 child->add_child_nocopy (i->second->state (true));
1392 child = node->add_child ("DiskStreams");
1395 Glib::RWLock::ReaderLock dl (diskstream_lock);
1396 for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
1397 if (!(*i)->hidden()) {
1398 child->add_child_nocopy ((*i)->get_state());
1403 node->add_child_nocopy (_locations.get_state());
1405 child = node->add_child ("Connections");
1407 Glib::Mutex::Lock lm (connection_lock);
1408 for (ConnectionList::iterator i = _connections.begin(); i != _connections.end(); ++i) {
1409 if (!(*i)->system_dependent()) {
1410 child->add_child_nocopy ((*i)->get_state());
1415 child = node->add_child ("Routes");
1417 boost::shared_ptr<RouteList> r = routes.reader ();
1419 RoutePublicOrderSorter cmp;
1420 RouteList public_order (*r);
1421 public_order.sort (cmp);
1423 for (RouteList::iterator i = public_order.begin(); i != public_order.end(); ++i) {
1424 if (!(*i)->hidden()) {
1426 child->add_child_nocopy ((*i)->get_state());
1428 child->add_child_nocopy ((*i)->get_template());
1435 child = node->add_child ("EditGroups");
1436 for (list<RouteGroup *>::iterator i = edit_groups.begin(); i != edit_groups.end(); ++i) {
1437 child->add_child_nocopy ((*i)->get_state());
1440 child = node->add_child ("MixGroups");
1441 for (list<RouteGroup *>::iterator i = mix_groups.begin(); i != mix_groups.end(); ++i) {
1442 child->add_child_nocopy ((*i)->get_state());
1445 child = node->add_child ("Playlists");
1446 for (PlaylistList::iterator i = playlists.begin(); i != playlists.end(); ++i) {
1447 if (!(*i)->hidden()) {
1448 if (!(*i)->empty()) {
1450 child->add_child_nocopy ((*i)->get_state());
1452 child->add_child_nocopy ((*i)->get_template());
1458 child = node->add_child ("UnusedPlaylists");
1459 for (PlaylistList::iterator i = unused_playlists.begin(); i != unused_playlists.end(); ++i) {
1460 if (!(*i)->hidden()) {
1461 if (!(*i)->empty()) {
1463 child->add_child_nocopy ((*i)->get_state());
1465 child->add_child_nocopy ((*i)->get_template());
1473 child = node->add_child ("Click");
1474 child->add_child_nocopy (_click_io->state (full_state));
1478 child = node->add_child ("NamedSelections");
1479 for (NamedSelectionList::iterator i = named_selections.begin(); i != named_selections.end(); ++i) {
1481 child->add_child_nocopy ((*i)->get_state());
1486 node->add_child_nocopy (_tempo_map->get_state());
1489 node->add_child_copy (*_extra_xml);
1496 Session::set_state (const XMLNode& node)
1500 const XMLProperty* prop;
1503 _state_of_the_state = StateOfTheState (_state_of_the_state|CannotSave);
1505 if (node.name() != X_("Session")){
1506 fatal << _("programming error: Session: incorrect XML node sent to set_state()") << endmsg;
1510 StateManager::prohibit_save ();
1512 if ((prop = node.property ("name")) != 0) {
1513 _name = prop->value ();
1516 if ((prop = node.property (X_("id-counter"))) != 0) {
1518 sscanf (prop->value().c_str(), "%" PRIu64, &x);
1519 ID::init_counter (x);
1521 /* old sessions used a timebased counter, so fake
1522 the startup ID counter based on a standard
1527 ID::init_counter (now);
1531 IO::disable_ports ();
1532 IO::disable_connecting ();
1534 /* Object loading order:
1551 if (use_config_midi_ports ()) {
1554 if ((child = find_named_node (node, "Path")) != 0) {
1555 /* XXX this XML content stuff horrible API design */
1556 string raid_path = _path + ':' + child->children().front()->content();
1557 setup_raid_path (raid_path);
1559 /* the path is already set */
1562 if ((child = find_named_node (node, "extra")) != 0) {
1563 _extra_xml = new XMLNode (*child);
1566 if ((child = find_named_node (node, "Options")) == 0) {
1567 error << _("Session: XML state has no options section") << endmsg;
1568 } else if (load_options (*child)) {
1571 if ((child = find_named_node (node, "Sources")) == 0) {
1572 error << _("Session: XML state has no sources section") << endmsg;
1574 } else if (load_sources (*child)) {
1578 if ((child = find_named_node (node, "Regions")) == 0) {
1579 error << _("Session: XML state has no Regions section") << endmsg;
1581 } else if (load_regions (*child)) {
1585 if ((child = find_named_node (node, "Playlists")) == 0) {
1586 error << _("Session: XML state has no playlists section") << endmsg;
1588 } else if (load_playlists (*child)) {
1592 if ((child = find_named_node (node, "UnusedPlaylists")) == 0) {
1594 } else if (load_unused_playlists (*child)) {
1598 if ((child = find_named_node (node, "NamedSelections")) != 0) {
1599 if (load_named_selections (*child)) {
1604 if ((child = find_named_node (node, "DiskStreams")) == 0) {
1605 error << _("Session: XML state has no diskstreams section") << endmsg;
1607 } else if (load_diskstreams (*child)) {
1611 if ((child = find_named_node (node, "Connections")) == 0) {
1612 error << _("Session: XML state has no connections section") << endmsg;
1614 } else if (load_connections (*child)) {
1618 if ((child = find_named_node (node, "Locations")) == 0) {
1619 error << _("Session: XML state has no locations section") << endmsg;
1621 } else if (_locations.set_state (*child)) {
1627 if ((location = _locations.auto_loop_location()) != 0) {
1628 set_auto_loop_location (location);
1631 if ((location = _locations.auto_punch_location()) != 0) {
1632 set_auto_punch_location (location);
1635 if ((location = _locations.end_location()) == 0) {
1636 _locations.add (end_location);
1638 delete end_location;
1639 end_location = location;
1642 if ((location = _locations.start_location()) == 0) {
1643 _locations.add (start_location);
1645 delete start_location;
1646 start_location = location;
1649 _locations.save_state (_("initial state"));
1651 if ((child = find_named_node (node, "EditGroups")) == 0) {
1652 error << _("Session: XML state has no edit groups section") << endmsg;
1654 } else if (load_edit_groups (*child)) {
1658 if ((child = find_named_node (node, "MixGroups")) == 0) {
1659 error << _("Session: XML state has no mix groups section") << endmsg;
1661 } else if (load_mix_groups (*child)) {
1665 if ((child = find_named_node (node, "TempoMap")) == 0) {
1666 error << _("Session: XML state has no Tempo Map section") << endmsg;
1668 } else if (_tempo_map->set_state (*child)) {
1672 if ((child = find_named_node (node, "Routes")) == 0) {
1673 error << _("Session: XML state has no routes section") << endmsg;
1675 } else if (load_routes (*child)) {
1679 if ((child = find_named_node (node, "Click")) == 0) {
1680 warning << _("Session: XML state has no click section") << endmsg;
1681 } else if (_click_io) {
1682 _click_io->set_state (*child);
1685 /* OK, now we can set edit mode */
1687 set_edit_mode (pending_edit_mode);
1689 /* here beginneth the second phase ... */
1691 StateReady (); /* EMIT SIGNAL */
1693 _state_of_the_state = Clean;
1695 StateManager::allow_save (_("initial state"), true);
1697 if (state_was_pending) {
1698 save_state (_current_snapshot_name);
1699 save_history (_current_snapshot_name);
1700 remove_pending_capture_state ();
1701 state_was_pending = false;
1707 /* we failed, re-enable state saving but don't actually save internal state */
1708 StateManager::allow_save (X_("ignored"), false);
1713 Session::load_routes (const XMLNode& node)
1716 XMLNodeConstIterator niter;
1718 nlist = node.children();
1722 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1724 boost::shared_ptr<Route> route (XMLRouteFactory (**niter));
1727 error << _("Session: cannot create Route from XML description.") << endmsg;
1737 boost::shared_ptr<Route>
1738 Session::XMLRouteFactory (const XMLNode& node)
1740 if (node.name() != "Route") {
1741 return boost::shared_ptr<Route> ((Route*) 0);
1744 bool has_diskstream = (node.property ("diskstream") != 0 || node.property ("diskstream-id") != 0);
1746 DataType type = DataType::AUDIO;
1747 const XMLProperty* prop = node.property("default-type");
1749 type = DataType(prop->value());
1751 assert(type != DataType::NIL);
1753 if (has_diskstream) {
1754 if (type == DataType::AUDIO) {
1755 boost::shared_ptr<Route> ret (new AudioTrack (*this, node));
1758 boost::shared_ptr<Route> ret (new MidiTrack (*this, node));
1762 boost::shared_ptr<Route> ret (new Route (*this, node));
1768 Session::load_regions (const XMLNode& node)
1771 XMLNodeConstIterator niter;
1772 AudioRegion* region;
1774 nlist = node.children();
1778 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1779 if ((region = XMLRegionFactory (**niter, false)) == 0) {
1780 error << _("Session: cannot create Region from XML description.") << endmsg;
1787 Session::XMLRegionFactory (const XMLNode& node, bool full)
1789 const XMLProperty* prop;
1792 AudioRegion::SourceList sources;
1793 uint32_t nchans = 1;
1796 if (node.name() != X_("Region")) {
1800 if ((prop = node.property (X_("channels"))) != 0) {
1801 nchans = atoi (prop->value().c_str());
1805 if ((prop = node.property (X_("source-0"))) == 0) {
1806 if ((prop = node.property ("source")) == 0) {
1807 error << _("Session: XMLNode describing a AudioRegion is incomplete (no source)") << endmsg;
1812 PBD::ID s_id (prop->value());
1814 if ((source = source_by_id (s_id)) == 0) {
1815 error << string_compose(_("Session: XMLNode describing a AudioRegion references an unknown source id =%1"), s_id) << endmsg;
1819 as = dynamic_cast<AudioSource*>(source);
1821 error << string_compose(_("Session: XMLNode describing a AudioRegion references a non-audio source id =%1"), s_id) << endmsg;
1825 sources.push_back (as);
1827 /* pickup other channels */
1829 for (uint32_t n=1; n < nchans; ++n) {
1830 snprintf (buf, sizeof(buf), X_("source-%d"), n);
1831 if ((prop = node.property (buf)) != 0) {
1833 PBD::ID id2 (prop->value());
1835 if ((source = source_by_id (id2)) == 0) {
1836 error << string_compose(_("Session: XMLNode describing a AudioRegion references an unknown source id =%1"), id2) << endmsg;
1840 as = dynamic_cast<AudioSource*>(source);
1842 error << string_compose(_("Session: XMLNode describing a AudioRegion references a non-audio source id =%1"), id2) << endmsg;
1845 sources.push_back (as);
1850 return new AudioRegion (sources, node);
1853 catch (failed_constructor& err) {
1859 Session::get_sources_as_xml ()
1862 XMLNode* node = new XMLNode (X_("Sources"));
1863 Glib::Mutex::Lock lm (audio_source_lock);
1865 for (AudioSourceList::iterator i = audio_sources.begin(); i != audio_sources.end(); ++i) {
1866 node->add_child_nocopy (i->second->get_state());
1869 /* XXX get MIDI and other sources here */
1875 Session::path_from_region_name (string name, string identifier)
1877 char buf[PATH_MAX+1];
1879 string dir = discover_best_sound_dir ();
1881 for (n = 0; n < 999999; ++n) {
1882 if (identifier.length()) {
1883 snprintf (buf, sizeof(buf), "%s/%s%s%" PRIu32 ".wav", dir.c_str(), name.c_str(),
1884 identifier.c_str(), n);
1886 snprintf (buf, sizeof(buf), "%s/%s-%" PRIu32 ".wav", dir.c_str(), name.c_str(), n);
1888 if (access (buf, F_OK) != 0) {
1898 Session::load_sources (const XMLNode& node)
1901 XMLNodeConstIterator niter;
1904 nlist = node.children();
1908 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1910 if ((source = XMLSourceFactory (**niter)) == 0) {
1911 error << _("Session: cannot create Source from XML description.") << endmsg;
1919 Session::XMLSourceFactory (const XMLNode& node)
1923 if (node.name() != "Source") {
1928 src = AudioFileSource::create (node);
1931 catch (failed_constructor& err) {
1932 error << _("Found a sound file that cannot be used by Ardour. Talk to the progammers.") << endmsg;
1940 Session::save_template (string template_name)
1943 string xml_path, bak_path, template_path;
1945 if (_state_of_the_state & CannotSave) {
1950 string dir = template_dir();
1952 if ((dp = opendir (dir.c_str()))) {
1955 if (mkdir (dir.c_str(), S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH)<0) {
1956 error << string_compose(_("Could not create mix templates directory \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
1961 tree.set_root (&get_template());
1964 xml_path += template_name;
1965 xml_path += _template_suffix;
1967 ifstream in(xml_path.c_str());
1970 warning << string_compose(_("Template \"%1\" already exists - new version not created"), template_name) << endmsg;
1976 if (!tree.write (xml_path)) {
1977 error << _("mix template not saved") << endmsg;
1985 Session::rename_template (string old_name, string new_name)
1987 string old_path = template_dir() + old_name + _template_suffix;
1988 string new_path = template_dir() + new_name + _template_suffix;
1990 return rename (old_path.c_str(), new_path.c_str());
1994 Session::delete_template (string name)
1996 string template_path = template_dir();
1997 template_path += name;
1998 template_path += _template_suffix;
2000 return remove (template_path.c_str());
2004 Session::refresh_disk_space ()
2007 struct statfs statfsbuf;
2008 vector<space_and_path>::iterator i;
2009 Glib::Mutex::Lock lm (space_lock);
2012 /* get freespace on every FS that is part of the session path */
2014 _total_free_4k_blocks = 0;
2016 for (i = session_dirs.begin(); i != session_dirs.end(); ++i) {
2017 statfs ((*i).path.c_str(), &statfsbuf);
2019 scale = statfsbuf.f_bsize/4096.0;
2021 (*i).blocks = (uint32_t) floor (statfsbuf.f_bavail * scale);
2022 _total_free_4k_blocks += (*i).blocks;
2028 Session::ensure_sound_dir (string path, string& result)
2033 /* Ensure that the parent directory exists */
2035 if (mkdir (path.c_str(), 0775)) {
2036 if (errno != EEXIST) {
2037 error << string_compose(_("cannot create session directory \"%1\"; ignored"), path) << endmsg;
2042 /* Ensure that the sounds directory exists */
2046 result += sound_dir_name;
2048 if (mkdir (result.c_str(), 0775)) {
2049 if (errno != EEXIST) {
2050 error << string_compose(_("cannot create sounds directory \"%1\"; ignored"), result) << endmsg;
2057 dead += dead_sound_dir_name;
2059 if (mkdir (dead.c_str(), 0775)) {
2060 if (errno != EEXIST) {
2061 error << string_compose(_("cannot create dead sounds directory \"%1\"; ignored"), dead) << endmsg;
2068 peak += peak_dir_name;
2070 if (mkdir (peak.c_str(), 0775)) {
2071 if (errno != EEXIST) {
2072 error << string_compose(_("cannot create peak file directory \"%1\"; ignored"), peak) << endmsg;
2077 /* callers expect this to be terminated ... */
2084 Session::discover_best_sound_dir (bool destructive)
2086 vector<space_and_path>::iterator i;
2089 /* destructive files all go into the same place */
2095 /* handle common case without system calls */
2097 if (session_dirs.size() == 1) {
2101 /* OK, here's the algorithm we're following here:
2103 We want to select which directory to use for
2104 the next file source to be created. Ideally,
2105 we'd like to use a round-robin process so as to
2106 get maximum performance benefits from splitting
2107 the files across multiple disks.
2109 However, in situations without much diskspace, an
2110 RR approach may end up filling up a filesystem
2111 with new files while others still have space.
2112 Its therefore important to pay some attention to
2113 the freespace in the filesystem holding each
2114 directory as well. However, if we did that by
2115 itself, we'd keep creating new files in the file
2116 system with the most space until it was as full
2117 as all others, thus negating any performance
2118 benefits of this RAID-1 like approach.
2120 So, we use a user-configurable space threshold. If
2121 there are at least 2 filesystems with more than this
2122 much space available, we use RR selection between them.
2123 If not, then we pick the filesystem with the most space.
2125 This gets a good balance between the two
2129 refresh_disk_space ();
2131 int free_enough = 0;
2133 for (i = session_dirs.begin(); i != session_dirs.end(); ++i) {
2134 if ((*i).blocks * 4096 >= Config->get_disk_choice_space_threshold()) {
2139 if (free_enough >= 2) {
2141 bool found_it = false;
2143 /* use RR selection process, ensuring that the one
2147 i = last_rr_session_dir;
2150 if (++i == session_dirs.end()) {
2151 i = session_dirs.begin();
2154 if ((*i).blocks * 4096 >= Config->get_disk_choice_space_threshold()) {
2155 if (ensure_sound_dir ((*i).path, result) == 0) {
2156 last_rr_session_dir = i;
2162 } while (i != last_rr_session_dir);
2165 result = sound_dir();
2170 /* pick FS with the most freespace (and that
2171 seems to actually work ...)
2174 vector<space_and_path> sorted;
2175 space_and_path_ascending_cmp cmp;
2177 sorted = session_dirs;
2178 sort (sorted.begin(), sorted.end(), cmp);
2180 for (i = sorted.begin(); i != sorted.end(); ++i) {
2181 if (ensure_sound_dir ((*i).path, result) == 0) {
2182 last_rr_session_dir = i;
2187 /* if the above fails, fall back to the most simplistic solution */
2189 if (i == sorted.end()) {
2198 Session::load_playlists (const XMLNode& node)
2201 XMLNodeConstIterator niter;
2204 nlist = node.children();
2208 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2210 if ((playlist = XMLPlaylistFactory (**niter)) == 0) {
2211 error << _("Session: cannot create Playlist from XML description.") << endmsg;
2219 Session::load_unused_playlists (const XMLNode& node)
2222 XMLNodeConstIterator niter;
2225 nlist = node.children();
2229 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2231 if ((playlist = XMLPlaylistFactory (**niter)) == 0) {
2232 error << _("Session: cannot create Playlist from XML description.") << endmsg;
2236 // now manually untrack it
2238 track_playlist (playlist, false);
2246 Session::XMLPlaylistFactory (const XMLNode& node)
2249 return new AudioPlaylist (*this, node);
2252 catch (failed_constructor& err) {
2258 Session::load_named_selections (const XMLNode& node)
2261 XMLNodeConstIterator niter;
2264 nlist = node.children();
2268 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2270 if ((ns = XMLNamedSelectionFactory (**niter)) == 0) {
2271 error << _("Session: cannot create Named Selection from XML description.") << endmsg;
2279 Session::XMLNamedSelectionFactory (const XMLNode& node)
2282 return new NamedSelection (*this, node);
2285 catch (failed_constructor& err) {
2291 Session::dead_sound_dir () const
2294 res += dead_sound_dir_name;
2300 Session::sound_dir () const
2303 res += sound_dir_name;
2309 Session::tape_dir () const
2312 res += tape_dir_name;
2318 Session::peak_dir () const
2321 res += peak_dir_name;
2327 Session::automation_dir () const
2330 res += "automation/";
2335 Session::template_dir ()
2337 string path = get_user_ardour_path();
2338 path += "templates/";
2344 Session::suffixed_search_path (string suffix, bool data)
2348 path += get_user_ardour_path();
2349 if (path[path.length()-1] != ':') {
2354 path += get_system_data_path();
2356 path += get_system_module_path();
2359 vector<string> split_path;
2361 split (path, split_path, ':');
2364 for (vector<string>::iterator i = split_path.begin(); i != split_path.end(); ++i) {
2369 if (distance (i, split_path.end()) != 1) {
2378 Session::template_path ()
2380 return suffixed_search_path (X_("templates"), true);
2384 Session::control_protocol_path ()
2386 return suffixed_search_path (X_("surfaces"), false);
2390 Session::load_connections (const XMLNode& node)
2392 XMLNodeList nlist = node.children();
2393 XMLNodeConstIterator niter;
2397 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2398 if ((*niter)->name() == "InputConnection") {
2399 add_connection (new ARDOUR::InputConnection (**niter));
2400 } else if ((*niter)->name() == "OutputConnection") {
2401 add_connection (new ARDOUR::OutputConnection (**niter));
2403 error << string_compose(_("Unknown node \"%1\" found in Connections list from state file"), (*niter)->name()) << endmsg;
2412 Session::load_edit_groups (const XMLNode& node)
2414 return load_route_groups (node, true);
2418 Session::load_mix_groups (const XMLNode& node)
2420 return load_route_groups (node, false);
2424 Session::load_route_groups (const XMLNode& node, bool edit)
2426 XMLNodeList nlist = node.children();
2427 XMLNodeConstIterator niter;
2432 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2433 if ((*niter)->name() == "RouteGroup") {
2435 rg = add_edit_group ("");
2436 rg->set_state (**niter);
2438 rg = add_mix_group ("");
2439 rg->set_state (**niter);
2448 state_file_filter (const string &str, void *arg)
2450 return (str.length() > strlen(Session::statefile_suffix()) &&
2451 str.find (Session::statefile_suffix()) == (str.length() - strlen (Session::statefile_suffix())));
2455 bool operator()(const string* a, const string* b) {
2461 remove_end(string* state)
2463 string statename(*state);
2465 string::size_type start,end;
2466 if ((start = statename.find_last_of ('/')) != string::npos) {
2467 statename = statename.substr (start+1);
2470 if ((end = statename.rfind(".ardour")) == string::npos) {
2471 end = statename.length();
2474 return new string(statename.substr (0, end));
2478 Session::possible_states (string path)
2480 PathScanner scanner;
2481 vector<string*>* states = scanner (path, state_file_filter, 0, false, false);
2483 transform(states->begin(), states->end(), states->begin(), remove_end);
2486 sort (states->begin(), states->end(), cmp);
2492 Session::possible_states () const
2494 return possible_states(_path);
2498 Session::auto_save()
2500 save_state (_current_snapshot_name);
2501 save_history (_current_snapshot_name);
2505 Session::add_edit_group (string name)
2507 RouteGroup* rg = new RouteGroup (*this, name);
2508 edit_groups.push_back (rg);
2509 edit_group_added (rg); /* EMIT SIGNAL */
2515 Session::add_mix_group (string name)
2517 RouteGroup* rg = new RouteGroup (*this, name, RouteGroup::Relative);
2518 mix_groups.push_back (rg);
2519 mix_group_added (rg); /* EMIT SIGNAL */
2525 Session::remove_edit_group (RouteGroup& rg)
2527 list<RouteGroup*>::iterator i;
2529 if ((i = find (edit_groups.begin(), edit_groups.end(), &rg)) != edit_groups.end()) {
2530 (*i)->apply (&Route::drop_edit_group, this);
2531 edit_groups.erase (i);
2532 edit_group_removed (); /* EMIT SIGNAL */
2539 Session::remove_mix_group (RouteGroup& rg)
2541 list<RouteGroup*>::iterator i;
2543 if ((i = find (mix_groups.begin(), mix_groups.end(), &rg)) != mix_groups.end()) {
2544 (*i)->apply (&Route::drop_mix_group, this);
2545 mix_groups.erase (i);
2546 mix_group_removed (); /* EMIT SIGNAL */
2553 Session::mix_group_by_name (string name)
2555 list<RouteGroup *>::iterator i;
2557 for (i = mix_groups.begin(); i != mix_groups.end(); ++i) {
2558 if ((*i)->name() == name) {
2566 Session::edit_group_by_name (string name)
2568 list<RouteGroup *>::iterator i;
2570 for (i = edit_groups.begin(); i != edit_groups.end(); ++i) {
2571 if ((*i)->name() == name) {
2579 Session::set_meter_hold (float val)
2582 MeterHoldChanged(); // emit
2586 Session::set_meter_falloff (float val)
2588 _meter_falloff = val;
2589 MeterFalloffChanged(); // emit
2594 Session::begin_reversible_command (string name)
2596 current_trans.clear ();
2597 current_trans.set_name (name);
2601 Session::commit_reversible_command (Command *cmd)
2606 current_trans.add_command (cmd);
2609 gettimeofday (&now, 0);
2610 current_trans.set_timestamp (now);
2612 history.add (current_trans);
2615 Session::GlobalRouteBooleanState
2616 Session::get_global_route_boolean (bool (Route::*method)(void) const)
2618 GlobalRouteBooleanState s;
2619 boost::shared_ptr<RouteList> r = routes.reader ();
2621 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
2622 if (!(*i)->hidden()) {
2623 RouteBooleanState v;
2626 Route* r = (*i).get();
2627 v.second = (r->*method)();
2636 Session::GlobalRouteMeterState
2637 Session::get_global_route_metering ()
2639 GlobalRouteMeterState s;
2640 boost::shared_ptr<RouteList> r = routes.reader ();
2642 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
2643 if (!(*i)->hidden()) {
2647 v.second = (*i)->meter_point();
2657 Session::set_global_route_metering (GlobalRouteMeterState s, void* arg)
2659 for (GlobalRouteMeterState::iterator i = s.begin(); i != s.end(); ++i) {
2660 i->first->set_meter_point (i->second, arg);
2665 Session::set_global_route_boolean (GlobalRouteBooleanState s, void (Route::*method)(bool, void*), void* arg)
2667 for (GlobalRouteBooleanState::iterator i = s.begin(); i != s.end(); ++i) {
2668 Route* r = i->first.get();
2669 (r->*method) (i->second, arg);
2674 Session::set_global_mute (GlobalRouteBooleanState s, void* src)
2676 set_global_route_boolean (s, &Route::set_mute, src);
2680 Session::set_global_solo (GlobalRouteBooleanState s, void* src)
2682 set_global_route_boolean (s, &Route::set_solo, src);
2686 Session::set_global_record_enable (GlobalRouteBooleanState s, void* src)
2688 set_global_route_boolean (s, &Route::set_record_enable, src);
2693 Session::global_mute_memento (void* src)
2695 return sigc::bind (mem_fun (*this, &Session::set_global_mute), get_global_route_boolean (&Route::muted), src);
2699 Session::global_metering_memento (void* src)
2701 return sigc::bind (mem_fun (*this, &Session::set_global_route_metering), get_global_route_metering (), src);
2705 Session::global_solo_memento (void* src)
2707 return sigc::bind (mem_fun (*this, &Session::set_global_solo), get_global_route_boolean (&Route::soloed), src);
2711 Session::global_record_enable_memento (void* src)
2713 return sigc::bind (mem_fun (*this, &Session::set_global_record_enable), get_global_route_boolean (&Route::record_enabled), src);
2718 template_filter (const string &str, void *arg)
2720 return (str.length() > strlen(Session::template_suffix()) &&
2721 str.find (Session::template_suffix()) == (str.length() - strlen (Session::template_suffix())));
2725 Session::get_template_list (list<string> &template_names)
2727 vector<string *> *templates;
2728 PathScanner scanner;
2731 path = template_path ();
2733 templates = scanner (path, template_filter, 0, false, true);
2735 vector<string*>::iterator i;
2736 for (i = templates->begin(); i != templates->end(); ++i) {
2737 string fullpath = *(*i);
2740 start = fullpath.find_last_of ('/') + 1;
2741 if ((end = fullpath.find_last_of ('.')) <0) {
2742 end = fullpath.length();
2745 template_names.push_back(fullpath.substr(start, (end-start)));
2750 Session::read_favorite_dirs (FavoriteDirs & favs)
2752 string path = get_user_ardour_path();
2753 path += "/favorite_dirs";
2755 ifstream fav (path.c_str());
2760 if (errno != ENOENT) {
2761 //error << string_compose (_("cannot open favorite file %1 (%2)"), path, strerror (errno)) << endmsg;
2772 getline(fav, newfav);
2778 favs.push_back (newfav);
2785 Session::write_favorite_dirs (FavoriteDirs & favs)
2787 string path = get_user_ardour_path();
2788 path += "/favorite_dirs";
2790 ofstream fav (path.c_str());
2796 for (FavoriteDirs::iterator i = favs.begin(); i != favs.end(); ++i) {
2797 fav << (*i) << endl;
2804 accept_all_non_peak_files (const string& path, void *arg)
2806 return (path.length() > 5 && path.find (".peak") != (path.length() - 5));
2810 accept_all_state_files (const string& path, void *arg)
2812 return (path.length() > 7 && path.find (".ardour") == (path.length() - 7));
2816 Session::find_all_sources (string path, set<string>& result)
2821 if (!tree.read (path)) {
2825 if ((node = find_named_node (*tree.root(), "Sources")) == 0) {
2830 XMLNodeConstIterator niter;
2832 nlist = node->children();
2836 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2840 if ((prop = (*niter)->property (X_("name"))) == 0) {
2844 if (prop->value()[0] == '/') {
2845 /* external file, ignore */
2849 string path = _path; /* /-terminated */
2850 path += sound_dir_name;
2852 path += prop->value();
2854 result.insert (path);
2861 Session::find_all_sources_across_snapshots (set<string>& result, bool exclude_this_snapshot)
2863 PathScanner scanner;
2864 vector<string*>* state_files;
2866 string this_snapshot_path;
2872 if (ripped[ripped.length()-1] == '/') {
2873 ripped = ripped.substr (0, ripped.length() - 1);
2876 state_files = scanner (ripped, accept_all_state_files, (void *) 0, false, true);
2878 if (state_files == 0) {
2883 this_snapshot_path = _path;
2884 this_snapshot_path += _current_snapshot_name;
2885 this_snapshot_path += _statefile_suffix;
2887 for (vector<string*>::iterator i = state_files->begin(); i != state_files->end(); ++i) {
2889 if (exclude_this_snapshot && **i == this_snapshot_path) {
2893 if (find_all_sources (**i, result) < 0) {
2902 Session::cleanup_sources (Session::cleanup_report& rep)
2904 vector<Source*> dead_sources;
2905 vector<Playlist*> playlists_tbd;
2906 PathScanner scanner;
2908 vector<space_and_path>::iterator i;
2909 vector<space_and_path>::iterator nexti;
2910 vector<string*>* soundfiles;
2911 vector<string> unused;
2912 set<string> all_sources;
2917 _state_of_the_state = (StateOfTheState) (_state_of_the_state | InCleanup);
2919 /* step 1: consider deleting all unused playlists */
2921 for (PlaylistList::iterator x = unused_playlists.begin(); x != unused_playlists.end(); ++x) {
2924 status = AskAboutPlaylistDeletion (*x);
2933 playlists_tbd.push_back (*x);
2937 /* leave it alone */
2942 /* now delete any that were marked for deletion */
2944 for (vector<Playlist*>::iterator x = playlists_tbd.begin(); x != playlists_tbd.end(); ++x) {
2945 PlaylistList::iterator foo;
2947 if ((foo = unused_playlists.find (*x)) != unused_playlists.end()) {
2948 unused_playlists.erase (foo);
2953 /* step 2: clear the undo/redo history for all playlists */
2955 for (PlaylistList::iterator x = playlists.begin(); x != playlists.end(); ++x) {
2956 (*x)->drop_all_states ();
2959 /* step 3: find all un-referenced sources */
2964 for (AudioSourceList::iterator i = audio_sources.begin(); i != audio_sources.end(); ) {
2966 AudioSourceList::iterator tmp;
2971 /* only remove files that are not in use and have some size
2972 to them. otherwise we remove the current "nascent"
2976 if (i->second->use_cnt() == 0 && i->second->length() > 0) {
2977 dead_sources.push_back (i->second);
2979 /* remove this source from our own list to avoid us
2980 adding it to the list of all sources below
2983 audio_sources.erase (i);
2989 /* Step 4: get rid of all regions in the region list that use any dead sources
2990 in case the sources themselves don't go away (they might be referenced in
2994 for (vector<Source*>::iterator i = dead_sources.begin(); i != dead_sources.end();++i) {
2996 for (AudioRegionList::iterator r = audio_regions.begin(); r != audio_regions.end(); ) {
2997 AudioRegionList::iterator tmp;
3005 for (uint32_t n = 0; n < ar->n_channels(); ++n) {
3006 if (&ar->source (n) == (*i)) {
3007 /* this region is dead */
3016 /* build a list of all the possible sound directories for the session */
3018 for (i = session_dirs.begin(); i != session_dirs.end(); ) {
3023 sound_path += (*i).path;
3024 sound_path += sound_dir_name;
3026 if (nexti != session_dirs.end()) {
3033 /* now do the same thing for the files that ended up in the sounds dir(s)
3034 but are not referenced as sources in any snapshot.
3037 soundfiles = scanner (sound_path, accept_all_non_peak_files, (void *) 0, false, true);
3039 if (soundfiles == 0) {
3043 /* find all sources, but don't use this snapshot because the
3044 state file on disk still references sources we may have already
3048 find_all_sources_across_snapshots (all_sources, true);
3050 /* add our current source list
3053 for (AudioSourceList::iterator i = audio_sources.begin(); i != audio_sources.end(); ++i) {
3054 AudioFileSource* fs;
3056 if ((fs = dynamic_cast<AudioFileSource*> (i->second)) != 0) {
3057 all_sources.insert (fs->path());
3061 for (vector<string*>::iterator x = soundfiles->begin(); x != soundfiles->end(); ++x) {
3066 for (set<string>::iterator i = all_sources.begin(); i != all_sources.end(); ++i) {
3076 unused.push_back (spath);
3080 /* now try to move all unused files into the "dead_sounds" directory(ies) */
3082 for (vector<string>::iterator x = unused.begin(); x != unused.end(); ++x) {
3083 struct stat statbuf;
3085 rep.paths.push_back (*x);
3086 if (stat ((*x).c_str(), &statbuf) == 0) {
3087 rep.space += statbuf.st_size;
3092 /* don't move the file across filesystems, just
3093 stick it in the `dead_sound_dir_name' directory
3094 on whichever filesystem it was already on.
3097 newpath = Glib::path_get_dirname (*x);
3098 newpath = Glib::path_get_dirname (newpath);
3101 newpath += dead_sound_dir_name;
3103 newpath += Glib::path_get_basename ((*x));
3105 if (access (newpath.c_str(), F_OK) == 0) {
3107 /* the new path already exists, try versioning */
3109 char buf[PATH_MAX+1];
3113 snprintf (buf, sizeof (buf), "%s.%d", newpath.c_str(), version);
3116 while (access (newpath_v.c_str(), F_OK) == 0 && version < 999) {
3117 snprintf (buf, sizeof (buf), "%s.%d", newpath.c_str(), ++version);
3121 if (version == 999) {
3122 error << string_compose (_("there are already 1000 files with names like %1; versioning discontinued"),
3126 newpath = newpath_v;
3131 /* it doesn't exist, or we can't read it or something */
3135 if (::rename ((*x).c_str(), newpath.c_str()) != 0) {
3136 error << string_compose (_("cannot rename audio file source from %1 to %2 (%3)"),
3137 (*x), newpath, strerror (errno))
3143 /* see if there an easy to find peakfile for this file, and remove it.
3146 string peakpath = (*x).substr (0, (*x).find_last_of ('.'));
3147 peakpath += ".peak";
3149 if (access (peakpath.c_str(), W_OK) == 0) {
3150 if (::unlink (peakpath.c_str()) != 0) {
3151 error << string_compose (_("cannot remove peakfile %1 for %2 (%3)"),
3152 peakpath, _path, strerror (errno))
3154 /* try to back out */
3155 rename (newpath.c_str(), _path.c_str());
3164 /* dump the history list */
3168 /* save state so we don't end up a session file
3169 referring to non-existent sources.
3176 _state_of_the_state = (StateOfTheState) (_state_of_the_state & ~InCleanup);
3181 Session::cleanup_trash_sources (Session::cleanup_report& rep)
3183 vector<space_and_path>::iterator i;
3184 string dead_sound_dir;
3185 struct dirent* dentry;
3186 struct stat statbuf;
3192 for (i = session_dirs.begin(); i != session_dirs.end(); ++i) {
3194 dead_sound_dir = (*i).path;
3195 dead_sound_dir += dead_sound_dir_name;
3197 if ((dead = opendir (dead_sound_dir.c_str())) == 0) {
3201 while ((dentry = readdir (dead)) != 0) {
3203 /* avoid '.' and '..' */
3205 if ((dentry->d_name[0] == '.' && dentry->d_name[1] == '\0') ||
3206 (dentry->d_name[2] == '\0' && dentry->d_name[0] == '.' && dentry->d_name[1] == '.')) {
3212 fullpath = dead_sound_dir;
3214 fullpath += dentry->d_name;
3216 if (stat (fullpath.c_str(), &statbuf)) {
3220 if (!S_ISREG (statbuf.st_mode)) {
3224 if (unlink (fullpath.c_str())) {
3225 error << string_compose (_("cannot remove dead sound file %1 (%2)"),
3226 fullpath, strerror (errno))
3230 rep.paths.push_back (dentry->d_name);
3231 rep.space += statbuf.st_size;
3242 Session::set_dirty ()
3244 bool was_dirty = dirty();
3246 _state_of_the_state = StateOfTheState (_state_of_the_state | Dirty);
3249 DirtyChanged(); /* EMIT SIGNAL */
3255 Session::set_clean ()
3257 bool was_dirty = dirty();
3259 _state_of_the_state = Clean;
3262 DirtyChanged(); /* EMIT SIGNAL */
3267 Session::add_controllable (Controllable* c)
3269 Glib::Mutex::Lock lm (controllables_lock);
3270 controllables.push_back (c);
3274 Session::remove_controllable (Controllable* c)
3276 if (_state_of_the_state | Deletion) {
3280 Glib::Mutex::Lock lm (controllables_lock);
3281 controllables.remove (c);
3285 Session::controllable_by_id (const PBD::ID& id)
3287 Glib::Mutex::Lock lm (controllables_lock);
3289 for (Controllables::iterator i = controllables.begin(); i != controllables.end(); ++i) {
3290 if ((*i)->id() == id) {
3299 Session::add_instant_xml (XMLNode& node, const std::string& dir)
3301 Stateful::add_instant_xml (node, dir);
3302 Config->add_instant_xml (node, get_user_ardour_path());
3307 Session::save_history (string snapshot_name)
3313 tree.set_root (&history.get_state());
3315 if (snapshot_name.empty()) {
3316 snapshot_name = _current_snapshot_name;
3319 xml_path = _path + snapshot_name + ".history";
3321 bak_path = xml_path + ".bak";
3323 if ((access (xml_path.c_str(), F_OK) == 0) &&
3324 (rename (xml_path.c_str(), bak_path.c_str())))
3326 error << _("could not backup old history file, current history not saved.") << endmsg;
3330 if (!tree.write (xml_path))
3332 error << string_compose (_("history could not be saved to %1"), xml_path) << endmsg;
3334 /* don't leave a corrupt file lying around if it is
3338 if (unlink (xml_path.c_str()))
3340 error << string_compose (_("could not remove corrupt history file %1"), xml_path) << endmsg;
3342 if (rename (bak_path.c_str(), xml_path.c_str()))
3344 error << string_compose (_("could not restore history file from backup %1"), bak_path) << endmsg;