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)) {
307 remove_empty_sounds ();
310 if (start_butler_thread()) {
314 if (start_midi_thread ()) {
319 if (set_state (*state_tree->root())) {
324 /* we can't save till after ::when_engine_running() is called,
325 because otherwise we save state with no connections made.
326 therefore, we reset _state_of_the_state because ::set_state()
327 will have cleared it.
329 we also have to include Loading so that any events that get
330 generated between here and the end of ::when_engine_running()
331 will be processed directly rather than queued.
334 _state_of_the_state = StateOfTheState (_state_of_the_state|CannotSave|Loading);
336 // set_auto_input (true);
337 _locations.changed.connect (mem_fun (this, &Session::locations_changed));
338 _locations.added.connect (mem_fun (this, &Session::locations_added));
339 setup_click_sounds (0);
340 setup_midi_control ();
342 /* Pay attention ... */
344 _engine.Halted.connect (mem_fun (*this, &Session::engine_halted));
345 _engine.Xrun.connect (mem_fun (*this, &Session::xrun_recovery));
347 if (_engine.running()) {
348 when_engine_running();
350 first_time_running = _engine.Running.connect (mem_fun (*this, &Session::when_engine_running));
353 send_full_time_code ();
354 _engine.transport_locate (0);
355 deliver_mmc (MIDI::MachineControl::cmdMmcReset, 0);
356 deliver_mmc (MIDI::MachineControl::cmdLocate, 0);
358 ControlProtocolManager::instance().set_session (*this);
361 _end_location_is_free = true;
363 _end_location_is_free = false;
370 Session::raid_path () const
374 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
379 return path.substr (0, path.length() - 1); // drop final colon
383 Session::set_raid_path (string path)
385 /* public-access to setup_raid_path() */
387 setup_raid_path (path);
391 Session::setup_raid_path (string path)
393 string::size_type colon;
397 string::size_type len = path.length();
402 if (path.length() == 0) {
406 session_dirs.clear ();
408 for (string::size_type n = 0; n < len; ++n) {
409 if (path[n] == ':') {
416 /* no multiple search path, just one location (common case) */
420 session_dirs.push_back (sp);
427 if (fspath[fspath.length()-1] != '/') {
430 fspath += sound_dir (false);
432 AudioFileSource::set_search_path (fspath);
439 while ((colon = remaining.find_first_of (':')) != string::npos) {
442 sp.path = remaining.substr (0, colon);
443 session_dirs.push_back (sp);
445 /* add sounds to file search path */
448 if (fspath[fspath.length()-1] != '/') {
451 fspath += sound_dir (false);
454 remaining = remaining.substr (colon+1);
457 if (remaining.length()) {
464 if (fspath[fspath.length()-1] != '/') {
467 fspath += sound_dir (false);
470 session_dirs.push_back (sp);
473 /* set the AudioFileSource search path */
475 AudioFileSource::set_search_path (fspath);
477 /* reset the round-robin soundfile path thingie */
479 last_rr_session_dir = session_dirs.begin();
483 Session::create (bool& new_session, string* mix_template, jack_nframes_t initial_length)
487 new_session = !g_file_test (_path.c_str(), GFileTest (G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR));
489 if (g_mkdir_with_parents (_path.c_str(), 0755) < 0) {
490 error << string_compose(_("Session: cannot create session dir \"%1\" (%2)"), _path, strerror (errno)) << endmsg;
496 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
497 error << string_compose(_("Session: cannot create session peakfile dir \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
503 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
504 error << string_compose(_("Session: cannot create session sounds dir \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
508 dir = dead_sound_dir ();
510 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
511 error << string_compose(_("Session: cannot create session dead sounds dir \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
515 dir = automation_dir ();
517 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
518 error << string_compose(_("Session: cannot create session automation dir \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
523 /* check new_session so we don't overwrite an existing one */
527 std::string in_path = *mix_template;
529 ifstream in(in_path.c_str());
532 string out_path = _path;
534 out_path += _statefile_suffix;
536 ofstream out(out_path.c_str());
541 // okay, session is set up. Treat like normal saved
542 // session from now on.
548 error << string_compose (_("Could not open %1 for writing mix template"), out_path)
554 error << string_compose (_("Could not open mix template %1 for reading"), in_path)
561 warning << _("Session already exists. Not overwriting") << endmsg;
568 /* set initial start + end point */
570 start_location->set_end (0);
571 _locations.add (start_location);
573 end_location->set_end (initial_length);
574 _locations.add (end_location);
576 _state_of_the_state = Clean;
578 if (save_state (_current_snapshot_name)) {
579 save_history (_current_snapshot_name);
588 Session::load_diskstreams (const XMLNode& node)
591 XMLNodeConstIterator citer;
593 clist = node.children();
595 for (citer = clist.begin(); citer != clist.end(); ++citer) {
599 boost::shared_ptr<AudioDiskstream> dstream (new AudioDiskstream (*this, **citer));
600 add_diskstream (dstream);
603 catch (failed_constructor& err) {
604 error << _("Session: could not load diskstream via XML state") << endmsg;
613 Session::remove_pending_capture_state ()
618 xml_path += _current_snapshot_name;
619 xml_path += _pending_suffix;
621 unlink (xml_path.c_str());
625 Session::save_state (string snapshot_name, bool pending)
631 if (_state_of_the_state & CannotSave) {
635 tree.set_root (&get_state());
637 if (snapshot_name.empty()) {
638 snapshot_name = _current_snapshot_name;
644 xml_path += snapshot_name;
645 xml_path += _statefile_suffix;
649 // Make backup of state file
651 if ((access (xml_path.c_str(), F_OK) == 0) &&
652 (rename(xml_path.c_str(), bak_path.c_str()))) {
653 error << _("could not backup old state file, current state not saved.") << endmsg;
660 xml_path += snapshot_name;
661 xml_path += _pending_suffix;
665 cerr << "actually writing state\n";
667 if (!tree.write (xml_path)) {
668 error << string_compose (_("state could not be saved to %1"), xml_path) << endmsg;
670 /* don't leave a corrupt file lying around if it is
674 if (unlink (xml_path.c_str())) {
675 error << string_compose (_("could not remove corrupt state file %1"), xml_path) << endmsg;
678 if (rename (bak_path.c_str(), xml_path.c_str())) {
679 error << string_compose (_("could not restore state file from backup %1"), bak_path) << endmsg;
688 save_history(snapshot_name);
690 bool was_dirty = dirty();
692 _state_of_the_state = StateOfTheState (_state_of_the_state & ~Dirty);
695 DirtyChanged (); /* EMIT SIGNAL */
698 StateSaved (snapshot_name); /* EMIT SIGNAL */
705 Session::restore_state (string snapshot_name)
707 if (load_state (snapshot_name) == 0) {
708 set_state (*state_tree->root());
715 Session::load_state (string snapshot_name)
724 state_was_pending = false;
726 /* check for leftover pending state from a crashed capture attempt */
729 xmlpath += snapshot_name;
730 xmlpath += _pending_suffix;
732 if (!access (xmlpath.c_str(), F_OK)) {
734 /* there is pending state from a crashed capture attempt */
736 if (AskAboutPendingState()) {
737 state_was_pending = true;
741 if (!state_was_pending) {
744 xmlpath += snapshot_name;
745 xmlpath += _statefile_suffix;
748 if (access (xmlpath.c_str(), F_OK)) {
749 error << string_compose(_("%1: session state information file \"%2\" doesn't exist!"), _name, xmlpath) << endmsg;
753 state_tree = new XMLTree;
757 if (state_tree->read (xmlpath)) {
760 error << string_compose(_("Could not understand ardour file %1"), xmlpath) << endmsg;
769 Session::load_options (const XMLNode& node)
773 bool have_fade_msecs = false;
774 bool have_fade_steepness = false;
775 float fade_msecs = 0;
776 float fade_steepness = 0;
777 SlaveSource slave_src = None;
779 LocaleGuard lg (X_("POSIX"));
781 if ((child = find_named_node (node, "input-auto-connect")) != 0) {
782 if ((prop = child->property ("val")) != 0) {
783 sscanf (prop->value().c_str(), "%x", &x);
784 input_auto_connect = AutoConnectOption (x);
788 if ((child = find_named_node (node, "output-auto-connect")) != 0) {
789 if ((prop = child->property ("val")) != 0) {
790 sscanf (prop->value().c_str(), "%x", &x);
791 output_auto_connect = AutoConnectOption (x);
795 if ((child = find_named_node (node, "slave")) != 0) {
796 if ((prop = child->property ("type")) != 0) {
797 if (prop->value() == "none") {
799 } else if (prop->value() == "mtc") {
801 } else if (prop->value() == "jack") {
804 set_slave_source (slave_src, 0);
808 /* we cannot set edit mode if we are loading a session,
809 because it might destroy the playlist's positioning
812 if ((child = find_named_node (node, "edit-mode")) != 0) {
813 if ((prop = child->property ("val")) != 0) {
814 if (prop->value() == "slide") {
815 pending_edit_mode = Slide;
816 } else if (prop->value() == "splice") {
817 pending_edit_mode = Splice;
822 if ((child = find_named_node (node, "send-midi-timecode")) != 0) {
823 if ((prop = child->property ("val")) != 0) {
824 bool x = (prop->value() == "yes");
825 send_mtc = !x; /* force change in value */
829 if ((child = find_named_node (node, "send-midi-machine-control")) != 0) {
830 if ((prop = child->property ("val")) != 0) {
831 bool x = (prop->value() == "yes");
832 send_mmc = !x; /* force change in value */
833 set_send_mmc (prop->value() == "yes");
836 if ((child = find_named_node (node, "max-level")) != 0) {
837 if ((prop = child->property ("val")) != 0) {
838 max_level = atoi (prop->value().c_str());
841 if ((child = find_named_node (node, "min-level")) != 0) {
842 if ((prop = child->property ("val")) != 0) {
843 min_level = atoi (prop->value().c_str());
846 if ((child = find_named_node (node, "meter-hold")) != 0) {
847 if ((prop = child->property ("val")) != 0) {
848 _meter_hold = atof (prop->value().c_str());
851 if ((child = find_named_node (node, "meter-falloff")) != 0) {
852 if ((prop = child->property ("val")) != 0) {
853 _meter_falloff = atof (prop->value().c_str());
856 if ((child = find_named_node (node, "long-over-length")) != 0) {
857 if ((prop = child->property ("val")) != 0) {
858 over_length_long = atoi (prop->value().c_str());
861 if ((child = find_named_node (node, "short-over-length")) != 0) {
862 if ((prop = child->property ("val")) != 0) {
863 over_length_short = atoi (prop->value().c_str());
866 if ((child = find_named_node (node, "shuttle-speed-factor")) != 0) {
867 if ((prop = child->property ("val")) != 0) {
868 shuttle_speed_factor = atof (prop->value().c_str());
871 if ((child = find_named_node (node, "shuttle-speed-threshold")) != 0) {
872 if ((prop = child->property ("val")) != 0) {
873 shuttle_speed_threshold = atof (prop->value().c_str());
876 if ((child = find_named_node (node, "rf-speed")) != 0) {
877 if ((prop = child->property ("val")) != 0) {
878 rf_speed = atof (prop->value().c_str());
881 if ((child = find_named_node (node, "video-pullup")) != 0) {
882 if ((prop = child->property ("val")) != 0) {
883 set_video_pullup( atof (prop->value().c_str()) );
886 if ((child = find_named_node (node, "smpte-frames-per-second")) != 0) {
887 if ((prop = child->property ("val")) != 0) {
888 set_smpte_type( atof (prop->value().c_str()), smpte_drop_frames );
891 if ((child = find_named_node (node, "smpte-drop-frames")) != 0) {
892 if ((prop = child->property ("val")) != 0) {
893 set_smpte_type( smpte_frames_per_second, (prop->value() == "yes") );
896 if ((child = find_named_node (node, "smpte-offset")) != 0) {
897 if ((prop = child->property ("val")) != 0) {
898 set_smpte_offset( atoi (prop->value().c_str()) );
901 if ((child = find_named_node (node, "smpte-offset-negative")) != 0) {
902 if ((prop = child->property ("val")) != 0) {
903 set_smpte_offset_negative( (prop->value() == "yes") );
906 if ((child = find_named_node (node, "click-sound")) != 0) {
907 if ((prop = child->property ("val")) != 0) {
908 click_sound = prop->value();
911 if ((child = find_named_node (node, "click-emphasis-sound")) != 0) {
912 if ((prop = child->property ("val")) != 0) {
913 click_emphasis_sound = prop->value();
917 if ((child = find_named_node (node, "solo-model")) != 0) {
918 if ((prop = child->property ("val")) != 0) {
919 if (prop->value() == "SoloBus")
920 _solo_model = SoloBus;
922 _solo_model = InverseMute;
926 /* BOOLEAN OPTIONS */
928 if ((child = find_named_node (node, "auto-play")) != 0) {
929 if ((prop = child->property ("val")) != 0) {
930 set_auto_play (prop->value() == "yes");
933 if ((child = find_named_node (node, "auto-input")) != 0) {
934 if ((prop = child->property ("val")) != 0) {
935 set_auto_input (prop->value() == "yes");
938 if ((child = find_named_node (node, "seamless-loop")) != 0) {
939 if ((prop = child->property ("val")) != 0) {
940 set_seamless_loop (prop->value() == "yes");
943 if ((child = find_named_node (node, "punch-in")) != 0) {
944 if ((prop = child->property ("val")) != 0) {
945 set_punch_in (prop->value() == "yes");
948 if ((child = find_named_node (node, "punch-out")) != 0) {
949 if ((prop = child->property ("val")) != 0) {
950 set_punch_out (prop->value() == "yes");
953 if ((child = find_named_node (node, "auto-return")) != 0) {
954 if ((prop = child->property ("val")) != 0) {
955 set_auto_return (prop->value() == "yes");
958 if ((child = find_named_node (node, "send-mtc")) != 0) {
959 if ((prop = child->property ("val")) != 0) {
960 set_send_mtc (prop->value() == "yes");
963 if ((child = find_named_node (node, "mmc-control")) != 0) {
964 if ((prop = child->property ("val")) != 0) {
965 set_mmc_control (prop->value() == "yes");
968 if ((child = find_named_node (node, "midi-control")) != 0) {
969 if ((prop = child->property ("val")) != 0) {
970 set_midi_control (prop->value() == "yes");
973 if ((child = find_named_node (node, "midi-feedback")) != 0) {
974 if ((prop = child->property ("val")) != 0) {
975 set_midi_feedback (prop->value() == "yes");
978 // Legacy support for <recording-plugins>
979 if ((child = find_named_node (node, "recording-plugins")) != 0) {
980 if ((prop = child->property ("val")) != 0) {
981 set_do_not_record_plugins (prop->value() == "no");
984 if ((child = find_named_node (node, "do-not-record-plugins")) != 0) {
985 if ((prop = child->property ("val")) != 0) {
986 set_do_not_record_plugins (prop->value() == "yes");
989 if ((child = find_named_node (node, "crossfades-active")) != 0) {
990 if ((prop = child->property ("val")) != 0) {
991 set_crossfades_active (prop->value() == "yes");
994 if ((child = find_named_node (node, "audible-click")) != 0) {
995 if ((prop = child->property ("val")) != 0) {
996 set_clicking (prop->value() == "yes");
1000 if ((child = find_named_node (node, "end-marker-is-free")) != 0) {
1001 if ((prop = child->property ("val")) != 0) {
1002 _end_location_is_free = (prop->value() == "yes");
1006 if ((child = find_named_node (node, "layer-model")) != 0) {
1007 if ((prop = child->property ("val")) != 0) {
1008 if (prop->value() == X_("LaterHigher")) {
1009 set_layer_model (LaterHigher);
1010 } else if (prop->value() == X_("AddHigher")) {
1011 set_layer_model (AddHigher);
1013 set_layer_model (MoveAddHigher);
1018 if ((child = find_named_node (node, "xfade-model")) != 0) {
1019 if ((prop = child->property ("val")) != 0) {
1020 if (prop->value() == X_("Short")) {
1021 set_xfade_model (ShortCrossfade);
1023 set_xfade_model (FullCrossfade);
1028 if ((child = find_named_node (node, "short-xfade-length")) != 0) {
1029 if ((prop = child->property ("val")) != 0) {
1030 /* value is stored as a fractional seconds */
1031 float secs = atof (prop->value().c_str());
1032 Crossfade::set_short_xfade_length ((jack_nframes_t) floor (secs * frame_rate()));
1036 if ((child = find_named_node (node, "full-xfades-unmuted")) != 0) {
1037 if ((prop = child->property ("val")) != 0) {
1038 crossfades_active = (prop->value() == "yes");
1044 if ((child = find_named_node (node, "default-fade-steepness")) != 0) {
1045 if ((prop = child->property ("val")) != 0) {
1046 fade_steepness = atof (prop->value().c_str());
1047 have_fade_steepness = true;
1050 if ((child = find_named_node (node, "default-fade-msec")) != 0) {
1051 if ((prop = child->property ("val")) != 0) {
1052 fade_msecs = atof (prop->value().c_str());
1053 have_fade_msecs = true;
1057 if (have_fade_steepness || have_fade_msecs) {
1058 // set_default_fade (fade_steepness, fade_msecs);
1065 Session::get_options () const
1070 LocaleGuard lg (X_("POSIX"));
1072 opthead = new XMLNode ("Options");
1074 SlaveSource src = slave_source ();
1078 src_string = "none";
1084 src_string = "jack";
1087 child = opthead->add_child ("slave");
1088 child->add_property ("type", src_string);
1090 child = opthead->add_child ("send-midi-timecode");
1091 child->add_property ("val", send_midi_timecode?"yes":"no");
1093 child = opthead->add_child ("send-midi-machine-control");
1094 child->add_property ("val", send_midi_machine_control?"yes":"no");
1096 snprintf (buf, sizeof(buf)-1, "%x", (int) input_auto_connect);
1097 child = opthead->add_child ("input-auto-connect");
1098 child->add_property ("val", buf);
1100 snprintf (buf, sizeof(buf)-1, "%x", (int) output_auto_connect);
1101 child = opthead->add_child ("output-auto-connect");
1102 child->add_property ("val", buf);
1104 snprintf (buf, sizeof(buf)-1, "%d", max_level);
1105 child = opthead->add_child ("max-level");
1106 child->add_property ("val", buf);
1108 snprintf (buf, sizeof(buf)-1, "%d", min_level);
1109 child = opthead->add_child ("min-level");
1110 child->add_property ("val", buf);
1112 snprintf (buf, sizeof(buf)-1, "%f", _meter_hold);
1113 child = opthead->add_child ("meter-hold");
1114 child->add_property ("val", buf);
1116 snprintf (buf, sizeof(buf)-1, "%f", _meter_falloff);
1117 child = opthead->add_child ("meter-falloff");
1118 child->add_property ("val", buf);
1120 snprintf (buf, sizeof(buf)-1, "%u", over_length_long);
1121 child = opthead->add_child ("long-over-length");
1122 child->add_property ("val", buf);
1124 snprintf (buf, sizeof(buf)-1, "%u", over_length_short);
1125 child = opthead->add_child ("short-over-length");
1126 child->add_property ("val", buf);
1128 snprintf (buf, sizeof(buf)-1, "%f", shuttle_speed_factor);
1129 child = opthead->add_child ("shuttle-speed-factor");
1130 child->add_property ("val", buf);
1132 snprintf (buf, sizeof(buf)-1, "%f", shuttle_speed_threshold);
1133 child = opthead->add_child ("shuttle-speed-threshold");
1134 child->add_property ("val", buf);
1136 snprintf (buf, sizeof(buf)-1, "%f", rf_speed);
1137 child = opthead->add_child ("rf-speed");
1138 child->add_property ("val", buf);
1140 snprintf (buf, sizeof(buf)-1, "%.4f", video_pullup);
1141 child = opthead->add_child ("video-pullup");
1142 child->add_property ("val", buf);
1144 snprintf (buf, sizeof(buf)-1, "%.2f", smpte_frames_per_second);
1145 child = opthead->add_child ("smpte-frames-per-second");
1146 child->add_property ("val", buf);
1148 child = opthead->add_child ("smpte-drop-frames");
1149 child->add_property ("val", smpte_drop_frames ? "yes" : "no");
1151 snprintf (buf, sizeof(buf)-1, "%u", smpte_offset ());
1152 child = opthead->add_child ("smpte-offset");
1153 child->add_property ("val", buf);
1155 child = opthead->add_child ("smpte-offset-negative");
1156 child->add_property ("val", smpte_offset_negative () ? "yes" : "no");
1158 child = opthead->add_child ("edit-mode");
1159 switch (_edit_mode) {
1161 child->add_property ("val", "splice");
1165 child->add_property ("val", "slide");
1169 child = opthead->add_child ("auto-play");
1170 child->add_property ("val", get_auto_play () ? "yes" : "no");
1171 child = opthead->add_child ("auto-input");
1172 child->add_property ("val", get_auto_input () ? "yes" : "no");
1173 child = opthead->add_child ("seamless-loop");
1174 child->add_property ("val", get_seamless_loop () ? "yes" : "no");
1175 child = opthead->add_child ("punch-in");
1176 child->add_property ("val", get_punch_in () ? "yes" : "no");
1177 child = opthead->add_child ("punch-out");
1178 child->add_property ("val", get_punch_out () ? "yes" : "no");
1179 child = opthead->add_child ("all-safe");
1180 child->add_property ("val", get_all_safe () ? "yes" : "no");
1181 child = opthead->add_child ("auto-return");
1182 child->add_property ("val", get_auto_return () ? "yes" : "no");
1183 child = opthead->add_child ("mmc-control");
1184 child->add_property ("val", get_mmc_control () ? "yes" : "no");
1185 child = opthead->add_child ("midi-control");
1186 child->add_property ("val", get_midi_control () ? "yes" : "no");
1187 child = opthead->add_child ("midi-feedback");
1188 child->add_property ("val", get_midi_feedback () ? "yes" : "no");
1189 child = opthead->add_child ("do-not-record-plugins");
1190 child->add_property ("val", get_do_not_record_plugins () ? "yes" : "no");
1191 child = opthead->add_child ("auto-crossfade");
1192 child->add_property ("val", get_crossfades_active () ? "yes" : "no");
1193 child = opthead->add_child ("audible-click");
1194 child->add_property ("val", get_clicking () ? "yes" : "no");
1195 child = opthead->add_child ("end-marker-is-free");
1196 child->add_property ("val", _end_location_is_free ? "yes" : "no");
1198 if (click_sound.length()) {
1199 child = opthead->add_child ("click-sound");
1200 child->add_property ("val", click_sound);
1203 if (click_emphasis_sound.length()) {
1204 child = opthead->add_child ("click-emphasis-sound");
1205 child->add_property ("val", click_emphasis_sound);
1208 child = opthead->add_child ("solo-model");
1209 child->add_property ("val", _solo_model == SoloBus ? "SoloBus" : "InverseMute");
1211 child = opthead->add_child ("layer-model");
1212 switch (layer_model) {
1214 child->add_property ("val", X_("LaterHigher"));
1217 child->add_property ("val", X_("MoveAddHigher"));
1220 child->add_property ("val", X_("AddHigher"));
1224 child = opthead->add_child ("xfade-model");
1225 switch (xfade_model) {
1227 child->add_property ("val", X_("Full"));
1229 case ShortCrossfade:
1230 child->add_property ("val", X_("Short"));
1233 child = opthead->add_child ("short-xfade-length");
1234 /* store as fractions of a second */
1235 snprintf (buf, sizeof(buf)-1, "%f",
1236 (float) Crossfade::short_xfade_length() / frame_rate());
1237 child->add_property ("val", buf);
1239 child = opthead->add_child ("full-xfades-unmuted");
1240 child->add_property ("val", crossfades_active ? "yes" : "no");
1246 Session::get_state()
1252 Session::get_template()
1254 /* if we don't disable rec-enable, diskstreams
1255 will believe they need to store their capture
1256 sources in their state node.
1259 disable_record (false);
1261 return state(false);
1265 Session::state(bool full_state)
1267 XMLNode* node = new XMLNode("Session");
1270 // store libardour version, just in case
1272 snprintf(buf, sizeof(buf)-1, "%d.%d.%d",
1273 libardour_major_version, libardour_minor_version, libardour_micro_version);
1274 node->add_property("version", string(buf));
1276 /* store configuration settings */
1280 /* store the name */
1281 node->add_property ("name", _name);
1283 if (session_dirs.size() > 1) {
1287 vector<space_and_path>::iterator i = session_dirs.begin();
1288 vector<space_and_path>::iterator next;
1290 ++i; /* skip the first one */
1294 while (i != session_dirs.end()) {
1298 if (next != session_dirs.end()) {
1308 child = node->add_child ("Path");
1309 child->add_content (p);
1313 /* save the ID counter */
1315 snprintf (buf, sizeof (buf), "%" PRIu64, ID::counter());
1316 node->add_property ("id-counter", buf);
1318 /* various options */
1320 node->add_child_nocopy (get_options());
1322 child = node->add_child ("Sources");
1325 Glib::Mutex::Lock sl (audio_source_lock);
1327 for (AudioSourceList::iterator siter = audio_sources.begin(); siter != audio_sources.end(); ++siter) {
1329 /* Don't save information about AudioFileSources that are empty */
1331 boost::shared_ptr<AudioFileSource> fs;
1333 if ((fs = boost::dynamic_pointer_cast<AudioFileSource> (siter->second)) != 0) {
1334 boost::shared_ptr<DestructiveFileSource> dfs = boost::dynamic_pointer_cast<DestructiveFileSource> (fs);
1336 /* destructive file sources are OK if they are empty, because
1337 we will re-use them every time.
1341 if (fs->length() == 0) {
1347 child->add_child_nocopy (siter->second->get_state());
1351 child = node->add_child ("Regions");
1354 Glib::Mutex::Lock rl (region_lock);
1356 for (AudioRegionList::const_iterator i = audio_regions.begin(); i != audio_regions.end(); ++i) {
1358 /* only store regions not attached to playlists */
1360 if (i->second->playlist() == 0) {
1361 child->add_child_nocopy (i->second->state (true));
1366 child = node->add_child ("DiskStreams");
1369 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
1370 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
1371 if (!(*i)->hidden()) {
1372 child->add_child_nocopy ((*i)->get_state());
1377 node->add_child_nocopy (_locations.get_state());
1379 child = node->add_child ("Connections");
1381 Glib::Mutex::Lock lm (connection_lock);
1382 for (ConnectionList::iterator i = _connections.begin(); i != _connections.end(); ++i) {
1383 if (!(*i)->system_dependent()) {
1384 child->add_child_nocopy ((*i)->get_state());
1389 child = node->add_child ("Routes");
1391 boost::shared_ptr<RouteList> r = routes.reader ();
1393 RoutePublicOrderSorter cmp;
1394 RouteList public_order (*r);
1395 public_order.sort (cmp);
1397 for (RouteList::iterator i = public_order.begin(); i != public_order.end(); ++i) {
1398 if (!(*i)->hidden()) {
1400 child->add_child_nocopy ((*i)->get_state());
1402 child->add_child_nocopy ((*i)->get_template());
1409 child = node->add_child ("EditGroups");
1410 for (list<RouteGroup *>::iterator i = edit_groups.begin(); i != edit_groups.end(); ++i) {
1411 child->add_child_nocopy ((*i)->get_state());
1414 child = node->add_child ("MixGroups");
1415 for (list<RouteGroup *>::iterator i = mix_groups.begin(); i != mix_groups.end(); ++i) {
1416 child->add_child_nocopy ((*i)->get_state());
1419 child = node->add_child ("Playlists");
1420 for (PlaylistList::iterator i = playlists.begin(); i != playlists.end(); ++i) {
1421 if (!(*i)->hidden()) {
1422 if (!(*i)->empty()) {
1424 child->add_child_nocopy ((*i)->get_state());
1426 child->add_child_nocopy ((*i)->get_template());
1432 child = node->add_child ("UnusedPlaylists");
1433 for (PlaylistList::iterator i = unused_playlists.begin(); i != unused_playlists.end(); ++i) {
1434 if (!(*i)->hidden()) {
1435 if (!(*i)->empty()) {
1437 child->add_child_nocopy ((*i)->get_state());
1439 child->add_child_nocopy ((*i)->get_template());
1447 child = node->add_child ("Click");
1448 child->add_child_nocopy (_click_io->state (full_state));
1452 child = node->add_child ("NamedSelections");
1453 for (NamedSelectionList::iterator i = named_selections.begin(); i != named_selections.end(); ++i) {
1455 child->add_child_nocopy ((*i)->get_state());
1460 node->add_child_nocopy (_tempo_map->get_state());
1463 node->add_child_copy (*_extra_xml);
1470 Session::set_state (const XMLNode& node)
1474 const XMLProperty* prop;
1477 _state_of_the_state = StateOfTheState (_state_of_the_state|CannotSave);
1479 if (node.name() != X_("Session")){
1480 fatal << _("programming error: Session: incorrect XML node sent to set_state()") << endmsg;
1484 StateManager::prohibit_save ();
1486 if ((prop = node.property ("name")) != 0) {
1487 _name = prop->value ();
1490 if ((prop = node.property (X_("id-counter"))) != 0) {
1492 sscanf (prop->value().c_str(), "%" PRIu64, &x);
1493 ID::init_counter (x);
1495 /* old sessions used a timebased counter, so fake
1496 the startup ID counter based on a standard
1501 ID::init_counter (now);
1505 IO::disable_ports ();
1506 IO::disable_connecting ();
1508 /* Object loading order:
1525 if (use_config_midi_ports ()) {
1528 if ((child = find_named_node (node, "Path")) != 0) {
1529 /* XXX this XML content stuff horrible API design */
1530 string raid_path = _path + ':' + child->children().front()->content();
1531 setup_raid_path (raid_path);
1533 /* the path is already set */
1536 if ((child = find_named_node (node, "extra")) != 0) {
1537 _extra_xml = new XMLNode (*child);
1540 if ((child = find_named_node (node, "Options")) == 0) {
1541 error << _("Session: XML state has no options section") << endmsg;
1542 } else if (load_options (*child)) {
1545 if ((child = find_named_node (node, "Sources")) == 0) {
1546 error << _("Session: XML state has no sources section") << endmsg;
1548 } else if (load_sources (*child)) {
1552 if ((child = find_named_node (node, "Regions")) == 0) {
1553 error << _("Session: XML state has no Regions section") << endmsg;
1555 } else if (load_regions (*child)) {
1559 if ((child = find_named_node (node, "Playlists")) == 0) {
1560 error << _("Session: XML state has no playlists section") << endmsg;
1562 } else if (load_playlists (*child)) {
1566 if ((child = find_named_node (node, "UnusedPlaylists")) == 0) {
1568 } else if (load_unused_playlists (*child)) {
1572 if ((child = find_named_node (node, "NamedSelections")) != 0) {
1573 if (load_named_selections (*child)) {
1578 if ((child = find_named_node (node, "DiskStreams")) == 0) {
1579 error << _("Session: XML state has no diskstreams section") << endmsg;
1581 } else if (load_diskstreams (*child)) {
1585 if ((child = find_named_node (node, "Connections")) == 0) {
1586 error << _("Session: XML state has no connections section") << endmsg;
1588 } else if (load_connections (*child)) {
1592 if ((child = find_named_node (node, "Locations")) == 0) {
1593 error << _("Session: XML state has no locations section") << endmsg;
1595 } else if (_locations.set_state (*child)) {
1601 if ((location = _locations.auto_loop_location()) != 0) {
1602 set_auto_loop_location (location);
1605 if ((location = _locations.auto_punch_location()) != 0) {
1606 set_auto_punch_location (location);
1609 if ((location = _locations.end_location()) == 0) {
1610 _locations.add (end_location);
1612 delete end_location;
1613 end_location = location;
1616 if ((location = _locations.start_location()) == 0) {
1617 _locations.add (start_location);
1619 delete start_location;
1620 start_location = location;
1623 _locations.save_state (_("initial state"));
1625 if ((child = find_named_node (node, "EditGroups")) == 0) {
1626 error << _("Session: XML state has no edit groups section") << endmsg;
1628 } else if (load_edit_groups (*child)) {
1632 if ((child = find_named_node (node, "MixGroups")) == 0) {
1633 error << _("Session: XML state has no mix groups section") << endmsg;
1635 } else if (load_mix_groups (*child)) {
1639 if ((child = find_named_node (node, "TempoMap")) == 0) {
1640 error << _("Session: XML state has no Tempo Map section") << endmsg;
1642 } else if (_tempo_map->set_state (*child)) {
1646 if ((child = find_named_node (node, "Routes")) == 0) {
1647 error << _("Session: XML state has no routes section") << endmsg;
1649 } else if (load_routes (*child)) {
1653 if ((child = find_named_node (node, "Click")) == 0) {
1654 warning << _("Session: XML state has no click section") << endmsg;
1655 } else if (_click_io) {
1656 _click_io->set_state (*child);
1659 /* OK, now we can set edit mode */
1661 set_edit_mode (pending_edit_mode);
1663 /* here beginneth the second phase ... */
1665 StateReady (); /* EMIT SIGNAL */
1667 _state_of_the_state = Clean;
1669 StateManager::allow_save (_("initial state"), true);
1671 if (state_was_pending) {
1672 save_state (_current_snapshot_name);
1673 remove_pending_capture_state ();
1674 state_was_pending = false;
1680 /* we failed, re-enable state saving but don't actually save internal state */
1681 StateManager::allow_save (X_("ignored"), false);
1686 Session::load_routes (const XMLNode& node)
1689 XMLNodeConstIterator niter;
1690 RouteList new_routes;
1692 nlist = node.children();
1696 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1698 boost::shared_ptr<Route> route (XMLRouteFactory (**niter));
1701 error << _("Session: cannot create Route from XML description.") << endmsg;
1705 new_routes.push_back (route);
1708 add_routes (new_routes);
1713 boost::shared_ptr<Route>
1714 Session::XMLRouteFactory (const XMLNode& node)
1716 if (node.name() != "Route") {
1717 return boost::shared_ptr<Route> ((Route*) 0);
1720 if (node.property ("diskstream") != 0 || node.property ("diskstream-id") != 0) {
1721 boost::shared_ptr<Route> x (new AudioTrack (*this, node));
1724 boost::shared_ptr<Route> x (new Route (*this, node));
1730 Session::load_regions (const XMLNode& node)
1733 XMLNodeConstIterator niter;
1734 boost::shared_ptr<AudioRegion> region;
1736 nlist = node.children();
1740 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1741 if ((region = XMLRegionFactory (**niter, false)) == 0) {
1742 error << _("Session: cannot create Region from XML description.") << endmsg;
1749 boost::shared_ptr<AudioRegion>
1750 Session::XMLRegionFactory (const XMLNode& node, bool full)
1752 const XMLProperty* prop;
1753 boost::shared_ptr<Source> source;
1754 boost::shared_ptr<AudioSource> as;
1756 uint32_t nchans = 1;
1759 if (node.name() != X_("Region")) {
1760 return boost::shared_ptr<AudioRegion>();
1763 if ((prop = node.property (X_("channels"))) != 0) {
1764 nchans = atoi (prop->value().c_str());
1768 if ((prop = node.property (X_("source-0"))) == 0) {
1769 if ((prop = node.property ("source")) == 0) {
1770 error << _("Session: XMLNode describing a AudioRegion is incomplete (no source)") << endmsg;
1771 return boost::shared_ptr<AudioRegion>();
1775 PBD::ID s_id (prop->value());
1777 if ((source = source_by_id (s_id)) == 0) {
1778 error << string_compose(_("Session: XMLNode describing a AudioRegion references an unknown source id =%1"), s_id) << endmsg;
1779 return boost::shared_ptr<AudioRegion>();
1782 as = boost::dynamic_pointer_cast<AudioSource>(source);
1784 error << string_compose(_("Session: XMLNode describing a AudioRegion references a non-audio source id =%1"), s_id) << endmsg;
1785 return boost::shared_ptr<AudioRegion>();
1788 sources.push_back (as);
1790 /* pickup other channels */
1792 for (uint32_t n=1; n < nchans; ++n) {
1793 snprintf (buf, sizeof(buf), X_("source-%d"), n);
1794 if ((prop = node.property (buf)) != 0) {
1796 PBD::ID id2 (prop->value());
1798 if ((source = source_by_id (id2)) == 0) {
1799 error << string_compose(_("Session: XMLNode describing a AudioRegion references an unknown source id =%1"), id2) << endmsg;
1800 return boost::shared_ptr<AudioRegion>();
1803 as = boost::dynamic_pointer_cast<AudioSource>(source);
1805 error << string_compose(_("Session: XMLNode describing a AudioRegion references a non-audio source id =%1"), id2) << endmsg;
1806 return boost::shared_ptr<AudioRegion>();
1808 sources.push_back (as);
1813 boost::shared_ptr<AudioRegion> region (boost::dynamic_pointer_cast<AudioRegion> (RegionFactory::create (sources, node)));
1818 catch (failed_constructor& err) {
1819 return boost::shared_ptr<AudioRegion>();
1824 Session::get_sources_as_xml ()
1827 XMLNode* node = new XMLNode (X_("Sources"));
1828 Glib::Mutex::Lock lm (audio_source_lock);
1830 for (AudioSourceList::iterator i = audio_sources.begin(); i != audio_sources.end(); ++i) {
1831 node->add_child_nocopy (i->second->get_state());
1834 /* XXX get MIDI and other sources here */
1840 Session::path_from_region_name (string name, string identifier)
1842 char buf[PATH_MAX+1];
1844 string dir = discover_best_sound_dir ();
1846 for (n = 0; n < 999999; ++n) {
1847 if (identifier.length()) {
1848 snprintf (buf, sizeof(buf), "%s/%s%s%" PRIu32 ".wav", dir.c_str(), name.c_str(),
1849 identifier.c_str(), n);
1851 snprintf (buf, sizeof(buf), "%s/%s-%" PRIu32 ".wav", dir.c_str(), name.c_str(), n);
1853 if (access (buf, F_OK) != 0) {
1863 Session::load_sources (const XMLNode& node)
1866 XMLNodeConstIterator niter;
1867 boost::shared_ptr<Source> source;
1869 nlist = node.children();
1873 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1875 if ((source = XMLSourceFactory (**niter)) == 0) {
1876 error << _("Session: cannot create Source from XML description.") << endmsg;
1883 boost::shared_ptr<Source>
1884 Session::XMLSourceFactory (const XMLNode& node)
1886 if (node.name() != "Source") {
1887 return boost::shared_ptr<Source>();
1891 return SourceFactory::create (*this, node);
1894 catch (failed_constructor& err) {
1895 error << _("Found a sound file that cannot be used by Ardour. Talk to the progammers.") << endmsg;
1896 return boost::shared_ptr<Source>();
1901 Session::save_template (string template_name)
1904 string xml_path, bak_path, template_path;
1906 if (_state_of_the_state & CannotSave) {
1911 string dir = template_dir();
1913 if ((dp = opendir (dir.c_str()))) {
1916 if (g_mkdir_with_parents (dir.c_str(), S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH)) {
1917 error << string_compose(_("Could not create mix templates directory \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
1922 tree.set_root (&get_template());
1925 xml_path += template_name;
1926 xml_path += _template_suffix;
1928 ifstream in(xml_path.c_str());
1931 warning << string_compose(_("Template \"%1\" already exists - new version not created"), template_name) << endmsg;
1937 if (!tree.write (xml_path)) {
1938 error << _("mix template not saved") << endmsg;
1946 Session::rename_template (string old_name, string new_name)
1948 string old_path = template_dir() + old_name + _template_suffix;
1949 string new_path = template_dir() + new_name + _template_suffix;
1951 return rename (old_path.c_str(), new_path.c_str());
1955 Session::delete_template (string name)
1957 string template_path = template_dir();
1958 template_path += name;
1959 template_path += _template_suffix;
1961 return remove (template_path.c_str());
1965 Session::refresh_disk_space ()
1968 struct statfs statfsbuf;
1969 vector<space_and_path>::iterator i;
1970 Glib::Mutex::Lock lm (space_lock);
1973 /* get freespace on every FS that is part of the session path */
1975 _total_free_4k_blocks = 0;
1977 for (i = session_dirs.begin(); i != session_dirs.end(); ++i) {
1978 statfs ((*i).path.c_str(), &statfsbuf);
1980 scale = statfsbuf.f_bsize/4096.0;
1982 (*i).blocks = (uint32_t) floor (statfsbuf.f_bavail * scale);
1983 _total_free_4k_blocks += (*i).blocks;
1989 Session::ensure_sound_dir (string path, string& result)
1994 /* Ensure that the parent directory exists */
1996 if (g_mkdir_with_parents (path.c_str(), 0775)) {
1997 error << string_compose(_("cannot create session directory \"%1\"; ignored"), path) << endmsg;
2001 /* Ensure that the sounds directory exists */
2005 result += sound_dir_name;
2007 if (g_mkdir_with_parents (result.c_str(), 0775)) {
2008 error << string_compose(_("cannot create sounds directory \"%1\"; ignored"), result) << endmsg;
2014 dead += dead_sound_dir_name;
2016 if (g_mkdir_with_parents (dead.c_str(), 0775)) {
2017 error << string_compose(_("cannot create dead sounds directory \"%1\"; ignored"), dead) << endmsg;
2023 peak += peak_dir_name;
2025 if (g_mkdir_with_parents (peak.c_str(), 0775)) {
2026 error << string_compose(_("cannot create peak file directory \"%1\"; ignored"), peak) << endmsg;
2030 /* callers expect this to be terminated ... */
2037 Session::discover_best_sound_dir (bool destructive)
2039 vector<space_and_path>::iterator i;
2042 /* handle common case without system calls */
2044 if (session_dirs.size() == 1) {
2048 /* OK, here's the algorithm we're following here:
2050 We want to select which directory to use for
2051 the next file source to be created. Ideally,
2052 we'd like to use a round-robin process so as to
2053 get maximum performance benefits from splitting
2054 the files across multiple disks.
2056 However, in situations without much diskspace, an
2057 RR approach may end up filling up a filesystem
2058 with new files while others still have space.
2059 Its therefore important to pay some attention to
2060 the freespace in the filesystem holding each
2061 directory as well. However, if we did that by
2062 itself, we'd keep creating new files in the file
2063 system with the most space until it was as full
2064 as all others, thus negating any performance
2065 benefits of this RAID-1 like approach.
2067 So, we use a user-configurable space threshold. If
2068 there are at least 2 filesystems with more than this
2069 much space available, we use RR selection between them.
2070 If not, then we pick the filesystem with the most space.
2072 This gets a good balance between the two
2076 refresh_disk_space ();
2078 int free_enough = 0;
2080 for (i = session_dirs.begin(); i != session_dirs.end(); ++i) {
2081 if ((*i).blocks * 4096 >= Config->get_disk_choice_space_threshold()) {
2086 if (free_enough >= 2) {
2088 bool found_it = false;
2090 /* use RR selection process, ensuring that the one
2094 i = last_rr_session_dir;
2097 if (++i == session_dirs.end()) {
2098 i = session_dirs.begin();
2101 if ((*i).blocks * 4096 >= Config->get_disk_choice_space_threshold()) {
2102 if (ensure_sound_dir ((*i).path, result) == 0) {
2103 last_rr_session_dir = i;
2109 } while (i != last_rr_session_dir);
2112 result = sound_dir();
2117 /* pick FS with the most freespace (and that
2118 seems to actually work ...)
2121 vector<space_and_path> sorted;
2122 space_and_path_ascending_cmp cmp;
2124 sorted = session_dirs;
2125 sort (sorted.begin(), sorted.end(), cmp);
2127 for (i = sorted.begin(); i != sorted.end(); ++i) {
2128 if (ensure_sound_dir ((*i).path, result) == 0) {
2129 last_rr_session_dir = i;
2134 /* if the above fails, fall back to the most simplistic solution */
2136 if (i == sorted.end()) {
2145 Session::load_playlists (const XMLNode& node)
2148 XMLNodeConstIterator niter;
2151 nlist = node.children();
2155 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2157 if ((playlist = XMLPlaylistFactory (**niter)) == 0) {
2158 error << _("Session: cannot create Playlist from XML description.") << endmsg;
2166 Session::load_unused_playlists (const XMLNode& node)
2169 XMLNodeConstIterator niter;
2172 nlist = node.children();
2176 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2178 if ((playlist = XMLPlaylistFactory (**niter)) == 0) {
2179 error << _("Session: cannot create Playlist from XML description.") << endmsg;
2183 // now manually untrack it
2185 track_playlist (playlist, false);
2193 Session::XMLPlaylistFactory (const XMLNode& node)
2196 return new AudioPlaylist (*this, node);
2199 catch (failed_constructor& err) {
2205 Session::load_named_selections (const XMLNode& node)
2208 XMLNodeConstIterator niter;
2211 nlist = node.children();
2215 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2217 if ((ns = XMLNamedSelectionFactory (**niter)) == 0) {
2218 error << _("Session: cannot create Named Selection from XML description.") << endmsg;
2226 Session::XMLNamedSelectionFactory (const XMLNode& node)
2229 return new NamedSelection (*this, node);
2232 catch (failed_constructor& err) {
2238 Session::dead_sound_dir () const
2241 res += dead_sound_dir_name;
2247 Session::sound_dir (bool with_path) const
2249 /* support old session structure */
2251 struct stat statbuf;
2258 old += sound_dir_name;
2261 if (stat (old.c_str(), &statbuf) == 0) {
2271 res += interchange_dir_name;
2273 res += legalize_for_path (_name);
2275 res += sound_dir_name;
2282 Session::peak_dir () const
2285 res += peak_dir_name;
2291 Session::automation_dir () const
2294 res += "automation/";
2299 Session::template_dir ()
2301 string path = get_user_ardour_path();
2302 path += "templates/";
2308 Session::suffixed_search_path (string suffix, bool data)
2312 path += get_user_ardour_path();
2313 if (path[path.length()-1] != ':') {
2318 path += get_system_data_path();
2320 path += get_system_module_path();
2323 vector<string> split_path;
2325 split (path, split_path, ':');
2328 for (vector<string>::iterator i = split_path.begin(); i != split_path.end(); ++i) {
2333 if (distance (i, split_path.end()) != 1) {
2342 Session::template_path ()
2344 return suffixed_search_path (X_("templates"), true);
2348 Session::control_protocol_path ()
2350 return suffixed_search_path (X_("surfaces"), false);
2354 Session::load_connections (const XMLNode& node)
2356 XMLNodeList nlist = node.children();
2357 XMLNodeConstIterator niter;
2361 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2362 if ((*niter)->name() == "InputConnection") {
2363 add_connection (new ARDOUR::InputConnection (**niter));
2364 } else if ((*niter)->name() == "OutputConnection") {
2365 add_connection (new ARDOUR::OutputConnection (**niter));
2367 error << string_compose(_("Unknown node \"%1\" found in Connections list from state file"), (*niter)->name()) << endmsg;
2376 Session::load_edit_groups (const XMLNode& node)
2378 return load_route_groups (node, true);
2382 Session::load_mix_groups (const XMLNode& node)
2384 return load_route_groups (node, false);
2388 Session::load_route_groups (const XMLNode& node, bool edit)
2390 XMLNodeList nlist = node.children();
2391 XMLNodeConstIterator niter;
2396 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2397 if ((*niter)->name() == "RouteGroup") {
2399 rg = add_edit_group ("");
2400 rg->set_state (**niter);
2402 rg = add_mix_group ("");
2403 rg->set_state (**niter);
2412 state_file_filter (const string &str, void *arg)
2414 return (str.length() > strlen(Session::statefile_suffix()) &&
2415 str.find (Session::statefile_suffix()) == (str.length() - strlen (Session::statefile_suffix())));
2419 bool operator()(const string* a, const string* b) {
2425 remove_end(string* state)
2427 string statename(*state);
2429 string::size_type start,end;
2430 if ((start = statename.find_last_of ('/')) != string::npos) {
2431 statename = statename.substr (start+1);
2434 if ((end = statename.rfind(".ardour")) == string::npos) {
2435 end = statename.length();
2438 return new string(statename.substr (0, end));
2442 Session::possible_states (string path)
2444 PathScanner scanner;
2445 vector<string*>* states = scanner (path, state_file_filter, 0, false, false);
2447 transform(states->begin(), states->end(), states->begin(), remove_end);
2450 sort (states->begin(), states->end(), cmp);
2456 Session::possible_states () const
2458 return possible_states(_path);
2462 Session::auto_save()
2464 save_state (_current_snapshot_name);
2468 Session::add_edit_group (string name)
2470 RouteGroup* rg = new RouteGroup (*this, name);
2471 edit_groups.push_back (rg);
2472 edit_group_added (rg); /* EMIT SIGNAL */
2478 Session::add_mix_group (string name)
2480 RouteGroup* rg = new RouteGroup (*this, name, RouteGroup::Relative);
2481 mix_groups.push_back (rg);
2482 mix_group_added (rg); /* EMIT SIGNAL */
2488 Session::remove_edit_group (RouteGroup& rg)
2490 list<RouteGroup*>::iterator i;
2492 if ((i = find (edit_groups.begin(), edit_groups.end(), &rg)) != edit_groups.end()) {
2493 (*i)->apply (&Route::drop_edit_group, this);
2494 edit_groups.erase (i);
2495 edit_group_removed (); /* EMIT SIGNAL */
2502 Session::remove_mix_group (RouteGroup& rg)
2504 list<RouteGroup*>::iterator i;
2506 if ((i = find (mix_groups.begin(), mix_groups.end(), &rg)) != mix_groups.end()) {
2507 (*i)->apply (&Route::drop_mix_group, this);
2508 mix_groups.erase (i);
2509 mix_group_removed (); /* EMIT SIGNAL */
2516 Session::mix_group_by_name (string name)
2518 list<RouteGroup *>::iterator i;
2520 for (i = mix_groups.begin(); i != mix_groups.end(); ++i) {
2521 if ((*i)->name() == name) {
2529 Session::edit_group_by_name (string name)
2531 list<RouteGroup *>::iterator i;
2533 for (i = edit_groups.begin(); i != edit_groups.end(); ++i) {
2534 if ((*i)->name() == name) {
2542 Session::set_meter_hold (float val)
2545 MeterHoldChanged(); // emit
2549 Session::set_meter_falloff (float val)
2551 _meter_falloff = val;
2552 MeterFalloffChanged(); // emit
2557 Session::begin_reversible_command (string name)
2559 current_trans = new UndoTransaction;
2560 current_trans->set_name (name);
2564 Session::commit_reversible_command (Command *cmd)
2569 current_trans->add_command (cmd);
2572 gettimeofday (&now, 0);
2573 current_trans->set_timestamp (now);
2575 history.add (current_trans);
2578 Session::GlobalRouteBooleanState
2579 Session::get_global_route_boolean (bool (Route::*method)(void) const)
2581 GlobalRouteBooleanState s;
2582 boost::shared_ptr<RouteList> r = routes.reader ();
2584 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
2585 if (!(*i)->hidden()) {
2586 RouteBooleanState v;
2589 Route* r = (*i).get();
2590 v.second = (r->*method)();
2599 Session::GlobalRouteMeterState
2600 Session::get_global_route_metering ()
2602 GlobalRouteMeterState s;
2603 boost::shared_ptr<RouteList> r = routes.reader ();
2605 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
2606 if (!(*i)->hidden()) {
2610 v.second = (*i)->meter_point();
2620 Session::set_global_route_metering (GlobalRouteMeterState s, void* arg)
2622 for (GlobalRouteMeterState::iterator i = s.begin(); i != s.end(); ++i) {
2623 i->first->set_meter_point (i->second, arg);
2628 Session::set_global_route_boolean (GlobalRouteBooleanState s, void (Route::*method)(bool, void*), void* arg)
2630 for (GlobalRouteBooleanState::iterator i = s.begin(); i != s.end(); ++i) {
2631 Route* r = i->first.get();
2632 (r->*method) (i->second, arg);
2637 Session::set_global_mute (GlobalRouteBooleanState s, void* src)
2639 set_global_route_boolean (s, &Route::set_mute, src);
2643 Session::set_global_solo (GlobalRouteBooleanState s, void* src)
2645 set_global_route_boolean (s, &Route::set_solo, src);
2649 Session::set_global_record_enable (GlobalRouteBooleanState s, void* src)
2651 set_global_route_boolean (s, &Route::set_record_enable, src);
2656 Session::global_mute_memento (void* src)
2658 return sigc::bind (mem_fun (*this, &Session::set_global_mute), get_global_route_boolean (&Route::muted), src);
2662 Session::global_metering_memento (void* src)
2664 return sigc::bind (mem_fun (*this, &Session::set_global_route_metering), get_global_route_metering (), src);
2668 Session::global_solo_memento (void* src)
2670 return sigc::bind (mem_fun (*this, &Session::set_global_solo), get_global_route_boolean (&Route::soloed), src);
2674 Session::global_record_enable_memento (void* src)
2676 return sigc::bind (mem_fun (*this, &Session::set_global_record_enable), get_global_route_boolean (&Route::record_enabled), src);
2681 template_filter (const string &str, void *arg)
2683 return (str.length() > strlen(Session::template_suffix()) &&
2684 str.find (Session::template_suffix()) == (str.length() - strlen (Session::template_suffix())));
2688 Session::get_template_list (list<string> &template_names)
2690 vector<string *> *templates;
2691 PathScanner scanner;
2694 path = template_path ();
2696 templates = scanner (path, template_filter, 0, false, true);
2698 vector<string*>::iterator i;
2699 for (i = templates->begin(); i != templates->end(); ++i) {
2700 string fullpath = *(*i);
2703 start = fullpath.find_last_of ('/') + 1;
2704 if ((end = fullpath.find_last_of ('.')) <0) {
2705 end = fullpath.length();
2708 template_names.push_back(fullpath.substr(start, (end-start)));
2713 Session::read_favorite_dirs (FavoriteDirs & favs)
2715 string path = get_user_ardour_path();
2716 path += "/favorite_dirs";
2718 ifstream fav (path.c_str());
2723 if (errno != ENOENT) {
2724 //error << string_compose (_("cannot open favorite file %1 (%2)"), path, strerror (errno)) << endmsg;
2735 getline(fav, newfav);
2741 favs.push_back (newfav);
2748 Session::write_favorite_dirs (FavoriteDirs & favs)
2750 string path = get_user_ardour_path();
2751 path += "/favorite_dirs";
2753 ofstream fav (path.c_str());
2759 for (FavoriteDirs::iterator i = favs.begin(); i != favs.end(); ++i) {
2760 fav << (*i) << endl;
2767 accept_all_non_peak_files (const string& path, void *arg)
2769 return (path.length() > 5 && path.find (".peak") != (path.length() - 5));
2773 accept_all_state_files (const string& path, void *arg)
2775 return (path.length() > 7 && path.find (".ardour") == (path.length() - 7));
2779 Session::find_all_sources (string path, set<string>& result)
2784 if (!tree.read (path)) {
2788 if ((node = find_named_node (*tree.root(), "Sources")) == 0) {
2793 XMLNodeConstIterator niter;
2795 nlist = node->children();
2799 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2803 if ((prop = (*niter)->property (X_("name"))) == 0) {
2807 if (prop->value()[0] == '/') {
2808 /* external file, ignore */
2812 string path = _path; /* /-terminated */
2813 path += sound_dir_name;
2815 path += prop->value();
2817 result.insert (path);
2824 Session::find_all_sources_across_snapshots (set<string>& result, bool exclude_this_snapshot)
2826 PathScanner scanner;
2827 vector<string*>* state_files;
2829 string this_snapshot_path;
2835 if (ripped[ripped.length()-1] == '/') {
2836 ripped = ripped.substr (0, ripped.length() - 1);
2839 state_files = scanner (ripped, accept_all_state_files, (void *) 0, false, true);
2841 if (state_files == 0) {
2846 this_snapshot_path = _path;
2847 this_snapshot_path += _current_snapshot_name;
2848 this_snapshot_path += _statefile_suffix;
2850 for (vector<string*>::iterator i = state_files->begin(); i != state_files->end(); ++i) {
2852 if (exclude_this_snapshot && **i == this_snapshot_path) {
2856 if (find_all_sources (**i, result) < 0) {
2865 Session::cleanup_sources (Session::cleanup_report& rep)
2867 vector<boost::shared_ptr<Source> > dead_sources;
2868 vector<Playlist*> playlists_tbd;
2869 PathScanner scanner;
2871 vector<space_and_path>::iterator i;
2872 vector<space_and_path>::iterator nexti;
2873 vector<string*>* soundfiles;
2874 vector<string> unused;
2875 set<string> all_sources;
2880 _state_of_the_state = (StateOfTheState) (_state_of_the_state | InCleanup);
2882 /* step 1: consider deleting all unused playlists */
2884 for (PlaylistList::iterator x = unused_playlists.begin(); x != unused_playlists.end(); ++x) {
2887 status = AskAboutPlaylistDeletion (*x);
2896 playlists_tbd.push_back (*x);
2900 /* leave it alone */
2905 /* now delete any that were marked for deletion */
2907 for (vector<Playlist*>::iterator x = playlists_tbd.begin(); x != playlists_tbd.end(); ++x) {
2908 PlaylistList::iterator foo;
2910 if ((foo = unused_playlists.find (*x)) != unused_playlists.end()) {
2911 unused_playlists.erase (foo);
2916 /* step 2: clear the undo/redo history for all playlists */
2918 for (PlaylistList::iterator x = playlists.begin(); x != playlists.end(); ++x) {
2919 (*x)->drop_all_states ();
2922 /* step 3: find all un-referenced sources */
2927 for (AudioSourceList::iterator i = audio_sources.begin(); i != audio_sources.end(); ) {
2929 AudioSourceList::iterator tmp;
2934 /* only remove files that are not in use and have some size
2935 to them. otherwise we remove the current "nascent"
2939 if (i->second.use_count() == 1 && i->second->length() > 0) {
2940 dead_sources.push_back (i->second);
2942 /* remove this source from our own list to avoid us
2943 adding it to the list of all sources below
2946 audio_sources.erase (i);
2952 /* Step 4: get rid of all regions in the region list that use any dead sources
2953 in case the sources themselves don't go away (they might be referenced in
2957 for (vector<boost::shared_ptr<Source> >::iterator i = dead_sources.begin(); i != dead_sources.end();++i) {
2959 for (AudioRegionList::iterator r = audio_regions.begin(); r != audio_regions.end(); ) {
2960 AudioRegionList::iterator tmp;
2961 boost::shared_ptr<AudioRegion> ar;
2968 for (uint32_t n = 0; n < ar->n_channels(); ++n) {
2969 if (ar->source (n) == (*i)) {
2970 /* this region is dead */
2979 /* build a list of all the possible sound directories for the session */
2981 for (i = session_dirs.begin(); i != session_dirs.end(); ) {
2986 sound_path += (*i).path;
2987 sound_path += sound_dir_name;
2989 if (nexti != session_dirs.end()) {
2996 /* now do the same thing for the files that ended up in the sounds dir(s)
2997 but are not referenced as sources in any snapshot.
3000 soundfiles = scanner (sound_path, accept_all_non_peak_files, (void *) 0, false, true);
3002 if (soundfiles == 0) {
3006 /* find all sources, but don't use this snapshot because the
3007 state file on disk still references sources we may have already
3011 find_all_sources_across_snapshots (all_sources, true);
3013 /* add our current source list
3016 for (AudioSourceList::iterator i = audio_sources.begin(); i != audio_sources.end(); ++i) {
3017 boost::shared_ptr<AudioFileSource> fs;
3019 if ((fs = boost::dynamic_pointer_cast<AudioFileSource> (i->second)) != 0) {
3020 all_sources.insert (fs->path());
3024 for (vector<string*>::iterator x = soundfiles->begin(); x != soundfiles->end(); ++x) {
3029 for (set<string>::iterator i = all_sources.begin(); i != all_sources.end(); ++i) {
3039 unused.push_back (spath);
3043 /* now try to move all unused files into the "dead_sounds" directory(ies) */
3045 for (vector<string>::iterator x = unused.begin(); x != unused.end(); ++x) {
3046 struct stat statbuf;
3048 rep.paths.push_back (*x);
3049 if (stat ((*x).c_str(), &statbuf) == 0) {
3050 rep.space += statbuf.st_size;
3055 /* don't move the file across filesystems, just
3056 stick it in the `dead_sound_dir_name' directory
3057 on whichever filesystem it was already on.
3060 newpath = Glib::path_get_dirname (*x);
3061 newpath = Glib::path_get_dirname (newpath);
3064 newpath += dead_sound_dir_name;
3066 newpath += Glib::path_get_basename ((*x));
3068 if (access (newpath.c_str(), F_OK) == 0) {
3070 /* the new path already exists, try versioning */
3072 char buf[PATH_MAX+1];
3076 snprintf (buf, sizeof (buf), "%s.%d", newpath.c_str(), version);
3079 while (access (newpath_v.c_str(), F_OK) == 0 && version < 999) {
3080 snprintf (buf, sizeof (buf), "%s.%d", newpath.c_str(), ++version);
3084 if (version == 999) {
3085 error << string_compose (_("there are already 1000 files with names like %1; versioning discontinued"),
3089 newpath = newpath_v;
3094 /* it doesn't exist, or we can't read it or something */
3098 if (::rename ((*x).c_str(), newpath.c_str()) != 0) {
3099 error << string_compose (_("cannot rename audio file source from %1 to %2 (%3)"),
3100 (*x), newpath, strerror (errno))
3106 /* see if there an easy to find peakfile for this file, and remove it.
3109 string peakpath = (*x).substr (0, (*x).find_last_of ('.'));
3110 peakpath += ".peak";
3112 if (access (peakpath.c_str(), W_OK) == 0) {
3113 if (::unlink (peakpath.c_str()) != 0) {
3114 error << string_compose (_("cannot remove peakfile %1 for %2 (%3)"),
3115 peakpath, _path, strerror (errno))
3117 /* try to back out */
3118 rename (newpath.c_str(), _path.c_str());
3127 /* dump the history list */
3131 /* save state so we don't end up a session file
3132 referring to non-existent sources.
3138 _state_of_the_state = (StateOfTheState) (_state_of_the_state & ~InCleanup);
3143 Session::cleanup_trash_sources (Session::cleanup_report& rep)
3145 vector<space_and_path>::iterator i;
3146 string dead_sound_dir;
3147 struct dirent* dentry;
3148 struct stat statbuf;
3154 for (i = session_dirs.begin(); i != session_dirs.end(); ++i) {
3156 dead_sound_dir = (*i).path;
3157 dead_sound_dir += dead_sound_dir_name;
3159 if ((dead = opendir (dead_sound_dir.c_str())) == 0) {
3163 while ((dentry = readdir (dead)) != 0) {
3165 /* avoid '.' and '..' */
3167 if ((dentry->d_name[0] == '.' && dentry->d_name[1] == '\0') ||
3168 (dentry->d_name[2] == '\0' && dentry->d_name[0] == '.' && dentry->d_name[1] == '.')) {
3174 fullpath = dead_sound_dir;
3176 fullpath += dentry->d_name;
3178 if (stat (fullpath.c_str(), &statbuf)) {
3182 if (!S_ISREG (statbuf.st_mode)) {
3186 if (unlink (fullpath.c_str())) {
3187 error << string_compose (_("cannot remove dead sound file %1 (%2)"),
3188 fullpath, strerror (errno))
3192 rep.paths.push_back (dentry->d_name);
3193 rep.space += statbuf.st_size;
3204 Session::set_dirty ()
3206 bool was_dirty = dirty();
3208 _state_of_the_state = StateOfTheState (_state_of_the_state | Dirty);
3211 DirtyChanged(); /* EMIT SIGNAL */
3217 Session::set_clean ()
3219 bool was_dirty = dirty();
3221 _state_of_the_state = Clean;
3224 DirtyChanged(); /* EMIT SIGNAL */
3229 Session::add_controllable (Controllable* c)
3231 Glib::Mutex::Lock lm (controllables_lock);
3232 controllables.push_back (c);
3236 Session::remove_controllable (Controllable* c)
3238 if (_state_of_the_state | Deletion) {
3242 Glib::Mutex::Lock lm (controllables_lock);
3243 controllables.remove (c);
3247 Session::controllable_by_id (const PBD::ID& id)
3249 Glib::Mutex::Lock lm (controllables_lock);
3251 for (Controllables::iterator i = controllables.begin(); i != controllables.end(); ++i) {
3252 if ((*i)->id() == id) {
3261 Session::add_instant_xml (XMLNode& node, const std::string& dir)
3263 Stateful::add_instant_xml (node, dir);
3264 Config->add_instant_xml (node, get_user_ardour_path());
3269 Session::save_history (string snapshot_name)
3275 tree.set_root (&history.get_state());
3277 if (snapshot_name.empty()) {
3278 snapshot_name = _current_snapshot_name;
3281 xml_path = _path + snapshot_name + ".history";
3283 bak_path = xml_path + ".bak";
3285 if ((access (xml_path.c_str(), F_OK) == 0) &&
3286 (rename (xml_path.c_str(), bak_path.c_str())))
3288 error << _("could not backup old history file, current history not saved.") << endmsg;
3292 cerr << "actually writing history\n";
3294 if (!tree.write (xml_path))
3296 error << string_compose (_("history could not be saved to %1"), xml_path) << endmsg;
3298 /* don't leave a corrupt file lying around if it is
3302 if (unlink (xml_path.c_str()))
3304 error << string_compose (_("could not remove corrupt history file %1"), xml_path) << endmsg;
3306 if (rename (bak_path.c_str(), xml_path.c_str()))
3308 error << string_compose (_("could not restore history file from backup %1"), bak_path) << endmsg;
3319 Session::restore_history (string snapshot_name)
3325 xmlpath = _path + snapshot_name + ".history";
3326 cerr << string_compose(_("Loading history from '%1'."), xmlpath) << endmsg;
3328 if (access (xmlpath.c_str(), F_OK)) {
3329 error << string_compose(_("%1: session history file \"%2\" doesn't exist!"), _name, xmlpath) << endmsg;
3333 if (!tree.read (xmlpath)) {
3334 error << string_compose(_("Could not understand ardour file %1"), xmlpath) << endmsg;
3338 /* replace history */
3340 for (XMLNodeConstIterator it = tree.root()->children().begin();
3341 it != tree.root()->children().end();
3345 UndoTransaction* ut = new UndoTransaction ();
3348 ut->set_name(t->property("name")->value());
3349 stringstream ss(t->property("tv_sec")->value());
3351 ss.str(t->property("tv_usec")->value());
3353 ut->set_timestamp(tv);
3355 for (XMLNodeConstIterator child_it = t->children().begin();
3356 child_it != t->children().end();
3359 XMLNode *n = *child_it;
3361 if (n->name() == "MementoCommand" ||
3362 n->name() == "MementoUndoCommand" ||
3363 n->name() == "MementoRedoCommand")
3365 c = memento_command_factory(n);
3371 error << string_compose(_("Couldn't figure out how to make a Command out of a %1 XMLNode."), n->name()) << endmsg;