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>
47 #include <midi++/mmc.h>
48 #include <midi++/port.h>
49 #include <pbd/error.h>
50 #include <pbd/dirname.h>
51 #include <pbd/lockmonitor.h>
52 #include <pbd/pathscanner.h>
53 #include <pbd/pthread_utils.h>
54 #include <pbd/basename.h>
55 #include <pbd/strsplit.h>
57 #include <ardour/audioengine.h>
58 #include <ardour/configuration.h>
59 #include <ardour/session.h>
60 #include <ardour/diskstream.h>
61 #include <ardour/utils.h>
62 #include <ardour/audioplaylist.h>
63 #include <ardour/source.h>
64 #include <ardour/filesource.h>
65 #include <ardour/destructive_filesource.h>
66 #include <ardour/sndfilesource.h>
67 #include <ardour/sndfile_helpers.h>
68 #include <ardour/auditioner.h>
69 #include <ardour/export.h>
70 #include <ardour/redirect.h>
71 #include <ardour/send.h>
72 #include <ardour/insert.h>
73 #include <ardour/connection.h>
74 #include <ardour/slave.h>
75 #include <ardour/tempo.h>
76 #include <ardour/audio_track.h>
77 #include <ardour/cycle_timer.h>
78 #include <ardour/utils.h>
79 #include <ardour/named_selection.h>
80 #include <ardour/version.h>
81 #include <ardour/location.h>
82 #include <ardour/audioregion.h>
83 #include <ardour/crossfade.h>
89 using namespace ARDOUR;
92 Session::first_stage_init (string fullpath, string snapshot_name)
94 if (fullpath.length() == 0) {
95 throw failed_constructor();
99 if (!realpath(fullpath.c_str(), buf) && (errno != ENOENT)) {
100 error << string_compose(_("Could not use path %1 (%s)"), buf, strerror(errno)) << endmsg;
101 throw failed_constructor();
105 if (_path[_path.length()-1] != '/') {
109 /* these two are just provisional settings. set_state()
110 will likely override them.
113 _name = _current_snapshot_name = snapshot_name;
114 setup_raid_path (_path);
116 _current_frame_rate = _engine.frame_rate ();
117 _tempo_map = new TempoMap (_current_frame_rate);
118 _tempo_map->StateChanged.connect (mem_fun (*this, &Session::tempo_map_changed));
120 atomic_set (&processing_prohibited, 0);
123 _transport_speed = 0;
124 _last_transport_speed = 0;
125 transport_sub_state = 0;
126 _transport_frame = 0;
128 end_location = new Location (0, 0, _("end"), Location::Flags ((Location::IsMark|Location::IsEnd)));
129 start_location = new Location (0, 0, _("start"), Location::Flags ((Location::IsMark|Location::IsStart)));
130 _end_location_is_free = true;
131 atomic_set (&_record_status, Disabled);
136 seamless_loop = false;
137 loop_changing = false;
139 crossfades_active = false;
142 _last_roll_location = 0;
143 _last_record_location = 0;
144 pending_locate_frame = 0;
145 pending_locate_roll = false;
146 pending_locate_flush = false;
147 dstream_buffer_size = 0;
149 state_was_pending = false;
151 outbound_mtc_smpte_frame = 0;
152 next_quarter_frame_to_send = -1;
153 current_block_size = 0;
154 _solo_latched = true;
155 _solo_model = InverseMute;
156 solo_update_disabled = false;
157 currently_soloing = false;
158 _worst_output_latency = 0;
159 _worst_input_latency = 0;
160 _worst_track_latency = 0;
161 _state_of_the_state = StateOfTheState(CannotSave|InitialConnecting|Loading);
164 butler_mixdown_buffer = 0;
165 butler_gain_buffer = 0;
168 midi_feedback = false;
171 post_transport_work = PostTransportWork (0);
172 atomic_set (&butler_should_do_transport_work, 0);
173 atomic_set (&butler_active, 0);
174 atomic_set (&_playback_load, 100);
175 atomic_set (&_capture_load, 100);
176 atomic_set (&_playback_load_min, 100);
177 atomic_set (&_capture_load_min, 100);
178 pending_audition_region = 0;
180 pending_edit_mode = _edit_mode;
184 input_auto_connect = AutoConnectOption (0);
185 output_auto_connect = AutoConnectOption (0);
186 _have_captured = false;
187 waiting_to_start = false;
189 _gain_automation_buffer = 0;
190 _pan_automation_buffer = 0;
192 pending_abort = false;
193 layer_model = MoveAddHigher;
194 xfade_model = ShortCrossfade;
195 destructive_index = 0;
197 /* allocate conversion buffers */
198 _conversion_buffers[ButlerContext] = new char[DiskStream::disk_io_frames() * 4];
199 _conversion_buffers[TransportContext] = new char[DiskStream::disk_io_frames() * 4];
201 /* default short fade = 15ms */
203 Crossfade::set_short_xfade_length ((jack_nframes_t) floor ((15.0 * frame_rate()) / 1000.0));
205 last_mmc_step.tv_sec = 0;
206 last_mmc_step.tv_usec = 0;
209 preroll.type = AnyTime::Frames;
211 postroll.type = AnyTime::Frames;
214 /* click sounds are unset by default, which causes us to internal
215 waveforms for clicks.
220 click_requested = false;
222 click_emphasis_data = 0;
224 click_emphasis_length = 0;
226 process_function = &Session::process_with_events;
230 _smpte_offset_negative = true;
231 last_smpte_valid = false;
233 last_rr_session_dir = session_dirs.begin();
234 refresh_disk_space ();
236 // set_default_fade (0.2, 5.0); /* steepness, millisecs */
238 /* default configuration */
240 do_not_record_plugins = false;
241 over_length_short = 2;
242 over_length_long = 10;
243 send_midi_timecode = false;
244 send_midi_machine_control = false;
245 shuttle_speed_factor = 1.0;
246 shuttle_speed_threshold = 5;
248 _meter_hold = 100; // XXX unknown units: number of calls to meter::set()
249 _meter_falloff = 1.5f; // XXX unknown units: refresh_rate
255 average_slave_delta = 1800;
256 have_first_delta_accumulator = false;
257 delta_accumulator_cnt = 0;
258 slave_state = Stopped;
260 /* default SMPTE type is 30 FPS, non-drop */
262 set_smpte_type (30.0, false);
264 _engine.GraphReordered.connect (mem_fun (*this, &Session::graph_reordered));
266 /* These are all static "per-class" signals */
268 Region::CheckNewRegion.connect (mem_fun (*this, &Session::add_region));
269 Source::SourceCreated.connect (mem_fun (*this, &Session::add_source));
270 Playlist::PlaylistCreated.connect (mem_fun (*this, &Session::add_playlist));
271 Redirect::RedirectCreated.connect (mem_fun (*this, &Session::add_redirect));
272 DiskStream::DiskStreamCreated.connect (mem_fun (*this, &Session::add_diskstream));
273 NamedSelection::NamedSelectionCreated.connect (mem_fun (*this, &Session::add_named_selection));
275 IO::MoreOutputs.connect (mem_fun (*this, &Session::ensure_passthru_buffers));
277 /* stop IO objects from doing stuff until we're ready for them */
279 IO::disable_panners ();
280 IO::disable_ports ();
281 IO::disable_connecting ();
285 Session::second_stage_init (bool new_session)
287 ExternalSource::set_peak_dir (peak_dir());
290 if (load_state (_current_snapshot_name)) {
293 remove_empty_sounds ();
296 if (start_butler_thread()) {
300 if (start_midi_thread ()) {
304 if (init_feedback ()) {
309 if (set_state (*state_tree->root())) {
314 /* we can't save till after ::when_engine_running() is called,
315 because otherwise we save state with no connections made.
316 therefore, we reset _state_of_the_state because ::set_state()
317 will have cleared it.
319 we also have to include Loading so that any events that get
320 generated between here and the end of ::when_engine_running()
321 will be processed directly rather than queued.
324 _state_of_the_state = StateOfTheState (_state_of_the_state|CannotSave|Loading);
326 // set_auto_input (true);
327 _locations.changed.connect (mem_fun (this, &Session::locations_changed));
328 _locations.added.connect (mem_fun (this, &Session::locations_added));
329 setup_click_sounds (0);
330 setup_midi_control ();
332 /* Pay attention ... */
334 _engine.Halted.connect (mem_fun (*this, &Session::engine_halted));
335 _engine.Xrun.connect (mem_fun (*this, &Session::xrun_recovery));
337 if (_engine.running()) {
338 when_engine_running();
340 first_time_running = _engine.Running.connect (mem_fun (*this, &Session::when_engine_running));
343 send_full_time_code ();
344 _engine.transport_locate (0);
345 deliver_mmc (MIDI::MachineControl::cmdMmcReset, 0);
346 deliver_mmc (MIDI::MachineControl::cmdLocate, 0);
347 send_all_midi_feedback();
350 _end_location_is_free = true;
352 _end_location_is_free = false;
359 Session::raid_path () const
363 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
368 return path.substr (0, path.length() - 1); // drop final colon
372 Session::set_raid_path (string path)
374 /* public-access to setup_raid_path() */
376 setup_raid_path (path);
380 Session::setup_raid_path (string path)
382 string::size_type colon;
386 string::size_type len = path.length();
391 if (path.length() == 0) {
395 session_dirs.clear ();
397 for (string::size_type n = 0; n < len; ++n) {
398 if (path[n] == ':') {
405 /* no multiple search path, just one location (common case) */
409 session_dirs.push_back (sp);
416 if (fspath[fspath.length()-1] != '/') {
419 fspath += sound_dir_name;
425 if (fspath[fspath.length()-1] != '/') {
428 fspath += tape_dir_name;
430 FileSource::set_search_path (fspath);
437 while ((colon = remaining.find_first_of (':')) != string::npos) {
440 sp.path = remaining.substr (0, colon);
441 session_dirs.push_back (sp);
443 /* add sounds to file search path */
446 if (fspath[fspath.length()-1] != '/') {
449 fspath += sound_dir_name;
452 /* add tape dir to file search path */
455 if (fspath[fspath.length()-1] != '/') {
458 fspath += tape_dir_name;
461 remaining = remaining.substr (colon+1);
464 if (remaining.length()) {
471 if (fspath[fspath.length()-1] != '/') {
474 fspath += sound_dir_name;
478 if (fspath[fspath.length()-1] != '/') {
481 fspath += tape_dir_name;
483 session_dirs.push_back (sp);
486 /* set the FileSource search path */
488 FileSource::set_search_path (fspath);
490 /* reset the round-robin soundfile path thingie */
492 last_rr_session_dir = session_dirs.begin();
496 Session::create (bool& new_session, string* mix_template, jack_nframes_t initial_length)
500 if (mkdir (_path.c_str(), 0755) < 0) {
501 if (errno == EEXIST) {
504 error << string_compose(_("Session: cannot create session dir \"%1\" (%2)"), _path, strerror (errno)) << endmsg;
513 if (mkdir (dir.c_str(), 0755) < 0) {
514 if (errno != EEXIST) {
515 error << string_compose(_("Session: cannot create session peakfile dir \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
522 if (mkdir (dir.c_str(), 0755) < 0) {
523 if (errno != EEXIST) {
524 error << string_compose(_("Session: cannot create session sounds dir \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
531 if (mkdir (dir.c_str(), 0755) < 0) {
532 if (errno != EEXIST) {
533 error << string_compose(_("Session: cannot create session tape dir \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
538 dir = dead_sound_dir ();
540 if (mkdir (dir.c_str(), 0755) < 0) {
541 if (errno != EEXIST) {
542 error << string_compose(_("Session: cannot create session dead sounds dir \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
547 dir = automation_dir ();
549 if (mkdir (dir.c_str(), 0755) < 0) {
550 if (errno != EEXIST) {
551 error << string_compose(_("Session: cannot create session automation dir \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
557 /* check new_session so we don't overwrite an existing one */
561 std::string in_path = *mix_template;
563 ifstream in(in_path.c_str());
566 string out_path = _path;
568 out_path += _statefile_suffix;
570 ofstream out(out_path.c_str());
575 // okay, session is set up. Treat like normal saved
576 // session from now on.
582 error << string_compose (_("Could not open %1 for writing mix template"), out_path)
588 error << string_compose (_("Could not open mix template %1 for reading"), in_path)
595 warning << _("Session already exists. Not overwriting") << endmsg;
602 /* set initial start + end point */
604 start_location->set_end (0);
605 _locations.add (start_location);
607 end_location->set_end (initial_length);
608 _locations.add (end_location);
610 _state_of_the_state = Clean;
612 if (save_state (_current_snapshot_name)) {
621 Session::load_diskstreams (const XMLNode& node)
624 XMLNodeConstIterator citer;
626 clist = node.children();
628 for (citer = clist.begin(); citer != clist.end(); ++citer) {
633 dstream = new DiskStream (*this, **citer);
634 /* added automatically by DiskStreamCreated handler */
637 catch (failed_constructor& err) {
638 error << _("Session: could not load diskstream via XML state") << endmsg;
647 Session::remove_pending_capture_state ()
652 xml_path += _current_snapshot_name;
653 xml_path += _pending_suffix;
655 unlink (xml_path.c_str());
659 Session::save_state (string snapshot_name, bool pending)
665 if (_state_of_the_state & CannotSave) {
669 tree.set_root (&get_state());
671 if (snapshot_name.empty()) {
672 snapshot_name = _current_snapshot_name;
678 xml_path += snapshot_name;
679 xml_path += _statefile_suffix;
683 // Make backup of state file
685 if ((access (xml_path.c_str(), F_OK) == 0) &&
686 (rename(xml_path.c_str(), bak_path.c_str()))) {
687 error << _("could not backup old state file, current state not saved.") << endmsg;
694 xml_path += snapshot_name;
695 xml_path += _pending_suffix;
699 if (!tree.write (xml_path)) {
700 error << string_compose (_("state could not be saved to %1"), xml_path) << endmsg;
702 /* don't leave a corrupt file lying around if it is
706 if (unlink (xml_path.c_str())) {
707 error << string_compose (_("could not remove corrupt state file %1"), xml_path) << endmsg;
710 if (rename (bak_path.c_str(), xml_path.c_str())) {
711 error << string_compose (_("could not restore state file from backup %1"), bak_path) << endmsg;
721 bool was_dirty = dirty();
723 _state_of_the_state = StateOfTheState (_state_of_the_state & ~Dirty);
726 DirtyChanged (); /* EMIT SIGNAL */
729 StateSaved (snapshot_name); /* EMIT SIGNAL */
736 Session::restore_state (string snapshot_name)
738 if (load_state (snapshot_name) == 0) {
739 set_state (*state_tree->root());
746 Session::load_state (string snapshot_name)
755 state_was_pending = false;
757 /* check for leftover pending state from a crashed capture attempt */
760 xmlpath += snapshot_name;
761 xmlpath += _pending_suffix;
763 if (!access (xmlpath.c_str(), F_OK)) {
765 /* there is pending state from a crashed capture attempt */
767 if (AskAboutPendingState()) {
768 state_was_pending = true;
772 if (!state_was_pending) {
775 xmlpath += snapshot_name;
776 xmlpath += _statefile_suffix;
779 if (access (xmlpath.c_str(), F_OK)) {
780 error << string_compose(_("%1: session state information file \"%2\" doesn't exist!"), _name, xmlpath) << endmsg;
784 state_tree = new XMLTree;
788 if (state_tree->read (xmlpath)) {
791 error << string_compose(_("Could not understand ardour file %1"), xmlpath) << endmsg;
800 Session::load_options (const XMLNode& node)
804 bool have_fade_msecs = false;
805 bool have_fade_steepness = false;
806 float fade_msecs = 0;
807 float fade_steepness = 0;
808 SlaveSource slave_src = None;
810 LocaleGuard lg (X_("POSIX"));
812 if ((child = find_named_node (node, "input-auto-connect")) != 0) {
813 if ((prop = child->property ("val")) != 0) {
814 sscanf (prop->value().c_str(), "%x", &x);
815 input_auto_connect = AutoConnectOption (x);
819 if ((child = find_named_node (node, "output-auto-connect")) != 0) {
820 if ((prop = child->property ("val")) != 0) {
821 sscanf (prop->value().c_str(), "%x", &x);
822 output_auto_connect = AutoConnectOption (x);
826 if ((child = find_named_node (node, "slave")) != 0) {
827 if ((prop = child->property ("type")) != 0) {
828 if (prop->value() == "none") {
830 } else if (prop->value() == "mtc") {
832 } else if (prop->value() == "jack") {
835 set_slave_source (slave_src, 0);
839 /* we cannot set edit mode if we are loading a session,
840 because it might destroy the playlist's positioning
843 if ((child = find_named_node (node, "edit-mode")) != 0) {
844 if ((prop = child->property ("val")) != 0) {
845 if (prop->value() == "slide") {
846 pending_edit_mode = Slide;
847 } else if (prop->value() == "splice") {
848 pending_edit_mode = Splice;
853 if ((child = find_named_node (node, "send-midi-timecode")) != 0) {
854 if ((prop = child->property ("val")) != 0) {
855 bool x = (prop->value() == "yes");
856 send_mtc = !x; /* force change in value */
860 if ((child = find_named_node (node, "send-midi-machine-control")) != 0) {
861 if ((prop = child->property ("val")) != 0) {
862 bool x = (prop->value() == "yes");
863 send_mmc = !x; /* force change in value */
864 set_send_mmc (prop->value() == "yes");
867 if ((child = find_named_node (node, "max-level")) != 0) {
868 if ((prop = child->property ("val")) != 0) {
869 max_level = atoi (prop->value().c_str());
872 if ((child = find_named_node (node, "min-level")) != 0) {
873 if ((prop = child->property ("val")) != 0) {
874 min_level = atoi (prop->value().c_str());
877 if ((child = find_named_node (node, "meter-hold")) != 0) {
878 if ((prop = child->property ("val")) != 0) {
879 _meter_hold = atof (prop->value().c_str());
882 if ((child = find_named_node (node, "meter-falloff")) != 0) {
883 if ((prop = child->property ("val")) != 0) {
884 _meter_falloff = atof (prop->value().c_str());
887 if ((child = find_named_node (node, "long-over-length")) != 0) {
888 if ((prop = child->property ("val")) != 0) {
889 over_length_long = atoi (prop->value().c_str());
892 if ((child = find_named_node (node, "short-over-length")) != 0) {
893 if ((prop = child->property ("val")) != 0) {
894 over_length_short = atoi (prop->value().c_str());
897 if ((child = find_named_node (node, "shuttle-speed-factor")) != 0) {
898 if ((prop = child->property ("val")) != 0) {
899 shuttle_speed_factor = atof (prop->value().c_str());
902 if ((child = find_named_node (node, "shuttle-speed-threshold")) != 0) {
903 if ((prop = child->property ("val")) != 0) {
904 shuttle_speed_threshold = atof (prop->value().c_str());
907 if ((child = find_named_node (node, "rf-speed")) != 0) {
908 if ((prop = child->property ("val")) != 0) {
909 rf_speed = atof (prop->value().c_str());
912 if ((child = find_named_node (node, "smpte-frames-per-second")) != 0) {
913 if ((prop = child->property ("val")) != 0) {
914 set_smpte_type( atof (prop->value().c_str()), smpte_drop_frames );
917 if ((child = find_named_node (node, "smpte-drop-frames")) != 0) {
918 if ((prop = child->property ("val")) != 0) {
919 set_smpte_type( smpte_frames_per_second, (prop->value() == "yes") );
922 if ((child = find_named_node (node, "smpte-offset")) != 0) {
923 if ((prop = child->property ("val")) != 0) {
924 set_smpte_offset( atoi (prop->value().c_str()) );
927 if ((child = find_named_node (node, "smpte-offset-negative")) != 0) {
928 if ((prop = child->property ("val")) != 0) {
929 set_smpte_offset_negative( (prop->value() == "yes") );
932 if ((child = find_named_node (node, "click-sound")) != 0) {
933 if ((prop = child->property ("val")) != 0) {
934 click_sound = prop->value();
937 if ((child = find_named_node (node, "click-emphasis-sound")) != 0) {
938 if ((prop = child->property ("val")) != 0) {
939 click_emphasis_sound = prop->value();
943 if ((child = find_named_node (node, "solo-model")) != 0) {
944 if ((prop = child->property ("val")) != 0) {
945 if (prop->value() == "SoloBus")
946 _solo_model = SoloBus;
948 _solo_model = InverseMute;
952 /* BOOLEAN OPTIONS */
954 if ((child = find_named_node (node, "auto-play")) != 0) {
955 if ((prop = child->property ("val")) != 0) {
956 set_auto_play (prop->value() == "yes");
959 if ((child = find_named_node (node, "auto-input")) != 0) {
960 if ((prop = child->property ("val")) != 0) {
961 set_auto_input (prop->value() == "yes");
964 if ((child = find_named_node (node, "seamless-loop")) != 0) {
965 if ((prop = child->property ("val")) != 0) {
966 set_seamless_loop (prop->value() == "yes");
969 if ((child = find_named_node (node, "punch-in")) != 0) {
970 if ((prop = child->property ("val")) != 0) {
971 set_punch_in (prop->value() == "yes");
974 if ((child = find_named_node (node, "punch-out")) != 0) {
975 if ((prop = child->property ("val")) != 0) {
976 set_punch_out (prop->value() == "yes");
979 if ((child = find_named_node (node, "auto-return")) != 0) {
980 if ((prop = child->property ("val")) != 0) {
981 set_auto_return (prop->value() == "yes");
984 if ((child = find_named_node (node, "send-mtc")) != 0) {
985 if ((prop = child->property ("val")) != 0) {
986 set_send_mtc (prop->value() == "yes");
989 if ((child = find_named_node (node, "mmc-control")) != 0) {
990 if ((prop = child->property ("val")) != 0) {
991 set_mmc_control (prop->value() == "yes");
994 if ((child = find_named_node (node, "midi-control")) != 0) {
995 if ((prop = child->property ("val")) != 0) {
996 set_midi_control (prop->value() == "yes");
999 if ((child = find_named_node (node, "midi-feedback")) != 0) {
1000 if ((prop = child->property ("val")) != 0) {
1001 set_midi_feedback (prop->value() == "yes");
1004 // Legacy support for <recording-plugins>
1005 if ((child = find_named_node (node, "recording-plugins")) != 0) {
1006 if ((prop = child->property ("val")) != 0) {
1007 set_do_not_record_plugins (prop->value() == "no");
1010 if ((child = find_named_node (node, "do-not-record-plugins")) != 0) {
1011 if ((prop = child->property ("val")) != 0) {
1012 set_do_not_record_plugins (prop->value() == "yes");
1015 if ((child = find_named_node (node, "crossfades-active")) != 0) {
1016 if ((prop = child->property ("val")) != 0) {
1017 set_crossfades_active (prop->value() == "yes");
1020 if ((child = find_named_node (node, "audible-click")) != 0) {
1021 if ((prop = child->property ("val")) != 0) {
1022 set_clicking (prop->value() == "yes");
1026 if ((child = find_named_node (node, "layer-model")) != 0) {
1027 if ((prop = child->property ("val")) != 0) {
1028 if (prop->value() == X_("LaterHigher")) {
1029 set_layer_model (LaterHigher);
1030 } else if (prop->value() == X_("AddHigher")) {
1031 set_layer_model (AddHigher);
1033 set_layer_model (MoveAddHigher);
1038 if ((child = find_named_node (node, "xfade-model")) != 0) {
1039 if ((prop = child->property ("val")) != 0) {
1040 if (prop->value() == X_("Short")) {
1041 set_xfade_model (ShortCrossfade);
1043 set_xfade_model (FullCrossfade);
1048 if ((child = find_named_node (node, "short-xfade-length")) != 0) {
1049 if ((prop = child->property ("val")) != 0) {
1050 /* value is stored as a fractional seconds */
1051 float secs = atof (prop->value().c_str());
1052 Crossfade::set_short_xfade_length ((jack_nframes_t) floor (secs * frame_rate()));
1056 if ((child = find_named_node (node, "full-xfades-unmuted")) != 0) {
1057 if ((prop = child->property ("val")) != 0) {
1058 crossfades_active = (prop->value() == "yes");
1064 if ((child = find_named_node (node, "default-fade-steepness")) != 0) {
1065 if ((prop = child->property ("val")) != 0) {
1066 fade_steepness = atof (prop->value().c_str());
1067 have_fade_steepness = true;
1070 if ((child = find_named_node (node, "default-fade-msec")) != 0) {
1071 if ((prop = child->property ("val")) != 0) {
1072 fade_msecs = atof (prop->value().c_str());
1073 have_fade_msecs = true;
1077 if (have_fade_steepness || have_fade_msecs) {
1078 // set_default_fade (fade_steepness, fade_msecs);
1085 Session::get_options () const
1090 LocaleGuard lg (X_("POSIX"));
1092 opthead = new XMLNode ("Options");
1094 SlaveSource src = slave_source ();
1098 src_string = "none";
1104 src_string = "jack";
1107 child = opthead->add_child ("slave");
1108 child->add_property ("type", src_string);
1110 child = opthead->add_child ("send-midi-timecode");
1111 child->add_property ("val", send_midi_timecode?"yes":"no");
1113 child = opthead->add_child ("send-midi-machine-control");
1114 child->add_property ("val", send_midi_machine_control?"yes":"no");
1116 snprintf (buf, sizeof(buf)-1, "%x", (int) input_auto_connect);
1117 child = opthead->add_child ("input-auto-connect");
1118 child->add_property ("val", buf);
1120 snprintf (buf, sizeof(buf)-1, "%x", (int) output_auto_connect);
1121 child = opthead->add_child ("output-auto-connect");
1122 child->add_property ("val", buf);
1124 snprintf (buf, sizeof(buf)-1, "%d", max_level);
1125 child = opthead->add_child ("max-level");
1126 child->add_property ("val", buf);
1128 snprintf (buf, sizeof(buf)-1, "%d", min_level);
1129 child = opthead->add_child ("min-level");
1130 child->add_property ("val", buf);
1132 snprintf (buf, sizeof(buf)-1, "%f", _meter_hold);
1133 child = opthead->add_child ("meter-hold");
1134 child->add_property ("val", buf);
1136 snprintf (buf, sizeof(buf)-1, "%f", _meter_falloff);
1137 child = opthead->add_child ("meter-falloff");
1138 child->add_property ("val", buf);
1140 snprintf (buf, sizeof(buf)-1, "%u", over_length_long);
1141 child = opthead->add_child ("long-over-length");
1142 child->add_property ("val", buf);
1144 snprintf (buf, sizeof(buf)-1, "%u", over_length_short);
1145 child = opthead->add_child ("short-over-length");
1146 child->add_property ("val", buf);
1148 snprintf (buf, sizeof(buf)-1, "%f", shuttle_speed_factor);
1149 child = opthead->add_child ("shuttle-speed-factor");
1150 child->add_property ("val", buf);
1152 snprintf (buf, sizeof(buf)-1, "%f", shuttle_speed_threshold);
1153 child = opthead->add_child ("shuttle-speed-threshold");
1154 child->add_property ("val", buf);
1156 snprintf (buf, sizeof(buf)-1, "%f", rf_speed);
1157 child = opthead->add_child ("rf-speed");
1158 child->add_property ("val", buf);
1160 snprintf (buf, sizeof(buf)-1, "%.2f", smpte_frames_per_second);
1161 child = opthead->add_child ("smpte-frames-per-second");
1162 child->add_property ("val", buf);
1164 child = opthead->add_child ("smpte-drop-frames");
1165 child->add_property ("val", smpte_drop_frames ? "yes" : "no");
1167 snprintf (buf, sizeof(buf)-1, "%u", smpte_offset ());
1168 child = opthead->add_child ("smpte-offset");
1169 child->add_property ("val", buf);
1171 child = opthead->add_child ("smpte-offset-negative");
1172 child->add_property ("val", smpte_offset_negative () ? "yes" : "no");
1174 child = opthead->add_child ("edit-mode");
1175 switch (_edit_mode) {
1177 child->add_property ("val", "splice");
1181 child->add_property ("val", "slide");
1185 child = opthead->add_child ("auto-play");
1186 child->add_property ("val", get_auto_play () ? "yes" : "no");
1187 child = opthead->add_child ("auto-input");
1188 child->add_property ("val", get_auto_input () ? "yes" : "no");
1189 child = opthead->add_child ("seamless-loop");
1190 child->add_property ("val", get_seamless_loop () ? "yes" : "no");
1191 child = opthead->add_child ("punch-in");
1192 child->add_property ("val", get_punch_in () ? "yes" : "no");
1193 child = opthead->add_child ("punch-out");
1194 child->add_property ("val", get_punch_out () ? "yes" : "no");
1195 child = opthead->add_child ("all-safe");
1196 child->add_property ("val", get_all_safe () ? "yes" : "no");
1197 child = opthead->add_child ("auto-return");
1198 child->add_property ("val", get_auto_return () ? "yes" : "no");
1199 child = opthead->add_child ("mmc-control");
1200 child->add_property ("val", get_mmc_control () ? "yes" : "no");
1201 child = opthead->add_child ("midi-control");
1202 child->add_property ("val", get_midi_control () ? "yes" : "no");
1203 child = opthead->add_child ("midi-feedback");
1204 child->add_property ("val", get_midi_feedback () ? "yes" : "no");
1205 child = opthead->add_child ("do-not-record-plugins");
1206 child->add_property ("val", get_do_not_record_plugins () ? "yes" : "no");
1207 child = opthead->add_child ("auto-crossfade");
1208 child->add_property ("val", get_crossfades_active () ? "yes" : "no");
1209 child = opthead->add_child ("audible-click");
1210 child->add_property ("val", get_clicking () ? "yes" : "no");
1212 if (click_sound.length()) {
1213 child = opthead->add_child ("click-sound");
1214 child->add_property ("val", click_sound);
1217 if (click_emphasis_sound.length()) {
1218 child = opthead->add_child ("click-emphasis-sound");
1219 child->add_property ("val", click_emphasis_sound);
1222 child = opthead->add_child ("solo-model");
1223 child->add_property ("val", _solo_model == SoloBus ? "SoloBus" : "InverseMute");
1225 child = opthead->add_child ("layer-model");
1226 switch (layer_model) {
1228 child->add_property ("val", X_("LaterHigher"));
1231 child->add_property ("val", X_("MoveAddHigher"));
1234 child->add_property ("val", X_("AddHigher"));
1238 child = opthead->add_child ("xfade-model");
1239 switch (xfade_model) {
1241 child->add_property ("val", X_("Full"));
1243 case ShortCrossfade:
1244 child->add_property ("val", X_("Short"));
1247 child = opthead->add_child ("short-xfade-length");
1248 /* store as fractions of a second */
1249 snprintf (buf, sizeof(buf)-1, "%f",
1250 (float) Crossfade::short_xfade_length() / frame_rate());
1251 child->add_property ("val", buf);
1253 child = opthead->add_child ("full-xfades-unmuted");
1254 child->add_property ("val", crossfades_active ? "yes" : "no");
1260 Session::get_state()
1266 Session::get_template()
1268 /* if we don't disable rec-enable, diskstreams
1269 will believe they need to store their capture
1270 sources in their state node.
1275 return state(false);
1279 Session::state(bool full_state)
1281 XMLNode* node = new XMLNode("Session");
1284 // store libardour version, just in case
1286 snprintf(buf, sizeof(buf)-1, "%d.%d.%d",
1287 libardour_major_version, libardour_minor_version, libardour_micro_version);
1288 node->add_property("version", string(buf));
1290 /* store configuration settings */
1294 /* store the name */
1295 node->add_property ("name", _name);
1297 if (session_dirs.size() > 1) {
1301 vector<space_and_path>::iterator i = session_dirs.begin();
1302 vector<space_and_path>::iterator next;
1304 ++i; /* skip the first one */
1308 while (i != session_dirs.end()) {
1312 if (next != session_dirs.end()) {
1322 child = node->add_child ("Path");
1323 child->add_content (p);
1327 node->add_child_nocopy (get_options());
1329 child = node->add_child ("Sources");
1332 LockMonitor sl (source_lock, __LINE__, __FILE__);
1334 for (SourceList::iterator siter = sources.begin(); siter != sources.end(); ++siter) {
1336 /* Don't save information about FileSources that are empty */
1340 if ((fs = dynamic_cast<FileSource*> ((*siter).second)) != 0) {
1341 DestructiveFileSource* dfs = dynamic_cast<DestructiveFileSource*> (fs);
1343 /* destructive file sources are OK if they are empty, because
1344 we will re-use them every time.
1348 if (fs->length() == 0) {
1354 child->add_child_nocopy ((*siter).second->get_state());
1358 child = node->add_child ("Regions");
1361 LockMonitor rl (region_lock, __LINE__, __FILE__);
1363 for (AudioRegionList::const_iterator i = audio_regions.begin(); i != audio_regions.end(); ++i) {
1365 /* only store regions not attached to playlists */
1367 if ((*i).second->playlist() == 0) {
1368 child->add_child_nocopy (i->second->state (true));
1373 child = node->add_child ("DiskStreams");
1376 RWLockMonitor dl (diskstream_lock, false, __LINE__, __FILE__);
1377 for (DiskStreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
1378 if (!(*i)->hidden()) {
1379 child->add_child_nocopy ((*i)->get_state());
1384 node->add_child_nocopy (_locations.get_state());
1386 child = node->add_child ("Connections");
1388 LockMonitor lm (connection_lock, __LINE__, __FILE__);
1389 for (ConnectionList::iterator i = _connections.begin(); i != _connections.end(); ++i) {
1390 if (!(*i)->system_dependent()) {
1391 child->add_child_nocopy ((*i)->get_state());
1396 child = node->add_child ("Routes");
1398 RWLockMonitor lm (route_lock, false, __LINE__, __FILE__);
1400 RoutePublicOrderSorter cmp;
1401 RouteList public_order(routes);
1402 public_order.sort (cmp);
1404 for (RouteList::iterator i = public_order.begin(); i != public_order.end(); ++i) {
1405 if (!(*i)->hidden()) {
1407 child->add_child_nocopy ((*i)->get_state());
1409 child->add_child_nocopy ((*i)->get_template());
1416 child = node->add_child ("EditGroups");
1417 for (list<RouteGroup *>::iterator i = edit_groups.begin(); i != edit_groups.end(); ++i) {
1418 child->add_child_nocopy ((*i)->get_state());
1421 child = node->add_child ("MixGroups");
1422 for (list<RouteGroup *>::iterator i = mix_groups.begin(); i != mix_groups.end(); ++i) {
1423 child->add_child_nocopy ((*i)->get_state());
1426 child = node->add_child ("Playlists");
1427 for (PlaylistList::iterator i = playlists.begin(); i != playlists.end(); ++i) {
1428 if (!(*i)->hidden()) {
1429 if (!(*i)->empty()) {
1431 child->add_child_nocopy ((*i)->get_state());
1433 child->add_child_nocopy ((*i)->get_template());
1439 child = node->add_child ("UnusedPlaylists");
1440 for (PlaylistList::iterator i = unused_playlists.begin(); i != unused_playlists.end(); ++i) {
1441 if (!(*i)->hidden()) {
1442 if (!(*i)->empty()) {
1444 child->add_child_nocopy ((*i)->get_state());
1446 child->add_child_nocopy ((*i)->get_template());
1454 child = node->add_child ("Click");
1455 child->add_child_nocopy (_click_io->state (full_state));
1459 child = node->add_child ("NamedSelections");
1460 for (NamedSelectionList::iterator i = named_selections.begin(); i != named_selections.end(); ++i) {
1462 child->add_child_nocopy ((*i)->get_state());
1467 node->add_child_nocopy (_tempo_map->get_state());
1470 node->add_child_copy (*_extra_xml);
1477 Session::set_state (const XMLNode& node)
1481 const XMLProperty* prop;
1484 _state_of_the_state = StateOfTheState (_state_of_the_state|CannotSave);
1486 if (node.name() != "Session"){
1487 fatal << _("programming error: Session: incorrect XML node sent to set_state()") << endmsg;
1491 StateManager::prohibit_save ();
1493 if ((prop = node.property ("name")) != 0) {
1494 _name = prop->value ();
1497 IO::disable_ports ();
1498 IO::disable_connecting ();
1500 /* Object loading order:
1517 if (use_config_midi_ports ()) {
1520 if ((child = find_named_node (node, "Path")) != 0) {
1521 /* XXX this XML content stuff horrible API design */
1522 string raid_path = _path + ':' + child->children().front()->content();
1523 setup_raid_path (raid_path);
1525 /* the path is already set */
1528 if ((child = find_named_node (node, "extra")) != 0) {
1529 _extra_xml = new XMLNode (*child);
1532 if ((child = find_named_node (node, "Options")) == 0) {
1533 error << _("Session: XML state has no options section") << endmsg;
1534 } else if (load_options (*child)) {
1537 if ((child = find_named_node (node, "Sources")) == 0) {
1538 error << _("Session: XML state has no sources section") << endmsg;
1540 } else if (load_sources (*child)) {
1544 if ((child = find_named_node (node, "Regions")) == 0) {
1545 error << _("Session: XML state has no Regions section") << endmsg;
1547 } else if (load_regions (*child)) {
1551 if ((child = find_named_node (node, "Playlists")) == 0) {
1552 error << _("Session: XML state has no playlists section") << endmsg;
1554 } else if (load_playlists (*child)) {
1558 if ((child = find_named_node (node, "UnusedPlaylists")) == 0) {
1560 } else if (load_unused_playlists (*child)) {
1564 if ((child = find_named_node (node, "NamedSelections")) != 0) {
1565 if (load_named_selections (*child)) {
1570 if ((child = find_named_node (node, "DiskStreams")) == 0) {
1571 error << _("Session: XML state has no diskstreams section") << endmsg;
1573 } else if (load_diskstreams (*child)) {
1577 if ((child = find_named_node (node, "Connections")) == 0) {
1578 error << _("Session: XML state has no connections section") << endmsg;
1580 } else if (load_connections (*child)) {
1584 if ((child = find_named_node (node, "Locations")) == 0) {
1585 error << _("Session: XML state has no locations section") << endmsg;
1587 } else if (_locations.set_state (*child)) {
1593 if ((location = _locations.auto_loop_location()) != 0) {
1594 set_auto_loop_location (location);
1597 if ((location = _locations.auto_punch_location()) != 0) {
1598 set_auto_punch_location (location);
1601 if ((location = _locations.end_location()) == 0) {
1602 _locations.add (end_location);
1604 delete end_location;
1605 end_location = location;
1608 if ((location = _locations.start_location()) == 0) {
1609 _locations.add (start_location);
1611 delete start_location;
1612 start_location = location;
1615 _locations.save_state (_("initial state"));
1617 if ((child = find_named_node (node, "EditGroups")) == 0) {
1618 error << _("Session: XML state has no edit groups section") << endmsg;
1620 } else if (load_edit_groups (*child)) {
1624 if ((child = find_named_node (node, "MixGroups")) == 0) {
1625 error << _("Session: XML state has no mix groups section") << endmsg;
1627 } else if (load_mix_groups (*child)) {
1631 if ((child = find_named_node (node, "TempoMap")) == 0) {
1632 error << _("Session: XML state has no Tempo Map section") << endmsg;
1634 } else if (_tempo_map->set_state (*child)) {
1638 if ((child = find_named_node (node, "Routes")) == 0) {
1639 error << _("Session: XML state has no routes section") << endmsg;
1641 } else if (load_routes (*child)) {
1645 if ((child = find_named_node (node, "Click")) == 0) {
1646 warning << _("Session: XML state has no click section") << endmsg;
1647 } else if (_click_io) {
1648 _click_io->set_state (*child);
1651 /* OK, now we can set edit mode */
1653 set_edit_mode (pending_edit_mode);
1655 /* here beginneth the second phase ... */
1657 StateReady (); /* EMIT SIGNAL */
1659 _state_of_the_state = Clean;
1661 StateManager::allow_save (_("initial state"), true);
1663 if (state_was_pending) {
1664 save_state (_current_snapshot_name);
1665 remove_pending_capture_state ();
1666 state_was_pending = false;
1672 /* we failed, re-enable state saving but don't actually save internal state */
1673 StateManager::allow_save (X_("ignored"), false);
1678 Session::load_routes (const XMLNode& node)
1681 XMLNodeConstIterator niter;
1684 nlist = node.children();
1688 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1690 if ((route = XMLRouteFactory (**niter)) == 0) {
1691 error << _("Session: cannot create Route from XML description.") << endmsg;
1702 Session::XMLRouteFactory (const XMLNode& node)
1704 if (node.name() != "Route") {
1708 if (node.property ("diskstream") != 0 || node.property ("diskstream-id") != 0) {
1709 return new AudioTrack (*this, node);
1711 return new Route (*this, node);
1716 Session::load_regions (const XMLNode& node)
1719 XMLNodeConstIterator niter;
1720 AudioRegion* region;
1722 nlist = node.children();
1726 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1728 if ((region = XMLRegionFactory (**niter, false)) == 0) {
1729 error << _("Session: cannot create Region from XML description.") << endmsg;
1737 Session::XMLRegionFactory (const XMLNode& node, bool full)
1739 const XMLProperty* prop;
1742 AudioRegion::SourceList sources;
1743 uint32_t nchans = 1;
1746 if (node.name() != X_("Region")) {
1750 if ((prop = node.property (X_("channels"))) != 0) {
1751 nchans = atoi (prop->value().c_str());
1755 if ((prop = node.property (X_("source-0"))) == 0) {
1756 if ((prop = node.property ("source")) == 0) {
1757 error << _("Session: XMLNode describing a AudioRegion is incomplete (no source)") << endmsg;
1762 sscanf (prop->value().c_str(), "%" PRIu64, &s_id);
1764 if ((source = get_source (s_id)) == 0) {
1765 error << string_compose(_("Session: XMLNode describing a AudioRegion references an unknown source id =%1"), s_id) << endmsg;
1769 sources.push_back(source);
1771 /* pickup other channels */
1773 for (uint32_t n=1; n < nchans; ++n) {
1774 snprintf (buf, sizeof(buf), X_("source-%d"), n);
1775 if ((prop = node.property (buf)) != 0) {
1776 sscanf (prop->value().c_str(), "%" PRIu64, &s_id);
1778 if ((source = get_source (s_id)) == 0) {
1779 error << string_compose(_("Session: XMLNode describing a AudioRegion references an unknown source id =%1"), s_id) << endmsg;
1782 sources.push_back(source);
1788 return new AudioRegion (sources, node);
1791 catch (failed_constructor& err) {
1797 Session::get_sources_as_xml ()
1800 XMLNode* node = new XMLNode (X_("Sources"));
1801 LockMonitor lm (source_lock, __LINE__, __FILE__);
1803 for (SourceList::iterator i = sources.begin(); i != sources.end(); ++i) {
1804 node->add_child_nocopy ((*i).second->get_state());
1811 Session::path_from_region_name (string name, string identifier)
1813 char buf[PATH_MAX+1];
1815 string dir = discover_best_sound_dir ();
1817 for (n = 0; n < 999999; ++n) {
1818 if (identifier.length()) {
1819 snprintf (buf, sizeof(buf), "%s/%s%s%" PRIu32 ".wav", dir.c_str(), name.c_str(),
1820 identifier.c_str(), n);
1822 snprintf (buf, sizeof(buf), "%s/%s-%" PRIu32 ".wav", dir.c_str(), name.c_str(), n);
1824 if (access (buf, F_OK) != 0) {
1834 Session::load_sources (const XMLNode& node)
1837 XMLNodeConstIterator niter;
1840 nlist = node.children();
1844 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1846 if ((source = XMLSourceFactory (**niter)) == 0) {
1847 error << _("Session: cannot create Source from XML description.") << endmsg;
1855 Session::XMLSourceFactory (const XMLNode& node)
1859 if (node.name() != "Source") {
1864 if (node.property (X_("destructive")) != 0) {
1865 src = new DestructiveFileSource (node, frame_rate());
1867 src = new FileSource (node, frame_rate());
1871 catch (failed_constructor& err) {
1874 src = ExternalSource::create (node);
1877 catch (failed_constructor& err) {
1878 error << _("Found a sound file that cannot be used by Ardour. See the progammers.") << endmsg;
1887 Session::save_template (string template_name)
1890 string xml_path, bak_path, template_path;
1892 if (_state_of_the_state & CannotSave) {
1897 string dir = template_dir();
1899 if ((dp = opendir (dir.c_str()))) {
1902 if (mkdir (dir.c_str(), S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH)<0) {
1903 error << string_compose(_("Could not create mix templates directory \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
1908 tree.set_root (&get_template());
1911 xml_path += template_name;
1912 xml_path += _template_suffix;
1914 ifstream in(xml_path.c_str());
1917 warning << string_compose(_("Template \"%1\" already exists - new version not created"), template_name) << endmsg;
1923 if (!tree.write (xml_path)) {
1924 error << _("mix template not saved") << endmsg;
1932 Session::rename_template (string old_name, string new_name)
1934 string old_path = template_dir() + old_name + _template_suffix;
1935 string new_path = template_dir() + new_name + _template_suffix;
1937 return rename (old_path.c_str(), new_path.c_str());
1941 Session::delete_template (string name)
1943 string template_path = template_dir();
1944 template_path += name;
1945 template_path += _template_suffix;
1947 return remove (template_path.c_str());
1951 Session::refresh_disk_space ()
1954 struct statfs statfsbuf;
1955 vector<space_and_path>::iterator i;
1956 LockMonitor lm (space_lock, __LINE__, __FILE__);
1959 /* get freespace on every FS that is part of the session path */
1961 _total_free_4k_blocks = 0;
1963 for (i = session_dirs.begin(); i != session_dirs.end(); ++i) {
1964 statfs ((*i).path.c_str(), &statfsbuf);
1966 scale = statfsbuf.f_bsize/4096.0;
1968 (*i).blocks = (uint32_t) floor (statfsbuf.f_bavail * scale);
1969 _total_free_4k_blocks += (*i).blocks;
1975 Session::ensure_sound_dir (string path, string& result)
1980 /* Ensure that the parent directory exists */
1982 if (mkdir (path.c_str(), 0775)) {
1983 if (errno != EEXIST) {
1984 error << string_compose(_("cannot create session directory \"%1\"; ignored"), path) << endmsg;
1989 /* Ensure that the sounds directory exists */
1993 result += sound_dir_name;
1995 if (mkdir (result.c_str(), 0775)) {
1996 if (errno != EEXIST) {
1997 error << string_compose(_("cannot create sounds directory \"%1\"; ignored"), result) << endmsg;
2004 dead += dead_sound_dir_name;
2006 if (mkdir (dead.c_str(), 0775)) {
2007 if (errno != EEXIST) {
2008 error << string_compose(_("cannot create dead sounds directory \"%1\"; ignored"), dead) << endmsg;
2015 peak += peak_dir_name;
2017 if (mkdir (peak.c_str(), 0775)) {
2018 if (errno != EEXIST) {
2019 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 /* destructive files all go into the same place */
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 () const
2250 res += sound_dir_name;
2256 Session::tape_dir () const
2259 res += tape_dir_name;
2265 Session::peak_dir () const
2268 res += peak_dir_name;
2274 Session::automation_dir () const
2277 res += "automation/";
2282 Session::template_dir ()
2284 string path = get_user_ardour_path();
2285 path += "templates/";
2291 Session::template_path ()
2295 path += get_user_ardour_path();
2296 if (path[path.length()-1] != ':') {
2299 path += get_system_ardour_path();
2301 vector<string> split_path;
2303 split (path, split_path, ':');
2306 for (vector<string>::iterator i = split_path.begin(); i != split_path.end(); ++i) {
2308 path += "templates/";
2310 if (distance (i, split_path.end()) != 1) {
2319 Session::load_connections (const XMLNode& node)
2321 XMLNodeList nlist = node.children();
2322 XMLNodeConstIterator niter;
2326 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2327 if ((*niter)->name() == "InputConnection") {
2328 add_connection (new ARDOUR::InputConnection (**niter));
2329 } else if ((*niter)->name() == "OutputConnection") {
2330 add_connection (new ARDOUR::OutputConnection (**niter));
2332 error << string_compose(_("Unknown node \"%1\" found in Connections list from state file"), (*niter)->name()) << endmsg;
2341 Session::load_edit_groups (const XMLNode& node)
2343 return load_route_groups (node, true);
2347 Session::load_mix_groups (const XMLNode& node)
2349 return load_route_groups (node, false);
2353 Session::load_route_groups (const XMLNode& node, bool edit)
2355 XMLNodeList nlist = node.children();
2356 XMLNodeConstIterator niter;
2361 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2362 if ((*niter)->name() == "RouteGroup") {
2364 route = add_edit_group ("");
2365 route->set_state (**niter);
2367 route = add_mix_group ("");
2368 route->set_state (**niter);
2377 Session::swap_configuration(Configuration** new_config)
2379 RWLockMonitor lm (route_lock, true, __LINE__, __FILE__); // jlc - WHY?
2380 Configuration* tmp = *new_config;
2381 *new_config = Config;
2387 Session::copy_configuration(Configuration* new_config)
2389 RWLockMonitor lm (route_lock, true, __LINE__, __FILE__);
2390 new_config = new Configuration(*Config);
2394 state_file_filter (const string &str, void *arg)
2396 return (str.length() > strlen(Session::statefile_suffix()) &&
2397 str.find (Session::statefile_suffix()) == (str.length() - strlen (Session::statefile_suffix())));
2401 bool operator()(const string* a, const string* b) {
2407 remove_end(string* state)
2409 string statename(*state);
2411 string::size_type start,end;
2412 if ((start = statename.find_last_of ('/')) != string::npos) {
2413 statename = statename.substr (start+1);
2416 if ((end = statename.rfind(".ardour")) < 0) {
2417 end = statename.length();
2420 return new string(statename.substr (0, end));
2424 Session::possible_states (string path)
2426 PathScanner scanner;
2427 vector<string*>* states = scanner (path, state_file_filter, 0, false, false);
2429 transform(states->begin(), states->end(), states->begin(), remove_end);
2432 sort (states->begin(), states->end(), cmp);
2438 Session::possible_states () const
2440 return possible_states(_path);
2444 Session::auto_save()
2446 save_state (_current_snapshot_name);
2450 Session::add_edit_group (string name)
2452 RouteGroup* rg = new RouteGroup (*this, name);
2453 edit_groups.push_back (rg);
2454 edit_group_added (rg); /* EMIT SIGNAL */
2460 Session::add_mix_group (string name)
2462 RouteGroup* rg = new RouteGroup (*this, name, RouteGroup::Relative);
2463 mix_groups.push_back (rg);
2464 mix_group_added (rg); /* EMIT SIGNAL */
2470 Session::remove_edit_group (RouteGroup& rg)
2472 list<RouteGroup*>::iterator i;
2474 if ((i = find (edit_groups.begin(), edit_groups.end(), &rg)) != edit_groups.end()) {
2475 (*i)->apply (&Route::drop_edit_group, this);
2476 edit_groups.erase (i);
2477 edit_group_removed (); /* EMIT SIGNAL */
2484 Session::remove_mix_group (RouteGroup& rg)
2486 list<RouteGroup*>::iterator i;
2488 if ((i = find (mix_groups.begin(), mix_groups.end(), &rg)) != mix_groups.end()) {
2489 (*i)->apply (&Route::drop_mix_group, this);
2490 mix_groups.erase (i);
2491 mix_group_removed (); /* EMIT SIGNAL */
2498 Session::mix_group_by_name (string name)
2500 list<RouteGroup *>::iterator i;
2502 for (i = mix_groups.begin(); i != mix_groups.end(); ++i) {
2503 if ((*i)->name() == name) {
2511 Session::edit_group_by_name (string name)
2513 list<RouteGroup *>::iterator i;
2515 for (i = edit_groups.begin(); i != edit_groups.end(); ++i) {
2516 if ((*i)->name() == name) {
2524 Session::set_meter_hold (float val)
2527 MeterHoldChanged(); // emit
2531 Session::set_meter_falloff (float val)
2533 _meter_falloff = val;
2534 MeterFalloffChanged(); // emit
2539 Session::begin_reversible_command (string name, UndoAction* private_undo)
2541 current_cmd.clear ();
2542 current_cmd.set_name (name);
2545 current_cmd.add_undo (*private_undo);
2550 Session::commit_reversible_command (UndoAction* private_redo)
2555 current_cmd.add_redo_no_execute (*private_redo);
2558 gettimeofday (&now, 0);
2559 current_cmd.set_timestamp (now);
2561 history.add (current_cmd);
2564 Session::GlobalRouteBooleanState
2565 Session::get_global_route_boolean (bool (Route::*method)(void) const)
2567 GlobalRouteBooleanState s;
2568 RWLockMonitor lm (route_lock, false, __LINE__, __FILE__);
2570 for (RouteList::iterator i = routes.begin(); i != routes.end(); ++i) {
2571 if (!(*i)->hidden()) {
2572 RouteBooleanState v;
2575 v.second = ((*i)->*method)();
2584 Session::GlobalRouteMeterState
2585 Session::get_global_route_metering ()
2587 GlobalRouteMeterState s;
2588 RWLockMonitor lm (route_lock, false, __LINE__, __FILE__);
2590 for (RouteList::iterator i = routes.begin(); i != routes.end(); ++i) {
2591 if (!(*i)->hidden()) {
2595 v.second = (*i)->meter_point();
2605 Session::set_global_route_metering (GlobalRouteMeterState s, void* arg)
2607 for (GlobalRouteMeterState::iterator i = s.begin(); i != s.end(); ++i) {
2608 i->first->set_meter_point (i->second, arg);
2613 Session::set_global_route_boolean (GlobalRouteBooleanState s, void (Route::*method)(bool, void*), void* arg)
2615 for (GlobalRouteBooleanState::iterator i = s.begin(); i != s.end(); ++i) {
2616 (i->first->*method) (i->second, arg);
2621 Session::set_global_mute (GlobalRouteBooleanState s, void* src)
2623 set_global_route_boolean (s, &Route::set_mute, src);
2627 Session::set_global_solo (GlobalRouteBooleanState s, void* src)
2629 set_global_route_boolean (s, &Route::set_solo, src);
2633 Session::set_global_record_enable (GlobalRouteBooleanState s, void* src)
2635 set_global_route_boolean (s, &Route::set_record_enable, src);
2639 Session::global_mute_memento (void* src)
2641 return sigc::bind (mem_fun (*this, &Session::set_global_mute), get_global_route_boolean (&Route::muted), src);
2645 Session::global_metering_memento (void* src)
2647 return sigc::bind (mem_fun (*this, &Session::set_global_route_metering), get_global_route_metering (), src);
2651 Session::global_solo_memento (void* src)
2653 return sigc::bind (mem_fun (*this, &Session::set_global_solo), get_global_route_boolean (&Route::soloed), src);
2657 Session::global_record_enable_memento (void* src)
2659 return sigc::bind (mem_fun (*this, &Session::set_global_record_enable), get_global_route_boolean (&Route::record_enabled), src);
2663 template_filter (const string &str, void *arg)
2665 return (str.length() > strlen(Session::template_suffix()) &&
2666 str.find (Session::template_suffix()) == (str.length() - strlen (Session::template_suffix())));
2670 Session::get_template_list (list<string> &template_names)
2672 vector<string *> *templates;
2673 PathScanner scanner;
2676 path = template_path ();
2678 templates = scanner (path, template_filter, 0, false, true);
2680 vector<string*>::iterator i;
2681 for (i = templates->begin(); i != templates->end(); ++i) {
2682 string fullpath = *(*i);
2685 start = fullpath.find_last_of ('/') + 1;
2686 if ((end = fullpath.find_last_of ('.')) <0) {
2687 end = fullpath.length();
2690 template_names.push_back(fullpath.substr(start, (end-start)));
2695 Session::read_favorite_dirs (FavoriteDirs & favs)
2697 string path = get_user_ardour_path();
2698 path += "/favorite_dirs";
2700 ifstream fav (path.c_str());
2705 if (errno != ENOENT) {
2706 //error << string_compose (_("cannot open favorite file %1 (%2)"), path, strerror (errno)) << endmsg;
2717 getline(fav, newfav);
2723 favs.push_back (newfav);
2730 Session::write_favorite_dirs (FavoriteDirs & favs)
2732 string path = get_user_ardour_path();
2733 path += "/favorite_dirs";
2735 ofstream fav (path.c_str());
2741 for (FavoriteDirs::iterator i = favs.begin(); i != favs.end(); ++i) {
2742 fav << (*i) << endl;
2749 accept_all_non_peak_files (const string& path, void *arg)
2751 return (path.length() > 5 && path.find (".peak") != (path.length() - 5));
2755 accept_all_state_files (const string& path, void *arg)
2757 return (path.length() > 7 && path.find (".ardour") == (path.length() - 7));
2761 Session::find_all_sources (string path, set<string>& result)
2766 if (!tree.read (path)) {
2770 if ((node = find_named_node (*tree.root(), "Sources")) == 0) {
2775 XMLNodeConstIterator niter;
2777 nlist = node->children();
2781 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2785 if ((prop = (*niter)->property (X_("name"))) == 0) {
2789 if (prop->value()[0] == '/') {
2790 /* external file, ignore */
2794 string path = _path; /* /-terminated */
2795 path += sound_dir_name;
2797 path += prop->value();
2799 result.insert (path);
2806 Session::find_all_sources_across_snapshots (set<string>& result, bool exclude_this_snapshot)
2808 PathScanner scanner;
2809 vector<string*>* state_files;
2811 string this_snapshot_path;
2817 if (ripped[ripped.length()-1] == '/') {
2818 ripped = ripped.substr (0, ripped.length() - 1);
2821 state_files = scanner (ripped, accept_all_state_files, (void *) 0, false, true);
2823 if (state_files == 0) {
2828 this_snapshot_path = _path;
2829 this_snapshot_path += _current_snapshot_name;
2830 this_snapshot_path += _statefile_suffix;
2832 for (vector<string*>::iterator i = state_files->begin(); i != state_files->end(); ++i) {
2834 if (exclude_this_snapshot && **i == this_snapshot_path) {
2838 if (find_all_sources (**i, result) < 0) {
2847 Session::cleanup_sources (Session::cleanup_report& rep)
2849 vector<Source*> dead_sources;
2850 vector<Playlist*> playlists_tbd;
2851 PathScanner scanner;
2853 vector<space_and_path>::iterator i;
2854 vector<space_and_path>::iterator nexti;
2855 vector<string*>* soundfiles;
2856 vector<string> unused;
2857 set<string> all_sources;
2862 _state_of_the_state = (StateOfTheState) (_state_of_the_state | InCleanup);
2864 /* step 1: consider deleting all unused playlists */
2866 for (PlaylistList::iterator x = unused_playlists.begin(); x != unused_playlists.end(); ++x) {
2869 status = AskAboutPlaylistDeletion (*x);
2878 playlists_tbd.push_back (*x);
2882 /* leave it alone */
2887 /* now delete any that were marked for deletion */
2889 for (vector<Playlist*>::iterator x = playlists_tbd.begin(); x != playlists_tbd.end(); ++x) {
2890 PlaylistList::iterator foo;
2892 if ((foo = unused_playlists.find (*x)) != unused_playlists.end()) {
2893 unused_playlists.erase (foo);
2898 /* step 2: clear the undo/redo history for all playlists */
2900 for (PlaylistList::iterator x = playlists.begin(); x != playlists.end(); ++x) {
2901 (*x)->drop_all_states ();
2904 /* step 3: find all un-referenced sources */
2909 for (SourceList::iterator i = sources.begin(); i != sources.end(); ) {
2911 SourceList::iterator tmp;
2916 /* only remove files that are not in use and have some size
2917 to them. otherwise we remove the current "nascent"
2921 if ((*i).second->use_cnt() == 0 && (*i).second->length() > 0) {
2922 dead_sources.push_back (i->second);
2924 /* remove this source from our own list to avoid us
2925 adding it to the list of all sources below
2934 /* Step 4: get rid of all regions in the region list that use any dead sources
2935 in case the sources themselves don't go away (they might be referenced in
2939 for (vector<Source*>::iterator i = dead_sources.begin(); i != dead_sources.end();++i) {
2941 for (AudioRegionList::iterator r = audio_regions.begin(); r != audio_regions.end(); ) {
2942 AudioRegionList::iterator tmp;
2950 for (uint32_t n = 0; n < ar->n_channels(); ++n) {
2951 if (&ar->source (n) == (*i)) {
2952 /* this region is dead */
2961 /* build a list of all the possible sound directories for the session */
2963 for (i = session_dirs.begin(); i != session_dirs.end(); ) {
2968 sound_path += (*i).path;
2969 sound_path += sound_dir_name;
2971 if (nexti != session_dirs.end()) {
2978 /* now do the same thing for the files that ended up in the sounds dir(s)
2979 but are not referenced as sources in any snapshot.
2982 soundfiles = scanner (sound_path, accept_all_non_peak_files, (void *) 0, false, true);
2984 if (soundfiles == 0) {
2988 /* find all sources, but don't use this snapshot because the
2989 state file on disk still references sources we may have already
2993 find_all_sources_across_snapshots (all_sources, true);
2995 /* add our current source list
2998 for (SourceList::iterator i = sources.begin(); i != sources.end(); ++i) {
3000 ExternalSource* sfs;
3002 if ((fs = dynamic_cast<FileSource*> ((*i).second)) != 0) {
3003 all_sources.insert (fs->path());
3004 } else if ((sfs = dynamic_cast<ExternalSource*> ((*i).second)) != 0) {
3005 all_sources.insert (sfs->path());
3009 for (vector<string*>::iterator x = soundfiles->begin(); x != soundfiles->end(); ++x) {
3014 for (set<string>::iterator i = all_sources.begin(); i != all_sources.end(); ++i) {
3024 unused.push_back (spath);
3028 /* now try to move all unused files into the "dead_sounds" directory(ies) */
3030 for (vector<string>::iterator x = unused.begin(); x != unused.end(); ++x) {
3031 struct stat statbuf;
3033 rep.paths.push_back (*x);
3034 if (stat ((*x).c_str(), &statbuf) == 0) {
3035 rep.space += statbuf.st_size;
3040 /* don't move the file across filesystems, just
3041 stick it in the `dead_sound_dir_name' directory
3042 on whichever filesystem it was already on.
3045 newpath = PBD::dirname (*x);
3046 newpath = PBD::dirname (newpath);
3049 newpath += dead_sound_dir_name;
3051 newpath += PBD::basename ((*x));
3053 if (access (newpath.c_str(), F_OK) == 0) {
3055 /* the new path already exists, try versioning */
3057 char buf[PATH_MAX+1];
3061 snprintf (buf, sizeof (buf), "%s.%d", newpath.c_str(), version);
3064 while (access (newpath_v.c_str(), F_OK) == 0 && version < 999) {
3065 snprintf (buf, sizeof (buf), "%s.%d", newpath.c_str(), ++version);
3069 if (version == 999) {
3070 error << string_compose (_("there are already 1000 files with names like %1; versioning discontinued"),
3074 newpath = newpath_v;
3079 /* it doesn't exist, or we can't read it or something */
3083 if (::rename ((*x).c_str(), newpath.c_str()) != 0) {
3084 error << string_compose (_("cannot rename audio file source from %1 to %2 (%3)"),
3085 (*x), newpath, strerror (errno))
3091 /* see if there an easy to find peakfile for this file, and remove it.
3094 string peakpath = (*x).substr (0, (*x).find_last_of ('.'));
3095 peakpath += ".peak";
3097 if (access (peakpath.c_str(), W_OK) == 0) {
3098 if (::unlink (peakpath.c_str()) != 0) {
3099 error << string_compose (_("cannot remove peakfile %1 for %2 (%3)"),
3100 peakpath, _path, strerror (errno))
3102 /* try to back out */
3103 rename (newpath.c_str(), _path.c_str());
3112 /* dump the history list */
3116 /* save state so we don't end up a session file
3117 referring to non-existent sources.
3123 _state_of_the_state = (StateOfTheState) (_state_of_the_state & ~InCleanup);
3128 Session::cleanup_trash_sources (Session::cleanup_report& rep)
3130 vector<space_and_path>::iterator i;
3131 string dead_sound_dir;
3132 struct dirent* dentry;
3133 struct stat statbuf;
3139 for (i = session_dirs.begin(); i != session_dirs.end(); ++i) {
3141 dead_sound_dir = (*i).path;
3142 dead_sound_dir += dead_sound_dir_name;
3144 if ((dead = opendir (dead_sound_dir.c_str())) == 0) {
3148 while ((dentry = readdir (dead)) != 0) {
3150 /* avoid '.' and '..' */
3152 if ((dentry->d_name[0] == '.' && dentry->d_name[1] == '\0') ||
3153 (dentry->d_name[2] == '\0' && dentry->d_name[0] == '.' && dentry->d_name[1] == '.')) {
3159 fullpath = dead_sound_dir;
3161 fullpath += dentry->d_name;
3163 if (stat (fullpath.c_str(), &statbuf)) {
3167 if (!S_ISREG (statbuf.st_mode)) {
3171 if (unlink (fullpath.c_str())) {
3172 error << string_compose (_("cannot remove dead sound file %1 (%2)"),
3173 fullpath, strerror (errno))
3177 rep.paths.push_back (dentry->d_name);
3178 rep.space += statbuf.st_size;
3189 Session::set_dirty ()
3191 bool was_dirty = dirty();
3193 _state_of_the_state = StateOfTheState (_state_of_the_state | Dirty);
3196 DirtyChanged(); /* EMIT SIGNAL */
3202 Session::set_clean ()
3204 bool was_dirty = dirty();
3206 _state_of_the_state = Clean;
3209 DirtyChanged(); /* EMIT SIGNAL */