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>
84 #include <ardour/control_protocol_manager.h>
90 using namespace ARDOUR;
93 Session::first_stage_init (string fullpath, string snapshot_name)
95 if (fullpath.length() == 0) {
96 throw failed_constructor();
100 if (!realpath(fullpath.c_str(), buf) && (errno != ENOENT)) {
101 error << string_compose(_("Could not use path %1 (%s)"), buf, strerror(errno)) << endmsg;
102 throw failed_constructor();
106 if (_path[_path.length()-1] != '/') {
110 /* these two are just provisional settings. set_state()
111 will likely override them.
114 _name = _current_snapshot_name = snapshot_name;
115 setup_raid_path (_path);
117 _current_frame_rate = _engine.frame_rate ();
118 _tempo_map = new TempoMap (_current_frame_rate);
119 _tempo_map->StateChanged.connect (mem_fun (*this, &Session::tempo_map_changed));
121 atomic_set (&processing_prohibited, 0);
124 _transport_speed = 0;
125 _last_transport_speed = 0;
126 transport_sub_state = 0;
127 _transport_frame = 0;
129 end_location = new Location (0, 0, _("end"), Location::Flags ((Location::IsMark|Location::IsEnd)));
130 start_location = new Location (0, 0, _("start"), Location::Flags ((Location::IsMark|Location::IsStart)));
131 _end_location_is_free = true;
132 atomic_set (&_record_status, Disabled);
137 seamless_loop = false;
138 loop_changing = false;
140 crossfades_active = false;
143 _last_roll_location = 0;
144 _last_record_location = 0;
145 pending_locate_frame = 0;
146 pending_locate_roll = false;
147 pending_locate_flush = false;
148 dstream_buffer_size = 0;
150 state_was_pending = false;
152 outbound_mtc_smpte_frame = 0;
153 next_quarter_frame_to_send = 0;
154 current_block_size = 0;
155 _solo_latched = true;
156 _solo_model = InverseMute;
157 solo_update_disabled = false;
158 currently_soloing = false;
159 _have_captured = false;
160 _worst_output_latency = 0;
161 _worst_input_latency = 0;
162 _worst_track_latency = 0;
163 _state_of_the_state = StateOfTheState(CannotSave|InitialConnecting|Loading);
166 butler_mixdown_buffer = 0;
167 butler_gain_buffer = 0;
172 post_transport_work = PostTransportWork (0);
173 atomic_set (&butler_should_do_transport_work, 0);
174 atomic_set (&butler_active, 0);
175 atomic_set (&_playback_load, 100);
176 atomic_set (&_capture_load, 100);
177 atomic_set (&_playback_load_min, 100);
178 atomic_set (&_capture_load_min, 100);
179 pending_audition_region = 0;
181 pending_edit_mode = _edit_mode;
185 input_auto_connect = AutoConnectOption (0);
186 output_auto_connect = AutoConnectOption (0);
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()) {
301 if (start_midi_thread ()) {
307 if (set_state (*state_tree->root())) {
312 /* we can't save till after ::when_engine_running() is called,
313 because otherwise we save state with no connections made.
314 therefore, we reset _state_of_the_state because ::set_state()
315 will have cleared it.
317 we also have to include Loading so that any events that get
318 generated between here and the end of ::when_engine_running()
319 will be processed directly rather than queued.
322 _state_of_the_state = StateOfTheState (_state_of_the_state|CannotSave|Loading);
324 // set_auto_input (true);
325 _locations.changed.connect (mem_fun (this, &Session::locations_changed));
326 _locations.added.connect (mem_fun (this, &Session::locations_added));
327 setup_click_sounds (0);
328 setup_midi_control ();
330 /* Pay attention ... */
332 _engine.Halted.connect (mem_fun (*this, &Session::engine_halted));
333 _engine.Xrun.connect (mem_fun (*this, &Session::xrun_recovery));
335 if (_engine.running()) {
336 when_engine_running();
338 first_time_running = _engine.Running.connect (mem_fun (*this, &Session::when_engine_running));
342 //send_full_time_code ();
343 _engine.transport_locate (0);
344 //deliver_mmc (MIDI::MachineControl::cmdMmcReset, 0);
345 //deliver_mmc (MIDI::MachineControl::cmdLocate, 0);
347 ControlProtocolManager::instance().set_session (*this);
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, "end-marker-is-free")) != 0) {
1027 if ((prop = child->property ("val")) != 0) {
1028 _end_location_is_free = (prop->value() == "yes");
1032 if ((child = find_named_node (node, "layer-model")) != 0) {
1033 if ((prop = child->property ("val")) != 0) {
1034 if (prop->value() == X_("LaterHigher")) {
1035 set_layer_model (LaterHigher);
1036 } else if (prop->value() == X_("AddHigher")) {
1037 set_layer_model (AddHigher);
1039 set_layer_model (MoveAddHigher);
1044 if ((child = find_named_node (node, "xfade-model")) != 0) {
1045 if ((prop = child->property ("val")) != 0) {
1046 if (prop->value() == X_("Short")) {
1047 set_xfade_model (ShortCrossfade);
1049 set_xfade_model (FullCrossfade);
1054 if ((child = find_named_node (node, "short-xfade-length")) != 0) {
1055 if ((prop = child->property ("val")) != 0) {
1056 /* value is stored as a fractional seconds */
1057 float secs = atof (prop->value().c_str());
1058 Crossfade::set_short_xfade_length ((jack_nframes_t) floor (secs * frame_rate()));
1062 if ((child = find_named_node (node, "full-xfades-unmuted")) != 0) {
1063 if ((prop = child->property ("val")) != 0) {
1064 crossfades_active = (prop->value() == "yes");
1070 if ((child = find_named_node (node, "default-fade-steepness")) != 0) {
1071 if ((prop = child->property ("val")) != 0) {
1072 fade_steepness = atof (prop->value().c_str());
1073 have_fade_steepness = true;
1076 if ((child = find_named_node (node, "default-fade-msec")) != 0) {
1077 if ((prop = child->property ("val")) != 0) {
1078 fade_msecs = atof (prop->value().c_str());
1079 have_fade_msecs = true;
1083 if (have_fade_steepness || have_fade_msecs) {
1084 // set_default_fade (fade_steepness, fade_msecs);
1091 Session::get_options () const
1096 LocaleGuard lg (X_("POSIX"));
1098 opthead = new XMLNode ("Options");
1100 SlaveSource src = slave_source ();
1104 src_string = "none";
1110 src_string = "jack";
1113 child = opthead->add_child ("slave");
1114 child->add_property ("type", src_string);
1116 child = opthead->add_child ("send-midi-timecode");
1117 child->add_property ("val", send_midi_timecode?"yes":"no");
1119 child = opthead->add_child ("send-midi-machine-control");
1120 child->add_property ("val", send_midi_machine_control?"yes":"no");
1122 snprintf (buf, sizeof(buf)-1, "%x", (int) input_auto_connect);
1123 child = opthead->add_child ("input-auto-connect");
1124 child->add_property ("val", buf);
1126 snprintf (buf, sizeof(buf)-1, "%x", (int) output_auto_connect);
1127 child = opthead->add_child ("output-auto-connect");
1128 child->add_property ("val", buf);
1130 snprintf (buf, sizeof(buf)-1, "%d", max_level);
1131 child = opthead->add_child ("max-level");
1132 child->add_property ("val", buf);
1134 snprintf (buf, sizeof(buf)-1, "%d", min_level);
1135 child = opthead->add_child ("min-level");
1136 child->add_property ("val", buf);
1138 snprintf (buf, sizeof(buf)-1, "%f", _meter_hold);
1139 child = opthead->add_child ("meter-hold");
1140 child->add_property ("val", buf);
1142 snprintf (buf, sizeof(buf)-1, "%f", _meter_falloff);
1143 child = opthead->add_child ("meter-falloff");
1144 child->add_property ("val", buf);
1146 snprintf (buf, sizeof(buf)-1, "%u", over_length_long);
1147 child = opthead->add_child ("long-over-length");
1148 child->add_property ("val", buf);
1150 snprintf (buf, sizeof(buf)-1, "%u", over_length_short);
1151 child = opthead->add_child ("short-over-length");
1152 child->add_property ("val", buf);
1154 snprintf (buf, sizeof(buf)-1, "%f", shuttle_speed_factor);
1155 child = opthead->add_child ("shuttle-speed-factor");
1156 child->add_property ("val", buf);
1158 snprintf (buf, sizeof(buf)-1, "%f", shuttle_speed_threshold);
1159 child = opthead->add_child ("shuttle-speed-threshold");
1160 child->add_property ("val", buf);
1162 snprintf (buf, sizeof(buf)-1, "%f", rf_speed);
1163 child = opthead->add_child ("rf-speed");
1164 child->add_property ("val", buf);
1166 snprintf (buf, sizeof(buf)-1, "%.2f", smpte_frames_per_second);
1167 child = opthead->add_child ("smpte-frames-per-second");
1168 child->add_property ("val", buf);
1170 child = opthead->add_child ("smpte-drop-frames");
1171 child->add_property ("val", smpte_drop_frames ? "yes" : "no");
1173 snprintf (buf, sizeof(buf)-1, "%u", smpte_offset ());
1174 child = opthead->add_child ("smpte-offset");
1175 child->add_property ("val", buf);
1177 child = opthead->add_child ("smpte-offset-negative");
1178 child->add_property ("val", smpte_offset_negative () ? "yes" : "no");
1180 child = opthead->add_child ("edit-mode");
1181 switch (_edit_mode) {
1183 child->add_property ("val", "splice");
1187 child->add_property ("val", "slide");
1191 child = opthead->add_child ("auto-play");
1192 child->add_property ("val", get_auto_play () ? "yes" : "no");
1193 child = opthead->add_child ("auto-input");
1194 child->add_property ("val", get_auto_input () ? "yes" : "no");
1195 child = opthead->add_child ("seamless-loop");
1196 child->add_property ("val", get_seamless_loop () ? "yes" : "no");
1197 child = opthead->add_child ("punch-in");
1198 child->add_property ("val", get_punch_in () ? "yes" : "no");
1199 child = opthead->add_child ("punch-out");
1200 child->add_property ("val", get_punch_out () ? "yes" : "no");
1201 child = opthead->add_child ("all-safe");
1202 child->add_property ("val", get_all_safe () ? "yes" : "no");
1203 child = opthead->add_child ("auto-return");
1204 child->add_property ("val", get_auto_return () ? "yes" : "no");
1205 child = opthead->add_child ("mmc-control");
1206 child->add_property ("val", get_mmc_control () ? "yes" : "no");
1207 child = opthead->add_child ("midi-control");
1208 child->add_property ("val", get_midi_control () ? "yes" : "no");
1209 child = opthead->add_child ("midi-feedback");
1210 child->add_property ("val", get_midi_feedback () ? "yes" : "no");
1211 child = opthead->add_child ("do-not-record-plugins");
1212 child->add_property ("val", get_do_not_record_plugins () ? "yes" : "no");
1213 child = opthead->add_child ("auto-crossfade");
1214 child->add_property ("val", get_crossfades_active () ? "yes" : "no");
1215 child = opthead->add_child ("audible-click");
1216 child->add_property ("val", get_clicking () ? "yes" : "no");
1217 child = opthead->add_child ("end-marker-is-free");
1218 child->add_property ("val", _end_location_is_free ? "yes" : "no");
1220 if (click_sound.length()) {
1221 child = opthead->add_child ("click-sound");
1222 child->add_property ("val", click_sound);
1225 if (click_emphasis_sound.length()) {
1226 child = opthead->add_child ("click-emphasis-sound");
1227 child->add_property ("val", click_emphasis_sound);
1230 child = opthead->add_child ("solo-model");
1231 child->add_property ("val", _solo_model == SoloBus ? "SoloBus" : "InverseMute");
1233 child = opthead->add_child ("layer-model");
1234 switch (layer_model) {
1236 child->add_property ("val", X_("LaterHigher"));
1239 child->add_property ("val", X_("MoveAddHigher"));
1242 child->add_property ("val", X_("AddHigher"));
1246 child = opthead->add_child ("xfade-model");
1247 switch (xfade_model) {
1249 child->add_property ("val", X_("Full"));
1251 case ShortCrossfade:
1252 child->add_property ("val", X_("Short"));
1255 child = opthead->add_child ("short-xfade-length");
1256 /* store as fractions of a second */
1257 snprintf (buf, sizeof(buf)-1, "%f",
1258 (float) Crossfade::short_xfade_length() / frame_rate());
1259 child->add_property ("val", buf);
1261 child = opthead->add_child ("full-xfades-unmuted");
1262 child->add_property ("val", crossfades_active ? "yes" : "no");
1268 Session::get_state()
1274 Session::get_template()
1276 /* if we don't disable rec-enable, diskstreams
1277 will believe they need to store their capture
1278 sources in their state node.
1281 disable_record (false);
1283 return state(false);
1287 Session::state(bool full_state)
1289 XMLNode* node = new XMLNode("Session");
1292 // store libardour version, just in case
1294 snprintf(buf, sizeof(buf)-1, "%d.%d.%d",
1295 libardour_major_version, libardour_minor_version, libardour_micro_version);
1296 node->add_property("version", string(buf));
1298 /* store configuration settings */
1302 /* store the name */
1303 node->add_property ("name", _name);
1305 if (session_dirs.size() > 1) {
1309 vector<space_and_path>::iterator i = session_dirs.begin();
1310 vector<space_and_path>::iterator next;
1312 ++i; /* skip the first one */
1316 while (i != session_dirs.end()) {
1320 if (next != session_dirs.end()) {
1330 child = node->add_child ("Path");
1331 child->add_content (p);
1335 node->add_child_nocopy (get_options());
1337 child = node->add_child ("Sources");
1340 LockMonitor sl (source_lock, __LINE__, __FILE__);
1342 for (SourceList::iterator siter = sources.begin(); siter != sources.end(); ++siter) {
1344 /* Don't save information about FileSources that are empty */
1348 if ((fs = dynamic_cast<FileSource*> ((*siter).second)) != 0) {
1349 DestructiveFileSource* dfs = dynamic_cast<DestructiveFileSource*> (fs);
1351 /* destructive file sources are OK if they are empty, because
1352 we will re-use them every time.
1356 if (fs->length() == 0) {
1362 child->add_child_nocopy ((*siter).second->get_state());
1366 child = node->add_child ("Regions");
1369 LockMonitor rl (region_lock, __LINE__, __FILE__);
1371 for (AudioRegionList::const_iterator i = audio_regions.begin(); i != audio_regions.end(); ++i) {
1373 /* only store regions not attached to playlists */
1375 if ((*i).second->playlist() == 0) {
1376 child->add_child_nocopy (i->second->state (true));
1381 child = node->add_child ("DiskStreams");
1384 RWLockMonitor dl (diskstream_lock, false, __LINE__, __FILE__);
1385 for (DiskStreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
1386 if (!(*i)->hidden()) {
1387 child->add_child_nocopy ((*i)->get_state());
1392 node->add_child_nocopy (_locations.get_state());
1394 child = node->add_child ("Connections");
1396 LockMonitor lm (connection_lock, __LINE__, __FILE__);
1397 for (ConnectionList::iterator i = _connections.begin(); i != _connections.end(); ++i) {
1398 if (!(*i)->system_dependent()) {
1399 child->add_child_nocopy ((*i)->get_state());
1404 child = node->add_child ("Routes");
1406 RWLockMonitor lm (route_lock, false, __LINE__, __FILE__);
1408 RoutePublicOrderSorter cmp;
1409 RouteList public_order(routes);
1410 public_order.sort (cmp);
1412 for (RouteList::iterator i = public_order.begin(); i != public_order.end(); ++i) {
1413 if (!(*i)->hidden()) {
1415 child->add_child_nocopy ((*i)->get_state());
1417 child->add_child_nocopy ((*i)->get_template());
1424 child = node->add_child ("EditGroups");
1425 for (list<RouteGroup *>::iterator i = edit_groups.begin(); i != edit_groups.end(); ++i) {
1426 child->add_child_nocopy ((*i)->get_state());
1429 child = node->add_child ("MixGroups");
1430 for (list<RouteGroup *>::iterator i = mix_groups.begin(); i != mix_groups.end(); ++i) {
1431 child->add_child_nocopy ((*i)->get_state());
1434 child = node->add_child ("Playlists");
1435 for (PlaylistList::iterator i = playlists.begin(); i != playlists.end(); ++i) {
1436 if (!(*i)->hidden()) {
1437 if (!(*i)->empty()) {
1439 child->add_child_nocopy ((*i)->get_state());
1441 child->add_child_nocopy ((*i)->get_template());
1447 child = node->add_child ("UnusedPlaylists");
1448 for (PlaylistList::iterator i = unused_playlists.begin(); i != unused_playlists.end(); ++i) {
1449 if (!(*i)->hidden()) {
1450 if (!(*i)->empty()) {
1452 child->add_child_nocopy ((*i)->get_state());
1454 child->add_child_nocopy ((*i)->get_template());
1462 child = node->add_child ("Click");
1463 child->add_child_nocopy (_click_io->state (full_state));
1467 child = node->add_child ("NamedSelections");
1468 for (NamedSelectionList::iterator i = named_selections.begin(); i != named_selections.end(); ++i) {
1470 child->add_child_nocopy ((*i)->get_state());
1475 node->add_child_nocopy (_tempo_map->get_state());
1478 node->add_child_copy (*_extra_xml);
1485 Session::set_state (const XMLNode& node)
1489 const XMLProperty* prop;
1492 _state_of_the_state = StateOfTheState (_state_of_the_state|CannotSave);
1494 if (node.name() != "Session"){
1495 fatal << _("programming error: Session: incorrect XML node sent to set_state()") << endmsg;
1499 StateManager::prohibit_save ();
1501 if ((prop = node.property ("name")) != 0) {
1502 _name = prop->value ();
1505 IO::disable_ports ();
1506 IO::disable_connecting ();
1508 /* Object loading order:
1525 if (use_config_midi_ports ()) {
1528 if ((child = find_named_node (node, "Path")) != 0) {
1529 /* XXX this XML content stuff horrible API design */
1530 string raid_path = _path + ':' + child->children().front()->content();
1531 setup_raid_path (raid_path);
1533 /* the path is already set */
1536 if ((child = find_named_node (node, "extra")) != 0) {
1537 _extra_xml = new XMLNode (*child);
1540 if ((child = find_named_node (node, "Options")) == 0) {
1541 error << _("Session: XML state has no options section") << endmsg;
1542 } else if (load_options (*child)) {
1545 if ((child = find_named_node (node, "Sources")) == 0) {
1546 error << _("Session: XML state has no sources section") << endmsg;
1548 } else if (load_sources (*child)) {
1552 if ((child = find_named_node (node, "Regions")) == 0) {
1553 error << _("Session: XML state has no Regions section") << endmsg;
1555 } else if (load_regions (*child)) {
1559 if ((child = find_named_node (node, "Playlists")) == 0) {
1560 error << _("Session: XML state has no playlists section") << endmsg;
1562 } else if (load_playlists (*child)) {
1566 if ((child = find_named_node (node, "UnusedPlaylists")) == 0) {
1568 } else if (load_unused_playlists (*child)) {
1572 if ((child = find_named_node (node, "NamedSelections")) != 0) {
1573 if (load_named_selections (*child)) {
1578 if ((child = find_named_node (node, "DiskStreams")) == 0) {
1579 error << _("Session: XML state has no diskstreams section") << endmsg;
1581 } else if (load_diskstreams (*child)) {
1585 if ((child = find_named_node (node, "Connections")) == 0) {
1586 error << _("Session: XML state has no connections section") << endmsg;
1588 } else if (load_connections (*child)) {
1592 if ((child = find_named_node (node, "Locations")) == 0) {
1593 error << _("Session: XML state has no locations section") << endmsg;
1595 } else if (_locations.set_state (*child)) {
1601 if ((location = _locations.auto_loop_location()) != 0) {
1602 set_auto_loop_location (location);
1605 if ((location = _locations.auto_punch_location()) != 0) {
1606 set_auto_punch_location (location);
1609 if ((location = _locations.end_location()) == 0) {
1610 _locations.add (end_location);
1612 delete end_location;
1613 end_location = location;
1616 if ((location = _locations.start_location()) == 0) {
1617 _locations.add (start_location);
1619 delete start_location;
1620 start_location = location;
1623 _locations.save_state (_("initial state"));
1625 if ((child = find_named_node (node, "EditGroups")) == 0) {
1626 error << _("Session: XML state has no edit groups section") << endmsg;
1628 } else if (load_edit_groups (*child)) {
1632 if ((child = find_named_node (node, "MixGroups")) == 0) {
1633 error << _("Session: XML state has no mix groups section") << endmsg;
1635 } else if (load_mix_groups (*child)) {
1639 if ((child = find_named_node (node, "TempoMap")) == 0) {
1640 error << _("Session: XML state has no Tempo Map section") << endmsg;
1642 } else if (_tempo_map->set_state (*child)) {
1646 if ((child = find_named_node (node, "Routes")) == 0) {
1647 error << _("Session: XML state has no routes section") << endmsg;
1649 } else if (load_routes (*child)) {
1653 if ((child = find_named_node (node, "Click")) == 0) {
1654 warning << _("Session: XML state has no click section") << endmsg;
1655 } else if (_click_io) {
1656 _click_io->set_state (*child);
1659 /* OK, now we can set edit mode */
1661 set_edit_mode (pending_edit_mode);
1663 /* here beginneth the second phase ... */
1665 StateReady (); /* EMIT SIGNAL */
1667 _state_of_the_state = Clean;
1669 StateManager::allow_save (_("initial state"), true);
1671 if (state_was_pending) {
1672 save_state (_current_snapshot_name);
1673 remove_pending_capture_state ();
1674 state_was_pending = false;
1680 /* we failed, re-enable state saving but don't actually save internal state */
1681 StateManager::allow_save (X_("ignored"), false);
1686 Session::load_routes (const XMLNode& node)
1689 XMLNodeConstIterator niter;
1692 nlist = node.children();
1696 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1698 if ((route = XMLRouteFactory (**niter)) == 0) {
1699 error << _("Session: cannot create Route from XML description.") << endmsg;
1710 Session::XMLRouteFactory (const XMLNode& node)
1712 if (node.name() != "Route") {
1716 if (node.property ("diskstream") != 0 || node.property ("diskstream-id") != 0) {
1717 return new AudioTrack (*this, node);
1719 return new Route (*this, node);
1724 Session::load_regions (const XMLNode& node)
1727 XMLNodeConstIterator niter;
1728 AudioRegion* region;
1730 nlist = node.children();
1734 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1736 if ((region = XMLRegionFactory (**niter, false)) == 0) {
1737 error << _("Session: cannot create Region from XML description.") << endmsg;
1745 Session::XMLRegionFactory (const XMLNode& node, bool full)
1747 const XMLProperty* prop;
1750 AudioRegion::SourceList sources;
1751 uint32_t nchans = 1;
1754 if (node.name() != X_("Region")) {
1758 if ((prop = node.property (X_("channels"))) != 0) {
1759 nchans = atoi (prop->value().c_str());
1763 if ((prop = node.property (X_("source-0"))) == 0) {
1764 if ((prop = node.property ("source")) == 0) {
1765 error << _("Session: XMLNode describing a AudioRegion is incomplete (no source)") << endmsg;
1770 sscanf (prop->value().c_str(), "%" PRIu64, &s_id);
1772 if ((source = get_source (s_id)) == 0) {
1773 error << string_compose(_("Session: XMLNode describing a AudioRegion references an unknown source id =%1"), s_id) << endmsg;
1777 sources.push_back(source);
1779 /* pickup other channels */
1781 for (uint32_t n=1; n < nchans; ++n) {
1782 snprintf (buf, sizeof(buf), X_("source-%d"), n);
1783 if ((prop = node.property (buf)) != 0) {
1784 sscanf (prop->value().c_str(), "%" PRIu64, &s_id);
1786 if ((source = get_source (s_id)) == 0) {
1787 error << string_compose(_("Session: XMLNode describing a AudioRegion references an unknown source id =%1"), s_id) << endmsg;
1790 sources.push_back(source);
1796 return new AudioRegion (sources, node);
1799 catch (failed_constructor& err) {
1805 Session::get_sources_as_xml ()
1808 XMLNode* node = new XMLNode (X_("Sources"));
1809 LockMonitor lm (source_lock, __LINE__, __FILE__);
1811 for (SourceList::iterator i = sources.begin(); i != sources.end(); ++i) {
1812 node->add_child_nocopy ((*i).second->get_state());
1819 Session::path_from_region_name (string name, string identifier)
1821 char buf[PATH_MAX+1];
1823 string dir = discover_best_sound_dir ();
1825 for (n = 0; n < 999999; ++n) {
1826 if (identifier.length()) {
1827 snprintf (buf, sizeof(buf), "%s/%s%s%" PRIu32 ".wav", dir.c_str(), name.c_str(),
1828 identifier.c_str(), n);
1830 snprintf (buf, sizeof(buf), "%s/%s-%" PRIu32 ".wav", dir.c_str(), name.c_str(), n);
1832 if (access (buf, F_OK) != 0) {
1842 Session::load_sources (const XMLNode& node)
1845 XMLNodeConstIterator niter;
1848 nlist = node.children();
1852 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1854 if ((source = XMLSourceFactory (**niter)) == 0) {
1855 error << _("Session: cannot create Source from XML description.") << endmsg;
1863 Session::XMLSourceFactory (const XMLNode& node)
1867 if (node.name() != "Source") {
1872 if (node.property (X_("destructive")) != 0) {
1873 src = new DestructiveFileSource (node, frame_rate());
1875 src = new FileSource (node, frame_rate());
1879 catch (failed_constructor& err) {
1882 src = ExternalSource::create (node);
1885 catch (failed_constructor& err) {
1886 error << _("Found a sound file that cannot be used by Ardour. See the progammers.") << endmsg;
1895 Session::save_template (string template_name)
1898 string xml_path, bak_path, template_path;
1900 if (_state_of_the_state & CannotSave) {
1905 string dir = template_dir();
1907 if ((dp = opendir (dir.c_str()))) {
1910 if (mkdir (dir.c_str(), S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH)<0) {
1911 error << string_compose(_("Could not create mix templates directory \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
1916 tree.set_root (&get_template());
1919 xml_path += template_name;
1920 xml_path += _template_suffix;
1922 ifstream in(xml_path.c_str());
1925 warning << string_compose(_("Template \"%1\" already exists - new version not created"), template_name) << endmsg;
1931 if (!tree.write (xml_path)) {
1932 error << _("mix template not saved") << endmsg;
1940 Session::rename_template (string old_name, string new_name)
1942 string old_path = template_dir() + old_name + _template_suffix;
1943 string new_path = template_dir() + new_name + _template_suffix;
1945 return rename (old_path.c_str(), new_path.c_str());
1949 Session::delete_template (string name)
1951 string template_path = template_dir();
1952 template_path += name;
1953 template_path += _template_suffix;
1955 return remove (template_path.c_str());
1959 Session::refresh_disk_space ()
1962 struct statfs statfsbuf;
1963 vector<space_and_path>::iterator i;
1964 LockMonitor lm (space_lock, __LINE__, __FILE__);
1967 /* get freespace on every FS that is part of the session path */
1969 _total_free_4k_blocks = 0;
1971 for (i = session_dirs.begin(); i != session_dirs.end(); ++i) {
1972 statfs ((*i).path.c_str(), &statfsbuf);
1974 scale = statfsbuf.f_bsize/4096.0;
1976 (*i).blocks = (uint32_t) floor (statfsbuf.f_bavail * scale);
1977 _total_free_4k_blocks += (*i).blocks;
1983 Session::ensure_sound_dir (string path, string& result)
1988 /* Ensure that the parent directory exists */
1990 if (mkdir (path.c_str(), 0775)) {
1991 if (errno != EEXIST) {
1992 error << string_compose(_("cannot create session directory \"%1\"; ignored"), path) << endmsg;
1997 /* Ensure that the sounds directory exists */
2001 result += sound_dir_name;
2003 if (mkdir (result.c_str(), 0775)) {
2004 if (errno != EEXIST) {
2005 error << string_compose(_("cannot create sounds directory \"%1\"; ignored"), result) << endmsg;
2012 dead += dead_sound_dir_name;
2014 if (mkdir (dead.c_str(), 0775)) {
2015 if (errno != EEXIST) {
2016 error << string_compose(_("cannot create dead sounds directory \"%1\"; ignored"), dead) << endmsg;
2023 peak += peak_dir_name;
2025 if (mkdir (peak.c_str(), 0775)) {
2026 if (errno != EEXIST) {
2027 error << string_compose(_("cannot create peak file directory \"%1\"; ignored"), peak) << endmsg;
2032 /* callers expect this to be terminated ... */
2039 Session::discover_best_sound_dir (bool destructive)
2041 vector<space_and_path>::iterator i;
2044 /* destructive files all go into the same place */
2050 /* handle common case without system calls */
2052 if (session_dirs.size() == 1) {
2056 /* OK, here's the algorithm we're following here:
2058 We want to select which directory to use for
2059 the next file source to be created. Ideally,
2060 we'd like to use a round-robin process so as to
2061 get maximum performance benefits from splitting
2062 the files across multiple disks.
2064 However, in situations without much diskspace, an
2065 RR approach may end up filling up a filesystem
2066 with new files while others still have space.
2067 Its therefore important to pay some attention to
2068 the freespace in the filesystem holding each
2069 directory as well. However, if we did that by
2070 itself, we'd keep creating new files in the file
2071 system with the most space until it was as full
2072 as all others, thus negating any performance
2073 benefits of this RAID-1 like approach.
2075 So, we use a user-configurable space threshold. If
2076 there are at least 2 filesystems with more than this
2077 much space available, we use RR selection between them.
2078 If not, then we pick the filesystem with the most space.
2080 This gets a good balance between the two
2084 refresh_disk_space ();
2086 int free_enough = 0;
2088 for (i = session_dirs.begin(); i != session_dirs.end(); ++i) {
2089 if ((*i).blocks * 4096 >= Config->get_disk_choice_space_threshold()) {
2094 if (free_enough >= 2) {
2096 bool found_it = false;
2098 /* use RR selection process, ensuring that the one
2102 i = last_rr_session_dir;
2105 if (++i == session_dirs.end()) {
2106 i = session_dirs.begin();
2109 if ((*i).blocks * 4096 >= Config->get_disk_choice_space_threshold()) {
2110 if (ensure_sound_dir ((*i).path, result) == 0) {
2111 last_rr_session_dir = i;
2117 } while (i != last_rr_session_dir);
2120 result = sound_dir();
2125 /* pick FS with the most freespace (and that
2126 seems to actually work ...)
2129 vector<space_and_path> sorted;
2130 space_and_path_ascending_cmp cmp;
2132 sorted = session_dirs;
2133 sort (sorted.begin(), sorted.end(), cmp);
2135 for (i = sorted.begin(); i != sorted.end(); ++i) {
2136 if (ensure_sound_dir ((*i).path, result) == 0) {
2137 last_rr_session_dir = i;
2142 /* if the above fails, fall back to the most simplistic solution */
2144 if (i == sorted.end()) {
2153 Session::load_playlists (const XMLNode& node)
2156 XMLNodeConstIterator niter;
2159 nlist = node.children();
2163 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2165 if ((playlist = XMLPlaylistFactory (**niter)) == 0) {
2166 error << _("Session: cannot create Playlist from XML description.") << endmsg;
2174 Session::load_unused_playlists (const XMLNode& node)
2177 XMLNodeConstIterator niter;
2180 nlist = node.children();
2184 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2186 if ((playlist = XMLPlaylistFactory (**niter)) == 0) {
2187 error << _("Session: cannot create Playlist from XML description.") << endmsg;
2191 // now manually untrack it
2193 track_playlist (playlist, false);
2201 Session::XMLPlaylistFactory (const XMLNode& node)
2204 return new AudioPlaylist (*this, node);
2207 catch (failed_constructor& err) {
2213 Session::load_named_selections (const XMLNode& node)
2216 XMLNodeConstIterator niter;
2219 nlist = node.children();
2223 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2225 if ((ns = XMLNamedSelectionFactory (**niter)) == 0) {
2226 error << _("Session: cannot create Named Selection from XML description.") << endmsg;
2234 Session::XMLNamedSelectionFactory (const XMLNode& node)
2237 return new NamedSelection (*this, node);
2240 catch (failed_constructor& err) {
2246 Session::dead_sound_dir () const
2249 res += dead_sound_dir_name;
2255 Session::sound_dir () const
2258 res += sound_dir_name;
2264 Session::tape_dir () const
2267 res += tape_dir_name;
2273 Session::peak_dir () const
2276 res += peak_dir_name;
2282 Session::automation_dir () const
2285 res += "automation/";
2290 Session::template_dir ()
2292 string path = get_user_ardour_path();
2293 path += "templates/";
2299 Session::suffixed_search_path (string suffix, bool data)
2303 path += get_user_ardour_path();
2304 if (path[path.length()-1] != ':') {
2309 path += get_system_data_path();
2311 path += get_system_module_path();
2314 vector<string> split_path;
2316 split (path, split_path, ':');
2319 for (vector<string>::iterator i = split_path.begin(); i != split_path.end(); ++i) {
2324 if (distance (i, split_path.end()) != 1) {
2333 Session::template_path ()
2335 return suffixed_search_path (X_("templates"), true);
2339 Session::control_protocol_path ()
2341 return suffixed_search_path (X_("surfaces"), false);
2345 Session::load_connections (const XMLNode& node)
2347 XMLNodeList nlist = node.children();
2348 XMLNodeConstIterator niter;
2352 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2353 if ((*niter)->name() == "InputConnection") {
2354 add_connection (new ARDOUR::InputConnection (**niter));
2355 } else if ((*niter)->name() == "OutputConnection") {
2356 add_connection (new ARDOUR::OutputConnection (**niter));
2358 error << string_compose(_("Unknown node \"%1\" found in Connections list from state file"), (*niter)->name()) << endmsg;
2367 Session::load_edit_groups (const XMLNode& node)
2369 return load_route_groups (node, true);
2373 Session::load_mix_groups (const XMLNode& node)
2375 return load_route_groups (node, false);
2379 Session::load_route_groups (const XMLNode& node, bool edit)
2381 XMLNodeList nlist = node.children();
2382 XMLNodeConstIterator niter;
2387 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2388 if ((*niter)->name() == "RouteGroup") {
2390 rg = add_edit_group ("");
2391 rg->set_state (**niter);
2393 rg = add_mix_group ("");
2394 rg->set_state (**niter);
2403 Session::swap_configuration(Configuration** new_config)
2405 RWLockMonitor lm (route_lock, true, __LINE__, __FILE__); // jlc - WHY?
2406 Configuration* tmp = *new_config;
2407 *new_config = Config;
2413 Session::copy_configuration(Configuration* new_config)
2415 RWLockMonitor lm (route_lock, true, __LINE__, __FILE__);
2416 new_config = new Configuration(*Config);
2420 state_file_filter (const string &str, void *arg)
2422 return (str.length() > strlen(Session::statefile_suffix()) &&
2423 str.find (Session::statefile_suffix()) == (str.length() - strlen (Session::statefile_suffix())));
2427 bool operator()(const string* a, const string* b) {
2433 remove_end(string* state)
2435 string statename(*state);
2437 string::size_type start,end;
2438 if ((start = statename.find_last_of ('/')) != string::npos) {
2439 statename = statename.substr (start+1);
2442 if ((end = statename.rfind(".ardour")) < 0) {
2443 end = statename.length();
2446 return new string(statename.substr (0, end));
2450 Session::possible_states (string path)
2452 PathScanner scanner;
2453 vector<string*>* states = scanner (path, state_file_filter, 0, false, false);
2455 transform(states->begin(), states->end(), states->begin(), remove_end);
2458 sort (states->begin(), states->end(), cmp);
2464 Session::possible_states () const
2466 return possible_states(_path);
2470 Session::auto_save()
2472 save_state (_current_snapshot_name);
2476 Session::add_edit_group (string name)
2478 RouteGroup* rg = new RouteGroup (*this, name);
2479 edit_groups.push_back (rg);
2480 edit_group_added (rg); /* EMIT SIGNAL */
2486 Session::add_mix_group (string name)
2488 RouteGroup* rg = new RouteGroup (*this, name, RouteGroup::Relative);
2489 mix_groups.push_back (rg);
2490 mix_group_added (rg); /* EMIT SIGNAL */
2496 Session::remove_edit_group (RouteGroup& rg)
2498 list<RouteGroup*>::iterator i;
2500 if ((i = find (edit_groups.begin(), edit_groups.end(), &rg)) != edit_groups.end()) {
2501 (*i)->apply (&Route::drop_edit_group, this);
2502 edit_groups.erase (i);
2503 edit_group_removed (); /* EMIT SIGNAL */
2510 Session::remove_mix_group (RouteGroup& rg)
2512 list<RouteGroup*>::iterator i;
2514 if ((i = find (mix_groups.begin(), mix_groups.end(), &rg)) != mix_groups.end()) {
2515 (*i)->apply (&Route::drop_mix_group, this);
2516 mix_groups.erase (i);
2517 mix_group_removed (); /* EMIT SIGNAL */
2524 Session::mix_group_by_name (string name)
2526 list<RouteGroup *>::iterator i;
2528 for (i = mix_groups.begin(); i != mix_groups.end(); ++i) {
2529 if ((*i)->name() == name) {
2537 Session::edit_group_by_name (string name)
2539 list<RouteGroup *>::iterator i;
2541 for (i = edit_groups.begin(); i != edit_groups.end(); ++i) {
2542 if ((*i)->name() == name) {
2550 Session::set_meter_hold (float val)
2553 MeterHoldChanged(); // emit
2557 Session::set_meter_falloff (float val)
2559 _meter_falloff = val;
2560 MeterFalloffChanged(); // emit
2565 Session::begin_reversible_command (string name, UndoAction* private_undo)
2567 current_cmd.clear ();
2568 current_cmd.set_name (name);
2571 current_cmd.add_undo (*private_undo);
2576 Session::commit_reversible_command (UndoAction* private_redo)
2581 current_cmd.add_redo_no_execute (*private_redo);
2584 gettimeofday (&now, 0);
2585 current_cmd.set_timestamp (now);
2587 history.add (current_cmd);
2590 Session::GlobalRouteBooleanState
2591 Session::get_global_route_boolean (bool (Route::*method)(void) const)
2593 GlobalRouteBooleanState s;
2594 RWLockMonitor lm (route_lock, false, __LINE__, __FILE__);
2596 for (RouteList::iterator i = routes.begin(); i != routes.end(); ++i) {
2597 if (!(*i)->hidden()) {
2598 RouteBooleanState v;
2601 v.second = ((*i)->*method)();
2610 Session::GlobalRouteMeterState
2611 Session::get_global_route_metering ()
2613 GlobalRouteMeterState s;
2614 RWLockMonitor lm (route_lock, false, __LINE__, __FILE__);
2616 for (RouteList::iterator i = routes.begin(); i != routes.end(); ++i) {
2617 if (!(*i)->hidden()) {
2621 v.second = (*i)->meter_point();
2631 Session::set_global_route_metering (GlobalRouteMeterState s, void* arg)
2633 for (GlobalRouteMeterState::iterator i = s.begin(); i != s.end(); ++i) {
2634 i->first->set_meter_point (i->second, arg);
2639 Session::set_global_route_boolean (GlobalRouteBooleanState s, void (Route::*method)(bool, void*), void* arg)
2641 for (GlobalRouteBooleanState::iterator i = s.begin(); i != s.end(); ++i) {
2642 (i->first->*method) (i->second, arg);
2647 Session::set_global_mute (GlobalRouteBooleanState s, void* src)
2649 set_global_route_boolean (s, &Route::set_mute, src);
2653 Session::set_global_solo (GlobalRouteBooleanState s, void* src)
2655 set_global_route_boolean (s, &Route::set_solo, src);
2659 Session::set_global_record_enable (GlobalRouteBooleanState s, void* src)
2661 set_global_route_boolean (s, &Route::set_record_enable, src);
2665 Session::global_mute_memento (void* src)
2667 return sigc::bind (mem_fun (*this, &Session::set_global_mute), get_global_route_boolean (&Route::muted), src);
2671 Session::global_metering_memento (void* src)
2673 return sigc::bind (mem_fun (*this, &Session::set_global_route_metering), get_global_route_metering (), src);
2677 Session::global_solo_memento (void* src)
2679 return sigc::bind (mem_fun (*this, &Session::set_global_solo), get_global_route_boolean (&Route::soloed), src);
2683 Session::global_record_enable_memento (void* src)
2685 return sigc::bind (mem_fun (*this, &Session::set_global_record_enable), get_global_route_boolean (&Route::record_enabled), src);
2689 template_filter (const string &str, void *arg)
2691 return (str.length() > strlen(Session::template_suffix()) &&
2692 str.find (Session::template_suffix()) == (str.length() - strlen (Session::template_suffix())));
2696 Session::get_template_list (list<string> &template_names)
2698 vector<string *> *templates;
2699 PathScanner scanner;
2702 path = template_path ();
2704 templates = scanner (path, template_filter, 0, false, true);
2706 vector<string*>::iterator i;
2707 for (i = templates->begin(); i != templates->end(); ++i) {
2708 string fullpath = *(*i);
2711 start = fullpath.find_last_of ('/') + 1;
2712 if ((end = fullpath.find_last_of ('.')) <0) {
2713 end = fullpath.length();
2716 template_names.push_back(fullpath.substr(start, (end-start)));
2721 Session::read_favorite_dirs (FavoriteDirs & favs)
2723 string path = get_user_ardour_path();
2724 path += "/favorite_dirs";
2726 ifstream fav (path.c_str());
2731 if (errno != ENOENT) {
2732 //error << string_compose (_("cannot open favorite file %1 (%2)"), path, strerror (errno)) << endmsg;
2743 getline(fav, newfav);
2749 favs.push_back (newfav);
2756 Session::write_favorite_dirs (FavoriteDirs & favs)
2758 string path = get_user_ardour_path();
2759 path += "/favorite_dirs";
2761 ofstream fav (path.c_str());
2767 for (FavoriteDirs::iterator i = favs.begin(); i != favs.end(); ++i) {
2768 fav << (*i) << endl;
2775 accept_all_non_peak_files (const string& path, void *arg)
2777 return (path.length() > 5 && path.find (".peak") != (path.length() - 5));
2781 accept_all_state_files (const string& path, void *arg)
2783 return (path.length() > 7 && path.find (".ardour") == (path.length() - 7));
2787 Session::find_all_sources (string path, set<string>& result)
2792 if (!tree.read (path)) {
2796 if ((node = find_named_node (*tree.root(), "Sources")) == 0) {
2801 XMLNodeConstIterator niter;
2803 nlist = node->children();
2807 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2811 if ((prop = (*niter)->property (X_("name"))) == 0) {
2815 if (prop->value()[0] == '/') {
2816 /* external file, ignore */
2820 string path = _path; /* /-terminated */
2821 path += sound_dir_name;
2823 path += prop->value();
2825 result.insert (path);
2832 Session::find_all_sources_across_snapshots (set<string>& result, bool exclude_this_snapshot)
2834 PathScanner scanner;
2835 vector<string*>* state_files;
2837 string this_snapshot_path;
2843 if (ripped[ripped.length()-1] == '/') {
2844 ripped = ripped.substr (0, ripped.length() - 1);
2847 state_files = scanner (ripped, accept_all_state_files, (void *) 0, false, true);
2849 if (state_files == 0) {
2854 this_snapshot_path = _path;
2855 this_snapshot_path += _current_snapshot_name;
2856 this_snapshot_path += _statefile_suffix;
2858 for (vector<string*>::iterator i = state_files->begin(); i != state_files->end(); ++i) {
2860 if (exclude_this_snapshot && **i == this_snapshot_path) {
2864 if (find_all_sources (**i, result) < 0) {
2873 Session::cleanup_sources (Session::cleanup_report& rep)
2875 vector<Source*> dead_sources;
2876 vector<Playlist*> playlists_tbd;
2877 PathScanner scanner;
2879 vector<space_and_path>::iterator i;
2880 vector<space_and_path>::iterator nexti;
2881 vector<string*>* soundfiles;
2882 vector<string> unused;
2883 set<string> all_sources;
2888 _state_of_the_state = (StateOfTheState) (_state_of_the_state | InCleanup);
2890 /* step 1: consider deleting all unused playlists */
2892 for (PlaylistList::iterator x = unused_playlists.begin(); x != unused_playlists.end(); ++x) {
2895 status = AskAboutPlaylistDeletion (*x);
2904 playlists_tbd.push_back (*x);
2908 /* leave it alone */
2913 /* now delete any that were marked for deletion */
2915 for (vector<Playlist*>::iterator x = playlists_tbd.begin(); x != playlists_tbd.end(); ++x) {
2916 PlaylistList::iterator foo;
2918 if ((foo = unused_playlists.find (*x)) != unused_playlists.end()) {
2919 unused_playlists.erase (foo);
2924 /* step 2: clear the undo/redo history for all playlists */
2926 for (PlaylistList::iterator x = playlists.begin(); x != playlists.end(); ++x) {
2927 (*x)->drop_all_states ();
2930 /* step 3: find all un-referenced sources */
2935 for (SourceList::iterator i = sources.begin(); i != sources.end(); ) {
2937 SourceList::iterator tmp;
2942 /* only remove files that are not in use and have some size
2943 to them. otherwise we remove the current "nascent"
2947 if ((*i).second->use_cnt() == 0 && (*i).second->length() > 0) {
2948 dead_sources.push_back (i->second);
2950 /* remove this source from our own list to avoid us
2951 adding it to the list of all sources below
2960 /* Step 4: get rid of all regions in the region list that use any dead sources
2961 in case the sources themselves don't go away (they might be referenced in
2965 for (vector<Source*>::iterator i = dead_sources.begin(); i != dead_sources.end();++i) {
2967 for (AudioRegionList::iterator r = audio_regions.begin(); r != audio_regions.end(); ) {
2968 AudioRegionList::iterator tmp;
2976 for (uint32_t n = 0; n < ar->n_channels(); ++n) {
2977 if (&ar->source (n) == (*i)) {
2978 /* this region is dead */
2987 /* build a list of all the possible sound directories for the session */
2989 for (i = session_dirs.begin(); i != session_dirs.end(); ) {
2994 sound_path += (*i).path;
2995 sound_path += sound_dir_name;
2997 if (nexti != session_dirs.end()) {
3004 /* now do the same thing for the files that ended up in the sounds dir(s)
3005 but are not referenced as sources in any snapshot.
3008 soundfiles = scanner (sound_path, accept_all_non_peak_files, (void *) 0, false, true);
3010 if (soundfiles == 0) {
3014 /* find all sources, but don't use this snapshot because the
3015 state file on disk still references sources we may have already
3019 find_all_sources_across_snapshots (all_sources, true);
3021 /* add our current source list
3024 for (SourceList::iterator i = sources.begin(); i != sources.end(); ++i) {
3026 ExternalSource* sfs;
3028 if ((fs = dynamic_cast<FileSource*> ((*i).second)) != 0) {
3029 all_sources.insert (fs->path());
3030 } else if ((sfs = dynamic_cast<ExternalSource*> ((*i).second)) != 0) {
3031 all_sources.insert (sfs->path());
3035 for (vector<string*>::iterator x = soundfiles->begin(); x != soundfiles->end(); ++x) {
3040 for (set<string>::iterator i = all_sources.begin(); i != all_sources.end(); ++i) {
3050 unused.push_back (spath);
3054 /* now try to move all unused files into the "dead_sounds" directory(ies) */
3056 for (vector<string>::iterator x = unused.begin(); x != unused.end(); ++x) {
3057 struct stat statbuf;
3059 rep.paths.push_back (*x);
3060 if (stat ((*x).c_str(), &statbuf) == 0) {
3061 rep.space += statbuf.st_size;
3066 /* don't move the file across filesystems, just
3067 stick it in the `dead_sound_dir_name' directory
3068 on whichever filesystem it was already on.
3071 newpath = PBD::dirname (*x);
3072 newpath = PBD::dirname (newpath);
3075 newpath += dead_sound_dir_name;
3077 newpath += PBD::basename ((*x));
3079 if (access (newpath.c_str(), F_OK) == 0) {
3081 /* the new path already exists, try versioning */
3083 char buf[PATH_MAX+1];
3087 snprintf (buf, sizeof (buf), "%s.%d", newpath.c_str(), version);
3090 while (access (newpath_v.c_str(), F_OK) == 0 && version < 999) {
3091 snprintf (buf, sizeof (buf), "%s.%d", newpath.c_str(), ++version);
3095 if (version == 999) {
3096 error << string_compose (_("there are already 1000 files with names like %1; versioning discontinued"),
3100 newpath = newpath_v;
3105 /* it doesn't exist, or we can't read it or something */
3109 if (::rename ((*x).c_str(), newpath.c_str()) != 0) {
3110 error << string_compose (_("cannot rename audio file source from %1 to %2 (%3)"),
3111 (*x), newpath, strerror (errno))
3117 /* see if there an easy to find peakfile for this file, and remove it.
3120 string peakpath = (*x).substr (0, (*x).find_last_of ('.'));
3121 peakpath += ".peak";
3123 if (access (peakpath.c_str(), W_OK) == 0) {
3124 if (::unlink (peakpath.c_str()) != 0) {
3125 error << string_compose (_("cannot remove peakfile %1 for %2 (%3)"),
3126 peakpath, _path, strerror (errno))
3128 /* try to back out */
3129 rename (newpath.c_str(), _path.c_str());
3138 /* dump the history list */
3142 /* save state so we don't end up a session file
3143 referring to non-existent sources.
3149 _state_of_the_state = (StateOfTheState) (_state_of_the_state & ~InCleanup);
3154 Session::cleanup_trash_sources (Session::cleanup_report& rep)
3156 vector<space_and_path>::iterator i;
3157 string dead_sound_dir;
3158 struct dirent* dentry;
3159 struct stat statbuf;
3165 for (i = session_dirs.begin(); i != session_dirs.end(); ++i) {
3167 dead_sound_dir = (*i).path;
3168 dead_sound_dir += dead_sound_dir_name;
3170 if ((dead = opendir (dead_sound_dir.c_str())) == 0) {
3174 while ((dentry = readdir (dead)) != 0) {
3176 /* avoid '.' and '..' */
3178 if ((dentry->d_name[0] == '.' && dentry->d_name[1] == '\0') ||
3179 (dentry->d_name[2] == '\0' && dentry->d_name[0] == '.' && dentry->d_name[1] == '.')) {
3185 fullpath = dead_sound_dir;
3187 fullpath += dentry->d_name;
3189 if (stat (fullpath.c_str(), &statbuf)) {
3193 if (!S_ISREG (statbuf.st_mode)) {
3197 if (unlink (fullpath.c_str())) {
3198 error << string_compose (_("cannot remove dead sound file %1 (%2)"),
3199 fullpath, strerror (errno))
3203 rep.paths.push_back (dentry->d_name);
3204 rep.space += statbuf.st_size;
3215 Session::set_dirty ()
3217 bool was_dirty = dirty();
3219 _state_of_the_state = StateOfTheState (_state_of_the_state | Dirty);
3222 DirtyChanged(); /* EMIT SIGNAL */
3228 Session::set_clean ()
3230 bool was_dirty = dirty();
3232 _state_of_the_state = Clean;
3235 DirtyChanged(); /* EMIT SIGNAL */