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;
352 restore_history(_current_snapshot_name);
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) {
629 AudioDiskstream* dstream;
632 dstream = new AudioDiskstream (*this, **citer);
633 /* added automatically by AudioDiskstreamCreated handler */
636 catch (failed_constructor& err) {
637 error << _("Session: could not load diskstream via XML state") << endmsg;
646 Session::remove_pending_capture_state ()
651 xml_path += _current_snapshot_name;
652 xml_path += _pending_suffix;
654 unlink (xml_path.c_str());
658 Session::save_state (string snapshot_name, bool pending)
664 if (_state_of_the_state & CannotSave) {
668 tree.set_root (&get_state());
670 if (snapshot_name.empty()) {
671 snapshot_name = _current_snapshot_name;
677 xml_path += snapshot_name;
678 xml_path += _statefile_suffix;
682 // Make backup of state file
684 if ((access (xml_path.c_str(), F_OK) == 0) &&
685 (rename(xml_path.c_str(), bak_path.c_str()))) {
686 error << _("could not backup old state file, current state not saved.") << endmsg;
693 xml_path += snapshot_name;
694 xml_path += _pending_suffix;
698 if (!tree.write (xml_path)) {
699 error << string_compose (_("state could not be saved to %1"), xml_path) << endmsg;
701 /* don't leave a corrupt file lying around if it is
705 if (unlink (xml_path.c_str())) {
706 error << string_compose (_("could not remove corrupt state file %1"), xml_path) << endmsg;
709 if (rename (bak_path.c_str(), xml_path.c_str())) {
710 error << string_compose (_("could not restore state file from backup %1"), bak_path) << endmsg;
719 save_history(snapshot_name);
721 bool was_dirty = dirty();
723 _state_of_the_state = StateOfTheState (_state_of_the_state & ~Dirty);
726 DirtyChanged (); /* EMIT SIGNAL */
729 StateSaved (snapshot_name); /* EMIT SIGNAL */
736 Session::restore_state (string snapshot_name)
738 if (load_state (snapshot_name) == 0) {
739 set_state (*state_tree->root());
746 Session::load_state (string snapshot_name)
755 state_was_pending = false;
757 /* check for leftover pending state from a crashed capture attempt */
760 xmlpath += snapshot_name;
761 xmlpath += _pending_suffix;
763 if (!access (xmlpath.c_str(), F_OK)) {
765 /* there is pending state from a crashed capture attempt */
767 if (AskAboutPendingState()) {
768 state_was_pending = true;
772 if (!state_was_pending) {
775 xmlpath += snapshot_name;
776 xmlpath += _statefile_suffix;
779 if (access (xmlpath.c_str(), F_OK)) {
780 error << string_compose(_("%1: session state information file \"%2\" doesn't exist!"), _name, xmlpath) << endmsg;
784 state_tree = new XMLTree;
788 if (state_tree->read (xmlpath)) {
791 error << string_compose(_("Could not understand ardour file %1"), xmlpath) << endmsg;
800 Session::load_options (const XMLNode& node)
804 bool have_fade_msecs = false;
805 bool have_fade_steepness = false;
806 float fade_msecs = 0;
807 float fade_steepness = 0;
808 SlaveSource slave_src = None;
810 LocaleGuard lg (X_("POSIX"));
812 if ((child = find_named_node (node, "input-auto-connect")) != 0) {
813 if ((prop = child->property ("val")) != 0) {
814 sscanf (prop->value().c_str(), "%x", &x);
815 input_auto_connect = AutoConnectOption (x);
819 if ((child = find_named_node (node, "output-auto-connect")) != 0) {
820 if ((prop = child->property ("val")) != 0) {
821 sscanf (prop->value().c_str(), "%x", &x);
822 output_auto_connect = AutoConnectOption (x);
826 if ((child = find_named_node (node, "slave")) != 0) {
827 if ((prop = child->property ("type")) != 0) {
828 if (prop->value() == "none") {
830 } else if (prop->value() == "mtc") {
832 } else if (prop->value() == "jack") {
835 set_slave_source (slave_src, 0);
839 /* we cannot set edit mode if we are loading a session,
840 because it might destroy the playlist's positioning
843 if ((child = find_named_node (node, "edit-mode")) != 0) {
844 if ((prop = child->property ("val")) != 0) {
845 if (prop->value() == "slide") {
846 pending_edit_mode = Slide;
847 } else if (prop->value() == "splice") {
848 pending_edit_mode = Splice;
853 if ((child = find_named_node (node, "send-midi-timecode")) != 0) {
854 if ((prop = child->property ("val")) != 0) {
855 bool x = (prop->value() == "yes");
856 send_mtc = !x; /* force change in value */
860 if ((child = find_named_node (node, "send-midi-machine-control")) != 0) {
861 if ((prop = child->property ("val")) != 0) {
862 bool x = (prop->value() == "yes");
863 send_mmc = !x; /* force change in value */
864 set_send_mmc (prop->value() == "yes");
867 if ((child = find_named_node (node, "max-level")) != 0) {
868 if ((prop = child->property ("val")) != 0) {
869 max_level = atoi (prop->value().c_str());
872 if ((child = find_named_node (node, "min-level")) != 0) {
873 if ((prop = child->property ("val")) != 0) {
874 min_level = atoi (prop->value().c_str());
877 if ((child = find_named_node (node, "meter-hold")) != 0) {
878 if ((prop = child->property ("val")) != 0) {
879 _meter_hold = atof (prop->value().c_str());
882 if ((child = find_named_node (node, "meter-falloff")) != 0) {
883 if ((prop = child->property ("val")) != 0) {
884 _meter_falloff = atof (prop->value().c_str());
887 if ((child = find_named_node (node, "long-over-length")) != 0) {
888 if ((prop = child->property ("val")) != 0) {
889 over_length_long = atoi (prop->value().c_str());
892 if ((child = find_named_node (node, "short-over-length")) != 0) {
893 if ((prop = child->property ("val")) != 0) {
894 over_length_short = atoi (prop->value().c_str());
897 if ((child = find_named_node (node, "shuttle-speed-factor")) != 0) {
898 if ((prop = child->property ("val")) != 0) {
899 shuttle_speed_factor = atof (prop->value().c_str());
902 if ((child = find_named_node (node, "shuttle-speed-threshold")) != 0) {
903 if ((prop = child->property ("val")) != 0) {
904 shuttle_speed_threshold = atof (prop->value().c_str());
907 if ((child = find_named_node (node, "rf-speed")) != 0) {
908 if ((prop = child->property ("val")) != 0) {
909 rf_speed = atof (prop->value().c_str());
912 if ((child = find_named_node (node, "smpte-frames-per-second")) != 0) {
913 if ((prop = child->property ("val")) != 0) {
914 set_smpte_type( atof (prop->value().c_str()), smpte_drop_frames );
917 if ((child = find_named_node (node, "smpte-drop-frames")) != 0) {
918 if ((prop = child->property ("val")) != 0) {
919 set_smpte_type( smpte_frames_per_second, (prop->value() == "yes") );
922 if ((child = find_named_node (node, "smpte-offset")) != 0) {
923 if ((prop = child->property ("val")) != 0) {
924 set_smpte_offset( atoi (prop->value().c_str()) );
927 if ((child = find_named_node (node, "smpte-offset-negative")) != 0) {
928 if ((prop = child->property ("val")) != 0) {
929 set_smpte_offset_negative( (prop->value() == "yes") );
932 if ((child = find_named_node (node, "click-sound")) != 0) {
933 if ((prop = child->property ("val")) != 0) {
934 click_sound = prop->value();
937 if ((child = find_named_node (node, "click-emphasis-sound")) != 0) {
938 if ((prop = child->property ("val")) != 0) {
939 click_emphasis_sound = prop->value();
943 if ((child = find_named_node (node, "solo-model")) != 0) {
944 if ((prop = child->property ("val")) != 0) {
945 if (prop->value() == "SoloBus")
946 _solo_model = SoloBus;
948 _solo_model = InverseMute;
952 /* BOOLEAN OPTIONS */
954 if ((child = find_named_node (node, "auto-play")) != 0) {
955 if ((prop = child->property ("val")) != 0) {
956 set_auto_play (prop->value() == "yes");
959 if ((child = find_named_node (node, "auto-input")) != 0) {
960 if ((prop = child->property ("val")) != 0) {
961 set_auto_input (prop->value() == "yes");
964 if ((child = find_named_node (node, "seamless-loop")) != 0) {
965 if ((prop = child->property ("val")) != 0) {
966 set_seamless_loop (prop->value() == "yes");
969 if ((child = find_named_node (node, "punch-in")) != 0) {
970 if ((prop = child->property ("val")) != 0) {
971 set_punch_in (prop->value() == "yes");
974 if ((child = find_named_node (node, "punch-out")) != 0) {
975 if ((prop = child->property ("val")) != 0) {
976 set_punch_out (prop->value() == "yes");
979 if ((child = find_named_node (node, "auto-return")) != 0) {
980 if ((prop = child->property ("val")) != 0) {
981 set_auto_return (prop->value() == "yes");
984 if ((child = find_named_node (node, "send-mtc")) != 0) {
985 if ((prop = child->property ("val")) != 0) {
986 set_send_mtc (prop->value() == "yes");
989 if ((child = find_named_node (node, "mmc-control")) != 0) {
990 if ((prop = child->property ("val")) != 0) {
991 set_mmc_control (prop->value() == "yes");
994 if ((child = find_named_node (node, "midi-control")) != 0) {
995 if ((prop = child->property ("val")) != 0) {
996 set_midi_control (prop->value() == "yes");
999 if ((child = find_named_node (node, "midi-feedback")) != 0) {
1000 if ((prop = child->property ("val")) != 0) {
1001 set_midi_feedback (prop->value() == "yes");
1004 // Legacy support for <recording-plugins>
1005 if ((child = find_named_node (node, "recording-plugins")) != 0) {
1006 if ((prop = child->property ("val")) != 0) {
1007 set_do_not_record_plugins (prop->value() == "no");
1010 if ((child = find_named_node (node, "do-not-record-plugins")) != 0) {
1011 if ((prop = child->property ("val")) != 0) {
1012 set_do_not_record_plugins (prop->value() == "yes");
1015 if ((child = find_named_node (node, "crossfades-active")) != 0) {
1016 if ((prop = child->property ("val")) != 0) {
1017 set_crossfades_active (prop->value() == "yes");
1020 if ((child = find_named_node (node, "audible-click")) != 0) {
1021 if ((prop = child->property ("val")) != 0) {
1022 set_clicking (prop->value() == "yes");
1026 if ((child = find_named_node (node, "end-marker-is-free")) != 0) {
1027 if ((prop = child->property ("val")) != 0) {
1028 _end_location_is_free = (prop->value() == "yes");
1032 if ((child = find_named_node (node, "layer-model")) != 0) {
1033 if ((prop = child->property ("val")) != 0) {
1034 if (prop->value() == X_("LaterHigher")) {
1035 set_layer_model (LaterHigher);
1036 } else if (prop->value() == X_("AddHigher")) {
1037 set_layer_model (AddHigher);
1039 set_layer_model (MoveAddHigher);
1044 if ((child = find_named_node (node, "xfade-model")) != 0) {
1045 if ((prop = child->property ("val")) != 0) {
1046 if (prop->value() == X_("Short")) {
1047 set_xfade_model (ShortCrossfade);
1049 set_xfade_model (FullCrossfade);
1054 if ((child = find_named_node (node, "short-xfade-length")) != 0) {
1055 if ((prop = child->property ("val")) != 0) {
1056 /* value is stored as a fractional seconds */
1057 float secs = atof (prop->value().c_str());
1058 Crossfade::set_short_xfade_length ((jack_nframes_t) floor (secs * frame_rate()));
1062 if ((child = find_named_node (node, "full-xfades-unmuted")) != 0) {
1063 if ((prop = child->property ("val")) != 0) {
1064 crossfades_active = (prop->value() == "yes");
1070 if ((child = find_named_node (node, "default-fade-steepness")) != 0) {
1071 if ((prop = child->property ("val")) != 0) {
1072 fade_steepness = atof (prop->value().c_str());
1073 have_fade_steepness = true;
1076 if ((child = find_named_node (node, "default-fade-msec")) != 0) {
1077 if ((prop = child->property ("val")) != 0) {
1078 fade_msecs = atof (prop->value().c_str());
1079 have_fade_msecs = true;
1083 if (have_fade_steepness || have_fade_msecs) {
1084 // set_default_fade (fade_steepness, fade_msecs);
1091 Session::get_options () const
1096 LocaleGuard lg (X_("POSIX"));
1098 opthead = new XMLNode ("Options");
1100 SlaveSource src = slave_source ();
1104 src_string = "none";
1110 src_string = "jack";
1113 child = opthead->add_child ("slave");
1114 child->add_property ("type", src_string);
1116 child = opthead->add_child ("send-midi-timecode");
1117 child->add_property ("val", send_midi_timecode?"yes":"no");
1119 child = opthead->add_child ("send-midi-machine-control");
1120 child->add_property ("val", send_midi_machine_control?"yes":"no");
1122 snprintf (buf, sizeof(buf)-1, "%x", (int) input_auto_connect);
1123 child = opthead->add_child ("input-auto-connect");
1124 child->add_property ("val", buf);
1126 snprintf (buf, sizeof(buf)-1, "%x", (int) output_auto_connect);
1127 child = opthead->add_child ("output-auto-connect");
1128 child->add_property ("val", buf);
1130 snprintf (buf, sizeof(buf)-1, "%d", max_level);
1131 child = opthead->add_child ("max-level");
1132 child->add_property ("val", buf);
1134 snprintf (buf, sizeof(buf)-1, "%d", min_level);
1135 child = opthead->add_child ("min-level");
1136 child->add_property ("val", buf);
1138 snprintf (buf, sizeof(buf)-1, "%f", _meter_hold);
1139 child = opthead->add_child ("meter-hold");
1140 child->add_property ("val", buf);
1142 snprintf (buf, sizeof(buf)-1, "%f", _meter_falloff);
1143 child = opthead->add_child ("meter-falloff");
1144 child->add_property ("val", buf);
1146 snprintf (buf, sizeof(buf)-1, "%u", over_length_long);
1147 child = opthead->add_child ("long-over-length");
1148 child->add_property ("val", buf);
1150 snprintf (buf, sizeof(buf)-1, "%u", over_length_short);
1151 child = opthead->add_child ("short-over-length");
1152 child->add_property ("val", buf);
1154 snprintf (buf, sizeof(buf)-1, "%f", shuttle_speed_factor);
1155 child = opthead->add_child ("shuttle-speed-factor");
1156 child->add_property ("val", buf);
1158 snprintf (buf, sizeof(buf)-1, "%f", shuttle_speed_threshold);
1159 child = opthead->add_child ("shuttle-speed-threshold");
1160 child->add_property ("val", buf);
1162 snprintf (buf, sizeof(buf)-1, "%f", rf_speed);
1163 child = opthead->add_child ("rf-speed");
1164 child->add_property ("val", buf);
1166 snprintf (buf, sizeof(buf)-1, "%.2f", smpte_frames_per_second);
1167 child = opthead->add_child ("smpte-frames-per-second");
1168 child->add_property ("val", buf);
1170 child = opthead->add_child ("smpte-drop-frames");
1171 child->add_property ("val", smpte_drop_frames ? "yes" : "no");
1173 snprintf (buf, sizeof(buf)-1, "%u", smpte_offset ());
1174 child = opthead->add_child ("smpte-offset");
1175 child->add_property ("val", buf);
1177 child = opthead->add_child ("smpte-offset-negative");
1178 child->add_property ("val", smpte_offset_negative () ? "yes" : "no");
1180 child = opthead->add_child ("edit-mode");
1181 switch (_edit_mode) {
1183 child->add_property ("val", "splice");
1187 child->add_property ("val", "slide");
1191 child = opthead->add_child ("auto-play");
1192 child->add_property ("val", get_auto_play () ? "yes" : "no");
1193 child = opthead->add_child ("auto-input");
1194 child->add_property ("val", get_auto_input () ? "yes" : "no");
1195 child = opthead->add_child ("seamless-loop");
1196 child->add_property ("val", get_seamless_loop () ? "yes" : "no");
1197 child = opthead->add_child ("punch-in");
1198 child->add_property ("val", get_punch_in () ? "yes" : "no");
1199 child = opthead->add_child ("punch-out");
1200 child->add_property ("val", get_punch_out () ? "yes" : "no");
1201 child = opthead->add_child ("all-safe");
1202 child->add_property ("val", get_all_safe () ? "yes" : "no");
1203 child = opthead->add_child ("auto-return");
1204 child->add_property ("val", get_auto_return () ? "yes" : "no");
1205 child = opthead->add_child ("mmc-control");
1206 child->add_property ("val", get_mmc_control () ? "yes" : "no");
1207 child = opthead->add_child ("midi-control");
1208 child->add_property ("val", get_midi_control () ? "yes" : "no");
1209 child = opthead->add_child ("midi-feedback");
1210 child->add_property ("val", get_midi_feedback () ? "yes" : "no");
1211 child = opthead->add_child ("do-not-record-plugins");
1212 child->add_property ("val", get_do_not_record_plugins () ? "yes" : "no");
1213 child = opthead->add_child ("auto-crossfade");
1214 child->add_property ("val", get_crossfades_active () ? "yes" : "no");
1215 child = opthead->add_child ("audible-click");
1216 child->add_property ("val", get_clicking () ? "yes" : "no");
1217 child = opthead->add_child ("end-marker-is-free");
1218 child->add_property ("val", _end_location_is_free ? "yes" : "no");
1220 if (click_sound.length()) {
1221 child = opthead->add_child ("click-sound");
1222 child->add_property ("val", click_sound);
1225 if (click_emphasis_sound.length()) {
1226 child = opthead->add_child ("click-emphasis-sound");
1227 child->add_property ("val", click_emphasis_sound);
1230 child = opthead->add_child ("solo-model");
1231 child->add_property ("val", _solo_model == SoloBus ? "SoloBus" : "InverseMute");
1233 child = opthead->add_child ("layer-model");
1234 switch (layer_model) {
1236 child->add_property ("val", X_("LaterHigher"));
1239 child->add_property ("val", X_("MoveAddHigher"));
1242 child->add_property ("val", X_("AddHigher"));
1246 child = opthead->add_child ("xfade-model");
1247 switch (xfade_model) {
1249 child->add_property ("val", X_("Full"));
1251 case ShortCrossfade:
1252 child->add_property ("val", X_("Short"));
1255 child = opthead->add_child ("short-xfade-length");
1256 /* store as fractions of a second */
1257 snprintf (buf, sizeof(buf)-1, "%f",
1258 (float) Crossfade::short_xfade_length() / frame_rate());
1259 child->add_property ("val", buf);
1261 child = opthead->add_child ("full-xfades-unmuted");
1262 child->add_property ("val", crossfades_active ? "yes" : "no");
1268 Session::get_state()
1274 Session::get_template()
1276 /* if we don't disable rec-enable, diskstreams
1277 will believe they need to store their capture
1278 sources in their state node.
1281 disable_record (false);
1283 return state(false);
1287 Session::state(bool full_state)
1289 XMLNode* node = new XMLNode("Session");
1292 // store libardour version, just in case
1294 snprintf(buf, sizeof(buf)-1, "%d.%d.%d",
1295 libardour_major_version, libardour_minor_version, libardour_micro_version);
1296 node->add_property("version", string(buf));
1298 /* store configuration settings */
1302 /* store the name */
1303 node->add_property ("name", _name);
1305 if (session_dirs.size() > 1) {
1309 vector<space_and_path>::iterator i = session_dirs.begin();
1310 vector<space_and_path>::iterator next;
1312 ++i; /* skip the first one */
1316 while (i != session_dirs.end()) {
1320 if (next != session_dirs.end()) {
1330 child = node->add_child ("Path");
1331 child->add_content (p);
1335 /* save the ID counter */
1337 snprintf (buf, sizeof (buf), "%" PRIu64, ID::counter());
1338 node->add_property ("id-counter", buf);
1340 /* various options */
1342 node->add_child_nocopy (get_options());
1344 child = node->add_child ("Sources");
1347 Glib::Mutex::Lock sl (audio_source_lock);
1349 for (AudioSourceList::iterator siter = audio_sources.begin(); siter != audio_sources.end(); ++siter) {
1351 /* Don't save information about AudioFileSources that are empty */
1353 AudioFileSource* fs;
1355 if ((fs = dynamic_cast<AudioFileSource*> (siter->second)) != 0) {
1356 DestructiveFileSource* dfs = dynamic_cast<DestructiveFileSource*> (fs);
1358 /* destructive file sources are OK if they are empty, because
1359 we will re-use them every time.
1363 if (fs->length() == 0) {
1369 child->add_child_nocopy (siter->second->get_state());
1373 child = node->add_child ("Regions");
1376 Glib::Mutex::Lock rl (region_lock);
1378 for (AudioRegionList::const_iterator i = audio_regions.begin(); i != audio_regions.end(); ++i) {
1380 /* only store regions not attached to playlists */
1382 if (i->second->playlist() == 0) {
1383 child->add_child_nocopy (i->second->state (true));
1388 child = node->add_child ("DiskStreams");
1391 Glib::RWLock::ReaderLock dl (diskstream_lock);
1392 for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
1393 if (!(*i)->hidden()) {
1394 child->add_child_nocopy ((*i)->get_state());
1399 node->add_child_nocopy (_locations.get_state());
1401 child = node->add_child ("Connections");
1403 Glib::Mutex::Lock lm (connection_lock);
1404 for (ConnectionList::iterator i = _connections.begin(); i != _connections.end(); ++i) {
1405 if (!(*i)->system_dependent()) {
1406 child->add_child_nocopy ((*i)->get_state());
1411 child = node->add_child ("Routes");
1413 boost::shared_ptr<RouteList> r = routes.reader ();
1415 RoutePublicOrderSorter cmp;
1416 RouteList public_order (*r);
1417 public_order.sort (cmp);
1419 for (RouteList::iterator i = public_order.begin(); i != public_order.end(); ++i) {
1420 if (!(*i)->hidden()) {
1422 child->add_child_nocopy ((*i)->get_state());
1424 child->add_child_nocopy ((*i)->get_template());
1431 child = node->add_child ("EditGroups");
1432 for (list<RouteGroup *>::iterator i = edit_groups.begin(); i != edit_groups.end(); ++i) {
1433 child->add_child_nocopy ((*i)->get_state());
1436 child = node->add_child ("MixGroups");
1437 for (list<RouteGroup *>::iterator i = mix_groups.begin(); i != mix_groups.end(); ++i) {
1438 child->add_child_nocopy ((*i)->get_state());
1441 child = node->add_child ("Playlists");
1442 for (PlaylistList::iterator i = playlists.begin(); i != playlists.end(); ++i) {
1443 if (!(*i)->hidden()) {
1444 if (!(*i)->empty()) {
1446 child->add_child_nocopy ((*i)->get_state());
1448 child->add_child_nocopy ((*i)->get_template());
1454 child = node->add_child ("UnusedPlaylists");
1455 for (PlaylistList::iterator i = unused_playlists.begin(); i != unused_playlists.end(); ++i) {
1456 if (!(*i)->hidden()) {
1457 if (!(*i)->empty()) {
1459 child->add_child_nocopy ((*i)->get_state());
1461 child->add_child_nocopy ((*i)->get_template());
1469 child = node->add_child ("Click");
1470 child->add_child_nocopy (_click_io->state (full_state));
1474 child = node->add_child ("NamedSelections");
1475 for (NamedSelectionList::iterator i = named_selections.begin(); i != named_selections.end(); ++i) {
1477 child->add_child_nocopy ((*i)->get_state());
1482 node->add_child_nocopy (_tempo_map->get_state());
1485 node->add_child_copy (*_extra_xml);
1492 Session::set_state (const XMLNode& node)
1496 const XMLProperty* prop;
1499 _state_of_the_state = StateOfTheState (_state_of_the_state|CannotSave);
1501 if (node.name() != X_("Session")){
1502 fatal << _("programming error: Session: incorrect XML node sent to set_state()") << endmsg;
1506 StateManager::prohibit_save ();
1508 if ((prop = node.property ("name")) != 0) {
1509 _name = prop->value ();
1512 if ((prop = node.property (X_("id-counter"))) != 0) {
1514 sscanf (prop->value().c_str(), "%" PRIu64, &x);
1515 ID::init_counter (x);
1517 /* old sessions used a timebased counter, so fake
1518 the startup ID counter based on a standard
1523 ID::init_counter (now);
1527 IO::disable_ports ();
1528 IO::disable_connecting ();
1530 /* Object loading order:
1547 if (use_config_midi_ports ()) {
1550 if ((child = find_named_node (node, "Path")) != 0) {
1551 /* XXX this XML content stuff horrible API design */
1552 string raid_path = _path + ':' + child->children().front()->content();
1553 setup_raid_path (raid_path);
1555 /* the path is already set */
1558 if ((child = find_named_node (node, "extra")) != 0) {
1559 _extra_xml = new XMLNode (*child);
1562 if ((child = find_named_node (node, "Options")) == 0) {
1563 error << _("Session: XML state has no options section") << endmsg;
1564 } else if (load_options (*child)) {
1567 if ((child = find_named_node (node, "Sources")) == 0) {
1568 error << _("Session: XML state has no sources section") << endmsg;
1570 } else if (load_sources (*child)) {
1574 if ((child = find_named_node (node, "Regions")) == 0) {
1575 error << _("Session: XML state has no Regions section") << endmsg;
1577 } else if (load_regions (*child)) {
1581 if ((child = find_named_node (node, "Playlists")) == 0) {
1582 error << _("Session: XML state has no playlists section") << endmsg;
1584 } else if (load_playlists (*child)) {
1588 if ((child = find_named_node (node, "UnusedPlaylists")) == 0) {
1590 } else if (load_unused_playlists (*child)) {
1594 if ((child = find_named_node (node, "NamedSelections")) != 0) {
1595 if (load_named_selections (*child)) {
1600 if ((child = find_named_node (node, "DiskStreams")) == 0) {
1601 error << _("Session: XML state has no diskstreams section") << endmsg;
1603 } else if (load_diskstreams (*child)) {
1607 if ((child = find_named_node (node, "Connections")) == 0) {
1608 error << _("Session: XML state has no connections section") << endmsg;
1610 } else if (load_connections (*child)) {
1614 if ((child = find_named_node (node, "Locations")) == 0) {
1615 error << _("Session: XML state has no locations section") << endmsg;
1617 } else if (_locations.set_state (*child)) {
1623 if ((location = _locations.auto_loop_location()) != 0) {
1624 set_auto_loop_location (location);
1627 if ((location = _locations.auto_punch_location()) != 0) {
1628 set_auto_punch_location (location);
1631 if ((location = _locations.end_location()) == 0) {
1632 _locations.add (end_location);
1634 delete end_location;
1635 end_location = location;
1638 if ((location = _locations.start_location()) == 0) {
1639 _locations.add (start_location);
1641 delete start_location;
1642 start_location = location;
1645 _locations.save_state (_("initial state"));
1647 if ((child = find_named_node (node, "EditGroups")) == 0) {
1648 error << _("Session: XML state has no edit groups section") << endmsg;
1650 } else if (load_edit_groups (*child)) {
1654 if ((child = find_named_node (node, "MixGroups")) == 0) {
1655 error << _("Session: XML state has no mix groups section") << endmsg;
1657 } else if (load_mix_groups (*child)) {
1661 if ((child = find_named_node (node, "TempoMap")) == 0) {
1662 error << _("Session: XML state has no Tempo Map section") << endmsg;
1664 } else if (_tempo_map->set_state (*child)) {
1668 if ((child = find_named_node (node, "Routes")) == 0) {
1669 error << _("Session: XML state has no routes section") << endmsg;
1671 } else if (load_routes (*child)) {
1675 if ((child = find_named_node (node, "Click")) == 0) {
1676 warning << _("Session: XML state has no click section") << endmsg;
1677 } else if (_click_io) {
1678 _click_io->set_state (*child);
1681 /* OK, now we can set edit mode */
1683 set_edit_mode (pending_edit_mode);
1685 /* here beginneth the second phase ... */
1687 StateReady (); /* EMIT SIGNAL */
1689 _state_of_the_state = Clean;
1691 StateManager::allow_save (_("initial state"), true);
1693 if (state_was_pending) {
1694 save_state (_current_snapshot_name);
1695 remove_pending_capture_state ();
1696 state_was_pending = false;
1702 /* we failed, re-enable state saving but don't actually save internal state */
1703 StateManager::allow_save (X_("ignored"), false);
1708 Session::load_routes (const XMLNode& node)
1711 XMLNodeConstIterator niter;
1713 nlist = node.children();
1717 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1719 boost::shared_ptr<Route> route (XMLRouteFactory (**niter));
1722 error << _("Session: cannot create Route from XML description.") << endmsg;
1732 boost::shared_ptr<Route>
1733 Session::XMLRouteFactory (const XMLNode& node)
1735 if (node.name() != "Route") {
1736 return boost::shared_ptr<Route> ((Route*) 0);
1739 if (node.property ("diskstream") != 0 || node.property ("diskstream-id") != 0) {
1740 boost::shared_ptr<Route> x (new AudioTrack (*this, node));
1743 boost::shared_ptr<Route> x (new Route (*this, node));
1749 Session::load_regions (const XMLNode& node)
1752 XMLNodeConstIterator niter;
1753 AudioRegion* region;
1755 nlist = node.children();
1759 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1760 if ((region = XMLRegionFactory (**niter, false)) == 0) {
1761 error << _("Session: cannot create Region from XML description.") << endmsg;
1768 Session::XMLRegionFactory (const XMLNode& node, bool full)
1770 const XMLProperty* prop;
1773 AudioRegion::SourceList sources;
1774 uint32_t nchans = 1;
1777 if (node.name() != X_("Region")) {
1781 if ((prop = node.property (X_("channels"))) != 0) {
1782 nchans = atoi (prop->value().c_str());
1786 if ((prop = node.property (X_("source-0"))) == 0) {
1787 if ((prop = node.property ("source")) == 0) {
1788 error << _("Session: XMLNode describing a AudioRegion is incomplete (no source)") << endmsg;
1793 PBD::ID s_id (prop->value());
1795 if ((source = source_by_id (s_id)) == 0) {
1796 error << string_compose(_("Session: XMLNode describing a AudioRegion references an unknown source id =%1"), s_id) << endmsg;
1800 as = dynamic_cast<AudioSource*>(source);
1802 error << string_compose(_("Session: XMLNode describing a AudioRegion references a non-audio source id =%1"), s_id) << endmsg;
1806 sources.push_back (as);
1808 /* pickup other channels */
1810 for (uint32_t n=1; n < nchans; ++n) {
1811 snprintf (buf, sizeof(buf), X_("source-%d"), n);
1812 if ((prop = node.property (buf)) != 0) {
1814 PBD::ID id2 (prop->value());
1816 if ((source = source_by_id (id2)) == 0) {
1817 error << string_compose(_("Session: XMLNode describing a AudioRegion references an unknown source id =%1"), id2) << endmsg;
1821 as = dynamic_cast<AudioSource*>(source);
1823 error << string_compose(_("Session: XMLNode describing a AudioRegion references a non-audio source id =%1"), id2) << endmsg;
1826 sources.push_back (as);
1831 return new AudioRegion (sources, node);
1834 catch (failed_constructor& err) {
1840 Session::get_sources_as_xml ()
1843 XMLNode* node = new XMLNode (X_("Sources"));
1844 Glib::Mutex::Lock lm (audio_source_lock);
1846 for (AudioSourceList::iterator i = audio_sources.begin(); i != audio_sources.end(); ++i) {
1847 node->add_child_nocopy (i->second->get_state());
1850 /* XXX get MIDI and other sources here */
1856 Session::path_from_region_name (string name, string identifier)
1858 char buf[PATH_MAX+1];
1860 string dir = discover_best_sound_dir ();
1862 for (n = 0; n < 999999; ++n) {
1863 if (identifier.length()) {
1864 snprintf (buf, sizeof(buf), "%s/%s%s%" PRIu32 ".wav", dir.c_str(), name.c_str(),
1865 identifier.c_str(), n);
1867 snprintf (buf, sizeof(buf), "%s/%s-%" PRIu32 ".wav", dir.c_str(), name.c_str(), n);
1869 if (access (buf, F_OK) != 0) {
1879 Session::load_sources (const XMLNode& node)
1882 XMLNodeConstIterator niter;
1885 nlist = node.children();
1889 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1891 if ((source = XMLSourceFactory (**niter)) == 0) {
1892 error << _("Session: cannot create Source from XML description.") << endmsg;
1900 Session::XMLSourceFactory (const XMLNode& node)
1904 if (node.name() != "Source") {
1909 src = AudioFileSource::create (node);
1912 catch (failed_constructor& err) {
1913 error << _("Found a sound file that cannot be used by Ardour. Talk to the progammers.") << endmsg;
1921 Session::save_template (string template_name)
1924 string xml_path, bak_path, template_path;
1926 if (_state_of_the_state & CannotSave) {
1931 string dir = template_dir();
1933 if ((dp = opendir (dir.c_str()))) {
1936 if (mkdir (dir.c_str(), S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH)<0) {
1937 error << string_compose(_("Could not create mix templates directory \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
1942 tree.set_root (&get_template());
1945 xml_path += template_name;
1946 xml_path += _template_suffix;
1948 ifstream in(xml_path.c_str());
1951 warning << string_compose(_("Template \"%1\" already exists - new version not created"), template_name) << endmsg;
1957 if (!tree.write (xml_path)) {
1958 error << _("mix template not saved") << endmsg;
1966 Session::rename_template (string old_name, string new_name)
1968 string old_path = template_dir() + old_name + _template_suffix;
1969 string new_path = template_dir() + new_name + _template_suffix;
1971 return rename (old_path.c_str(), new_path.c_str());
1975 Session::delete_template (string name)
1977 string template_path = template_dir();
1978 template_path += name;
1979 template_path += _template_suffix;
1981 return remove (template_path.c_str());
1985 Session::refresh_disk_space ()
1988 struct statfs statfsbuf;
1989 vector<space_and_path>::iterator i;
1990 Glib::Mutex::Lock lm (space_lock);
1993 /* get freespace on every FS that is part of the session path */
1995 _total_free_4k_blocks = 0;
1997 for (i = session_dirs.begin(); i != session_dirs.end(); ++i) {
1998 statfs ((*i).path.c_str(), &statfsbuf);
2000 scale = statfsbuf.f_bsize/4096.0;
2002 (*i).blocks = (uint32_t) floor (statfsbuf.f_bavail * scale);
2003 _total_free_4k_blocks += (*i).blocks;
2009 Session::ensure_sound_dir (string path, string& result)
2014 /* Ensure that the parent directory exists */
2016 if (mkdir (path.c_str(), 0775)) {
2017 if (errno != EEXIST) {
2018 error << string_compose(_("cannot create session directory \"%1\"; ignored"), path) << endmsg;
2023 /* Ensure that the sounds directory exists */
2027 result += sound_dir_name;
2029 if (mkdir (result.c_str(), 0775)) {
2030 if (errno != EEXIST) {
2031 error << string_compose(_("cannot create sounds directory \"%1\"; ignored"), result) << endmsg;
2038 dead += dead_sound_dir_name;
2040 if (mkdir (dead.c_str(), 0775)) {
2041 if (errno != EEXIST) {
2042 error << string_compose(_("cannot create dead sounds directory \"%1\"; ignored"), dead) << endmsg;
2049 peak += peak_dir_name;
2051 if (mkdir (peak.c_str(), 0775)) {
2052 if (errno != EEXIST) {
2053 error << string_compose(_("cannot create peak file directory \"%1\"; ignored"), peak) << endmsg;
2058 /* callers expect this to be terminated ... */
2065 Session::discover_best_sound_dir (bool destructive)
2067 vector<space_and_path>::iterator i;
2070 /* destructive files all go into the same place */
2076 /* handle common case without system calls */
2078 if (session_dirs.size() == 1) {
2082 /* OK, here's the algorithm we're following here:
2084 We want to select which directory to use for
2085 the next file source to be created. Ideally,
2086 we'd like to use a round-robin process so as to
2087 get maximum performance benefits from splitting
2088 the files across multiple disks.
2090 However, in situations without much diskspace, an
2091 RR approach may end up filling up a filesystem
2092 with new files while others still have space.
2093 Its therefore important to pay some attention to
2094 the freespace in the filesystem holding each
2095 directory as well. However, if we did that by
2096 itself, we'd keep creating new files in the file
2097 system with the most space until it was as full
2098 as all others, thus negating any performance
2099 benefits of this RAID-1 like approach.
2101 So, we use a user-configurable space threshold. If
2102 there are at least 2 filesystems with more than this
2103 much space available, we use RR selection between them.
2104 If not, then we pick the filesystem with the most space.
2106 This gets a good balance between the two
2110 refresh_disk_space ();
2112 int free_enough = 0;
2114 for (i = session_dirs.begin(); i != session_dirs.end(); ++i) {
2115 if ((*i).blocks * 4096 >= Config->get_disk_choice_space_threshold()) {
2120 if (free_enough >= 2) {
2122 bool found_it = false;
2124 /* use RR selection process, ensuring that the one
2128 i = last_rr_session_dir;
2131 if (++i == session_dirs.end()) {
2132 i = session_dirs.begin();
2135 if ((*i).blocks * 4096 >= Config->get_disk_choice_space_threshold()) {
2136 if (ensure_sound_dir ((*i).path, result) == 0) {
2137 last_rr_session_dir = i;
2143 } while (i != last_rr_session_dir);
2146 result = sound_dir();
2151 /* pick FS with the most freespace (and that
2152 seems to actually work ...)
2155 vector<space_and_path> sorted;
2156 space_and_path_ascending_cmp cmp;
2158 sorted = session_dirs;
2159 sort (sorted.begin(), sorted.end(), cmp);
2161 for (i = sorted.begin(); i != sorted.end(); ++i) {
2162 if (ensure_sound_dir ((*i).path, result) == 0) {
2163 last_rr_session_dir = i;
2168 /* if the above fails, fall back to the most simplistic solution */
2170 if (i == sorted.end()) {
2179 Session::load_playlists (const XMLNode& node)
2182 XMLNodeConstIterator niter;
2185 nlist = node.children();
2189 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2191 if ((playlist = XMLPlaylistFactory (**niter)) == 0) {
2192 error << _("Session: cannot create Playlist from XML description.") << endmsg;
2200 Session::load_unused_playlists (const XMLNode& node)
2203 XMLNodeConstIterator niter;
2206 nlist = node.children();
2210 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2212 if ((playlist = XMLPlaylistFactory (**niter)) == 0) {
2213 error << _("Session: cannot create Playlist from XML description.") << endmsg;
2217 // now manually untrack it
2219 track_playlist (playlist, false);
2227 Session::XMLPlaylistFactory (const XMLNode& node)
2230 return new AudioPlaylist (*this, node);
2233 catch (failed_constructor& err) {
2239 Session::load_named_selections (const XMLNode& node)
2242 XMLNodeConstIterator niter;
2245 nlist = node.children();
2249 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2251 if ((ns = XMLNamedSelectionFactory (**niter)) == 0) {
2252 error << _("Session: cannot create Named Selection from XML description.") << endmsg;
2260 Session::XMLNamedSelectionFactory (const XMLNode& node)
2263 return new NamedSelection (*this, node);
2266 catch (failed_constructor& err) {
2272 Session::dead_sound_dir () const
2275 res += dead_sound_dir_name;
2281 Session::sound_dir () const
2284 res += sound_dir_name;
2290 Session::tape_dir () const
2293 res += tape_dir_name;
2299 Session::peak_dir () const
2302 res += peak_dir_name;
2308 Session::automation_dir () const
2311 res += "automation/";
2316 Session::template_dir ()
2318 string path = get_user_ardour_path();
2319 path += "templates/";
2325 Session::suffixed_search_path (string suffix, bool data)
2329 path += get_user_ardour_path();
2330 if (path[path.length()-1] != ':') {
2335 path += get_system_data_path();
2337 path += get_system_module_path();
2340 vector<string> split_path;
2342 split (path, split_path, ':');
2345 for (vector<string>::iterator i = split_path.begin(); i != split_path.end(); ++i) {
2350 if (distance (i, split_path.end()) != 1) {
2359 Session::template_path ()
2361 return suffixed_search_path (X_("templates"), true);
2365 Session::control_protocol_path ()
2367 return suffixed_search_path (X_("surfaces"), false);
2371 Session::load_connections (const XMLNode& node)
2373 XMLNodeList nlist = node.children();
2374 XMLNodeConstIterator niter;
2378 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2379 if ((*niter)->name() == "InputConnection") {
2380 add_connection (new ARDOUR::InputConnection (**niter));
2381 } else if ((*niter)->name() == "OutputConnection") {
2382 add_connection (new ARDOUR::OutputConnection (**niter));
2384 error << string_compose(_("Unknown node \"%1\" found in Connections list from state file"), (*niter)->name()) << endmsg;
2393 Session::load_edit_groups (const XMLNode& node)
2395 return load_route_groups (node, true);
2399 Session::load_mix_groups (const XMLNode& node)
2401 return load_route_groups (node, false);
2405 Session::load_route_groups (const XMLNode& node, bool edit)
2407 XMLNodeList nlist = node.children();
2408 XMLNodeConstIterator niter;
2413 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2414 if ((*niter)->name() == "RouteGroup") {
2416 rg = add_edit_group ("");
2417 rg->set_state (**niter);
2419 rg = add_mix_group ("");
2420 rg->set_state (**niter);
2429 state_file_filter (const string &str, void *arg)
2431 return (str.length() > strlen(Session::statefile_suffix()) &&
2432 str.find (Session::statefile_suffix()) == (str.length() - strlen (Session::statefile_suffix())));
2436 bool operator()(const string* a, const string* b) {
2442 remove_end(string* state)
2444 string statename(*state);
2446 string::size_type start,end;
2447 if ((start = statename.find_last_of ('/')) != string::npos) {
2448 statename = statename.substr (start+1);
2451 if ((end = statename.rfind(".ardour")) == string::npos) {
2452 end = statename.length();
2455 return new string(statename.substr (0, end));
2459 Session::possible_states (string path)
2461 PathScanner scanner;
2462 vector<string*>* states = scanner (path, state_file_filter, 0, false, false);
2464 transform(states->begin(), states->end(), states->begin(), remove_end);
2467 sort (states->begin(), states->end(), cmp);
2473 Session::possible_states () const
2475 return possible_states(_path);
2479 Session::auto_save()
2481 save_state (_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.
3155 _state_of_the_state = (StateOfTheState) (_state_of_the_state & ~InCleanup);
3160 Session::cleanup_trash_sources (Session::cleanup_report& rep)
3162 vector<space_and_path>::iterator i;
3163 string dead_sound_dir;
3164 struct dirent* dentry;
3165 struct stat statbuf;
3171 for (i = session_dirs.begin(); i != session_dirs.end(); ++i) {
3173 dead_sound_dir = (*i).path;
3174 dead_sound_dir += dead_sound_dir_name;
3176 if ((dead = opendir (dead_sound_dir.c_str())) == 0) {
3180 while ((dentry = readdir (dead)) != 0) {
3182 /* avoid '.' and '..' */
3184 if ((dentry->d_name[0] == '.' && dentry->d_name[1] == '\0') ||
3185 (dentry->d_name[2] == '\0' && dentry->d_name[0] == '.' && dentry->d_name[1] == '.')) {
3191 fullpath = dead_sound_dir;
3193 fullpath += dentry->d_name;
3195 if (stat (fullpath.c_str(), &statbuf)) {
3199 if (!S_ISREG (statbuf.st_mode)) {
3203 if (unlink (fullpath.c_str())) {
3204 error << string_compose (_("cannot remove dead sound file %1 (%2)"),
3205 fullpath, strerror (errno))
3209 rep.paths.push_back (dentry->d_name);
3210 rep.space += statbuf.st_size;
3221 Session::set_dirty ()
3223 bool was_dirty = dirty();
3225 _state_of_the_state = StateOfTheState (_state_of_the_state | Dirty);
3228 DirtyChanged(); /* EMIT SIGNAL */
3234 Session::set_clean ()
3236 bool was_dirty = dirty();
3238 _state_of_the_state = Clean;
3241 DirtyChanged(); /* EMIT SIGNAL */
3246 Session::add_controllable (Controllable* c)
3248 Glib::Mutex::Lock lm (controllables_lock);
3249 controllables.push_back (c);
3253 Session::remove_controllable (Controllable* c)
3255 if (_state_of_the_state | Deletion) {
3259 Glib::Mutex::Lock lm (controllables_lock);
3260 controllables.remove (c);
3264 Session::controllable_by_id (const PBD::ID& id)
3266 Glib::Mutex::Lock lm (controllables_lock);
3268 for (Controllables::iterator i = controllables.begin(); i != controllables.end(); ++i) {
3269 if ((*i)->id() == id) {
3278 Session::add_instant_xml (XMLNode& node, const std::string& dir)
3280 Stateful::add_instant_xml (node, dir);
3281 Config->add_instant_xml (node, get_user_ardour_path());
3286 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";
3300 info << "Saving history to " << xml_path << endmsg;
3302 bak_path = xml_path + ".bak";
3304 if ((access (xml_path.c_str(), F_OK) == 0) &&
3305 (rename (xml_path.c_str(), bak_path.c_str())))
3307 error << _("could not backup old history file, current history not saved.") << endmsg;
3311 if (!tree.write (xml_path))
3313 error << string_compose (_("history could not be saved to %1"), xml_path) << endmsg;
3315 /* don't leave a corrupt file lying around if it is
3319 if (unlink (xml_path.c_str()))
3321 error << string_compose (_("could not remove corrupt history file %1"), xml_path) << endmsg;
3323 if (rename (bak_path.c_str(), xml_path.c_str()))
3325 error << string_compose (_("could not restore history file from backup %1"), bak_path) << endmsg;
3336 Session::restore_history (string snapshot_name)
3342 xmlpath = _path + snapshot_name + ".history";
3343 info << string_compose(_("Loading history from '%1'."), xmlpath) << endmsg;
3345 if (access (xmlpath.c_str(), F_OK)) {
3346 error << string_compose(_("%1: session history file \"%2\" doesn't exist!"), _name, xmlpath) << endmsg;
3350 if (!tree.read (xmlpath)) {
3351 error << string_compose(_("Could not understand ardour file %1"), xmlpath) << endmsg;
3355 /* replace history */
3357 for (XMLNodeConstIterator it = tree.root()->children().begin();
3358 it != tree.root()->children().end();
3365 ut.set_name(t->property("name")->value());
3366 stringstream ss(t->property("tv_sec")->value());
3368 ss.str(t->property("tv_usec")->value());
3370 ut.set_timestamp(tv);
3372 for (XMLNodeConstIterator child_it = t->children().begin();
3373 child_it != t->children().end();
3376 XMLNode *n = *child_it;
3378 if (n->name() == "MementoCommand" ||
3379 n->name() == "MementoUndoCommand" ||
3380 n->name() == "MementoRedoCommand")
3382 c = memento_command_factory(n);
3388 error << string_compose(_("Couldn't figure out how to make a Command out of a %1 XMLNode."), n->name()) << endmsg;