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/sndfilesource.h>
66 #include <ardour/sndfile_helpers.h>
67 #include <ardour/auditioner.h>
68 #include <ardour/export.h>
69 #include <ardour/redirect.h>
70 #include <ardour/send.h>
71 #include <ardour/insert.h>
72 #include <ardour/connection.h>
73 #include <ardour/slave.h>
74 #include <ardour/tempo.h>
75 #include <ardour/audio_track.h>
76 #include <ardour/cycle_timer.h>
77 #include <ardour/utils.h>
78 #include <ardour/named_selection.h>
79 #include <ardour/version.h>
80 #include <ardour/location.h>
81 #include <ardour/audioregion.h>
82 #include <ardour/crossfade.h>
88 using namespace ARDOUR;
91 Session::first_stage_init (string fullpath, string snapshot_name)
93 if (fullpath.length() == 0) {
94 throw failed_constructor();
98 if (!realpath(fullpath.c_str(), buf) && (errno != ENOENT)) {
99 error << string_compose(_("Could not use path %1 (%s)"), buf, strerror(errno)) << endmsg;
100 throw failed_constructor();
104 if (_path[_path.length()-1] != '/') {
108 /* these two are just provisional settings. set_state()
109 will likely override them.
112 _name = _current_snapshot_name = snapshot_name;
113 setup_raid_path (_path);
115 _current_frame_rate = _engine.frame_rate ();
116 _tempo_map = new TempoMap (_current_frame_rate);
117 _tempo_map->StateChanged.connect (mem_fun (*this, &Session::tempo_map_changed));
119 atomic_set (&processing_prohibited, 0);
122 _transport_speed = 0;
123 _last_transport_speed = 0;
124 transport_sub_state = 0;
125 _transport_frame = 0;
127 end_location = new Location (0, 0, _("end"), Location::Flags ((Location::IsMark|Location::IsEnd)));
128 _end_location_is_free = true;
129 atomic_set (&_record_status, Disabled);
134 seamless_loop = false;
135 loop_changing = false;
137 crossfades_active = false;
140 _last_roll_location = 0;
141 _last_record_location = 0;
142 pending_locate_frame = 0;
143 pending_locate_roll = false;
144 pending_locate_flush = false;
145 dstream_buffer_size = 0;
147 state_was_pending = false;
149 outbound_mtc_smpte_frame = 0;
150 next_quarter_frame_to_send = -1;
151 current_block_size = 0;
152 _solo_latched = true;
153 _solo_model = InverseMute;
154 solo_update_disabled = false;
155 currently_soloing = false;
156 _worst_output_latency = 0;
157 _worst_input_latency = 0;
158 _worst_track_latency = 0;
159 _state_of_the_state = StateOfTheState(CannotSave|InitialConnecting|Loading);
162 butler_mixdown_buffer = 0;
163 butler_gain_buffer = 0;
166 midi_feedback = false;
169 post_transport_work = PostTransportWork (0);
170 atomic_set (&butler_should_do_transport_work, 0);
171 atomic_set (&butler_active, 0);
172 atomic_set (&_playback_load, 100);
173 atomic_set (&_capture_load, 100);
174 atomic_set (&_playback_load_min, 100);
175 atomic_set (&_capture_load_min, 100);
176 pending_audition_region = 0;
178 pending_edit_mode = _edit_mode;
182 input_auto_connect = AutoConnectOption (0);
183 output_auto_connect = AutoConnectOption (0);
184 _have_captured = false;
185 waiting_to_start = false;
187 _gain_automation_buffer = 0;
188 _pan_automation_buffer = 0;
190 pending_abort = false;
191 layer_model = MoveAddHigher;
192 xfade_model = ShortCrossfade;
194 /* allocate conversion buffers */
195 _conversion_buffers[ButlerContext] = new char[DiskStream::disk_io_frames() * 4];
196 _conversion_buffers[TransportContext] = new char[DiskStream::disk_io_frames() * 4];
198 /* default short fade = 15ms */
200 Crossfade::set_short_xfade_length ((jack_nframes_t) floor ((15.0 * frame_rate()) / 1000.0));
202 last_mmc_step.tv_sec = 0;
203 last_mmc_step.tv_usec = 0;
206 preroll.type = AnyTime::Frames;
208 postroll.type = AnyTime::Frames;
211 /* click sounds are unset by default, which causes us to internal
212 waveforms for clicks.
217 click_requested = false;
219 click_emphasis_data = 0;
221 click_emphasis_length = 0;
223 process_function = &Session::process_with_events;
227 _smpte_offset_negative = true;
228 last_smpte_valid = false;
230 last_rr_session_dir = session_dirs.begin();
231 refresh_disk_space ();
233 // set_default_fade (0.2, 5.0); /* steepness, millisecs */
235 /* default configuration */
237 do_not_record_plugins = false;
238 over_length_short = 2;
239 over_length_long = 10;
240 send_midi_timecode = false;
241 send_midi_machine_control = false;
242 shuttle_speed_factor = 1.0;
243 shuttle_speed_threshold = 5;
245 _meter_hold = 100; // XXX unknown units: number of calls to meter::set()
246 _meter_falloff = 1.5f; // XXX unknown units: refresh_rate
252 average_slave_delta = 1800;
253 have_first_delta_accumulator = false;
254 delta_accumulator_cnt = 0;
255 slave_state = Stopped;
257 /* default SMPTE type is 30 FPS, non-drop */
259 set_smpte_type (30.0, false);
261 _engine.GraphReordered.connect (mem_fun (*this, &Session::graph_reordered));
263 /* These are all static "per-class" signals */
265 Region::CheckNewRegion.connect (mem_fun (*this, &Session::add_region));
266 Source::SourceCreated.connect (mem_fun (*this, &Session::add_source));
267 Playlist::PlaylistCreated.connect (mem_fun (*this, &Session::add_playlist));
268 Redirect::RedirectCreated.connect (mem_fun (*this, &Session::add_redirect));
269 DiskStream::DiskStreamCreated.connect (mem_fun (*this, &Session::add_diskstream));
270 NamedSelection::NamedSelectionCreated.connect (mem_fun (*this, &Session::add_named_selection));
272 IO::MoreOutputs.connect (mem_fun (*this, &Session::ensure_passthru_buffers));
274 /* stop IO objects from doing stuff until we're ready for them */
276 IO::disable_panners ();
277 IO::disable_ports ();
278 IO::disable_connecting ();
282 Session::second_stage_init (bool new_session)
284 SndFileSource::set_peak_dir (peak_dir());
287 if (load_state (_current_snapshot_name)) {
290 remove_empty_sounds ();
293 if (start_butler_thread()) {
297 if (start_midi_thread ()) {
301 if (init_feedback ()) {
306 if (set_state (*state_tree->root())) {
311 /* we can't save till after ::when_engine_running() is called,
312 because otherwise we save state with no connections made.
313 therefore, we reset _state_of_the_state because ::set_state()
314 will have cleared it.
316 we also have to include Loading so that any events that get
317 generated between here and the end of ::when_engine_running()
318 will be processed directly rather than queued.
321 _state_of_the_state = StateOfTheState (_state_of_the_state|CannotSave|Loading);
323 // set_auto_input (true);
324 _locations.changed.connect (mem_fun (this, &Session::locations_changed));
325 _locations.added.connect (mem_fun (this, &Session::locations_added));
326 setup_click_sounds (0);
327 setup_midi_control ();
329 /* Pay attention ... */
331 _engine.Halted.connect (mem_fun (*this, &Session::engine_halted));
332 _engine.Xrun.connect (mem_fun (*this, &Session::xrun_recovery));
334 if (_engine.running()) {
335 when_engine_running();
337 first_time_running = _engine.Running.connect (mem_fun (*this, &Session::when_engine_running));
340 send_full_time_code ();
341 _engine.transport_locate (0);
342 deliver_mmc (MIDI::MachineControl::cmdMmcReset, 0);
343 deliver_mmc (MIDI::MachineControl::cmdLocate, 0);
344 send_all_midi_feedback();
347 _end_location_is_free = true;
349 _end_location_is_free = false;
356 Session::raid_path () const
360 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
365 return path.substr (0, path.length() - 1); // drop final colon
369 Session::set_raid_path (string path)
371 /* public-access to setup_raid_path() */
373 setup_raid_path (path);
377 Session::setup_raid_path (string path)
379 string::size_type colon;
383 string::size_type len = path.length();
388 if (path.length() == 0) {
392 session_dirs.clear ();
394 for (string::size_type n = 0; n < len; ++n) {
395 if (path[n] == ':') {
402 /* no multiple search path, just one directory (common case) */
406 session_dirs.push_back (sp);
408 FileSource::set_search_path (path + sound_dir_name);
415 while ((colon = remaining.find_first_of (':')) != string::npos) {
418 sp.path = remaining.substr (0, colon);
421 if (fspath[fspath.length()-1] != '/') {
424 fspath += sound_dir_name;
427 session_dirs.push_back (sp);
429 remaining = remaining.substr (colon+1);
432 if (remaining.length()) {
438 if (fspath[fspath.length()-1] != '/') {
441 fspath += sound_dir_name;
443 session_dirs.push_back (sp);
446 /* set the FileSource search path */
448 FileSource::set_search_path (fspath);
450 /* reset the round-robin soundfile path thingie */
452 last_rr_session_dir = session_dirs.begin();
456 Session::create (bool& new_session, string* mix_template, jack_nframes_t initial_length)
460 if (mkdir (_path.c_str(), 0755) < 0) {
461 if (errno == EEXIST) {
464 error << string_compose(_("Session: cannot create session dir \"%1\" (%2)"), _path, strerror (errno)) << endmsg;
473 if (mkdir (dir.c_str(), 0755) < 0) {
474 if (errno != EEXIST) {
475 error << string_compose(_("Session: cannot create session peakfile dir \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
482 if (mkdir (dir.c_str(), 0755) < 0) {
483 if (errno != EEXIST) {
484 error << string_compose(_("Session: cannot create session sounds dir \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
489 dir = dead_sound_dir ();
491 if (mkdir (dir.c_str(), 0755) < 0) {
492 if (errno != EEXIST) {
493 error << string_compose(_("Session: cannot create session dead sounds dir \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
498 dir = automation_dir ();
500 if (mkdir (dir.c_str(), 0755) < 0) {
501 if (errno != EEXIST) {
502 error << string_compose(_("Session: cannot create session automation dir \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
508 /* check new_session so we don't overwrite an existing one */
512 std::string in_path = *mix_template;
514 ifstream in(in_path.c_str());
517 string out_path = _path;
519 out_path += _statefile_suffix;
521 ofstream out(out_path.c_str());
526 // okay, session is set up. Treat like normal saved
527 // session from now on.
533 error << string_compose (_("Could not open %1 for writing mix template"), out_path)
539 error << string_compose (_("Could not open mix template %1 for reading"), in_path)
546 warning << _("Session already exists. Not overwriting") << endmsg;
553 /* set an initial end point */
555 end_location->set_end (initial_length);
556 _locations.add (end_location);
558 _state_of_the_state = Clean;
560 if (save_state (_current_snapshot_name)) {
569 Session::load_diskstreams (const XMLNode& node)
572 XMLNodeConstIterator citer;
574 clist = node.children();
576 for (citer = clist.begin(); citer != clist.end(); ++citer) {
581 dstream = new DiskStream (*this, **citer);
582 /* added automatically by DiskStreamCreated handler */
585 catch (failed_constructor& err) {
586 error << _("Session: could not load diskstream via XML state") << endmsg;
595 Session::remove_pending_capture_state ()
600 xml_path += _current_snapshot_name;
601 xml_path += _pending_suffix;
603 unlink (xml_path.c_str());
607 Session::save_state (string snapshot_name, bool pending)
613 if (_state_of_the_state & CannotSave) {
617 tree.set_root (&get_state());
619 if (snapshot_name.empty()) {
620 snapshot_name = _current_snapshot_name;
626 xml_path += snapshot_name;
627 xml_path += _statefile_suffix;
631 // Make backup of state file
633 if ((access (xml_path.c_str(), F_OK) == 0) &&
634 (rename(xml_path.c_str(), bak_path.c_str()))) {
635 error << _("could not backup old state file, current state not saved.") << endmsg;
642 xml_path += snapshot_name;
643 xml_path += _pending_suffix;
647 if (!tree.write (xml_path)) {
648 error << string_compose (_("state could not be saved to %1"), xml_path) << endmsg;
650 /* don't leave a corrupt file lying around if it is
654 if (unlink (xml_path.c_str())) {
655 error << string_compose (_("could not remove corrupt state file %1"), xml_path) << endmsg;
658 if (rename (bak_path.c_str(), xml_path.c_str())) {
659 error << string_compose (_("could not restore state file from backup %1"), bak_path) << endmsg;
669 bool was_dirty = dirty();
671 _state_of_the_state = StateOfTheState (_state_of_the_state & ~Dirty);
674 DirtyChanged (); /* EMIT SIGNAL */
677 StateSaved (snapshot_name); /* EMIT SIGNAL */
684 Session::restore_state (string snapshot_name)
686 if (load_state (snapshot_name) == 0) {
687 set_state (*state_tree->root());
694 Session::load_state (string snapshot_name)
703 state_was_pending = false;
705 /* check for leftover pending state from a crashed capture attempt */
708 xmlpath += snapshot_name;
709 xmlpath += _pending_suffix;
711 if (!access (xmlpath.c_str(), F_OK)) {
713 /* there is pending state from a crashed capture attempt */
715 if (AskAboutPendingState()) {
716 state_was_pending = true;
720 if (!state_was_pending) {
723 xmlpath += snapshot_name;
724 xmlpath += _statefile_suffix;
727 if (access (xmlpath.c_str(), F_OK)) {
728 error << string_compose(_("%1: session state information file \"%2\" doesn't exist!"), _name, xmlpath) << endmsg;
732 state_tree = new XMLTree;
736 if (state_tree->read (xmlpath)) {
739 error << string_compose(_("Could not understand ardour file %1"), xmlpath) << endmsg;
748 Session::load_options (const XMLNode& node)
752 bool have_fade_msecs = false;
753 bool have_fade_steepness = false;
754 float fade_msecs = 0;
755 float fade_steepness = 0;
756 SlaveSource slave_src = None;
758 LocaleGuard lg (X_("POSIX"));
760 if ((child = find_named_node (node, "input-auto-connect")) != 0) {
761 if ((prop = child->property ("val")) != 0) {
762 sscanf (prop->value().c_str(), "%x", &x);
763 input_auto_connect = AutoConnectOption (x);
767 if ((child = find_named_node (node, "output-auto-connect")) != 0) {
768 if ((prop = child->property ("val")) != 0) {
769 sscanf (prop->value().c_str(), "%x", &x);
770 output_auto_connect = AutoConnectOption (x);
774 if ((child = find_named_node (node, "slave")) != 0) {
775 if ((prop = child->property ("type")) != 0) {
776 if (prop->value() == "none") {
778 } else if (prop->value() == "mtc") {
780 } else if (prop->value() == "jack") {
783 set_slave_source (slave_src, 0);
787 /* we cannot set edit mode if we are loading a session,
788 because it might destroy the playlist's positioning
791 if ((child = find_named_node (node, "edit-mode")) != 0) {
792 if ((prop = child->property ("val")) != 0) {
793 if (prop->value() == "slide") {
794 pending_edit_mode = Slide;
795 } else if (prop->value() == "splice") {
796 pending_edit_mode = Splice;
801 if ((child = find_named_node (node, "send-midi-timecode")) != 0) {
802 if ((prop = child->property ("val")) != 0) {
803 bool x = (prop->value() == "yes");
804 send_mtc = !x; /* force change in value */
808 if ((child = find_named_node (node, "send-midi-machine-control")) != 0) {
809 if ((prop = child->property ("val")) != 0) {
810 bool x = (prop->value() == "yes");
811 send_mmc = !x; /* force change in value */
812 set_send_mmc (prop->value() == "yes");
815 if ((child = find_named_node (node, "max-level")) != 0) {
816 if ((prop = child->property ("val")) != 0) {
817 max_level = atoi (prop->value().c_str());
820 if ((child = find_named_node (node, "min-level")) != 0) {
821 if ((prop = child->property ("val")) != 0) {
822 min_level = atoi (prop->value().c_str());
825 if ((child = find_named_node (node, "meter-hold")) != 0) {
826 if ((prop = child->property ("val")) != 0) {
827 _meter_hold = atof (prop->value().c_str());
830 if ((child = find_named_node (node, "meter-falloff")) != 0) {
831 if ((prop = child->property ("val")) != 0) {
832 _meter_falloff = atof (prop->value().c_str());
835 if ((child = find_named_node (node, "long-over-length")) != 0) {
836 if ((prop = child->property ("val")) != 0) {
837 over_length_long = atoi (prop->value().c_str());
840 if ((child = find_named_node (node, "short-over-length")) != 0) {
841 if ((prop = child->property ("val")) != 0) {
842 over_length_short = atoi (prop->value().c_str());
845 if ((child = find_named_node (node, "shuttle-speed-factor")) != 0) {
846 if ((prop = child->property ("val")) != 0) {
847 shuttle_speed_factor = atof (prop->value().c_str());
850 if ((child = find_named_node (node, "shuttle-speed-threshold")) != 0) {
851 if ((prop = child->property ("val")) != 0) {
852 shuttle_speed_threshold = atof (prop->value().c_str());
855 if ((child = find_named_node (node, "rf-speed")) != 0) {
856 if ((prop = child->property ("val")) != 0) {
857 rf_speed = atof (prop->value().c_str());
860 if ((child = find_named_node (node, "smpte-frames-per-second")) != 0) {
861 if ((prop = child->property ("val")) != 0) {
862 set_smpte_type( atof (prop->value().c_str()), smpte_drop_frames );
865 if ((child = find_named_node (node, "smpte-drop-frames")) != 0) {
866 if ((prop = child->property ("val")) != 0) {
867 set_smpte_type( smpte_frames_per_second, (prop->value() == "yes") );
870 if ((child = find_named_node (node, "smpte-offset")) != 0) {
871 if ((prop = child->property ("val")) != 0) {
872 set_smpte_offset( atoi (prop->value().c_str()) );
875 if ((child = find_named_node (node, "smpte-offset-negative")) != 0) {
876 if ((prop = child->property ("val")) != 0) {
877 set_smpte_offset_negative( (prop->value() == "yes") );
880 if ((child = find_named_node (node, "click-sound")) != 0) {
881 if ((prop = child->property ("val")) != 0) {
882 click_sound = prop->value();
885 if ((child = find_named_node (node, "click-emphasis-sound")) != 0) {
886 if ((prop = child->property ("val")) != 0) {
887 click_emphasis_sound = prop->value();
891 if ((child = find_named_node (node, "solo-model")) != 0) {
892 if ((prop = child->property ("val")) != 0) {
893 if (prop->value() == "SoloBus")
894 _solo_model = SoloBus;
896 _solo_model = InverseMute;
900 /* BOOLEAN OPTIONS */
902 if ((child = find_named_node (node, "auto-play")) != 0) {
903 if ((prop = child->property ("val")) != 0) {
904 set_auto_play (prop->value() == "yes");
907 if ((child = find_named_node (node, "auto-input")) != 0) {
908 if ((prop = child->property ("val")) != 0) {
909 set_auto_input (prop->value() == "yes");
912 if ((child = find_named_node (node, "seamless-loop")) != 0) {
913 if ((prop = child->property ("val")) != 0) {
914 set_seamless_loop (prop->value() == "yes");
917 if ((child = find_named_node (node, "punch-in")) != 0) {
918 if ((prop = child->property ("val")) != 0) {
919 set_punch_in (prop->value() == "yes");
922 if ((child = find_named_node (node, "punch-out")) != 0) {
923 if ((prop = child->property ("val")) != 0) {
924 set_punch_out (prop->value() == "yes");
927 if ((child = find_named_node (node, "auto-return")) != 0) {
928 if ((prop = child->property ("val")) != 0) {
929 set_auto_return (prop->value() == "yes");
932 if ((child = find_named_node (node, "send-mtc")) != 0) {
933 if ((prop = child->property ("val")) != 0) {
934 set_send_mtc (prop->value() == "yes");
937 if ((child = find_named_node (node, "mmc-control")) != 0) {
938 if ((prop = child->property ("val")) != 0) {
939 set_mmc_control (prop->value() == "yes");
942 if ((child = find_named_node (node, "midi-control")) != 0) {
943 if ((prop = child->property ("val")) != 0) {
944 set_midi_control (prop->value() == "yes");
947 if ((child = find_named_node (node, "midi-feedback")) != 0) {
948 if ((prop = child->property ("val")) != 0) {
949 set_midi_feedback (prop->value() == "yes");
952 // Legacy support for <recording-plugins>
953 if ((child = find_named_node (node, "recording-plugins")) != 0) {
954 if ((prop = child->property ("val")) != 0) {
955 set_do_not_record_plugins (prop->value() == "no");
958 if ((child = find_named_node (node, "do-not-record-plugins")) != 0) {
959 if ((prop = child->property ("val")) != 0) {
960 set_do_not_record_plugins (prop->value() == "yes");
963 if ((child = find_named_node (node, "crossfades-active")) != 0) {
964 if ((prop = child->property ("val")) != 0) {
965 set_crossfades_active (prop->value() == "yes");
968 if ((child = find_named_node (node, "audible-click")) != 0) {
969 if ((prop = child->property ("val")) != 0) {
970 set_clicking (prop->value() == "yes");
974 if ((child = find_named_node (node, "layer-model")) != 0) {
975 if ((prop = child->property ("val")) != 0) {
976 if (prop->value() == X_("LaterHigher")) {
977 set_layer_model (LaterHigher);
978 } else if (prop->value() == X_("AddHigher")) {
979 set_layer_model (AddHigher);
981 set_layer_model (MoveAddHigher);
986 if ((child = find_named_node (node, "xfade-model")) != 0) {
987 if ((prop = child->property ("val")) != 0) {
988 if (prop->value() == X_("Short")) {
989 set_xfade_model (ShortCrossfade);
991 set_xfade_model (FullCrossfade);
996 if ((child = find_named_node (node, "short-xfade-length")) != 0) {
997 if ((prop = child->property ("val")) != 0) {
998 /* value is stored as a fractional seconds */
999 float secs = atof (prop->value().c_str());
1000 Crossfade::set_short_xfade_length ((jack_nframes_t) floor (secs * frame_rate()));
1004 if ((child = find_named_node (node, "full-xfades-unmuted")) != 0) {
1005 if ((prop = child->property ("val")) != 0) {
1006 crossfades_active = (prop->value() == "yes");
1012 if ((child = find_named_node (node, "default-fade-steepness")) != 0) {
1013 if ((prop = child->property ("val")) != 0) {
1014 fade_steepness = atof (prop->value().c_str());
1015 have_fade_steepness = true;
1018 if ((child = find_named_node (node, "default-fade-msec")) != 0) {
1019 if ((prop = child->property ("val")) != 0) {
1020 fade_msecs = atof (prop->value().c_str());
1021 have_fade_msecs = true;
1025 if (have_fade_steepness || have_fade_msecs) {
1026 // set_default_fade (fade_steepness, fade_msecs);
1033 Session::get_options () const
1038 LocaleGuard lg (X_("POSIX"));
1040 opthead = new XMLNode ("Options");
1042 SlaveSource src = slave_source ();
1046 src_string = "none";
1052 src_string = "jack";
1055 child = opthead->add_child ("slave");
1056 child->add_property ("type", src_string);
1058 child = opthead->add_child ("send-midi-timecode");
1059 child->add_property ("val", send_midi_timecode?"yes":"no");
1061 child = opthead->add_child ("send-midi-machine-control");
1062 child->add_property ("val", send_midi_machine_control?"yes":"no");
1064 snprintf (buf, sizeof(buf)-1, "%x", (int) input_auto_connect);
1065 child = opthead->add_child ("input-auto-connect");
1066 child->add_property ("val", buf);
1068 snprintf (buf, sizeof(buf)-1, "%x", (int) output_auto_connect);
1069 child = opthead->add_child ("output-auto-connect");
1070 child->add_property ("val", buf);
1072 snprintf (buf, sizeof(buf)-1, "%d", max_level);
1073 child = opthead->add_child ("max-level");
1074 child->add_property ("val", buf);
1076 snprintf (buf, sizeof(buf)-1, "%d", min_level);
1077 child = opthead->add_child ("min-level");
1078 child->add_property ("val", buf);
1080 snprintf (buf, sizeof(buf)-1, "%f", _meter_hold);
1081 child = opthead->add_child ("meter-hold");
1082 child->add_property ("val", buf);
1084 snprintf (buf, sizeof(buf)-1, "%f", _meter_falloff);
1085 child = opthead->add_child ("meter-falloff");
1086 child->add_property ("val", buf);
1088 snprintf (buf, sizeof(buf)-1, "%u", over_length_long);
1089 child = opthead->add_child ("long-over-length");
1090 child->add_property ("val", buf);
1092 snprintf (buf, sizeof(buf)-1, "%u", over_length_short);
1093 child = opthead->add_child ("short-over-length");
1094 child->add_property ("val", buf);
1096 snprintf (buf, sizeof(buf)-1, "%f", shuttle_speed_factor);
1097 child = opthead->add_child ("shuttle-speed-factor");
1098 child->add_property ("val", buf);
1100 snprintf (buf, sizeof(buf)-1, "%f", shuttle_speed_threshold);
1101 child = opthead->add_child ("shuttle-speed-threshold");
1102 child->add_property ("val", buf);
1104 snprintf (buf, sizeof(buf)-1, "%f", rf_speed);
1105 child = opthead->add_child ("rf-speed");
1106 child->add_property ("val", buf);
1108 snprintf (buf, sizeof(buf)-1, "%.2f", smpte_frames_per_second);
1109 child = opthead->add_child ("smpte-frames-per-second");
1110 child->add_property ("val", buf);
1112 child = opthead->add_child ("smpte-drop-frames");
1113 child->add_property ("val", smpte_drop_frames ? "yes" : "no");
1115 snprintf (buf, sizeof(buf)-1, "%u", smpte_offset ());
1116 child = opthead->add_child ("smpte-offset");
1117 child->add_property ("val", buf);
1119 child = opthead->add_child ("smpte-offset-negative");
1120 child->add_property ("val", smpte_offset_negative () ? "yes" : "no");
1122 child = opthead->add_child ("edit-mode");
1123 switch (_edit_mode) {
1125 child->add_property ("val", "splice");
1129 child->add_property ("val", "slide");
1133 child = opthead->add_child ("auto-play");
1134 child->add_property ("val", get_auto_play () ? "yes" : "no");
1135 child = opthead->add_child ("auto-input");
1136 child->add_property ("val", get_auto_input () ? "yes" : "no");
1137 child = opthead->add_child ("seamless-loop");
1138 child->add_property ("val", get_seamless_loop () ? "yes" : "no");
1139 child = opthead->add_child ("punch-in");
1140 child->add_property ("val", get_punch_in () ? "yes" : "no");
1141 child = opthead->add_child ("punch-out");
1142 child->add_property ("val", get_punch_out () ? "yes" : "no");
1143 child = opthead->add_child ("all-safe");
1144 child->add_property ("val", get_all_safe () ? "yes" : "no");
1145 child = opthead->add_child ("auto-return");
1146 child->add_property ("val", get_auto_return () ? "yes" : "no");
1147 child = opthead->add_child ("mmc-control");
1148 child->add_property ("val", get_mmc_control () ? "yes" : "no");
1149 child = opthead->add_child ("midi-control");
1150 child->add_property ("val", get_midi_control () ? "yes" : "no");
1151 child = opthead->add_child ("midi-feedback");
1152 child->add_property ("val", get_midi_feedback () ? "yes" : "no");
1153 child = opthead->add_child ("do-not-record-plugins");
1154 child->add_property ("val", get_do_not_record_plugins () ? "yes" : "no");
1155 child = opthead->add_child ("auto-crossfade");
1156 child->add_property ("val", get_crossfades_active () ? "yes" : "no");
1157 child = opthead->add_child ("audible-click");
1158 child->add_property ("val", get_clicking () ? "yes" : "no");
1160 if (click_sound.length()) {
1161 child = opthead->add_child ("click-sound");
1162 child->add_property ("val", click_sound);
1165 if (click_emphasis_sound.length()) {
1166 child = opthead->add_child ("click-emphasis-sound");
1167 child->add_property ("val", click_emphasis_sound);
1170 child = opthead->add_child ("solo-model");
1171 child->add_property ("val", _solo_model == SoloBus ? "SoloBus" : "InverseMute");
1173 child = opthead->add_child ("layer-model");
1174 switch (layer_model) {
1176 child->add_property ("val", X_("LaterHigher"));
1179 child->add_property ("val", X_("MoveAddHigher"));
1182 child->add_property ("val", X_("AddHigher"));
1186 child = opthead->add_child ("xfade-model");
1187 switch (xfade_model) {
1189 child->add_property ("val", X_("Full"));
1191 case ShortCrossfade:
1192 child->add_property ("val", X_("Short"));
1195 child = opthead->add_child ("short-xfade-length");
1196 /* store as fractions of a second */
1197 snprintf (buf, sizeof(buf)-1, "%f",
1198 (float) Crossfade::short_xfade_length() / frame_rate());
1199 child->add_property ("val", buf);
1201 child = opthead->add_child ("full-xfades-unmuted");
1202 child->add_property ("val", crossfades_active ? "yes" : "no");
1208 Session::get_state()
1214 Session::get_template()
1216 /* if we don't disable rec-enable, diskstreams
1217 will believe they need to store their capture
1218 sources in their state node.
1223 return state(false);
1227 Session::state(bool full_state)
1229 XMLNode* node = new XMLNode("Session");
1232 // store libardour version, just in case
1234 snprintf(buf, sizeof(buf)-1, "%d.%d.%d",
1235 libardour_major_version, libardour_minor_version, libardour_micro_version);
1236 node->add_property("version", string(buf));
1238 /* store configuration settings */
1242 /* store the name */
1243 node->add_property ("name", _name);
1245 if (session_dirs.size() > 1) {
1249 vector<space_and_path>::iterator i = session_dirs.begin();
1250 vector<space_and_path>::iterator next;
1252 ++i; /* skip the first one */
1256 while (i != session_dirs.end()) {
1260 if (next != session_dirs.end()) {
1270 child = node->add_child ("Path");
1271 child->add_content (p);
1275 node->add_child_nocopy (get_options());
1277 child = node->add_child ("Sources");
1280 LockMonitor sl (source_lock, __LINE__, __FILE__);
1282 for (SourceList::iterator siter = sources.begin(); siter != sources.end(); ++siter) {
1284 /* Don't save information about FileSources that are empty */
1288 if ((fs = dynamic_cast<FileSource*> ((*siter).second)) != 0) {
1289 if (fs->length() == 0) {
1294 child->add_child_nocopy ((*siter).second->get_state());
1298 child = node->add_child ("Regions");
1301 LockMonitor rl (region_lock, __LINE__, __FILE__);
1303 for (AudioRegionList::const_iterator i = audio_regions.begin(); i != audio_regions.end(); ++i) {
1305 /* only store regions not attached to playlists */
1307 if ((*i).second->playlist() == 0) {
1308 child->add_child_nocopy (i->second->state (true));
1313 child = node->add_child ("DiskStreams");
1316 RWLockMonitor dl (diskstream_lock, false, __LINE__, __FILE__);
1317 for (DiskStreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
1318 if (!(*i)->hidden()) {
1319 child->add_child_nocopy ((*i)->get_state());
1324 node->add_child_nocopy (_locations.get_state());
1326 child = node->add_child ("Connections");
1328 LockMonitor lm (connection_lock, __LINE__, __FILE__);
1329 for (ConnectionList::iterator i = _connections.begin(); i != _connections.end(); ++i) {
1330 if (!(*i)->system_dependent()) {
1331 child->add_child_nocopy ((*i)->get_state());
1336 child = node->add_child ("Routes");
1338 RWLockMonitor lm (route_lock, false, __LINE__, __FILE__);
1340 RoutePublicOrderSorter cmp;
1341 RouteList public_order(routes);
1342 public_order.sort (cmp);
1344 for (RouteList::iterator i = public_order.begin(); i != public_order.end(); ++i) {
1345 if (!(*i)->hidden()) {
1347 child->add_child_nocopy ((*i)->get_state());
1349 child->add_child_nocopy ((*i)->get_template());
1356 child = node->add_child ("EditGroups");
1357 for (list<RouteGroup *>::iterator i = edit_groups.begin(); i != edit_groups.end(); ++i) {
1358 child->add_child_nocopy ((*i)->get_state());
1361 child = node->add_child ("MixGroups");
1362 for (list<RouteGroup *>::iterator i = mix_groups.begin(); i != mix_groups.end(); ++i) {
1363 child->add_child_nocopy ((*i)->get_state());
1366 child = node->add_child ("Playlists");
1367 for (PlaylistList::iterator i = playlists.begin(); i != playlists.end(); ++i) {
1368 if (!(*i)->hidden()) {
1369 if (!(*i)->empty()) {
1371 child->add_child_nocopy ((*i)->get_state());
1373 child->add_child_nocopy ((*i)->get_template());
1379 child = node->add_child ("UnusedPlaylists");
1380 for (PlaylistList::iterator i = unused_playlists.begin(); i != unused_playlists.end(); ++i) {
1381 if (!(*i)->hidden()) {
1382 if (!(*i)->empty()) {
1384 child->add_child_nocopy ((*i)->get_state());
1386 child->add_child_nocopy ((*i)->get_template());
1394 child = node->add_child ("Click");
1395 child->add_child_nocopy (_click_io->state (full_state));
1399 child = node->add_child ("NamedSelections");
1400 for (NamedSelectionList::iterator i = named_selections.begin(); i != named_selections.end(); ++i) {
1402 child->add_child_nocopy ((*i)->get_state());
1407 node->add_child_nocopy (_tempo_map->get_state());
1410 node->add_child_copy (*_extra_xml);
1417 Session::set_state (const XMLNode& node)
1421 const XMLProperty* prop;
1424 _state_of_the_state = StateOfTheState (_state_of_the_state|CannotSave);
1426 if (node.name() != "Session"){
1427 fatal << _("programming error: Session: incorrect XML node sent to set_state()") << endmsg;
1431 StateManager::prohibit_save ();
1433 if ((prop = node.property ("name")) != 0) {
1434 _name = prop->value ();
1437 IO::disable_ports ();
1438 IO::disable_connecting ();
1440 /* Object loading order:
1457 if (use_config_midi_ports ()) {
1460 if ((child = find_named_node (node, "Path")) != 0) {
1461 /* XXX this XML content stuff horrible API design */
1462 string raid_path = _path + ':' + child->children().front()->content();
1463 setup_raid_path (raid_path);
1465 /* the path is already set */
1468 if ((child = find_named_node (node, "extra")) != 0) {
1469 _extra_xml = new XMLNode (*child);
1472 if ((child = find_named_node (node, "Options")) == 0) {
1473 error << _("Session: XML state has no options section") << endmsg;
1474 } else if (load_options (*child)) {
1477 if ((child = find_named_node (node, "Sources")) == 0) {
1478 error << _("Session: XML state has no sources section") << endmsg;
1480 } else if (load_sources (*child)) {
1484 if ((child = find_named_node (node, "Regions")) == 0) {
1485 error << _("Session: XML state has no Regions section") << endmsg;
1487 } else if (load_regions (*child)) {
1491 if ((child = find_named_node (node, "Playlists")) == 0) {
1492 error << _("Session: XML state has no playlists section") << endmsg;
1494 } else if (load_playlists (*child)) {
1498 if ((child = find_named_node (node, "UnusedPlaylists")) == 0) {
1500 } else if (load_unused_playlists (*child)) {
1504 if ((child = find_named_node (node, "NamedSelections")) != 0) {
1505 if (load_named_selections (*child)) {
1510 if ((child = find_named_node (node, "DiskStreams")) == 0) {
1511 error << _("Session: XML state has no diskstreams section") << endmsg;
1513 } else if (load_diskstreams (*child)) {
1517 if ((child = find_named_node (node, "Connections")) == 0) {
1518 error << _("Session: XML state has no connections section") << endmsg;
1520 } else if (load_connections (*child)) {
1524 if ((child = find_named_node (node, "Locations")) == 0) {
1525 error << _("Session: XML state has no locations section") << endmsg;
1527 } else if (_locations.set_state (*child)) {
1533 if ((location = _locations.auto_loop_location()) != 0) {
1534 set_auto_loop_location (location);
1537 if ((location = _locations.auto_punch_location()) != 0) {
1538 set_auto_punch_location (location);
1541 if ((location = _locations.end_location()) == 0) {
1542 _locations.add (end_location);
1544 end_location = location;
1547 _locations.save_state (_("initial state"));
1549 if ((child = find_named_node (node, "EditGroups")) == 0) {
1550 error << _("Session: XML state has no edit groups section") << endmsg;
1552 } else if (load_edit_groups (*child)) {
1556 if ((child = find_named_node (node, "MixGroups")) == 0) {
1557 error << _("Session: XML state has no mix groups section") << endmsg;
1559 } else if (load_mix_groups (*child)) {
1563 if ((child = find_named_node (node, "TempoMap")) == 0) {
1564 error << _("Session: XML state has no Tempo Map section") << endmsg;
1566 } else if (_tempo_map->set_state (*child)) {
1570 if ((child = find_named_node (node, "Routes")) == 0) {
1571 error << _("Session: XML state has no routes section") << endmsg;
1573 } else if (load_routes (*child)) {
1577 if ((child = find_named_node (node, "Click")) == 0) {
1578 warning << _("Session: XML state has no click section") << endmsg;
1579 } else if (_click_io) {
1580 _click_io->set_state (*child);
1583 /* OK, now we can set edit mode */
1585 set_edit_mode (pending_edit_mode);
1587 /* here beginneth the second phase ... */
1589 StateReady (); /* EMIT SIGNAL */
1591 _state_of_the_state = Clean;
1593 StateManager::allow_save (_("initial state"), true);
1595 if (state_was_pending) {
1596 save_state (_current_snapshot_name);
1597 remove_pending_capture_state ();
1598 state_was_pending = false;
1604 /* we failed, re-enable state saving but don't actually save internal state */
1605 StateManager::allow_save (X_("ignored"), false);
1610 Session::load_routes (const XMLNode& node)
1613 XMLNodeConstIterator niter;
1616 nlist = node.children();
1620 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1622 if ((route = XMLRouteFactory (**niter)) == 0) {
1623 error << _("Session: cannot create Route from XML description.") << endmsg;
1634 Session::XMLRouteFactory (const XMLNode& node)
1636 if (node.name() != "Route") {
1640 if (node.property ("diskstream") != 0 || node.property ("diskstream-id") != 0) {
1641 return new AudioTrack (*this, node);
1643 return new Route (*this, node);
1648 Session::load_regions (const XMLNode& node)
1651 XMLNodeConstIterator niter;
1652 AudioRegion* region;
1654 nlist = node.children();
1658 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1660 if ((region = XMLRegionFactory (**niter, false)) == 0) {
1661 error << _("Session: cannot create Region from XML description.") << endmsg;
1669 Session::XMLRegionFactory (const XMLNode& node, bool full)
1671 const XMLProperty* prop;
1674 AudioRegion::SourceList sources;
1675 uint32_t nchans = 1;
1678 if (node.name() != X_("Region")) {
1682 if ((prop = node.property (X_("channels"))) != 0) {
1683 nchans = atoi (prop->value().c_str());
1687 if ((prop = node.property (X_("source-0"))) == 0) {
1688 if ((prop = node.property ("source")) == 0) {
1689 error << _("Session: XMLNode describing a AudioRegion is incomplete (no source)") << endmsg;
1694 sscanf (prop->value().c_str(), "%" PRIu64, &s_id);
1696 if ((source = get_source (s_id)) == 0) {
1697 error << string_compose(_("Session: XMLNode describing a AudioRegion references an unknown source id =%1"), s_id) << endmsg;
1701 sources.push_back(source);
1703 /* pickup other channels */
1705 for (uint32_t n=1; n < nchans; ++n) {
1706 snprintf (buf, sizeof(buf), X_("source-%d"), n);
1707 if ((prop = node.property (buf)) != 0) {
1708 sscanf (prop->value().c_str(), "%" PRIu64, &s_id);
1710 if ((source = get_source (s_id)) == 0) {
1711 error << string_compose(_("Session: XMLNode describing a AudioRegion references an unknown source id =%1"), s_id) << endmsg;
1714 sources.push_back(source);
1720 return new AudioRegion (sources, node);
1723 catch (failed_constructor& err) {
1729 Session::get_sources_as_xml ()
1732 XMLNode* node = new XMLNode (X_("Sources"));
1733 LockMonitor lm (source_lock, __LINE__, __FILE__);
1735 for (SourceList::iterator i = sources.begin(); i != sources.end(); ++i) {
1736 node->add_child_nocopy ((*i).second->get_state());
1743 Session::path_from_region_name (string name, string identifier)
1745 char buf[PATH_MAX+1];
1747 string dir = discover_best_sound_dir ();
1749 for (n = 0; n < 999999; ++n) {
1750 if (identifier.length()) {
1751 snprintf (buf, sizeof(buf), "%s/%s%s%" PRIu32 ".wav", dir.c_str(), name.c_str(),
1752 identifier.c_str(), n);
1754 snprintf (buf, sizeof(buf), "%s/%s-%" PRIu32 ".wav", dir.c_str(), name.c_str(), n);
1756 if (access (buf, F_OK) != 0) {
1766 Session::load_sources (const XMLNode& node)
1769 XMLNodeConstIterator niter;
1772 nlist = node.children();
1776 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1778 if ((source = XMLSourceFactory (**niter)) == 0) {
1779 error << _("Session: cannot create Source from XML description.") << endmsg;
1787 Session::XMLSourceFactory (const XMLNode& node)
1791 if (node.name() != "Source") {
1796 src = new FileSource (node, frame_rate());
1799 catch (failed_constructor& err) {
1802 src = new SndFileSource (node);
1805 catch (failed_constructor& err) {
1806 error << _("Found a sound file that cannot be used by Ardour. See the progammers.") << endmsg;
1815 Session::save_template (string template_name)
1818 string xml_path, bak_path, template_path;
1820 if (_state_of_the_state & CannotSave) {
1825 string dir = template_dir();
1827 if ((dp = opendir (dir.c_str()))) {
1830 if (mkdir (dir.c_str(), S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH)<0) {
1831 error << string_compose(_("Could not create mix templates directory \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
1836 tree.set_root (&get_template());
1839 xml_path += template_name;
1840 xml_path += _template_suffix;
1842 ifstream in(xml_path.c_str());
1845 warning << string_compose(_("Template \"%1\" already exists - new version not created"), template_name) << endmsg;
1851 if (!tree.write (xml_path)) {
1852 error << _("mix template not saved") << endmsg;
1860 Session::rename_template (string old_name, string new_name)
1862 string old_path = template_dir() + old_name + _template_suffix;
1863 string new_path = template_dir() + new_name + _template_suffix;
1865 return rename (old_path.c_str(), new_path.c_str());
1869 Session::delete_template (string name)
1871 string template_path = template_dir();
1872 template_path += name;
1873 template_path += _template_suffix;
1875 return remove (template_path.c_str());
1879 Session::refresh_disk_space ()
1882 struct statfs statfsbuf;
1883 vector<space_and_path>::iterator i;
1884 LockMonitor lm (space_lock, __LINE__, __FILE__);
1887 /* get freespace on every FS that is part of the session path */
1889 _total_free_4k_blocks = 0;
1891 for (i = session_dirs.begin(); i != session_dirs.end(); ++i) {
1892 statfs ((*i).path.c_str(), &statfsbuf);
1894 scale = statfsbuf.f_bsize/4096.0;
1896 (*i).blocks = (uint32_t) floor (statfsbuf.f_bavail * scale);
1897 _total_free_4k_blocks += (*i).blocks;
1903 Session::ensure_sound_dir (string path, string& result)
1908 /* Ensure that the parent directory exists */
1910 if (mkdir (path.c_str(), 0775)) {
1911 if (errno != EEXIST) {
1912 error << string_compose(_("cannot create session directory \"%1\"; ignored"), path) << endmsg;
1917 /* Ensure that the sounds directory exists */
1921 result += sound_dir_name;
1923 if (mkdir (result.c_str(), 0775)) {
1924 if (errno != EEXIST) {
1925 error << string_compose(_("cannot create sounds directory \"%1\"; ignored"), result) << endmsg;
1932 dead += dead_sound_dir_name;
1934 if (mkdir (dead.c_str(), 0775)) {
1935 if (errno != EEXIST) {
1936 error << string_compose(_("cannot create dead sounds directory \"%1\"; ignored"), dead) << endmsg;
1943 peak += peak_dir_name;
1945 if (mkdir (peak.c_str(), 0775)) {
1946 if (errno != EEXIST) {
1947 error << string_compose(_("cannot create peak file directory \"%1\"; ignored"), peak) << endmsg;
1952 /* callers expect this to be terminated ... */
1959 Session::discover_best_sound_dir ()
1961 vector<space_and_path>::iterator i;
1964 /* handle common case without system calls */
1966 if (session_dirs.size() == 1) {
1970 /* OK, here's the algorithm we're following here:
1972 We want to select which directory to use for
1973 the next file source to be created. Ideally,
1974 we'd like to use a round-robin process so as to
1975 get maximum performance benefits from splitting
1976 the files across multiple disks.
1978 However, in situations without much diskspace, an
1979 RR approach may end up filling up a filesystem
1980 with new files while others still have space.
1981 Its therefore important to pay some attention to
1982 the freespace in the filesystem holding each
1983 directory as well. However, if we did that by
1984 itself, we'd keep creating new files in the file
1985 system with the most space until it was as full
1986 as all others, thus negating any performance
1987 benefits of this RAID-1 like approach.
1989 So, we use a user-configurable space threshold. If
1990 there are at least 2 filesystems with more than this
1991 much space available, we use RR selection between them.
1992 If not, then we pick the filesystem with the most space.
1994 This gets a good balance between the two
1998 refresh_disk_space ();
2000 int free_enough = 0;
2002 for (i = session_dirs.begin(); i != session_dirs.end(); ++i) {
2003 if ((*i).blocks * 4096 >= Config->get_disk_choice_space_threshold()) {
2008 if (free_enough >= 2) {
2010 bool found_it = false;
2012 /* use RR selection process, ensuring that the one
2016 i = last_rr_session_dir;
2019 if (++i == session_dirs.end()) {
2020 i = session_dirs.begin();
2023 if ((*i).blocks * 4096 >= Config->get_disk_choice_space_threshold()) {
2024 if (ensure_sound_dir ((*i).path, result) == 0) {
2025 last_rr_session_dir = i;
2031 } while (i != last_rr_session_dir);
2034 result = sound_dir();
2039 /* pick FS with the most freespace (and that
2040 seems to actually work ...)
2043 vector<space_and_path> sorted;
2044 space_and_path_ascending_cmp cmp;
2046 sorted = session_dirs;
2047 sort (sorted.begin(), sorted.end(), cmp);
2049 for (i = sorted.begin(); i != sorted.end(); ++i) {
2050 if (ensure_sound_dir ((*i).path, result) == 0) {
2051 last_rr_session_dir = i;
2056 /* if the above fails, fall back to the most simplistic solution */
2058 if (i == sorted.end()) {
2067 Session::load_playlists (const XMLNode& node)
2070 XMLNodeConstIterator niter;
2073 nlist = node.children();
2077 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2079 if ((playlist = XMLPlaylistFactory (**niter)) == 0) {
2080 error << _("Session: cannot create Playlist from XML description.") << endmsg;
2088 Session::load_unused_playlists (const XMLNode& node)
2091 XMLNodeConstIterator niter;
2094 nlist = node.children();
2098 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2100 if ((playlist = XMLPlaylistFactory (**niter)) == 0) {
2101 error << _("Session: cannot create Playlist from XML description.") << endmsg;
2105 // now manually untrack it
2107 track_playlist (playlist, false);
2115 Session::XMLPlaylistFactory (const XMLNode& node)
2118 return new AudioPlaylist (*this, node);
2121 catch (failed_constructor& err) {
2127 Session::load_named_selections (const XMLNode& node)
2130 XMLNodeConstIterator niter;
2133 nlist = node.children();
2137 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2139 if ((ns = XMLNamedSelectionFactory (**niter)) == 0) {
2140 error << _("Session: cannot create Named Selection from XML description.") << endmsg;
2148 Session::XMLNamedSelectionFactory (const XMLNode& node)
2151 return new NamedSelection (*this, node);
2154 catch (failed_constructor& err) {
2160 Session::dead_sound_dir () const
2163 res += dead_sound_dir_name;
2169 Session::sound_dir () const
2172 res += sound_dir_name;
2178 Session::peak_dir () const
2181 res += peak_dir_name;
2187 Session::automation_dir () const
2190 res += "automation/";
2195 Session::template_dir ()
2197 string path = Config->get_user_ardour_path();
2198 path += "templates/";
2204 Session::template_path ()
2208 path += Config->get_user_ardour_path();
2209 if (path[path.length()-1] != ':') {
2212 path += Config->get_system_ardour_path();
2214 vector<string> split_path;
2216 split (path, split_path, ':');
2219 for (vector<string>::iterator i = split_path.begin(); i != split_path.end(); ++i) {
2221 path += "templates/";
2223 if (distance (i, split_path.end()) != 1) {
2232 Session::load_connections (const XMLNode& node)
2234 XMLNodeList nlist = node.children();
2235 XMLNodeConstIterator niter;
2239 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2240 if ((*niter)->name() == "InputConnection") {
2241 add_connection (new ARDOUR::InputConnection (**niter));
2242 } else if ((*niter)->name() == "OutputConnection") {
2243 add_connection (new ARDOUR::OutputConnection (**niter));
2245 error << string_compose(_("Unknown node \"%1\" found in Connections list from state file"), (*niter)->name()) << endmsg;
2254 Session::load_edit_groups (const XMLNode& node)
2256 return load_route_groups (node, true);
2260 Session::load_mix_groups (const XMLNode& node)
2262 return load_route_groups (node, false);
2266 Session::load_route_groups (const XMLNode& node, bool edit)
2268 XMLNodeList nlist = node.children();
2269 XMLNodeConstIterator niter;
2274 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2275 if ((*niter)->name() == "RouteGroup") {
2277 route = add_edit_group ("");
2278 route->set_state (**niter);
2280 route = add_mix_group ("");
2281 route->set_state (**niter);
2290 Session::swap_configuration(Configuration** new_config)
2292 RWLockMonitor lm (route_lock, true, __LINE__, __FILE__); // jlc - WHY?
2293 Configuration* tmp = *new_config;
2294 *new_config = Config;
2300 Session::copy_configuration(Configuration* new_config)
2302 RWLockMonitor lm (route_lock, true, __LINE__, __FILE__);
2303 new_config = new Configuration(*Config);
2307 state_file_filter (const string &str, void *arg)
2309 return (str.length() > strlen(Session::statefile_suffix()) &&
2310 str.find (Session::statefile_suffix()) == (str.length() - strlen (Session::statefile_suffix())));
2314 bool operator()(const string* a, const string* b) {
2320 remove_end(string* state)
2322 string statename(*state);
2324 string::size_type start,end;
2325 if ((start = statename.find_last_of ('/')) != string::npos) {
2326 statename = statename.substr (start+1);
2329 if ((end = statename.rfind(".ardour")) < 0) {
2330 end = statename.length();
2333 return new string(statename.substr (0, end));
2337 Session::possible_states (string path)
2339 PathScanner scanner;
2340 vector<string*>* states = scanner (path, state_file_filter, 0, false, false);
2342 transform(states->begin(), states->end(), states->begin(), remove_end);
2345 sort (states->begin(), states->end(), cmp);
2351 Session::possible_states () const
2353 return possible_states(_path);
2357 Session::auto_save()
2359 save_state (_current_snapshot_name);
2363 Session::add_edit_group (string name)
2365 RouteGroup* rg = new RouteGroup (name);
2366 edit_groups.push_back (rg);
2367 edit_group_added (rg); /* EMIT SIGNAL */
2373 Session::add_mix_group (string name)
2375 RouteGroup* rg = new RouteGroup (name, RouteGroup::Relative);
2376 mix_groups.push_back (rg);
2377 mix_group_added (rg); /* EMIT SIGNAL */
2383 Session::mix_group_by_name (string name)
2385 list<RouteGroup *>::iterator i;
2387 for (i = mix_groups.begin(); i != mix_groups.end(); ++i) {
2388 if ((*i)->name() == name) {
2396 Session::edit_group_by_name (string name)
2398 list<RouteGroup *>::iterator i;
2400 for (i = edit_groups.begin(); i != edit_groups.end(); ++i) {
2401 if ((*i)->name() == name) {
2409 Session::set_meter_hold (float val)
2412 MeterHoldChanged(); // emit
2416 Session::set_meter_falloff (float val)
2418 _meter_falloff = val;
2419 MeterFalloffChanged(); // emit
2424 Session::begin_reversible_command (string name, UndoAction* private_undo)
2426 current_cmd.clear ();
2427 current_cmd.set_name (name);
2430 current_cmd.add_undo (*private_undo);
2435 Session::commit_reversible_command (UndoAction* private_redo)
2440 current_cmd.add_redo_no_execute (*private_redo);
2443 gettimeofday (&now, 0);
2444 current_cmd.set_timestamp (now);
2446 history.add (current_cmd);
2449 Session::GlobalRouteBooleanState
2450 Session::get_global_route_boolean (bool (Route::*method)(void) const)
2452 GlobalRouteBooleanState s;
2453 RWLockMonitor lm (route_lock, false, __LINE__, __FILE__);
2455 for (RouteList::iterator i = routes.begin(); i != routes.end(); ++i) {
2456 if (!(*i)->hidden()) {
2457 RouteBooleanState v;
2460 v.second = ((*i)->*method)();
2469 Session::GlobalRouteMeterState
2470 Session::get_global_route_metering ()
2472 GlobalRouteMeterState s;
2473 RWLockMonitor lm (route_lock, false, __LINE__, __FILE__);
2475 for (RouteList::iterator i = routes.begin(); i != routes.end(); ++i) {
2476 if (!(*i)->hidden()) {
2480 v.second = (*i)->meter_point();
2490 Session::set_global_route_metering (GlobalRouteMeterState s, void* arg)
2492 for (GlobalRouteMeterState::iterator i = s.begin(); i != s.end(); ++i) {
2493 i->first->set_meter_point (i->second, arg);
2498 Session::set_global_route_boolean (GlobalRouteBooleanState s, void (Route::*method)(bool, void*), void* arg)
2500 for (GlobalRouteBooleanState::iterator i = s.begin(); i != s.end(); ++i) {
2501 (i->first->*method) (i->second, arg);
2506 Session::set_global_mute (GlobalRouteBooleanState s, void* src)
2508 set_global_route_boolean (s, &Route::set_mute, src);
2512 Session::set_global_solo (GlobalRouteBooleanState s, void* src)
2514 set_global_route_boolean (s, &Route::set_solo, src);
2518 Session::set_global_record_enable (GlobalRouteBooleanState s, void* src)
2520 set_global_route_boolean (s, &Route::set_record_enable, src);
2524 Session::global_mute_memento (void* src)
2526 return sigc::bind (mem_fun (*this, &Session::set_global_mute), get_global_route_boolean (&Route::muted), src);
2530 Session::global_metering_memento (void* src)
2532 return sigc::bind (mem_fun (*this, &Session::set_global_route_metering), get_global_route_metering (), src);
2536 Session::global_solo_memento (void* src)
2538 return sigc::bind (mem_fun (*this, &Session::set_global_solo), get_global_route_boolean (&Route::soloed), src);
2542 Session::global_record_enable_memento (void* src)
2544 return sigc::bind (mem_fun (*this, &Session::set_global_record_enable), get_global_route_boolean (&Route::record_enabled), src);
2548 template_filter (const string &str, void *arg)
2550 return (str.length() > strlen(Session::template_suffix()) &&
2551 str.find (Session::template_suffix()) == (str.length() - strlen (Session::template_suffix())));
2555 Session::get_template_list (list<string> &template_names)
2557 vector<string *> *templates;
2558 PathScanner scanner;
2561 path = template_path ();
2563 templates = scanner (path, template_filter, 0, false, true);
2565 vector<string*>::iterator i;
2566 for (i = templates->begin(); i != templates->end(); ++i) {
2567 string fullpath = *(*i);
2570 start = fullpath.find_last_of ('/') + 1;
2571 if ((end = fullpath.find_last_of ('.')) <0) {
2572 end = fullpath.length();
2575 template_names.push_back(fullpath.substr(start, (end-start)));
2580 Session::read_favorite_dirs (FavoriteDirs & favs)
2582 string path = Config->get_user_ardour_path();
2583 path += "/favorite_dirs";
2585 ifstream fav (path.c_str());
2590 if (errno != ENOENT) {
2591 //error << string_compose (_("cannot open favorite file %1 (%2)"), path, strerror (errno)) << endmsg;
2602 getline(fav, newfav);
2608 favs.push_back (newfav);
2615 Session::write_favorite_dirs (FavoriteDirs & favs)
2617 string path = Config->get_user_ardour_path();
2618 path += "/favorite_dirs";
2620 ofstream fav (path.c_str());
2626 for (FavoriteDirs::iterator i = favs.begin(); i != favs.end(); ++i) {
2627 fav << (*i) << endl;
2634 accept_all_non_peak_files (const string& path, void *arg)
2636 return (path.length() > 5 && path.find (".peak") != (path.length() - 5));
2640 accept_all_state_files (const string& path, void *arg)
2642 return (path.length() > 7 && path.find (".ardour") == (path.length() - 7));
2646 Session::find_all_sources (string path, set<string>& result)
2651 if (!tree.read (path)) {
2655 if ((node = find_named_node (*tree.root(), "Sources")) == 0) {
2660 XMLNodeConstIterator niter;
2662 nlist = node->children();
2666 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2670 if ((prop = (*niter)->property (X_("name"))) == 0) {
2674 if (prop->value()[0] == '/') {
2675 /* external file, ignore */
2679 string path = _path; /* /-terminated */
2680 path += sound_dir_name;
2682 path += prop->value();
2684 result.insert (path);
2691 Session::find_all_sources_across_snapshots (set<string>& result, bool exclude_this_snapshot)
2693 PathScanner scanner;
2694 vector<string*>* state_files;
2696 string this_snapshot_path;
2702 if (ripped[ripped.length()-1] == '/') {
2703 ripped = ripped.substr (0, ripped.length() - 1);
2706 state_files = scanner (ripped, accept_all_state_files, (void *) 0, false, true);
2708 if (state_files == 0) {
2713 this_snapshot_path = _path;
2714 this_snapshot_path += _current_snapshot_name;
2715 this_snapshot_path += _statefile_suffix;
2717 for (vector<string*>::iterator i = state_files->begin(); i != state_files->end(); ++i) {
2719 if (exclude_this_snapshot && **i == this_snapshot_path) {
2723 if (find_all_sources (**i, result) < 0) {
2732 Session::cleanup_sources (Session::cleanup_report& rep)
2734 vector<Source*> dead_sources;
2735 vector<Playlist*> playlists_tbd;
2736 PathScanner scanner;
2738 vector<space_and_path>::iterator i;
2739 vector<space_and_path>::iterator nexti;
2740 vector<string*>* soundfiles;
2741 vector<string> unused;
2742 set<string> all_sources;
2747 _state_of_the_state = (StateOfTheState) (_state_of_the_state | InCleanup);
2749 /* step 1: consider deleting all unused playlists */
2751 for (PlaylistList::iterator x = unused_playlists.begin(); x != unused_playlists.end(); ++x) {
2754 status = AskAboutPlaylistDeletion (*x);
2763 playlists_tbd.push_back (*x);
2767 /* leave it alone */
2772 /* now delete any that were marked for deletion */
2774 for (vector<Playlist*>::iterator x = playlists_tbd.begin(); x != playlists_tbd.end(); ++x) {
2775 PlaylistList::iterator foo;
2777 if ((foo = unused_playlists.find (*x)) != unused_playlists.end()) {
2778 unused_playlists.erase (foo);
2783 /* step 2: clear the undo/redo history for all playlists */
2785 for (PlaylistList::iterator x = playlists.begin(); x != playlists.end(); ++x) {
2786 (*x)->drop_all_states ();
2789 /* step 3: find all un-referenced sources */
2794 for (SourceList::iterator i = sources.begin(); i != sources.end(); ) {
2796 SourceList::iterator tmp;
2801 /* only remove files that are not in use and have some size
2802 to them. otherwise we remove the current "nascent"
2806 if ((*i).second->use_cnt() == 0 && (*i).second->length() > 0) {
2807 dead_sources.push_back (i->second);
2809 /* remove this source from our own list to avoid us
2810 adding it to the list of all sources below
2819 /* Step 4: get rid of all regions in the region list that use any dead sources
2820 in case the sources themselves don't go away (they might be referenced in
2824 for (vector<Source*>::iterator i = dead_sources.begin(); i != dead_sources.end();++i) {
2826 for (AudioRegionList::iterator r = audio_regions.begin(); r != audio_regions.end(); ) {
2827 AudioRegionList::iterator tmp;
2835 for (uint32_t n = 0; n < ar->n_channels(); ++n) {
2836 if (&ar->source (n) == (*i)) {
2837 /* this region is dead */
2846 /* build a list of all the possible sound directories for the session */
2848 for (i = session_dirs.begin(); i != session_dirs.end(); ) {
2853 sound_path += (*i).path;
2854 sound_path += sound_dir_name;
2856 if (nexti != session_dirs.end()) {
2863 /* now do the same thing for the files that ended up in the sounds dir(s)
2864 but are not referenced as sources in any snapshot.
2867 soundfiles = scanner (sound_path, accept_all_non_peak_files, (void *) 0, false, true);
2869 if (soundfiles == 0) {
2873 /* find all sources, but don't use this snapshot because the
2874 state file on disk still references sources we may have already
2878 find_all_sources_across_snapshots (all_sources, true);
2880 /* add our current source list
2883 for (SourceList::iterator i = sources.begin(); i != sources.end(); ++i) {
2887 if ((fs = dynamic_cast<FileSource*> ((*i).second)) != 0) {
2888 all_sources.insert (fs->path());
2889 } else if ((sfs = dynamic_cast<SndFileSource*> ((*i).second)) != 0) {
2890 all_sources.insert (sfs->path());
2894 for (vector<string*>::iterator x = soundfiles->begin(); x != soundfiles->end(); ++x) {
2899 for (set<string>::iterator i = all_sources.begin(); i != all_sources.end(); ++i) {
2909 unused.push_back (spath);
2913 /* now try to move all unused files into the "dead_sounds" directory(ies) */
2915 for (vector<string>::iterator x = unused.begin(); x != unused.end(); ++x) {
2916 struct stat statbuf;
2918 rep.paths.push_back (*x);
2919 if (stat ((*x).c_str(), &statbuf) == 0) {
2920 rep.space += statbuf.st_size;
2925 /* don't move the file across filesystems, just
2926 stick it in the `dead_sound_dir_name' directory
2927 on whichever filesystem it was already on.
2930 newpath = PBD::dirname (*x);
2931 newpath = PBD::dirname (newpath);
2934 newpath += dead_sound_dir_name;
2936 newpath += PBD::basename ((*x));
2938 if (access (newpath.c_str(), F_OK) == 0) {
2940 /* the new path already exists, try versioning */
2942 char buf[PATH_MAX+1];
2946 snprintf (buf, sizeof (buf), "%s.%d", newpath.c_str(), version);
2949 while (access (newpath_v.c_str(), F_OK) == 0 && version < 999) {
2950 snprintf (buf, sizeof (buf), "%s.%d", newpath.c_str(), ++version);
2954 if (version == 999) {
2955 error << string_compose (_("there are already 1000 files with names like %1; versioning discontinued"),
2959 newpath = newpath_v;
2964 /* it doesn't exist, or we can't read it or something */
2968 if (::rename ((*x).c_str(), newpath.c_str()) != 0) {
2969 error << string_compose (_("cannot rename audio file source from %1 to %2 (%3)"),
2970 (*x), newpath, strerror (errno))
2976 /* see if there an easy to find peakfile for this file, and remove it.
2979 string peakpath = (*x).substr (0, (*x).find_last_of ('.'));
2980 peakpath += ".peak";
2982 if (access (peakpath.c_str(), W_OK) == 0) {
2983 if (::unlink (peakpath.c_str()) != 0) {
2984 error << string_compose (_("cannot remove peakfile %1 for %2 (%3)"),
2985 peakpath, _path, strerror (errno))
2987 /* try to back out */
2988 rename (newpath.c_str(), _path.c_str());
2997 /* dump the history list */
3001 /* save state so we don't end up a session file
3002 referring to non-existent sources.
3008 _state_of_the_state = (StateOfTheState) (_state_of_the_state & ~InCleanup);
3013 Session::cleanup_trash_sources (Session::cleanup_report& rep)
3015 vector<space_and_path>::iterator i;
3016 string dead_sound_dir;
3017 struct dirent* dentry;
3018 struct stat statbuf;
3024 for (i = session_dirs.begin(); i != session_dirs.end(); ++i) {
3026 dead_sound_dir = (*i).path;
3027 dead_sound_dir += dead_sound_dir_name;
3029 if ((dead = opendir (dead_sound_dir.c_str())) == 0) {
3033 while ((dentry = readdir (dead)) != 0) {
3035 /* avoid '.' and '..' */
3037 if ((dentry->d_name[0] == '.' && dentry->d_name[1] == '\0') ||
3038 (dentry->d_name[2] == '\0' && dentry->d_name[0] == '.' && dentry->d_name[1] == '.')) {
3044 fullpath = dead_sound_dir;
3046 fullpath += dentry->d_name;
3048 if (stat (fullpath.c_str(), &statbuf)) {
3052 if (!S_ISREG (statbuf.st_mode)) {
3056 if (unlink (fullpath.c_str())) {
3057 error << string_compose (_("cannot remove dead sound file %1 (%2)"),
3058 fullpath, strerror (errno))
3062 rep.paths.push_back (dentry->d_name);
3063 rep.space += statbuf.st_size;
3074 Session::set_dirty ()
3076 bool was_dirty = dirty();
3078 _state_of_the_state = StateOfTheState (_state_of_the_state | Dirty);
3081 DirtyChanged(); /* EMIT SIGNAL */
3087 Session::set_clean ()
3089 bool was_dirty = dirty();
3091 _state_of_the_state = Clean;
3094 DirtyChanged(); /* EMIT SIGNAL */