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;
118 _current_frame_rate = _engine.frame_rate ();
119 _tempo_map = new TempoMap (_current_frame_rate);
120 _tempo_map->StateChanged.connect (mem_fun (*this, &Session::tempo_map_changed));
122 g_atomic_int_set (&processing_prohibited, 0);
125 _transport_speed = 0;
126 _last_transport_speed = 0;
127 transport_sub_state = 0;
128 _transport_frame = 0;
130 end_location = new Location (0, 0, _("end"), Location::Flags ((Location::IsMark|Location::IsEnd)));
131 start_location = new Location (0, 0, _("start"), Location::Flags ((Location::IsMark|Location::IsStart)));
132 _end_location_is_free = true;
133 g_atomic_int_set (&_record_status, Disabled);
138 seamless_loop = false;
139 loop_changing = false;
141 crossfades_active = false;
144 _last_roll_location = 0;
145 _last_record_location = 0;
146 pending_locate_frame = 0;
147 pending_locate_roll = false;
148 pending_locate_flush = false;
149 dstream_buffer_size = 0;
151 state_was_pending = false;
153 outbound_mtc_smpte_frame = 0;
154 next_quarter_frame_to_send = -1;
155 current_block_size = 0;
156 _solo_latched = true;
157 _solo_model = InverseMute;
158 solo_update_disabled = false;
159 currently_soloing = false;
160 _have_captured = false;
161 _worst_output_latency = 0;
162 _worst_input_latency = 0;
163 _worst_track_latency = 0;
164 _state_of_the_state = StateOfTheState(CannotSave|InitialConnecting|Loading);
167 butler_mixdown_buffer = 0;
168 butler_gain_buffer = 0;
172 post_transport_work = PostTransportWork (0);
173 g_atomic_int_set (&butler_should_do_transport_work, 0);
174 g_atomic_int_set (&butler_active, 0);
175 g_atomic_int_set (&_playback_load, 100);
176 g_atomic_int_set (&_capture_load, 100);
177 g_atomic_int_set (&_playback_load_min, 100);
178 g_atomic_int_set (&_capture_load_min, 100);
180 pending_edit_mode = _edit_mode;
182 input_auto_connect = AutoConnectOption (0);
183 output_auto_connect = AutoConnectOption (0);
184 waiting_to_start = false;
186 _gain_automation_buffer = 0;
187 _pan_automation_buffer = 0;
189 pending_abort = false;
190 layer_model = MoveAddHigher;
191 xfade_model = ShortCrossfade;
192 destructive_index = 0;
195 AudioDiskstream::allocate_working_buffers();
197 /* default short fade = 15ms */
199 Crossfade::set_short_xfade_length ((jack_nframes_t) floor ((15.0 * frame_rate()) / 1000.0));
200 DestructiveFileSource::setup_standard_crossfades (frame_rate());
202 last_mmc_step.tv_sec = 0;
203 last_mmc_step.tv_usec = 0;
206 preroll.type = AnyTime::Frames;
208 postroll.type = AnyTime::Frames;
211 /* click sounds are unset by default, which causes us to internal
212 waveforms for clicks.
216 click_requested = false;
218 click_emphasis_data = 0;
220 click_emphasis_length = 0;
222 process_function = &Session::process_with_events;
224 if (Config->get_use_video_sync()) {
225 waiting_for_sync_offset = true;
227 waiting_for_sync_offset = false;
230 _current_frame_rate = 48000;
231 _base_frame_rate = 48000;
233 smpte_frames_per_second = 30;
235 smpte_drop_frames = false;
238 _smpte_offset_negative = true;
239 last_smpte_valid = false;
241 last_rr_session_dir = session_dirs.begin();
242 refresh_disk_space ();
244 // set_default_fade (0.2, 5.0); /* steepness, millisecs */
246 /* default configuration */
248 do_not_record_plugins = false;
249 over_length_short = 2;
250 over_length_long = 10;
251 send_midi_timecode = false;
252 send_midi_machine_control = false;
253 shuttle_speed_factor = 1.0;
254 shuttle_speed_threshold = 5;
256 _meter_hold = 100; // XXX unknown units: number of calls to meter::set()
257 _meter_falloff = 0.375f; // XXX unknown units: refresh_rate
263 average_slave_delta = 1800;
264 have_first_delta_accumulator = false;
265 delta_accumulator_cnt = 0;
266 slave_state = Stopped;
268 /* default SMPTE type is 30 FPS, non-drop */
270 set_smpte_type (30.0, false);
271 set_video_pullup (0.0);
273 _engine.GraphReordered.connect (mem_fun (*this, &Session::graph_reordered));
275 /* These are all static "per-class" signals */
277 RegionFactory::CheckNewRegion.connect (mem_fun (*this, &Session::add_region));
278 SourceFactory::SourceCreated.connect (mem_fun (*this, &Session::add_source));
279 Playlist::PlaylistCreated.connect (mem_fun (*this, &Session::add_playlist));
280 Redirect::RedirectCreated.connect (mem_fun (*this, &Session::add_redirect));
281 NamedSelection::NamedSelectionCreated.connect (mem_fun (*this, &Session::add_named_selection));
282 Curve::CurveCreated.connect (mem_fun (*this, &Session::add_curve));
283 AutomationList::AutomationListCreated.connect (mem_fun (*this, &Session::add_automation_list));
285 Controllable::Created.connect (mem_fun (*this, &Session::add_controllable));
286 Controllable::GoingAway.connect (mem_fun (*this, &Session::remove_controllable));
288 IO::MoreOutputs.connect (mem_fun (*this, &Session::ensure_passthru_buffers));
290 /* stop IO objects from doing stuff until we're ready for them */
292 IO::disable_panners ();
293 IO::disable_ports ();
294 IO::disable_connecting ();
298 Session::second_stage_init (bool new_session)
300 AudioFileSource::set_peak_dir (peak_dir());
303 if (load_state (_current_snapshot_name)) {
306 remove_empty_sounds ();
309 if (start_butler_thread()) {
313 if (start_midi_thread ()) {
317 // set_state() will call setup_raid_path(), but if it's a new session we need
318 // to call setup_raid_path() here.
320 if (set_state (*state_tree->root())) {
324 setup_raid_path(_path);
327 /* we can't save till after ::when_engine_running() is called,
328 because otherwise we save state with no connections made.
329 therefore, we reset _state_of_the_state because ::set_state()
330 will have cleared it.
332 we also have to include Loading so that any events that get
333 generated between here and the end of ::when_engine_running()
334 will be processed directly rather than queued.
337 _state_of_the_state = StateOfTheState (_state_of_the_state|CannotSave|Loading);
339 // set_auto_input (true);
340 _locations.changed.connect (mem_fun (this, &Session::locations_changed));
341 _locations.added.connect (mem_fun (this, &Session::locations_added));
342 setup_click_sounds (0);
343 setup_midi_control ();
345 /* Pay attention ... */
347 _engine.Halted.connect (mem_fun (*this, &Session::engine_halted));
348 _engine.Xrun.connect (mem_fun (*this, &Session::xrun_recovery));
350 if (_engine.running()) {
351 when_engine_running();
353 first_time_running = _engine.Running.connect (mem_fun (*this, &Session::when_engine_running));
356 send_full_time_code ();
357 _engine.transport_locate (0);
358 deliver_mmc (MIDI::MachineControl::cmdMmcReset, 0);
359 deliver_mmc (MIDI::MachineControl::cmdLocate, 0);
361 ControlProtocolManager::instance().set_session (*this);
364 _end_location_is_free = true;
366 _end_location_is_free = false;
373 Session::raid_path () const
377 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
382 return path.substr (0, path.length() - 1); // drop final colon
386 Session::set_raid_path (string path)
388 /* public-access to setup_raid_path() */
390 setup_raid_path (path);
394 Session::setup_raid_path (string path)
396 string::size_type colon;
400 string::size_type len = path.length();
405 if (path.length() == 0) {
409 session_dirs.clear ();
411 for (string::size_type n = 0; n < len; ++n) {
412 if (path[n] == ':') {
419 /* no multiple search path, just one location (common case) */
423 session_dirs.push_back (sp);
430 if (fspath[fspath.length()-1] != '/') {
433 fspath += sound_dir (false);
435 AudioFileSource::set_search_path (fspath);
442 while ((colon = remaining.find_first_of (':')) != string::npos) {
445 sp.path = remaining.substr (0, colon);
446 session_dirs.push_back (sp);
448 /* add sounds to file search path */
451 if (fspath[fspath.length()-1] != '/') {
454 fspath += sound_dir (false);
457 remaining = remaining.substr (colon+1);
460 if (remaining.length()) {
467 if (fspath[fspath.length()-1] != '/') {
470 fspath += sound_dir (false);
473 session_dirs.push_back (sp);
476 /* set the AudioFileSource search path */
478 AudioFileSource::set_search_path (fspath);
480 /* reset the round-robin soundfile path thingie */
482 last_rr_session_dir = session_dirs.begin();
486 Session::create (bool& new_session, string* mix_template, jack_nframes_t initial_length)
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 */
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 /* set initial start + end point */
563 start_location->set_end (0);
564 _locations.add (start_location);
566 end_location->set_end (initial_length);
567 _locations.add (end_location);
569 _state_of_the_state = Clean;
571 if (save_state (_current_snapshot_name)) {
572 save_history (_current_snapshot_name);
580 Session::load_diskstreams (const XMLNode& node)
583 XMLNodeConstIterator citer;
585 clist = node.children();
587 for (citer = clist.begin(); citer != clist.end(); ++citer) {
591 boost::shared_ptr<AudioDiskstream> dstream (new AudioDiskstream (*this, **citer));
592 add_diskstream (dstream);
595 catch (failed_constructor& err) {
596 error << _("Session: could not load diskstream via XML state") << endmsg;
605 Session::remove_pending_capture_state ()
610 xml_path += _current_snapshot_name;
611 xml_path += _pending_suffix;
613 unlink (xml_path.c_str());
617 Session::save_state (string snapshot_name, bool pending)
623 if (_state_of_the_state & CannotSave) {
627 tree.set_root (&get_state());
629 if (snapshot_name.empty()) {
630 snapshot_name = _current_snapshot_name;
636 xml_path += snapshot_name;
637 xml_path += _statefile_suffix;
641 // Make backup of state file
643 if ((access (xml_path.c_str(), F_OK) == 0) &&
644 (rename(xml_path.c_str(), bak_path.c_str()))) {
645 error << _("could not backup old state file, current state not saved.") << endmsg;
652 xml_path += snapshot_name;
653 xml_path += _pending_suffix;
657 cerr << "actually writing state\n";
659 if (!tree.write (xml_path)) {
660 error << string_compose (_("state could not be saved to %1"), xml_path) << endmsg;
662 /* don't leave a corrupt file lying around if it is
666 if (unlink (xml_path.c_str())) {
667 error << string_compose (_("could not remove corrupt state file %1"), xml_path) << endmsg;
670 if (rename (bak_path.c_str(), xml_path.c_str())) {
671 error << string_compose (_("could not restore state file from backup %1"), bak_path) << endmsg;
680 save_history(snapshot_name);
682 bool was_dirty = dirty();
684 _state_of_the_state = StateOfTheState (_state_of_the_state & ~Dirty);
687 DirtyChanged (); /* EMIT SIGNAL */
690 StateSaved (snapshot_name); /* EMIT SIGNAL */
697 Session::restore_state (string snapshot_name)
699 if (load_state (snapshot_name) == 0) {
700 set_state (*state_tree->root());
707 Session::load_state (string snapshot_name)
716 state_was_pending = false;
718 /* check for leftover pending state from a crashed capture attempt */
721 xmlpath += snapshot_name;
722 xmlpath += _pending_suffix;
724 if (!access (xmlpath.c_str(), F_OK)) {
726 /* there is pending state from a crashed capture attempt */
728 if (AskAboutPendingState()) {
729 state_was_pending = true;
733 if (!state_was_pending) {
736 xmlpath += snapshot_name;
737 xmlpath += _statefile_suffix;
740 if (access (xmlpath.c_str(), F_OK)) {
741 error << string_compose(_("%1: session state information file \"%2\" doesn't exist!"), _name, xmlpath) << endmsg;
745 state_tree = new XMLTree;
749 if (state_tree->read (xmlpath)) {
752 error << string_compose(_("Could not understand ardour file %1"), xmlpath) << endmsg;
761 Session::load_options (const XMLNode& node)
765 bool have_fade_msecs = false;
766 bool have_fade_steepness = false;
767 float fade_msecs = 0;
768 float fade_steepness = 0;
769 SlaveSource slave_src = None;
771 LocaleGuard lg (X_("POSIX"));
773 if ((child = find_named_node (node, "input-auto-connect")) != 0) {
774 if ((prop = child->property ("val")) != 0) {
775 sscanf (prop->value().c_str(), "%x", &x);
776 input_auto_connect = AutoConnectOption (x);
780 if ((child = find_named_node (node, "output-auto-connect")) != 0) {
781 if ((prop = child->property ("val")) != 0) {
782 sscanf (prop->value().c_str(), "%x", &x);
783 output_auto_connect = AutoConnectOption (x);
787 if ((child = find_named_node (node, "slave")) != 0) {
788 if ((prop = child->property ("type")) != 0) {
789 if (prop->value() == "none") {
791 } else if (prop->value() == "mtc") {
793 } else if (prop->value() == "jack") {
796 set_slave_source (slave_src, 0);
800 /* we cannot set edit mode if we are loading a session,
801 because it might destroy the playlist's positioning
804 if ((child = find_named_node (node, "edit-mode")) != 0) {
805 if ((prop = child->property ("val")) != 0) {
806 if (prop->value() == "slide") {
807 pending_edit_mode = Slide;
808 } else if (prop->value() == "splice") {
809 pending_edit_mode = Splice;
814 if ((child = find_named_node (node, "send-midi-timecode")) != 0) {
815 if ((prop = child->property ("val")) != 0) {
816 bool x = (prop->value() == "yes");
817 send_mtc = !x; /* force change in value */
821 if ((child = find_named_node (node, "send-midi-machine-control")) != 0) {
822 if ((prop = child->property ("val")) != 0) {
823 bool x = (prop->value() == "yes");
824 send_mmc = !x; /* force change in value */
825 set_send_mmc (prop->value() == "yes");
828 if ((child = find_named_node (node, "max-level")) != 0) {
829 if ((prop = child->property ("val")) != 0) {
830 max_level = atoi (prop->value().c_str());
833 if ((child = find_named_node (node, "min-level")) != 0) {
834 if ((prop = child->property ("val")) != 0) {
835 min_level = atoi (prop->value().c_str());
838 if ((child = find_named_node (node, "meter-hold")) != 0) {
839 if ((prop = child->property ("val")) != 0) {
840 _meter_hold = atof (prop->value().c_str());
843 if ((child = find_named_node (node, "meter-falloff")) != 0) {
844 if ((prop = child->property ("val")) != 0) {
845 _meter_falloff = atof (prop->value().c_str());
848 if ((child = find_named_node (node, "long-over-length")) != 0) {
849 if ((prop = child->property ("val")) != 0) {
850 over_length_long = atoi (prop->value().c_str());
853 if ((child = find_named_node (node, "short-over-length")) != 0) {
854 if ((prop = child->property ("val")) != 0) {
855 over_length_short = atoi (prop->value().c_str());
858 if ((child = find_named_node (node, "shuttle-speed-factor")) != 0) {
859 if ((prop = child->property ("val")) != 0) {
860 shuttle_speed_factor = atof (prop->value().c_str());
863 if ((child = find_named_node (node, "shuttle-speed-threshold")) != 0) {
864 if ((prop = child->property ("val")) != 0) {
865 shuttle_speed_threshold = atof (prop->value().c_str());
868 if ((child = find_named_node (node, "rf-speed")) != 0) {
869 if ((prop = child->property ("val")) != 0) {
870 rf_speed = atof (prop->value().c_str());
873 if ((child = find_named_node (node, "video-pullup")) != 0) {
874 if ((prop = child->property ("val")) != 0) {
875 set_video_pullup( atof (prop->value().c_str()) );
878 if ((child = find_named_node (node, "smpte-frames-per-second")) != 0) {
879 if ((prop = child->property ("val")) != 0) {
880 set_smpte_type( atof (prop->value().c_str()), smpte_drop_frames );
883 if ((child = find_named_node (node, "smpte-drop-frames")) != 0) {
884 if ((prop = child->property ("val")) != 0) {
885 set_smpte_type( smpte_frames_per_second, (prop->value() == "yes") );
888 if ((child = find_named_node (node, "smpte-offset")) != 0) {
889 if ((prop = child->property ("val")) != 0) {
890 set_smpte_offset( atoi (prop->value().c_str()) );
893 if ((child = find_named_node (node, "smpte-offset-negative")) != 0) {
894 if ((prop = child->property ("val")) != 0) {
895 set_smpte_offset_negative( (prop->value() == "yes") );
898 if ((child = find_named_node (node, "click-sound")) != 0) {
899 if ((prop = child->property ("val")) != 0) {
900 click_sound = prop->value();
903 if ((child = find_named_node (node, "click-emphasis-sound")) != 0) {
904 if ((prop = child->property ("val")) != 0) {
905 click_emphasis_sound = prop->value();
909 if ((child = find_named_node (node, "solo-model")) != 0) {
910 if ((prop = child->property ("val")) != 0) {
911 if (prop->value() == "SoloBus")
912 _solo_model = SoloBus;
914 _solo_model = InverseMute;
918 /* BOOLEAN OPTIONS */
920 if ((child = find_named_node (node, "auto-play")) != 0) {
921 if ((prop = child->property ("val")) != 0) {
922 set_auto_play (prop->value() == "yes");
925 if ((child = find_named_node (node, "auto-input")) != 0) {
926 if ((prop = child->property ("val")) != 0) {
927 set_auto_input (prop->value() == "yes");
930 if ((child = find_named_node (node, "seamless-loop")) != 0) {
931 if ((prop = child->property ("val")) != 0) {
932 set_seamless_loop (prop->value() == "yes");
935 if ((child = find_named_node (node, "punch-in")) != 0) {
936 if ((prop = child->property ("val")) != 0) {
937 set_punch_in (prop->value() == "yes");
940 if ((child = find_named_node (node, "punch-out")) != 0) {
941 if ((prop = child->property ("val")) != 0) {
942 set_punch_out (prop->value() == "yes");
945 if ((child = find_named_node (node, "auto-return")) != 0) {
946 if ((prop = child->property ("val")) != 0) {
947 set_auto_return (prop->value() == "yes");
950 if ((child = find_named_node (node, "send-mtc")) != 0) {
951 if ((prop = child->property ("val")) != 0) {
952 set_send_mtc (prop->value() == "yes");
955 if ((child = find_named_node (node, "mmc-control")) != 0) {
956 if ((prop = child->property ("val")) != 0) {
957 set_mmc_control (prop->value() == "yes");
960 if ((child = find_named_node (node, "midi-control")) != 0) {
961 if ((prop = child->property ("val")) != 0) {
962 set_midi_control (prop->value() == "yes");
965 if ((child = find_named_node (node, "midi-feedback")) != 0) {
966 if ((prop = child->property ("val")) != 0) {
967 set_midi_feedback (prop->value() == "yes");
970 // Legacy support for <recording-plugins>
971 if ((child = find_named_node (node, "recording-plugins")) != 0) {
972 if ((prop = child->property ("val")) != 0) {
973 set_do_not_record_plugins (prop->value() == "no");
976 if ((child = find_named_node (node, "do-not-record-plugins")) != 0) {
977 if ((prop = child->property ("val")) != 0) {
978 set_do_not_record_plugins (prop->value() == "yes");
981 if ((child = find_named_node (node, "crossfades-active")) != 0) {
982 if ((prop = child->property ("val")) != 0) {
983 set_crossfades_active (prop->value() == "yes");
986 if ((child = find_named_node (node, "audible-click")) != 0) {
987 if ((prop = child->property ("val")) != 0) {
988 set_clicking (prop->value() == "yes");
992 if ((child = find_named_node (node, "end-marker-is-free")) != 0) {
993 if ((prop = child->property ("val")) != 0) {
994 _end_location_is_free = (prop->value() == "yes");
998 if ((child = find_named_node (node, "layer-model")) != 0) {
999 if ((prop = child->property ("val")) != 0) {
1000 if (prop->value() == X_("LaterHigher")) {
1001 set_layer_model (LaterHigher);
1002 } else if (prop->value() == X_("AddHigher")) {
1003 set_layer_model (AddHigher);
1005 set_layer_model (MoveAddHigher);
1010 if ((child = find_named_node (node, "xfade-model")) != 0) {
1011 if ((prop = child->property ("val")) != 0) {
1012 if (prop->value() == X_("Short")) {
1013 set_xfade_model (ShortCrossfade);
1015 set_xfade_model (FullCrossfade);
1020 if ((child = find_named_node (node, "short-xfade-length")) != 0) {
1021 if ((prop = child->property ("val")) != 0) {
1022 /* value is stored as a fractional seconds */
1023 float secs = atof (prop->value().c_str());
1024 Crossfade::set_short_xfade_length ((jack_nframes_t) floor (secs * frame_rate()));
1028 if ((child = find_named_node (node, "full-xfades-unmuted")) != 0) {
1029 if ((prop = child->property ("val")) != 0) {
1030 crossfades_active = (prop->value() == "yes");
1036 if ((child = find_named_node (node, "default-fade-steepness")) != 0) {
1037 if ((prop = child->property ("val")) != 0) {
1038 fade_steepness = atof (prop->value().c_str());
1039 have_fade_steepness = true;
1042 if ((child = find_named_node (node, "default-fade-msec")) != 0) {
1043 if ((prop = child->property ("val")) != 0) {
1044 fade_msecs = atof (prop->value().c_str());
1045 have_fade_msecs = true;
1049 if (have_fade_steepness || have_fade_msecs) {
1050 // set_default_fade (fade_steepness, fade_msecs);
1057 Session::get_options () const
1062 LocaleGuard lg (X_("POSIX"));
1064 opthead = new XMLNode ("Options");
1066 SlaveSource src = slave_source ();
1070 src_string = "none";
1076 src_string = "jack";
1079 child = opthead->add_child ("slave");
1080 child->add_property ("type", src_string);
1082 child = opthead->add_child ("send-midi-timecode");
1083 child->add_property ("val", send_midi_timecode?"yes":"no");
1085 child = opthead->add_child ("send-midi-machine-control");
1086 child->add_property ("val", send_midi_machine_control?"yes":"no");
1088 snprintf (buf, sizeof(buf)-1, "%x", (int) input_auto_connect);
1089 child = opthead->add_child ("input-auto-connect");
1090 child->add_property ("val", buf);
1092 snprintf (buf, sizeof(buf)-1, "%x", (int) output_auto_connect);
1093 child = opthead->add_child ("output-auto-connect");
1094 child->add_property ("val", buf);
1096 snprintf (buf, sizeof(buf)-1, "%d", max_level);
1097 child = opthead->add_child ("max-level");
1098 child->add_property ("val", buf);
1100 snprintf (buf, sizeof(buf)-1, "%d", min_level);
1101 child = opthead->add_child ("min-level");
1102 child->add_property ("val", buf);
1104 snprintf (buf, sizeof(buf)-1, "%f", _meter_hold);
1105 child = opthead->add_child ("meter-hold");
1106 child->add_property ("val", buf);
1108 snprintf (buf, sizeof(buf)-1, "%f", _meter_falloff);
1109 child = opthead->add_child ("meter-falloff");
1110 child->add_property ("val", buf);
1112 snprintf (buf, sizeof(buf)-1, "%u", over_length_long);
1113 child = opthead->add_child ("long-over-length");
1114 child->add_property ("val", buf);
1116 snprintf (buf, sizeof(buf)-1, "%u", over_length_short);
1117 child = opthead->add_child ("short-over-length");
1118 child->add_property ("val", buf);
1120 snprintf (buf, sizeof(buf)-1, "%f", shuttle_speed_factor);
1121 child = opthead->add_child ("shuttle-speed-factor");
1122 child->add_property ("val", buf);
1124 snprintf (buf, sizeof(buf)-1, "%f", shuttle_speed_threshold);
1125 child = opthead->add_child ("shuttle-speed-threshold");
1126 child->add_property ("val", buf);
1128 snprintf (buf, sizeof(buf)-1, "%f", rf_speed);
1129 child = opthead->add_child ("rf-speed");
1130 child->add_property ("val", buf);
1132 snprintf (buf, sizeof(buf)-1, "%.4f", video_pullup);
1133 child = opthead->add_child ("video-pullup");
1134 child->add_property ("val", buf);
1136 snprintf (buf, sizeof(buf)-1, "%.2f", smpte_frames_per_second);
1137 child = opthead->add_child ("smpte-frames-per-second");
1138 child->add_property ("val", buf);
1140 child = opthead->add_child ("smpte-drop-frames");
1141 child->add_property ("val", smpte_drop_frames ? "yes" : "no");
1143 snprintf (buf, sizeof(buf)-1, "%u", smpte_offset ());
1144 child = opthead->add_child ("smpte-offset");
1145 child->add_property ("val", buf);
1147 child = opthead->add_child ("smpte-offset-negative");
1148 child->add_property ("val", smpte_offset_negative () ? "yes" : "no");
1150 child = opthead->add_child ("edit-mode");
1151 switch (_edit_mode) {
1153 child->add_property ("val", "splice");
1157 child->add_property ("val", "slide");
1161 child = opthead->add_child ("auto-play");
1162 child->add_property ("val", get_auto_play () ? "yes" : "no");
1163 child = opthead->add_child ("auto-input");
1164 child->add_property ("val", get_auto_input () ? "yes" : "no");
1165 child = opthead->add_child ("seamless-loop");
1166 child->add_property ("val", get_seamless_loop () ? "yes" : "no");
1167 child = opthead->add_child ("punch-in");
1168 child->add_property ("val", get_punch_in () ? "yes" : "no");
1169 child = opthead->add_child ("punch-out");
1170 child->add_property ("val", get_punch_out () ? "yes" : "no");
1171 child = opthead->add_child ("all-safe");
1172 child->add_property ("val", get_all_safe () ? "yes" : "no");
1173 child = opthead->add_child ("auto-return");
1174 child->add_property ("val", get_auto_return () ? "yes" : "no");
1175 child = opthead->add_child ("mmc-control");
1176 child->add_property ("val", get_mmc_control () ? "yes" : "no");
1177 child = opthead->add_child ("midi-control");
1178 child->add_property ("val", get_midi_control () ? "yes" : "no");
1179 child = opthead->add_child ("midi-feedback");
1180 child->add_property ("val", get_midi_feedback () ? "yes" : "no");
1181 child = opthead->add_child ("do-not-record-plugins");
1182 child->add_property ("val", get_do_not_record_plugins () ? "yes" : "no");
1183 child = opthead->add_child ("auto-crossfade");
1184 child->add_property ("val", get_crossfades_active () ? "yes" : "no");
1185 child = opthead->add_child ("audible-click");
1186 child->add_property ("val", get_clicking () ? "yes" : "no");
1187 child = opthead->add_child ("end-marker-is-free");
1188 child->add_property ("val", _end_location_is_free ? "yes" : "no");
1190 if (click_sound.length()) {
1191 child = opthead->add_child ("click-sound");
1192 child->add_property ("val", click_sound);
1195 if (click_emphasis_sound.length()) {
1196 child = opthead->add_child ("click-emphasis-sound");
1197 child->add_property ("val", click_emphasis_sound);
1200 child = opthead->add_child ("solo-model");
1201 child->add_property ("val", _solo_model == SoloBus ? "SoloBus" : "InverseMute");
1203 child = opthead->add_child ("layer-model");
1204 switch (layer_model) {
1206 child->add_property ("val", X_("LaterHigher"));
1209 child->add_property ("val", X_("MoveAddHigher"));
1212 child->add_property ("val", X_("AddHigher"));
1216 child = opthead->add_child ("xfade-model");
1217 switch (xfade_model) {
1219 child->add_property ("val", X_("Full"));
1221 case ShortCrossfade:
1222 child->add_property ("val", X_("Short"));
1225 child = opthead->add_child ("short-xfade-length");
1226 /* store as fractions of a second */
1227 snprintf (buf, sizeof(buf)-1, "%f",
1228 (float) Crossfade::short_xfade_length() / frame_rate());
1229 child->add_property ("val", buf);
1231 child = opthead->add_child ("full-xfades-unmuted");
1232 child->add_property ("val", crossfades_active ? "yes" : "no");
1238 Session::get_state()
1244 Session::get_template()
1246 /* if we don't disable rec-enable, diskstreams
1247 will believe they need to store their capture
1248 sources in their state node.
1251 disable_record (false);
1253 return state(false);
1257 Session::state(bool full_state)
1259 XMLNode* node = new XMLNode("Session");
1262 // store libardour version, just in case
1264 snprintf(buf, sizeof(buf)-1, "%d.%d.%d",
1265 libardour_major_version, libardour_minor_version, libardour_micro_version);
1266 node->add_property("version", string(buf));
1268 /* store configuration settings */
1272 /* store the name */
1273 node->add_property ("name", _name);
1275 if (session_dirs.size() > 1) {
1279 vector<space_and_path>::iterator i = session_dirs.begin();
1280 vector<space_and_path>::iterator next;
1282 ++i; /* skip the first one */
1286 while (i != session_dirs.end()) {
1290 if (next != session_dirs.end()) {
1300 child = node->add_child ("Path");
1301 child->add_content (p);
1305 /* save the ID counter */
1307 snprintf (buf, sizeof (buf), "%" PRIu64, ID::counter());
1308 node->add_property ("id-counter", buf);
1310 /* various options */
1312 node->add_child_nocopy (get_options());
1314 child = node->add_child ("Sources");
1317 Glib::Mutex::Lock sl (audio_source_lock);
1319 for (AudioSourceList::iterator siter = audio_sources.begin(); siter != audio_sources.end(); ++siter) {
1321 /* Don't save information about AudioFileSources that are empty */
1323 boost::shared_ptr<AudioFileSource> fs;
1325 if ((fs = boost::dynamic_pointer_cast<AudioFileSource> (siter->second)) != 0) {
1326 boost::shared_ptr<DestructiveFileSource> dfs = boost::dynamic_pointer_cast<DestructiveFileSource> (fs);
1328 /* destructive file sources are OK if they are empty, because
1329 we will re-use them every time.
1333 if (fs->length() == 0) {
1339 child->add_child_nocopy (siter->second->get_state());
1343 child = node->add_child ("Regions");
1346 Glib::Mutex::Lock rl (region_lock);
1348 for (AudioRegionList::const_iterator i = audio_regions.begin(); i != audio_regions.end(); ++i) {
1350 /* only store regions not attached to playlists */
1352 if (i->second->playlist() == 0) {
1353 child->add_child_nocopy (i->second->state (true));
1358 child = node->add_child ("DiskStreams");
1361 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
1362 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
1363 if (!(*i)->hidden()) {
1364 child->add_child_nocopy ((*i)->get_state());
1369 node->add_child_nocopy (_locations.get_state());
1371 child = node->add_child ("Connections");
1373 Glib::Mutex::Lock lm (connection_lock);
1374 for (ConnectionList::iterator i = _connections.begin(); i != _connections.end(); ++i) {
1375 if (!(*i)->system_dependent()) {
1376 child->add_child_nocopy ((*i)->get_state());
1381 child = node->add_child ("Routes");
1383 boost::shared_ptr<RouteList> r = routes.reader ();
1385 RoutePublicOrderSorter cmp;
1386 RouteList public_order (*r);
1387 public_order.sort (cmp);
1389 for (RouteList::iterator i = public_order.begin(); i != public_order.end(); ++i) {
1390 if (!(*i)->hidden()) {
1392 child->add_child_nocopy ((*i)->get_state());
1394 child->add_child_nocopy ((*i)->get_template());
1401 child = node->add_child ("EditGroups");
1402 for (list<RouteGroup *>::iterator i = edit_groups.begin(); i != edit_groups.end(); ++i) {
1403 child->add_child_nocopy ((*i)->get_state());
1406 child = node->add_child ("MixGroups");
1407 for (list<RouteGroup *>::iterator i = mix_groups.begin(); i != mix_groups.end(); ++i) {
1408 child->add_child_nocopy ((*i)->get_state());
1411 child = node->add_child ("Playlists");
1412 for (PlaylistList::iterator i = playlists.begin(); i != playlists.end(); ++i) {
1413 if (!(*i)->hidden()) {
1414 if (!(*i)->empty()) {
1416 child->add_child_nocopy ((*i)->get_state());
1418 child->add_child_nocopy ((*i)->get_template());
1424 child = node->add_child ("UnusedPlaylists");
1425 for (PlaylistList::iterator i = unused_playlists.begin(); i != unused_playlists.end(); ++i) {
1426 if (!(*i)->hidden()) {
1427 if (!(*i)->empty()) {
1429 child->add_child_nocopy ((*i)->get_state());
1431 child->add_child_nocopy ((*i)->get_template());
1439 child = node->add_child ("Click");
1440 child->add_child_nocopy (_click_io->state (full_state));
1444 child = node->add_child ("NamedSelections");
1445 for (NamedSelectionList::iterator i = named_selections.begin(); i != named_selections.end(); ++i) {
1447 child->add_child_nocopy ((*i)->get_state());
1452 node->add_child_nocopy (_tempo_map->get_state());
1455 node->add_child_copy (*_extra_xml);
1462 Session::set_state (const XMLNode& node)
1466 const XMLProperty* prop;
1469 _state_of_the_state = StateOfTheState (_state_of_the_state|CannotSave);
1471 if (node.name() != X_("Session")){
1472 fatal << _("programming error: Session: incorrect XML node sent to set_state()") << endmsg;
1476 StateManager::prohibit_save ();
1478 if ((prop = node.property ("name")) != 0) {
1479 _name = prop->value ();
1482 setup_raid_path(_path);
1484 if ((prop = node.property (X_("id-counter"))) != 0) {
1486 sscanf (prop->value().c_str(), "%" PRIu64, &x);
1487 ID::init_counter (x);
1489 /* old sessions used a timebased counter, so fake
1490 the startup ID counter based on a standard
1495 ID::init_counter (now);
1499 IO::disable_ports ();
1500 IO::disable_connecting ();
1502 /* Object loading order:
1519 if (use_config_midi_ports ()) {
1522 if ((child = find_named_node (node, "Path")) != 0) {
1523 /* XXX this XML content stuff horrible API design */
1524 string raid_path = _path + ':' + child->children().front()->content();
1525 setup_raid_path (raid_path);
1527 /* the path is already set */
1530 if ((child = find_named_node (node, "extra")) != 0) {
1531 _extra_xml = new XMLNode (*child);
1534 if ((child = find_named_node (node, "Options")) == 0) {
1535 error << _("Session: XML state has no options section") << endmsg;
1536 } else if (load_options (*child)) {
1539 if ((child = find_named_node (node, "Sources")) == 0) {
1540 error << _("Session: XML state has no sources section") << endmsg;
1542 } else if (load_sources (*child)) {
1546 if ((child = find_named_node (node, "Regions")) == 0) {
1547 error << _("Session: XML state has no Regions section") << endmsg;
1549 } else if (load_regions (*child)) {
1553 if ((child = find_named_node (node, "Playlists")) == 0) {
1554 error << _("Session: XML state has no playlists section") << endmsg;
1556 } else if (load_playlists (*child)) {
1560 if ((child = find_named_node (node, "UnusedPlaylists")) == 0) {
1562 } else if (load_unused_playlists (*child)) {
1566 if ((child = find_named_node (node, "NamedSelections")) != 0) {
1567 if (load_named_selections (*child)) {
1572 if ((child = find_named_node (node, "DiskStreams")) == 0) {
1573 error << _("Session: XML state has no diskstreams section") << endmsg;
1575 } else if (load_diskstreams (*child)) {
1579 if ((child = find_named_node (node, "Connections")) == 0) {
1580 error << _("Session: XML state has no connections section") << endmsg;
1582 } else if (load_connections (*child)) {
1586 if ((child = find_named_node (node, "Locations")) == 0) {
1587 error << _("Session: XML state has no locations section") << endmsg;
1589 } else if (_locations.set_state (*child)) {
1595 if ((location = _locations.auto_loop_location()) != 0) {
1596 set_auto_loop_location (location);
1599 if ((location = _locations.auto_punch_location()) != 0) {
1600 set_auto_punch_location (location);
1603 if ((location = _locations.end_location()) == 0) {
1604 _locations.add (end_location);
1606 delete end_location;
1607 end_location = location;
1610 if ((location = _locations.start_location()) == 0) {
1611 _locations.add (start_location);
1613 delete start_location;
1614 start_location = location;
1617 _locations.save_state (_("initial state"));
1619 if ((child = find_named_node (node, "EditGroups")) == 0) {
1620 error << _("Session: XML state has no edit groups section") << endmsg;
1622 } else if (load_edit_groups (*child)) {
1626 if ((child = find_named_node (node, "MixGroups")) == 0) {
1627 error << _("Session: XML state has no mix groups section") << endmsg;
1629 } else if (load_mix_groups (*child)) {
1633 if ((child = find_named_node (node, "TempoMap")) == 0) {
1634 error << _("Session: XML state has no Tempo Map section") << endmsg;
1636 } else if (_tempo_map->set_state (*child)) {
1640 if ((child = find_named_node (node, "Routes")) == 0) {
1641 error << _("Session: XML state has no routes section") << endmsg;
1643 } else if (load_routes (*child)) {
1647 if ((child = find_named_node (node, "Click")) == 0) {
1648 warning << _("Session: XML state has no click section") << endmsg;
1649 } else if (_click_io) {
1650 _click_io->set_state (*child);
1653 /* OK, now we can set edit mode */
1655 set_edit_mode (pending_edit_mode);
1657 /* here beginneth the second phase ... */
1659 StateReady (); /* EMIT SIGNAL */
1661 _state_of_the_state = Clean;
1663 StateManager::allow_save (_("initial state"), true);
1665 if (state_was_pending) {
1666 save_state (_current_snapshot_name);
1667 remove_pending_capture_state ();
1668 state_was_pending = false;
1674 /* we failed, re-enable state saving but don't actually save internal state */
1675 StateManager::allow_save (X_("ignored"), false);
1680 Session::load_routes (const XMLNode& node)
1683 XMLNodeConstIterator niter;
1684 RouteList new_routes;
1686 nlist = node.children();
1690 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1692 boost::shared_ptr<Route> route (XMLRouteFactory (**niter));
1695 error << _("Session: cannot create Route from XML description.") << endmsg;
1699 new_routes.push_back (route);
1702 add_routes (new_routes);
1707 boost::shared_ptr<Route>
1708 Session::XMLRouteFactory (const XMLNode& node)
1710 if (node.name() != "Route") {
1711 return boost::shared_ptr<Route> ((Route*) 0);
1714 if (node.property ("diskstream") != 0 || node.property ("diskstream-id") != 0) {
1715 boost::shared_ptr<Route> x (new AudioTrack (*this, node));
1718 boost::shared_ptr<Route> x (new Route (*this, node));
1724 Session::load_regions (const XMLNode& node)
1727 XMLNodeConstIterator niter;
1728 boost::shared_ptr<AudioRegion> region;
1730 nlist = node.children();
1734 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1735 if ((region = XMLRegionFactory (**niter, false)) == 0) {
1736 error << _("Session: cannot create Region from XML description.") << endmsg;
1743 boost::shared_ptr<AudioRegion>
1744 Session::XMLRegionFactory (const XMLNode& node, bool full)
1746 const XMLProperty* prop;
1747 boost::shared_ptr<Source> source;
1748 boost::shared_ptr<AudioSource> as;
1750 uint32_t nchans = 1;
1753 if (node.name() != X_("Region")) {
1754 return boost::shared_ptr<AudioRegion>();
1757 if ((prop = node.property (X_("channels"))) != 0) {
1758 nchans = atoi (prop->value().c_str());
1762 if ((prop = node.property (X_("source-0"))) == 0) {
1763 if ((prop = node.property ("source")) == 0) {
1764 error << _("Session: XMLNode describing a AudioRegion is incomplete (no source)") << endmsg;
1765 return boost::shared_ptr<AudioRegion>();
1769 PBD::ID s_id (prop->value());
1771 if ((source = source_by_id (s_id)) == 0) {
1772 error << string_compose(_("Session: XMLNode describing a AudioRegion references an unknown source id =%1"), s_id) << endmsg;
1773 return boost::shared_ptr<AudioRegion>();
1776 as = boost::dynamic_pointer_cast<AudioSource>(source);
1778 error << string_compose(_("Session: XMLNode describing a AudioRegion references a non-audio source id =%1"), s_id) << endmsg;
1779 return boost::shared_ptr<AudioRegion>();
1782 sources.push_back (as);
1784 /* pickup other channels */
1786 for (uint32_t n=1; n < nchans; ++n) {
1787 snprintf (buf, sizeof(buf), X_("source-%d"), n);
1788 if ((prop = node.property (buf)) != 0) {
1790 PBD::ID id2 (prop->value());
1792 if ((source = source_by_id (id2)) == 0) {
1793 error << string_compose(_("Session: XMLNode describing a AudioRegion references an unknown source id =%1"), id2) << endmsg;
1794 return boost::shared_ptr<AudioRegion>();
1797 as = boost::dynamic_pointer_cast<AudioSource>(source);
1799 error << string_compose(_("Session: XMLNode describing a AudioRegion references a non-audio source id =%1"), id2) << endmsg;
1800 return boost::shared_ptr<AudioRegion>();
1802 sources.push_back (as);
1807 boost::shared_ptr<AudioRegion> region (boost::dynamic_pointer_cast<AudioRegion> (RegionFactory::create (sources, node)));
1812 catch (failed_constructor& err) {
1813 return boost::shared_ptr<AudioRegion>();
1818 Session::get_sources_as_xml ()
1821 XMLNode* node = new XMLNode (X_("Sources"));
1822 Glib::Mutex::Lock lm (audio_source_lock);
1824 for (AudioSourceList::iterator i = audio_sources.begin(); i != audio_sources.end(); ++i) {
1825 node->add_child_nocopy (i->second->get_state());
1828 /* XXX get MIDI and other sources here */
1834 Session::path_from_region_name (string name, string identifier)
1836 char buf[PATH_MAX+1];
1838 string dir = discover_best_sound_dir ();
1840 for (n = 0; n < 999999; ++n) {
1841 if (identifier.length()) {
1842 snprintf (buf, sizeof(buf), "%s/%s%s%" PRIu32 ".wav", dir.c_str(), name.c_str(),
1843 identifier.c_str(), n);
1845 snprintf (buf, sizeof(buf), "%s/%s-%" PRIu32 ".wav", dir.c_str(), name.c_str(), n);
1847 if (access (buf, F_OK) != 0) {
1857 Session::load_sources (const XMLNode& node)
1860 XMLNodeConstIterator niter;
1861 boost::shared_ptr<Source> source;
1863 nlist = node.children();
1867 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1869 if ((source = XMLSourceFactory (**niter)) == 0) {
1870 error << _("Session: cannot create Source from XML description.") << endmsg;
1877 boost::shared_ptr<Source>
1878 Session::XMLSourceFactory (const XMLNode& node)
1880 if (node.name() != "Source") {
1881 return boost::shared_ptr<Source>();
1885 return SourceFactory::create (*this, node);
1888 catch (failed_constructor& err) {
1889 error << _("Found a sound file that cannot be used by Ardour. Talk to the progammers.") << endmsg;
1890 return boost::shared_ptr<Source>();
1895 Session::save_template (string template_name)
1898 string xml_path, bak_path, template_path;
1900 if (_state_of_the_state & CannotSave) {
1905 string dir = template_dir();
1907 if ((dp = opendir (dir.c_str()))) {
1910 if (g_mkdir_with_parents (dir.c_str(), S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH)) {
1911 error << string_compose(_("Could not create mix templates directory \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
1916 tree.set_root (&get_template());
1919 xml_path += template_name;
1920 xml_path += _template_suffix;
1922 ifstream in(xml_path.c_str());
1925 warning << string_compose(_("Template \"%1\" already exists - new version not created"), template_name) << endmsg;
1931 if (!tree.write (xml_path)) {
1932 error << _("mix template not saved") << endmsg;
1940 Session::rename_template (string old_name, string new_name)
1942 string old_path = template_dir() + old_name + _template_suffix;
1943 string new_path = template_dir() + new_name + _template_suffix;
1945 return rename (old_path.c_str(), new_path.c_str());
1949 Session::delete_template (string name)
1951 string template_path = template_dir();
1952 template_path += name;
1953 template_path += _template_suffix;
1955 return remove (template_path.c_str());
1959 Session::refresh_disk_space ()
1962 struct statfs statfsbuf;
1963 vector<space_and_path>::iterator i;
1964 Glib::Mutex::Lock lm (space_lock);
1967 /* get freespace on every FS that is part of the session path */
1969 _total_free_4k_blocks = 0;
1971 for (i = session_dirs.begin(); i != session_dirs.end(); ++i) {
1972 statfs ((*i).path.c_str(), &statfsbuf);
1974 scale = statfsbuf.f_bsize/4096.0;
1976 (*i).blocks = (uint32_t) floor (statfsbuf.f_bavail * scale);
1977 _total_free_4k_blocks += (*i).blocks;
1983 Session::ensure_sound_dir (string path, string& result)
1988 /* Ensure that the parent directory exists */
1990 if (g_mkdir_with_parents (path.c_str(), 0775)) {
1991 error << string_compose(_("cannot create session directory \"%1\"; ignored"), path) << endmsg;
1995 /* Ensure that the sounds directory exists */
1999 result += sound_dir_name;
2001 if (g_mkdir_with_parents (result.c_str(), 0775)) {
2002 error << string_compose(_("cannot create sounds directory \"%1\"; ignored"), result) << endmsg;
2008 dead += dead_sound_dir_name;
2010 if (g_mkdir_with_parents (dead.c_str(), 0775)) {
2011 error << string_compose(_("cannot create dead sounds directory \"%1\"; ignored"), dead) << endmsg;
2017 peak += peak_dir_name;
2019 if (g_mkdir_with_parents (peak.c_str(), 0775)) {
2020 error << string_compose(_("cannot create peak file directory \"%1\"; ignored"), peak) << endmsg;
2024 /* callers expect this to be terminated ... */
2031 Session::discover_best_sound_dir (bool destructive)
2033 vector<space_and_path>::iterator i;
2036 /* handle common case without system calls */
2038 if (session_dirs.size() == 1) {
2042 /* OK, here's the algorithm we're following here:
2044 We want to select which directory to use for
2045 the next file source to be created. Ideally,
2046 we'd like to use a round-robin process so as to
2047 get maximum performance benefits from splitting
2048 the files across multiple disks.
2050 However, in situations without much diskspace, an
2051 RR approach may end up filling up a filesystem
2052 with new files while others still have space.
2053 Its therefore important to pay some attention to
2054 the freespace in the filesystem holding each
2055 directory as well. However, if we did that by
2056 itself, we'd keep creating new files in the file
2057 system with the most space until it was as full
2058 as all others, thus negating any performance
2059 benefits of this RAID-1 like approach.
2061 So, we use a user-configurable space threshold. If
2062 there are at least 2 filesystems with more than this
2063 much space available, we use RR selection between them.
2064 If not, then we pick the filesystem with the most space.
2066 This gets a good balance between the two
2070 refresh_disk_space ();
2072 int free_enough = 0;
2074 for (i = session_dirs.begin(); i != session_dirs.end(); ++i) {
2075 if ((*i).blocks * 4096 >= Config->get_disk_choice_space_threshold()) {
2080 if (free_enough >= 2) {
2082 bool found_it = false;
2084 /* use RR selection process, ensuring that the one
2088 i = last_rr_session_dir;
2091 if (++i == session_dirs.end()) {
2092 i = session_dirs.begin();
2095 if ((*i).blocks * 4096 >= Config->get_disk_choice_space_threshold()) {
2096 if (ensure_sound_dir ((*i).path, result) == 0) {
2097 last_rr_session_dir = i;
2103 } while (i != last_rr_session_dir);
2106 result = sound_dir();
2111 /* pick FS with the most freespace (and that
2112 seems to actually work ...)
2115 vector<space_and_path> sorted;
2116 space_and_path_ascending_cmp cmp;
2118 sorted = session_dirs;
2119 sort (sorted.begin(), sorted.end(), cmp);
2121 for (i = sorted.begin(); i != sorted.end(); ++i) {
2122 if (ensure_sound_dir ((*i).path, result) == 0) {
2123 last_rr_session_dir = i;
2128 /* if the above fails, fall back to the most simplistic solution */
2130 if (i == sorted.end()) {
2139 Session::load_playlists (const XMLNode& node)
2142 XMLNodeConstIterator niter;
2145 nlist = node.children();
2149 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2151 if ((playlist = XMLPlaylistFactory (**niter)) == 0) {
2152 error << _("Session: cannot create Playlist from XML description.") << endmsg;
2160 Session::load_unused_playlists (const XMLNode& node)
2163 XMLNodeConstIterator niter;
2166 nlist = node.children();
2170 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2172 if ((playlist = XMLPlaylistFactory (**niter)) == 0) {
2173 error << _("Session: cannot create Playlist from XML description.") << endmsg;
2177 // now manually untrack it
2179 track_playlist (playlist, false);
2187 Session::XMLPlaylistFactory (const XMLNode& node)
2190 return new AudioPlaylist (*this, node);
2193 catch (failed_constructor& err) {
2199 Session::load_named_selections (const XMLNode& node)
2202 XMLNodeConstIterator niter;
2205 nlist = node.children();
2209 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2211 if ((ns = XMLNamedSelectionFactory (**niter)) == 0) {
2212 error << _("Session: cannot create Named Selection from XML description.") << endmsg;
2220 Session::XMLNamedSelectionFactory (const XMLNode& node)
2223 return new NamedSelection (*this, node);
2226 catch (failed_constructor& err) {
2232 Session::dead_sound_dir () const
2235 res += dead_sound_dir_name;
2241 Session::sound_dir (bool with_path) const
2243 /* support old session structure */
2245 struct stat statbuf;
2247 string old_withpath;
2249 old_nopath += old_sound_dir_name;
2252 old_withpath = _path;
2253 old_withpath += old_sound_dir_name;
2254 old_withpath += '/';
2256 if (stat (old_withpath.c_str(), &statbuf) == 0) {
2258 return old_withpath;
2269 res += interchange_dir_name;
2271 res += legalize_for_path (_name);
2273 res += sound_dir_name;
2280 Session::peak_dir () const
2283 res += peak_dir_name;
2289 Session::automation_dir () const
2292 res += "automation/";
2297 Session::template_dir ()
2299 string path = get_user_ardour_path();
2300 path += "templates/";
2306 Session::suffixed_search_path (string suffix, bool data)
2310 path += get_user_ardour_path();
2311 if (path[path.length()-1] != ':') {
2316 path += get_system_data_path();
2318 path += get_system_module_path();
2321 vector<string> split_path;
2323 split (path, split_path, ':');
2326 for (vector<string>::iterator i = split_path.begin(); i != split_path.end(); ++i) {
2331 if (distance (i, split_path.end()) != 1) {
2340 Session::template_path ()
2342 return suffixed_search_path (X_("templates"), true);
2346 Session::control_protocol_path ()
2348 return suffixed_search_path (X_("surfaces"), false);
2352 Session::load_connections (const XMLNode& node)
2354 XMLNodeList nlist = node.children();
2355 XMLNodeConstIterator niter;
2359 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2360 if ((*niter)->name() == "InputConnection") {
2361 add_connection (new ARDOUR::InputConnection (**niter));
2362 } else if ((*niter)->name() == "OutputConnection") {
2363 add_connection (new ARDOUR::OutputConnection (**niter));
2365 error << string_compose(_("Unknown node \"%1\" found in Connections list from state file"), (*niter)->name()) << endmsg;
2374 Session::load_edit_groups (const XMLNode& node)
2376 return load_route_groups (node, true);
2380 Session::load_mix_groups (const XMLNode& node)
2382 return load_route_groups (node, false);
2386 Session::load_route_groups (const XMLNode& node, bool edit)
2388 XMLNodeList nlist = node.children();
2389 XMLNodeConstIterator niter;
2394 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2395 if ((*niter)->name() == "RouteGroup") {
2397 rg = add_edit_group ("");
2398 rg->set_state (**niter);
2400 rg = add_mix_group ("");
2401 rg->set_state (**niter);
2410 state_file_filter (const string &str, void *arg)
2412 return (str.length() > strlen(Session::statefile_suffix()) &&
2413 str.find (Session::statefile_suffix()) == (str.length() - strlen (Session::statefile_suffix())));
2417 bool operator()(const string* a, const string* b) {
2423 remove_end(string* state)
2425 string statename(*state);
2427 string::size_type start,end;
2428 if ((start = statename.find_last_of ('/')) != string::npos) {
2429 statename = statename.substr (start+1);
2432 if ((end = statename.rfind(".ardour")) == string::npos) {
2433 end = statename.length();
2436 return new string(statename.substr (0, end));
2440 Session::possible_states (string path)
2442 PathScanner scanner;
2443 vector<string*>* states = scanner (path, state_file_filter, 0, false, false);
2445 transform(states->begin(), states->end(), states->begin(), remove_end);
2448 sort (states->begin(), states->end(), cmp);
2454 Session::possible_states () const
2456 return possible_states(_path);
2460 Session::auto_save()
2462 save_state (_current_snapshot_name);
2466 Session::add_edit_group (string name)
2468 RouteGroup* rg = new RouteGroup (*this, name);
2469 edit_groups.push_back (rg);
2470 edit_group_added (rg); /* EMIT SIGNAL */
2476 Session::add_mix_group (string name)
2478 RouteGroup* rg = new RouteGroup (*this, name, RouteGroup::Relative);
2479 mix_groups.push_back (rg);
2480 mix_group_added (rg); /* EMIT SIGNAL */
2486 Session::remove_edit_group (RouteGroup& rg)
2488 list<RouteGroup*>::iterator i;
2490 if ((i = find (edit_groups.begin(), edit_groups.end(), &rg)) != edit_groups.end()) {
2491 (*i)->apply (&Route::drop_edit_group, this);
2492 edit_groups.erase (i);
2493 edit_group_removed (); /* EMIT SIGNAL */
2500 Session::remove_mix_group (RouteGroup& rg)
2502 list<RouteGroup*>::iterator i;
2504 if ((i = find (mix_groups.begin(), mix_groups.end(), &rg)) != mix_groups.end()) {
2505 (*i)->apply (&Route::drop_mix_group, this);
2506 mix_groups.erase (i);
2507 mix_group_removed (); /* EMIT SIGNAL */
2514 Session::mix_group_by_name (string name)
2516 list<RouteGroup *>::iterator i;
2518 for (i = mix_groups.begin(); i != mix_groups.end(); ++i) {
2519 if ((*i)->name() == name) {
2527 Session::edit_group_by_name (string name)
2529 list<RouteGroup *>::iterator i;
2531 for (i = edit_groups.begin(); i != edit_groups.end(); ++i) {
2532 if ((*i)->name() == name) {
2540 Session::set_meter_hold (float val)
2543 MeterHoldChanged(); // emit
2547 Session::set_meter_falloff (float val)
2549 _meter_falloff = val;
2550 MeterFalloffChanged(); // emit
2555 Session::begin_reversible_command (string name)
2557 current_trans = new UndoTransaction;
2558 current_trans->set_name (name);
2562 Session::commit_reversible_command (Command *cmd)
2567 current_trans->add_command (cmd);
2570 gettimeofday (&now, 0);
2571 current_trans->set_timestamp (now);
2573 history.add (current_trans);
2576 Session::GlobalRouteBooleanState
2577 Session::get_global_route_boolean (bool (Route::*method)(void) const)
2579 GlobalRouteBooleanState s;
2580 boost::shared_ptr<RouteList> r = routes.reader ();
2582 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
2583 if (!(*i)->hidden()) {
2584 RouteBooleanState v;
2587 Route* r = (*i).get();
2588 v.second = (r->*method)();
2597 Session::GlobalRouteMeterState
2598 Session::get_global_route_metering ()
2600 GlobalRouteMeterState s;
2601 boost::shared_ptr<RouteList> r = routes.reader ();
2603 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
2604 if (!(*i)->hidden()) {
2608 v.second = (*i)->meter_point();
2618 Session::set_global_route_metering (GlobalRouteMeterState s, void* arg)
2620 for (GlobalRouteMeterState::iterator i = s.begin(); i != s.end(); ++i) {
2621 i->first->set_meter_point (i->second, arg);
2626 Session::set_global_route_boolean (GlobalRouteBooleanState s, void (Route::*method)(bool, void*), void* arg)
2628 for (GlobalRouteBooleanState::iterator i = s.begin(); i != s.end(); ++i) {
2629 Route* r = i->first.get();
2630 (r->*method) (i->second, arg);
2635 Session::set_global_mute (GlobalRouteBooleanState s, void* src)
2637 set_global_route_boolean (s, &Route::set_mute, src);
2641 Session::set_global_solo (GlobalRouteBooleanState s, void* src)
2643 set_global_route_boolean (s, &Route::set_solo, src);
2647 Session::set_global_record_enable (GlobalRouteBooleanState s, void* src)
2649 set_global_route_boolean (s, &Route::set_record_enable, src);
2654 Session::global_mute_memento (void* src)
2656 return sigc::bind (mem_fun (*this, &Session::set_global_mute), get_global_route_boolean (&Route::muted), src);
2660 Session::global_metering_memento (void* src)
2662 return sigc::bind (mem_fun (*this, &Session::set_global_route_metering), get_global_route_metering (), src);
2666 Session::global_solo_memento (void* src)
2668 return sigc::bind (mem_fun (*this, &Session::set_global_solo), get_global_route_boolean (&Route::soloed), src);
2672 Session::global_record_enable_memento (void* src)
2674 return sigc::bind (mem_fun (*this, &Session::set_global_record_enable), get_global_route_boolean (&Route::record_enabled), src);
2679 template_filter (const string &str, void *arg)
2681 return (str.length() > strlen(Session::template_suffix()) &&
2682 str.find (Session::template_suffix()) == (str.length() - strlen (Session::template_suffix())));
2686 Session::get_template_list (list<string> &template_names)
2688 vector<string *> *templates;
2689 PathScanner scanner;
2692 path = template_path ();
2694 templates = scanner (path, template_filter, 0, false, true);
2696 vector<string*>::iterator i;
2697 for (i = templates->begin(); i != templates->end(); ++i) {
2698 string fullpath = *(*i);
2701 start = fullpath.find_last_of ('/') + 1;
2702 if ((end = fullpath.find_last_of ('.')) <0) {
2703 end = fullpath.length();
2706 template_names.push_back(fullpath.substr(start, (end-start)));
2711 Session::read_favorite_dirs (FavoriteDirs & favs)
2713 string path = get_user_ardour_path();
2714 path += "/favorite_dirs";
2716 ifstream fav (path.c_str());
2721 if (errno != ENOENT) {
2722 //error << string_compose (_("cannot open favorite file %1 (%2)"), path, strerror (errno)) << endmsg;
2733 getline(fav, newfav);
2739 favs.push_back (newfav);
2746 Session::write_favorite_dirs (FavoriteDirs & favs)
2748 string path = get_user_ardour_path();
2749 path += "/favorite_dirs";
2751 ofstream fav (path.c_str());
2757 for (FavoriteDirs::iterator i = favs.begin(); i != favs.end(); ++i) {
2758 fav << (*i) << endl;
2765 accept_all_non_peak_files (const string& path, void *arg)
2767 return (path.length() > 5 && path.find (".peak") != (path.length() - 5));
2771 accept_all_state_files (const string& path, void *arg)
2773 return (path.length() > 7 && path.find (".ardour") == (path.length() - 7));
2777 Session::find_all_sources (string path, set<string>& result)
2782 if (!tree.read (path)) {
2786 if ((node = find_named_node (*tree.root(), "Sources")) == 0) {
2791 XMLNodeConstIterator niter;
2793 nlist = node->children();
2797 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2801 if ((prop = (*niter)->property (X_("name"))) == 0) {
2805 if (prop->value()[0] == '/') {
2806 /* external file, ignore */
2810 string path = _path; /* /-terminated */
2811 path += sound_dir_name;
2813 path += prop->value();
2815 result.insert (path);
2822 Session::find_all_sources_across_snapshots (set<string>& result, bool exclude_this_snapshot)
2824 PathScanner scanner;
2825 vector<string*>* state_files;
2827 string this_snapshot_path;
2833 if (ripped[ripped.length()-1] == '/') {
2834 ripped = ripped.substr (0, ripped.length() - 1);
2837 state_files = scanner (ripped, accept_all_state_files, (void *) 0, false, true);
2839 if (state_files == 0) {
2844 this_snapshot_path = _path;
2845 this_snapshot_path += _current_snapshot_name;
2846 this_snapshot_path += _statefile_suffix;
2848 for (vector<string*>::iterator i = state_files->begin(); i != state_files->end(); ++i) {
2850 if (exclude_this_snapshot && **i == this_snapshot_path) {
2854 if (find_all_sources (**i, result) < 0) {
2863 Session::cleanup_sources (Session::cleanup_report& rep)
2865 vector<boost::shared_ptr<Source> > dead_sources;
2866 vector<Playlist*> playlists_tbd;
2867 PathScanner scanner;
2869 vector<space_and_path>::iterator i;
2870 vector<space_and_path>::iterator nexti;
2871 vector<string*>* soundfiles;
2872 vector<string> unused;
2873 set<string> all_sources;
2878 _state_of_the_state = (StateOfTheState) (_state_of_the_state | InCleanup);
2880 /* step 1: consider deleting all unused playlists */
2882 for (PlaylistList::iterator x = unused_playlists.begin(); x != unused_playlists.end(); ++x) {
2885 status = AskAboutPlaylistDeletion (*x);
2894 playlists_tbd.push_back (*x);
2898 /* leave it alone */
2903 /* now delete any that were marked for deletion */
2905 for (vector<Playlist*>::iterator x = playlists_tbd.begin(); x != playlists_tbd.end(); ++x) {
2906 PlaylistList::iterator foo;
2908 if ((foo = unused_playlists.find (*x)) != unused_playlists.end()) {
2909 unused_playlists.erase (foo);
2914 /* step 2: clear the undo/redo history for all playlists */
2916 for (PlaylistList::iterator x = playlists.begin(); x != playlists.end(); ++x) {
2917 (*x)->drop_all_states ();
2920 /* step 3: find all un-referenced sources */
2925 for (AudioSourceList::iterator i = audio_sources.begin(); i != audio_sources.end(); ) {
2927 AudioSourceList::iterator tmp;
2932 /* only remove files that are not in use and have some size
2933 to them. otherwise we remove the current "nascent"
2937 if (i->second.use_count() == 1 && i->second->length() > 0) {
2938 dead_sources.push_back (i->second);
2940 /* remove this source from our own list to avoid us
2941 adding it to the list of all sources below
2944 audio_sources.erase (i);
2950 /* Step 4: get rid of all regions in the region list that use any dead sources
2951 in case the sources themselves don't go away (they might be referenced in
2955 for (vector<boost::shared_ptr<Source> >::iterator i = dead_sources.begin(); i != dead_sources.end();++i) {
2957 for (AudioRegionList::iterator r = audio_regions.begin(); r != audio_regions.end(); ) {
2958 AudioRegionList::iterator tmp;
2959 boost::shared_ptr<AudioRegion> ar;
2966 for (uint32_t n = 0; n < ar->n_channels(); ++n) {
2967 if (ar->source (n) == (*i)) {
2968 /* this region is dead */
2977 /* build a list of all the possible sound directories for the session */
2979 for (i = session_dirs.begin(); i != session_dirs.end(); ) {
2984 sound_path += (*i).path;
2985 sound_path += sound_dir_name;
2987 if (nexti != session_dirs.end()) {
2994 /* now do the same thing for the files that ended up in the sounds dir(s)
2995 but are not referenced as sources in any snapshot.
2998 soundfiles = scanner (sound_path, accept_all_non_peak_files, (void *) 0, false, true);
3000 if (soundfiles == 0) {
3004 /* find all sources, but don't use this snapshot because the
3005 state file on disk still references sources we may have already
3009 find_all_sources_across_snapshots (all_sources, true);
3011 /* add our current source list
3014 for (AudioSourceList::iterator i = audio_sources.begin(); i != audio_sources.end(); ++i) {
3015 boost::shared_ptr<AudioFileSource> fs;
3017 if ((fs = boost::dynamic_pointer_cast<AudioFileSource> (i->second)) != 0) {
3018 all_sources.insert (fs->path());
3022 for (vector<string*>::iterator x = soundfiles->begin(); x != soundfiles->end(); ++x) {
3027 for (set<string>::iterator i = all_sources.begin(); i != all_sources.end(); ++i) {
3037 unused.push_back (spath);
3041 /* now try to move all unused files into the "dead_sounds" directory(ies) */
3043 for (vector<string>::iterator x = unused.begin(); x != unused.end(); ++x) {
3044 struct stat statbuf;
3046 rep.paths.push_back (*x);
3047 if (stat ((*x).c_str(), &statbuf) == 0) {
3048 rep.space += statbuf.st_size;
3053 /* don't move the file across filesystems, just
3054 stick it in the `dead_sound_dir_name' directory
3055 on whichever filesystem it was already on.
3058 newpath = Glib::path_get_dirname (*x);
3059 newpath = Glib::path_get_dirname (newpath);
3062 newpath += dead_sound_dir_name;
3064 newpath += Glib::path_get_basename ((*x));
3066 if (access (newpath.c_str(), F_OK) == 0) {
3068 /* the new path already exists, try versioning */
3070 char buf[PATH_MAX+1];
3074 snprintf (buf, sizeof (buf), "%s.%d", newpath.c_str(), version);
3077 while (access (newpath_v.c_str(), F_OK) == 0 && version < 999) {
3078 snprintf (buf, sizeof (buf), "%s.%d", newpath.c_str(), ++version);
3082 if (version == 999) {
3083 error << string_compose (_("there are already 1000 files with names like %1; versioning discontinued"),
3087 newpath = newpath_v;
3092 /* it doesn't exist, or we can't read it or something */
3096 if (::rename ((*x).c_str(), newpath.c_str()) != 0) {
3097 error << string_compose (_("cannot rename audio file source from %1 to %2 (%3)"),
3098 (*x), newpath, strerror (errno))
3104 /* see if there an easy to find peakfile for this file, and remove it.
3107 string peakpath = (*x).substr (0, (*x).find_last_of ('.'));
3108 peakpath += ".peak";
3110 if (access (peakpath.c_str(), W_OK) == 0) {
3111 if (::unlink (peakpath.c_str()) != 0) {
3112 error << string_compose (_("cannot remove peakfile %1 for %2 (%3)"),
3113 peakpath, _path, strerror (errno))
3115 /* try to back out */
3116 rename (newpath.c_str(), _path.c_str());
3125 /* dump the history list */
3129 /* save state so we don't end up a session file
3130 referring to non-existent sources.
3136 _state_of_the_state = (StateOfTheState) (_state_of_the_state & ~InCleanup);
3141 Session::cleanup_trash_sources (Session::cleanup_report& rep)
3143 vector<space_and_path>::iterator i;
3144 string dead_sound_dir;
3145 struct dirent* dentry;
3146 struct stat statbuf;
3152 for (i = session_dirs.begin(); i != session_dirs.end(); ++i) {
3154 dead_sound_dir = (*i).path;
3155 dead_sound_dir += dead_sound_dir_name;
3157 if ((dead = opendir (dead_sound_dir.c_str())) == 0) {
3161 while ((dentry = readdir (dead)) != 0) {
3163 /* avoid '.' and '..' */
3165 if ((dentry->d_name[0] == '.' && dentry->d_name[1] == '\0') ||
3166 (dentry->d_name[2] == '\0' && dentry->d_name[0] == '.' && dentry->d_name[1] == '.')) {
3172 fullpath = dead_sound_dir;
3174 fullpath += dentry->d_name;
3176 if (stat (fullpath.c_str(), &statbuf)) {
3180 if (!S_ISREG (statbuf.st_mode)) {
3184 if (unlink (fullpath.c_str())) {
3185 error << string_compose (_("cannot remove dead sound file %1 (%2)"),
3186 fullpath, strerror (errno))
3190 rep.paths.push_back (dentry->d_name);
3191 rep.space += statbuf.st_size;
3202 Session::set_dirty ()
3204 bool was_dirty = dirty();
3206 _state_of_the_state = StateOfTheState (_state_of_the_state | Dirty);
3209 DirtyChanged(); /* EMIT SIGNAL */
3215 Session::set_clean ()
3217 bool was_dirty = dirty();
3219 _state_of_the_state = Clean;
3222 DirtyChanged(); /* EMIT SIGNAL */
3227 Session::add_controllable (Controllable* c)
3229 Glib::Mutex::Lock lm (controllables_lock);
3230 controllables.push_back (c);
3234 Session::remove_controllable (Controllable* c)
3236 if (_state_of_the_state | Deletion) {
3240 Glib::Mutex::Lock lm (controllables_lock);
3241 controllables.remove (c);
3245 Session::controllable_by_id (const PBD::ID& id)
3247 Glib::Mutex::Lock lm (controllables_lock);
3249 for (Controllables::iterator i = controllables.begin(); i != controllables.end(); ++i) {
3250 if ((*i)->id() == id) {
3259 Session::add_instant_xml (XMLNode& node, const std::string& dir)
3261 Stateful::add_instant_xml (node, dir);
3262 Config->add_instant_xml (node, get_user_ardour_path());
3267 Session::save_history (string snapshot_name)
3273 tree.set_root (&history.get_state());
3275 if (snapshot_name.empty()) {
3276 snapshot_name = _current_snapshot_name;
3279 xml_path = _path + snapshot_name + ".history";
3281 bak_path = xml_path + ".bak";
3283 if ((access (xml_path.c_str(), F_OK) == 0) &&
3284 (rename (xml_path.c_str(), bak_path.c_str())))
3286 error << _("could not backup old history file, current history not saved.") << endmsg;
3290 cerr << "actually writing history\n";
3292 if (!tree.write (xml_path))
3294 error << string_compose (_("history could not be saved to %1"), xml_path) << endmsg;
3296 /* don't leave a corrupt file lying around if it is
3300 if (unlink (xml_path.c_str()))
3302 error << string_compose (_("could not remove corrupt history file %1"), xml_path) << endmsg;
3304 if (rename (bak_path.c_str(), xml_path.c_str()))
3306 error << string_compose (_("could not restore history file from backup %1"), bak_path) << endmsg;
3317 Session::restore_history (string snapshot_name)
3323 xmlpath = _path + snapshot_name + ".history";
3324 cerr << string_compose(_("Loading history from '%1'."), xmlpath) << endmsg;
3326 if (access (xmlpath.c_str(), F_OK)) {
3327 error << string_compose(_("%1: session history file \"%2\" doesn't exist!"), _name, xmlpath) << endmsg;
3331 if (!tree.read (xmlpath)) {
3332 error << string_compose(_("Could not understand ardour file %1"), xmlpath) << endmsg;
3336 /* replace history */
3338 for (XMLNodeConstIterator it = tree.root()->children().begin();
3339 it != tree.root()->children().end();
3343 UndoTransaction* ut = new UndoTransaction ();
3346 ut->set_name(t->property("name")->value());
3347 stringstream ss(t->property("tv_sec")->value());
3349 ss.str(t->property("tv_usec")->value());
3351 ut->set_timestamp(tv);
3353 for (XMLNodeConstIterator child_it = t->children().begin();
3354 child_it != t->children().end();
3357 XMLNode *n = *child_it;
3359 if (n->name() == "MementoCommand" ||
3360 n->name() == "MementoUndoCommand" ||
3361 n->name() == "MementoRedoCommand")
3363 c = memento_command_factory(n);
3369 error << string_compose(_("Couldn't figure out how to make a Command out of a %1 XMLNode."), n->name()) << endmsg;