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 _have_captured = false;
159 _worst_output_latency = 0;
160 _worst_input_latency = 0;
161 _worst_track_latency = 0;
162 _state_of_the_state = StateOfTheState(CannotSave|InitialConnecting|Loading);
165 butler_mixdown_buffer = 0;
166 butler_gain_buffer = 0;
168 generic_midi_control_protocol = 0;
170 midi_feedback = false;
173 post_transport_work = PostTransportWork (0);
174 atomic_set (&butler_should_do_transport_work, 0);
175 atomic_set (&butler_active, 0);
176 atomic_set (&_playback_load, 100);
177 atomic_set (&_capture_load, 100);
178 atomic_set (&_playback_load_min, 100);
179 atomic_set (&_capture_load_min, 100);
180 pending_audition_region = 0;
182 pending_edit_mode = _edit_mode;
186 input_auto_connect = AutoConnectOption (0);
187 output_auto_connect = AutoConnectOption (0);
188 waiting_to_start = false;
190 _gain_automation_buffer = 0;
191 _pan_automation_buffer = 0;
193 pending_abort = false;
194 layer_model = MoveAddHigher;
195 xfade_model = ShortCrossfade;
196 destructive_index = 0;
198 /* allocate conversion buffers */
199 _conversion_buffers[ButlerContext] = new char[DiskStream::disk_io_frames() * 4];
200 _conversion_buffers[TransportContext] = new char[DiskStream::disk_io_frames() * 4];
202 /* default short fade = 15ms */
204 Crossfade::set_short_xfade_length ((jack_nframes_t) floor ((15.0 * frame_rate()) / 1000.0));
206 last_mmc_step.tv_sec = 0;
207 last_mmc_step.tv_usec = 0;
210 preroll.type = AnyTime::Frames;
212 postroll.type = AnyTime::Frames;
215 /* click sounds are unset by default, which causes us to internal
216 waveforms for clicks.
221 click_requested = false;
223 click_emphasis_data = 0;
225 click_emphasis_length = 0;
227 process_function = &Session::process_with_events;
231 _smpte_offset_negative = true;
232 last_smpte_valid = false;
234 last_rr_session_dir = session_dirs.begin();
235 refresh_disk_space ();
237 // set_default_fade (0.2, 5.0); /* steepness, millisecs */
239 /* default configuration */
241 do_not_record_plugins = false;
242 over_length_short = 2;
243 over_length_long = 10;
244 send_midi_timecode = false;
245 send_midi_machine_control = false;
246 shuttle_speed_factor = 1.0;
247 shuttle_speed_threshold = 5;
249 _meter_hold = 100; // XXX unknown units: number of calls to meter::set()
250 _meter_falloff = 1.5f; // XXX unknown units: refresh_rate
256 average_slave_delta = 1800;
257 have_first_delta_accumulator = false;
258 delta_accumulator_cnt = 0;
259 slave_state = Stopped;
261 /* default SMPTE type is 30 FPS, non-drop */
263 set_smpte_type (30.0, false);
265 _engine.GraphReordered.connect (mem_fun (*this, &Session::graph_reordered));
267 /* These are all static "per-class" signals */
269 Region::CheckNewRegion.connect (mem_fun (*this, &Session::add_region));
270 Source::SourceCreated.connect (mem_fun (*this, &Session::add_source));
271 Playlist::PlaylistCreated.connect (mem_fun (*this, &Session::add_playlist));
272 Redirect::RedirectCreated.connect (mem_fun (*this, &Session::add_redirect));
273 DiskStream::DiskStreamCreated.connect (mem_fun (*this, &Session::add_diskstream));
274 NamedSelection::NamedSelectionCreated.connect (mem_fun (*this, &Session::add_named_selection));
276 IO::MoreOutputs.connect (mem_fun (*this, &Session::ensure_passthru_buffers));
278 /* stop IO objects from doing stuff until we're ready for them */
280 IO::disable_panners ();
281 IO::disable_ports ();
282 IO::disable_connecting ();
286 Session::second_stage_init (bool new_session)
288 ExternalSource::set_peak_dir (peak_dir());
291 if (load_state (_current_snapshot_name)) {
294 remove_empty_sounds ();
297 if (start_butler_thread()) {
301 if (start_midi_thread ()) {
305 initialize_control();
307 if (init_feedback ()) {
312 if (set_state (*state_tree->root())) {
317 /* we can't save till after ::when_engine_running() is called,
318 because otherwise we save state with no connections made.
319 therefore, we reset _state_of_the_state because ::set_state()
320 will have cleared it.
322 we also have to include Loading so that any events that get
323 generated between here and the end of ::when_engine_running()
324 will be processed directly rather than queued.
327 _state_of_the_state = StateOfTheState (_state_of_the_state|CannotSave|Loading);
329 // set_auto_input (true);
330 _locations.changed.connect (mem_fun (this, &Session::locations_changed));
331 _locations.added.connect (mem_fun (this, &Session::locations_added));
332 setup_click_sounds (0);
333 setup_midi_control ();
335 /* Pay attention ... */
337 _engine.Halted.connect (mem_fun (*this, &Session::engine_halted));
338 _engine.Xrun.connect (mem_fun (*this, &Session::xrun_recovery));
340 if (_engine.running()) {
341 when_engine_running();
343 first_time_running = _engine.Running.connect (mem_fun (*this, &Session::when_engine_running));
346 send_full_time_code ();
347 _engine.transport_locate (0);
348 deliver_mmc (MIDI::MachineControl::cmdMmcReset, 0);
349 deliver_mmc (MIDI::MachineControl::cmdLocate, 0);
351 // XXX need to poke the feedback thread to send full state
354 _end_location_is_free = true;
356 _end_location_is_free = false;
363 Session::raid_path () const
367 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
372 return path.substr (0, path.length() - 1); // drop final colon
376 Session::set_raid_path (string path)
378 /* public-access to setup_raid_path() */
380 setup_raid_path (path);
384 Session::setup_raid_path (string path)
386 string::size_type colon;
390 string::size_type len = path.length();
395 if (path.length() == 0) {
399 session_dirs.clear ();
401 for (string::size_type n = 0; n < len; ++n) {
402 if (path[n] == ':') {
409 /* no multiple search path, just one location (common case) */
413 session_dirs.push_back (sp);
420 if (fspath[fspath.length()-1] != '/') {
423 fspath += sound_dir_name;
429 if (fspath[fspath.length()-1] != '/') {
432 fspath += tape_dir_name;
434 FileSource::set_search_path (fspath);
441 while ((colon = remaining.find_first_of (':')) != string::npos) {
444 sp.path = remaining.substr (0, colon);
445 session_dirs.push_back (sp);
447 /* add sounds to file search path */
450 if (fspath[fspath.length()-1] != '/') {
453 fspath += sound_dir_name;
456 /* add tape dir to file search path */
459 if (fspath[fspath.length()-1] != '/') {
462 fspath += tape_dir_name;
465 remaining = remaining.substr (colon+1);
468 if (remaining.length()) {
475 if (fspath[fspath.length()-1] != '/') {
478 fspath += sound_dir_name;
482 if (fspath[fspath.length()-1] != '/') {
485 fspath += tape_dir_name;
487 session_dirs.push_back (sp);
490 /* set the FileSource search path */
492 FileSource::set_search_path (fspath);
494 /* reset the round-robin soundfile path thingie */
496 last_rr_session_dir = session_dirs.begin();
500 Session::create (bool& new_session, string* mix_template, jack_nframes_t initial_length)
504 if (mkdir (_path.c_str(), 0755) < 0) {
505 if (errno == EEXIST) {
508 error << string_compose(_("Session: cannot create session dir \"%1\" (%2)"), _path, strerror (errno)) << endmsg;
517 if (mkdir (dir.c_str(), 0755) < 0) {
518 if (errno != EEXIST) {
519 error << string_compose(_("Session: cannot create session peakfile dir \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
526 if (mkdir (dir.c_str(), 0755) < 0) {
527 if (errno != EEXIST) {
528 error << string_compose(_("Session: cannot create session sounds dir \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
535 if (mkdir (dir.c_str(), 0755) < 0) {
536 if (errno != EEXIST) {
537 error << string_compose(_("Session: cannot create session tape dir \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
542 dir = dead_sound_dir ();
544 if (mkdir (dir.c_str(), 0755) < 0) {
545 if (errno != EEXIST) {
546 error << string_compose(_("Session: cannot create session dead sounds dir \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
551 dir = automation_dir ();
553 if (mkdir (dir.c_str(), 0755) < 0) {
554 if (errno != EEXIST) {
555 error << string_compose(_("Session: cannot create session automation dir \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
561 /* check new_session so we don't overwrite an existing one */
565 std::string in_path = *mix_template;
567 ifstream in(in_path.c_str());
570 string out_path = _path;
572 out_path += _statefile_suffix;
574 ofstream out(out_path.c_str());
579 // okay, session is set up. Treat like normal saved
580 // session from now on.
586 error << string_compose (_("Could not open %1 for writing mix template"), out_path)
592 error << string_compose (_("Could not open mix template %1 for reading"), in_path)
599 warning << _("Session already exists. Not overwriting") << endmsg;
606 /* set initial start + end point */
608 start_location->set_end (0);
609 _locations.add (start_location);
611 end_location->set_end (initial_length);
612 _locations.add (end_location);
614 _state_of_the_state = Clean;
616 if (save_state (_current_snapshot_name)) {
625 Session::load_diskstreams (const XMLNode& node)
628 XMLNodeConstIterator citer;
630 clist = node.children();
632 for (citer = clist.begin(); citer != clist.end(); ++citer) {
637 dstream = new DiskStream (*this, **citer);
638 /* added automatically by DiskStreamCreated handler */
641 catch (failed_constructor& err) {
642 error << _("Session: could not load diskstream via XML state") << endmsg;
651 Session::remove_pending_capture_state ()
656 xml_path += _current_snapshot_name;
657 xml_path += _pending_suffix;
659 unlink (xml_path.c_str());
663 Session::save_state (string snapshot_name, bool pending)
669 if (_state_of_the_state & CannotSave) {
673 tree.set_root (&get_state());
675 if (snapshot_name.empty()) {
676 snapshot_name = _current_snapshot_name;
682 xml_path += snapshot_name;
683 xml_path += _statefile_suffix;
687 // Make backup of state file
689 if ((access (xml_path.c_str(), F_OK) == 0) &&
690 (rename(xml_path.c_str(), bak_path.c_str()))) {
691 error << _("could not backup old state file, current state not saved.") << endmsg;
698 xml_path += snapshot_name;
699 xml_path += _pending_suffix;
703 if (!tree.write (xml_path)) {
704 error << string_compose (_("state could not be saved to %1"), xml_path) << endmsg;
706 /* don't leave a corrupt file lying around if it is
710 if (unlink (xml_path.c_str())) {
711 error << string_compose (_("could not remove corrupt state file %1"), xml_path) << endmsg;
714 if (rename (bak_path.c_str(), xml_path.c_str())) {
715 error << string_compose (_("could not restore state file from backup %1"), bak_path) << endmsg;
725 bool was_dirty = dirty();
727 _state_of_the_state = StateOfTheState (_state_of_the_state & ~Dirty);
730 DirtyChanged (); /* EMIT SIGNAL */
733 StateSaved (snapshot_name); /* EMIT SIGNAL */
740 Session::restore_state (string snapshot_name)
742 if (load_state (snapshot_name) == 0) {
743 set_state (*state_tree->root());
750 Session::load_state (string snapshot_name)
759 state_was_pending = false;
761 /* check for leftover pending state from a crashed capture attempt */
764 xmlpath += snapshot_name;
765 xmlpath += _pending_suffix;
767 if (!access (xmlpath.c_str(), F_OK)) {
769 /* there is pending state from a crashed capture attempt */
771 if (AskAboutPendingState()) {
772 state_was_pending = true;
776 if (!state_was_pending) {
779 xmlpath += snapshot_name;
780 xmlpath += _statefile_suffix;
783 if (access (xmlpath.c_str(), F_OK)) {
784 error << string_compose(_("%1: session state information file \"%2\" doesn't exist!"), _name, xmlpath) << endmsg;
788 state_tree = new XMLTree;
792 if (state_tree->read (xmlpath)) {
795 error << string_compose(_("Could not understand ardour file %1"), xmlpath) << endmsg;
804 Session::load_options (const XMLNode& node)
808 bool have_fade_msecs = false;
809 bool have_fade_steepness = false;
810 float fade_msecs = 0;
811 float fade_steepness = 0;
812 SlaveSource slave_src = None;
814 LocaleGuard lg (X_("POSIX"));
816 if ((child = find_named_node (node, "input-auto-connect")) != 0) {
817 if ((prop = child->property ("val")) != 0) {
818 sscanf (prop->value().c_str(), "%x", &x);
819 input_auto_connect = AutoConnectOption (x);
823 if ((child = find_named_node (node, "output-auto-connect")) != 0) {
824 if ((prop = child->property ("val")) != 0) {
825 sscanf (prop->value().c_str(), "%x", &x);
826 output_auto_connect = AutoConnectOption (x);
830 if ((child = find_named_node (node, "slave")) != 0) {
831 if ((prop = child->property ("type")) != 0) {
832 if (prop->value() == "none") {
834 } else if (prop->value() == "mtc") {
836 } else if (prop->value() == "jack") {
839 set_slave_source (slave_src, 0);
843 /* we cannot set edit mode if we are loading a session,
844 because it might destroy the playlist's positioning
847 if ((child = find_named_node (node, "edit-mode")) != 0) {
848 if ((prop = child->property ("val")) != 0) {
849 if (prop->value() == "slide") {
850 pending_edit_mode = Slide;
851 } else if (prop->value() == "splice") {
852 pending_edit_mode = Splice;
857 if ((child = find_named_node (node, "send-midi-timecode")) != 0) {
858 if ((prop = child->property ("val")) != 0) {
859 bool x = (prop->value() == "yes");
860 send_mtc = !x; /* force change in value */
864 if ((child = find_named_node (node, "send-midi-machine-control")) != 0) {
865 if ((prop = child->property ("val")) != 0) {
866 bool x = (prop->value() == "yes");
867 send_mmc = !x; /* force change in value */
868 set_send_mmc (prop->value() == "yes");
871 if ((child = find_named_node (node, "max-level")) != 0) {
872 if ((prop = child->property ("val")) != 0) {
873 max_level = atoi (prop->value().c_str());
876 if ((child = find_named_node (node, "min-level")) != 0) {
877 if ((prop = child->property ("val")) != 0) {
878 min_level = atoi (prop->value().c_str());
881 if ((child = find_named_node (node, "meter-hold")) != 0) {
882 if ((prop = child->property ("val")) != 0) {
883 _meter_hold = atof (prop->value().c_str());
886 if ((child = find_named_node (node, "meter-falloff")) != 0) {
887 if ((prop = child->property ("val")) != 0) {
888 _meter_falloff = atof (prop->value().c_str());
891 if ((child = find_named_node (node, "long-over-length")) != 0) {
892 if ((prop = child->property ("val")) != 0) {
893 over_length_long = atoi (prop->value().c_str());
896 if ((child = find_named_node (node, "short-over-length")) != 0) {
897 if ((prop = child->property ("val")) != 0) {
898 over_length_short = atoi (prop->value().c_str());
901 if ((child = find_named_node (node, "shuttle-speed-factor")) != 0) {
902 if ((prop = child->property ("val")) != 0) {
903 shuttle_speed_factor = atof (prop->value().c_str());
906 if ((child = find_named_node (node, "shuttle-speed-threshold")) != 0) {
907 if ((prop = child->property ("val")) != 0) {
908 shuttle_speed_threshold = atof (prop->value().c_str());
911 if ((child = find_named_node (node, "rf-speed")) != 0) {
912 if ((prop = child->property ("val")) != 0) {
913 rf_speed = atof (prop->value().c_str());
916 if ((child = find_named_node (node, "smpte-frames-per-second")) != 0) {
917 if ((prop = child->property ("val")) != 0) {
918 set_smpte_type( atof (prop->value().c_str()), smpte_drop_frames );
921 if ((child = find_named_node (node, "smpte-drop-frames")) != 0) {
922 if ((prop = child->property ("val")) != 0) {
923 set_smpte_type( smpte_frames_per_second, (prop->value() == "yes") );
926 if ((child = find_named_node (node, "smpte-offset")) != 0) {
927 if ((prop = child->property ("val")) != 0) {
928 set_smpte_offset( atoi (prop->value().c_str()) );
931 if ((child = find_named_node (node, "smpte-offset-negative")) != 0) {
932 if ((prop = child->property ("val")) != 0) {
933 set_smpte_offset_negative( (prop->value() == "yes") );
936 if ((child = find_named_node (node, "click-sound")) != 0) {
937 if ((prop = child->property ("val")) != 0) {
938 click_sound = prop->value();
941 if ((child = find_named_node (node, "click-emphasis-sound")) != 0) {
942 if ((prop = child->property ("val")) != 0) {
943 click_emphasis_sound = prop->value();
947 if ((child = find_named_node (node, "solo-model")) != 0) {
948 if ((prop = child->property ("val")) != 0) {
949 if (prop->value() == "SoloBus")
950 _solo_model = SoloBus;
952 _solo_model = InverseMute;
956 /* BOOLEAN OPTIONS */
958 if ((child = find_named_node (node, "auto-play")) != 0) {
959 if ((prop = child->property ("val")) != 0) {
960 set_auto_play (prop->value() == "yes");
963 if ((child = find_named_node (node, "auto-input")) != 0) {
964 if ((prop = child->property ("val")) != 0) {
965 set_auto_input (prop->value() == "yes");
968 if ((child = find_named_node (node, "seamless-loop")) != 0) {
969 if ((prop = child->property ("val")) != 0) {
970 set_seamless_loop (prop->value() == "yes");
973 if ((child = find_named_node (node, "punch-in")) != 0) {
974 if ((prop = child->property ("val")) != 0) {
975 set_punch_in (prop->value() == "yes");
978 if ((child = find_named_node (node, "punch-out")) != 0) {
979 if ((prop = child->property ("val")) != 0) {
980 set_punch_out (prop->value() == "yes");
983 if ((child = find_named_node (node, "auto-return")) != 0) {
984 if ((prop = child->property ("val")) != 0) {
985 set_auto_return (prop->value() == "yes");
988 if ((child = find_named_node (node, "send-mtc")) != 0) {
989 if ((prop = child->property ("val")) != 0) {
990 set_send_mtc (prop->value() == "yes");
993 if ((child = find_named_node (node, "mmc-control")) != 0) {
994 if ((prop = child->property ("val")) != 0) {
995 set_mmc_control (prop->value() == "yes");
998 if ((child = find_named_node (node, "midi-control")) != 0) {
999 if ((prop = child->property ("val")) != 0) {
1000 set_midi_control (prop->value() == "yes");
1003 if ((child = find_named_node (node, "midi-feedback")) != 0) {
1004 if ((prop = child->property ("val")) != 0) {
1005 set_midi_feedback (prop->value() == "yes");
1008 // Legacy support for <recording-plugins>
1009 if ((child = find_named_node (node, "recording-plugins")) != 0) {
1010 if ((prop = child->property ("val")) != 0) {
1011 set_do_not_record_plugins (prop->value() == "no");
1014 if ((child = find_named_node (node, "do-not-record-plugins")) != 0) {
1015 if ((prop = child->property ("val")) != 0) {
1016 set_do_not_record_plugins (prop->value() == "yes");
1019 if ((child = find_named_node (node, "crossfades-active")) != 0) {
1020 if ((prop = child->property ("val")) != 0) {
1021 set_crossfades_active (prop->value() == "yes");
1024 if ((child = find_named_node (node, "audible-click")) != 0) {
1025 if ((prop = child->property ("val")) != 0) {
1026 set_clicking (prop->value() == "yes");
1030 if ((child = find_named_node (node, "end-marker-is-free")) != 0) {
1031 if ((prop = child->property ("val")) != 0) {
1032 _end_location_is_free = (prop->value() == "yes");
1036 if ((child = find_named_node (node, "layer-model")) != 0) {
1037 if ((prop = child->property ("val")) != 0) {
1038 if (prop->value() == X_("LaterHigher")) {
1039 set_layer_model (LaterHigher);
1040 } else if (prop->value() == X_("AddHigher")) {
1041 set_layer_model (AddHigher);
1043 set_layer_model (MoveAddHigher);
1048 if ((child = find_named_node (node, "xfade-model")) != 0) {
1049 if ((prop = child->property ("val")) != 0) {
1050 if (prop->value() == X_("Short")) {
1051 set_xfade_model (ShortCrossfade);
1053 set_xfade_model (FullCrossfade);
1058 if ((child = find_named_node (node, "short-xfade-length")) != 0) {
1059 if ((prop = child->property ("val")) != 0) {
1060 /* value is stored as a fractional seconds */
1061 float secs = atof (prop->value().c_str());
1062 Crossfade::set_short_xfade_length ((jack_nframes_t) floor (secs * frame_rate()));
1066 if ((child = find_named_node (node, "full-xfades-unmuted")) != 0) {
1067 if ((prop = child->property ("val")) != 0) {
1068 crossfades_active = (prop->value() == "yes");
1074 if ((child = find_named_node (node, "default-fade-steepness")) != 0) {
1075 if ((prop = child->property ("val")) != 0) {
1076 fade_steepness = atof (prop->value().c_str());
1077 have_fade_steepness = true;
1080 if ((child = find_named_node (node, "default-fade-msec")) != 0) {
1081 if ((prop = child->property ("val")) != 0) {
1082 fade_msecs = atof (prop->value().c_str());
1083 have_fade_msecs = true;
1087 if (have_fade_steepness || have_fade_msecs) {
1088 // set_default_fade (fade_steepness, fade_msecs);
1095 Session::get_options () const
1100 LocaleGuard lg (X_("POSIX"));
1102 opthead = new XMLNode ("Options");
1104 SlaveSource src = slave_source ();
1108 src_string = "none";
1114 src_string = "jack";
1117 child = opthead->add_child ("slave");
1118 child->add_property ("type", src_string);
1120 child = opthead->add_child ("send-midi-timecode");
1121 child->add_property ("val", send_midi_timecode?"yes":"no");
1123 child = opthead->add_child ("send-midi-machine-control");
1124 child->add_property ("val", send_midi_machine_control?"yes":"no");
1126 snprintf (buf, sizeof(buf)-1, "%x", (int) input_auto_connect);
1127 child = opthead->add_child ("input-auto-connect");
1128 child->add_property ("val", buf);
1130 snprintf (buf, sizeof(buf)-1, "%x", (int) output_auto_connect);
1131 child = opthead->add_child ("output-auto-connect");
1132 child->add_property ("val", buf);
1134 snprintf (buf, sizeof(buf)-1, "%d", max_level);
1135 child = opthead->add_child ("max-level");
1136 child->add_property ("val", buf);
1138 snprintf (buf, sizeof(buf)-1, "%d", min_level);
1139 child = opthead->add_child ("min-level");
1140 child->add_property ("val", buf);
1142 snprintf (buf, sizeof(buf)-1, "%f", _meter_hold);
1143 child = opthead->add_child ("meter-hold");
1144 child->add_property ("val", buf);
1146 snprintf (buf, sizeof(buf)-1, "%f", _meter_falloff);
1147 child = opthead->add_child ("meter-falloff");
1148 child->add_property ("val", buf);
1150 snprintf (buf, sizeof(buf)-1, "%u", over_length_long);
1151 child = opthead->add_child ("long-over-length");
1152 child->add_property ("val", buf);
1154 snprintf (buf, sizeof(buf)-1, "%u", over_length_short);
1155 child = opthead->add_child ("short-over-length");
1156 child->add_property ("val", buf);
1158 snprintf (buf, sizeof(buf)-1, "%f", shuttle_speed_factor);
1159 child = opthead->add_child ("shuttle-speed-factor");
1160 child->add_property ("val", buf);
1162 snprintf (buf, sizeof(buf)-1, "%f", shuttle_speed_threshold);
1163 child = opthead->add_child ("shuttle-speed-threshold");
1164 child->add_property ("val", buf);
1166 snprintf (buf, sizeof(buf)-1, "%f", rf_speed);
1167 child = opthead->add_child ("rf-speed");
1168 child->add_property ("val", buf);
1170 snprintf (buf, sizeof(buf)-1, "%.2f", smpte_frames_per_second);
1171 child = opthead->add_child ("smpte-frames-per-second");
1172 child->add_property ("val", buf);
1174 child = opthead->add_child ("smpte-drop-frames");
1175 child->add_property ("val", smpte_drop_frames ? "yes" : "no");
1177 snprintf (buf, sizeof(buf)-1, "%u", smpte_offset ());
1178 child = opthead->add_child ("smpte-offset");
1179 child->add_property ("val", buf);
1181 child = opthead->add_child ("smpte-offset-negative");
1182 child->add_property ("val", smpte_offset_negative () ? "yes" : "no");
1184 child = opthead->add_child ("edit-mode");
1185 switch (_edit_mode) {
1187 child->add_property ("val", "splice");
1191 child->add_property ("val", "slide");
1195 child = opthead->add_child ("auto-play");
1196 child->add_property ("val", get_auto_play () ? "yes" : "no");
1197 child = opthead->add_child ("auto-input");
1198 child->add_property ("val", get_auto_input () ? "yes" : "no");
1199 child = opthead->add_child ("seamless-loop");
1200 child->add_property ("val", get_seamless_loop () ? "yes" : "no");
1201 child = opthead->add_child ("punch-in");
1202 child->add_property ("val", get_punch_in () ? "yes" : "no");
1203 child = opthead->add_child ("punch-out");
1204 child->add_property ("val", get_punch_out () ? "yes" : "no");
1205 child = opthead->add_child ("all-safe");
1206 child->add_property ("val", get_all_safe () ? "yes" : "no");
1207 child = opthead->add_child ("auto-return");
1208 child->add_property ("val", get_auto_return () ? "yes" : "no");
1209 child = opthead->add_child ("mmc-control");
1210 child->add_property ("val", get_mmc_control () ? "yes" : "no");
1211 child = opthead->add_child ("midi-control");
1212 child->add_property ("val", get_midi_control () ? "yes" : "no");
1213 child = opthead->add_child ("midi-feedback");
1214 child->add_property ("val", get_midi_feedback () ? "yes" : "no");
1215 child = opthead->add_child ("do-not-record-plugins");
1216 child->add_property ("val", get_do_not_record_plugins () ? "yes" : "no");
1217 child = opthead->add_child ("auto-crossfade");
1218 child->add_property ("val", get_crossfades_active () ? "yes" : "no");
1219 child = opthead->add_child ("audible-click");
1220 child->add_property ("val", get_clicking () ? "yes" : "no");
1221 child = opthead->add_child ("end-marker-is-free");
1222 child->add_property ("val", _end_location_is_free ? "yes" : "no");
1224 if (click_sound.length()) {
1225 child = opthead->add_child ("click-sound");
1226 child->add_property ("val", click_sound);
1229 if (click_emphasis_sound.length()) {
1230 child = opthead->add_child ("click-emphasis-sound");
1231 child->add_property ("val", click_emphasis_sound);
1234 child = opthead->add_child ("solo-model");
1235 child->add_property ("val", _solo_model == SoloBus ? "SoloBus" : "InverseMute");
1237 child = opthead->add_child ("layer-model");
1238 switch (layer_model) {
1240 child->add_property ("val", X_("LaterHigher"));
1243 child->add_property ("val", X_("MoveAddHigher"));
1246 child->add_property ("val", X_("AddHigher"));
1250 child = opthead->add_child ("xfade-model");
1251 switch (xfade_model) {
1253 child->add_property ("val", X_("Full"));
1255 case ShortCrossfade:
1256 child->add_property ("val", X_("Short"));
1259 child = opthead->add_child ("short-xfade-length");
1260 /* store as fractions of a second */
1261 snprintf (buf, sizeof(buf)-1, "%f",
1262 (float) Crossfade::short_xfade_length() / frame_rate());
1263 child->add_property ("val", buf);
1265 child = opthead->add_child ("full-xfades-unmuted");
1266 child->add_property ("val", crossfades_active ? "yes" : "no");
1272 Session::get_state()
1278 Session::get_template()
1280 /* if we don't disable rec-enable, diskstreams
1281 will believe they need to store their capture
1282 sources in their state node.
1285 disable_record (false);
1287 return state(false);
1291 Session::state(bool full_state)
1293 XMLNode* node = new XMLNode("Session");
1296 // store libardour version, just in case
1298 snprintf(buf, sizeof(buf)-1, "%d.%d.%d",
1299 libardour_major_version, libardour_minor_version, libardour_micro_version);
1300 node->add_property("version", string(buf));
1302 /* store configuration settings */
1306 /* store the name */
1307 node->add_property ("name", _name);
1309 if (session_dirs.size() > 1) {
1313 vector<space_and_path>::iterator i = session_dirs.begin();
1314 vector<space_and_path>::iterator next;
1316 ++i; /* skip the first one */
1320 while (i != session_dirs.end()) {
1324 if (next != session_dirs.end()) {
1334 child = node->add_child ("Path");
1335 child->add_content (p);
1339 node->add_child_nocopy (get_options());
1341 child = node->add_child ("Sources");
1344 LockMonitor sl (source_lock, __LINE__, __FILE__);
1346 for (SourceList::iterator siter = sources.begin(); siter != sources.end(); ++siter) {
1348 /* Don't save information about FileSources that are empty */
1352 if ((fs = dynamic_cast<FileSource*> ((*siter).second)) != 0) {
1353 DestructiveFileSource* dfs = dynamic_cast<DestructiveFileSource*> (fs);
1355 /* destructive file sources are OK if they are empty, because
1356 we will re-use them every time.
1360 if (fs->length() == 0) {
1366 child->add_child_nocopy ((*siter).second->get_state());
1370 child = node->add_child ("Regions");
1373 LockMonitor rl (region_lock, __LINE__, __FILE__);
1375 for (AudioRegionList::const_iterator i = audio_regions.begin(); i != audio_regions.end(); ++i) {
1377 /* only store regions not attached to playlists */
1379 if ((*i).second->playlist() == 0) {
1380 child->add_child_nocopy (i->second->state (true));
1385 child = node->add_child ("DiskStreams");
1388 RWLockMonitor dl (diskstream_lock, false, __LINE__, __FILE__);
1389 for (DiskStreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
1390 if (!(*i)->hidden()) {
1391 child->add_child_nocopy ((*i)->get_state());
1396 node->add_child_nocopy (_locations.get_state());
1398 child = node->add_child ("Connections");
1400 LockMonitor lm (connection_lock, __LINE__, __FILE__);
1401 for (ConnectionList::iterator i = _connections.begin(); i != _connections.end(); ++i) {
1402 if (!(*i)->system_dependent()) {
1403 child->add_child_nocopy ((*i)->get_state());
1408 child = node->add_child ("Routes");
1410 RWLockMonitor lm (route_lock, false, __LINE__, __FILE__);
1412 RoutePublicOrderSorter cmp;
1413 RouteList public_order(routes);
1414 public_order.sort (cmp);
1416 for (RouteList::iterator i = public_order.begin(); i != public_order.end(); ++i) {
1417 if (!(*i)->hidden()) {
1419 child->add_child_nocopy ((*i)->get_state());
1421 child->add_child_nocopy ((*i)->get_template());
1428 child = node->add_child ("EditGroups");
1429 for (list<RouteGroup *>::iterator i = edit_groups.begin(); i != edit_groups.end(); ++i) {
1430 child->add_child_nocopy ((*i)->get_state());
1433 child = node->add_child ("MixGroups");
1434 for (list<RouteGroup *>::iterator i = mix_groups.begin(); i != mix_groups.end(); ++i) {
1435 child->add_child_nocopy ((*i)->get_state());
1438 child = node->add_child ("Playlists");
1439 for (PlaylistList::iterator i = playlists.begin(); i != playlists.end(); ++i) {
1440 if (!(*i)->hidden()) {
1441 if (!(*i)->empty()) {
1443 child->add_child_nocopy ((*i)->get_state());
1445 child->add_child_nocopy ((*i)->get_template());
1451 child = node->add_child ("UnusedPlaylists");
1452 for (PlaylistList::iterator i = unused_playlists.begin(); i != unused_playlists.end(); ++i) {
1453 if (!(*i)->hidden()) {
1454 if (!(*i)->empty()) {
1456 child->add_child_nocopy ((*i)->get_state());
1458 child->add_child_nocopy ((*i)->get_template());
1466 child = node->add_child ("Click");
1467 child->add_child_nocopy (_click_io->state (full_state));
1471 child = node->add_child ("NamedSelections");
1472 for (NamedSelectionList::iterator i = named_selections.begin(); i != named_selections.end(); ++i) {
1474 child->add_child_nocopy ((*i)->get_state());
1479 node->add_child_nocopy (_tempo_map->get_state());
1482 node->add_child_copy (*_extra_xml);
1489 Session::set_state (const XMLNode& node)
1493 const XMLProperty* prop;
1496 _state_of_the_state = StateOfTheState (_state_of_the_state|CannotSave);
1498 if (node.name() != "Session"){
1499 fatal << _("programming error: Session: incorrect XML node sent to set_state()") << endmsg;
1503 StateManager::prohibit_save ();
1505 if ((prop = node.property ("name")) != 0) {
1506 _name = prop->value ();
1509 IO::disable_ports ();
1510 IO::disable_connecting ();
1512 /* Object loading order:
1529 if (use_config_midi_ports ()) {
1532 if ((child = find_named_node (node, "Path")) != 0) {
1533 /* XXX this XML content stuff horrible API design */
1534 string raid_path = _path + ':' + child->children().front()->content();
1535 setup_raid_path (raid_path);
1537 /* the path is already set */
1540 if ((child = find_named_node (node, "extra")) != 0) {
1541 _extra_xml = new XMLNode (*child);
1544 if ((child = find_named_node (node, "Options")) == 0) {
1545 error << _("Session: XML state has no options section") << endmsg;
1546 } else if (load_options (*child)) {
1549 if ((child = find_named_node (node, "Sources")) == 0) {
1550 error << _("Session: XML state has no sources section") << endmsg;
1552 } else if (load_sources (*child)) {
1556 if ((child = find_named_node (node, "Regions")) == 0) {
1557 error << _("Session: XML state has no Regions section") << endmsg;
1559 } else if (load_regions (*child)) {
1563 if ((child = find_named_node (node, "Playlists")) == 0) {
1564 error << _("Session: XML state has no playlists section") << endmsg;
1566 } else if (load_playlists (*child)) {
1570 if ((child = find_named_node (node, "UnusedPlaylists")) == 0) {
1572 } else if (load_unused_playlists (*child)) {
1576 if ((child = find_named_node (node, "NamedSelections")) != 0) {
1577 if (load_named_selections (*child)) {
1582 if ((child = find_named_node (node, "DiskStreams")) == 0) {
1583 error << _("Session: XML state has no diskstreams section") << endmsg;
1585 } else if (load_diskstreams (*child)) {
1589 if ((child = find_named_node (node, "Connections")) == 0) {
1590 error << _("Session: XML state has no connections section") << endmsg;
1592 } else if (load_connections (*child)) {
1596 if ((child = find_named_node (node, "Locations")) == 0) {
1597 error << _("Session: XML state has no locations section") << endmsg;
1599 } else if (_locations.set_state (*child)) {
1605 if ((location = _locations.auto_loop_location()) != 0) {
1606 set_auto_loop_location (location);
1609 if ((location = _locations.auto_punch_location()) != 0) {
1610 set_auto_punch_location (location);
1613 if ((location = _locations.end_location()) == 0) {
1614 _locations.add (end_location);
1616 delete end_location;
1617 end_location = location;
1620 if ((location = _locations.start_location()) == 0) {
1621 _locations.add (start_location);
1623 delete start_location;
1624 start_location = location;
1627 _locations.save_state (_("initial state"));
1629 if ((child = find_named_node (node, "EditGroups")) == 0) {
1630 error << _("Session: XML state has no edit groups section") << endmsg;
1632 } else if (load_edit_groups (*child)) {
1636 if ((child = find_named_node (node, "MixGroups")) == 0) {
1637 error << _("Session: XML state has no mix groups section") << endmsg;
1639 } else if (load_mix_groups (*child)) {
1643 if ((child = find_named_node (node, "TempoMap")) == 0) {
1644 error << _("Session: XML state has no Tempo Map section") << endmsg;
1646 } else if (_tempo_map->set_state (*child)) {
1650 if ((child = find_named_node (node, "Routes")) == 0) {
1651 error << _("Session: XML state has no routes section") << endmsg;
1653 } else if (load_routes (*child)) {
1657 if ((child = find_named_node (node, "Click")) == 0) {
1658 warning << _("Session: XML state has no click section") << endmsg;
1659 } else if (_click_io) {
1660 _click_io->set_state (*child);
1663 /* OK, now we can set edit mode */
1665 set_edit_mode (pending_edit_mode);
1667 /* here beginneth the second phase ... */
1669 StateReady (); /* EMIT SIGNAL */
1671 _state_of_the_state = Clean;
1673 StateManager::allow_save (_("initial state"), true);
1675 if (state_was_pending) {
1676 save_state (_current_snapshot_name);
1677 remove_pending_capture_state ();
1678 state_was_pending = false;
1684 /* we failed, re-enable state saving but don't actually save internal state */
1685 StateManager::allow_save (X_("ignored"), false);
1690 Session::load_routes (const XMLNode& node)
1693 XMLNodeConstIterator niter;
1696 nlist = node.children();
1700 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1702 if ((route = XMLRouteFactory (**niter)) == 0) {
1703 error << _("Session: cannot create Route from XML description.") << endmsg;
1714 Session::XMLRouteFactory (const XMLNode& node)
1716 if (node.name() != "Route") {
1720 if (node.property ("diskstream") != 0 || node.property ("diskstream-id") != 0) {
1721 return new AudioTrack (*this, node);
1723 return new Route (*this, node);
1728 Session::load_regions (const XMLNode& node)
1731 XMLNodeConstIterator niter;
1732 AudioRegion* region;
1734 nlist = node.children();
1738 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1740 if ((region = XMLRegionFactory (**niter, false)) == 0) {
1741 error << _("Session: cannot create Region from XML description.") << endmsg;
1749 Session::XMLRegionFactory (const XMLNode& node, bool full)
1751 const XMLProperty* prop;
1754 AudioRegion::SourceList sources;
1755 uint32_t nchans = 1;
1758 if (node.name() != X_("Region")) {
1762 if ((prop = node.property (X_("channels"))) != 0) {
1763 nchans = atoi (prop->value().c_str());
1767 if ((prop = node.property (X_("source-0"))) == 0) {
1768 if ((prop = node.property ("source")) == 0) {
1769 error << _("Session: XMLNode describing a AudioRegion is incomplete (no source)") << endmsg;
1774 sscanf (prop->value().c_str(), "%" PRIu64, &s_id);
1776 if ((source = get_source (s_id)) == 0) {
1777 error << string_compose(_("Session: XMLNode describing a AudioRegion references an unknown source id =%1"), s_id) << endmsg;
1781 sources.push_back(source);
1783 /* pickup other channels */
1785 for (uint32_t n=1; n < nchans; ++n) {
1786 snprintf (buf, sizeof(buf), X_("source-%d"), n);
1787 if ((prop = node.property (buf)) != 0) {
1788 sscanf (prop->value().c_str(), "%" PRIu64, &s_id);
1790 if ((source = get_source (s_id)) == 0) {
1791 error << string_compose(_("Session: XMLNode describing a AudioRegion references an unknown source id =%1"), s_id) << endmsg;
1794 sources.push_back(source);
1800 return new AudioRegion (sources, node);
1803 catch (failed_constructor& err) {
1809 Session::get_sources_as_xml ()
1812 XMLNode* node = new XMLNode (X_("Sources"));
1813 LockMonitor lm (source_lock, __LINE__, __FILE__);
1815 for (SourceList::iterator i = sources.begin(); i != sources.end(); ++i) {
1816 node->add_child_nocopy ((*i).second->get_state());
1823 Session::path_from_region_name (string name, string identifier)
1825 char buf[PATH_MAX+1];
1827 string dir = discover_best_sound_dir ();
1829 for (n = 0; n < 999999; ++n) {
1830 if (identifier.length()) {
1831 snprintf (buf, sizeof(buf), "%s/%s%s%" PRIu32 ".wav", dir.c_str(), name.c_str(),
1832 identifier.c_str(), n);
1834 snprintf (buf, sizeof(buf), "%s/%s-%" PRIu32 ".wav", dir.c_str(), name.c_str(), n);
1836 if (access (buf, F_OK) != 0) {
1846 Session::load_sources (const XMLNode& node)
1849 XMLNodeConstIterator niter;
1852 nlist = node.children();
1856 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1858 if ((source = XMLSourceFactory (**niter)) == 0) {
1859 error << _("Session: cannot create Source from XML description.") << endmsg;
1867 Session::XMLSourceFactory (const XMLNode& node)
1871 if (node.name() != "Source") {
1876 if (node.property (X_("destructive")) != 0) {
1877 src = new DestructiveFileSource (node, frame_rate());
1879 src = new FileSource (node, frame_rate());
1883 catch (failed_constructor& err) {
1886 src = ExternalSource::create (node);
1889 catch (failed_constructor& err) {
1890 error << _("Found a sound file that cannot be used by Ardour. See the progammers.") << endmsg;
1899 Session::save_template (string template_name)
1902 string xml_path, bak_path, template_path;
1904 if (_state_of_the_state & CannotSave) {
1909 string dir = template_dir();
1911 if ((dp = opendir (dir.c_str()))) {
1914 if (mkdir (dir.c_str(), S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH)<0) {
1915 error << string_compose(_("Could not create mix templates directory \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
1920 tree.set_root (&get_template());
1923 xml_path += template_name;
1924 xml_path += _template_suffix;
1926 ifstream in(xml_path.c_str());
1929 warning << string_compose(_("Template \"%1\" already exists - new version not created"), template_name) << endmsg;
1935 if (!tree.write (xml_path)) {
1936 error << _("mix template not saved") << endmsg;
1944 Session::rename_template (string old_name, string new_name)
1946 string old_path = template_dir() + old_name + _template_suffix;
1947 string new_path = template_dir() + new_name + _template_suffix;
1949 return rename (old_path.c_str(), new_path.c_str());
1953 Session::delete_template (string name)
1955 string template_path = template_dir();
1956 template_path += name;
1957 template_path += _template_suffix;
1959 return remove (template_path.c_str());
1963 Session::refresh_disk_space ()
1966 struct statfs statfsbuf;
1967 vector<space_and_path>::iterator i;
1968 LockMonitor lm (space_lock, __LINE__, __FILE__);
1971 /* get freespace on every FS that is part of the session path */
1973 _total_free_4k_blocks = 0;
1975 for (i = session_dirs.begin(); i != session_dirs.end(); ++i) {
1976 statfs ((*i).path.c_str(), &statfsbuf);
1978 scale = statfsbuf.f_bsize/4096.0;
1980 (*i).blocks = (uint32_t) floor (statfsbuf.f_bavail * scale);
1981 _total_free_4k_blocks += (*i).blocks;
1987 Session::ensure_sound_dir (string path, string& result)
1992 /* Ensure that the parent directory exists */
1994 if (mkdir (path.c_str(), 0775)) {
1995 if (errno != EEXIST) {
1996 error << string_compose(_("cannot create session directory \"%1\"; ignored"), path) << endmsg;
2001 /* Ensure that the sounds directory exists */
2005 result += sound_dir_name;
2007 if (mkdir (result.c_str(), 0775)) {
2008 if (errno != EEXIST) {
2009 error << string_compose(_("cannot create sounds directory \"%1\"; ignored"), result) << endmsg;
2016 dead += dead_sound_dir_name;
2018 if (mkdir (dead.c_str(), 0775)) {
2019 if (errno != EEXIST) {
2020 error << string_compose(_("cannot create dead sounds directory \"%1\"; ignored"), dead) << endmsg;
2027 peak += peak_dir_name;
2029 if (mkdir (peak.c_str(), 0775)) {
2030 if (errno != EEXIST) {
2031 error << string_compose(_("cannot create peak file directory \"%1\"; ignored"), peak) << endmsg;
2036 /* callers expect this to be terminated ... */
2043 Session::discover_best_sound_dir (bool destructive)
2045 vector<space_and_path>::iterator i;
2048 /* destructive files all go into the same place */
2054 /* handle common case without system calls */
2056 if (session_dirs.size() == 1) {
2060 /* OK, here's the algorithm we're following here:
2062 We want to select which directory to use for
2063 the next file source to be created. Ideally,
2064 we'd like to use a round-robin process so as to
2065 get maximum performance benefits from splitting
2066 the files across multiple disks.
2068 However, in situations without much diskspace, an
2069 RR approach may end up filling up a filesystem
2070 with new files while others still have space.
2071 Its therefore important to pay some attention to
2072 the freespace in the filesystem holding each
2073 directory as well. However, if we did that by
2074 itself, we'd keep creating new files in the file
2075 system with the most space until it was as full
2076 as all others, thus negating any performance
2077 benefits of this RAID-1 like approach.
2079 So, we use a user-configurable space threshold. If
2080 there are at least 2 filesystems with more than this
2081 much space available, we use RR selection between them.
2082 If not, then we pick the filesystem with the most space.
2084 This gets a good balance between the two
2088 refresh_disk_space ();
2090 int free_enough = 0;
2092 for (i = session_dirs.begin(); i != session_dirs.end(); ++i) {
2093 if ((*i).blocks * 4096 >= Config->get_disk_choice_space_threshold()) {
2098 if (free_enough >= 2) {
2100 bool found_it = false;
2102 /* use RR selection process, ensuring that the one
2106 i = last_rr_session_dir;
2109 if (++i == session_dirs.end()) {
2110 i = session_dirs.begin();
2113 if ((*i).blocks * 4096 >= Config->get_disk_choice_space_threshold()) {
2114 if (ensure_sound_dir ((*i).path, result) == 0) {
2115 last_rr_session_dir = i;
2121 } while (i != last_rr_session_dir);
2124 result = sound_dir();
2129 /* pick FS with the most freespace (and that
2130 seems to actually work ...)
2133 vector<space_and_path> sorted;
2134 space_and_path_ascending_cmp cmp;
2136 sorted = session_dirs;
2137 sort (sorted.begin(), sorted.end(), cmp);
2139 for (i = sorted.begin(); i != sorted.end(); ++i) {
2140 if (ensure_sound_dir ((*i).path, result) == 0) {
2141 last_rr_session_dir = i;
2146 /* if the above fails, fall back to the most simplistic solution */
2148 if (i == sorted.end()) {
2157 Session::load_playlists (const XMLNode& node)
2160 XMLNodeConstIterator niter;
2163 nlist = node.children();
2167 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2169 if ((playlist = XMLPlaylistFactory (**niter)) == 0) {
2170 error << _("Session: cannot create Playlist from XML description.") << endmsg;
2178 Session::load_unused_playlists (const XMLNode& node)
2181 XMLNodeConstIterator niter;
2184 nlist = node.children();
2188 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2190 if ((playlist = XMLPlaylistFactory (**niter)) == 0) {
2191 error << _("Session: cannot create Playlist from XML description.") << endmsg;
2195 // now manually untrack it
2197 track_playlist (playlist, false);
2205 Session::XMLPlaylistFactory (const XMLNode& node)
2208 return new AudioPlaylist (*this, node);
2211 catch (failed_constructor& err) {
2217 Session::load_named_selections (const XMLNode& node)
2220 XMLNodeConstIterator niter;
2223 nlist = node.children();
2227 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2229 if ((ns = XMLNamedSelectionFactory (**niter)) == 0) {
2230 error << _("Session: cannot create Named Selection from XML description.") << endmsg;
2238 Session::XMLNamedSelectionFactory (const XMLNode& node)
2241 return new NamedSelection (*this, node);
2244 catch (failed_constructor& err) {
2250 Session::dead_sound_dir () const
2253 res += dead_sound_dir_name;
2259 Session::sound_dir () const
2262 res += sound_dir_name;
2268 Session::tape_dir () const
2271 res += tape_dir_name;
2277 Session::peak_dir () const
2280 res += peak_dir_name;
2286 Session::automation_dir () const
2289 res += "automation/";
2294 Session::template_dir ()
2296 string path = get_user_ardour_path();
2297 path += "templates/";
2303 Session::template_path ()
2307 path += get_user_ardour_path();
2308 if (path[path.length()-1] != ':') {
2311 path += get_system_ardour_path();
2313 vector<string> split_path;
2315 split (path, split_path, ':');
2318 for (vector<string>::iterator i = split_path.begin(); i != split_path.end(); ++i) {
2320 path += "templates/";
2322 if (distance (i, split_path.end()) != 1) {
2331 Session::load_connections (const XMLNode& node)
2333 XMLNodeList nlist = node.children();
2334 XMLNodeConstIterator niter;
2338 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2339 if ((*niter)->name() == "InputConnection") {
2340 add_connection (new ARDOUR::InputConnection (**niter));
2341 } else if ((*niter)->name() == "OutputConnection") {
2342 add_connection (new ARDOUR::OutputConnection (**niter));
2344 error << string_compose(_("Unknown node \"%1\" found in Connections list from state file"), (*niter)->name()) << endmsg;
2353 Session::load_edit_groups (const XMLNode& node)
2355 return load_route_groups (node, true);
2359 Session::load_mix_groups (const XMLNode& node)
2361 return load_route_groups (node, false);
2365 Session::load_route_groups (const XMLNode& node, bool edit)
2367 XMLNodeList nlist = node.children();
2368 XMLNodeConstIterator niter;
2373 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2374 if ((*niter)->name() == "RouteGroup") {
2376 route = add_edit_group ("");
2377 route->set_state (**niter);
2379 route = add_mix_group ("");
2380 route->set_state (**niter);
2389 Session::swap_configuration(Configuration** new_config)
2391 RWLockMonitor lm (route_lock, true, __LINE__, __FILE__); // jlc - WHY?
2392 Configuration* tmp = *new_config;
2393 *new_config = Config;
2399 Session::copy_configuration(Configuration* new_config)
2401 RWLockMonitor lm (route_lock, true, __LINE__, __FILE__);
2402 new_config = new Configuration(*Config);
2406 state_file_filter (const string &str, void *arg)
2408 return (str.length() > strlen(Session::statefile_suffix()) &&
2409 str.find (Session::statefile_suffix()) == (str.length() - strlen (Session::statefile_suffix())));
2413 bool operator()(const string* a, const string* b) {
2419 remove_end(string* state)
2421 string statename(*state);
2423 string::size_type start,end;
2424 if ((start = statename.find_last_of ('/')) != string::npos) {
2425 statename = statename.substr (start+1);
2428 if ((end = statename.rfind(".ardour")) < 0) {
2429 end = statename.length();
2432 return new string(statename.substr (0, end));
2436 Session::possible_states (string path)
2438 PathScanner scanner;
2439 vector<string*>* states = scanner (path, state_file_filter, 0, false, false);
2441 transform(states->begin(), states->end(), states->begin(), remove_end);
2444 sort (states->begin(), states->end(), cmp);
2450 Session::possible_states () const
2452 return possible_states(_path);
2456 Session::auto_save()
2458 save_state (_current_snapshot_name);
2462 Session::add_edit_group (string name)
2464 RouteGroup* rg = new RouteGroup (*this, name);
2465 edit_groups.push_back (rg);
2466 edit_group_added (rg); /* EMIT SIGNAL */
2472 Session::add_mix_group (string name)
2474 RouteGroup* rg = new RouteGroup (*this, name, RouteGroup::Relative);
2475 mix_groups.push_back (rg);
2476 mix_group_added (rg); /* EMIT SIGNAL */
2482 Session::remove_edit_group (RouteGroup& rg)
2484 list<RouteGroup*>::iterator i;
2486 if ((i = find (edit_groups.begin(), edit_groups.end(), &rg)) != edit_groups.end()) {
2487 (*i)->apply (&Route::drop_edit_group, this);
2488 edit_groups.erase (i);
2489 edit_group_removed (); /* EMIT SIGNAL */
2496 Session::remove_mix_group (RouteGroup& rg)
2498 list<RouteGroup*>::iterator i;
2500 if ((i = find (mix_groups.begin(), mix_groups.end(), &rg)) != mix_groups.end()) {
2501 (*i)->apply (&Route::drop_mix_group, this);
2502 mix_groups.erase (i);
2503 mix_group_removed (); /* EMIT SIGNAL */
2510 Session::mix_group_by_name (string name)
2512 list<RouteGroup *>::iterator i;
2514 for (i = mix_groups.begin(); i != mix_groups.end(); ++i) {
2515 if ((*i)->name() == name) {
2523 Session::edit_group_by_name (string name)
2525 list<RouteGroup *>::iterator i;
2527 for (i = edit_groups.begin(); i != edit_groups.end(); ++i) {
2528 if ((*i)->name() == name) {
2536 Session::set_meter_hold (float val)
2539 MeterHoldChanged(); // emit
2543 Session::set_meter_falloff (float val)
2545 _meter_falloff = val;
2546 MeterFalloffChanged(); // emit
2551 Session::begin_reversible_command (string name, UndoAction* private_undo)
2553 current_cmd.clear ();
2554 current_cmd.set_name (name);
2557 current_cmd.add_undo (*private_undo);
2562 Session::commit_reversible_command (UndoAction* private_redo)
2567 current_cmd.add_redo_no_execute (*private_redo);
2570 gettimeofday (&now, 0);
2571 current_cmd.set_timestamp (now);
2573 history.add (current_cmd);
2576 Session::GlobalRouteBooleanState
2577 Session::get_global_route_boolean (bool (Route::*method)(void) const)
2579 GlobalRouteBooleanState s;
2580 RWLockMonitor lm (route_lock, false, __LINE__, __FILE__);
2582 for (RouteList::iterator i = routes.begin(); i != routes.end(); ++i) {
2583 if (!(*i)->hidden()) {
2584 RouteBooleanState v;
2587 v.second = ((*i)->*method)();
2596 Session::GlobalRouteMeterState
2597 Session::get_global_route_metering ()
2599 GlobalRouteMeterState s;
2600 RWLockMonitor lm (route_lock, false, __LINE__, __FILE__);
2602 for (RouteList::iterator i = routes.begin(); i != routes.end(); ++i) {
2603 if (!(*i)->hidden()) {
2607 v.second = (*i)->meter_point();
2617 Session::set_global_route_metering (GlobalRouteMeterState s, void* arg)
2619 for (GlobalRouteMeterState::iterator i = s.begin(); i != s.end(); ++i) {
2620 i->first->set_meter_point (i->second, arg);
2625 Session::set_global_route_boolean (GlobalRouteBooleanState s, void (Route::*method)(bool, void*), void* arg)
2627 for (GlobalRouteBooleanState::iterator i = s.begin(); i != s.end(); ++i) {
2628 (i->first->*method) (i->second, arg);
2633 Session::set_global_mute (GlobalRouteBooleanState s, void* src)
2635 set_global_route_boolean (s, &Route::set_mute, src);
2639 Session::set_global_solo (GlobalRouteBooleanState s, void* src)
2641 set_global_route_boolean (s, &Route::set_solo, src);
2645 Session::set_global_record_enable (GlobalRouteBooleanState s, void* src)
2647 set_global_route_boolean (s, &Route::set_record_enable, src);
2651 Session::global_mute_memento (void* src)
2653 return sigc::bind (mem_fun (*this, &Session::set_global_mute), get_global_route_boolean (&Route::muted), src);
2657 Session::global_metering_memento (void* src)
2659 return sigc::bind (mem_fun (*this, &Session::set_global_route_metering), get_global_route_metering (), src);
2663 Session::global_solo_memento (void* src)
2665 return sigc::bind (mem_fun (*this, &Session::set_global_solo), get_global_route_boolean (&Route::soloed), src);
2669 Session::global_record_enable_memento (void* src)
2671 return sigc::bind (mem_fun (*this, &Session::set_global_record_enable), get_global_route_boolean (&Route::record_enabled), src);
2675 template_filter (const string &str, void *arg)
2677 return (str.length() > strlen(Session::template_suffix()) &&
2678 str.find (Session::template_suffix()) == (str.length() - strlen (Session::template_suffix())));
2682 Session::get_template_list (list<string> &template_names)
2684 vector<string *> *templates;
2685 PathScanner scanner;
2688 path = template_path ();
2690 templates = scanner (path, template_filter, 0, false, true);
2692 vector<string*>::iterator i;
2693 for (i = templates->begin(); i != templates->end(); ++i) {
2694 string fullpath = *(*i);
2697 start = fullpath.find_last_of ('/') + 1;
2698 if ((end = fullpath.find_last_of ('.')) <0) {
2699 end = fullpath.length();
2702 template_names.push_back(fullpath.substr(start, (end-start)));
2707 Session::read_favorite_dirs (FavoriteDirs & favs)
2709 string path = get_user_ardour_path();
2710 path += "/favorite_dirs";
2712 ifstream fav (path.c_str());
2717 if (errno != ENOENT) {
2718 //error << string_compose (_("cannot open favorite file %1 (%2)"), path, strerror (errno)) << endmsg;
2729 getline(fav, newfav);
2735 favs.push_back (newfav);
2742 Session::write_favorite_dirs (FavoriteDirs & favs)
2744 string path = get_user_ardour_path();
2745 path += "/favorite_dirs";
2747 ofstream fav (path.c_str());
2753 for (FavoriteDirs::iterator i = favs.begin(); i != favs.end(); ++i) {
2754 fav << (*i) << endl;
2761 accept_all_non_peak_files (const string& path, void *arg)
2763 return (path.length() > 5 && path.find (".peak") != (path.length() - 5));
2767 accept_all_state_files (const string& path, void *arg)
2769 return (path.length() > 7 && path.find (".ardour") == (path.length() - 7));
2773 Session::find_all_sources (string path, set<string>& result)
2778 if (!tree.read (path)) {
2782 if ((node = find_named_node (*tree.root(), "Sources")) == 0) {
2787 XMLNodeConstIterator niter;
2789 nlist = node->children();
2793 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2797 if ((prop = (*niter)->property (X_("name"))) == 0) {
2801 if (prop->value()[0] == '/') {
2802 /* external file, ignore */
2806 string path = _path; /* /-terminated */
2807 path += sound_dir_name;
2809 path += prop->value();
2811 result.insert (path);
2818 Session::find_all_sources_across_snapshots (set<string>& result, bool exclude_this_snapshot)
2820 PathScanner scanner;
2821 vector<string*>* state_files;
2823 string this_snapshot_path;
2829 if (ripped[ripped.length()-1] == '/') {
2830 ripped = ripped.substr (0, ripped.length() - 1);
2833 state_files = scanner (ripped, accept_all_state_files, (void *) 0, false, true);
2835 if (state_files == 0) {
2840 this_snapshot_path = _path;
2841 this_snapshot_path += _current_snapshot_name;
2842 this_snapshot_path += _statefile_suffix;
2844 for (vector<string*>::iterator i = state_files->begin(); i != state_files->end(); ++i) {
2846 if (exclude_this_snapshot && **i == this_snapshot_path) {
2850 if (find_all_sources (**i, result) < 0) {
2859 Session::cleanup_sources (Session::cleanup_report& rep)
2861 vector<Source*> dead_sources;
2862 vector<Playlist*> playlists_tbd;
2863 PathScanner scanner;
2865 vector<space_and_path>::iterator i;
2866 vector<space_and_path>::iterator nexti;
2867 vector<string*>* soundfiles;
2868 vector<string> unused;
2869 set<string> all_sources;
2874 _state_of_the_state = (StateOfTheState) (_state_of_the_state | InCleanup);
2876 /* step 1: consider deleting all unused playlists */
2878 for (PlaylistList::iterator x = unused_playlists.begin(); x != unused_playlists.end(); ++x) {
2881 status = AskAboutPlaylistDeletion (*x);
2890 playlists_tbd.push_back (*x);
2894 /* leave it alone */
2899 /* now delete any that were marked for deletion */
2901 for (vector<Playlist*>::iterator x = playlists_tbd.begin(); x != playlists_tbd.end(); ++x) {
2902 PlaylistList::iterator foo;
2904 if ((foo = unused_playlists.find (*x)) != unused_playlists.end()) {
2905 unused_playlists.erase (foo);
2910 /* step 2: clear the undo/redo history for all playlists */
2912 for (PlaylistList::iterator x = playlists.begin(); x != playlists.end(); ++x) {
2913 (*x)->drop_all_states ();
2916 /* step 3: find all un-referenced sources */
2921 for (SourceList::iterator i = sources.begin(); i != sources.end(); ) {
2923 SourceList::iterator tmp;
2928 /* only remove files that are not in use and have some size
2929 to them. otherwise we remove the current "nascent"
2933 if ((*i).second->use_cnt() == 0 && (*i).second->length() > 0) {
2934 dead_sources.push_back (i->second);
2936 /* remove this source from our own list to avoid us
2937 adding it to the list of all sources below
2946 /* Step 4: get rid of all regions in the region list that use any dead sources
2947 in case the sources themselves don't go away (they might be referenced in
2951 for (vector<Source*>::iterator i = dead_sources.begin(); i != dead_sources.end();++i) {
2953 for (AudioRegionList::iterator r = audio_regions.begin(); r != audio_regions.end(); ) {
2954 AudioRegionList::iterator tmp;
2962 for (uint32_t n = 0; n < ar->n_channels(); ++n) {
2963 if (&ar->source (n) == (*i)) {
2964 /* this region is dead */
2973 /* build a list of all the possible sound directories for the session */
2975 for (i = session_dirs.begin(); i != session_dirs.end(); ) {
2980 sound_path += (*i).path;
2981 sound_path += sound_dir_name;
2983 if (nexti != session_dirs.end()) {
2990 /* now do the same thing for the files that ended up in the sounds dir(s)
2991 but are not referenced as sources in any snapshot.
2994 soundfiles = scanner (sound_path, accept_all_non_peak_files, (void *) 0, false, true);
2996 if (soundfiles == 0) {
3000 /* find all sources, but don't use this snapshot because the
3001 state file on disk still references sources we may have already
3005 find_all_sources_across_snapshots (all_sources, true);
3007 /* add our current source list
3010 for (SourceList::iterator i = sources.begin(); i != sources.end(); ++i) {
3012 ExternalSource* sfs;
3014 if ((fs = dynamic_cast<FileSource*> ((*i).second)) != 0) {
3015 all_sources.insert (fs->path());
3016 } else if ((sfs = dynamic_cast<ExternalSource*> ((*i).second)) != 0) {
3017 all_sources.insert (sfs->path());
3021 for (vector<string*>::iterator x = soundfiles->begin(); x != soundfiles->end(); ++x) {
3026 for (set<string>::iterator i = all_sources.begin(); i != all_sources.end(); ++i) {
3036 unused.push_back (spath);
3040 /* now try to move all unused files into the "dead_sounds" directory(ies) */
3042 for (vector<string>::iterator x = unused.begin(); x != unused.end(); ++x) {
3043 struct stat statbuf;
3045 rep.paths.push_back (*x);
3046 if (stat ((*x).c_str(), &statbuf) == 0) {
3047 rep.space += statbuf.st_size;
3052 /* don't move the file across filesystems, just
3053 stick it in the `dead_sound_dir_name' directory
3054 on whichever filesystem it was already on.
3057 newpath = PBD::dirname (*x);
3058 newpath = PBD::dirname (newpath);
3061 newpath += dead_sound_dir_name;
3063 newpath += PBD::basename ((*x));
3065 if (access (newpath.c_str(), F_OK) == 0) {
3067 /* the new path already exists, try versioning */
3069 char buf[PATH_MAX+1];
3073 snprintf (buf, sizeof (buf), "%s.%d", newpath.c_str(), version);
3076 while (access (newpath_v.c_str(), F_OK) == 0 && version < 999) {
3077 snprintf (buf, sizeof (buf), "%s.%d", newpath.c_str(), ++version);
3081 if (version == 999) {
3082 error << string_compose (_("there are already 1000 files with names like %1; versioning discontinued"),
3086 newpath = newpath_v;
3091 /* it doesn't exist, or we can't read it or something */
3095 if (::rename ((*x).c_str(), newpath.c_str()) != 0) {
3096 error << string_compose (_("cannot rename audio file source from %1 to %2 (%3)"),
3097 (*x), newpath, strerror (errno))
3103 /* see if there an easy to find peakfile for this file, and remove it.
3106 string peakpath = (*x).substr (0, (*x).find_last_of ('.'));
3107 peakpath += ".peak";
3109 if (access (peakpath.c_str(), W_OK) == 0) {
3110 if (::unlink (peakpath.c_str()) != 0) {
3111 error << string_compose (_("cannot remove peakfile %1 for %2 (%3)"),
3112 peakpath, _path, strerror (errno))
3114 /* try to back out */
3115 rename (newpath.c_str(), _path.c_str());
3124 /* dump the history list */
3128 /* save state so we don't end up a session file
3129 referring to non-existent sources.
3135 _state_of_the_state = (StateOfTheState) (_state_of_the_state & ~InCleanup);
3140 Session::cleanup_trash_sources (Session::cleanup_report& rep)
3142 vector<space_and_path>::iterator i;
3143 string dead_sound_dir;
3144 struct dirent* dentry;
3145 struct stat statbuf;
3151 for (i = session_dirs.begin(); i != session_dirs.end(); ++i) {
3153 dead_sound_dir = (*i).path;
3154 dead_sound_dir += dead_sound_dir_name;
3156 if ((dead = opendir (dead_sound_dir.c_str())) == 0) {
3160 while ((dentry = readdir (dead)) != 0) {
3162 /* avoid '.' and '..' */
3164 if ((dentry->d_name[0] == '.' && dentry->d_name[1] == '\0') ||
3165 (dentry->d_name[2] == '\0' && dentry->d_name[0] == '.' && dentry->d_name[1] == '.')) {
3171 fullpath = dead_sound_dir;
3173 fullpath += dentry->d_name;
3175 if (stat (fullpath.c_str(), &statbuf)) {
3179 if (!S_ISREG (statbuf.st_mode)) {
3183 if (unlink (fullpath.c_str())) {
3184 error << string_compose (_("cannot remove dead sound file %1 (%2)"),
3185 fullpath, strerror (errno))
3189 rep.paths.push_back (dentry->d_name);
3190 rep.space += statbuf.st_size;
3201 Session::set_dirty ()
3203 bool was_dirty = dirty();
3205 _state_of_the_state = StateOfTheState (_state_of_the_state | Dirty);
3208 DirtyChanged(); /* EMIT SIGNAL */
3214 Session::set_clean ()
3216 bool was_dirty = dirty();
3218 _state_of_the_state = Clean;
3221 DirtyChanged(); /* EMIT SIGNAL */