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;
225 if (Config->get_use_video_sync()) {
226 waiting_for_sync_offset = true;
228 waiting_for_sync_offset = false;
231 _current_frame_rate = 48000;
232 _base_frame_rate = 48000;
234 smpte_frames_per_second = 30;
236 smpte_drop_frames = false;
239 _smpte_offset_negative = true;
240 last_smpte_valid = false;
242 last_rr_session_dir = session_dirs.begin();
243 refresh_disk_space ();
245 // set_default_fade (0.2, 5.0); /* steepness, millisecs */
247 /* default configuration */
249 do_not_record_plugins = false;
250 over_length_short = 2;
251 over_length_long = 10;
252 send_midi_timecode = false;
253 send_midi_machine_control = false;
254 shuttle_speed_factor = 1.0;
255 shuttle_speed_threshold = 5;
257 _meter_hold = 100; // XXX unknown units: number of calls to meter::set()
258 _meter_falloff = 0.375f; // XXX unknown units: refresh_rate
264 average_slave_delta = 1800;
265 have_first_delta_accumulator = false;
266 delta_accumulator_cnt = 0;
267 slave_state = Stopped;
269 /* default SMPTE type is 30 FPS, non-drop */
271 set_smpte_type (30.0, false);
272 set_video_pullup (0.0);
274 _engine.GraphReordered.connect (mem_fun (*this, &Session::graph_reordered));
276 /* These are all static "per-class" signals */
278 RegionFactory::CheckNewRegion.connect (mem_fun (*this, &Session::add_region));
279 SourceFactory::SourceCreated.connect (mem_fun (*this, &Session::add_source));
280 Playlist::PlaylistCreated.connect (mem_fun (*this, &Session::add_playlist));
281 Redirect::RedirectCreated.connect (mem_fun (*this, &Session::add_redirect));
282 NamedSelection::NamedSelectionCreated.connect (mem_fun (*this, &Session::add_named_selection));
283 Curve::CurveCreated.connect (mem_fun (*this, &Session::add_curve));
284 AutomationList::AutomationListCreated.connect (mem_fun (*this, &Session::add_automation_list));
286 Controllable::Created.connect (mem_fun (*this, &Session::add_controllable));
287 Controllable::GoingAway.connect (mem_fun (*this, &Session::remove_controllable));
289 IO::MoreOutputs.connect (mem_fun (*this, &Session::ensure_passthru_buffers));
291 /* stop IO objects from doing stuff until we're ready for them */
293 IO::disable_panners ();
294 IO::disable_ports ();
295 IO::disable_connecting ();
299 Session::second_stage_init (bool new_session)
301 AudioFileSource::set_peak_dir (peak_dir());
304 if (load_state (_current_snapshot_name)) {
305 cerr << "load state failed\n";
308 remove_empty_sounds ();
311 if (start_butler_thread()) {
315 if (start_midi_thread ()) {
320 if (set_state (*state_tree->root())) {
325 /* we can't save till after ::when_engine_running() is called,
326 because otherwise we save state with no connections made.
327 therefore, we reset _state_of_the_state because ::set_state()
328 will have cleared it.
330 we also have to include Loading so that any events that get
331 generated between here and the end of ::when_engine_running()
332 will be processed directly rather than queued.
335 _state_of_the_state = StateOfTheState (_state_of_the_state|CannotSave|Loading);
337 // set_auto_input (true);
338 _locations.changed.connect (mem_fun (this, &Session::locations_changed));
339 _locations.added.connect (mem_fun (this, &Session::locations_added));
340 setup_click_sounds (0);
341 setup_midi_control ();
343 /* Pay attention ... */
345 _engine.Halted.connect (mem_fun (*this, &Session::engine_halted));
346 _engine.Xrun.connect (mem_fun (*this, &Session::xrun_recovery));
348 if (_engine.running()) {
349 when_engine_running();
351 first_time_running = _engine.Running.connect (mem_fun (*this, &Session::when_engine_running));
354 send_full_time_code ();
355 _engine.transport_locate (0);
356 deliver_mmc (MIDI::MachineControl::cmdMmcReset, 0);
357 deliver_mmc (MIDI::MachineControl::cmdLocate, 0);
359 ControlProtocolManager::instance().set_session (*this);
362 _end_location_is_free = true;
364 _end_location_is_free = false;
371 Session::raid_path () const
375 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
380 return path.substr (0, path.length() - 1); // drop final colon
384 Session::set_raid_path (string path)
386 /* public-access to setup_raid_path() */
388 setup_raid_path (path);
392 Session::setup_raid_path (string path)
394 string::size_type colon;
398 string::size_type len = path.length();
403 if (path.length() == 0) {
407 session_dirs.clear ();
409 for (string::size_type n = 0; n < len; ++n) {
410 if (path[n] == ':') {
417 /* no multiple search path, just one location (common case) */
421 session_dirs.push_back (sp);
428 if (fspath[fspath.length()-1] != '/') {
431 fspath += sound_dir (false);
433 AudioFileSource::set_search_path (fspath);
440 while ((colon = remaining.find_first_of (':')) != string::npos) {
443 sp.path = remaining.substr (0, colon);
444 session_dirs.push_back (sp);
446 /* add sounds to file search path */
449 if (fspath[fspath.length()-1] != '/') {
452 fspath += sound_dir (false);
455 remaining = remaining.substr (colon+1);
458 if (remaining.length()) {
465 if (fspath[fspath.length()-1] != '/') {
468 fspath += sound_dir (false);
471 session_dirs.push_back (sp);
474 /* set the AudioFileSource search path */
476 AudioFileSource::set_search_path (fspath);
478 /* reset the round-robin soundfile path thingie */
480 last_rr_session_dir = session_dirs.begin();
484 Session::create (bool& new_session, string* mix_template, jack_nframes_t initial_length)
488 new_session = !g_file_test (_path.c_str(), GFileTest (G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR));
490 if (g_mkdir_with_parents (_path.c_str(), 0755) < 0) {
491 error << string_compose(_("Session: cannot create session dir \"%1\" (%2)"), _path, strerror (errno)) << endmsg;
497 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
498 error << string_compose(_("Session: cannot create session peakfile dir \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
504 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
505 error << string_compose(_("Session: cannot create session sounds dir \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
509 dir = dead_sound_dir ();
511 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
512 error << string_compose(_("Session: cannot create session dead sounds dir \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
516 dir = automation_dir ();
518 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
519 error << string_compose(_("Session: cannot create session automation dir \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
524 /* check new_session so we don't overwrite an existing one */
528 std::string in_path = *mix_template;
530 ifstream in(in_path.c_str());
533 string out_path = _path;
535 out_path += _statefile_suffix;
537 ofstream out(out_path.c_str());
542 // okay, session is set up. Treat like normal saved
543 // session from now on.
549 error << string_compose (_("Could not open %1 for writing mix template"), out_path)
555 error << string_compose (_("Could not open mix template %1 for reading"), in_path)
562 warning << _("Session already exists. Not overwriting") << endmsg;
569 /* set initial start + end point */
571 start_location->set_end (0);
572 _locations.add (start_location);
574 end_location->set_end (initial_length);
575 _locations.add (end_location);
577 _state_of_the_state = Clean;
579 if (save_state (_current_snapshot_name)) {
580 save_history (_current_snapshot_name);
589 Session::load_diskstreams (const XMLNode& node)
592 XMLNodeConstIterator citer;
594 clist = node.children();
596 for (citer = clist.begin(); citer != clist.end(); ++citer) {
600 boost::shared_ptr<AudioDiskstream> dstream (new AudioDiskstream (*this, **citer));
601 add_diskstream (dstream);
604 catch (failed_constructor& err) {
605 error << _("Session: could not load diskstream via XML state") << endmsg;
614 Session::remove_pending_capture_state ()
619 xml_path += _current_snapshot_name;
620 xml_path += _pending_suffix;
622 unlink (xml_path.c_str());
626 Session::save_state (string snapshot_name, bool pending)
632 if (_state_of_the_state & CannotSave) {
636 tree.set_root (&get_state());
638 if (snapshot_name.empty()) {
639 snapshot_name = _current_snapshot_name;
645 xml_path += snapshot_name;
646 xml_path += _statefile_suffix;
650 // Make backup of state file
652 if ((access (xml_path.c_str(), F_OK) == 0) &&
653 (rename(xml_path.c_str(), bak_path.c_str()))) {
654 error << _("could not backup old state file, current state not saved.") << endmsg;
661 xml_path += snapshot_name;
662 xml_path += _pending_suffix;
666 cerr << "actually writing state\n";
668 if (!tree.write (xml_path)) {
669 error << string_compose (_("state could not be saved to %1"), xml_path) << endmsg;
671 /* don't leave a corrupt file lying around if it is
675 if (unlink (xml_path.c_str())) {
676 error << string_compose (_("could not remove corrupt state file %1"), xml_path) << endmsg;
679 if (rename (bak_path.c_str(), xml_path.c_str())) {
680 error << string_compose (_("could not restore state file from backup %1"), bak_path) << endmsg;
689 save_history(snapshot_name);
691 bool was_dirty = dirty();
693 _state_of_the_state = StateOfTheState (_state_of_the_state & ~Dirty);
696 DirtyChanged (); /* EMIT SIGNAL */
699 StateSaved (snapshot_name); /* EMIT SIGNAL */
706 Session::restore_state (string snapshot_name)
708 if (load_state (snapshot_name) == 0) {
709 set_state (*state_tree->root());
716 Session::load_state (string snapshot_name)
725 state_was_pending = false;
727 /* check for leftover pending state from a crashed capture attempt */
730 xmlpath += snapshot_name;
731 xmlpath += _pending_suffix;
733 if (!access (xmlpath.c_str(), F_OK)) {
735 /* there is pending state from a crashed capture attempt */
737 if (AskAboutPendingState()) {
738 state_was_pending = true;
742 if (!state_was_pending) {
745 xmlpath += snapshot_name;
746 xmlpath += _statefile_suffix;
749 if (access (xmlpath.c_str(), F_OK)) {
750 error << string_compose(_("%1: session state information file \"%2\" doesn't exist!"), _name, xmlpath) << endmsg;
754 state_tree = new XMLTree;
758 if (state_tree->read (xmlpath)) {
761 error << string_compose(_("Could not understand ardour file %1"), xmlpath) << endmsg;
770 Session::load_options (const XMLNode& node)
774 bool have_fade_msecs = false;
775 bool have_fade_steepness = false;
776 float fade_msecs = 0;
777 float fade_steepness = 0;
778 SlaveSource slave_src = None;
780 LocaleGuard lg (X_("POSIX"));
782 if ((child = find_named_node (node, "input-auto-connect")) != 0) {
783 if ((prop = child->property ("val")) != 0) {
784 sscanf (prop->value().c_str(), "%x", &x);
785 input_auto_connect = AutoConnectOption (x);
789 if ((child = find_named_node (node, "output-auto-connect")) != 0) {
790 if ((prop = child->property ("val")) != 0) {
791 sscanf (prop->value().c_str(), "%x", &x);
792 output_auto_connect = AutoConnectOption (x);
796 if ((child = find_named_node (node, "slave")) != 0) {
797 if ((prop = child->property ("type")) != 0) {
798 if (prop->value() == "none") {
800 } else if (prop->value() == "mtc") {
802 } else if (prop->value() == "jack") {
805 set_slave_source (slave_src, 0);
809 /* we cannot set edit mode if we are loading a session,
810 because it might destroy the playlist's positioning
813 if ((child = find_named_node (node, "edit-mode")) != 0) {
814 if ((prop = child->property ("val")) != 0) {
815 if (prop->value() == "slide") {
816 pending_edit_mode = Slide;
817 } else if (prop->value() == "splice") {
818 pending_edit_mode = Splice;
823 if ((child = find_named_node (node, "send-midi-timecode")) != 0) {
824 if ((prop = child->property ("val")) != 0) {
825 bool x = (prop->value() == "yes");
826 send_mtc = !x; /* force change in value */
830 if ((child = find_named_node (node, "send-midi-machine-control")) != 0) {
831 if ((prop = child->property ("val")) != 0) {
832 bool x = (prop->value() == "yes");
833 send_mmc = !x; /* force change in value */
834 set_send_mmc (prop->value() == "yes");
837 if ((child = find_named_node (node, "max-level")) != 0) {
838 if ((prop = child->property ("val")) != 0) {
839 max_level = atoi (prop->value().c_str());
842 if ((child = find_named_node (node, "min-level")) != 0) {
843 if ((prop = child->property ("val")) != 0) {
844 min_level = atoi (prop->value().c_str());
847 if ((child = find_named_node (node, "meter-hold")) != 0) {
848 if ((prop = child->property ("val")) != 0) {
849 _meter_hold = atof (prop->value().c_str());
852 if ((child = find_named_node (node, "meter-falloff")) != 0) {
853 if ((prop = child->property ("val")) != 0) {
854 _meter_falloff = atof (prop->value().c_str());
857 if ((child = find_named_node (node, "long-over-length")) != 0) {
858 if ((prop = child->property ("val")) != 0) {
859 over_length_long = atoi (prop->value().c_str());
862 if ((child = find_named_node (node, "short-over-length")) != 0) {
863 if ((prop = child->property ("val")) != 0) {
864 over_length_short = atoi (prop->value().c_str());
867 if ((child = find_named_node (node, "shuttle-speed-factor")) != 0) {
868 if ((prop = child->property ("val")) != 0) {
869 shuttle_speed_factor = atof (prop->value().c_str());
872 if ((child = find_named_node (node, "shuttle-speed-threshold")) != 0) {
873 if ((prop = child->property ("val")) != 0) {
874 shuttle_speed_threshold = atof (prop->value().c_str());
877 if ((child = find_named_node (node, "rf-speed")) != 0) {
878 if ((prop = child->property ("val")) != 0) {
879 rf_speed = atof (prop->value().c_str());
882 if ((child = find_named_node (node, "video-pullup")) != 0) {
883 if ((prop = child->property ("val")) != 0) {
884 set_video_pullup( atof (prop->value().c_str()) );
887 if ((child = find_named_node (node, "smpte-frames-per-second")) != 0) {
888 if ((prop = child->property ("val")) != 0) {
889 set_smpte_type( atof (prop->value().c_str()), smpte_drop_frames );
892 if ((child = find_named_node (node, "smpte-drop-frames")) != 0) {
893 if ((prop = child->property ("val")) != 0) {
894 set_smpte_type( smpte_frames_per_second, (prop->value() == "yes") );
897 if ((child = find_named_node (node, "smpte-offset")) != 0) {
898 if ((prop = child->property ("val")) != 0) {
899 set_smpte_offset( atoi (prop->value().c_str()) );
902 if ((child = find_named_node (node, "smpte-offset-negative")) != 0) {
903 if ((prop = child->property ("val")) != 0) {
904 set_smpte_offset_negative( (prop->value() == "yes") );
907 if ((child = find_named_node (node, "click-sound")) != 0) {
908 if ((prop = child->property ("val")) != 0) {
909 click_sound = prop->value();
912 if ((child = find_named_node (node, "click-emphasis-sound")) != 0) {
913 if ((prop = child->property ("val")) != 0) {
914 click_emphasis_sound = prop->value();
918 if ((child = find_named_node (node, "solo-model")) != 0) {
919 if ((prop = child->property ("val")) != 0) {
920 if (prop->value() == "SoloBus")
921 _solo_model = SoloBus;
923 _solo_model = InverseMute;
927 /* BOOLEAN OPTIONS */
929 if ((child = find_named_node (node, "auto-play")) != 0) {
930 if ((prop = child->property ("val")) != 0) {
931 set_auto_play (prop->value() == "yes");
934 if ((child = find_named_node (node, "auto-input")) != 0) {
935 if ((prop = child->property ("val")) != 0) {
936 set_auto_input (prop->value() == "yes");
939 if ((child = find_named_node (node, "seamless-loop")) != 0) {
940 if ((prop = child->property ("val")) != 0) {
941 set_seamless_loop (prop->value() == "yes");
944 if ((child = find_named_node (node, "punch-in")) != 0) {
945 if ((prop = child->property ("val")) != 0) {
946 set_punch_in (prop->value() == "yes");
949 if ((child = find_named_node (node, "punch-out")) != 0) {
950 if ((prop = child->property ("val")) != 0) {
951 set_punch_out (prop->value() == "yes");
954 if ((child = find_named_node (node, "auto-return")) != 0) {
955 if ((prop = child->property ("val")) != 0) {
956 set_auto_return (prop->value() == "yes");
959 if ((child = find_named_node (node, "send-mtc")) != 0) {
960 if ((prop = child->property ("val")) != 0) {
961 set_send_mtc (prop->value() == "yes");
964 if ((child = find_named_node (node, "mmc-control")) != 0) {
965 if ((prop = child->property ("val")) != 0) {
966 set_mmc_control (prop->value() == "yes");
969 if ((child = find_named_node (node, "midi-control")) != 0) {
970 if ((prop = child->property ("val")) != 0) {
971 set_midi_control (prop->value() == "yes");
974 if ((child = find_named_node (node, "midi-feedback")) != 0) {
975 if ((prop = child->property ("val")) != 0) {
976 set_midi_feedback (prop->value() == "yes");
979 // Legacy support for <recording-plugins>
980 if ((child = find_named_node (node, "recording-plugins")) != 0) {
981 if ((prop = child->property ("val")) != 0) {
982 set_do_not_record_plugins (prop->value() == "no");
985 if ((child = find_named_node (node, "do-not-record-plugins")) != 0) {
986 if ((prop = child->property ("val")) != 0) {
987 set_do_not_record_plugins (prop->value() == "yes");
990 if ((child = find_named_node (node, "crossfades-active")) != 0) {
991 if ((prop = child->property ("val")) != 0) {
992 set_crossfades_active (prop->value() == "yes");
995 if ((child = find_named_node (node, "audible-click")) != 0) {
996 if ((prop = child->property ("val")) != 0) {
997 set_clicking (prop->value() == "yes");
1001 if ((child = find_named_node (node, "end-marker-is-free")) != 0) {
1002 if ((prop = child->property ("val")) != 0) {
1003 _end_location_is_free = (prop->value() == "yes");
1007 if ((child = find_named_node (node, "layer-model")) != 0) {
1008 if ((prop = child->property ("val")) != 0) {
1009 if (prop->value() == X_("LaterHigher")) {
1010 set_layer_model (LaterHigher);
1011 } else if (prop->value() == X_("AddHigher")) {
1012 set_layer_model (AddHigher);
1014 set_layer_model (MoveAddHigher);
1019 if ((child = find_named_node (node, "xfade-model")) != 0) {
1020 if ((prop = child->property ("val")) != 0) {
1021 if (prop->value() == X_("Short")) {
1022 set_xfade_model (ShortCrossfade);
1024 set_xfade_model (FullCrossfade);
1029 if ((child = find_named_node (node, "short-xfade-length")) != 0) {
1030 if ((prop = child->property ("val")) != 0) {
1031 /* value is stored as a fractional seconds */
1032 float secs = atof (prop->value().c_str());
1033 Crossfade::set_short_xfade_length ((jack_nframes_t) floor (secs * frame_rate()));
1037 if ((child = find_named_node (node, "full-xfades-unmuted")) != 0) {
1038 if ((prop = child->property ("val")) != 0) {
1039 crossfades_active = (prop->value() == "yes");
1045 if ((child = find_named_node (node, "default-fade-steepness")) != 0) {
1046 if ((prop = child->property ("val")) != 0) {
1047 fade_steepness = atof (prop->value().c_str());
1048 have_fade_steepness = true;
1051 if ((child = find_named_node (node, "default-fade-msec")) != 0) {
1052 if ((prop = child->property ("val")) != 0) {
1053 fade_msecs = atof (prop->value().c_str());
1054 have_fade_msecs = true;
1058 if (have_fade_steepness || have_fade_msecs) {
1059 // set_default_fade (fade_steepness, fade_msecs);
1066 Session::get_options () const
1071 LocaleGuard lg (X_("POSIX"));
1073 opthead = new XMLNode ("Options");
1075 SlaveSource src = slave_source ();
1079 src_string = "none";
1085 src_string = "jack";
1088 child = opthead->add_child ("slave");
1089 child->add_property ("type", src_string);
1091 child = opthead->add_child ("send-midi-timecode");
1092 child->add_property ("val", send_midi_timecode?"yes":"no");
1094 child = opthead->add_child ("send-midi-machine-control");
1095 child->add_property ("val", send_midi_machine_control?"yes":"no");
1097 snprintf (buf, sizeof(buf)-1, "%x", (int) input_auto_connect);
1098 child = opthead->add_child ("input-auto-connect");
1099 child->add_property ("val", buf);
1101 snprintf (buf, sizeof(buf)-1, "%x", (int) output_auto_connect);
1102 child = opthead->add_child ("output-auto-connect");
1103 child->add_property ("val", buf);
1105 snprintf (buf, sizeof(buf)-1, "%d", max_level);
1106 child = opthead->add_child ("max-level");
1107 child->add_property ("val", buf);
1109 snprintf (buf, sizeof(buf)-1, "%d", min_level);
1110 child = opthead->add_child ("min-level");
1111 child->add_property ("val", buf);
1113 snprintf (buf, sizeof(buf)-1, "%f", _meter_hold);
1114 child = opthead->add_child ("meter-hold");
1115 child->add_property ("val", buf);
1117 snprintf (buf, sizeof(buf)-1, "%f", _meter_falloff);
1118 child = opthead->add_child ("meter-falloff");
1119 child->add_property ("val", buf);
1121 snprintf (buf, sizeof(buf)-1, "%u", over_length_long);
1122 child = opthead->add_child ("long-over-length");
1123 child->add_property ("val", buf);
1125 snprintf (buf, sizeof(buf)-1, "%u", over_length_short);
1126 child = opthead->add_child ("short-over-length");
1127 child->add_property ("val", buf);
1129 snprintf (buf, sizeof(buf)-1, "%f", shuttle_speed_factor);
1130 child = opthead->add_child ("shuttle-speed-factor");
1131 child->add_property ("val", buf);
1133 snprintf (buf, sizeof(buf)-1, "%f", shuttle_speed_threshold);
1134 child = opthead->add_child ("shuttle-speed-threshold");
1135 child->add_property ("val", buf);
1137 snprintf (buf, sizeof(buf)-1, "%f", rf_speed);
1138 child = opthead->add_child ("rf-speed");
1139 child->add_property ("val", buf);
1141 snprintf (buf, sizeof(buf)-1, "%.4f", video_pullup);
1142 child = opthead->add_child ("video-pullup");
1143 child->add_property ("val", buf);
1145 snprintf (buf, sizeof(buf)-1, "%.2f", smpte_frames_per_second);
1146 child = opthead->add_child ("smpte-frames-per-second");
1147 child->add_property ("val", buf);
1149 child = opthead->add_child ("smpte-drop-frames");
1150 child->add_property ("val", smpte_drop_frames ? "yes" : "no");
1152 snprintf (buf, sizeof(buf)-1, "%u", smpte_offset ());
1153 child = opthead->add_child ("smpte-offset");
1154 child->add_property ("val", buf);
1156 child = opthead->add_child ("smpte-offset-negative");
1157 child->add_property ("val", smpte_offset_negative () ? "yes" : "no");
1159 child = opthead->add_child ("edit-mode");
1160 switch (_edit_mode) {
1162 child->add_property ("val", "splice");
1166 child->add_property ("val", "slide");
1170 child = opthead->add_child ("auto-play");
1171 child->add_property ("val", get_auto_play () ? "yes" : "no");
1172 child = opthead->add_child ("auto-input");
1173 child->add_property ("val", get_auto_input () ? "yes" : "no");
1174 child = opthead->add_child ("seamless-loop");
1175 child->add_property ("val", get_seamless_loop () ? "yes" : "no");
1176 child = opthead->add_child ("punch-in");
1177 child->add_property ("val", get_punch_in () ? "yes" : "no");
1178 child = opthead->add_child ("punch-out");
1179 child->add_property ("val", get_punch_out () ? "yes" : "no");
1180 child = opthead->add_child ("all-safe");
1181 child->add_property ("val", get_all_safe () ? "yes" : "no");
1182 child = opthead->add_child ("auto-return");
1183 child->add_property ("val", get_auto_return () ? "yes" : "no");
1184 child = opthead->add_child ("mmc-control");
1185 child->add_property ("val", get_mmc_control () ? "yes" : "no");
1186 child = opthead->add_child ("midi-control");
1187 child->add_property ("val", get_midi_control () ? "yes" : "no");
1188 child = opthead->add_child ("midi-feedback");
1189 child->add_property ("val", get_midi_feedback () ? "yes" : "no");
1190 child = opthead->add_child ("do-not-record-plugins");
1191 child->add_property ("val", get_do_not_record_plugins () ? "yes" : "no");
1192 child = opthead->add_child ("auto-crossfade");
1193 child->add_property ("val", get_crossfades_active () ? "yes" : "no");
1194 child = opthead->add_child ("audible-click");
1195 child->add_property ("val", get_clicking () ? "yes" : "no");
1196 child = opthead->add_child ("end-marker-is-free");
1197 child->add_property ("val", _end_location_is_free ? "yes" : "no");
1199 if (click_sound.length()) {
1200 child = opthead->add_child ("click-sound");
1201 child->add_property ("val", click_sound);
1204 if (click_emphasis_sound.length()) {
1205 child = opthead->add_child ("click-emphasis-sound");
1206 child->add_property ("val", click_emphasis_sound);
1209 child = opthead->add_child ("solo-model");
1210 child->add_property ("val", _solo_model == SoloBus ? "SoloBus" : "InverseMute");
1212 child = opthead->add_child ("layer-model");
1213 switch (layer_model) {
1215 child->add_property ("val", X_("LaterHigher"));
1218 child->add_property ("val", X_("MoveAddHigher"));
1221 child->add_property ("val", X_("AddHigher"));
1225 child = opthead->add_child ("xfade-model");
1226 switch (xfade_model) {
1228 child->add_property ("val", X_("Full"));
1230 case ShortCrossfade:
1231 child->add_property ("val", X_("Short"));
1234 child = opthead->add_child ("short-xfade-length");
1235 /* store as fractions of a second */
1236 snprintf (buf, sizeof(buf)-1, "%f",
1237 (float) Crossfade::short_xfade_length() / frame_rate());
1238 child->add_property ("val", buf);
1240 child = opthead->add_child ("full-xfades-unmuted");
1241 child->add_property ("val", crossfades_active ? "yes" : "no");
1247 Session::get_state()
1253 Session::get_template()
1255 /* if we don't disable rec-enable, diskstreams
1256 will believe they need to store their capture
1257 sources in their state node.
1260 disable_record (false);
1262 return state(false);
1266 Session::state(bool full_state)
1268 XMLNode* node = new XMLNode("Session");
1271 // store libardour version, just in case
1273 snprintf(buf, sizeof(buf)-1, "%d.%d.%d",
1274 libardour_major_version, libardour_minor_version, libardour_micro_version);
1275 node->add_property("version", string(buf));
1277 /* store configuration settings */
1281 /* store the name */
1282 node->add_property ("name", _name);
1284 if (session_dirs.size() > 1) {
1288 vector<space_and_path>::iterator i = session_dirs.begin();
1289 vector<space_and_path>::iterator next;
1291 ++i; /* skip the first one */
1295 while (i != session_dirs.end()) {
1299 if (next != session_dirs.end()) {
1309 child = node->add_child ("Path");
1310 child->add_content (p);
1314 /* save the ID counter */
1316 snprintf (buf, sizeof (buf), "%" PRIu64, ID::counter());
1317 node->add_property ("id-counter", buf);
1319 /* various options */
1321 node->add_child_nocopy (get_options());
1323 child = node->add_child ("Sources");
1326 Glib::Mutex::Lock sl (audio_source_lock);
1328 for (AudioSourceList::iterator siter = audio_sources.begin(); siter != audio_sources.end(); ++siter) {
1330 /* Don't save information about AudioFileSources that are empty */
1332 boost::shared_ptr<AudioFileSource> fs;
1334 if ((fs = boost::dynamic_pointer_cast<AudioFileSource> (siter->second)) != 0) {
1335 boost::shared_ptr<DestructiveFileSource> dfs = boost::dynamic_pointer_cast<DestructiveFileSource> (fs);
1337 /* destructive file sources are OK if they are empty, because
1338 we will re-use them every time.
1342 if (fs->length() == 0) {
1348 child->add_child_nocopy (siter->second->get_state());
1352 child = node->add_child ("Regions");
1355 Glib::Mutex::Lock rl (region_lock);
1357 for (AudioRegionList::const_iterator i = audio_regions.begin(); i != audio_regions.end(); ++i) {
1359 /* only store regions not attached to playlists */
1361 if (i->second->playlist() == 0) {
1362 child->add_child_nocopy (i->second->state (true));
1367 child = node->add_child ("DiskStreams");
1370 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
1371 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
1372 if (!(*i)->hidden()) {
1373 child->add_child_nocopy ((*i)->get_state());
1378 node->add_child_nocopy (_locations.get_state());
1380 child = node->add_child ("Connections");
1382 Glib::Mutex::Lock lm (connection_lock);
1383 for (ConnectionList::iterator i = _connections.begin(); i != _connections.end(); ++i) {
1384 if (!(*i)->system_dependent()) {
1385 child->add_child_nocopy ((*i)->get_state());
1390 child = node->add_child ("Routes");
1392 boost::shared_ptr<RouteList> r = routes.reader ();
1394 RoutePublicOrderSorter cmp;
1395 RouteList public_order (*r);
1396 public_order.sort (cmp);
1398 for (RouteList::iterator i = public_order.begin(); i != public_order.end(); ++i) {
1399 if (!(*i)->hidden()) {
1401 child->add_child_nocopy ((*i)->get_state());
1403 child->add_child_nocopy ((*i)->get_template());
1410 child = node->add_child ("EditGroups");
1411 for (list<RouteGroup *>::iterator i = edit_groups.begin(); i != edit_groups.end(); ++i) {
1412 child->add_child_nocopy ((*i)->get_state());
1415 child = node->add_child ("MixGroups");
1416 for (list<RouteGroup *>::iterator i = mix_groups.begin(); i != mix_groups.end(); ++i) {
1417 child->add_child_nocopy ((*i)->get_state());
1420 child = node->add_child ("Playlists");
1421 for (PlaylistList::iterator i = playlists.begin(); i != playlists.end(); ++i) {
1422 if (!(*i)->hidden()) {
1423 if (!(*i)->empty()) {
1425 child->add_child_nocopy ((*i)->get_state());
1427 child->add_child_nocopy ((*i)->get_template());
1433 child = node->add_child ("UnusedPlaylists");
1434 for (PlaylistList::iterator i = unused_playlists.begin(); i != unused_playlists.end(); ++i) {
1435 if (!(*i)->hidden()) {
1436 if (!(*i)->empty()) {
1438 child->add_child_nocopy ((*i)->get_state());
1440 child->add_child_nocopy ((*i)->get_template());
1448 child = node->add_child ("Click");
1449 child->add_child_nocopy (_click_io->state (full_state));
1453 child = node->add_child ("NamedSelections");
1454 for (NamedSelectionList::iterator i = named_selections.begin(); i != named_selections.end(); ++i) {
1456 child->add_child_nocopy ((*i)->get_state());
1461 node->add_child_nocopy (_tempo_map->get_state());
1464 node->add_child_copy (*_extra_xml);
1471 Session::set_state (const XMLNode& node)
1475 const XMLProperty* prop;
1478 _state_of_the_state = StateOfTheState (_state_of_the_state|CannotSave);
1480 if (node.name() != X_("Session")){
1481 fatal << _("programming error: Session: incorrect XML node sent to set_state()") << endmsg;
1485 StateManager::prohibit_save ();
1487 if ((prop = node.property ("name")) != 0) {
1488 _name = prop->value ();
1491 if ((prop = node.property (X_("id-counter"))) != 0) {
1493 sscanf (prop->value().c_str(), "%" PRIu64, &x);
1494 ID::init_counter (x);
1496 /* old sessions used a timebased counter, so fake
1497 the startup ID counter based on a standard
1502 ID::init_counter (now);
1506 IO::disable_ports ();
1507 IO::disable_connecting ();
1509 /* Object loading order:
1526 if (use_config_midi_ports ()) {
1529 if ((child = find_named_node (node, "Path")) != 0) {
1530 /* XXX this XML content stuff horrible API design */
1531 string raid_path = _path + ':' + child->children().front()->content();
1532 setup_raid_path (raid_path);
1534 /* the path is already set */
1537 if ((child = find_named_node (node, "extra")) != 0) {
1538 _extra_xml = new XMLNode (*child);
1541 if ((child = find_named_node (node, "Options")) == 0) {
1542 error << _("Session: XML state has no options section") << endmsg;
1543 } else if (load_options (*child)) {
1546 if ((child = find_named_node (node, "Sources")) == 0) {
1547 error << _("Session: XML state has no sources section") << endmsg;
1549 } else if (load_sources (*child)) {
1553 if ((child = find_named_node (node, "Regions")) == 0) {
1554 error << _("Session: XML state has no Regions section") << endmsg;
1556 } else if (load_regions (*child)) {
1560 if ((child = find_named_node (node, "Playlists")) == 0) {
1561 error << _("Session: XML state has no playlists section") << endmsg;
1563 } else if (load_playlists (*child)) {
1567 if ((child = find_named_node (node, "UnusedPlaylists")) == 0) {
1569 } else if (load_unused_playlists (*child)) {
1573 if ((child = find_named_node (node, "NamedSelections")) != 0) {
1574 if (load_named_selections (*child)) {
1579 if ((child = find_named_node (node, "DiskStreams")) == 0) {
1580 error << _("Session: XML state has no diskstreams section") << endmsg;
1582 } else if (load_diskstreams (*child)) {
1586 if ((child = find_named_node (node, "Connections")) == 0) {
1587 error << _("Session: XML state has no connections section") << endmsg;
1589 } else if (load_connections (*child)) {
1593 if ((child = find_named_node (node, "Locations")) == 0) {
1594 error << _("Session: XML state has no locations section") << endmsg;
1596 } else if (_locations.set_state (*child)) {
1602 if ((location = _locations.auto_loop_location()) != 0) {
1603 set_auto_loop_location (location);
1606 if ((location = _locations.auto_punch_location()) != 0) {
1607 set_auto_punch_location (location);
1610 if ((location = _locations.end_location()) == 0) {
1611 _locations.add (end_location);
1613 delete end_location;
1614 end_location = location;
1617 if ((location = _locations.start_location()) == 0) {
1618 _locations.add (start_location);
1620 delete start_location;
1621 start_location = location;
1624 _locations.save_state (_("initial state"));
1626 if ((child = find_named_node (node, "EditGroups")) == 0) {
1627 error << _("Session: XML state has no edit groups section") << endmsg;
1629 } else if (load_edit_groups (*child)) {
1633 if ((child = find_named_node (node, "MixGroups")) == 0) {
1634 error << _("Session: XML state has no mix groups section") << endmsg;
1636 } else if (load_mix_groups (*child)) {
1640 if ((child = find_named_node (node, "TempoMap")) == 0) {
1641 error << _("Session: XML state has no Tempo Map section") << endmsg;
1643 } else if (_tempo_map->set_state (*child)) {
1647 if ((child = find_named_node (node, "Routes")) == 0) {
1648 error << _("Session: XML state has no routes section") << endmsg;
1650 } else if (load_routes (*child)) {
1654 if ((child = find_named_node (node, "Click")) == 0) {
1655 warning << _("Session: XML state has no click section") << endmsg;
1656 } else if (_click_io) {
1657 _click_io->set_state (*child);
1660 /* OK, now we can set edit mode */
1662 set_edit_mode (pending_edit_mode);
1664 /* here beginneth the second phase ... */
1666 StateReady (); /* EMIT SIGNAL */
1668 _state_of_the_state = Clean;
1670 StateManager::allow_save (_("initial state"), true);
1672 if (state_was_pending) {
1673 save_state (_current_snapshot_name);
1674 remove_pending_capture_state ();
1675 state_was_pending = false;
1681 /* we failed, re-enable state saving but don't actually save internal state */
1682 StateManager::allow_save (X_("ignored"), false);
1687 Session::load_routes (const XMLNode& node)
1690 XMLNodeConstIterator niter;
1691 RouteList new_routes;
1693 nlist = node.children();
1697 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1699 boost::shared_ptr<Route> route (XMLRouteFactory (**niter));
1702 error << _("Session: cannot create Route from XML description.") << endmsg;
1706 new_routes.push_back (route);
1709 add_routes (new_routes);
1714 boost::shared_ptr<Route>
1715 Session::XMLRouteFactory (const XMLNode& node)
1717 if (node.name() != "Route") {
1718 return boost::shared_ptr<Route> ((Route*) 0);
1721 if (node.property ("diskstream") != 0 || node.property ("diskstream-id") != 0) {
1722 boost::shared_ptr<Route> x (new AudioTrack (*this, node));
1725 boost::shared_ptr<Route> x (new Route (*this, node));
1731 Session::load_regions (const XMLNode& node)
1734 XMLNodeConstIterator niter;
1735 boost::shared_ptr<AudioRegion> region;
1737 nlist = node.children();
1741 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1742 if ((region = XMLRegionFactory (**niter, false)) == 0) {
1743 error << _("Session: cannot create Region from XML description.") << endmsg;
1750 boost::shared_ptr<AudioRegion>
1751 Session::XMLRegionFactory (const XMLNode& node, bool full)
1753 const XMLProperty* prop;
1754 boost::shared_ptr<Source> source;
1755 boost::shared_ptr<AudioSource> as;
1757 uint32_t nchans = 1;
1760 if (node.name() != X_("Region")) {
1761 return boost::shared_ptr<AudioRegion>();
1764 if ((prop = node.property (X_("channels"))) != 0) {
1765 nchans = atoi (prop->value().c_str());
1769 if ((prop = node.property (X_("source-0"))) == 0) {
1770 if ((prop = node.property ("source")) == 0) {
1771 error << _("Session: XMLNode describing a AudioRegion is incomplete (no source)") << endmsg;
1772 return boost::shared_ptr<AudioRegion>();
1776 PBD::ID s_id (prop->value());
1778 if ((source = source_by_id (s_id)) == 0) {
1779 error << string_compose(_("Session: XMLNode describing a AudioRegion references an unknown source id =%1"), s_id) << endmsg;
1780 return boost::shared_ptr<AudioRegion>();
1783 as = boost::dynamic_pointer_cast<AudioSource>(source);
1785 error << string_compose(_("Session: XMLNode describing a AudioRegion references a non-audio source id =%1"), s_id) << endmsg;
1786 return boost::shared_ptr<AudioRegion>();
1789 sources.push_back (as);
1791 /* pickup other channels */
1793 for (uint32_t n=1; n < nchans; ++n) {
1794 snprintf (buf, sizeof(buf), X_("source-%d"), n);
1795 if ((prop = node.property (buf)) != 0) {
1797 PBD::ID id2 (prop->value());
1799 if ((source = source_by_id (id2)) == 0) {
1800 error << string_compose(_("Session: XMLNode describing a AudioRegion references an unknown source id =%1"), id2) << endmsg;
1801 return boost::shared_ptr<AudioRegion>();
1804 as = boost::dynamic_pointer_cast<AudioSource>(source);
1806 error << string_compose(_("Session: XMLNode describing a AudioRegion references a non-audio source id =%1"), id2) << endmsg;
1807 return boost::shared_ptr<AudioRegion>();
1809 sources.push_back (as);
1814 boost::shared_ptr<AudioRegion> region (boost::dynamic_pointer_cast<AudioRegion> (RegionFactory::create (sources, node)));
1819 catch (failed_constructor& err) {
1820 return boost::shared_ptr<AudioRegion>();
1825 Session::get_sources_as_xml ()
1828 XMLNode* node = new XMLNode (X_("Sources"));
1829 Glib::Mutex::Lock lm (audio_source_lock);
1831 for (AudioSourceList::iterator i = audio_sources.begin(); i != audio_sources.end(); ++i) {
1832 node->add_child_nocopy (i->second->get_state());
1835 /* XXX get MIDI and other sources here */
1841 Session::path_from_region_name (string name, string identifier)
1843 char buf[PATH_MAX+1];
1845 string dir = discover_best_sound_dir ();
1847 for (n = 0; n < 999999; ++n) {
1848 if (identifier.length()) {
1849 snprintf (buf, sizeof(buf), "%s/%s%s%" PRIu32 ".wav", dir.c_str(), name.c_str(),
1850 identifier.c_str(), n);
1852 snprintf (buf, sizeof(buf), "%s/%s-%" PRIu32 ".wav", dir.c_str(), name.c_str(), n);
1854 if (access (buf, F_OK) != 0) {
1864 Session::load_sources (const XMLNode& node)
1867 XMLNodeConstIterator niter;
1868 boost::shared_ptr<Source> source;
1870 nlist = node.children();
1874 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1876 if ((source = XMLSourceFactory (**niter)) == 0) {
1877 error << _("Session: cannot create Source from XML description.") << endmsg;
1884 boost::shared_ptr<Source>
1885 Session::XMLSourceFactory (const XMLNode& node)
1888 if (node.name() != "Source") {
1889 return boost::shared_ptr<Source>();
1893 return SourceFactory::create (*this, node);
1896 catch (failed_constructor& err) {
1897 error << _("Found a sound file that cannot be used by Ardour. Talk to the progammers.") << endmsg;
1898 return boost::shared_ptr<Source>();
1903 Session::save_template (string template_name)
1906 string xml_path, bak_path, template_path;
1908 if (_state_of_the_state & CannotSave) {
1913 string dir = template_dir();
1915 if ((dp = opendir (dir.c_str()))) {
1918 if (g_mkdir_with_parents (dir.c_str(), S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH)) {
1919 error << string_compose(_("Could not create mix templates directory \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
1924 tree.set_root (&get_template());
1927 xml_path += template_name;
1928 xml_path += _template_suffix;
1930 ifstream in(xml_path.c_str());
1933 warning << string_compose(_("Template \"%1\" already exists - new version not created"), template_name) << endmsg;
1939 if (!tree.write (xml_path)) {
1940 error << _("mix template not saved") << endmsg;
1948 Session::rename_template (string old_name, string new_name)
1950 string old_path = template_dir() + old_name + _template_suffix;
1951 string new_path = template_dir() + new_name + _template_suffix;
1953 return rename (old_path.c_str(), new_path.c_str());
1957 Session::delete_template (string name)
1959 string template_path = template_dir();
1960 template_path += name;
1961 template_path += _template_suffix;
1963 return remove (template_path.c_str());
1967 Session::refresh_disk_space ()
1970 struct statfs statfsbuf;
1971 vector<space_and_path>::iterator i;
1972 Glib::Mutex::Lock lm (space_lock);
1975 /* get freespace on every FS that is part of the session path */
1977 _total_free_4k_blocks = 0;
1979 for (i = session_dirs.begin(); i != session_dirs.end(); ++i) {
1980 statfs ((*i).path.c_str(), &statfsbuf);
1982 scale = statfsbuf.f_bsize/4096.0;
1984 (*i).blocks = (uint32_t) floor (statfsbuf.f_bavail * scale);
1985 _total_free_4k_blocks += (*i).blocks;
1991 Session::ensure_sound_dir (string path, string& result)
1996 /* Ensure that the parent directory exists */
1998 if (g_mkdir_with_parents (path.c_str(), 0775)) {
1999 error << string_compose(_("cannot create session directory \"%1\"; ignored"), path) << endmsg;
2003 /* Ensure that the sounds directory exists */
2007 result += sound_dir_name;
2009 if (g_mkdir_with_parents (result.c_str(), 0775)) {
2010 error << string_compose(_("cannot create sounds directory \"%1\"; ignored"), result) << endmsg;
2016 dead += dead_sound_dir_name;
2018 if (g_mkdir_with_parents (dead.c_str(), 0775)) {
2019 error << string_compose(_("cannot create dead sounds directory \"%1\"; ignored"), dead) << endmsg;
2025 peak += peak_dir_name;
2027 if (g_mkdir_with_parents (peak.c_str(), 0775)) {
2028 error << string_compose(_("cannot create peak file directory \"%1\"; ignored"), peak) << endmsg;
2032 /* callers expect this to be terminated ... */
2039 Session::discover_best_sound_dir (bool destructive)
2041 vector<space_and_path>::iterator i;
2044 /* handle common case without system calls */
2046 if (session_dirs.size() == 1) {
2050 /* OK, here's the algorithm we're following here:
2052 We want to select which directory to use for
2053 the next file source to be created. Ideally,
2054 we'd like to use a round-robin process so as to
2055 get maximum performance benefits from splitting
2056 the files across multiple disks.
2058 However, in situations without much diskspace, an
2059 RR approach may end up filling up a filesystem
2060 with new files while others still have space.
2061 Its therefore important to pay some attention to
2062 the freespace in the filesystem holding each
2063 directory as well. However, if we did that by
2064 itself, we'd keep creating new files in the file
2065 system with the most space until it was as full
2066 as all others, thus negating any performance
2067 benefits of this RAID-1 like approach.
2069 So, we use a user-configurable space threshold. If
2070 there are at least 2 filesystems with more than this
2071 much space available, we use RR selection between them.
2072 If not, then we pick the filesystem with the most space.
2074 This gets a good balance between the two
2078 refresh_disk_space ();
2080 int free_enough = 0;
2082 for (i = session_dirs.begin(); i != session_dirs.end(); ++i) {
2083 if ((*i).blocks * 4096 >= Config->get_disk_choice_space_threshold()) {
2088 if (free_enough >= 2) {
2090 bool found_it = false;
2092 /* use RR selection process, ensuring that the one
2096 i = last_rr_session_dir;
2099 if (++i == session_dirs.end()) {
2100 i = session_dirs.begin();
2103 if ((*i).blocks * 4096 >= Config->get_disk_choice_space_threshold()) {
2104 if (ensure_sound_dir ((*i).path, result) == 0) {
2105 last_rr_session_dir = i;
2111 } while (i != last_rr_session_dir);
2114 result = sound_dir();
2119 /* pick FS with the most freespace (and that
2120 seems to actually work ...)
2123 vector<space_and_path> sorted;
2124 space_and_path_ascending_cmp cmp;
2126 sorted = session_dirs;
2127 sort (sorted.begin(), sorted.end(), cmp);
2129 for (i = sorted.begin(); i != sorted.end(); ++i) {
2130 if (ensure_sound_dir ((*i).path, result) == 0) {
2131 last_rr_session_dir = i;
2136 /* if the above fails, fall back to the most simplistic solution */
2138 if (i == sorted.end()) {
2147 Session::load_playlists (const XMLNode& node)
2150 XMLNodeConstIterator niter;
2153 nlist = node.children();
2157 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2159 if ((playlist = XMLPlaylistFactory (**niter)) == 0) {
2160 error << _("Session: cannot create Playlist from XML description.") << endmsg;
2168 Session::load_unused_playlists (const XMLNode& node)
2171 XMLNodeConstIterator niter;
2174 nlist = node.children();
2178 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2180 if ((playlist = XMLPlaylistFactory (**niter)) == 0) {
2181 error << _("Session: cannot create Playlist from XML description.") << endmsg;
2185 // now manually untrack it
2187 track_playlist (playlist, false);
2195 Session::XMLPlaylistFactory (const XMLNode& node)
2198 return new AudioPlaylist (*this, node);
2201 catch (failed_constructor& err) {
2207 Session::load_named_selections (const XMLNode& node)
2210 XMLNodeConstIterator niter;
2213 nlist = node.children();
2217 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2219 if ((ns = XMLNamedSelectionFactory (**niter)) == 0) {
2220 error << _("Session: cannot create Named Selection from XML description.") << endmsg;
2228 Session::XMLNamedSelectionFactory (const XMLNode& node)
2231 return new NamedSelection (*this, node);
2234 catch (failed_constructor& err) {
2240 Session::dead_sound_dir () const
2243 res += dead_sound_dir_name;
2249 Session::sound_dir (bool with_path) const
2251 /* support old session structure */
2253 struct stat statbuf;
2260 old += sound_dir_name;
2263 if (stat (old.c_str(), &statbuf) == 0) {
2273 res += interchange_dir_name;
2275 res += legalize_for_path (_name);
2277 res += sound_dir_name;
2284 Session::peak_dir () const
2287 res += peak_dir_name;
2293 Session::automation_dir () const
2296 res += "automation/";
2301 Session::template_dir ()
2303 string path = get_user_ardour_path();
2304 path += "templates/";
2310 Session::suffixed_search_path (string suffix, bool data)
2314 path += get_user_ardour_path();
2315 if (path[path.length()-1] != ':') {
2320 path += get_system_data_path();
2322 path += get_system_module_path();
2325 vector<string> split_path;
2327 split (path, split_path, ':');
2330 for (vector<string>::iterator i = split_path.begin(); i != split_path.end(); ++i) {
2335 if (distance (i, split_path.end()) != 1) {
2344 Session::template_path ()
2346 return suffixed_search_path (X_("templates"), true);
2350 Session::control_protocol_path ()
2352 return suffixed_search_path (X_("surfaces"), false);
2356 Session::load_connections (const XMLNode& node)
2358 XMLNodeList nlist = node.children();
2359 XMLNodeConstIterator niter;
2363 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2364 if ((*niter)->name() == "InputConnection") {
2365 add_connection (new ARDOUR::InputConnection (**niter));
2366 } else if ((*niter)->name() == "OutputConnection") {
2367 add_connection (new ARDOUR::OutputConnection (**niter));
2369 error << string_compose(_("Unknown node \"%1\" found in Connections list from state file"), (*niter)->name()) << endmsg;
2378 Session::load_edit_groups (const XMLNode& node)
2380 return load_route_groups (node, true);
2384 Session::load_mix_groups (const XMLNode& node)
2386 return load_route_groups (node, false);
2390 Session::load_route_groups (const XMLNode& node, bool edit)
2392 XMLNodeList nlist = node.children();
2393 XMLNodeConstIterator niter;
2398 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2399 if ((*niter)->name() == "RouteGroup") {
2401 rg = add_edit_group ("");
2402 rg->set_state (**niter);
2404 rg = add_mix_group ("");
2405 rg->set_state (**niter);
2414 state_file_filter (const string &str, void *arg)
2416 return (str.length() > strlen(Session::statefile_suffix()) &&
2417 str.find (Session::statefile_suffix()) == (str.length() - strlen (Session::statefile_suffix())));
2421 bool operator()(const string* a, const string* b) {
2427 remove_end(string* state)
2429 string statename(*state);
2431 string::size_type start,end;
2432 if ((start = statename.find_last_of ('/')) != string::npos) {
2433 statename = statename.substr (start+1);
2436 if ((end = statename.rfind(".ardour")) == string::npos) {
2437 end = statename.length();
2440 return new string(statename.substr (0, end));
2444 Session::possible_states (string path)
2446 PathScanner scanner;
2447 vector<string*>* states = scanner (path, state_file_filter, 0, false, false);
2449 transform(states->begin(), states->end(), states->begin(), remove_end);
2452 sort (states->begin(), states->end(), cmp);
2458 Session::possible_states () const
2460 return possible_states(_path);
2464 Session::auto_save()
2466 save_state (_current_snapshot_name);
2470 Session::add_edit_group (string name)
2472 RouteGroup* rg = new RouteGroup (*this, name);
2473 edit_groups.push_back (rg);
2474 edit_group_added (rg); /* EMIT SIGNAL */
2480 Session::add_mix_group (string name)
2482 RouteGroup* rg = new RouteGroup (*this, name, RouteGroup::Relative);
2483 mix_groups.push_back (rg);
2484 mix_group_added (rg); /* EMIT SIGNAL */
2490 Session::remove_edit_group (RouteGroup& rg)
2492 list<RouteGroup*>::iterator i;
2494 if ((i = find (edit_groups.begin(), edit_groups.end(), &rg)) != edit_groups.end()) {
2495 (*i)->apply (&Route::drop_edit_group, this);
2496 edit_groups.erase (i);
2497 edit_group_removed (); /* EMIT SIGNAL */
2504 Session::remove_mix_group (RouteGroup& rg)
2506 list<RouteGroup*>::iterator i;
2508 if ((i = find (mix_groups.begin(), mix_groups.end(), &rg)) != mix_groups.end()) {
2509 (*i)->apply (&Route::drop_mix_group, this);
2510 mix_groups.erase (i);
2511 mix_group_removed (); /* EMIT SIGNAL */
2518 Session::mix_group_by_name (string name)
2520 list<RouteGroup *>::iterator i;
2522 for (i = mix_groups.begin(); i != mix_groups.end(); ++i) {
2523 if ((*i)->name() == name) {
2531 Session::edit_group_by_name (string name)
2533 list<RouteGroup *>::iterator i;
2535 for (i = edit_groups.begin(); i != edit_groups.end(); ++i) {
2536 if ((*i)->name() == name) {
2544 Session::set_meter_hold (float val)
2547 MeterHoldChanged(); // emit
2551 Session::set_meter_falloff (float val)
2553 _meter_falloff = val;
2554 MeterFalloffChanged(); // emit
2559 Session::begin_reversible_command (string name)
2561 current_trans = new UndoTransaction;
2562 current_trans->set_name (name);
2566 Session::commit_reversible_command (Command *cmd)
2571 current_trans->add_command (cmd);
2574 gettimeofday (&now, 0);
2575 current_trans->set_timestamp (now);
2577 history.add (current_trans);
2580 Session::GlobalRouteBooleanState
2581 Session::get_global_route_boolean (bool (Route::*method)(void) const)
2583 GlobalRouteBooleanState s;
2584 boost::shared_ptr<RouteList> r = routes.reader ();
2586 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
2587 if (!(*i)->hidden()) {
2588 RouteBooleanState v;
2591 Route* r = (*i).get();
2592 v.second = (r->*method)();
2601 Session::GlobalRouteMeterState
2602 Session::get_global_route_metering ()
2604 GlobalRouteMeterState s;
2605 boost::shared_ptr<RouteList> r = routes.reader ();
2607 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
2608 if (!(*i)->hidden()) {
2612 v.second = (*i)->meter_point();
2622 Session::set_global_route_metering (GlobalRouteMeterState s, void* arg)
2624 for (GlobalRouteMeterState::iterator i = s.begin(); i != s.end(); ++i) {
2625 i->first->set_meter_point (i->second, arg);
2630 Session::set_global_route_boolean (GlobalRouteBooleanState s, void (Route::*method)(bool, void*), void* arg)
2632 for (GlobalRouteBooleanState::iterator i = s.begin(); i != s.end(); ++i) {
2633 Route* r = i->first.get();
2634 (r->*method) (i->second, arg);
2639 Session::set_global_mute (GlobalRouteBooleanState s, void* src)
2641 set_global_route_boolean (s, &Route::set_mute, src);
2645 Session::set_global_solo (GlobalRouteBooleanState s, void* src)
2647 set_global_route_boolean (s, &Route::set_solo, src);
2651 Session::set_global_record_enable (GlobalRouteBooleanState s, void* src)
2653 set_global_route_boolean (s, &Route::set_record_enable, src);
2658 Session::global_mute_memento (void* src)
2660 return sigc::bind (mem_fun (*this, &Session::set_global_mute), get_global_route_boolean (&Route::muted), src);
2664 Session::global_metering_memento (void* src)
2666 return sigc::bind (mem_fun (*this, &Session::set_global_route_metering), get_global_route_metering (), src);
2670 Session::global_solo_memento (void* src)
2672 return sigc::bind (mem_fun (*this, &Session::set_global_solo), get_global_route_boolean (&Route::soloed), src);
2676 Session::global_record_enable_memento (void* src)
2678 return sigc::bind (mem_fun (*this, &Session::set_global_record_enable), get_global_route_boolean (&Route::record_enabled), src);
2683 template_filter (const string &str, void *arg)
2685 return (str.length() > strlen(Session::template_suffix()) &&
2686 str.find (Session::template_suffix()) == (str.length() - strlen (Session::template_suffix())));
2690 Session::get_template_list (list<string> &template_names)
2692 vector<string *> *templates;
2693 PathScanner scanner;
2696 path = template_path ();
2698 templates = scanner (path, template_filter, 0, false, true);
2700 vector<string*>::iterator i;
2701 for (i = templates->begin(); i != templates->end(); ++i) {
2702 string fullpath = *(*i);
2705 start = fullpath.find_last_of ('/') + 1;
2706 if ((end = fullpath.find_last_of ('.')) <0) {
2707 end = fullpath.length();
2710 template_names.push_back(fullpath.substr(start, (end-start)));
2715 Session::read_favorite_dirs (FavoriteDirs & favs)
2717 string path = get_user_ardour_path();
2718 path += "/favorite_dirs";
2720 ifstream fav (path.c_str());
2725 if (errno != ENOENT) {
2726 //error << string_compose (_("cannot open favorite file %1 (%2)"), path, strerror (errno)) << endmsg;
2737 getline(fav, newfav);
2743 favs.push_back (newfav);
2750 Session::write_favorite_dirs (FavoriteDirs & favs)
2752 string path = get_user_ardour_path();
2753 path += "/favorite_dirs";
2755 ofstream fav (path.c_str());
2761 for (FavoriteDirs::iterator i = favs.begin(); i != favs.end(); ++i) {
2762 fav << (*i) << endl;
2769 accept_all_non_peak_files (const string& path, void *arg)
2771 return (path.length() > 5 && path.find (".peak") != (path.length() - 5));
2775 accept_all_state_files (const string& path, void *arg)
2777 return (path.length() > 7 && path.find (".ardour") == (path.length() - 7));
2781 Session::find_all_sources (string path, set<string>& result)
2786 if (!tree.read (path)) {
2790 if ((node = find_named_node (*tree.root(), "Sources")) == 0) {
2795 XMLNodeConstIterator niter;
2797 nlist = node->children();
2801 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2805 if ((prop = (*niter)->property (X_("name"))) == 0) {
2809 if (prop->value()[0] == '/') {
2810 /* external file, ignore */
2814 string path = _path; /* /-terminated */
2815 path += sound_dir_name;
2817 path += prop->value();
2819 result.insert (path);
2826 Session::find_all_sources_across_snapshots (set<string>& result, bool exclude_this_snapshot)
2828 PathScanner scanner;
2829 vector<string*>* state_files;
2831 string this_snapshot_path;
2837 if (ripped[ripped.length()-1] == '/') {
2838 ripped = ripped.substr (0, ripped.length() - 1);
2841 state_files = scanner (ripped, accept_all_state_files, (void *) 0, false, true);
2843 if (state_files == 0) {
2848 this_snapshot_path = _path;
2849 this_snapshot_path += _current_snapshot_name;
2850 this_snapshot_path += _statefile_suffix;
2852 for (vector<string*>::iterator i = state_files->begin(); i != state_files->end(); ++i) {
2854 if (exclude_this_snapshot && **i == this_snapshot_path) {
2858 if (find_all_sources (**i, result) < 0) {
2867 Session::cleanup_sources (Session::cleanup_report& rep)
2869 vector<boost::shared_ptr<Source> > dead_sources;
2870 vector<Playlist*> playlists_tbd;
2871 PathScanner scanner;
2873 vector<space_and_path>::iterator i;
2874 vector<space_and_path>::iterator nexti;
2875 vector<string*>* soundfiles;
2876 vector<string> unused;
2877 set<string> all_sources;
2882 _state_of_the_state = (StateOfTheState) (_state_of_the_state | InCleanup);
2884 /* step 1: consider deleting all unused playlists */
2886 for (PlaylistList::iterator x = unused_playlists.begin(); x != unused_playlists.end(); ++x) {
2889 status = AskAboutPlaylistDeletion (*x);
2898 playlists_tbd.push_back (*x);
2902 /* leave it alone */
2907 /* now delete any that were marked for deletion */
2909 for (vector<Playlist*>::iterator x = playlists_tbd.begin(); x != playlists_tbd.end(); ++x) {
2910 PlaylistList::iterator foo;
2912 if ((foo = unused_playlists.find (*x)) != unused_playlists.end()) {
2913 unused_playlists.erase (foo);
2918 /* step 2: clear the undo/redo history for all playlists */
2920 for (PlaylistList::iterator x = playlists.begin(); x != playlists.end(); ++x) {
2921 (*x)->drop_all_states ();
2924 /* step 3: find all un-referenced sources */
2929 for (AudioSourceList::iterator i = audio_sources.begin(); i != audio_sources.end(); ) {
2931 AudioSourceList::iterator tmp;
2936 /* only remove files that are not in use and have some size
2937 to them. otherwise we remove the current "nascent"
2941 if (i->second.use_count() == 1 && i->second->length() > 0) {
2942 dead_sources.push_back (i->second);
2944 /* remove this source from our own list to avoid us
2945 adding it to the list of all sources below
2948 audio_sources.erase (i);
2954 /* Step 4: get rid of all regions in the region list that use any dead sources
2955 in case the sources themselves don't go away (they might be referenced in
2959 for (vector<boost::shared_ptr<Source> >::iterator i = dead_sources.begin(); i != dead_sources.end();++i) {
2961 for (AudioRegionList::iterator r = audio_regions.begin(); r != audio_regions.end(); ) {
2962 AudioRegionList::iterator tmp;
2963 boost::shared_ptr<AudioRegion> ar;
2970 for (uint32_t n = 0; n < ar->n_channels(); ++n) {
2971 if (ar->source (n) == (*i)) {
2972 /* this region is dead */
2981 /* build a list of all the possible sound directories for the session */
2983 for (i = session_dirs.begin(); i != session_dirs.end(); ) {
2988 sound_path += (*i).path;
2989 sound_path += sound_dir_name;
2991 if (nexti != session_dirs.end()) {
2998 /* now do the same thing for the files that ended up in the sounds dir(s)
2999 but are not referenced as sources in any snapshot.
3002 soundfiles = scanner (sound_path, accept_all_non_peak_files, (void *) 0, false, true);
3004 if (soundfiles == 0) {
3008 /* find all sources, but don't use this snapshot because the
3009 state file on disk still references sources we may have already
3013 find_all_sources_across_snapshots (all_sources, true);
3015 /* add our current source list
3018 for (AudioSourceList::iterator i = audio_sources.begin(); i != audio_sources.end(); ++i) {
3019 boost::shared_ptr<AudioFileSource> fs;
3021 if ((fs = boost::dynamic_pointer_cast<AudioFileSource> (i->second)) != 0) {
3022 all_sources.insert (fs->path());
3026 for (vector<string*>::iterator x = soundfiles->begin(); x != soundfiles->end(); ++x) {
3031 for (set<string>::iterator i = all_sources.begin(); i != all_sources.end(); ++i) {
3041 unused.push_back (spath);
3045 /* now try to move all unused files into the "dead_sounds" directory(ies) */
3047 for (vector<string>::iterator x = unused.begin(); x != unused.end(); ++x) {
3048 struct stat statbuf;
3050 rep.paths.push_back (*x);
3051 if (stat ((*x).c_str(), &statbuf) == 0) {
3052 rep.space += statbuf.st_size;
3057 /* don't move the file across filesystems, just
3058 stick it in the `dead_sound_dir_name' directory
3059 on whichever filesystem it was already on.
3062 newpath = Glib::path_get_dirname (*x);
3063 newpath = Glib::path_get_dirname (newpath);
3066 newpath += dead_sound_dir_name;
3068 newpath += Glib::path_get_basename ((*x));
3070 if (access (newpath.c_str(), F_OK) == 0) {
3072 /* the new path already exists, try versioning */
3074 char buf[PATH_MAX+1];
3078 snprintf (buf, sizeof (buf), "%s.%d", newpath.c_str(), version);
3081 while (access (newpath_v.c_str(), F_OK) == 0 && version < 999) {
3082 snprintf (buf, sizeof (buf), "%s.%d", newpath.c_str(), ++version);
3086 if (version == 999) {
3087 error << string_compose (_("there are already 1000 files with names like %1; versioning discontinued"),
3091 newpath = newpath_v;
3096 /* it doesn't exist, or we can't read it or something */
3100 if (::rename ((*x).c_str(), newpath.c_str()) != 0) {
3101 error << string_compose (_("cannot rename audio file source from %1 to %2 (%3)"),
3102 (*x), newpath, strerror (errno))
3108 /* see if there an easy to find peakfile for this file, and remove it.
3111 string peakpath = (*x).substr (0, (*x).find_last_of ('.'));
3112 peakpath += ".peak";
3114 if (access (peakpath.c_str(), W_OK) == 0) {
3115 if (::unlink (peakpath.c_str()) != 0) {
3116 error << string_compose (_("cannot remove peakfile %1 for %2 (%3)"),
3117 peakpath, _path, strerror (errno))
3119 /* try to back out */
3120 rename (newpath.c_str(), _path.c_str());
3129 /* dump the history list */
3133 /* save state so we don't end up a session file
3134 referring to non-existent sources.
3140 _state_of_the_state = (StateOfTheState) (_state_of_the_state & ~InCleanup);
3145 Session::cleanup_trash_sources (Session::cleanup_report& rep)
3147 vector<space_and_path>::iterator i;
3148 string dead_sound_dir;
3149 struct dirent* dentry;
3150 struct stat statbuf;
3156 for (i = session_dirs.begin(); i != session_dirs.end(); ++i) {
3158 dead_sound_dir = (*i).path;
3159 dead_sound_dir += dead_sound_dir_name;
3161 if ((dead = opendir (dead_sound_dir.c_str())) == 0) {
3165 while ((dentry = readdir (dead)) != 0) {
3167 /* avoid '.' and '..' */
3169 if ((dentry->d_name[0] == '.' && dentry->d_name[1] == '\0') ||
3170 (dentry->d_name[2] == '\0' && dentry->d_name[0] == '.' && dentry->d_name[1] == '.')) {
3176 fullpath = dead_sound_dir;
3178 fullpath += dentry->d_name;
3180 if (stat (fullpath.c_str(), &statbuf)) {
3184 if (!S_ISREG (statbuf.st_mode)) {
3188 if (unlink (fullpath.c_str())) {
3189 error << string_compose (_("cannot remove dead sound file %1 (%2)"),
3190 fullpath, strerror (errno))
3194 rep.paths.push_back (dentry->d_name);
3195 rep.space += statbuf.st_size;
3206 Session::set_dirty ()
3208 bool was_dirty = dirty();
3210 _state_of_the_state = StateOfTheState (_state_of_the_state | Dirty);
3213 DirtyChanged(); /* EMIT SIGNAL */
3219 Session::set_clean ()
3221 bool was_dirty = dirty();
3223 _state_of_the_state = Clean;
3226 DirtyChanged(); /* EMIT SIGNAL */
3231 Session::add_controllable (Controllable* c)
3233 Glib::Mutex::Lock lm (controllables_lock);
3234 controllables.push_back (c);
3238 Session::remove_controllable (Controllable* c)
3240 if (_state_of_the_state | Deletion) {
3244 Glib::Mutex::Lock lm (controllables_lock);
3245 controllables.remove (c);
3249 Session::controllable_by_id (const PBD::ID& id)
3251 Glib::Mutex::Lock lm (controllables_lock);
3253 for (Controllables::iterator i = controllables.begin(); i != controllables.end(); ++i) {
3254 if ((*i)->id() == id) {
3263 Session::add_instant_xml (XMLNode& node, const std::string& dir)
3265 Stateful::add_instant_xml (node, dir);
3266 Config->add_instant_xml (node, get_user_ardour_path());
3271 Session::save_history (string snapshot_name)
3277 tree.set_root (&history.get_state());
3279 if (snapshot_name.empty()) {
3280 snapshot_name = _current_snapshot_name;
3283 xml_path = _path + snapshot_name + ".history";
3285 bak_path = xml_path + ".bak";
3287 if ((access (xml_path.c_str(), F_OK) == 0) &&
3288 (rename (xml_path.c_str(), bak_path.c_str())))
3290 error << _("could not backup old history file, current history not saved.") << endmsg;
3294 cerr << "actually writing history\n";
3296 if (!tree.write (xml_path))
3298 error << string_compose (_("history could not be saved to %1"), xml_path) << endmsg;
3300 /* don't leave a corrupt file lying around if it is
3304 if (unlink (xml_path.c_str()))
3306 error << string_compose (_("could not remove corrupt history file %1"), xml_path) << endmsg;
3308 if (rename (bak_path.c_str(), xml_path.c_str()))
3310 error << string_compose (_("could not restore history file from backup %1"), bak_path) << endmsg;
3321 Session::restore_history (string snapshot_name)
3327 xmlpath = _path + snapshot_name + ".history";
3328 cerr << string_compose(_("Loading history from '%1'."), xmlpath) << endmsg;
3330 if (access (xmlpath.c_str(), F_OK)) {
3331 error << string_compose(_("%1: session history file \"%2\" doesn't exist!"), _name, xmlpath) << endmsg;
3335 if (!tree.read (xmlpath)) {
3336 error << string_compose(_("Could not understand ardour file %1"), xmlpath) << endmsg;
3340 /* replace history */
3342 for (XMLNodeConstIterator it = tree.root()->children().begin();
3343 it != tree.root()->children().end();
3347 UndoTransaction* ut = new UndoTransaction ();
3350 ut->set_name(t->property("name")->value());
3351 stringstream ss(t->property("tv_sec")->value());
3353 ss.str(t->property("tv_usec")->value());
3355 ut->set_timestamp(tv);
3357 for (XMLNodeConstIterator child_it = t->children().begin();
3358 child_it != t->children().end();
3361 XMLNode *n = *child_it;
3363 if (n->name() == "MementoCommand" ||
3364 n->name() == "MementoUndoCommand" ||
3365 n->name() == "MementoRedoCommand")
3367 c = memento_command_factory(n);
3373 error << string_compose(_("Couldn't figure out how to make a Command out of a %1 XMLNode."), n->name()) << endmsg;