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/audio_diskstream.h>
62 #include <ardour/utils.h>
63 #include <ardour/audioplaylist.h>
64 #include <ardour/audiofilesource.h>
65 #include <ardour/destructive_filesource.h>
66 #include <ardour/sndfile_helpers.h>
67 #include <ardour/auditioner.h>
68 #include <ardour/export.h>
69 #include <ardour/redirect.h>
70 #include <ardour/send.h>
71 #include <ardour/insert.h>
72 #include <ardour/connection.h>
73 #include <ardour/slave.h>
74 #include <ardour/tempo.h>
75 #include <ardour/audio_track.h>
76 #include <ardour/cycle_timer.h>
77 #include <ardour/utils.h>
78 #include <ardour/named_selection.h>
79 #include <ardour/version.h>
80 #include <ardour/location.h>
81 #include <ardour/audioregion.h>
82 #include <ardour/crossfade.h>
83 #include <ardour/control_protocol_manager.h>
89 using namespace ARDOUR;
93 Session::first_stage_init (string fullpath, string snapshot_name)
95 if (fullpath.length() == 0) {
96 throw failed_constructor();
100 if (!realpath(fullpath.c_str(), buf) && (errno != ENOENT)) {
101 error << string_compose(_("Could not use path %1 (%s)"), buf, strerror(errno)) << endmsg;
102 throw failed_constructor();
106 if (_path[_path.length()-1] != '/') {
110 /* these two are just provisional settings. set_state()
111 will likely override them.
114 _name = _current_snapshot_name = snapshot_name;
115 setup_raid_path (_path);
117 _current_frame_rate = _engine.frame_rate ();
118 _tempo_map = new TempoMap (_current_frame_rate);
119 _tempo_map->StateChanged.connect (mem_fun (*this, &Session::tempo_map_changed));
121 g_atomic_int_set (&processing_prohibited, 0);
124 _transport_speed = 0;
125 _last_transport_speed = 0;
126 transport_sub_state = 0;
127 _transport_frame = 0;
129 end_location = new Location (0, 0, _("end"), Location::Flags ((Location::IsMark|Location::IsEnd)));
130 start_location = new Location (0, 0, _("start"), Location::Flags ((Location::IsMark|Location::IsStart)));
131 _end_location_is_free = true;
132 g_atomic_int_set (&_record_status, Disabled);
137 seamless_loop = false;
138 loop_changing = false;
140 crossfades_active = false;
143 _last_roll_location = 0;
144 _last_record_location = 0;
145 pending_locate_frame = 0;
146 pending_locate_roll = false;
147 pending_locate_flush = false;
148 dstream_buffer_size = 0;
150 state_was_pending = false;
152 outbound_mtc_smpte_frame = 0;
153 next_quarter_frame_to_send = -1;
154 current_block_size = 0;
155 _solo_latched = true;
156 _solo_model = InverseMute;
157 solo_update_disabled = false;
158 currently_soloing = false;
159 _have_captured = false;
160 _worst_output_latency = 0;
161 _worst_input_latency = 0;
162 _worst_track_latency = 0;
163 _state_of_the_state = StateOfTheState(CannotSave|InitialConnecting|Loading);
166 butler_mixdown_buffer = 0;
167 butler_gain_buffer = 0;
171 post_transport_work = PostTransportWork (0);
172 g_atomic_int_set (&butler_should_do_transport_work, 0);
173 g_atomic_int_set (&butler_active, 0);
174 g_atomic_int_set (&_playback_load, 100);
175 g_atomic_int_set (&_capture_load, 100);
176 g_atomic_int_set (&_playback_load_min, 100);
177 g_atomic_int_set (&_capture_load_min, 100);
178 pending_audition_region = 0;
180 pending_edit_mode = _edit_mode;
182 input_auto_connect = AutoConnectOption (0);
183 output_auto_connect = AutoConnectOption (0);
184 waiting_to_start = false;
186 _gain_automation_buffer = 0;
187 _pan_automation_buffer = 0;
189 pending_abort = false;
190 layer_model = MoveAddHigher;
191 xfade_model = ShortCrossfade;
192 destructive_index = 0;
194 AudioDiskstream::allocate_working_buffers();
196 /* default short fade = 15ms */
198 Crossfade::set_short_xfade_length ((jack_nframes_t) floor ((15.0 * frame_rate()) / 1000.0));
199 DestructiveFileSource::setup_standard_crossfades (frame_rate());
201 last_mmc_step.tv_sec = 0;
202 last_mmc_step.tv_usec = 0;
205 preroll.type = AnyTime::Frames;
207 postroll.type = AnyTime::Frames;
210 /* click sounds are unset by default, which causes us to internal
211 waveforms for clicks.
215 click_requested = false;
217 click_emphasis_data = 0;
219 click_emphasis_length = 0;
221 process_function = &Session::process_with_events;
225 _smpte_offset_negative = true;
226 last_smpte_valid = false;
228 last_rr_session_dir = session_dirs.begin();
229 refresh_disk_space ();
231 // set_default_fade (0.2, 5.0); /* steepness, millisecs */
233 /* default configuration */
235 do_not_record_plugins = false;
236 over_length_short = 2;
237 over_length_long = 10;
238 send_midi_timecode = false;
239 send_midi_machine_control = false;
240 shuttle_speed_factor = 1.0;
241 shuttle_speed_threshold = 5;
243 _meter_hold = 100; // XXX unknown units: number of calls to meter::set()
244 _meter_falloff = 1.5f; // XXX unknown units: refresh_rate
250 average_slave_delta = 1800;
251 have_first_delta_accumulator = false;
252 delta_accumulator_cnt = 0;
253 slave_state = Stopped;
255 /* default SMPTE type is 30 FPS, non-drop */
257 set_smpte_type (30.0, false);
259 _engine.GraphReordered.connect (mem_fun (*this, &Session::graph_reordered));
261 /* These are all static "per-class" signals */
263 Region::CheckNewRegion.connect (mem_fun (*this, &Session::add_region));
264 AudioSource::AudioSourceCreated.connect (mem_fun (*this, &Session::add_audio_source));
265 Playlist::PlaylistCreated.connect (mem_fun (*this, &Session::add_playlist));
266 Redirect::RedirectCreated.connect (mem_fun (*this, &Session::add_redirect));
267 AudioDiskstream::DiskstreamCreated.connect (mem_fun (*this, &Session::add_diskstream));
268 NamedSelection::NamedSelectionCreated.connect (mem_fun (*this, &Session::add_named_selection));
269 Curve::CurveCreated.connect (mem_fun (*this, &Session::add_curve));
270 AutomationList::AutomationListCreated.connect (mem_fun (*this, &Session::add_automation_list));
272 Controllable::Created.connect (mem_fun (*this, &Session::add_controllable));
273 Controllable::GoingAway.connect (mem_fun (*this, &Session::remove_controllable));
275 IO::MoreOutputs.connect (mem_fun (*this, &Session::ensure_passthru_buffers));
277 /* stop IO objects from doing stuff until we're ready for them */
279 IO::disable_panners ();
280 IO::disable_ports ();
281 IO::disable_connecting ();
285 Session::second_stage_init (bool new_session)
287 AudioFileSource::set_peak_dir (peak_dir());
290 if (load_state (_current_snapshot_name)) {
293 remove_empty_sounds ();
296 if (start_butler_thread()) {
300 if (start_midi_thread ()) {
305 if (set_state (*state_tree->root())) {
310 /* we can't save till after ::when_engine_running() is called,
311 because otherwise we save state with no connections made.
312 therefore, we reset _state_of_the_state because ::set_state()
313 will have cleared it.
315 we also have to include Loading so that any events that get
316 generated between here and the end of ::when_engine_running()
317 will be processed directly rather than queued.
320 _state_of_the_state = StateOfTheState (_state_of_the_state|CannotSave|Loading);
322 // set_auto_input (true);
323 _locations.changed.connect (mem_fun (this, &Session::locations_changed));
324 _locations.added.connect (mem_fun (this, &Session::locations_added));
325 setup_click_sounds (0);
326 setup_midi_control ();
328 /* Pay attention ... */
330 _engine.Halted.connect (mem_fun (*this, &Session::engine_halted));
331 _engine.Xrun.connect (mem_fun (*this, &Session::xrun_recovery));
333 if (_engine.running()) {
334 when_engine_running();
336 first_time_running = _engine.Running.connect (mem_fun (*this, &Session::when_engine_running));
339 send_full_time_code ();
340 _engine.transport_locate (0);
341 deliver_mmc (MIDI::MachineControl::cmdMmcReset, 0);
342 deliver_mmc (MIDI::MachineControl::cmdLocate, 0);
344 ControlProtocolManager::instance().set_session (*this);
347 _end_location_is_free = true;
349 _end_location_is_free = false;
356 Session::raid_path () const
360 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
365 return path.substr (0, path.length() - 1); // drop final colon
369 Session::set_raid_path (string path)
371 /* public-access to setup_raid_path() */
373 setup_raid_path (path);
377 Session::setup_raid_path (string path)
379 string::size_type colon;
383 string::size_type len = path.length();
388 if (path.length() == 0) {
392 session_dirs.clear ();
394 for (string::size_type n = 0; n < len; ++n) {
395 if (path[n] == ':') {
402 /* no multiple search path, just one location (common case) */
406 session_dirs.push_back (sp);
413 if (fspath[fspath.length()-1] != '/') {
416 fspath += sound_dir_name;
422 if (fspath[fspath.length()-1] != '/') {
425 fspath += tape_dir_name;
427 AudioFileSource::set_search_path (fspath);
434 while ((colon = remaining.find_first_of (':')) != string::npos) {
437 sp.path = remaining.substr (0, colon);
438 session_dirs.push_back (sp);
440 /* add sounds to file search path */
443 if (fspath[fspath.length()-1] != '/') {
446 fspath += sound_dir_name;
449 /* add tape dir to file search path */
452 if (fspath[fspath.length()-1] != '/') {
455 fspath += tape_dir_name;
458 remaining = remaining.substr (colon+1);
461 if (remaining.length()) {
468 if (fspath[fspath.length()-1] != '/') {
471 fspath += sound_dir_name;
475 if (fspath[fspath.length()-1] != '/') {
478 fspath += tape_dir_name;
480 session_dirs.push_back (sp);
483 /* set the AudioFileSource search path */
485 AudioFileSource::set_search_path (fspath);
487 /* reset the round-robin soundfile path thingie */
489 last_rr_session_dir = session_dirs.begin();
493 Session::create (bool& new_session, string* mix_template, jack_nframes_t initial_length)
497 if (mkdir (_path.c_str(), 0755) < 0) {
498 if (errno == EEXIST) {
501 error << string_compose(_("Session: cannot create session dir \"%1\" (%2)"), _path, strerror (errno)) << endmsg;
510 if (mkdir (dir.c_str(), 0755) < 0) {
511 if (errno != EEXIST) {
512 error << string_compose(_("Session: cannot create session peakfile dir \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
519 if (mkdir (dir.c_str(), 0755) < 0) {
520 if (errno != EEXIST) {
521 error << string_compose(_("Session: cannot create session sounds dir \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
528 if (mkdir (dir.c_str(), 0755) < 0) {
529 if (errno != EEXIST) {
530 error << string_compose(_("Session: cannot create session tape dir \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
535 dir = dead_sound_dir ();
537 if (mkdir (dir.c_str(), 0755) < 0) {
538 if (errno != EEXIST) {
539 error << string_compose(_("Session: cannot create session dead sounds dir \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
544 dir = automation_dir ();
546 if (mkdir (dir.c_str(), 0755) < 0) {
547 if (errno != EEXIST) {
548 error << string_compose(_("Session: cannot create session automation dir \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
554 /* check new_session so we don't overwrite an existing one */
558 std::string in_path = *mix_template;
560 ifstream in(in_path.c_str());
563 string out_path = _path;
565 out_path += _statefile_suffix;
567 ofstream out(out_path.c_str());
572 // okay, session is set up. Treat like normal saved
573 // session from now on.
579 error << string_compose (_("Could not open %1 for writing mix template"), out_path)
585 error << string_compose (_("Could not open mix template %1 for reading"), in_path)
592 warning << _("Session already exists. Not overwriting") << endmsg;
599 /* set initial start + end point */
601 start_location->set_end (0);
602 _locations.add (start_location);
604 end_location->set_end (initial_length);
605 _locations.add (end_location);
607 _state_of_the_state = Clean;
609 if (save_state (_current_snapshot_name)) {
610 save_history (_current_snapshot_name);
619 Session::load_diskstreams (const XMLNode& node)
622 XMLNodeConstIterator citer;
624 clist = node.children();
626 for (citer = clist.begin(); citer != clist.end(); ++citer) {
628 AudioDiskstream* dstream;
631 dstream = new AudioDiskstream (*this, **citer);
632 /* added automatically by AudioDiskstreamCreated handler */
635 catch (failed_constructor& err) {
636 error << _("Session: could not load diskstream via XML state") << endmsg;
645 Session::remove_pending_capture_state ()
650 xml_path += _current_snapshot_name;
651 xml_path += _pending_suffix;
653 unlink (xml_path.c_str());
657 Session::save_state (string snapshot_name, bool pending)
663 if (_state_of_the_state & CannotSave) {
667 tree.set_root (&get_state());
669 if (snapshot_name.empty()) {
670 snapshot_name = _current_snapshot_name;
676 xml_path += snapshot_name;
677 xml_path += _statefile_suffix;
681 // Make backup of state file
683 if ((access (xml_path.c_str(), F_OK) == 0) &&
684 (rename(xml_path.c_str(), bak_path.c_str()))) {
685 error << _("could not backup old state file, current state not saved.") << endmsg;
692 xml_path += snapshot_name;
693 xml_path += _pending_suffix;
697 if (!tree.write (xml_path)) {
698 error << string_compose (_("state could not be saved to %1"), xml_path) << endmsg;
700 /* don't leave a corrupt file lying around if it is
704 if (unlink (xml_path.c_str())) {
705 error << string_compose (_("could not remove corrupt state file %1"), xml_path) << endmsg;
708 if (rename (bak_path.c_str(), xml_path.c_str())) {
709 error << string_compose (_("could not restore state file from backup %1"), bak_path) << endmsg;
719 bool was_dirty = dirty();
721 _state_of_the_state = StateOfTheState (_state_of_the_state & ~Dirty);
724 DirtyChanged (); /* EMIT SIGNAL */
727 StateSaved (snapshot_name); /* EMIT SIGNAL */
734 Session::restore_state (string snapshot_name)
736 if (load_state (snapshot_name) == 0) {
737 set_state (*state_tree->root());
744 Session::load_state (string snapshot_name)
753 state_was_pending = false;
755 /* check for leftover pending state from a crashed capture attempt */
758 xmlpath += snapshot_name;
759 xmlpath += _pending_suffix;
761 if (!access (xmlpath.c_str(), F_OK)) {
763 /* there is pending state from a crashed capture attempt */
765 if (AskAboutPendingState()) {
766 state_was_pending = true;
770 if (!state_was_pending) {
773 xmlpath += snapshot_name;
774 xmlpath += _statefile_suffix;
777 if (access (xmlpath.c_str(), F_OK)) {
778 error << string_compose(_("%1: session state information file \"%2\" doesn't exist!"), _name, xmlpath) << endmsg;
782 state_tree = new XMLTree;
786 if (state_tree->read (xmlpath)) {
789 error << string_compose(_("Could not understand ardour file %1"), xmlpath) << endmsg;
798 Session::load_options (const XMLNode& node)
802 bool have_fade_msecs = false;
803 bool have_fade_steepness = false;
804 float fade_msecs = 0;
805 float fade_steepness = 0;
806 SlaveSource slave_src = None;
808 LocaleGuard lg (X_("POSIX"));
810 if ((child = find_named_node (node, "input-auto-connect")) != 0) {
811 if ((prop = child->property ("val")) != 0) {
812 sscanf (prop->value().c_str(), "%x", &x);
813 input_auto_connect = AutoConnectOption (x);
817 if ((child = find_named_node (node, "output-auto-connect")) != 0) {
818 if ((prop = child->property ("val")) != 0) {
819 sscanf (prop->value().c_str(), "%x", &x);
820 output_auto_connect = AutoConnectOption (x);
824 if ((child = find_named_node (node, "slave")) != 0) {
825 if ((prop = child->property ("type")) != 0) {
826 if (prop->value() == "none") {
828 } else if (prop->value() == "mtc") {
830 } else if (prop->value() == "jack") {
833 set_slave_source (slave_src, 0);
837 /* we cannot set edit mode if we are loading a session,
838 because it might destroy the playlist's positioning
841 if ((child = find_named_node (node, "edit-mode")) != 0) {
842 if ((prop = child->property ("val")) != 0) {
843 if (prop->value() == "slide") {
844 pending_edit_mode = Slide;
845 } else if (prop->value() == "splice") {
846 pending_edit_mode = Splice;
851 if ((child = find_named_node (node, "send-midi-timecode")) != 0) {
852 if ((prop = child->property ("val")) != 0) {
853 bool x = (prop->value() == "yes");
854 send_mtc = !x; /* force change in value */
858 if ((child = find_named_node (node, "send-midi-machine-control")) != 0) {
859 if ((prop = child->property ("val")) != 0) {
860 bool x = (prop->value() == "yes");
861 send_mmc = !x; /* force change in value */
862 set_send_mmc (prop->value() == "yes");
865 if ((child = find_named_node (node, "max-level")) != 0) {
866 if ((prop = child->property ("val")) != 0) {
867 max_level = atoi (prop->value().c_str());
870 if ((child = find_named_node (node, "min-level")) != 0) {
871 if ((prop = child->property ("val")) != 0) {
872 min_level = atoi (prop->value().c_str());
875 if ((child = find_named_node (node, "meter-hold")) != 0) {
876 if ((prop = child->property ("val")) != 0) {
877 _meter_hold = atof (prop->value().c_str());
880 if ((child = find_named_node (node, "meter-falloff")) != 0) {
881 if ((prop = child->property ("val")) != 0) {
882 _meter_falloff = atof (prop->value().c_str());
885 if ((child = find_named_node (node, "long-over-length")) != 0) {
886 if ((prop = child->property ("val")) != 0) {
887 over_length_long = atoi (prop->value().c_str());
890 if ((child = find_named_node (node, "short-over-length")) != 0) {
891 if ((prop = child->property ("val")) != 0) {
892 over_length_short = atoi (prop->value().c_str());
895 if ((child = find_named_node (node, "shuttle-speed-factor")) != 0) {
896 if ((prop = child->property ("val")) != 0) {
897 shuttle_speed_factor = atof (prop->value().c_str());
900 if ((child = find_named_node (node, "shuttle-speed-threshold")) != 0) {
901 if ((prop = child->property ("val")) != 0) {
902 shuttle_speed_threshold = atof (prop->value().c_str());
905 if ((child = find_named_node (node, "rf-speed")) != 0) {
906 if ((prop = child->property ("val")) != 0) {
907 rf_speed = atof (prop->value().c_str());
910 if ((child = find_named_node (node, "smpte-frames-per-second")) != 0) {
911 if ((prop = child->property ("val")) != 0) {
912 set_smpte_type( atof (prop->value().c_str()), smpte_drop_frames );
915 if ((child = find_named_node (node, "smpte-drop-frames")) != 0) {
916 if ((prop = child->property ("val")) != 0) {
917 set_smpte_type( smpte_frames_per_second, (prop->value() == "yes") );
920 if ((child = find_named_node (node, "smpte-offset")) != 0) {
921 if ((prop = child->property ("val")) != 0) {
922 set_smpte_offset( atoi (prop->value().c_str()) );
925 if ((child = find_named_node (node, "smpte-offset-negative")) != 0) {
926 if ((prop = child->property ("val")) != 0) {
927 set_smpte_offset_negative( (prop->value() == "yes") );
930 if ((child = find_named_node (node, "click-sound")) != 0) {
931 if ((prop = child->property ("val")) != 0) {
932 click_sound = prop->value();
935 if ((child = find_named_node (node, "click-emphasis-sound")) != 0) {
936 if ((prop = child->property ("val")) != 0) {
937 click_emphasis_sound = prop->value();
941 if ((child = find_named_node (node, "solo-model")) != 0) {
942 if ((prop = child->property ("val")) != 0) {
943 if (prop->value() == "SoloBus")
944 _solo_model = SoloBus;
946 _solo_model = InverseMute;
950 /* BOOLEAN OPTIONS */
952 if ((child = find_named_node (node, "auto-play")) != 0) {
953 if ((prop = child->property ("val")) != 0) {
954 set_auto_play (prop->value() == "yes");
957 if ((child = find_named_node (node, "auto-input")) != 0) {
958 if ((prop = child->property ("val")) != 0) {
959 set_auto_input (prop->value() == "yes");
962 if ((child = find_named_node (node, "seamless-loop")) != 0) {
963 if ((prop = child->property ("val")) != 0) {
964 set_seamless_loop (prop->value() == "yes");
967 if ((child = find_named_node (node, "punch-in")) != 0) {
968 if ((prop = child->property ("val")) != 0) {
969 set_punch_in (prop->value() == "yes");
972 if ((child = find_named_node (node, "punch-out")) != 0) {
973 if ((prop = child->property ("val")) != 0) {
974 set_punch_out (prop->value() == "yes");
977 if ((child = find_named_node (node, "auto-return")) != 0) {
978 if ((prop = child->property ("val")) != 0) {
979 set_auto_return (prop->value() == "yes");
982 if ((child = find_named_node (node, "send-mtc")) != 0) {
983 if ((prop = child->property ("val")) != 0) {
984 set_send_mtc (prop->value() == "yes");
987 if ((child = find_named_node (node, "mmc-control")) != 0) {
988 if ((prop = child->property ("val")) != 0) {
989 set_mmc_control (prop->value() == "yes");
992 if ((child = find_named_node (node, "midi-control")) != 0) {
993 if ((prop = child->property ("val")) != 0) {
994 set_midi_control (prop->value() == "yes");
997 if ((child = find_named_node (node, "midi-feedback")) != 0) {
998 if ((prop = child->property ("val")) != 0) {
999 set_midi_feedback (prop->value() == "yes");
1002 // Legacy support for <recording-plugins>
1003 if ((child = find_named_node (node, "recording-plugins")) != 0) {
1004 if ((prop = child->property ("val")) != 0) {
1005 set_do_not_record_plugins (prop->value() == "no");
1008 if ((child = find_named_node (node, "do-not-record-plugins")) != 0) {
1009 if ((prop = child->property ("val")) != 0) {
1010 set_do_not_record_plugins (prop->value() == "yes");
1013 if ((child = find_named_node (node, "crossfades-active")) != 0) {
1014 if ((prop = child->property ("val")) != 0) {
1015 set_crossfades_active (prop->value() == "yes");
1018 if ((child = find_named_node (node, "audible-click")) != 0) {
1019 if ((prop = child->property ("val")) != 0) {
1020 set_clicking (prop->value() == "yes");
1024 if ((child = find_named_node (node, "end-marker-is-free")) != 0) {
1025 if ((prop = child->property ("val")) != 0) {
1026 _end_location_is_free = (prop->value() == "yes");
1030 if ((child = find_named_node (node, "layer-model")) != 0) {
1031 if ((prop = child->property ("val")) != 0) {
1032 if (prop->value() == X_("LaterHigher")) {
1033 set_layer_model (LaterHigher);
1034 } else if (prop->value() == X_("AddHigher")) {
1035 set_layer_model (AddHigher);
1037 set_layer_model (MoveAddHigher);
1042 if ((child = find_named_node (node, "xfade-model")) != 0) {
1043 if ((prop = child->property ("val")) != 0) {
1044 if (prop->value() == X_("Short")) {
1045 set_xfade_model (ShortCrossfade);
1047 set_xfade_model (FullCrossfade);
1052 if ((child = find_named_node (node, "short-xfade-length")) != 0) {
1053 if ((prop = child->property ("val")) != 0) {
1054 /* value is stored as a fractional seconds */
1055 float secs = atof (prop->value().c_str());
1056 Crossfade::set_short_xfade_length ((jack_nframes_t) floor (secs * frame_rate()));
1060 if ((child = find_named_node (node, "full-xfades-unmuted")) != 0) {
1061 if ((prop = child->property ("val")) != 0) {
1062 crossfades_active = (prop->value() == "yes");
1068 if ((child = find_named_node (node, "default-fade-steepness")) != 0) {
1069 if ((prop = child->property ("val")) != 0) {
1070 fade_steepness = atof (prop->value().c_str());
1071 have_fade_steepness = true;
1074 if ((child = find_named_node (node, "default-fade-msec")) != 0) {
1075 if ((prop = child->property ("val")) != 0) {
1076 fade_msecs = atof (prop->value().c_str());
1077 have_fade_msecs = true;
1081 if (have_fade_steepness || have_fade_msecs) {
1082 // set_default_fade (fade_steepness, fade_msecs);
1089 Session::get_options () const
1094 LocaleGuard lg (X_("POSIX"));
1096 opthead = new XMLNode ("Options");
1098 SlaveSource src = slave_source ();
1102 src_string = "none";
1108 src_string = "jack";
1111 child = opthead->add_child ("slave");
1112 child->add_property ("type", src_string);
1114 child = opthead->add_child ("send-midi-timecode");
1115 child->add_property ("val", send_midi_timecode?"yes":"no");
1117 child = opthead->add_child ("send-midi-machine-control");
1118 child->add_property ("val", send_midi_machine_control?"yes":"no");
1120 snprintf (buf, sizeof(buf)-1, "%x", (int) input_auto_connect);
1121 child = opthead->add_child ("input-auto-connect");
1122 child->add_property ("val", buf);
1124 snprintf (buf, sizeof(buf)-1, "%x", (int) output_auto_connect);
1125 child = opthead->add_child ("output-auto-connect");
1126 child->add_property ("val", buf);
1128 snprintf (buf, sizeof(buf)-1, "%d", max_level);
1129 child = opthead->add_child ("max-level");
1130 child->add_property ("val", buf);
1132 snprintf (buf, sizeof(buf)-1, "%d", min_level);
1133 child = opthead->add_child ("min-level");
1134 child->add_property ("val", buf);
1136 snprintf (buf, sizeof(buf)-1, "%f", _meter_hold);
1137 child = opthead->add_child ("meter-hold");
1138 child->add_property ("val", buf);
1140 snprintf (buf, sizeof(buf)-1, "%f", _meter_falloff);
1141 child = opthead->add_child ("meter-falloff");
1142 child->add_property ("val", buf);
1144 snprintf (buf, sizeof(buf)-1, "%u", over_length_long);
1145 child = opthead->add_child ("long-over-length");
1146 child->add_property ("val", buf);
1148 snprintf (buf, sizeof(buf)-1, "%u", over_length_short);
1149 child = opthead->add_child ("short-over-length");
1150 child->add_property ("val", buf);
1152 snprintf (buf, sizeof(buf)-1, "%f", shuttle_speed_factor);
1153 child = opthead->add_child ("shuttle-speed-factor");
1154 child->add_property ("val", buf);
1156 snprintf (buf, sizeof(buf)-1, "%f", shuttle_speed_threshold);
1157 child = opthead->add_child ("shuttle-speed-threshold");
1158 child->add_property ("val", buf);
1160 snprintf (buf, sizeof(buf)-1, "%f", rf_speed);
1161 child = opthead->add_child ("rf-speed");
1162 child->add_property ("val", buf);
1164 snprintf (buf, sizeof(buf)-1, "%.2f", smpte_frames_per_second);
1165 child = opthead->add_child ("smpte-frames-per-second");
1166 child->add_property ("val", buf);
1168 child = opthead->add_child ("smpte-drop-frames");
1169 child->add_property ("val", smpte_drop_frames ? "yes" : "no");
1171 snprintf (buf, sizeof(buf)-1, "%u", smpte_offset ());
1172 child = opthead->add_child ("smpte-offset");
1173 child->add_property ("val", buf);
1175 child = opthead->add_child ("smpte-offset-negative");
1176 child->add_property ("val", smpte_offset_negative () ? "yes" : "no");
1178 child = opthead->add_child ("edit-mode");
1179 switch (_edit_mode) {
1181 child->add_property ("val", "splice");
1185 child->add_property ("val", "slide");
1189 child = opthead->add_child ("auto-play");
1190 child->add_property ("val", get_auto_play () ? "yes" : "no");
1191 child = opthead->add_child ("auto-input");
1192 child->add_property ("val", get_auto_input () ? "yes" : "no");
1193 child = opthead->add_child ("seamless-loop");
1194 child->add_property ("val", get_seamless_loop () ? "yes" : "no");
1195 child = opthead->add_child ("punch-in");
1196 child->add_property ("val", get_punch_in () ? "yes" : "no");
1197 child = opthead->add_child ("punch-out");
1198 child->add_property ("val", get_punch_out () ? "yes" : "no");
1199 child = opthead->add_child ("all-safe");
1200 child->add_property ("val", get_all_safe () ? "yes" : "no");
1201 child = opthead->add_child ("auto-return");
1202 child->add_property ("val", get_auto_return () ? "yes" : "no");
1203 child = opthead->add_child ("mmc-control");
1204 child->add_property ("val", get_mmc_control () ? "yes" : "no");
1205 child = opthead->add_child ("midi-control");
1206 child->add_property ("val", get_midi_control () ? "yes" : "no");
1207 child = opthead->add_child ("midi-feedback");
1208 child->add_property ("val", get_midi_feedback () ? "yes" : "no");
1209 child = opthead->add_child ("do-not-record-plugins");
1210 child->add_property ("val", get_do_not_record_plugins () ? "yes" : "no");
1211 child = opthead->add_child ("auto-crossfade");
1212 child->add_property ("val", get_crossfades_active () ? "yes" : "no");
1213 child = opthead->add_child ("audible-click");
1214 child->add_property ("val", get_clicking () ? "yes" : "no");
1215 child = opthead->add_child ("end-marker-is-free");
1216 child->add_property ("val", _end_location_is_free ? "yes" : "no");
1218 if (click_sound.length()) {
1219 child = opthead->add_child ("click-sound");
1220 child->add_property ("val", click_sound);
1223 if (click_emphasis_sound.length()) {
1224 child = opthead->add_child ("click-emphasis-sound");
1225 child->add_property ("val", click_emphasis_sound);
1228 child = opthead->add_child ("solo-model");
1229 child->add_property ("val", _solo_model == SoloBus ? "SoloBus" : "InverseMute");
1231 child = opthead->add_child ("layer-model");
1232 switch (layer_model) {
1234 child->add_property ("val", X_("LaterHigher"));
1237 child->add_property ("val", X_("MoveAddHigher"));
1240 child->add_property ("val", X_("AddHigher"));
1244 child = opthead->add_child ("xfade-model");
1245 switch (xfade_model) {
1247 child->add_property ("val", X_("Full"));
1249 case ShortCrossfade:
1250 child->add_property ("val", X_("Short"));
1253 child = opthead->add_child ("short-xfade-length");
1254 /* store as fractions of a second */
1255 snprintf (buf, sizeof(buf)-1, "%f",
1256 (float) Crossfade::short_xfade_length() / frame_rate());
1257 child->add_property ("val", buf);
1259 child = opthead->add_child ("full-xfades-unmuted");
1260 child->add_property ("val", crossfades_active ? "yes" : "no");
1266 Session::get_state()
1272 Session::get_template()
1274 /* if we don't disable rec-enable, diskstreams
1275 will believe they need to store their capture
1276 sources in their state node.
1279 disable_record (false);
1281 return state(false);
1285 Session::state(bool full_state)
1287 XMLNode* node = new XMLNode("Session");
1290 // store libardour version, just in case
1292 snprintf(buf, sizeof(buf)-1, "%d.%d.%d",
1293 libardour_major_version, libardour_minor_version, libardour_micro_version);
1294 node->add_property("version", string(buf));
1296 /* store configuration settings */
1300 /* store the name */
1301 node->add_property ("name", _name);
1303 if (session_dirs.size() > 1) {
1307 vector<space_and_path>::iterator i = session_dirs.begin();
1308 vector<space_and_path>::iterator next;
1310 ++i; /* skip the first one */
1314 while (i != session_dirs.end()) {
1318 if (next != session_dirs.end()) {
1328 child = node->add_child ("Path");
1329 child->add_content (p);
1333 /* save the ID counter */
1335 snprintf (buf, sizeof (buf), "%" PRIu64, ID::counter());
1336 node->add_property ("id-counter", buf);
1338 /* various options */
1340 node->add_child_nocopy (get_options());
1342 child = node->add_child ("Sources");
1345 Glib::Mutex::Lock sl (audio_source_lock);
1347 for (AudioSourceList::iterator siter = audio_sources.begin(); siter != audio_sources.end(); ++siter) {
1349 /* Don't save information about AudioFileSources that are empty */
1351 AudioFileSource* fs;
1353 if ((fs = dynamic_cast<AudioFileSource*> (siter->second)) != 0) {
1354 DestructiveFileSource* dfs = dynamic_cast<DestructiveFileSource*> (fs);
1356 /* destructive file sources are OK if they are empty, because
1357 we will re-use them every time.
1361 if (fs->length() == 0) {
1367 child->add_child_nocopy (siter->second->get_state());
1371 child = node->add_child ("Regions");
1374 Glib::Mutex::Lock rl (region_lock);
1376 for (AudioRegionList::const_iterator i = audio_regions.begin(); i != audio_regions.end(); ++i) {
1378 /* only store regions not attached to playlists */
1380 if (i->second->playlist() == 0) {
1381 child->add_child_nocopy (i->second->state (true));
1386 child = node->add_child ("DiskStreams");
1389 Glib::RWLock::ReaderLock dl (diskstream_lock);
1390 for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
1391 if (!(*i)->hidden()) {
1392 child->add_child_nocopy ((*i)->get_state());
1397 node->add_child_nocopy (_locations.get_state());
1399 child = node->add_child ("Connections");
1401 Glib::Mutex::Lock lm (connection_lock);
1402 for (ConnectionList::iterator i = _connections.begin(); i != _connections.end(); ++i) {
1403 if (!(*i)->system_dependent()) {
1404 child->add_child_nocopy ((*i)->get_state());
1409 child = node->add_child ("Routes");
1411 boost::shared_ptr<RouteList> r = routes.reader ();
1413 RoutePublicOrderSorter cmp;
1414 RouteList public_order (*r);
1415 public_order.sort (cmp);
1417 for (RouteList::iterator i = public_order.begin(); i != public_order.end(); ++i) {
1418 if (!(*i)->hidden()) {
1420 child->add_child_nocopy ((*i)->get_state());
1422 child->add_child_nocopy ((*i)->get_template());
1429 child = node->add_child ("EditGroups");
1430 for (list<RouteGroup *>::iterator i = edit_groups.begin(); i != edit_groups.end(); ++i) {
1431 child->add_child_nocopy ((*i)->get_state());
1434 child = node->add_child ("MixGroups");
1435 for (list<RouteGroup *>::iterator i = mix_groups.begin(); i != mix_groups.end(); ++i) {
1436 child->add_child_nocopy ((*i)->get_state());
1439 child = node->add_child ("Playlists");
1440 for (PlaylistList::iterator i = playlists.begin(); i != playlists.end(); ++i) {
1441 if (!(*i)->hidden()) {
1442 if (!(*i)->empty()) {
1444 child->add_child_nocopy ((*i)->get_state());
1446 child->add_child_nocopy ((*i)->get_template());
1452 child = node->add_child ("UnusedPlaylists");
1453 for (PlaylistList::iterator i = unused_playlists.begin(); i != unused_playlists.end(); ++i) {
1454 if (!(*i)->hidden()) {
1455 if (!(*i)->empty()) {
1457 child->add_child_nocopy ((*i)->get_state());
1459 child->add_child_nocopy ((*i)->get_template());
1467 child = node->add_child ("Click");
1468 child->add_child_nocopy (_click_io->state (full_state));
1472 child = node->add_child ("NamedSelections");
1473 for (NamedSelectionList::iterator i = named_selections.begin(); i != named_selections.end(); ++i) {
1475 child->add_child_nocopy ((*i)->get_state());
1480 node->add_child_nocopy (_tempo_map->get_state());
1483 node->add_child_copy (*_extra_xml);
1490 Session::set_state (const XMLNode& node)
1494 const XMLProperty* prop;
1497 _state_of_the_state = StateOfTheState (_state_of_the_state|CannotSave);
1499 if (node.name() != X_("Session")){
1500 fatal << _("programming error: Session: incorrect XML node sent to set_state()") << endmsg;
1504 StateManager::prohibit_save ();
1506 if ((prop = node.property ("name")) != 0) {
1507 _name = prop->value ();
1510 if ((prop = node.property (X_("id-counter"))) != 0) {
1512 sscanf (prop->value().c_str(), "%" PRIu64, &x);
1513 ID::init_counter (x);
1515 /* old sessions used a timebased counter, so fake
1516 the startup ID counter based on a standard
1521 ID::init_counter (now);
1525 IO::disable_ports ();
1526 IO::disable_connecting ();
1528 /* Object loading order:
1545 if (use_config_midi_ports ()) {
1548 if ((child = find_named_node (node, "Path")) != 0) {
1549 /* XXX this XML content stuff horrible API design */
1550 string raid_path = _path + ':' + child->children().front()->content();
1551 setup_raid_path (raid_path);
1553 /* the path is already set */
1556 if ((child = find_named_node (node, "extra")) != 0) {
1557 _extra_xml = new XMLNode (*child);
1560 if ((child = find_named_node (node, "Options")) == 0) {
1561 error << _("Session: XML state has no options section") << endmsg;
1562 } else if (load_options (*child)) {
1565 if ((child = find_named_node (node, "Sources")) == 0) {
1566 error << _("Session: XML state has no sources section") << endmsg;
1568 } else if (load_sources (*child)) {
1572 if ((child = find_named_node (node, "Regions")) == 0) {
1573 error << _("Session: XML state has no Regions section") << endmsg;
1575 } else if (load_regions (*child)) {
1579 if ((child = find_named_node (node, "Playlists")) == 0) {
1580 error << _("Session: XML state has no playlists section") << endmsg;
1582 } else if (load_playlists (*child)) {
1586 if ((child = find_named_node (node, "UnusedPlaylists")) == 0) {
1588 } else if (load_unused_playlists (*child)) {
1592 if ((child = find_named_node (node, "NamedSelections")) != 0) {
1593 if (load_named_selections (*child)) {
1598 if ((child = find_named_node (node, "DiskStreams")) == 0) {
1599 error << _("Session: XML state has no diskstreams section") << endmsg;
1601 } else if (load_diskstreams (*child)) {
1605 if ((child = find_named_node (node, "Connections")) == 0) {
1606 error << _("Session: XML state has no connections section") << endmsg;
1608 } else if (load_connections (*child)) {
1612 if ((child = find_named_node (node, "Locations")) == 0) {
1613 error << _("Session: XML state has no locations section") << endmsg;
1615 } else if (_locations.set_state (*child)) {
1621 if ((location = _locations.auto_loop_location()) != 0) {
1622 set_auto_loop_location (location);
1625 if ((location = _locations.auto_punch_location()) != 0) {
1626 set_auto_punch_location (location);
1629 if ((location = _locations.end_location()) == 0) {
1630 _locations.add (end_location);
1632 delete end_location;
1633 end_location = location;
1636 if ((location = _locations.start_location()) == 0) {
1637 _locations.add (start_location);
1639 delete start_location;
1640 start_location = location;
1643 _locations.save_state (_("initial state"));
1645 if ((child = find_named_node (node, "EditGroups")) == 0) {
1646 error << _("Session: XML state has no edit groups section") << endmsg;
1648 } else if (load_edit_groups (*child)) {
1652 if ((child = find_named_node (node, "MixGroups")) == 0) {
1653 error << _("Session: XML state has no mix groups section") << endmsg;
1655 } else if (load_mix_groups (*child)) {
1659 if ((child = find_named_node (node, "TempoMap")) == 0) {
1660 error << _("Session: XML state has no Tempo Map section") << endmsg;
1662 } else if (_tempo_map->set_state (*child)) {
1666 if ((child = find_named_node (node, "Routes")) == 0) {
1667 error << _("Session: XML state has no routes section") << endmsg;
1669 } else if (load_routes (*child)) {
1673 if ((child = find_named_node (node, "Click")) == 0) {
1674 warning << _("Session: XML state has no click section") << endmsg;
1675 } else if (_click_io) {
1676 _click_io->set_state (*child);
1679 /* OK, now we can set edit mode */
1681 set_edit_mode (pending_edit_mode);
1683 /* here beginneth the second phase ... */
1685 StateReady (); /* EMIT SIGNAL */
1687 _state_of_the_state = Clean;
1689 StateManager::allow_save (_("initial state"), true);
1691 if (state_was_pending) {
1692 save_state (_current_snapshot_name);
1693 save_history (_current_snapshot_name);
1694 remove_pending_capture_state ();
1695 state_was_pending = false;
1701 /* we failed, re-enable state saving but don't actually save internal state */
1702 StateManager::allow_save (X_("ignored"), false);
1707 Session::load_routes (const XMLNode& node)
1710 XMLNodeConstIterator niter;
1712 nlist = node.children();
1716 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1718 boost::shared_ptr<Route> route (XMLRouteFactory (**niter));
1721 error << _("Session: cannot create Route from XML description.") << endmsg;
1731 boost::shared_ptr<Route>
1732 Session::XMLRouteFactory (const XMLNode& node)
1734 if (node.name() != "Route") {
1735 return boost::shared_ptr<Route> ((Route*) 0);
1738 if (node.property ("diskstream") != 0 || node.property ("diskstream-id") != 0) {
1739 boost::shared_ptr<Route> x (new AudioTrack (*this, node));
1742 boost::shared_ptr<Route> x (new Route (*this, node));
1748 Session::load_regions (const XMLNode& node)
1751 XMLNodeConstIterator niter;
1752 AudioRegion* region;
1754 nlist = node.children();
1758 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1759 if ((region = XMLRegionFactory (**niter, false)) == 0) {
1760 error << _("Session: cannot create Region from XML description.") << endmsg;
1767 Session::XMLRegionFactory (const XMLNode& node, bool full)
1769 const XMLProperty* prop;
1772 AudioRegion::SourceList sources;
1773 uint32_t nchans = 1;
1776 if (node.name() != X_("Region")) {
1780 if ((prop = node.property (X_("channels"))) != 0) {
1781 nchans = atoi (prop->value().c_str());
1785 if ((prop = node.property (X_("source-0"))) == 0) {
1786 if ((prop = node.property ("source")) == 0) {
1787 error << _("Session: XMLNode describing a AudioRegion is incomplete (no source)") << endmsg;
1792 PBD::ID s_id (prop->value());
1794 if ((source = source_by_id (s_id)) == 0) {
1795 error << string_compose(_("Session: XMLNode describing a AudioRegion references an unknown source id =%1"), s_id) << endmsg;
1799 as = dynamic_cast<AudioSource*>(source);
1801 error << string_compose(_("Session: XMLNode describing a AudioRegion references a non-audio source id =%1"), s_id) << endmsg;
1805 sources.push_back (as);
1807 /* pickup other channels */
1809 for (uint32_t n=1; n < nchans; ++n) {
1810 snprintf (buf, sizeof(buf), X_("source-%d"), n);
1811 if ((prop = node.property (buf)) != 0) {
1813 PBD::ID id2 (prop->value());
1815 if ((source = source_by_id (id2)) == 0) {
1816 error << string_compose(_("Session: XMLNode describing a AudioRegion references an unknown source id =%1"), id2) << endmsg;
1820 as = dynamic_cast<AudioSource*>(source);
1822 error << string_compose(_("Session: XMLNode describing a AudioRegion references a non-audio source id =%1"), id2) << endmsg;
1825 sources.push_back (as);
1830 return new AudioRegion (sources, node);
1833 catch (failed_constructor& err) {
1839 Session::get_sources_as_xml ()
1842 XMLNode* node = new XMLNode (X_("Sources"));
1843 Glib::Mutex::Lock lm (audio_source_lock);
1845 for (AudioSourceList::iterator i = audio_sources.begin(); i != audio_sources.end(); ++i) {
1846 node->add_child_nocopy (i->second->get_state());
1849 /* XXX get MIDI and other sources here */
1855 Session::path_from_region_name (string name, string identifier)
1857 char buf[PATH_MAX+1];
1859 string dir = discover_best_sound_dir ();
1861 for (n = 0; n < 999999; ++n) {
1862 if (identifier.length()) {
1863 snprintf (buf, sizeof(buf), "%s/%s%s%" PRIu32 ".wav", dir.c_str(), name.c_str(),
1864 identifier.c_str(), n);
1866 snprintf (buf, sizeof(buf), "%s/%s-%" PRIu32 ".wav", dir.c_str(), name.c_str(), n);
1868 if (access (buf, F_OK) != 0) {
1878 Session::load_sources (const XMLNode& node)
1881 XMLNodeConstIterator niter;
1884 nlist = node.children();
1888 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1890 if ((source = XMLSourceFactory (**niter)) == 0) {
1891 error << _("Session: cannot create Source from XML description.") << endmsg;
1899 Session::XMLSourceFactory (const XMLNode& node)
1903 if (node.name() != "Source") {
1908 src = AudioFileSource::create (node);
1911 catch (failed_constructor& err) {
1912 error << _("Found a sound file that cannot be used by Ardour. Talk to the progammers.") << endmsg;
1920 Session::save_template (string template_name)
1923 string xml_path, bak_path, template_path;
1925 if (_state_of_the_state & CannotSave) {
1930 string dir = template_dir();
1932 if ((dp = opendir (dir.c_str()))) {
1935 if (mkdir (dir.c_str(), S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH)<0) {
1936 error << string_compose(_("Could not create mix templates directory \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
1941 tree.set_root (&get_template());
1944 xml_path += template_name;
1945 xml_path += _template_suffix;
1947 ifstream in(xml_path.c_str());
1950 warning << string_compose(_("Template \"%1\" already exists - new version not created"), template_name) << endmsg;
1956 if (!tree.write (xml_path)) {
1957 error << _("mix template not saved") << endmsg;
1965 Session::rename_template (string old_name, string new_name)
1967 string old_path = template_dir() + old_name + _template_suffix;
1968 string new_path = template_dir() + new_name + _template_suffix;
1970 return rename (old_path.c_str(), new_path.c_str());
1974 Session::delete_template (string name)
1976 string template_path = template_dir();
1977 template_path += name;
1978 template_path += _template_suffix;
1980 return remove (template_path.c_str());
1984 Session::refresh_disk_space ()
1987 struct statfs statfsbuf;
1988 vector<space_and_path>::iterator i;
1989 Glib::Mutex::Lock lm (space_lock);
1992 /* get freespace on every FS that is part of the session path */
1994 _total_free_4k_blocks = 0;
1996 for (i = session_dirs.begin(); i != session_dirs.end(); ++i) {
1997 statfs ((*i).path.c_str(), &statfsbuf);
1999 scale = statfsbuf.f_bsize/4096.0;
2001 (*i).blocks = (uint32_t) floor (statfsbuf.f_bavail * scale);
2002 _total_free_4k_blocks += (*i).blocks;
2008 Session::ensure_sound_dir (string path, string& result)
2013 /* Ensure that the parent directory exists */
2015 if (mkdir (path.c_str(), 0775)) {
2016 if (errno != EEXIST) {
2017 error << string_compose(_("cannot create session directory \"%1\"; ignored"), path) << endmsg;
2022 /* Ensure that the sounds directory exists */
2026 result += sound_dir_name;
2028 if (mkdir (result.c_str(), 0775)) {
2029 if (errno != EEXIST) {
2030 error << string_compose(_("cannot create sounds directory \"%1\"; ignored"), result) << endmsg;
2037 dead += dead_sound_dir_name;
2039 if (mkdir (dead.c_str(), 0775)) {
2040 if (errno != EEXIST) {
2041 error << string_compose(_("cannot create dead sounds directory \"%1\"; ignored"), dead) << endmsg;
2048 peak += peak_dir_name;
2050 if (mkdir (peak.c_str(), 0775)) {
2051 if (errno != EEXIST) {
2052 error << string_compose(_("cannot create peak file directory \"%1\"; ignored"), peak) << endmsg;
2057 /* callers expect this to be terminated ... */
2064 Session::discover_best_sound_dir (bool destructive)
2066 vector<space_and_path>::iterator i;
2069 /* destructive files all go into the same place */
2075 /* handle common case without system calls */
2077 if (session_dirs.size() == 1) {
2081 /* OK, here's the algorithm we're following here:
2083 We want to select which directory to use for
2084 the next file source to be created. Ideally,
2085 we'd like to use a round-robin process so as to
2086 get maximum performance benefits from splitting
2087 the files across multiple disks.
2089 However, in situations without much diskspace, an
2090 RR approach may end up filling up a filesystem
2091 with new files while others still have space.
2092 Its therefore important to pay some attention to
2093 the freespace in the filesystem holding each
2094 directory as well. However, if we did that by
2095 itself, we'd keep creating new files in the file
2096 system with the most space until it was as full
2097 as all others, thus negating any performance
2098 benefits of this RAID-1 like approach.
2100 So, we use a user-configurable space threshold. If
2101 there are at least 2 filesystems with more than this
2102 much space available, we use RR selection between them.
2103 If not, then we pick the filesystem with the most space.
2105 This gets a good balance between the two
2109 refresh_disk_space ();
2111 int free_enough = 0;
2113 for (i = session_dirs.begin(); i != session_dirs.end(); ++i) {
2114 if ((*i).blocks * 4096 >= Config->get_disk_choice_space_threshold()) {
2119 if (free_enough >= 2) {
2121 bool found_it = false;
2123 /* use RR selection process, ensuring that the one
2127 i = last_rr_session_dir;
2130 if (++i == session_dirs.end()) {
2131 i = session_dirs.begin();
2134 if ((*i).blocks * 4096 >= Config->get_disk_choice_space_threshold()) {
2135 if (ensure_sound_dir ((*i).path, result) == 0) {
2136 last_rr_session_dir = i;
2142 } while (i != last_rr_session_dir);
2145 result = sound_dir();
2150 /* pick FS with the most freespace (and that
2151 seems to actually work ...)
2154 vector<space_and_path> sorted;
2155 space_and_path_ascending_cmp cmp;
2157 sorted = session_dirs;
2158 sort (sorted.begin(), sorted.end(), cmp);
2160 for (i = sorted.begin(); i != sorted.end(); ++i) {
2161 if (ensure_sound_dir ((*i).path, result) == 0) {
2162 last_rr_session_dir = i;
2167 /* if the above fails, fall back to the most simplistic solution */
2169 if (i == sorted.end()) {
2178 Session::load_playlists (const XMLNode& node)
2181 XMLNodeConstIterator niter;
2184 nlist = node.children();
2188 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2190 if ((playlist = XMLPlaylistFactory (**niter)) == 0) {
2191 error << _("Session: cannot create Playlist from XML description.") << endmsg;
2199 Session::load_unused_playlists (const XMLNode& node)
2202 XMLNodeConstIterator niter;
2205 nlist = node.children();
2209 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2211 if ((playlist = XMLPlaylistFactory (**niter)) == 0) {
2212 error << _("Session: cannot create Playlist from XML description.") << endmsg;
2216 // now manually untrack it
2218 track_playlist (playlist, false);
2226 Session::XMLPlaylistFactory (const XMLNode& node)
2229 return new AudioPlaylist (*this, node);
2232 catch (failed_constructor& err) {
2238 Session::load_named_selections (const XMLNode& node)
2241 XMLNodeConstIterator niter;
2244 nlist = node.children();
2248 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2250 if ((ns = XMLNamedSelectionFactory (**niter)) == 0) {
2251 error << _("Session: cannot create Named Selection from XML description.") << endmsg;
2259 Session::XMLNamedSelectionFactory (const XMLNode& node)
2262 return new NamedSelection (*this, node);
2265 catch (failed_constructor& err) {
2271 Session::dead_sound_dir () const
2274 res += dead_sound_dir_name;
2280 Session::sound_dir () const
2283 res += sound_dir_name;
2289 Session::tape_dir () const
2292 res += tape_dir_name;
2298 Session::peak_dir () const
2301 res += peak_dir_name;
2307 Session::automation_dir () const
2310 res += "automation/";
2315 Session::template_dir ()
2317 string path = get_user_ardour_path();
2318 path += "templates/";
2324 Session::suffixed_search_path (string suffix, bool data)
2328 path += get_user_ardour_path();
2329 if (path[path.length()-1] != ':') {
2334 path += get_system_data_path();
2336 path += get_system_module_path();
2339 vector<string> split_path;
2341 split (path, split_path, ':');
2344 for (vector<string>::iterator i = split_path.begin(); i != split_path.end(); ++i) {
2349 if (distance (i, split_path.end()) != 1) {
2358 Session::template_path ()
2360 return suffixed_search_path (X_("templates"), true);
2364 Session::control_protocol_path ()
2366 return suffixed_search_path (X_("surfaces"), false);
2370 Session::load_connections (const XMLNode& node)
2372 XMLNodeList nlist = node.children();
2373 XMLNodeConstIterator niter;
2377 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2378 if ((*niter)->name() == "InputConnection") {
2379 add_connection (new ARDOUR::InputConnection (**niter));
2380 } else if ((*niter)->name() == "OutputConnection") {
2381 add_connection (new ARDOUR::OutputConnection (**niter));
2383 error << string_compose(_("Unknown node \"%1\" found in Connections list from state file"), (*niter)->name()) << endmsg;
2392 Session::load_edit_groups (const XMLNode& node)
2394 return load_route_groups (node, true);
2398 Session::load_mix_groups (const XMLNode& node)
2400 return load_route_groups (node, false);
2404 Session::load_route_groups (const XMLNode& node, bool edit)
2406 XMLNodeList nlist = node.children();
2407 XMLNodeConstIterator niter;
2412 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2413 if ((*niter)->name() == "RouteGroup") {
2415 rg = add_edit_group ("");
2416 rg->set_state (**niter);
2418 rg = add_mix_group ("");
2419 rg->set_state (**niter);
2428 state_file_filter (const string &str, void *arg)
2430 return (str.length() > strlen(Session::statefile_suffix()) &&
2431 str.find (Session::statefile_suffix()) == (str.length() - strlen (Session::statefile_suffix())));
2435 bool operator()(const string* a, const string* b) {
2441 remove_end(string* state)
2443 string statename(*state);
2445 string::size_type start,end;
2446 if ((start = statename.find_last_of ('/')) != string::npos) {
2447 statename = statename.substr (start+1);
2450 if ((end = statename.rfind(".ardour")) == string::npos) {
2451 end = statename.length();
2454 return new string(statename.substr (0, end));
2458 Session::possible_states (string path)
2460 PathScanner scanner;
2461 vector<string*>* states = scanner (path, state_file_filter, 0, false, false);
2463 transform(states->begin(), states->end(), states->begin(), remove_end);
2466 sort (states->begin(), states->end(), cmp);
2472 Session::possible_states () const
2474 return possible_states(_path);
2478 Session::auto_save()
2480 save_state (_current_snapshot_name);
2481 save_history (_current_snapshot_name);
2485 Session::add_edit_group (string name)
2487 RouteGroup* rg = new RouteGroup (*this, name);
2488 edit_groups.push_back (rg);
2489 edit_group_added (rg); /* EMIT SIGNAL */
2495 Session::add_mix_group (string name)
2497 RouteGroup* rg = new RouteGroup (*this, name, RouteGroup::Relative);
2498 mix_groups.push_back (rg);
2499 mix_group_added (rg); /* EMIT SIGNAL */
2505 Session::remove_edit_group (RouteGroup& rg)
2507 list<RouteGroup*>::iterator i;
2509 if ((i = find (edit_groups.begin(), edit_groups.end(), &rg)) != edit_groups.end()) {
2510 (*i)->apply (&Route::drop_edit_group, this);
2511 edit_groups.erase (i);
2512 edit_group_removed (); /* EMIT SIGNAL */
2519 Session::remove_mix_group (RouteGroup& rg)
2521 list<RouteGroup*>::iterator i;
2523 if ((i = find (mix_groups.begin(), mix_groups.end(), &rg)) != mix_groups.end()) {
2524 (*i)->apply (&Route::drop_mix_group, this);
2525 mix_groups.erase (i);
2526 mix_group_removed (); /* EMIT SIGNAL */
2533 Session::mix_group_by_name (string name)
2535 list<RouteGroup *>::iterator i;
2537 for (i = mix_groups.begin(); i != mix_groups.end(); ++i) {
2538 if ((*i)->name() == name) {
2546 Session::edit_group_by_name (string name)
2548 list<RouteGroup *>::iterator i;
2550 for (i = edit_groups.begin(); i != edit_groups.end(); ++i) {
2551 if ((*i)->name() == name) {
2559 Session::set_meter_hold (float val)
2562 MeterHoldChanged(); // emit
2566 Session::set_meter_falloff (float val)
2568 _meter_falloff = val;
2569 MeterFalloffChanged(); // emit
2574 Session::begin_reversible_command (string name)
2576 current_trans.clear ();
2577 current_trans.set_name (name);
2581 Session::commit_reversible_command (Command *cmd)
2586 current_trans.add_command (cmd);
2589 gettimeofday (&now, 0);
2590 current_trans.set_timestamp (now);
2592 history.add (current_trans);
2595 Session::GlobalRouteBooleanState
2596 Session::get_global_route_boolean (bool (Route::*method)(void) const)
2598 GlobalRouteBooleanState s;
2599 boost::shared_ptr<RouteList> r = routes.reader ();
2601 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
2602 if (!(*i)->hidden()) {
2603 RouteBooleanState v;
2606 Route* r = (*i).get();
2607 v.second = (r->*method)();
2616 Session::GlobalRouteMeterState
2617 Session::get_global_route_metering ()
2619 GlobalRouteMeterState s;
2620 boost::shared_ptr<RouteList> r = routes.reader ();
2622 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
2623 if (!(*i)->hidden()) {
2627 v.second = (*i)->meter_point();
2637 Session::set_global_route_metering (GlobalRouteMeterState s, void* arg)
2639 for (GlobalRouteMeterState::iterator i = s.begin(); i != s.end(); ++i) {
2640 i->first->set_meter_point (i->second, arg);
2645 Session::set_global_route_boolean (GlobalRouteBooleanState s, void (Route::*method)(bool, void*), void* arg)
2647 for (GlobalRouteBooleanState::iterator i = s.begin(); i != s.end(); ++i) {
2648 Route* r = i->first.get();
2649 (r->*method) (i->second, arg);
2654 Session::set_global_mute (GlobalRouteBooleanState s, void* src)
2656 set_global_route_boolean (s, &Route::set_mute, src);
2660 Session::set_global_solo (GlobalRouteBooleanState s, void* src)
2662 set_global_route_boolean (s, &Route::set_solo, src);
2666 Session::set_global_record_enable (GlobalRouteBooleanState s, void* src)
2668 set_global_route_boolean (s, &Route::set_record_enable, src);
2673 Session::global_mute_memento (void* src)
2675 return sigc::bind (mem_fun (*this, &Session::set_global_mute), get_global_route_boolean (&Route::muted), src);
2679 Session::global_metering_memento (void* src)
2681 return sigc::bind (mem_fun (*this, &Session::set_global_route_metering), get_global_route_metering (), src);
2685 Session::global_solo_memento (void* src)
2687 return sigc::bind (mem_fun (*this, &Session::set_global_solo), get_global_route_boolean (&Route::soloed), src);
2691 Session::global_record_enable_memento (void* src)
2693 return sigc::bind (mem_fun (*this, &Session::set_global_record_enable), get_global_route_boolean (&Route::record_enabled), src);
2698 template_filter (const string &str, void *arg)
2700 return (str.length() > strlen(Session::template_suffix()) &&
2701 str.find (Session::template_suffix()) == (str.length() - strlen (Session::template_suffix())));
2705 Session::get_template_list (list<string> &template_names)
2707 vector<string *> *templates;
2708 PathScanner scanner;
2711 path = template_path ();
2713 templates = scanner (path, template_filter, 0, false, true);
2715 vector<string*>::iterator i;
2716 for (i = templates->begin(); i != templates->end(); ++i) {
2717 string fullpath = *(*i);
2720 start = fullpath.find_last_of ('/') + 1;
2721 if ((end = fullpath.find_last_of ('.')) <0) {
2722 end = fullpath.length();
2725 template_names.push_back(fullpath.substr(start, (end-start)));
2730 Session::read_favorite_dirs (FavoriteDirs & favs)
2732 string path = get_user_ardour_path();
2733 path += "/favorite_dirs";
2735 ifstream fav (path.c_str());
2740 if (errno != ENOENT) {
2741 //error << string_compose (_("cannot open favorite file %1 (%2)"), path, strerror (errno)) << endmsg;
2752 getline(fav, newfav);
2758 favs.push_back (newfav);
2765 Session::write_favorite_dirs (FavoriteDirs & favs)
2767 string path = get_user_ardour_path();
2768 path += "/favorite_dirs";
2770 ofstream fav (path.c_str());
2776 for (FavoriteDirs::iterator i = favs.begin(); i != favs.end(); ++i) {
2777 fav << (*i) << endl;
2784 accept_all_non_peak_files (const string& path, void *arg)
2786 return (path.length() > 5 && path.find (".peak") != (path.length() - 5));
2790 accept_all_state_files (const string& path, void *arg)
2792 return (path.length() > 7 && path.find (".ardour") == (path.length() - 7));
2796 Session::find_all_sources (string path, set<string>& result)
2801 if (!tree.read (path)) {
2805 if ((node = find_named_node (*tree.root(), "Sources")) == 0) {
2810 XMLNodeConstIterator niter;
2812 nlist = node->children();
2816 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2820 if ((prop = (*niter)->property (X_("name"))) == 0) {
2824 if (prop->value()[0] == '/') {
2825 /* external file, ignore */
2829 string path = _path; /* /-terminated */
2830 path += sound_dir_name;
2832 path += prop->value();
2834 result.insert (path);
2841 Session::find_all_sources_across_snapshots (set<string>& result, bool exclude_this_snapshot)
2843 PathScanner scanner;
2844 vector<string*>* state_files;
2846 string this_snapshot_path;
2852 if (ripped[ripped.length()-1] == '/') {
2853 ripped = ripped.substr (0, ripped.length() - 1);
2856 state_files = scanner (ripped, accept_all_state_files, (void *) 0, false, true);
2858 if (state_files == 0) {
2863 this_snapshot_path = _path;
2864 this_snapshot_path += _current_snapshot_name;
2865 this_snapshot_path += _statefile_suffix;
2867 for (vector<string*>::iterator i = state_files->begin(); i != state_files->end(); ++i) {
2869 if (exclude_this_snapshot && **i == this_snapshot_path) {
2873 if (find_all_sources (**i, result) < 0) {
2882 Session::cleanup_sources (Session::cleanup_report& rep)
2884 vector<Source*> dead_sources;
2885 vector<Playlist*> playlists_tbd;
2886 PathScanner scanner;
2888 vector<space_and_path>::iterator i;
2889 vector<space_and_path>::iterator nexti;
2890 vector<string*>* soundfiles;
2891 vector<string> unused;
2892 set<string> all_sources;
2897 _state_of_the_state = (StateOfTheState) (_state_of_the_state | InCleanup);
2899 /* step 1: consider deleting all unused playlists */
2901 for (PlaylistList::iterator x = unused_playlists.begin(); x != unused_playlists.end(); ++x) {
2904 status = AskAboutPlaylistDeletion (*x);
2913 playlists_tbd.push_back (*x);
2917 /* leave it alone */
2922 /* now delete any that were marked for deletion */
2924 for (vector<Playlist*>::iterator x = playlists_tbd.begin(); x != playlists_tbd.end(); ++x) {
2925 PlaylistList::iterator foo;
2927 if ((foo = unused_playlists.find (*x)) != unused_playlists.end()) {
2928 unused_playlists.erase (foo);
2933 /* step 2: clear the undo/redo history for all playlists */
2935 for (PlaylistList::iterator x = playlists.begin(); x != playlists.end(); ++x) {
2936 (*x)->drop_all_states ();
2939 /* step 3: find all un-referenced sources */
2944 for (AudioSourceList::iterator i = audio_sources.begin(); i != audio_sources.end(); ) {
2946 AudioSourceList::iterator tmp;
2951 /* only remove files that are not in use and have some size
2952 to them. otherwise we remove the current "nascent"
2956 if (i->second->use_cnt() == 0 && i->second->length() > 0) {
2957 dead_sources.push_back (i->second);
2959 /* remove this source from our own list to avoid us
2960 adding it to the list of all sources below
2963 audio_sources.erase (i);
2969 /* Step 4: get rid of all regions in the region list that use any dead sources
2970 in case the sources themselves don't go away (they might be referenced in
2974 for (vector<Source*>::iterator i = dead_sources.begin(); i != dead_sources.end();++i) {
2976 for (AudioRegionList::iterator r = audio_regions.begin(); r != audio_regions.end(); ) {
2977 AudioRegionList::iterator tmp;
2985 for (uint32_t n = 0; n < ar->n_channels(); ++n) {
2986 if (&ar->source (n) == (*i)) {
2987 /* this region is dead */
2996 /* build a list of all the possible sound directories for the session */
2998 for (i = session_dirs.begin(); i != session_dirs.end(); ) {
3003 sound_path += (*i).path;
3004 sound_path += sound_dir_name;
3006 if (nexti != session_dirs.end()) {
3013 /* now do the same thing for the files that ended up in the sounds dir(s)
3014 but are not referenced as sources in any snapshot.
3017 soundfiles = scanner (sound_path, accept_all_non_peak_files, (void *) 0, false, true);
3019 if (soundfiles == 0) {
3023 /* find all sources, but don't use this snapshot because the
3024 state file on disk still references sources we may have already
3028 find_all_sources_across_snapshots (all_sources, true);
3030 /* add our current source list
3033 for (AudioSourceList::iterator i = audio_sources.begin(); i != audio_sources.end(); ++i) {
3034 AudioFileSource* fs;
3036 if ((fs = dynamic_cast<AudioFileSource*> (i->second)) != 0) {
3037 all_sources.insert (fs->path());
3041 for (vector<string*>::iterator x = soundfiles->begin(); x != soundfiles->end(); ++x) {
3046 for (set<string>::iterator i = all_sources.begin(); i != all_sources.end(); ++i) {
3056 unused.push_back (spath);
3060 /* now try to move all unused files into the "dead_sounds" directory(ies) */
3062 for (vector<string>::iterator x = unused.begin(); x != unused.end(); ++x) {
3063 struct stat statbuf;
3065 rep.paths.push_back (*x);
3066 if (stat ((*x).c_str(), &statbuf) == 0) {
3067 rep.space += statbuf.st_size;
3072 /* don't move the file across filesystems, just
3073 stick it in the `dead_sound_dir_name' directory
3074 on whichever filesystem it was already on.
3077 newpath = Glib::path_get_dirname (*x);
3078 newpath = Glib::path_get_dirname (newpath);
3081 newpath += dead_sound_dir_name;
3083 newpath += Glib::path_get_basename ((*x));
3085 if (access (newpath.c_str(), F_OK) == 0) {
3087 /* the new path already exists, try versioning */
3089 char buf[PATH_MAX+1];
3093 snprintf (buf, sizeof (buf), "%s.%d", newpath.c_str(), version);
3096 while (access (newpath_v.c_str(), F_OK) == 0 && version < 999) {
3097 snprintf (buf, sizeof (buf), "%s.%d", newpath.c_str(), ++version);
3101 if (version == 999) {
3102 error << string_compose (_("there are already 1000 files with names like %1; versioning discontinued"),
3106 newpath = newpath_v;
3111 /* it doesn't exist, or we can't read it or something */
3115 if (::rename ((*x).c_str(), newpath.c_str()) != 0) {
3116 error << string_compose (_("cannot rename audio file source from %1 to %2 (%3)"),
3117 (*x), newpath, strerror (errno))
3123 /* see if there an easy to find peakfile for this file, and remove it.
3126 string peakpath = (*x).substr (0, (*x).find_last_of ('.'));
3127 peakpath += ".peak";
3129 if (access (peakpath.c_str(), W_OK) == 0) {
3130 if (::unlink (peakpath.c_str()) != 0) {
3131 error << string_compose (_("cannot remove peakfile %1 for %2 (%3)"),
3132 peakpath, _path, strerror (errno))
3134 /* try to back out */
3135 rename (newpath.c_str(), _path.c_str());
3144 /* dump the history list */
3148 /* save state so we don't end up a session file
3149 referring to non-existent sources.
3156 _state_of_the_state = (StateOfTheState) (_state_of_the_state & ~InCleanup);
3161 Session::cleanup_trash_sources (Session::cleanup_report& rep)
3163 vector<space_and_path>::iterator i;
3164 string dead_sound_dir;
3165 struct dirent* dentry;
3166 struct stat statbuf;
3172 for (i = session_dirs.begin(); i != session_dirs.end(); ++i) {
3174 dead_sound_dir = (*i).path;
3175 dead_sound_dir += dead_sound_dir_name;
3177 if ((dead = opendir (dead_sound_dir.c_str())) == 0) {
3181 while ((dentry = readdir (dead)) != 0) {
3183 /* avoid '.' and '..' */
3185 if ((dentry->d_name[0] == '.' && dentry->d_name[1] == '\0') ||
3186 (dentry->d_name[2] == '\0' && dentry->d_name[0] == '.' && dentry->d_name[1] == '.')) {
3192 fullpath = dead_sound_dir;
3194 fullpath += dentry->d_name;
3196 if (stat (fullpath.c_str(), &statbuf)) {
3200 if (!S_ISREG (statbuf.st_mode)) {
3204 if (unlink (fullpath.c_str())) {
3205 error << string_compose (_("cannot remove dead sound file %1 (%2)"),
3206 fullpath, strerror (errno))
3210 rep.paths.push_back (dentry->d_name);
3211 rep.space += statbuf.st_size;
3222 Session::set_dirty ()
3224 bool was_dirty = dirty();
3226 _state_of_the_state = StateOfTheState (_state_of_the_state | Dirty);
3229 DirtyChanged(); /* EMIT SIGNAL */
3235 Session::set_clean ()
3237 bool was_dirty = dirty();
3239 _state_of_the_state = Clean;
3242 DirtyChanged(); /* EMIT SIGNAL */
3247 Session::add_controllable (Controllable* c)
3249 Glib::Mutex::Lock lm (controllables_lock);
3250 controllables.push_back (c);
3254 Session::remove_controllable (Controllable* c)
3256 if (_state_of_the_state | Deletion) {
3260 Glib::Mutex::Lock lm (controllables_lock);
3261 controllables.remove (c);
3265 Session::controllable_by_id (const PBD::ID& id)
3267 Glib::Mutex::Lock lm (controllables_lock);
3269 for (Controllables::iterator i = controllables.begin(); i != controllables.end(); ++i) {
3270 if ((*i)->id() == id) {
3279 Session::add_instant_xml (XMLNode& node, const std::string& dir)
3281 Stateful::add_instant_xml (node, dir);
3282 Config->add_instant_xml (node, get_user_ardour_path());
3287 Session::save_history (string snapshot_name)
3293 tree.set_root (&history.get_state());
3295 if (snapshot_name.empty()) {
3296 snapshot_name = _current_snapshot_name;
3299 xml_path = _path + snapshot_name + ".history";
3301 bak_path = xml_path + ".bak";
3303 if ((access (xml_path.c_str(), F_OK) == 0) &&
3304 (rename (xml_path.c_str(), bak_path.c_str())))
3306 error << _("could not backup old history file, current history not saved.") << endmsg;
3310 if (!tree.write (xml_path))
3312 error << string_compose (_("history could not be saved to %1"), xml_path) << endmsg;
3314 /* don't leave a corrupt file lying around if it is
3318 if (unlink (xml_path.c_str()))
3320 error << string_compose (_("could not remove corrupt history file %1"), xml_path) << endmsg;
3322 if (rename (bak_path.c_str(), xml_path.c_str()))
3324 error << string_compose (_("could not restore history file from backup %1"), bak_path) << endmsg;
3335 Session::restore_history (string snapshot_name)
3341 xmlpath = _path + snapshot_name + ".history";
3343 if (access (xmlpath.c_str(), F_OK)) {
3344 error << string_compose(_("%1: session history file \"%2\" doesn't exist!"), _name, xmlpath) << endmsg;
3348 if (!tree.read (xmlpath)) {
3349 error << string_compose(_("Could not understand ardour file %1"), xmlpath) << endmsg;
3353 /* replace history */
3355 for (XMLNodeConstIterator it = tree.root()->children().begin();
3356 it != tree.root()->children().end();
3363 ut.set_name(t->property("name")->value());
3364 stringstream ss(t->property("tv_sec")->value());
3366 ss.str(t->property("tv_usec")->value());
3368 ut.set_timestamp(tv);
3370 for (XMLNodeConstIterator child_it = t->children().begin();
3371 child_it != t->children().end();
3374 XMLNode *n = *child_it;
3376 if (n->name() == "MementoCommand" ||
3377 n->name() == "MementoUndoCommand" ||
3378 n->name() == "MementoRedoCommand")
3380 c = memento_command_factory(n);
3386 error << string_compose(_("Couldn't figure out how to make a Command out of a %1 XMLNode."), n->name()) << endmsg;