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>
84 #include <ardour/region_factory.h>
85 #include <ardour/source_factory.h>
91 using namespace ARDOUR;
95 Session::first_stage_init (string fullpath, string snapshot_name)
97 if (fullpath.length() == 0) {
98 throw failed_constructor();
101 char buf[PATH_MAX+1];
102 if (!realpath(fullpath.c_str(), buf) && (errno != ENOENT)) {
103 error << string_compose(_("Could not use path %1 (%s)"), buf, strerror(errno)) << endmsg;
104 throw failed_constructor();
108 if (_path[_path.length()-1] != '/') {
112 /* these two are just provisional settings. set_state()
113 will likely override them.
116 _name = _current_snapshot_name = snapshot_name;
117 setup_raid_path (_path);
119 _current_frame_rate = _engine.frame_rate ();
120 _tempo_map = new TempoMap (_current_frame_rate);
121 _tempo_map->StateChanged.connect (mem_fun (*this, &Session::tempo_map_changed));
123 g_atomic_int_set (&processing_prohibited, 0);
126 _transport_speed = 0;
127 _last_transport_speed = 0;
128 transport_sub_state = 0;
129 _transport_frame = 0;
131 end_location = new Location (0, 0, _("end"), Location::Flags ((Location::IsMark|Location::IsEnd)));
132 start_location = new Location (0, 0, _("start"), Location::Flags ((Location::IsMark|Location::IsStart)));
133 _end_location_is_free = true;
134 g_atomic_int_set (&_record_status, Disabled);
139 seamless_loop = false;
140 loop_changing = false;
142 crossfades_active = false;
145 _last_roll_location = 0;
146 _last_record_location = 0;
147 pending_locate_frame = 0;
148 pending_locate_roll = false;
149 pending_locate_flush = false;
150 dstream_buffer_size = 0;
152 state_was_pending = false;
154 outbound_mtc_smpte_frame = 0;
155 next_quarter_frame_to_send = -1;
156 current_block_size = 0;
157 _solo_latched = true;
158 _solo_model = InverseMute;
159 solo_update_disabled = false;
160 currently_soloing = false;
161 _have_captured = false;
162 _worst_output_latency = 0;
163 _worst_input_latency = 0;
164 _worst_track_latency = 0;
165 _state_of_the_state = StateOfTheState(CannotSave|InitialConnecting|Loading);
168 butler_mixdown_buffer = 0;
169 butler_gain_buffer = 0;
173 post_transport_work = PostTransportWork (0);
174 g_atomic_int_set (&butler_should_do_transport_work, 0);
175 g_atomic_int_set (&butler_active, 0);
176 g_atomic_int_set (&_playback_load, 100);
177 g_atomic_int_set (&_capture_load, 100);
178 g_atomic_int_set (&_playback_load_min, 100);
179 g_atomic_int_set (&_capture_load_min, 100);
181 pending_edit_mode = _edit_mode;
183 input_auto_connect = AutoConnectOption (0);
184 output_auto_connect = AutoConnectOption (0);
185 waiting_to_start = false;
187 _gain_automation_buffer = 0;
188 _pan_automation_buffer = 0;
190 pending_abort = false;
191 layer_model = MoveAddHigher;
192 xfade_model = ShortCrossfade;
193 destructive_index = 0;
196 AudioDiskstream::allocate_working_buffers();
198 /* default short fade = 15ms */
200 Crossfade::set_short_xfade_length ((jack_nframes_t) floor ((15.0 * frame_rate()) / 1000.0));
201 DestructiveFileSource::setup_standard_crossfades (frame_rate());
203 last_mmc_step.tv_sec = 0;
204 last_mmc_step.tv_usec = 0;
207 preroll.type = AnyTime::Frames;
209 postroll.type = AnyTime::Frames;
212 /* click sounds are unset by default, which causes us to internal
213 waveforms for clicks.
217 click_requested = false;
219 click_emphasis_data = 0;
221 click_emphasis_length = 0;
223 process_function = &Session::process_with_events;
227 _smpte_offset_negative = true;
228 last_smpte_valid = false;
230 last_rr_session_dir = session_dirs.begin();
231 refresh_disk_space ();
233 // set_default_fade (0.2, 5.0); /* steepness, millisecs */
235 /* default configuration */
237 do_not_record_plugins = false;
238 over_length_short = 2;
239 over_length_long = 10;
240 send_midi_timecode = false;
241 send_midi_machine_control = false;
242 shuttle_speed_factor = 1.0;
243 shuttle_speed_threshold = 5;
245 _meter_hold = 100; // XXX unknown units: number of calls to meter::set()
246 _meter_falloff = 0.375f; // XXX unknown units: refresh_rate
252 average_slave_delta = 1800;
253 have_first_delta_accumulator = false;
254 delta_accumulator_cnt = 0;
255 slave_state = Stopped;
257 /* default SMPTE type is 30 FPS, non-drop */
259 set_smpte_type (30.0, false);
261 _engine.GraphReordered.connect (mem_fun (*this, &Session::graph_reordered));
263 /* These are all static "per-class" signals */
265 RegionFactory::CheckNewRegion.connect (mem_fun (*this, &Session::add_region));
266 SourceFactory::SourceCreated.connect (mem_fun (*this, &Session::add_source));
267 Playlist::PlaylistCreated.connect (mem_fun (*this, &Session::add_playlist));
268 Redirect::RedirectCreated.connect (mem_fun (*this, &Session::add_redirect));
269 NamedSelection::NamedSelectionCreated.connect (mem_fun (*this, &Session::add_named_selection));
270 Curve::CurveCreated.connect (mem_fun (*this, &Session::add_curve));
271 AutomationList::AutomationListCreated.connect (mem_fun (*this, &Session::add_automation_list));
273 Controllable::Created.connect (mem_fun (*this, &Session::add_controllable));
274 Controllable::GoingAway.connect (mem_fun (*this, &Session::remove_controllable));
276 IO::MoreOutputs.connect (mem_fun (*this, &Session::ensure_passthru_buffers));
278 /* stop IO objects from doing stuff until we're ready for them */
280 IO::disable_panners ();
281 IO::disable_ports ();
282 IO::disable_connecting ();
286 Session::second_stage_init (bool new_session)
288 AudioFileSource::set_peak_dir (peak_dir());
291 if (load_state (_current_snapshot_name)) {
292 cerr << "load state failed\n";
295 remove_empty_sounds ();
298 if (start_butler_thread()) {
302 if (start_midi_thread ()) {
307 if (set_state (*state_tree->root())) {
312 /* we can't save till after ::when_engine_running() is called,
313 because otherwise we save state with no connections made.
314 therefore, we reset _state_of_the_state because ::set_state()
315 will have cleared it.
317 we also have to include Loading so that any events that get
318 generated between here and the end of ::when_engine_running()
319 will be processed directly rather than queued.
322 _state_of_the_state = StateOfTheState (_state_of_the_state|CannotSave|Loading);
324 // set_auto_input (true);
325 _locations.changed.connect (mem_fun (this, &Session::locations_changed));
326 _locations.added.connect (mem_fun (this, &Session::locations_added));
327 setup_click_sounds (0);
328 setup_midi_control ();
330 /* Pay attention ... */
332 _engine.Halted.connect (mem_fun (*this, &Session::engine_halted));
333 _engine.Xrun.connect (mem_fun (*this, &Session::xrun_recovery));
335 if (_engine.running()) {
336 when_engine_running();
338 first_time_running = _engine.Running.connect (mem_fun (*this, &Session::when_engine_running));
341 send_full_time_code ();
342 _engine.transport_locate (0);
343 deliver_mmc (MIDI::MachineControl::cmdMmcReset, 0);
344 deliver_mmc (MIDI::MachineControl::cmdLocate, 0);
346 ControlProtocolManager::instance().set_session (*this);
349 _end_location_is_free = true;
351 _end_location_is_free = false;
354 restore_history(_current_snapshot_name);
359 Session::raid_path () const
363 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
368 return path.substr (0, path.length() - 1); // drop final colon
372 Session::set_raid_path (string path)
374 /* public-access to setup_raid_path() */
376 setup_raid_path (path);
380 Session::setup_raid_path (string path)
382 string::size_type colon;
386 string::size_type len = path.length();
391 if (path.length() == 0) {
395 session_dirs.clear ();
397 for (string::size_type n = 0; n < len; ++n) {
398 if (path[n] == ':') {
405 /* no multiple search path, just one location (common case) */
409 session_dirs.push_back (sp);
416 if (fspath[fspath.length()-1] != '/') {
419 fspath += sound_dir_name;
425 if (fspath[fspath.length()-1] != '/') {
428 fspath += tape_dir_name;
430 AudioFileSource::set_search_path (fspath);
437 while ((colon = remaining.find_first_of (':')) != string::npos) {
440 sp.path = remaining.substr (0, colon);
441 session_dirs.push_back (sp);
443 /* add sounds to file search path */
446 if (fspath[fspath.length()-1] != '/') {
449 fspath += sound_dir_name;
452 /* add tape dir to file search path */
455 if (fspath[fspath.length()-1] != '/') {
458 fspath += tape_dir_name;
461 remaining = remaining.substr (colon+1);
464 if (remaining.length()) {
471 if (fspath[fspath.length()-1] != '/') {
474 fspath += sound_dir_name;
478 if (fspath[fspath.length()-1] != '/') {
481 fspath += tape_dir_name;
483 session_dirs.push_back (sp);
486 /* set the AudioFileSource search path */
488 AudioFileSource::set_search_path (fspath);
490 /* reset the round-robin soundfile path thingie */
492 last_rr_session_dir = session_dirs.begin();
496 Session::create (bool& new_session, string* mix_template, jack_nframes_t initial_length)
500 if (mkdir (_path.c_str(), 0755) < 0) {
501 if (errno == EEXIST) {
504 error << string_compose(_("Session: cannot create session dir \"%1\" (%2)"), _path, strerror (errno)) << endmsg;
513 if (mkdir (dir.c_str(), 0755) < 0) {
514 if (errno != EEXIST) {
515 error << string_compose(_("Session: cannot create session peakfile dir \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
522 if (mkdir (dir.c_str(), 0755) < 0) {
523 if (errno != EEXIST) {
524 error << string_compose(_("Session: cannot create session sounds dir \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
531 if (mkdir (dir.c_str(), 0755) < 0) {
532 if (errno != EEXIST) {
533 error << string_compose(_("Session: cannot create session tape dir \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
538 dir = dead_sound_dir ();
540 if (mkdir (dir.c_str(), 0755) < 0) {
541 if (errno != EEXIST) {
542 error << string_compose(_("Session: cannot create session dead sounds dir \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
547 dir = automation_dir ();
549 if (mkdir (dir.c_str(), 0755) < 0) {
550 if (errno != EEXIST) {
551 error << string_compose(_("Session: cannot create session automation dir \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
557 /* check new_session so we don't overwrite an existing one */
561 std::string in_path = *mix_template;
563 ifstream in(in_path.c_str());
566 string out_path = _path;
568 out_path += _statefile_suffix;
570 ofstream out(out_path.c_str());
575 // okay, session is set up. Treat like normal saved
576 // session from now on.
582 error << string_compose (_("Could not open %1 for writing mix template"), out_path)
588 error << string_compose (_("Could not open mix template %1 for reading"), in_path)
595 warning << _("Session already exists. Not overwriting") << endmsg;
602 /* set initial start + end point */
604 start_location->set_end (0);
605 _locations.add (start_location);
607 end_location->set_end (initial_length);
608 _locations.add (end_location);
610 _state_of_the_state = Clean;
612 if (save_state (_current_snapshot_name)) {
613 save_history (_current_snapshot_name);
622 Session::load_diskstreams (const XMLNode& node)
625 XMLNodeConstIterator citer;
627 clist = node.children();
629 for (citer = clist.begin(); citer != clist.end(); ++citer) {
633 boost::shared_ptr<AudioDiskstream> dstream (new AudioDiskstream (*this, **citer));
634 add_diskstream (dstream);
637 catch (failed_constructor& err) {
638 error << _("Session: could not load diskstream via XML state") << endmsg;
647 Session::remove_pending_capture_state ()
652 xml_path += _current_snapshot_name;
653 xml_path += _pending_suffix;
655 unlink (xml_path.c_str());
659 Session::save_state (string snapshot_name, bool pending)
665 if (_state_of_the_state & CannotSave) {
669 tree.set_root (&get_state());
671 if (snapshot_name.empty()) {
672 snapshot_name = _current_snapshot_name;
678 xml_path += snapshot_name;
679 xml_path += _statefile_suffix;
683 // Make backup of state file
685 if ((access (xml_path.c_str(), F_OK) == 0) &&
686 (rename(xml_path.c_str(), bak_path.c_str()))) {
687 error << _("could not backup old state file, current state not saved.") << endmsg;
694 xml_path += snapshot_name;
695 xml_path += _pending_suffix;
699 if (!tree.write (xml_path)) {
700 error << string_compose (_("state could not be saved to %1"), xml_path) << endmsg;
702 /* don't leave a corrupt file lying around if it is
706 if (unlink (xml_path.c_str())) {
707 error << string_compose (_("could not remove corrupt state file %1"), xml_path) << endmsg;
710 if (rename (bak_path.c_str(), xml_path.c_str())) {
711 error << string_compose (_("could not restore state file from backup %1"), bak_path) << endmsg;
720 save_history(snapshot_name);
722 bool was_dirty = dirty();
724 _state_of_the_state = StateOfTheState (_state_of_the_state & ~Dirty);
727 DirtyChanged (); /* EMIT SIGNAL */
730 StateSaved (snapshot_name); /* EMIT SIGNAL */
737 Session::restore_state (string snapshot_name)
739 if (load_state (snapshot_name) == 0) {
740 set_state (*state_tree->root());
747 Session::load_state (string snapshot_name)
756 state_was_pending = false;
758 /* check for leftover pending state from a crashed capture attempt */
761 xmlpath += snapshot_name;
762 xmlpath += _pending_suffix;
764 if (!access (xmlpath.c_str(), F_OK)) {
766 /* there is pending state from a crashed capture attempt */
768 if (AskAboutPendingState()) {
769 state_was_pending = true;
773 if (!state_was_pending) {
776 xmlpath += snapshot_name;
777 xmlpath += _statefile_suffix;
780 if (access (xmlpath.c_str(), F_OK)) {
781 error << string_compose(_("%1: session state information file \"%2\" doesn't exist!"), _name, xmlpath) << endmsg;
785 state_tree = new XMLTree;
789 if (state_tree->read (xmlpath)) {
792 error << string_compose(_("Could not understand ardour file %1"), xmlpath) << endmsg;
801 Session::load_options (const XMLNode& node)
805 bool have_fade_msecs = false;
806 bool have_fade_steepness = false;
807 float fade_msecs = 0;
808 float fade_steepness = 0;
809 SlaveSource slave_src = None;
811 LocaleGuard lg (X_("POSIX"));
813 if ((child = find_named_node (node, "input-auto-connect")) != 0) {
814 if ((prop = child->property ("val")) != 0) {
815 sscanf (prop->value().c_str(), "%x", &x);
816 input_auto_connect = AutoConnectOption (x);
820 if ((child = find_named_node (node, "output-auto-connect")) != 0) {
821 if ((prop = child->property ("val")) != 0) {
822 sscanf (prop->value().c_str(), "%x", &x);
823 output_auto_connect = AutoConnectOption (x);
827 if ((child = find_named_node (node, "slave")) != 0) {
828 if ((prop = child->property ("type")) != 0) {
829 if (prop->value() == "none") {
831 } else if (prop->value() == "mtc") {
833 } else if (prop->value() == "jack") {
836 set_slave_source (slave_src, 0);
840 /* we cannot set edit mode if we are loading a session,
841 because it might destroy the playlist's positioning
844 if ((child = find_named_node (node, "edit-mode")) != 0) {
845 if ((prop = child->property ("val")) != 0) {
846 if (prop->value() == "slide") {
847 pending_edit_mode = Slide;
848 } else if (prop->value() == "splice") {
849 pending_edit_mode = Splice;
854 if ((child = find_named_node (node, "send-midi-timecode")) != 0) {
855 if ((prop = child->property ("val")) != 0) {
856 bool x = (prop->value() == "yes");
857 send_mtc = !x; /* force change in value */
861 if ((child = find_named_node (node, "send-midi-machine-control")) != 0) {
862 if ((prop = child->property ("val")) != 0) {
863 bool x = (prop->value() == "yes");
864 send_mmc = !x; /* force change in value */
865 set_send_mmc (prop->value() == "yes");
868 if ((child = find_named_node (node, "max-level")) != 0) {
869 if ((prop = child->property ("val")) != 0) {
870 max_level = atoi (prop->value().c_str());
873 if ((child = find_named_node (node, "min-level")) != 0) {
874 if ((prop = child->property ("val")) != 0) {
875 min_level = atoi (prop->value().c_str());
878 if ((child = find_named_node (node, "meter-hold")) != 0) {
879 if ((prop = child->property ("val")) != 0) {
880 _meter_hold = atof (prop->value().c_str());
883 if ((child = find_named_node (node, "meter-falloff")) != 0) {
884 if ((prop = child->property ("val")) != 0) {
885 _meter_falloff = atof (prop->value().c_str());
888 if ((child = find_named_node (node, "long-over-length")) != 0) {
889 if ((prop = child->property ("val")) != 0) {
890 over_length_long = atoi (prop->value().c_str());
893 if ((child = find_named_node (node, "short-over-length")) != 0) {
894 if ((prop = child->property ("val")) != 0) {
895 over_length_short = atoi (prop->value().c_str());
898 if ((child = find_named_node (node, "shuttle-speed-factor")) != 0) {
899 if ((prop = child->property ("val")) != 0) {
900 shuttle_speed_factor = atof (prop->value().c_str());
903 if ((child = find_named_node (node, "shuttle-speed-threshold")) != 0) {
904 if ((prop = child->property ("val")) != 0) {
905 shuttle_speed_threshold = atof (prop->value().c_str());
908 if ((child = find_named_node (node, "rf-speed")) != 0) {
909 if ((prop = child->property ("val")) != 0) {
910 rf_speed = atof (prop->value().c_str());
913 if ((child = find_named_node (node, "smpte-frames-per-second")) != 0) {
914 if ((prop = child->property ("val")) != 0) {
915 set_smpte_type( atof (prop->value().c_str()), smpte_drop_frames );
918 if ((child = find_named_node (node, "smpte-drop-frames")) != 0) {
919 if ((prop = child->property ("val")) != 0) {
920 set_smpte_type( smpte_frames_per_second, (prop->value() == "yes") );
923 if ((child = find_named_node (node, "smpte-offset")) != 0) {
924 if ((prop = child->property ("val")) != 0) {
925 set_smpte_offset( atoi (prop->value().c_str()) );
928 if ((child = find_named_node (node, "smpte-offset-negative")) != 0) {
929 if ((prop = child->property ("val")) != 0) {
930 set_smpte_offset_negative( (prop->value() == "yes") );
933 if ((child = find_named_node (node, "click-sound")) != 0) {
934 if ((prop = child->property ("val")) != 0) {
935 click_sound = prop->value();
938 if ((child = find_named_node (node, "click-emphasis-sound")) != 0) {
939 if ((prop = child->property ("val")) != 0) {
940 click_emphasis_sound = prop->value();
944 if ((child = find_named_node (node, "solo-model")) != 0) {
945 if ((prop = child->property ("val")) != 0) {
946 if (prop->value() == "SoloBus")
947 _solo_model = SoloBus;
949 _solo_model = InverseMute;
953 /* BOOLEAN OPTIONS */
955 if ((child = find_named_node (node, "auto-play")) != 0) {
956 if ((prop = child->property ("val")) != 0) {
957 set_auto_play (prop->value() == "yes");
960 if ((child = find_named_node (node, "auto-input")) != 0) {
961 if ((prop = child->property ("val")) != 0) {
962 set_auto_input (prop->value() == "yes");
965 if ((child = find_named_node (node, "seamless-loop")) != 0) {
966 if ((prop = child->property ("val")) != 0) {
967 set_seamless_loop (prop->value() == "yes");
970 if ((child = find_named_node (node, "punch-in")) != 0) {
971 if ((prop = child->property ("val")) != 0) {
972 set_punch_in (prop->value() == "yes");
975 if ((child = find_named_node (node, "punch-out")) != 0) {
976 if ((prop = child->property ("val")) != 0) {
977 set_punch_out (prop->value() == "yes");
980 if ((child = find_named_node (node, "auto-return")) != 0) {
981 if ((prop = child->property ("val")) != 0) {
982 set_auto_return (prop->value() == "yes");
985 if ((child = find_named_node (node, "send-mtc")) != 0) {
986 if ((prop = child->property ("val")) != 0) {
987 set_send_mtc (prop->value() == "yes");
990 if ((child = find_named_node (node, "mmc-control")) != 0) {
991 if ((prop = child->property ("val")) != 0) {
992 set_mmc_control (prop->value() == "yes");
995 if ((child = find_named_node (node, "midi-control")) != 0) {
996 if ((prop = child->property ("val")) != 0) {
997 set_midi_control (prop->value() == "yes");
1000 if ((child = find_named_node (node, "midi-feedback")) != 0) {
1001 if ((prop = child->property ("val")) != 0) {
1002 set_midi_feedback (prop->value() == "yes");
1005 // Legacy support for <recording-plugins>
1006 if ((child = find_named_node (node, "recording-plugins")) != 0) {
1007 if ((prop = child->property ("val")) != 0) {
1008 set_do_not_record_plugins (prop->value() == "no");
1011 if ((child = find_named_node (node, "do-not-record-plugins")) != 0) {
1012 if ((prop = child->property ("val")) != 0) {
1013 set_do_not_record_plugins (prop->value() == "yes");
1016 if ((child = find_named_node (node, "crossfades-active")) != 0) {
1017 if ((prop = child->property ("val")) != 0) {
1018 set_crossfades_active (prop->value() == "yes");
1021 if ((child = find_named_node (node, "audible-click")) != 0) {
1022 if ((prop = child->property ("val")) != 0) {
1023 set_clicking (prop->value() == "yes");
1027 if ((child = find_named_node (node, "end-marker-is-free")) != 0) {
1028 if ((prop = child->property ("val")) != 0) {
1029 _end_location_is_free = (prop->value() == "yes");
1033 if ((child = find_named_node (node, "layer-model")) != 0) {
1034 if ((prop = child->property ("val")) != 0) {
1035 if (prop->value() == X_("LaterHigher")) {
1036 set_layer_model (LaterHigher);
1037 } else if (prop->value() == X_("AddHigher")) {
1038 set_layer_model (AddHigher);
1040 set_layer_model (MoveAddHigher);
1045 if ((child = find_named_node (node, "xfade-model")) != 0) {
1046 if ((prop = child->property ("val")) != 0) {
1047 if (prop->value() == X_("Short")) {
1048 set_xfade_model (ShortCrossfade);
1050 set_xfade_model (FullCrossfade);
1055 if ((child = find_named_node (node, "short-xfade-length")) != 0) {
1056 if ((prop = child->property ("val")) != 0) {
1057 /* value is stored as a fractional seconds */
1058 float secs = atof (prop->value().c_str());
1059 Crossfade::set_short_xfade_length ((jack_nframes_t) floor (secs * frame_rate()));
1063 if ((child = find_named_node (node, "full-xfades-unmuted")) != 0) {
1064 if ((prop = child->property ("val")) != 0) {
1065 crossfades_active = (prop->value() == "yes");
1071 if ((child = find_named_node (node, "default-fade-steepness")) != 0) {
1072 if ((prop = child->property ("val")) != 0) {
1073 fade_steepness = atof (prop->value().c_str());
1074 have_fade_steepness = true;
1077 if ((child = find_named_node (node, "default-fade-msec")) != 0) {
1078 if ((prop = child->property ("val")) != 0) {
1079 fade_msecs = atof (prop->value().c_str());
1080 have_fade_msecs = true;
1084 if (have_fade_steepness || have_fade_msecs) {
1085 // set_default_fade (fade_steepness, fade_msecs);
1092 Session::get_options () const
1097 LocaleGuard lg (X_("POSIX"));
1099 opthead = new XMLNode ("Options");
1101 SlaveSource src = slave_source ();
1105 src_string = "none";
1111 src_string = "jack";
1114 child = opthead->add_child ("slave");
1115 child->add_property ("type", src_string);
1117 child = opthead->add_child ("send-midi-timecode");
1118 child->add_property ("val", send_midi_timecode?"yes":"no");
1120 child = opthead->add_child ("send-midi-machine-control");
1121 child->add_property ("val", send_midi_machine_control?"yes":"no");
1123 snprintf (buf, sizeof(buf)-1, "%x", (int) input_auto_connect);
1124 child = opthead->add_child ("input-auto-connect");
1125 child->add_property ("val", buf);
1127 snprintf (buf, sizeof(buf)-1, "%x", (int) output_auto_connect);
1128 child = opthead->add_child ("output-auto-connect");
1129 child->add_property ("val", buf);
1131 snprintf (buf, sizeof(buf)-1, "%d", max_level);
1132 child = opthead->add_child ("max-level");
1133 child->add_property ("val", buf);
1135 snprintf (buf, sizeof(buf)-1, "%d", min_level);
1136 child = opthead->add_child ("min-level");
1137 child->add_property ("val", buf);
1139 snprintf (buf, sizeof(buf)-1, "%f", _meter_hold);
1140 child = opthead->add_child ("meter-hold");
1141 child->add_property ("val", buf);
1143 snprintf (buf, sizeof(buf)-1, "%f", _meter_falloff);
1144 child = opthead->add_child ("meter-falloff");
1145 child->add_property ("val", buf);
1147 snprintf (buf, sizeof(buf)-1, "%u", over_length_long);
1148 child = opthead->add_child ("long-over-length");
1149 child->add_property ("val", buf);
1151 snprintf (buf, sizeof(buf)-1, "%u", over_length_short);
1152 child = opthead->add_child ("short-over-length");
1153 child->add_property ("val", buf);
1155 snprintf (buf, sizeof(buf)-1, "%f", shuttle_speed_factor);
1156 child = opthead->add_child ("shuttle-speed-factor");
1157 child->add_property ("val", buf);
1159 snprintf (buf, sizeof(buf)-1, "%f", shuttle_speed_threshold);
1160 child = opthead->add_child ("shuttle-speed-threshold");
1161 child->add_property ("val", buf);
1163 snprintf (buf, sizeof(buf)-1, "%f", rf_speed);
1164 child = opthead->add_child ("rf-speed");
1165 child->add_property ("val", buf);
1167 snprintf (buf, sizeof(buf)-1, "%.2f", smpte_frames_per_second);
1168 child = opthead->add_child ("smpte-frames-per-second");
1169 child->add_property ("val", buf);
1171 child = opthead->add_child ("smpte-drop-frames");
1172 child->add_property ("val", smpte_drop_frames ? "yes" : "no");
1174 snprintf (buf, sizeof(buf)-1, "%u", smpte_offset ());
1175 child = opthead->add_child ("smpte-offset");
1176 child->add_property ("val", buf);
1178 child = opthead->add_child ("smpte-offset-negative");
1179 child->add_property ("val", smpte_offset_negative () ? "yes" : "no");
1181 child = opthead->add_child ("edit-mode");
1182 switch (_edit_mode) {
1184 child->add_property ("val", "splice");
1188 child->add_property ("val", "slide");
1192 child = opthead->add_child ("auto-play");
1193 child->add_property ("val", get_auto_play () ? "yes" : "no");
1194 child = opthead->add_child ("auto-input");
1195 child->add_property ("val", get_auto_input () ? "yes" : "no");
1196 child = opthead->add_child ("seamless-loop");
1197 child->add_property ("val", get_seamless_loop () ? "yes" : "no");
1198 child = opthead->add_child ("punch-in");
1199 child->add_property ("val", get_punch_in () ? "yes" : "no");
1200 child = opthead->add_child ("punch-out");
1201 child->add_property ("val", get_punch_out () ? "yes" : "no");
1202 child = opthead->add_child ("all-safe");
1203 child->add_property ("val", get_all_safe () ? "yes" : "no");
1204 child = opthead->add_child ("auto-return");
1205 child->add_property ("val", get_auto_return () ? "yes" : "no");
1206 child = opthead->add_child ("mmc-control");
1207 child->add_property ("val", get_mmc_control () ? "yes" : "no");
1208 child = opthead->add_child ("midi-control");
1209 child->add_property ("val", get_midi_control () ? "yes" : "no");
1210 child = opthead->add_child ("midi-feedback");
1211 child->add_property ("val", get_midi_feedback () ? "yes" : "no");
1212 child = opthead->add_child ("do-not-record-plugins");
1213 child->add_property ("val", get_do_not_record_plugins () ? "yes" : "no");
1214 child = opthead->add_child ("auto-crossfade");
1215 child->add_property ("val", get_crossfades_active () ? "yes" : "no");
1216 child = opthead->add_child ("audible-click");
1217 child->add_property ("val", get_clicking () ? "yes" : "no");
1218 child = opthead->add_child ("end-marker-is-free");
1219 child->add_property ("val", _end_location_is_free ? "yes" : "no");
1221 if (click_sound.length()) {
1222 child = opthead->add_child ("click-sound");
1223 child->add_property ("val", click_sound);
1226 if (click_emphasis_sound.length()) {
1227 child = opthead->add_child ("click-emphasis-sound");
1228 child->add_property ("val", click_emphasis_sound);
1231 child = opthead->add_child ("solo-model");
1232 child->add_property ("val", _solo_model == SoloBus ? "SoloBus" : "InverseMute");
1234 child = opthead->add_child ("layer-model");
1235 switch (layer_model) {
1237 child->add_property ("val", X_("LaterHigher"));
1240 child->add_property ("val", X_("MoveAddHigher"));
1243 child->add_property ("val", X_("AddHigher"));
1247 child = opthead->add_child ("xfade-model");
1248 switch (xfade_model) {
1250 child->add_property ("val", X_("Full"));
1252 case ShortCrossfade:
1253 child->add_property ("val", X_("Short"));
1256 child = opthead->add_child ("short-xfade-length");
1257 /* store as fractions of a second */
1258 snprintf (buf, sizeof(buf)-1, "%f",
1259 (float) Crossfade::short_xfade_length() / frame_rate());
1260 child->add_property ("val", buf);
1262 child = opthead->add_child ("full-xfades-unmuted");
1263 child->add_property ("val", crossfades_active ? "yes" : "no");
1269 Session::get_state()
1275 Session::get_template()
1277 /* if we don't disable rec-enable, diskstreams
1278 will believe they need to store their capture
1279 sources in their state node.
1282 disable_record (false);
1284 return state(false);
1288 Session::state(bool full_state)
1290 XMLNode* node = new XMLNode("Session");
1293 // store libardour version, just in case
1295 snprintf(buf, sizeof(buf)-1, "%d.%d.%d",
1296 libardour_major_version, libardour_minor_version, libardour_micro_version);
1297 node->add_property("version", string(buf));
1299 /* store configuration settings */
1303 /* store the name */
1304 node->add_property ("name", _name);
1306 if (session_dirs.size() > 1) {
1310 vector<space_and_path>::iterator i = session_dirs.begin();
1311 vector<space_and_path>::iterator next;
1313 ++i; /* skip the first one */
1317 while (i != session_dirs.end()) {
1321 if (next != session_dirs.end()) {
1331 child = node->add_child ("Path");
1332 child->add_content (p);
1336 /* save the ID counter */
1338 snprintf (buf, sizeof (buf), "%" PRIu64, ID::counter());
1339 node->add_property ("id-counter", buf);
1341 /* various options */
1343 node->add_child_nocopy (get_options());
1345 child = node->add_child ("Sources");
1348 Glib::Mutex::Lock sl (audio_source_lock);
1350 for (AudioSourceList::iterator siter = audio_sources.begin(); siter != audio_sources.end(); ++siter) {
1352 /* Don't save information about AudioFileSources that are empty */
1354 boost::shared_ptr<AudioFileSource> fs;
1356 if ((fs = boost::dynamic_pointer_cast<AudioFileSource> (siter->second)) != 0) {
1357 boost::shared_ptr<DestructiveFileSource> dfs = boost::dynamic_pointer_cast<DestructiveFileSource> (fs);
1359 /* destructive file sources are OK if they are empty, because
1360 we will re-use them every time.
1364 if (fs->length() == 0) {
1370 child->add_child_nocopy (siter->second->get_state());
1374 child = node->add_child ("Regions");
1377 Glib::Mutex::Lock rl (region_lock);
1379 for (AudioRegionList::const_iterator i = audio_regions.begin(); i != audio_regions.end(); ++i) {
1381 /* only store regions not attached to playlists */
1383 if (i->second->playlist() == 0) {
1384 child->add_child_nocopy (i->second->state (true));
1389 child = node->add_child ("DiskStreams");
1392 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
1393 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
1394 if (!(*i)->hidden()) {
1395 child->add_child_nocopy ((*i)->get_state());
1400 node->add_child_nocopy (_locations.get_state());
1402 child = node->add_child ("Connections");
1404 Glib::Mutex::Lock lm (connection_lock);
1405 for (ConnectionList::iterator i = _connections.begin(); i != _connections.end(); ++i) {
1406 if (!(*i)->system_dependent()) {
1407 child->add_child_nocopy ((*i)->get_state());
1412 child = node->add_child ("Routes");
1414 boost::shared_ptr<RouteList> r = routes.reader ();
1416 RoutePublicOrderSorter cmp;
1417 RouteList public_order (*r);
1418 public_order.sort (cmp);
1420 for (RouteList::iterator i = public_order.begin(); i != public_order.end(); ++i) {
1421 if (!(*i)->hidden()) {
1423 child->add_child_nocopy ((*i)->get_state());
1425 child->add_child_nocopy ((*i)->get_template());
1432 child = node->add_child ("EditGroups");
1433 for (list<RouteGroup *>::iterator i = edit_groups.begin(); i != edit_groups.end(); ++i) {
1434 child->add_child_nocopy ((*i)->get_state());
1437 child = node->add_child ("MixGroups");
1438 for (list<RouteGroup *>::iterator i = mix_groups.begin(); i != mix_groups.end(); ++i) {
1439 child->add_child_nocopy ((*i)->get_state());
1442 child = node->add_child ("Playlists");
1443 for (PlaylistList::iterator i = playlists.begin(); i != playlists.end(); ++i) {
1444 if (!(*i)->hidden()) {
1445 if (!(*i)->empty()) {
1447 child->add_child_nocopy ((*i)->get_state());
1449 child->add_child_nocopy ((*i)->get_template());
1455 child = node->add_child ("UnusedPlaylists");
1456 for (PlaylistList::iterator i = unused_playlists.begin(); i != unused_playlists.end(); ++i) {
1457 if (!(*i)->hidden()) {
1458 if (!(*i)->empty()) {
1460 child->add_child_nocopy ((*i)->get_state());
1462 child->add_child_nocopy ((*i)->get_template());
1470 child = node->add_child ("Click");
1471 child->add_child_nocopy (_click_io->state (full_state));
1475 child = node->add_child ("NamedSelections");
1476 for (NamedSelectionList::iterator i = named_selections.begin(); i != named_selections.end(); ++i) {
1478 child->add_child_nocopy ((*i)->get_state());
1483 node->add_child_nocopy (_tempo_map->get_state());
1486 node->add_child_copy (*_extra_xml);
1493 Session::set_state (const XMLNode& node)
1497 const XMLProperty* prop;
1500 _state_of_the_state = StateOfTheState (_state_of_the_state|CannotSave);
1502 if (node.name() != X_("Session")){
1503 fatal << _("programming error: Session: incorrect XML node sent to set_state()") << endmsg;
1507 StateManager::prohibit_save ();
1509 if ((prop = node.property ("name")) != 0) {
1510 _name = prop->value ();
1513 if ((prop = node.property (X_("id-counter"))) != 0) {
1515 sscanf (prop->value().c_str(), "%" PRIu64, &x);
1516 ID::init_counter (x);
1518 /* old sessions used a timebased counter, so fake
1519 the startup ID counter based on a standard
1524 ID::init_counter (now);
1528 IO::disable_ports ();
1529 IO::disable_connecting ();
1531 /* Object loading order:
1548 if (use_config_midi_ports ()) {
1551 if ((child = find_named_node (node, "Path")) != 0) {
1552 /* XXX this XML content stuff horrible API design */
1553 string raid_path = _path + ':' + child->children().front()->content();
1554 setup_raid_path (raid_path);
1556 /* the path is already set */
1559 if ((child = find_named_node (node, "extra")) != 0) {
1560 _extra_xml = new XMLNode (*child);
1563 if ((child = find_named_node (node, "Options")) == 0) {
1564 error << _("Session: XML state has no options section") << endmsg;
1565 } else if (load_options (*child)) {
1568 if ((child = find_named_node (node, "Sources")) == 0) {
1569 error << _("Session: XML state has no sources section") << endmsg;
1571 } else if (load_sources (*child)) {
1575 if ((child = find_named_node (node, "Regions")) == 0) {
1576 error << _("Session: XML state has no Regions section") << endmsg;
1578 } else if (load_regions (*child)) {
1582 if ((child = find_named_node (node, "Playlists")) == 0) {
1583 error << _("Session: XML state has no playlists section") << endmsg;
1585 } else if (load_playlists (*child)) {
1589 if ((child = find_named_node (node, "UnusedPlaylists")) == 0) {
1591 } else if (load_unused_playlists (*child)) {
1595 if ((child = find_named_node (node, "NamedSelections")) != 0) {
1596 if (load_named_selections (*child)) {
1601 if ((child = find_named_node (node, "DiskStreams")) == 0) {
1602 error << _("Session: XML state has no diskstreams section") << endmsg;
1604 } else if (load_diskstreams (*child)) {
1608 if ((child = find_named_node (node, "Connections")) == 0) {
1609 error << _("Session: XML state has no connections section") << endmsg;
1611 } else if (load_connections (*child)) {
1615 if ((child = find_named_node (node, "Locations")) == 0) {
1616 error << _("Session: XML state has no locations section") << endmsg;
1618 } else if (_locations.set_state (*child)) {
1624 if ((location = _locations.auto_loop_location()) != 0) {
1625 set_auto_loop_location (location);
1628 if ((location = _locations.auto_punch_location()) != 0) {
1629 set_auto_punch_location (location);
1632 if ((location = _locations.end_location()) == 0) {
1633 _locations.add (end_location);
1635 delete end_location;
1636 end_location = location;
1639 if ((location = _locations.start_location()) == 0) {
1640 _locations.add (start_location);
1642 delete start_location;
1643 start_location = location;
1646 _locations.save_state (_("initial state"));
1648 if ((child = find_named_node (node, "EditGroups")) == 0) {
1649 error << _("Session: XML state has no edit groups section") << endmsg;
1651 } else if (load_edit_groups (*child)) {
1655 if ((child = find_named_node (node, "MixGroups")) == 0) {
1656 error << _("Session: XML state has no mix groups section") << endmsg;
1658 } else if (load_mix_groups (*child)) {
1662 if ((child = find_named_node (node, "TempoMap")) == 0) {
1663 error << _("Session: XML state has no Tempo Map section") << endmsg;
1665 } else if (_tempo_map->set_state (*child)) {
1669 if ((child = find_named_node (node, "Routes")) == 0) {
1670 error << _("Session: XML state has no routes section") << endmsg;
1672 } else if (load_routes (*child)) {
1676 if ((child = find_named_node (node, "Click")) == 0) {
1677 warning << _("Session: XML state has no click section") << endmsg;
1678 } else if (_click_io) {
1679 _click_io->set_state (*child);
1682 /* OK, now we can set edit mode */
1684 set_edit_mode (pending_edit_mode);
1686 /* here beginneth the second phase ... */
1688 StateReady (); /* EMIT SIGNAL */
1690 _state_of_the_state = Clean;
1692 StateManager::allow_save (_("initial state"), true);
1694 if (state_was_pending) {
1695 save_state (_current_snapshot_name);
1696 remove_pending_capture_state ();
1697 state_was_pending = false;
1703 /* we failed, re-enable state saving but don't actually save internal state */
1704 StateManager::allow_save (X_("ignored"), false);
1709 Session::load_routes (const XMLNode& node)
1712 XMLNodeConstIterator niter;
1713 RouteList new_routes;
1715 nlist = node.children();
1719 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1721 boost::shared_ptr<Route> route (XMLRouteFactory (**niter));
1724 error << _("Session: cannot create Route from XML description.") << endmsg;
1728 new_routes.push_back (route);
1731 add_routes (new_routes);
1736 boost::shared_ptr<Route>
1737 Session::XMLRouteFactory (const XMLNode& node)
1739 if (node.name() != "Route") {
1740 return boost::shared_ptr<Route> ((Route*) 0);
1743 if (node.property ("diskstream") != 0 || node.property ("diskstream-id") != 0) {
1744 boost::shared_ptr<Route> x (new AudioTrack (*this, node));
1747 boost::shared_ptr<Route> x (new Route (*this, node));
1753 Session::load_regions (const XMLNode& node)
1756 XMLNodeConstIterator niter;
1757 boost::shared_ptr<AudioRegion> region;
1759 nlist = node.children();
1763 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1764 if ((region = XMLRegionFactory (**niter, false)) == 0) {
1765 error << _("Session: cannot create Region from XML description.") << endmsg;
1772 boost::shared_ptr<AudioRegion>
1773 Session::XMLRegionFactory (const XMLNode& node, bool full)
1775 const XMLProperty* prop;
1776 boost::shared_ptr<Source> source;
1777 boost::shared_ptr<AudioSource> as;
1779 uint32_t nchans = 1;
1782 if (node.name() != X_("Region")) {
1783 return boost::shared_ptr<AudioRegion>();
1786 if ((prop = node.property (X_("channels"))) != 0) {
1787 nchans = atoi (prop->value().c_str());
1791 if ((prop = node.property (X_("source-0"))) == 0) {
1792 if ((prop = node.property ("source")) == 0) {
1793 error << _("Session: XMLNode describing a AudioRegion is incomplete (no source)") << endmsg;
1794 return boost::shared_ptr<AudioRegion>();
1798 PBD::ID s_id (prop->value());
1800 if ((source = source_by_id (s_id)) == 0) {
1801 error << string_compose(_("Session: XMLNode describing a AudioRegion references an unknown source id =%1"), s_id) << endmsg;
1802 return boost::shared_ptr<AudioRegion>();
1805 as = boost::dynamic_pointer_cast<AudioSource>(source);
1807 error << string_compose(_("Session: XMLNode describing a AudioRegion references a non-audio source id =%1"), s_id) << endmsg;
1808 return boost::shared_ptr<AudioRegion>();
1811 sources.push_back (as);
1813 /* pickup other channels */
1815 for (uint32_t n=1; n < nchans; ++n) {
1816 snprintf (buf, sizeof(buf), X_("source-%d"), n);
1817 if ((prop = node.property (buf)) != 0) {
1819 PBD::ID id2 (prop->value());
1821 if ((source = source_by_id (id2)) == 0) {
1822 error << string_compose(_("Session: XMLNode describing a AudioRegion references an unknown source id =%1"), id2) << endmsg;
1823 return boost::shared_ptr<AudioRegion>();
1826 as = boost::dynamic_pointer_cast<AudioSource>(source);
1828 error << string_compose(_("Session: XMLNode describing a AudioRegion references a non-audio source id =%1"), id2) << endmsg;
1829 return boost::shared_ptr<AudioRegion>();
1831 sources.push_back (as);
1836 boost::shared_ptr<AudioRegion> region (boost::dynamic_pointer_cast<AudioRegion> (RegionFactory::create (sources, node)));
1841 catch (failed_constructor& err) {
1842 return boost::shared_ptr<AudioRegion>();
1847 Session::get_sources_as_xml ()
1850 XMLNode* node = new XMLNode (X_("Sources"));
1851 Glib::Mutex::Lock lm (audio_source_lock);
1853 for (AudioSourceList::iterator i = audio_sources.begin(); i != audio_sources.end(); ++i) {
1854 node->add_child_nocopy (i->second->get_state());
1857 /* XXX get MIDI and other sources here */
1863 Session::path_from_region_name (string name, string identifier)
1865 char buf[PATH_MAX+1];
1867 string dir = discover_best_sound_dir ();
1869 for (n = 0; n < 999999; ++n) {
1870 if (identifier.length()) {
1871 snprintf (buf, sizeof(buf), "%s/%s%s%" PRIu32 ".wav", dir.c_str(), name.c_str(),
1872 identifier.c_str(), n);
1874 snprintf (buf, sizeof(buf), "%s/%s-%" PRIu32 ".wav", dir.c_str(), name.c_str(), n);
1876 if (access (buf, F_OK) != 0) {
1886 Session::load_sources (const XMLNode& node)
1889 XMLNodeConstIterator niter;
1890 boost::shared_ptr<Source> source;
1892 nlist = node.children();
1896 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1898 if ((source = XMLSourceFactory (**niter)) == 0) {
1899 error << _("Session: cannot create Source from XML description.") << endmsg;
1906 boost::shared_ptr<Source>
1907 Session::XMLSourceFactory (const XMLNode& node)
1910 if (node.name() != "Source") {
1911 return boost::shared_ptr<Source>();
1915 return SourceFactory::create (node);
1918 catch (failed_constructor& err) {
1919 error << _("Found a sound file that cannot be used by Ardour. Talk to the progammers.") << endmsg;
1920 return boost::shared_ptr<Source>();
1925 Session::save_template (string template_name)
1928 string xml_path, bak_path, template_path;
1930 if (_state_of_the_state & CannotSave) {
1935 string dir = template_dir();
1937 if ((dp = opendir (dir.c_str()))) {
1940 if (mkdir (dir.c_str(), S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH)<0) {
1941 error << string_compose(_("Could not create mix templates directory \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
1946 tree.set_root (&get_template());
1949 xml_path += template_name;
1950 xml_path += _template_suffix;
1952 ifstream in(xml_path.c_str());
1955 warning << string_compose(_("Template \"%1\" already exists - new version not created"), template_name) << endmsg;
1961 if (!tree.write (xml_path)) {
1962 error << _("mix template not saved") << endmsg;
1970 Session::rename_template (string old_name, string new_name)
1972 string old_path = template_dir() + old_name + _template_suffix;
1973 string new_path = template_dir() + new_name + _template_suffix;
1975 return rename (old_path.c_str(), new_path.c_str());
1979 Session::delete_template (string name)
1981 string template_path = template_dir();
1982 template_path += name;
1983 template_path += _template_suffix;
1985 return remove (template_path.c_str());
1989 Session::refresh_disk_space ()
1992 struct statfs statfsbuf;
1993 vector<space_and_path>::iterator i;
1994 Glib::Mutex::Lock lm (space_lock);
1997 /* get freespace on every FS that is part of the session path */
1999 _total_free_4k_blocks = 0;
2001 for (i = session_dirs.begin(); i != session_dirs.end(); ++i) {
2002 statfs ((*i).path.c_str(), &statfsbuf);
2004 scale = statfsbuf.f_bsize/4096.0;
2006 (*i).blocks = (uint32_t) floor (statfsbuf.f_bavail * scale);
2007 _total_free_4k_blocks += (*i).blocks;
2013 Session::ensure_sound_dir (string path, string& result)
2018 /* Ensure that the parent directory exists */
2020 if (mkdir (path.c_str(), 0775)) {
2021 if (errno != EEXIST) {
2022 error << string_compose(_("cannot create session directory \"%1\"; ignored"), path) << endmsg;
2027 /* Ensure that the sounds directory exists */
2031 result += sound_dir_name;
2033 if (mkdir (result.c_str(), 0775)) {
2034 if (errno != EEXIST) {
2035 error << string_compose(_("cannot create sounds directory \"%1\"; ignored"), result) << endmsg;
2042 dead += dead_sound_dir_name;
2044 if (mkdir (dead.c_str(), 0775)) {
2045 if (errno != EEXIST) {
2046 error << string_compose(_("cannot create dead sounds directory \"%1\"; ignored"), dead) << endmsg;
2053 peak += peak_dir_name;
2055 if (mkdir (peak.c_str(), 0775)) {
2056 if (errno != EEXIST) {
2057 error << string_compose(_("cannot create peak file directory \"%1\"; ignored"), peak) << endmsg;
2062 /* callers expect this to be terminated ... */
2069 Session::discover_best_sound_dir (bool destructive)
2071 vector<space_and_path>::iterator i;
2074 /* destructive files all go into the same place */
2080 /* handle common case without system calls */
2082 if (session_dirs.size() == 1) {
2086 /* OK, here's the algorithm we're following here:
2088 We want to select which directory to use for
2089 the next file source to be created. Ideally,
2090 we'd like to use a round-robin process so as to
2091 get maximum performance benefits from splitting
2092 the files across multiple disks.
2094 However, in situations without much diskspace, an
2095 RR approach may end up filling up a filesystem
2096 with new files while others still have space.
2097 Its therefore important to pay some attention to
2098 the freespace in the filesystem holding each
2099 directory as well. However, if we did that by
2100 itself, we'd keep creating new files in the file
2101 system with the most space until it was as full
2102 as all others, thus negating any performance
2103 benefits of this RAID-1 like approach.
2105 So, we use a user-configurable space threshold. If
2106 there are at least 2 filesystems with more than this
2107 much space available, we use RR selection between them.
2108 If not, then we pick the filesystem with the most space.
2110 This gets a good balance between the two
2114 refresh_disk_space ();
2116 int free_enough = 0;
2118 for (i = session_dirs.begin(); i != session_dirs.end(); ++i) {
2119 if ((*i).blocks * 4096 >= Config->get_disk_choice_space_threshold()) {
2124 if (free_enough >= 2) {
2126 bool found_it = false;
2128 /* use RR selection process, ensuring that the one
2132 i = last_rr_session_dir;
2135 if (++i == session_dirs.end()) {
2136 i = session_dirs.begin();
2139 if ((*i).blocks * 4096 >= Config->get_disk_choice_space_threshold()) {
2140 if (ensure_sound_dir ((*i).path, result) == 0) {
2141 last_rr_session_dir = i;
2147 } while (i != last_rr_session_dir);
2150 result = sound_dir();
2155 /* pick FS with the most freespace (and that
2156 seems to actually work ...)
2159 vector<space_and_path> sorted;
2160 space_and_path_ascending_cmp cmp;
2162 sorted = session_dirs;
2163 sort (sorted.begin(), sorted.end(), cmp);
2165 for (i = sorted.begin(); i != sorted.end(); ++i) {
2166 if (ensure_sound_dir ((*i).path, result) == 0) {
2167 last_rr_session_dir = i;
2172 /* if the above fails, fall back to the most simplistic solution */
2174 if (i == sorted.end()) {
2183 Session::load_playlists (const XMLNode& node)
2186 XMLNodeConstIterator niter;
2189 nlist = node.children();
2193 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2195 if ((playlist = XMLPlaylistFactory (**niter)) == 0) {
2196 error << _("Session: cannot create Playlist from XML description.") << endmsg;
2204 Session::load_unused_playlists (const XMLNode& node)
2207 XMLNodeConstIterator niter;
2210 nlist = node.children();
2214 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2216 if ((playlist = XMLPlaylistFactory (**niter)) == 0) {
2217 error << _("Session: cannot create Playlist from XML description.") << endmsg;
2221 // now manually untrack it
2223 track_playlist (playlist, false);
2231 Session::XMLPlaylistFactory (const XMLNode& node)
2234 return new AudioPlaylist (*this, node);
2237 catch (failed_constructor& err) {
2243 Session::load_named_selections (const XMLNode& node)
2246 XMLNodeConstIterator niter;
2249 nlist = node.children();
2253 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2255 if ((ns = XMLNamedSelectionFactory (**niter)) == 0) {
2256 error << _("Session: cannot create Named Selection from XML description.") << endmsg;
2264 Session::XMLNamedSelectionFactory (const XMLNode& node)
2267 return new NamedSelection (*this, node);
2270 catch (failed_constructor& err) {
2276 Session::dead_sound_dir () const
2279 res += dead_sound_dir_name;
2285 Session::sound_dir () const
2288 res += sound_dir_name;
2294 Session::tape_dir () const
2297 res += tape_dir_name;
2303 Session::peak_dir () const
2306 res += peak_dir_name;
2312 Session::automation_dir () const
2315 res += "automation/";
2320 Session::template_dir ()
2322 string path = get_user_ardour_path();
2323 path += "templates/";
2329 Session::suffixed_search_path (string suffix, bool data)
2333 path += get_user_ardour_path();
2334 if (path[path.length()-1] != ':') {
2339 path += get_system_data_path();
2341 path += get_system_module_path();
2344 vector<string> split_path;
2346 split (path, split_path, ':');
2349 for (vector<string>::iterator i = split_path.begin(); i != split_path.end(); ++i) {
2354 if (distance (i, split_path.end()) != 1) {
2363 Session::template_path ()
2365 return suffixed_search_path (X_("templates"), true);
2369 Session::control_protocol_path ()
2371 return suffixed_search_path (X_("surfaces"), false);
2375 Session::load_connections (const XMLNode& node)
2377 XMLNodeList nlist = node.children();
2378 XMLNodeConstIterator niter;
2382 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2383 if ((*niter)->name() == "InputConnection") {
2384 add_connection (new ARDOUR::InputConnection (**niter));
2385 } else if ((*niter)->name() == "OutputConnection") {
2386 add_connection (new ARDOUR::OutputConnection (**niter));
2388 error << string_compose(_("Unknown node \"%1\" found in Connections list from state file"), (*niter)->name()) << endmsg;
2397 Session::load_edit_groups (const XMLNode& node)
2399 return load_route_groups (node, true);
2403 Session::load_mix_groups (const XMLNode& node)
2405 return load_route_groups (node, false);
2409 Session::load_route_groups (const XMLNode& node, bool edit)
2411 XMLNodeList nlist = node.children();
2412 XMLNodeConstIterator niter;
2417 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2418 if ((*niter)->name() == "RouteGroup") {
2420 rg = add_edit_group ("");
2421 rg->set_state (**niter);
2423 rg = add_mix_group ("");
2424 rg->set_state (**niter);
2433 state_file_filter (const string &str, void *arg)
2435 return (str.length() > strlen(Session::statefile_suffix()) &&
2436 str.find (Session::statefile_suffix()) == (str.length() - strlen (Session::statefile_suffix())));
2440 bool operator()(const string* a, const string* b) {
2446 remove_end(string* state)
2448 string statename(*state);
2450 string::size_type start,end;
2451 if ((start = statename.find_last_of ('/')) != string::npos) {
2452 statename = statename.substr (start+1);
2455 if ((end = statename.rfind(".ardour")) == string::npos) {
2456 end = statename.length();
2459 return new string(statename.substr (0, end));
2463 Session::possible_states (string path)
2465 PathScanner scanner;
2466 vector<string*>* states = scanner (path, state_file_filter, 0, false, false);
2468 transform(states->begin(), states->end(), states->begin(), remove_end);
2471 sort (states->begin(), states->end(), cmp);
2477 Session::possible_states () const
2479 return possible_states(_path);
2483 Session::auto_save()
2485 save_state (_current_snapshot_name);
2489 Session::add_edit_group (string name)
2491 RouteGroup* rg = new RouteGroup (*this, name);
2492 edit_groups.push_back (rg);
2493 edit_group_added (rg); /* EMIT SIGNAL */
2499 Session::add_mix_group (string name)
2501 RouteGroup* rg = new RouteGroup (*this, name, RouteGroup::Relative);
2502 mix_groups.push_back (rg);
2503 mix_group_added (rg); /* EMIT SIGNAL */
2509 Session::remove_edit_group (RouteGroup& rg)
2511 list<RouteGroup*>::iterator i;
2513 if ((i = find (edit_groups.begin(), edit_groups.end(), &rg)) != edit_groups.end()) {
2514 (*i)->apply (&Route::drop_edit_group, this);
2515 edit_groups.erase (i);
2516 edit_group_removed (); /* EMIT SIGNAL */
2523 Session::remove_mix_group (RouteGroup& rg)
2525 list<RouteGroup*>::iterator i;
2527 if ((i = find (mix_groups.begin(), mix_groups.end(), &rg)) != mix_groups.end()) {
2528 (*i)->apply (&Route::drop_mix_group, this);
2529 mix_groups.erase (i);
2530 mix_group_removed (); /* EMIT SIGNAL */
2537 Session::mix_group_by_name (string name)
2539 list<RouteGroup *>::iterator i;
2541 for (i = mix_groups.begin(); i != mix_groups.end(); ++i) {
2542 if ((*i)->name() == name) {
2550 Session::edit_group_by_name (string name)
2552 list<RouteGroup *>::iterator i;
2554 for (i = edit_groups.begin(); i != edit_groups.end(); ++i) {
2555 if ((*i)->name() == name) {
2563 Session::set_meter_hold (float val)
2566 MeterHoldChanged(); // emit
2570 Session::set_meter_falloff (float val)
2572 _meter_falloff = val;
2573 MeterFalloffChanged(); // emit
2578 Session::begin_reversible_command (string name)
2580 current_trans = new UndoTransaction;
2581 current_trans->set_name (name);
2585 Session::commit_reversible_command (Command *cmd)
2590 current_trans->add_command (cmd);
2593 gettimeofday (&now, 0);
2594 current_trans->set_timestamp (now);
2596 history.add (current_trans);
2599 Session::GlobalRouteBooleanState
2600 Session::get_global_route_boolean (bool (Route::*method)(void) const)
2602 GlobalRouteBooleanState s;
2603 boost::shared_ptr<RouteList> r = routes.reader ();
2605 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
2606 if (!(*i)->hidden()) {
2607 RouteBooleanState v;
2610 Route* r = (*i).get();
2611 v.second = (r->*method)();
2620 Session::GlobalRouteMeterState
2621 Session::get_global_route_metering ()
2623 GlobalRouteMeterState s;
2624 boost::shared_ptr<RouteList> r = routes.reader ();
2626 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
2627 if (!(*i)->hidden()) {
2631 v.second = (*i)->meter_point();
2641 Session::set_global_route_metering (GlobalRouteMeterState s, void* arg)
2643 for (GlobalRouteMeterState::iterator i = s.begin(); i != s.end(); ++i) {
2644 i->first->set_meter_point (i->second, arg);
2649 Session::set_global_route_boolean (GlobalRouteBooleanState s, void (Route::*method)(bool, void*), void* arg)
2651 for (GlobalRouteBooleanState::iterator i = s.begin(); i != s.end(); ++i) {
2652 Route* r = i->first.get();
2653 (r->*method) (i->second, arg);
2658 Session::set_global_mute (GlobalRouteBooleanState s, void* src)
2660 set_global_route_boolean (s, &Route::set_mute, src);
2664 Session::set_global_solo (GlobalRouteBooleanState s, void* src)
2666 set_global_route_boolean (s, &Route::set_solo, src);
2670 Session::set_global_record_enable (GlobalRouteBooleanState s, void* src)
2672 set_global_route_boolean (s, &Route::set_record_enable, src);
2677 Session::global_mute_memento (void* src)
2679 return sigc::bind (mem_fun (*this, &Session::set_global_mute), get_global_route_boolean (&Route::muted), src);
2683 Session::global_metering_memento (void* src)
2685 return sigc::bind (mem_fun (*this, &Session::set_global_route_metering), get_global_route_metering (), src);
2689 Session::global_solo_memento (void* src)
2691 return sigc::bind (mem_fun (*this, &Session::set_global_solo), get_global_route_boolean (&Route::soloed), src);
2695 Session::global_record_enable_memento (void* src)
2697 return sigc::bind (mem_fun (*this, &Session::set_global_record_enable), get_global_route_boolean (&Route::record_enabled), src);
2702 template_filter (const string &str, void *arg)
2704 return (str.length() > strlen(Session::template_suffix()) &&
2705 str.find (Session::template_suffix()) == (str.length() - strlen (Session::template_suffix())));
2709 Session::get_template_list (list<string> &template_names)
2711 vector<string *> *templates;
2712 PathScanner scanner;
2715 path = template_path ();
2717 templates = scanner (path, template_filter, 0, false, true);
2719 vector<string*>::iterator i;
2720 for (i = templates->begin(); i != templates->end(); ++i) {
2721 string fullpath = *(*i);
2724 start = fullpath.find_last_of ('/') + 1;
2725 if ((end = fullpath.find_last_of ('.')) <0) {
2726 end = fullpath.length();
2729 template_names.push_back(fullpath.substr(start, (end-start)));
2734 Session::read_favorite_dirs (FavoriteDirs & favs)
2736 string path = get_user_ardour_path();
2737 path += "/favorite_dirs";
2739 ifstream fav (path.c_str());
2744 if (errno != ENOENT) {
2745 //error << string_compose (_("cannot open favorite file %1 (%2)"), path, strerror (errno)) << endmsg;
2756 getline(fav, newfav);
2762 favs.push_back (newfav);
2769 Session::write_favorite_dirs (FavoriteDirs & favs)
2771 string path = get_user_ardour_path();
2772 path += "/favorite_dirs";
2774 ofstream fav (path.c_str());
2780 for (FavoriteDirs::iterator i = favs.begin(); i != favs.end(); ++i) {
2781 fav << (*i) << endl;
2788 accept_all_non_peak_files (const string& path, void *arg)
2790 return (path.length() > 5 && path.find (".peak") != (path.length() - 5));
2794 accept_all_state_files (const string& path, void *arg)
2796 return (path.length() > 7 && path.find (".ardour") == (path.length() - 7));
2800 Session::find_all_sources (string path, set<string>& result)
2805 if (!tree.read (path)) {
2809 if ((node = find_named_node (*tree.root(), "Sources")) == 0) {
2814 XMLNodeConstIterator niter;
2816 nlist = node->children();
2820 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2824 if ((prop = (*niter)->property (X_("name"))) == 0) {
2828 if (prop->value()[0] == '/') {
2829 /* external file, ignore */
2833 string path = _path; /* /-terminated */
2834 path += sound_dir_name;
2836 path += prop->value();
2838 result.insert (path);
2845 Session::find_all_sources_across_snapshots (set<string>& result, bool exclude_this_snapshot)
2847 PathScanner scanner;
2848 vector<string*>* state_files;
2850 string this_snapshot_path;
2856 if (ripped[ripped.length()-1] == '/') {
2857 ripped = ripped.substr (0, ripped.length() - 1);
2860 state_files = scanner (ripped, accept_all_state_files, (void *) 0, false, true);
2862 if (state_files == 0) {
2867 this_snapshot_path = _path;
2868 this_snapshot_path += _current_snapshot_name;
2869 this_snapshot_path += _statefile_suffix;
2871 for (vector<string*>::iterator i = state_files->begin(); i != state_files->end(); ++i) {
2873 if (exclude_this_snapshot && **i == this_snapshot_path) {
2877 if (find_all_sources (**i, result) < 0) {
2886 Session::cleanup_sources (Session::cleanup_report& rep)
2888 vector<boost::shared_ptr<Source> > dead_sources;
2889 vector<Playlist*> playlists_tbd;
2890 PathScanner scanner;
2892 vector<space_and_path>::iterator i;
2893 vector<space_and_path>::iterator nexti;
2894 vector<string*>* soundfiles;
2895 vector<string> unused;
2896 set<string> all_sources;
2901 _state_of_the_state = (StateOfTheState) (_state_of_the_state | InCleanup);
2903 /* step 1: consider deleting all unused playlists */
2905 for (PlaylistList::iterator x = unused_playlists.begin(); x != unused_playlists.end(); ++x) {
2908 status = AskAboutPlaylistDeletion (*x);
2917 playlists_tbd.push_back (*x);
2921 /* leave it alone */
2926 /* now delete any that were marked for deletion */
2928 for (vector<Playlist*>::iterator x = playlists_tbd.begin(); x != playlists_tbd.end(); ++x) {
2929 PlaylistList::iterator foo;
2931 if ((foo = unused_playlists.find (*x)) != unused_playlists.end()) {
2932 unused_playlists.erase (foo);
2937 /* step 2: clear the undo/redo history for all playlists */
2939 for (PlaylistList::iterator x = playlists.begin(); x != playlists.end(); ++x) {
2940 (*x)->drop_all_states ();
2943 /* step 3: find all un-referenced sources */
2948 for (AudioSourceList::iterator i = audio_sources.begin(); i != audio_sources.end(); ) {
2950 AudioSourceList::iterator tmp;
2955 /* only remove files that are not in use and have some size
2956 to them. otherwise we remove the current "nascent"
2960 if (i->second.use_count() == 1 && i->second->length() > 0) {
2961 dead_sources.push_back (i->second);
2963 /* remove this source from our own list to avoid us
2964 adding it to the list of all sources below
2967 audio_sources.erase (i);
2973 /* Step 4: get rid of all regions in the region list that use any dead sources
2974 in case the sources themselves don't go away (they might be referenced in
2978 for (vector<boost::shared_ptr<Source> >::iterator i = dead_sources.begin(); i != dead_sources.end();++i) {
2980 for (AudioRegionList::iterator r = audio_regions.begin(); r != audio_regions.end(); ) {
2981 AudioRegionList::iterator tmp;
2982 boost::shared_ptr<AudioRegion> ar;
2989 for (uint32_t n = 0; n < ar->n_channels(); ++n) {
2990 if (ar->source (n) == (*i)) {
2991 /* this region is dead */
3000 /* build a list of all the possible sound directories for the session */
3002 for (i = session_dirs.begin(); i != session_dirs.end(); ) {
3007 sound_path += (*i).path;
3008 sound_path += sound_dir_name;
3010 if (nexti != session_dirs.end()) {
3017 /* now do the same thing for the files that ended up in the sounds dir(s)
3018 but are not referenced as sources in any snapshot.
3021 soundfiles = scanner (sound_path, accept_all_non_peak_files, (void *) 0, false, true);
3023 if (soundfiles == 0) {
3027 /* find all sources, but don't use this snapshot because the
3028 state file on disk still references sources we may have already
3032 find_all_sources_across_snapshots (all_sources, true);
3034 /* add our current source list
3037 for (AudioSourceList::iterator i = audio_sources.begin(); i != audio_sources.end(); ++i) {
3038 boost::shared_ptr<AudioFileSource> fs;
3040 if ((fs = boost::dynamic_pointer_cast<AudioFileSource> (i->second)) != 0) {
3041 all_sources.insert (fs->path());
3045 for (vector<string*>::iterator x = soundfiles->begin(); x != soundfiles->end(); ++x) {
3050 for (set<string>::iterator i = all_sources.begin(); i != all_sources.end(); ++i) {
3060 unused.push_back (spath);
3064 /* now try to move all unused files into the "dead_sounds" directory(ies) */
3066 for (vector<string>::iterator x = unused.begin(); x != unused.end(); ++x) {
3067 struct stat statbuf;
3069 rep.paths.push_back (*x);
3070 if (stat ((*x).c_str(), &statbuf) == 0) {
3071 rep.space += statbuf.st_size;
3076 /* don't move the file across filesystems, just
3077 stick it in the `dead_sound_dir_name' directory
3078 on whichever filesystem it was already on.
3081 newpath = Glib::path_get_dirname (*x);
3082 newpath = Glib::path_get_dirname (newpath);
3085 newpath += dead_sound_dir_name;
3087 newpath += Glib::path_get_basename ((*x));
3089 if (access (newpath.c_str(), F_OK) == 0) {
3091 /* the new path already exists, try versioning */
3093 char buf[PATH_MAX+1];
3097 snprintf (buf, sizeof (buf), "%s.%d", newpath.c_str(), version);
3100 while (access (newpath_v.c_str(), F_OK) == 0 && version < 999) {
3101 snprintf (buf, sizeof (buf), "%s.%d", newpath.c_str(), ++version);
3105 if (version == 999) {
3106 error << string_compose (_("there are already 1000 files with names like %1; versioning discontinued"),
3110 newpath = newpath_v;
3115 /* it doesn't exist, or we can't read it or something */
3119 if (::rename ((*x).c_str(), newpath.c_str()) != 0) {
3120 error << string_compose (_("cannot rename audio file source from %1 to %2 (%3)"),
3121 (*x), newpath, strerror (errno))
3127 /* see if there an easy to find peakfile for this file, and remove it.
3130 string peakpath = (*x).substr (0, (*x).find_last_of ('.'));
3131 peakpath += ".peak";
3133 if (access (peakpath.c_str(), W_OK) == 0) {
3134 if (::unlink (peakpath.c_str()) != 0) {
3135 error << string_compose (_("cannot remove peakfile %1 for %2 (%3)"),
3136 peakpath, _path, strerror (errno))
3138 /* try to back out */
3139 rename (newpath.c_str(), _path.c_str());
3148 /* dump the history list */
3152 /* save state so we don't end up a session file
3153 referring to non-existent sources.
3159 _state_of_the_state = (StateOfTheState) (_state_of_the_state & ~InCleanup);
3164 Session::cleanup_trash_sources (Session::cleanup_report& rep)
3166 vector<space_and_path>::iterator i;
3167 string dead_sound_dir;
3168 struct dirent* dentry;
3169 struct stat statbuf;
3175 for (i = session_dirs.begin(); i != session_dirs.end(); ++i) {
3177 dead_sound_dir = (*i).path;
3178 dead_sound_dir += dead_sound_dir_name;
3180 if ((dead = opendir (dead_sound_dir.c_str())) == 0) {
3184 while ((dentry = readdir (dead)) != 0) {
3186 /* avoid '.' and '..' */
3188 if ((dentry->d_name[0] == '.' && dentry->d_name[1] == '\0') ||
3189 (dentry->d_name[2] == '\0' && dentry->d_name[0] == '.' && dentry->d_name[1] == '.')) {
3195 fullpath = dead_sound_dir;
3197 fullpath += dentry->d_name;
3199 if (stat (fullpath.c_str(), &statbuf)) {
3203 if (!S_ISREG (statbuf.st_mode)) {
3207 if (unlink (fullpath.c_str())) {
3208 error << string_compose (_("cannot remove dead sound file %1 (%2)"),
3209 fullpath, strerror (errno))
3213 rep.paths.push_back (dentry->d_name);
3214 rep.space += statbuf.st_size;
3225 Session::set_dirty ()
3227 bool was_dirty = dirty();
3229 _state_of_the_state = StateOfTheState (_state_of_the_state | Dirty);
3232 DirtyChanged(); /* EMIT SIGNAL */
3238 Session::set_clean ()
3240 bool was_dirty = dirty();
3242 _state_of_the_state = Clean;
3245 DirtyChanged(); /* EMIT SIGNAL */
3250 Session::add_controllable (Controllable* c)
3252 Glib::Mutex::Lock lm (controllables_lock);
3253 controllables.push_back (c);
3257 Session::remove_controllable (Controllable* c)
3259 if (_state_of_the_state | Deletion) {
3263 Glib::Mutex::Lock lm (controllables_lock);
3264 controllables.remove (c);
3268 Session::controllable_by_id (const PBD::ID& id)
3270 Glib::Mutex::Lock lm (controllables_lock);
3272 for (Controllables::iterator i = controllables.begin(); i != controllables.end(); ++i) {
3273 if ((*i)->id() == id) {
3282 Session::add_instant_xml (XMLNode& node, const std::string& dir)
3284 Stateful::add_instant_xml (node, dir);
3285 Config->add_instant_xml (node, get_user_ardour_path());
3290 Session::save_history (string snapshot_name)
3297 tree.set_root (&history.get_state());
3299 if (snapshot_name.empty()) {
3300 snapshot_name = _current_snapshot_name;
3303 xml_path = _path + snapshot_name + ".history";
3304 cerr << "Saving history to " << xml_path << endmsg;
3306 bak_path = xml_path + ".bak";
3308 if ((access (xml_path.c_str(), F_OK) == 0) &&
3309 (rename (xml_path.c_str(), bak_path.c_str())))
3311 error << _("could not backup old history file, current history not saved.") << endmsg;
3315 if (!tree.write (xml_path))
3317 error << string_compose (_("history could not be saved to %1"), xml_path) << endmsg;
3319 /* don't leave a corrupt file lying around if it is
3323 if (unlink (xml_path.c_str()))
3325 error << string_compose (_("could not remove corrupt history file %1"), xml_path) << endmsg;
3327 if (rename (bak_path.c_str(), xml_path.c_str()))
3329 error << string_compose (_("could not restore history file from backup %1"), bak_path) << endmsg;
3340 Session::restore_history (string snapshot_name)
3346 xmlpath = _path + snapshot_name + ".history";
3347 cerr << string_compose(_("Loading history from '%1'."), xmlpath) << endmsg;
3349 if (access (xmlpath.c_str(), F_OK)) {
3350 error << string_compose(_("%1: session history file \"%2\" doesn't exist!"), _name, xmlpath) << endmsg;
3354 if (!tree.read (xmlpath)) {
3355 error << string_compose(_("Could not understand ardour file %1"), xmlpath) << endmsg;
3359 /* replace history */
3361 for (XMLNodeConstIterator it = tree.root()->children().begin();
3362 it != tree.root()->children().end();
3366 UndoTransaction* ut = new UndoTransaction ();
3369 ut->set_name(t->property("name")->value());
3370 stringstream ss(t->property("tv_sec")->value());
3372 ss.str(t->property("tv_usec")->value());
3374 ut->set_timestamp(tv);
3376 for (XMLNodeConstIterator child_it = t->children().begin();
3377 child_it != t->children().end();
3380 XMLNode *n = *child_it;
3382 if (n->name() == "MementoCommand" ||
3383 n->name() == "MementoUndoCommand" ||
3384 n->name() == "MementoRedoCommand")
3386 c = memento_command_factory(n);
3392 error << string_compose(_("Couldn't figure out how to make a Command out of a %1 XMLNode."), n->name()) << endmsg;