2 Copyright (C) 1999-2002 Paul Davis
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
26 #include <sigc++/bind.h>
28 #include <cstdio> /* snprintf(3) ... grrr */
43 #include <sys/mount.h>
44 #include <sys/param.h>
49 #include <midi++/mmc.h>
50 #include <midi++/port.h>
51 #include <pbd/error.h>
53 #include <glibmm/thread.h>
54 #include <pbd/pathscanner.h>
55 #include <pbd/pthread_utils.h>
56 #include <pbd/strsplit.h>
58 #include <ardour/audioengine.h>
59 #include <ardour/configuration.h>
60 #include <ardour/session.h>
61 #include <ardour/buffer.h>
62 #include <ardour/audio_diskstream.h>
63 #include <ardour/midi_diskstream.h>
64 #include <ardour/utils.h>
65 #include <ardour/audioplaylist.h>
66 #include <ardour/midi_playlist.h>
67 #include <ardour/smf_source.h>
68 #include <ardour/audiofilesource.h>
69 #include <ardour/destructive_filesource.h>
70 #include <ardour/midi_source.h>
71 #include <ardour/sndfile_helpers.h>
72 #include <ardour/auditioner.h>
73 #include <ardour/export.h>
74 #include <ardour/redirect.h>
75 #include <ardour/send.h>
76 #include <ardour/insert.h>
77 #include <ardour/connection.h>
78 #include <ardour/slave.h>
79 #include <ardour/tempo.h>
80 #include <ardour/audio_track.h>
81 #include <ardour/midi_track.h>
82 #include <ardour/cycle_timer.h>
83 #include <ardour/utils.h>
84 #include <ardour/named_selection.h>
85 #include <ardour/version.h>
86 #include <ardour/location.h>
87 #include <ardour/audioregion.h>
88 #include <ardour/midi_region.h>
89 #include <ardour/crossfade.h>
90 #include <ardour/control_protocol_manager.h>
91 #include <ardour/region_factory.h>
92 #include <ardour/source_factory.h>
98 using namespace ARDOUR;
102 Session::first_stage_init (string fullpath, string snapshot_name)
104 if (fullpath.length() == 0) {
105 throw failed_constructor();
108 char buf[PATH_MAX+1];
109 if (!realpath(fullpath.c_str(), buf) && (errno != ENOENT)) {
110 error << string_compose(_("Could not use path %1 (%s)"), buf, strerror(errno)) << endmsg;
111 throw failed_constructor();
115 if (_path[_path.length()-1] != '/') {
119 /* these two are just provisional settings. set_state()
120 will likely override them.
123 _name = _current_snapshot_name = snapshot_name;
124 setup_raid_path (_path);
126 _current_frame_rate = _engine.frame_rate ();
127 _tempo_map = new TempoMap (_current_frame_rate);
128 _tempo_map->StateChanged.connect (mem_fun (*this, &Session::tempo_map_changed));
130 g_atomic_int_set (&processing_prohibited, 0);
133 _transport_speed = 0;
134 _last_transport_speed = 0;
135 transport_sub_state = 0;
136 _transport_frame = 0;
138 end_location = new Location (0, 0, _("end"), Location::Flags ((Location::IsMark|Location::IsEnd)));
139 start_location = new Location (0, 0, _("start"), Location::Flags ((Location::IsMark|Location::IsStart)));
140 _end_location_is_free = true;
141 g_atomic_int_set (&_record_status, Disabled);
146 seamless_loop = false;
147 loop_changing = false;
149 crossfades_active = false;
152 _last_roll_location = 0;
153 _last_record_location = 0;
154 pending_locate_frame = 0;
155 pending_locate_roll = false;
156 pending_locate_flush = false;
157 dstream_buffer_size = 0;
159 state_was_pending = false;
161 outbound_mtc_smpte_frame = 0;
162 next_quarter_frame_to_send = -1;
163 current_block_size = 0;
164 _solo_latched = true;
165 _solo_model = InverseMute;
166 solo_update_disabled = false;
167 currently_soloing = false;
168 _have_captured = false;
169 _worst_output_latency = 0;
170 _worst_input_latency = 0;
171 _worst_track_latency = 0;
172 _state_of_the_state = StateOfTheState(CannotSave|InitialConnecting|Loading);
175 butler_mixdown_buffer = 0;
176 butler_gain_buffer = 0;
180 post_transport_work = PostTransportWork (0);
181 g_atomic_int_set (&butler_should_do_transport_work, 0);
182 g_atomic_int_set (&butler_active, 0);
183 g_atomic_int_set (&_playback_load, 100);
184 g_atomic_int_set (&_capture_load, 100);
185 g_atomic_int_set (&_playback_load_min, 100);
186 g_atomic_int_set (&_capture_load_min, 100);
188 pending_edit_mode = _edit_mode;
190 input_auto_connect = AutoConnectOption (0);
191 output_auto_connect = AutoConnectOption (0);
192 waiting_to_start = false;
194 _gain_automation_buffer = 0;
195 _pan_automation_buffer = 0;
197 pending_abort = false;
198 layer_model = MoveAddHigher;
199 xfade_model = ShortCrossfade;
200 destructive_index = 0;
203 AudioDiskstream::allocate_working_buffers();
205 /* default short fade = 15ms */
207 Crossfade::set_short_xfade_length ((jack_nframes_t) floor ((15.0 * frame_rate()) / 1000.0));
208 DestructiveFileSource::setup_standard_crossfades (frame_rate());
210 last_mmc_step.tv_sec = 0;
211 last_mmc_step.tv_usec = 0;
214 preroll.type = AnyTime::Frames;
216 postroll.type = AnyTime::Frames;
219 /* click sounds are unset by default, which causes us to internal
220 waveforms for clicks.
224 click_requested = false;
226 click_emphasis_data = 0;
228 click_emphasis_length = 0;
230 process_function = &Session::process_with_events;
234 _smpte_offset_negative = true;
235 last_smpte_valid = false;
237 last_rr_session_dir = session_dirs.begin();
238 refresh_disk_space ();
240 // set_default_fade (0.2, 5.0); /* steepness, millisecs */
242 /* default configuration */
244 do_not_record_plugins = false;
245 over_length_short = 2;
246 over_length_long = 10;
247 send_midi_timecode = false;
248 send_midi_machine_control = false;
249 shuttle_speed_factor = 1.0;
250 shuttle_speed_threshold = 5;
252 _meter_hold = 100; // XXX unknown units: number of calls to meter::set()
253 _meter_falloff = 0.375f; // XXX unknown units: refresh_rate
259 average_slave_delta = 1800;
260 have_first_delta_accumulator = false;
261 delta_accumulator_cnt = 0;
262 slave_state = Stopped;
264 /* default SMPTE type is 30 FPS, non-drop */
266 set_smpte_type (30.0, false);
268 _engine.GraphReordered.connect (mem_fun (*this, &Session::graph_reordered));
270 /* These are all static "per-class" signals */
272 RegionFactory::CheckNewRegion.connect (mem_fun (*this, &Session::add_region));
273 SourceFactory::SourceCreated.connect (mem_fun (*this, &Session::add_source));
274 Playlist::PlaylistCreated.connect (mem_fun (*this, &Session::add_playlist));
275 Redirect::RedirectCreated.connect (mem_fun (*this, &Session::add_redirect));
276 NamedSelection::NamedSelectionCreated.connect (mem_fun (*this, &Session::add_named_selection));
277 Curve::CurveCreated.connect (mem_fun (*this, &Session::add_curve));
278 AutomationList::AutomationListCreated.connect (mem_fun (*this, &Session::add_automation_list));
280 Controllable::Created.connect (mem_fun (*this, &Session::add_controllable));
281 Controllable::GoingAway.connect (mem_fun (*this, &Session::remove_controllable));
283 IO::MoreChannels.connect (mem_fun (*this, &Session::ensure_buffers));
285 /* stop IO objects from doing stuff until we're ready for them */
287 IO::disable_panners ();
288 IO::disable_ports ();
289 IO::disable_connecting ();
293 Session::second_stage_init (bool new_session)
295 AudioFileSource::set_peak_dir (peak_dir());
298 if (load_state (_current_snapshot_name)) {
299 cerr << "load state failed\n";
302 remove_empty_sounds ();
305 if (start_butler_thread()) {
309 /*if (start_midi_thread ()) {
314 if (set_state (*state_tree->root())) {
319 /* we can't save till after ::when_engine_running() is called,
320 because otherwise we save state with no connections made.
321 therefore, we reset _state_of_the_state because ::set_state()
322 will have cleared it.
324 we also have to include Loading so that any events that get
325 generated between here and the end of ::when_engine_running()
326 will be processed directly rather than queued.
329 _state_of_the_state = StateOfTheState (_state_of_the_state|CannotSave|Loading);
331 // set_auto_input (true);
332 _locations.changed.connect (mem_fun (this, &Session::locations_changed));
333 _locations.added.connect (mem_fun (this, &Session::locations_added));
334 setup_click_sounds (0);
335 setup_midi_control ();
337 /* Pay attention ... */
339 _engine.Halted.connect (mem_fun (*this, &Session::engine_halted));
340 _engine.Xrun.connect (mem_fun (*this, &Session::xrun_recovery));
342 if (_engine.running()) {
343 when_engine_running();
345 first_time_running = _engine.Running.connect (mem_fun (*this, &Session::when_engine_running));
348 //send_full_time_code ();
349 _engine.transport_locate (0);
350 deliver_mmc (MIDI::MachineControl::cmdMmcReset, 0);
351 deliver_mmc (MIDI::MachineControl::cmdLocate, 0);
353 ControlProtocolManager::instance().set_session (*this);
356 _end_location_is_free = true;
358 _end_location_is_free = false;
361 restore_history(_current_snapshot_name);
366 Session::raid_path () const
370 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
375 return path.substr (0, path.length() - 1); // drop final colon
379 Session::set_raid_path (string path)
381 /* public-access to setup_raid_path() */
383 setup_raid_path (path);
387 Session::setup_raid_path (string path)
389 string::size_type colon;
393 string::size_type len = path.length();
398 if (path.length() == 0) {
402 session_dirs.clear ();
404 for (string::size_type n = 0; n < len; ++n) {
405 if (path[n] == ':') {
412 /* no multiple search path, just one location (common case) */
416 session_dirs.push_back (sp);
423 if (fspath[fspath.length()-1] != '/') {
426 fspath += sound_dir_name;
432 if (fspath[fspath.length()-1] != '/') {
435 fspath += tape_dir_name;
437 AudioFileSource::set_search_path (fspath);
438 SMFSource::set_search_path (fspath); // FIXME: should be different
445 while ((colon = remaining.find_first_of (':')) != string::npos) {
448 sp.path = remaining.substr (0, colon);
449 session_dirs.push_back (sp);
451 /* add sounds to file search path */
454 if (fspath[fspath.length()-1] != '/') {
457 fspath += sound_dir_name;
460 /* add tape dir to file search path */
463 if (fspath[fspath.length()-1] != '/') {
466 fspath += tape_dir_name;
469 remaining = remaining.substr (colon+1);
472 if (remaining.length()) {
479 if (fspath[fspath.length()-1] != '/') {
482 fspath += sound_dir_name;
486 if (fspath[fspath.length()-1] != '/') {
489 fspath += tape_dir_name;
491 session_dirs.push_back (sp);
494 /* set the AudioFileSource search path */
496 AudioFileSource::set_search_path (fspath);
497 SMFSource::set_search_path (fspath); // FIXME: should be different
499 /* reset the round-robin soundfile path thingie */
501 last_rr_session_dir = session_dirs.begin();
505 Session::create (bool& new_session, string* mix_template, jack_nframes_t initial_length)
509 if (mkdir (_path.c_str(), 0755) < 0) {
510 if (errno == EEXIST) {
513 error << string_compose(_("Session: cannot create session dir \"%1\" (%2)"), _path, strerror (errno)) << endmsg;
522 if (mkdir (dir.c_str(), 0755) < 0) {
523 if (errno != EEXIST) {
524 error << string_compose(_("Session: cannot create session peakfile 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 sounds dir \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
540 if (mkdir (dir.c_str(), 0755) < 0) {
541 if (errno != EEXIST) {
542 error << string_compose(_("Session: cannot create session tape dir \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
547 dir = dead_sound_dir ();
549 if (mkdir (dir.c_str(), 0755) < 0) {
550 if (errno != EEXIST) {
551 error << string_compose(_("Session: cannot create session dead sounds dir \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
556 dir = automation_dir ();
558 if (mkdir (dir.c_str(), 0755) < 0) {
559 if (errno != EEXIST) {
560 error << string_compose(_("Session: cannot create session automation dir \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
566 /* check new_session so we don't overwrite an existing one */
570 std::string in_path = *mix_template;
572 ifstream in(in_path.c_str());
575 string out_path = _path;
577 out_path += _statefile_suffix;
579 ofstream out(out_path.c_str());
584 // okay, session is set up. Treat like normal saved
585 // session from now on.
591 error << string_compose (_("Could not open %1 for writing mix template"), out_path)
597 error << string_compose (_("Could not open mix template %1 for reading"), in_path)
604 warning << _("Session already exists. Not overwriting") << endmsg;
611 /* set initial start + end point */
613 start_location->set_end (0);
614 _locations.add (start_location);
616 end_location->set_end (initial_length);
617 _locations.add (end_location);
619 _state_of_the_state = Clean;
621 if (save_state (_current_snapshot_name)) {
622 save_history (_current_snapshot_name);
631 Session::load_diskstreams (const XMLNode& node)
634 XMLNodeConstIterator citer;
636 clist = node.children();
638 for (citer = clist.begin(); citer != clist.end(); ++citer) {
641 /* diskstreams added automatically by DiskstreamCreated handler */
642 if ((*citer)->name() == "AudioDiskstream" || (*citer)->name() == "DiskStream") {
643 boost::shared_ptr<AudioDiskstream> dstream (new AudioDiskstream (*this, **citer));
644 add_diskstream (dstream);
645 } else if ((*citer)->name() == "MidiDiskstream") {
646 boost::shared_ptr<MidiDiskstream> dstream (new MidiDiskstream (*this, **citer));
647 add_diskstream (dstream);
649 error << _("Session: unknown diskstream type in XML") << endmsg;
653 catch (failed_constructor& err) {
654 error << _("Session: could not load diskstream via XML state") << endmsg;
663 Session::remove_pending_capture_state ()
668 xml_path += _current_snapshot_name;
669 xml_path += _pending_suffix;
671 unlink (xml_path.c_str());
675 Session::save_state (string snapshot_name, bool pending)
681 if (_state_of_the_state & CannotSave) {
685 tree.set_root (&get_state());
687 if (snapshot_name.empty()) {
688 snapshot_name = _current_snapshot_name;
694 xml_path += snapshot_name;
695 xml_path += _statefile_suffix;
699 // Make backup of state file
701 if ((access (xml_path.c_str(), F_OK) == 0) &&
702 (rename(xml_path.c_str(), bak_path.c_str()))) {
703 error << _("could not backup old state file, current state not saved.") << endmsg;
710 xml_path += snapshot_name;
711 xml_path += _pending_suffix;
715 if (!tree.write (xml_path)) {
716 error << string_compose (_("state could not be saved to %1"), xml_path) << endmsg;
718 /* don't leave a corrupt file lying around if it is
722 if (unlink (xml_path.c_str())) {
723 error << string_compose (_("could not remove corrupt state file %1"), xml_path) << endmsg;
726 if (rename (bak_path.c_str(), xml_path.c_str())) {
727 error << string_compose (_("could not restore state file from backup %1"), bak_path) << endmsg;
736 save_history(snapshot_name);
738 bool was_dirty = dirty();
740 _state_of_the_state = StateOfTheState (_state_of_the_state & ~Dirty);
743 DirtyChanged (); /* EMIT SIGNAL */
746 StateSaved (snapshot_name); /* EMIT SIGNAL */
753 Session::restore_state (string snapshot_name)
755 if (load_state (snapshot_name) == 0) {
756 set_state (*state_tree->root());
763 Session::load_state (string snapshot_name)
772 state_was_pending = false;
774 /* check for leftover pending state from a crashed capture attempt */
777 xmlpath += snapshot_name;
778 xmlpath += _pending_suffix;
780 if (!access (xmlpath.c_str(), F_OK)) {
782 /* there is pending state from a crashed capture attempt */
784 if (AskAboutPendingState()) {
785 state_was_pending = true;
789 if (!state_was_pending) {
792 xmlpath += snapshot_name;
793 xmlpath += _statefile_suffix;
796 if (access (xmlpath.c_str(), F_OK)) {
797 error << string_compose(_("%1: session state information file \"%2\" doesn't exist!"), _name, xmlpath) << endmsg;
801 state_tree = new XMLTree;
805 if (state_tree->read (xmlpath)) {
808 error << string_compose(_("Could not understand ardour file %1"), xmlpath) << endmsg;
817 Session::load_options (const XMLNode& node)
821 bool have_fade_msecs = false;
822 bool have_fade_steepness = false;
823 float fade_msecs = 0;
824 float fade_steepness = 0;
825 SlaveSource slave_src = None;
827 LocaleGuard lg (X_("POSIX"));
829 if ((child = find_named_node (node, "input-auto-connect")) != 0) {
830 if ((prop = child->property ("val")) != 0) {
831 sscanf (prop->value().c_str(), "%x", &x);
832 input_auto_connect = AutoConnectOption (x);
836 if ((child = find_named_node (node, "output-auto-connect")) != 0) {
837 if ((prop = child->property ("val")) != 0) {
838 sscanf (prop->value().c_str(), "%x", &x);
839 output_auto_connect = AutoConnectOption (x);
843 if ((child = find_named_node (node, "slave")) != 0) {
844 if ((prop = child->property ("type")) != 0) {
845 if (prop->value() == "none") {
847 } else if (prop->value() == "mtc") {
849 } else if (prop->value() == "jack") {
852 set_slave_source (slave_src, 0);
856 /* we cannot set edit mode if we are loading a session,
857 because it might destroy the playlist's positioning
860 if ((child = find_named_node (node, "edit-mode")) != 0) {
861 if ((prop = child->property ("val")) != 0) {
862 if (prop->value() == "slide") {
863 pending_edit_mode = Slide;
864 } else if (prop->value() == "splice") {
865 pending_edit_mode = Splice;
870 if ((child = find_named_node (node, "send-midi-timecode")) != 0) {
871 if ((prop = child->property ("val")) != 0) {
872 bool x = (prop->value() == "yes");
873 send_mtc = !x; /* force change in value */
877 if ((child = find_named_node (node, "send-midi-machine-control")) != 0) {
878 if ((prop = child->property ("val")) != 0) {
879 bool x = (prop->value() == "yes");
880 send_mmc = !x; /* force change in value */
881 set_send_mmc (prop->value() == "yes");
884 if ((child = find_named_node (node, "max-level")) != 0) {
885 if ((prop = child->property ("val")) != 0) {
886 max_level = atoi (prop->value().c_str());
889 if ((child = find_named_node (node, "min-level")) != 0) {
890 if ((prop = child->property ("val")) != 0) {
891 min_level = atoi (prop->value().c_str());
894 if ((child = find_named_node (node, "meter-hold")) != 0) {
895 if ((prop = child->property ("val")) != 0) {
896 _meter_hold = atof (prop->value().c_str());
899 if ((child = find_named_node (node, "meter-falloff")) != 0) {
900 if ((prop = child->property ("val")) != 0) {
901 _meter_falloff = atof (prop->value().c_str());
904 if ((child = find_named_node (node, "long-over-length")) != 0) {
905 if ((prop = child->property ("val")) != 0) {
906 over_length_long = atoi (prop->value().c_str());
909 if ((child = find_named_node (node, "short-over-length")) != 0) {
910 if ((prop = child->property ("val")) != 0) {
911 over_length_short = atoi (prop->value().c_str());
914 if ((child = find_named_node (node, "shuttle-speed-factor")) != 0) {
915 if ((prop = child->property ("val")) != 0) {
916 shuttle_speed_factor = atof (prop->value().c_str());
919 if ((child = find_named_node (node, "shuttle-speed-threshold")) != 0) {
920 if ((prop = child->property ("val")) != 0) {
921 shuttle_speed_threshold = atof (prop->value().c_str());
924 if ((child = find_named_node (node, "rf-speed")) != 0) {
925 if ((prop = child->property ("val")) != 0) {
926 rf_speed = atof (prop->value().c_str());
929 if ((child = find_named_node (node, "smpte-frames-per-second")) != 0) {
930 if ((prop = child->property ("val")) != 0) {
931 set_smpte_type( atof (prop->value().c_str()), smpte_drop_frames );
934 if ((child = find_named_node (node, "smpte-drop-frames")) != 0) {
935 if ((prop = child->property ("val")) != 0) {
936 set_smpte_type( smpte_frames_per_second, (prop->value() == "yes") );
939 if ((child = find_named_node (node, "smpte-offset")) != 0) {
940 if ((prop = child->property ("val")) != 0) {
941 set_smpte_offset( atoi (prop->value().c_str()) );
944 if ((child = find_named_node (node, "smpte-offset-negative")) != 0) {
945 if ((prop = child->property ("val")) != 0) {
946 set_smpte_offset_negative( (prop->value() == "yes") );
949 if ((child = find_named_node (node, "click-sound")) != 0) {
950 if ((prop = child->property ("val")) != 0) {
951 click_sound = prop->value();
954 if ((child = find_named_node (node, "click-emphasis-sound")) != 0) {
955 if ((prop = child->property ("val")) != 0) {
956 click_emphasis_sound = prop->value();
960 if ((child = find_named_node (node, "solo-model")) != 0) {
961 if ((prop = child->property ("val")) != 0) {
962 if (prop->value() == "SoloBus")
963 _solo_model = SoloBus;
965 _solo_model = InverseMute;
969 /* BOOLEAN OPTIONS */
971 if ((child = find_named_node (node, "auto-play")) != 0) {
972 if ((prop = child->property ("val")) != 0) {
973 set_auto_play (prop->value() == "yes");
976 if ((child = find_named_node (node, "auto-input")) != 0) {
977 if ((prop = child->property ("val")) != 0) {
978 set_auto_input (prop->value() == "yes");
981 if ((child = find_named_node (node, "seamless-loop")) != 0) {
982 if ((prop = child->property ("val")) != 0) {
983 set_seamless_loop (prop->value() == "yes");
986 if ((child = find_named_node (node, "punch-in")) != 0) {
987 if ((prop = child->property ("val")) != 0) {
988 set_punch_in (prop->value() == "yes");
991 if ((child = find_named_node (node, "punch-out")) != 0) {
992 if ((prop = child->property ("val")) != 0) {
993 set_punch_out (prop->value() == "yes");
996 if ((child = find_named_node (node, "auto-return")) != 0) {
997 if ((prop = child->property ("val")) != 0) {
998 set_auto_return (prop->value() == "yes");
1001 if ((child = find_named_node (node, "send-mtc")) != 0) {
1002 if ((prop = child->property ("val")) != 0) {
1003 set_send_mtc (prop->value() == "yes");
1006 if ((child = find_named_node (node, "mmc-control")) != 0) {
1007 if ((prop = child->property ("val")) != 0) {
1008 set_mmc_control (prop->value() == "yes");
1011 if ((child = find_named_node (node, "midi-control")) != 0) {
1012 if ((prop = child->property ("val")) != 0) {
1013 set_midi_control (prop->value() == "yes");
1016 if ((child = find_named_node (node, "midi-feedback")) != 0) {
1017 if ((prop = child->property ("val")) != 0) {
1018 set_midi_feedback (prop->value() == "yes");
1021 // Legacy support for <recording-plugins>
1022 if ((child = find_named_node (node, "recording-plugins")) != 0) {
1023 if ((prop = child->property ("val")) != 0) {
1024 set_do_not_record_plugins (prop->value() == "no");
1027 if ((child = find_named_node (node, "do-not-record-plugins")) != 0) {
1028 if ((prop = child->property ("val")) != 0) {
1029 set_do_not_record_plugins (prop->value() == "yes");
1032 if ((child = find_named_node (node, "crossfades-active")) != 0) {
1033 if ((prop = child->property ("val")) != 0) {
1034 set_crossfades_active (prop->value() == "yes");
1037 if ((child = find_named_node (node, "audible-click")) != 0) {
1038 if ((prop = child->property ("val")) != 0) {
1039 set_clicking (prop->value() == "yes");
1043 if ((child = find_named_node (node, "end-marker-is-free")) != 0) {
1044 if ((prop = child->property ("val")) != 0) {
1045 _end_location_is_free = (prop->value() == "yes");
1049 if ((child = find_named_node (node, "layer-model")) != 0) {
1050 if ((prop = child->property ("val")) != 0) {
1051 if (prop->value() == X_("LaterHigher")) {
1052 set_layer_model (LaterHigher);
1053 } else if (prop->value() == X_("AddHigher")) {
1054 set_layer_model (AddHigher);
1056 set_layer_model (MoveAddHigher);
1061 if ((child = find_named_node (node, "xfade-model")) != 0) {
1062 if ((prop = child->property ("val")) != 0) {
1063 if (prop->value() == X_("Short")) {
1064 set_xfade_model (ShortCrossfade);
1066 set_xfade_model (FullCrossfade);
1071 if ((child = find_named_node (node, "short-xfade-length")) != 0) {
1072 if ((prop = child->property ("val")) != 0) {
1073 /* value is stored as a fractional seconds */
1074 float secs = atof (prop->value().c_str());
1075 Crossfade::set_short_xfade_length ((jack_nframes_t) floor (secs * frame_rate()));
1079 if ((child = find_named_node (node, "full-xfades-unmuted")) != 0) {
1080 if ((prop = child->property ("val")) != 0) {
1081 crossfades_active = (prop->value() == "yes");
1087 if ((child = find_named_node (node, "default-fade-steepness")) != 0) {
1088 if ((prop = child->property ("val")) != 0) {
1089 fade_steepness = atof (prop->value().c_str());
1090 have_fade_steepness = true;
1093 if ((child = find_named_node (node, "default-fade-msec")) != 0) {
1094 if ((prop = child->property ("val")) != 0) {
1095 fade_msecs = atof (prop->value().c_str());
1096 have_fade_msecs = true;
1100 if (have_fade_steepness || have_fade_msecs) {
1101 // set_default_fade (fade_steepness, fade_msecs);
1108 Session::get_options () const
1113 LocaleGuard lg (X_("POSIX"));
1115 opthead = new XMLNode ("Options");
1117 SlaveSource src = slave_source ();
1121 src_string = "none";
1127 src_string = "jack";
1130 child = opthead->add_child ("slave");
1131 child->add_property ("type", src_string);
1133 child = opthead->add_child ("send-midi-timecode");
1134 child->add_property ("val", send_midi_timecode?"yes":"no");
1136 child = opthead->add_child ("send-midi-machine-control");
1137 child->add_property ("val", send_midi_machine_control?"yes":"no");
1139 snprintf (buf, sizeof(buf)-1, "%x", (int) input_auto_connect);
1140 child = opthead->add_child ("input-auto-connect");
1141 child->add_property ("val", buf);
1143 snprintf (buf, sizeof(buf)-1, "%x", (int) output_auto_connect);
1144 child = opthead->add_child ("output-auto-connect");
1145 child->add_property ("val", buf);
1147 snprintf (buf, sizeof(buf)-1, "%d", max_level);
1148 child = opthead->add_child ("max-level");
1149 child->add_property ("val", buf);
1151 snprintf (buf, sizeof(buf)-1, "%d", min_level);
1152 child = opthead->add_child ("min-level");
1153 child->add_property ("val", buf);
1155 snprintf (buf, sizeof(buf)-1, "%f", _meter_hold);
1156 child = opthead->add_child ("meter-hold");
1157 child->add_property ("val", buf);
1159 snprintf (buf, sizeof(buf)-1, "%f", _meter_falloff);
1160 child = opthead->add_child ("meter-falloff");
1161 child->add_property ("val", buf);
1163 snprintf (buf, sizeof(buf)-1, "%u", over_length_long);
1164 child = opthead->add_child ("long-over-length");
1165 child->add_property ("val", buf);
1167 snprintf (buf, sizeof(buf)-1, "%u", over_length_short);
1168 child = opthead->add_child ("short-over-length");
1169 child->add_property ("val", buf);
1171 snprintf (buf, sizeof(buf)-1, "%f", shuttle_speed_factor);
1172 child = opthead->add_child ("shuttle-speed-factor");
1173 child->add_property ("val", buf);
1175 snprintf (buf, sizeof(buf)-1, "%f", shuttle_speed_threshold);
1176 child = opthead->add_child ("shuttle-speed-threshold");
1177 child->add_property ("val", buf);
1179 snprintf (buf, sizeof(buf)-1, "%f", rf_speed);
1180 child = opthead->add_child ("rf-speed");
1181 child->add_property ("val", buf);
1183 snprintf (buf, sizeof(buf)-1, "%.2f", smpte_frames_per_second);
1184 child = opthead->add_child ("smpte-frames-per-second");
1185 child->add_property ("val", buf);
1187 child = opthead->add_child ("smpte-drop-frames");
1188 child->add_property ("val", smpte_drop_frames ? "yes" : "no");
1190 snprintf (buf, sizeof(buf)-1, "%u", smpte_offset ());
1191 child = opthead->add_child ("smpte-offset");
1192 child->add_property ("val", buf);
1194 child = opthead->add_child ("smpte-offset-negative");
1195 child->add_property ("val", smpte_offset_negative () ? "yes" : "no");
1197 child = opthead->add_child ("edit-mode");
1198 switch (_edit_mode) {
1200 child->add_property ("val", "splice");
1204 child->add_property ("val", "slide");
1208 child = opthead->add_child ("auto-play");
1209 child->add_property ("val", get_auto_play () ? "yes" : "no");
1210 child = opthead->add_child ("auto-input");
1211 child->add_property ("val", get_auto_input () ? "yes" : "no");
1212 child = opthead->add_child ("seamless-loop");
1213 child->add_property ("val", get_seamless_loop () ? "yes" : "no");
1214 child = opthead->add_child ("punch-in");
1215 child->add_property ("val", get_punch_in () ? "yes" : "no");
1216 child = opthead->add_child ("punch-out");
1217 child->add_property ("val", get_punch_out () ? "yes" : "no");
1218 child = opthead->add_child ("all-safe");
1219 child->add_property ("val", get_all_safe () ? "yes" : "no");
1220 child = opthead->add_child ("auto-return");
1221 child->add_property ("val", get_auto_return () ? "yes" : "no");
1222 child = opthead->add_child ("mmc-control");
1223 child->add_property ("val", get_mmc_control () ? "yes" : "no");
1224 child = opthead->add_child ("midi-control");
1225 child->add_property ("val", get_midi_control () ? "yes" : "no");
1226 child = opthead->add_child ("midi-feedback");
1227 child->add_property ("val", get_midi_feedback () ? "yes" : "no");
1228 child = opthead->add_child ("do-not-record-plugins");
1229 child->add_property ("val", get_do_not_record_plugins () ? "yes" : "no");
1230 child = opthead->add_child ("auto-crossfade");
1231 child->add_property ("val", get_crossfades_active () ? "yes" : "no");
1232 child = opthead->add_child ("audible-click");
1233 child->add_property ("val", get_clicking () ? "yes" : "no");
1234 child = opthead->add_child ("end-marker-is-free");
1235 child->add_property ("val", _end_location_is_free ? "yes" : "no");
1237 if (click_sound.length()) {
1238 child = opthead->add_child ("click-sound");
1239 child->add_property ("val", click_sound);
1242 if (click_emphasis_sound.length()) {
1243 child = opthead->add_child ("click-emphasis-sound");
1244 child->add_property ("val", click_emphasis_sound);
1247 child = opthead->add_child ("solo-model");
1248 child->add_property ("val", _solo_model == SoloBus ? "SoloBus" : "InverseMute");
1250 child = opthead->add_child ("layer-model");
1251 switch (layer_model) {
1253 child->add_property ("val", X_("LaterHigher"));
1256 child->add_property ("val", X_("MoveAddHigher"));
1259 child->add_property ("val", X_("AddHigher"));
1263 child = opthead->add_child ("xfade-model");
1264 switch (xfade_model) {
1266 child->add_property ("val", X_("Full"));
1268 case ShortCrossfade:
1269 child->add_property ("val", X_("Short"));
1272 child = opthead->add_child ("short-xfade-length");
1273 /* store as fractions of a second */
1274 snprintf (buf, sizeof(buf)-1, "%f",
1275 (float) Crossfade::short_xfade_length() / frame_rate());
1276 child->add_property ("val", buf);
1278 child = opthead->add_child ("full-xfades-unmuted");
1279 child->add_property ("val", crossfades_active ? "yes" : "no");
1285 Session::get_state()
1291 Session::get_template()
1293 /* if we don't disable rec-enable, diskstreams
1294 will believe they need to store their capture
1295 sources in their state node.
1298 disable_record (false);
1300 return state(false);
1304 Session::state(bool full_state)
1306 XMLNode* node = new XMLNode("Session");
1309 // store libardour version, just in case
1311 snprintf(buf, sizeof(buf)-1, "%d.%d.%d",
1312 libardour_major_version, libardour_minor_version, libardour_micro_version);
1313 node->add_property("version", string(buf));
1315 /* store configuration settings */
1319 /* store the name */
1320 node->add_property ("name", _name);
1322 if (session_dirs.size() > 1) {
1326 vector<space_and_path>::iterator i = session_dirs.begin();
1327 vector<space_and_path>::iterator next;
1329 ++i; /* skip the first one */
1333 while (i != session_dirs.end()) {
1337 if (next != session_dirs.end()) {
1347 child = node->add_child ("Path");
1348 child->add_content (p);
1352 /* save the ID counter */
1354 snprintf (buf, sizeof (buf), "%" PRIu64, ID::counter());
1355 node->add_property ("id-counter", buf);
1357 /* various options */
1359 node->add_child_nocopy (get_options());
1361 child = node->add_child ("Sources");
1364 Glib::Mutex::Lock sl (source_lock);
1366 for (SourceMap::iterator siter = sources.begin(); siter != sources.end(); ++siter) {
1368 /* Don't save information about AudioFileSources that are empty */
1370 boost::shared_ptr<AudioFileSource> fs;
1372 if ((fs = boost::dynamic_pointer_cast<AudioFileSource> (siter->second)) != 0) {
1373 boost::shared_ptr<DestructiveFileSource> dfs = boost::dynamic_pointer_cast<DestructiveFileSource> (fs);
1375 /* Don't save sources that are empty, unless they're destructive (which are OK
1376 if they are empty, because we will re-use them every time.)
1378 if ( ! dfs && siter->second->length() == 0) {
1383 child->add_child_nocopy (siter->second->get_state());
1387 child = node->add_child ("Regions");
1390 Glib::Mutex::Lock rl (region_lock);
1392 for (RegionList::const_iterator i = regions.begin(); i != regions.end(); ++i) {
1394 /* only store regions not attached to playlists */
1396 if (i->second->playlist() == 0) {
1397 child->add_child_nocopy (i->second->state (true));
1402 child = node->add_child ("DiskStreams");
1405 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
1406 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
1407 if (!(*i)->hidden()) {
1408 child->add_child_nocopy ((*i)->get_state());
1413 node->add_child_nocopy (_locations.get_state());
1415 child = node->add_child ("Connections");
1417 Glib::Mutex::Lock lm (connection_lock);
1418 for (ConnectionList::iterator i = _connections.begin(); i != _connections.end(); ++i) {
1419 if (!(*i)->system_dependent()) {
1420 child->add_child_nocopy ((*i)->get_state());
1425 child = node->add_child ("Routes");
1427 boost::shared_ptr<RouteList> r = routes.reader ();
1429 RoutePublicOrderSorter cmp;
1430 RouteList public_order (*r);
1431 public_order.sort (cmp);
1433 for (RouteList::iterator i = public_order.begin(); i != public_order.end(); ++i) {
1434 if (!(*i)->hidden()) {
1436 child->add_child_nocopy ((*i)->get_state());
1438 child->add_child_nocopy ((*i)->get_template());
1445 child = node->add_child ("EditGroups");
1446 for (list<RouteGroup *>::iterator i = edit_groups.begin(); i != edit_groups.end(); ++i) {
1447 child->add_child_nocopy ((*i)->get_state());
1450 child = node->add_child ("MixGroups");
1451 for (list<RouteGroup *>::iterator i = mix_groups.begin(); i != mix_groups.end(); ++i) {
1452 child->add_child_nocopy ((*i)->get_state());
1455 child = node->add_child ("Playlists");
1456 for (PlaylistList::iterator i = playlists.begin(); i != playlists.end(); ++i) {
1457 if (!(*i)->hidden()) {
1458 if (!(*i)->empty()) {
1460 child->add_child_nocopy ((*i)->get_state());
1462 child->add_child_nocopy ((*i)->get_template());
1468 child = node->add_child ("UnusedPlaylists");
1469 for (PlaylistList::iterator i = unused_playlists.begin(); i != unused_playlists.end(); ++i) {
1470 if (!(*i)->hidden()) {
1471 if (!(*i)->empty()) {
1473 child->add_child_nocopy ((*i)->get_state());
1475 child->add_child_nocopy ((*i)->get_template());
1483 child = node->add_child ("Click");
1484 child->add_child_nocopy (_click_io->state (full_state));
1488 child = node->add_child ("NamedSelections");
1489 for (NamedSelectionList::iterator i = named_selections.begin(); i != named_selections.end(); ++i) {
1491 child->add_child_nocopy ((*i)->get_state());
1496 node->add_child_nocopy (_tempo_map->get_state());
1499 node->add_child_copy (*_extra_xml);
1506 Session::set_state (const XMLNode& node)
1510 const XMLProperty* prop;
1513 _state_of_the_state = StateOfTheState (_state_of_the_state|CannotSave);
1515 if (node.name() != X_("Session")){
1516 fatal << _("programming error: Session: incorrect XML node sent to set_state()") << endmsg;
1520 StateManager::prohibit_save ();
1522 if ((prop = node.property ("name")) != 0) {
1523 _name = prop->value ();
1526 if ((prop = node.property (X_("id-counter"))) != 0) {
1528 sscanf (prop->value().c_str(), "%" PRIu64, &x);
1529 ID::init_counter (x);
1531 /* old sessions used a timebased counter, so fake
1532 the startup ID counter based on a standard
1537 ID::init_counter (now);
1541 IO::disable_ports ();
1542 IO::disable_connecting ();
1544 /* Object loading order:
1561 if (use_config_midi_ports ()) {
1564 if ((child = find_named_node (node, "Path")) != 0) {
1565 /* XXX this XML content stuff horrible API design */
1566 string raid_path = _path + ':' + child->children().front()->content();
1567 setup_raid_path (raid_path);
1569 /* the path is already set */
1572 if ((child = find_named_node (node, "extra")) != 0) {
1573 _extra_xml = new XMLNode (*child);
1576 if ((child = find_named_node (node, "Options")) == 0) {
1577 error << _("Session: XML state has no options section") << endmsg;
1578 } else if (load_options (*child)) {
1581 if ((child = find_named_node (node, "Sources")) == 0) {
1582 error << _("Session: XML state has no sources section") << endmsg;
1584 } else if (load_sources (*child)) {
1588 if ((child = find_named_node (node, "Regions")) == 0) {
1589 error << _("Session: XML state has no Regions section") << endmsg;
1591 } else if (load_regions (*child)) {
1595 if ((child = find_named_node (node, "Playlists")) == 0) {
1596 error << _("Session: XML state has no playlists section") << endmsg;
1598 } else if (load_playlists (*child)) {
1602 if ((child = find_named_node (node, "UnusedPlaylists")) == 0) {
1604 } else if (load_unused_playlists (*child)) {
1608 if ((child = find_named_node (node, "NamedSelections")) != 0) {
1609 if (load_named_selections (*child)) {
1614 if ((child = find_named_node (node, "DiskStreams")) == 0) {
1615 error << _("Session: XML state has no diskstreams section") << endmsg;
1617 } else if (load_diskstreams (*child)) {
1621 if ((child = find_named_node (node, "Connections")) == 0) {
1622 error << _("Session: XML state has no connections section") << endmsg;
1624 } else if (load_connections (*child)) {
1628 if ((child = find_named_node (node, "Locations")) == 0) {
1629 error << _("Session: XML state has no locations section") << endmsg;
1631 } else if (_locations.set_state (*child)) {
1637 if ((location = _locations.auto_loop_location()) != 0) {
1638 set_auto_loop_location (location);
1641 if ((location = _locations.auto_punch_location()) != 0) {
1642 set_auto_punch_location (location);
1645 if ((location = _locations.end_location()) == 0) {
1646 _locations.add (end_location);
1648 delete end_location;
1649 end_location = location;
1652 if ((location = _locations.start_location()) == 0) {
1653 _locations.add (start_location);
1655 delete start_location;
1656 start_location = location;
1659 _locations.save_state (_("initial state"));
1661 if ((child = find_named_node (node, "EditGroups")) == 0) {
1662 error << _("Session: XML state has no edit groups section") << endmsg;
1664 } else if (load_edit_groups (*child)) {
1668 if ((child = find_named_node (node, "MixGroups")) == 0) {
1669 error << _("Session: XML state has no mix groups section") << endmsg;
1671 } else if (load_mix_groups (*child)) {
1675 if ((child = find_named_node (node, "TempoMap")) == 0) {
1676 error << _("Session: XML state has no Tempo Map section") << endmsg;
1678 } else if (_tempo_map->set_state (*child)) {
1682 if ((child = find_named_node (node, "Routes")) == 0) {
1683 error << _("Session: XML state has no routes section") << endmsg;
1685 } else if (load_routes (*child)) {
1689 if ((child = find_named_node (node, "Click")) == 0) {
1690 warning << _("Session: XML state has no click section") << endmsg;
1691 } else if (_click_io) {
1692 _click_io->set_state (*child);
1695 /* OK, now we can set edit mode */
1697 set_edit_mode (pending_edit_mode);
1699 /* here beginneth the second phase ... */
1701 StateReady (); /* EMIT SIGNAL */
1703 _state_of_the_state = Clean;
1705 StateManager::allow_save (_("initial state"), true);
1707 if (state_was_pending) {
1708 save_state (_current_snapshot_name);
1709 remove_pending_capture_state ();
1710 state_was_pending = false;
1716 /* we failed, re-enable state saving but don't actually save internal state */
1717 StateManager::allow_save (X_("ignored"), false);
1722 Session::load_routes (const XMLNode& node)
1725 XMLNodeConstIterator niter;
1726 RouteList new_routes;
1728 nlist = node.children();
1732 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1734 boost::shared_ptr<Route> route (XMLRouteFactory (**niter));
1737 error << _("Session: cannot create Route from XML description.") << endmsg;
1741 new_routes.push_back (route);
1744 add_routes (new_routes);
1749 boost::shared_ptr<Route>
1750 Session::XMLRouteFactory (const XMLNode& node)
1752 if (node.name() != "Route") {
1753 return boost::shared_ptr<Route> ((Route*) 0);
1756 bool has_diskstream = (node.property ("diskstream") != 0 || node.property ("diskstream-id") != 0);
1758 DataType type = DataType::AUDIO;
1759 const XMLProperty* prop = node.property("default-type");
1761 type = DataType(prop->value());
1763 assert(type != DataType::NIL);
1765 if (has_diskstream) {
1766 if (type == DataType::AUDIO) {
1767 boost::shared_ptr<Route> ret (new AudioTrack (*this, node));
1770 boost::shared_ptr<Route> ret (new MidiTrack (*this, node));
1774 boost::shared_ptr<Route> ret (new Route (*this, node));
1780 Session::load_regions (const XMLNode& node)
1783 XMLNodeConstIterator niter;
1784 boost::shared_ptr<Region> region;
1786 nlist = node.children();
1790 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1791 if ((region = XMLRegionFactory (**niter, false)) == 0) {
1792 error << _("Session: cannot create Region from XML description.") << endmsg;
1799 boost::shared_ptr<Region>
1800 Session::XMLRegionFactory (const XMLNode& node, bool full)
1802 const XMLProperty* type = node.property("type");
1806 if ( !type || type->value() == "audio" ) {
1808 return boost::shared_ptr<Region>(XMLAudioRegionFactory (node, full));
1810 } else if (type->value() == "midi") {
1812 return boost::shared_ptr<Region>(XMLMidiRegionFactory (node, full));
1816 } catch (failed_constructor& err) {
1817 return boost::shared_ptr<Region> ();
1820 return boost::shared_ptr<Region> ();
1823 boost::shared_ptr<AudioRegion>
1824 Session::XMLAudioRegionFactory (const XMLNode& node, bool full)
1826 const XMLProperty* prop;
1827 boost::shared_ptr<Source> source;
1828 boost::shared_ptr<AudioSource> as;
1830 uint32_t nchans = 1;
1833 if (node.name() != X_("Region")) {
1834 return boost::shared_ptr<AudioRegion>();
1837 if ((prop = node.property (X_("channels"))) != 0) {
1838 nchans = atoi (prop->value().c_str());
1842 if ((prop = node.property (X_("source-0"))) == 0) {
1843 if ((prop = node.property ("source")) == 0) {
1844 error << _("Session: XMLNode describing a AudioRegion is incomplete (no source)") << endmsg;
1845 return boost::shared_ptr<AudioRegion>();
1849 PBD::ID s_id (prop->value());
1851 if ((source = source_by_id (s_id)) == 0) {
1852 error << string_compose(_("Session: XMLNode describing a AudioRegion references an unknown source id =%1"), s_id) << endmsg;
1853 return boost::shared_ptr<AudioRegion>();
1856 as = boost::dynamic_pointer_cast<AudioSource>(source);
1858 error << string_compose(_("Session: XMLNode describing a AudioRegion references a non-audio source id =%1"), s_id) << endmsg;
1859 return boost::shared_ptr<AudioRegion>();
1862 sources.push_back (as);
1864 /* pickup other channels */
1866 for (uint32_t n=1; n < nchans; ++n) {
1867 snprintf (buf, sizeof(buf), X_("source-%d"), n);
1868 if ((prop = node.property (buf)) != 0) {
1870 PBD::ID id2 (prop->value());
1872 if ((source = source_by_id (id2)) == 0) {
1873 error << string_compose(_("Session: XMLNode describing a AudioRegion references an unknown source id =%1"), id2) << endmsg;
1874 return boost::shared_ptr<AudioRegion>();
1877 as = boost::dynamic_pointer_cast<AudioSource>(source);
1879 error << string_compose(_("Session: XMLNode describing a AudioRegion references a non-audio source id =%1"), id2) << endmsg;
1880 return boost::shared_ptr<AudioRegion>();
1882 sources.push_back (as);
1887 boost::shared_ptr<AudioRegion> region (boost::dynamic_pointer_cast<AudioRegion> (RegionFactory::create (sources, node)));
1892 catch (failed_constructor& err) {
1893 return boost::shared_ptr<AudioRegion>();
1897 boost::shared_ptr<MidiRegion>
1898 Session::XMLMidiRegionFactory (const XMLNode& node, bool full)
1900 const XMLProperty* prop;
1901 boost::shared_ptr<Source> source;
1902 boost::shared_ptr<MidiSource> ms;
1903 MidiRegion::SourceList sources;
1904 uint32_t nchans = 1;
1906 if (node.name() != X_("Region")) {
1907 return boost::shared_ptr<MidiRegion>();
1910 if ((prop = node.property (X_("channels"))) != 0) {
1911 nchans = atoi (prop->value().c_str());
1914 // Multiple midi channels? that's just crazy talk
1915 assert(nchans == 1);
1917 if ((prop = node.property (X_("source-0"))) == 0) {
1918 if ((prop = node.property ("source")) == 0) {
1919 error << _("Session: XMLNode describing a MidiRegion is incomplete (no source)") << endmsg;
1920 return boost::shared_ptr<MidiRegion>();
1924 PBD::ID s_id (prop->value());
1926 if ((source = source_by_id (s_id)) == 0) {
1927 error << string_compose(_("Session: XMLNode describing a MidiRegion references an unknown source id =%1"), s_id) << endmsg;
1928 return boost::shared_ptr<MidiRegion>();
1931 ms = boost::dynamic_pointer_cast<MidiSource>(source);
1933 error << string_compose(_("Session: XMLNode describing a MidiRegion references a non-midi source id =%1"), s_id) << endmsg;
1934 return boost::shared_ptr<MidiRegion>();
1937 sources.push_back (ms);
1940 boost::shared_ptr<MidiRegion> region (boost::dynamic_pointer_cast<MidiRegion> (RegionFactory::create (sources, node)));
1944 catch (failed_constructor& err) {
1945 return boost::shared_ptr<MidiRegion>();
1950 Session::get_sources_as_xml ()
1953 XMLNode* node = new XMLNode (X_("Sources"));
1954 Glib::Mutex::Lock lm (source_lock);
1956 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ++i) {
1957 node->add_child_nocopy (i->second->get_state());
1960 /* XXX get MIDI and other sources here */
1966 Session::path_from_region_name (string name, string identifier)
1968 char buf[PATH_MAX+1];
1970 string dir = discover_best_sound_dir ();
1972 for (n = 0; n < 999999; ++n) {
1973 if (identifier.length()) {
1974 snprintf (buf, sizeof(buf), "%s/%s%s%" PRIu32 ".wav", dir.c_str(), name.c_str(),
1975 identifier.c_str(), n);
1977 snprintf (buf, sizeof(buf), "%s/%s-%" PRIu32 ".wav", dir.c_str(), name.c_str(), n);
1979 if (access (buf, F_OK) != 0) {
1989 Session::load_sources (const XMLNode& node)
1992 XMLNodeConstIterator niter;
1993 boost::shared_ptr<Source> source;
1995 nlist = node.children();
1999 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2001 if ((source = XMLSourceFactory (**niter)) == 0) {
2002 error << _("Session: cannot create Source from XML description.") << endmsg;
2009 boost::shared_ptr<Source>
2010 Session::XMLSourceFactory (const XMLNode& node)
2013 if (node.name() != "Source") {
2014 return boost::shared_ptr<Source>();
2018 return SourceFactory::create (node);
2021 catch (failed_constructor& err) {
2022 error << _("Found a sound file that cannot be used by Ardour. Talk to the progammers.") << endmsg;
2023 return boost::shared_ptr<Source>();
2028 Session::save_template (string template_name)
2031 string xml_path, bak_path, template_path;
2033 if (_state_of_the_state & CannotSave) {
2038 string dir = template_dir();
2040 if ((dp = opendir (dir.c_str()))) {
2043 if (mkdir (dir.c_str(), S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH)<0) {
2044 error << string_compose(_("Could not create mix templates directory \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
2049 tree.set_root (&get_template());
2052 xml_path += template_name;
2053 xml_path += _template_suffix;
2055 ifstream in(xml_path.c_str());
2058 warning << string_compose(_("Template \"%1\" already exists - new version not created"), template_name) << endmsg;
2064 if (!tree.write (xml_path)) {
2065 error << _("mix template not saved") << endmsg;
2073 Session::rename_template (string old_name, string new_name)
2075 string old_path = template_dir() + old_name + _template_suffix;
2076 string new_path = template_dir() + new_name + _template_suffix;
2078 return rename (old_path.c_str(), new_path.c_str());
2082 Session::delete_template (string name)
2084 string template_path = template_dir();
2085 template_path += name;
2086 template_path += _template_suffix;
2088 return remove (template_path.c_str());
2092 Session::refresh_disk_space ()
2095 struct statfs statfsbuf;
2096 vector<space_and_path>::iterator i;
2097 Glib::Mutex::Lock lm (space_lock);
2100 /* get freespace on every FS that is part of the session path */
2102 _total_free_4k_blocks = 0;
2104 for (i = session_dirs.begin(); i != session_dirs.end(); ++i) {
2105 statfs ((*i).path.c_str(), &statfsbuf);
2107 scale = statfsbuf.f_bsize/4096.0;
2109 (*i).blocks = (uint32_t) floor (statfsbuf.f_bavail * scale);
2110 _total_free_4k_blocks += (*i).blocks;
2116 Session::ensure_sound_dir (string path, string& result)
2121 /* Ensure that the parent directory exists */
2123 if (mkdir (path.c_str(), 0775)) {
2124 if (errno != EEXIST) {
2125 error << string_compose(_("cannot create session directory \"%1\"; ignored"), path) << endmsg;
2130 /* Ensure that the sounds directory exists */
2134 result += sound_dir_name;
2136 if (mkdir (result.c_str(), 0775)) {
2137 if (errno != EEXIST) {
2138 error << string_compose(_("cannot create sounds directory \"%1\"; ignored"), result) << endmsg;
2145 dead += dead_sound_dir_name;
2147 if (mkdir (dead.c_str(), 0775)) {
2148 if (errno != EEXIST) {
2149 error << string_compose(_("cannot create dead sounds directory \"%1\"; ignored"), dead) << endmsg;
2156 peak += peak_dir_name;
2158 if (mkdir (peak.c_str(), 0775)) {
2159 if (errno != EEXIST) {
2160 error << string_compose(_("cannot create peak file directory \"%1\"; ignored"), peak) << endmsg;
2165 /* callers expect this to be terminated ... */
2172 Session::discover_best_sound_dir (bool destructive)
2174 vector<space_and_path>::iterator i;
2177 /* destructive files all go into the same place */
2183 /* handle common case without system calls */
2185 if (session_dirs.size() == 1) {
2189 /* OK, here's the algorithm we're following here:
2191 We want to select which directory to use for
2192 the next file source to be created. Ideally,
2193 we'd like to use a round-robin process so as to
2194 get maximum performance benefits from splitting
2195 the files across multiple disks.
2197 However, in situations without much diskspace, an
2198 RR approach may end up filling up a filesystem
2199 with new files while others still have space.
2200 Its therefore important to pay some attention to
2201 the freespace in the filesystem holding each
2202 directory as well. However, if we did that by
2203 itself, we'd keep creating new files in the file
2204 system with the most space until it was as full
2205 as all others, thus negating any performance
2206 benefits of this RAID-1 like approach.
2208 So, we use a user-configurable space threshold. If
2209 there are at least 2 filesystems with more than this
2210 much space available, we use RR selection between them.
2211 If not, then we pick the filesystem with the most space.
2213 This gets a good balance between the two
2217 refresh_disk_space ();
2219 int free_enough = 0;
2221 for (i = session_dirs.begin(); i != session_dirs.end(); ++i) {
2222 if ((*i).blocks * 4096 >= Config->get_disk_choice_space_threshold()) {
2227 if (free_enough >= 2) {
2229 bool found_it = false;
2231 /* use RR selection process, ensuring that the one
2235 i = last_rr_session_dir;
2238 if (++i == session_dirs.end()) {
2239 i = session_dirs.begin();
2242 if ((*i).blocks * 4096 >= Config->get_disk_choice_space_threshold()) {
2243 if (ensure_sound_dir ((*i).path, result) == 0) {
2244 last_rr_session_dir = i;
2250 } while (i != last_rr_session_dir);
2253 result = sound_dir();
2258 /* pick FS with the most freespace (and that
2259 seems to actually work ...)
2262 vector<space_and_path> sorted;
2263 space_and_path_ascending_cmp cmp;
2265 sorted = session_dirs;
2266 sort (sorted.begin(), sorted.end(), cmp);
2268 for (i = sorted.begin(); i != sorted.end(); ++i) {
2269 if (ensure_sound_dir ((*i).path, result) == 0) {
2270 last_rr_session_dir = i;
2275 /* if the above fails, fall back to the most simplistic solution */
2277 if (i == sorted.end()) {
2286 Session::load_playlists (const XMLNode& node)
2289 XMLNodeConstIterator niter;
2292 nlist = node.children();
2296 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2298 if ((playlist = XMLPlaylistFactory (**niter)) == 0) {
2299 error << _("Session: cannot create Playlist from XML description.") << endmsg;
2307 Session::load_unused_playlists (const XMLNode& node)
2310 XMLNodeConstIterator niter;
2313 nlist = node.children();
2317 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2319 if ((playlist = XMLPlaylistFactory (**niter)) == 0) {
2320 error << _("Session: cannot create Playlist from XML description.") << endmsg;
2324 // now manually untrack it
2326 track_playlist (playlist, false);
2333 Session::XMLPlaylistFactory (const XMLNode& node)
2335 const XMLProperty* type = node.property("type");
2339 if ( !type || type->value() == "audio" ) {
2341 return new AudioPlaylist (*this, node);
2343 } else if (type->value() == "midi") {
2345 return new MidiPlaylist (*this, node);
2349 } catch (failed_constructor& err) {
2357 Session::load_named_selections (const XMLNode& node)
2360 XMLNodeConstIterator niter;
2363 nlist = node.children();
2367 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2369 if ((ns = XMLNamedSelectionFactory (**niter)) == 0) {
2370 error << _("Session: cannot create Named Selection from XML description.") << endmsg;
2378 Session::XMLNamedSelectionFactory (const XMLNode& node)
2381 return new NamedSelection (*this, node);
2384 catch (failed_constructor& err) {
2390 Session::dead_sound_dir () const
2393 res += dead_sound_dir_name;
2399 Session::sound_dir () const
2402 res += sound_dir_name;
2408 Session::tape_dir () const
2411 res += tape_dir_name;
2417 Session::peak_dir () const
2420 res += peak_dir_name;
2426 Session::automation_dir () const
2429 res += "automation/";
2434 Session::template_dir ()
2436 string path = get_user_ardour_path();
2437 path += "templates/";
2443 Session::suffixed_search_path (string suffix, bool data)
2447 path += get_user_ardour_path();
2448 if (path[path.length()-1] != ':') {
2453 path += get_system_data_path();
2455 path += get_system_module_path();
2458 vector<string> split_path;
2460 split (path, split_path, ':');
2463 for (vector<string>::iterator i = split_path.begin(); i != split_path.end(); ++i) {
2468 if (distance (i, split_path.end()) != 1) {
2477 Session::template_path ()
2479 return suffixed_search_path (X_("templates"), true);
2483 Session::control_protocol_path ()
2485 return suffixed_search_path (X_("surfaces"), false);
2489 Session::load_connections (const XMLNode& node)
2491 XMLNodeList nlist = node.children();
2492 XMLNodeConstIterator niter;
2496 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2497 if ((*niter)->name() == "InputConnection") {
2498 add_connection (new ARDOUR::InputConnection (**niter));
2499 } else if ((*niter)->name() == "OutputConnection") {
2500 add_connection (new ARDOUR::OutputConnection (**niter));
2502 error << string_compose(_("Unknown node \"%1\" found in Connections list from state file"), (*niter)->name()) << endmsg;
2511 Session::load_edit_groups (const XMLNode& node)
2513 return load_route_groups (node, true);
2517 Session::load_mix_groups (const XMLNode& node)
2519 return load_route_groups (node, false);
2523 Session::load_route_groups (const XMLNode& node, bool edit)
2525 XMLNodeList nlist = node.children();
2526 XMLNodeConstIterator niter;
2531 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2532 if ((*niter)->name() == "RouteGroup") {
2534 rg = add_edit_group ("");
2535 rg->set_state (**niter);
2537 rg = add_mix_group ("");
2538 rg->set_state (**niter);
2547 state_file_filter (const string &str, void *arg)
2549 return (str.length() > strlen(Session::statefile_suffix()) &&
2550 str.find (Session::statefile_suffix()) == (str.length() - strlen (Session::statefile_suffix())));
2554 bool operator()(const string* a, const string* b) {
2560 remove_end(string* state)
2562 string statename(*state);
2564 string::size_type start,end;
2565 if ((start = statename.find_last_of ('/')) != string::npos) {
2566 statename = statename.substr (start+1);
2569 if ((end = statename.rfind(".ardour")) == string::npos) {
2570 end = statename.length();
2573 return new string(statename.substr (0, end));
2577 Session::possible_states (string path)
2579 PathScanner scanner;
2580 vector<string*>* states = scanner (path, state_file_filter, 0, false, false);
2582 transform(states->begin(), states->end(), states->begin(), remove_end);
2585 sort (states->begin(), states->end(), cmp);
2591 Session::possible_states () const
2593 return possible_states(_path);
2597 Session::auto_save()
2599 save_state (_current_snapshot_name);
2603 Session::add_edit_group (string name)
2605 RouteGroup* rg = new RouteGroup (*this, name);
2606 edit_groups.push_back (rg);
2607 edit_group_added (rg); /* EMIT SIGNAL */
2613 Session::add_mix_group (string name)
2615 RouteGroup* rg = new RouteGroup (*this, name, RouteGroup::Relative);
2616 mix_groups.push_back (rg);
2617 mix_group_added (rg); /* EMIT SIGNAL */
2623 Session::remove_edit_group (RouteGroup& rg)
2625 list<RouteGroup*>::iterator i;
2627 if ((i = find (edit_groups.begin(), edit_groups.end(), &rg)) != edit_groups.end()) {
2628 (*i)->apply (&Route::drop_edit_group, this);
2629 edit_groups.erase (i);
2630 edit_group_removed (); /* EMIT SIGNAL */
2637 Session::remove_mix_group (RouteGroup& rg)
2639 list<RouteGroup*>::iterator i;
2641 if ((i = find (mix_groups.begin(), mix_groups.end(), &rg)) != mix_groups.end()) {
2642 (*i)->apply (&Route::drop_mix_group, this);
2643 mix_groups.erase (i);
2644 mix_group_removed (); /* EMIT SIGNAL */
2651 Session::mix_group_by_name (string name)
2653 list<RouteGroup *>::iterator i;
2655 for (i = mix_groups.begin(); i != mix_groups.end(); ++i) {
2656 if ((*i)->name() == name) {
2664 Session::edit_group_by_name (string name)
2666 list<RouteGroup *>::iterator i;
2668 for (i = edit_groups.begin(); i != edit_groups.end(); ++i) {
2669 if ((*i)->name() == name) {
2677 Session::set_meter_hold (float val)
2680 MeterHoldChanged(); // emit
2684 Session::set_meter_falloff (float val)
2686 _meter_falloff = val;
2687 MeterFalloffChanged(); // emit
2692 Session::begin_reversible_command (string name)
2694 current_trans = new UndoTransaction;
2695 current_trans->set_name (name);
2699 Session::commit_reversible_command (Command *cmd)
2704 current_trans->add_command (cmd);
2707 gettimeofday (&now, 0);
2708 current_trans->set_timestamp (now);
2710 history.add (current_trans);
2713 Session::GlobalRouteBooleanState
2714 Session::get_global_route_boolean (bool (Route::*method)(void) const)
2716 GlobalRouteBooleanState s;
2717 boost::shared_ptr<RouteList> r = routes.reader ();
2719 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
2720 if (!(*i)->hidden()) {
2721 RouteBooleanState v;
2724 Route* r = (*i).get();
2725 v.second = (r->*method)();
2734 Session::GlobalRouteMeterState
2735 Session::get_global_route_metering ()
2737 GlobalRouteMeterState s;
2738 boost::shared_ptr<RouteList> r = routes.reader ();
2740 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
2741 if (!(*i)->hidden()) {
2745 v.second = (*i)->meter_point();
2755 Session::set_global_route_metering (GlobalRouteMeterState s, void* arg)
2757 for (GlobalRouteMeterState::iterator i = s.begin(); i != s.end(); ++i) {
2758 i->first->set_meter_point (i->second, arg);
2763 Session::set_global_route_boolean (GlobalRouteBooleanState s, void (Route::*method)(bool, void*), void* arg)
2765 for (GlobalRouteBooleanState::iterator i = s.begin(); i != s.end(); ++i) {
2766 Route* r = i->first.get();
2767 (r->*method) (i->second, arg);
2772 Session::set_global_mute (GlobalRouteBooleanState s, void* src)
2774 set_global_route_boolean (s, &Route::set_mute, src);
2778 Session::set_global_solo (GlobalRouteBooleanState s, void* src)
2780 set_global_route_boolean (s, &Route::set_solo, src);
2784 Session::set_global_record_enable (GlobalRouteBooleanState s, void* src)
2786 set_global_route_boolean (s, &Route::set_record_enable, src);
2791 Session::global_mute_memento (void* src)
2793 return sigc::bind (mem_fun (*this, &Session::set_global_mute), get_global_route_boolean (&Route::muted), src);
2797 Session::global_metering_memento (void* src)
2799 return sigc::bind (mem_fun (*this, &Session::set_global_route_metering), get_global_route_metering (), src);
2803 Session::global_solo_memento (void* src)
2805 return sigc::bind (mem_fun (*this, &Session::set_global_solo), get_global_route_boolean (&Route::soloed), src);
2809 Session::global_record_enable_memento (void* src)
2811 return sigc::bind (mem_fun (*this, &Session::set_global_record_enable), get_global_route_boolean (&Route::record_enabled), src);
2816 template_filter (const string &str, void *arg)
2818 return (str.length() > strlen(Session::template_suffix()) &&
2819 str.find (Session::template_suffix()) == (str.length() - strlen (Session::template_suffix())));
2823 Session::get_template_list (list<string> &template_names)
2825 vector<string *> *templates;
2826 PathScanner scanner;
2829 path = template_path ();
2831 templates = scanner (path, template_filter, 0, false, true);
2833 vector<string*>::iterator i;
2834 for (i = templates->begin(); i != templates->end(); ++i) {
2835 string fullpath = *(*i);
2838 start = fullpath.find_last_of ('/') + 1;
2839 if ((end = fullpath.find_last_of ('.')) <0) {
2840 end = fullpath.length();
2843 template_names.push_back(fullpath.substr(start, (end-start)));
2848 Session::read_favorite_dirs (FavoriteDirs & favs)
2850 string path = get_user_ardour_path();
2851 path += "/favorite_dirs";
2853 ifstream fav (path.c_str());
2858 if (errno != ENOENT) {
2859 //error << string_compose (_("cannot open favorite file %1 (%2)"), path, strerror (errno)) << endmsg;
2870 getline(fav, newfav);
2876 favs.push_back (newfav);
2883 Session::write_favorite_dirs (FavoriteDirs & favs)
2885 string path = get_user_ardour_path();
2886 path += "/favorite_dirs";
2888 ofstream fav (path.c_str());
2894 for (FavoriteDirs::iterator i = favs.begin(); i != favs.end(); ++i) {
2895 fav << (*i) << endl;
2902 accept_all_non_peak_files (const string& path, void *arg)
2904 return (path.length() > 5 && path.find (".peak") != (path.length() - 5));
2908 accept_all_state_files (const string& path, void *arg)
2910 return (path.length() > 7 && path.find (".ardour") == (path.length() - 7));
2914 Session::find_all_sources (string path, set<string>& result)
2919 if (!tree.read (path)) {
2923 if ((node = find_named_node (*tree.root(), "Sources")) == 0) {
2928 XMLNodeConstIterator niter;
2930 nlist = node->children();
2934 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2938 if ((prop = (*niter)->property (X_("name"))) == 0) {
2942 if (prop->value()[0] == '/') {
2943 /* external file, ignore */
2947 string path = _path; /* /-terminated */
2948 path += sound_dir_name;
2950 path += prop->value();
2952 result.insert (path);
2959 Session::find_all_sources_across_snapshots (set<string>& result, bool exclude_this_snapshot)
2961 PathScanner scanner;
2962 vector<string*>* state_files;
2964 string this_snapshot_path;
2970 if (ripped[ripped.length()-1] == '/') {
2971 ripped = ripped.substr (0, ripped.length() - 1);
2974 state_files = scanner (ripped, accept_all_state_files, (void *) 0, false, true);
2976 if (state_files == 0) {
2981 this_snapshot_path = _path;
2982 this_snapshot_path += _current_snapshot_name;
2983 this_snapshot_path += _statefile_suffix;
2985 for (vector<string*>::iterator i = state_files->begin(); i != state_files->end(); ++i) {
2987 if (exclude_this_snapshot && **i == this_snapshot_path) {
2991 if (find_all_sources (**i, result) < 0) {
3000 Session::cleanup_sources (Session::cleanup_report& rep)
3002 vector<boost::shared_ptr<Source> > dead_sources;
3003 vector<Playlist*> playlists_tbd;
3004 PathScanner scanner;
3006 vector<space_and_path>::iterator i;
3007 vector<space_and_path>::iterator nexti;
3008 vector<string*>* soundfiles;
3009 vector<string> unused;
3010 set<string> all_sources;
3015 _state_of_the_state = (StateOfTheState) (_state_of_the_state | InCleanup);
3017 /* step 1: consider deleting all unused playlists */
3019 for (PlaylistList::iterator x = unused_playlists.begin(); x != unused_playlists.end(); ++x) {
3022 status = AskAboutPlaylistDeletion (*x);
3031 playlists_tbd.push_back (*x);
3035 /* leave it alone */
3040 /* now delete any that were marked for deletion */
3042 for (vector<Playlist*>::iterator x = playlists_tbd.begin(); x != playlists_tbd.end(); ++x) {
3043 PlaylistList::iterator foo;
3045 if ((foo = unused_playlists.find (*x)) != unused_playlists.end()) {
3046 unused_playlists.erase (foo);
3051 /* step 2: clear the undo/redo history for all playlists */
3053 for (PlaylistList::iterator x = playlists.begin(); x != playlists.end(); ++x) {
3054 (*x)->drop_all_states ();
3057 /* step 3: find all un-referenced sources */
3062 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ) {
3064 SourceMap::iterator tmp;
3069 /* only remove files that are not in use and have some size
3070 to them. otherwise we remove the current "nascent"
3074 if (i->second.use_count() == 1 && i->second->length() > 0) {
3075 dead_sources.push_back (i->second);
3077 /* remove this source from our own list to avoid us
3078 adding it to the list of all sources below
3087 /* Step 4: get rid of all regions in the region list that use any dead sources
3088 in case the sources themselves don't go away (they might be referenced in
3092 for (vector<boost::shared_ptr<Source> >::iterator i = dead_sources.begin(); i != dead_sources.end();++i) {
3094 for (RegionList::iterator r = regions.begin(); r != regions.end(); ) {
3095 RegionList::iterator tmp;
3100 boost::shared_ptr<Region> reg = r->second;
3102 for (uint32_t n = 0; n < reg->n_channels(); ++n) {
3103 if (reg->source (n) == (*i)) {
3104 /* this region is dead */
3105 remove_region (reg);
3113 /* build a list of all the possible sound directories for the session */
3115 for (i = session_dirs.begin(); i != session_dirs.end(); ) {
3120 sound_path += (*i).path;
3121 sound_path += sound_dir_name;
3123 if (nexti != session_dirs.end()) {
3130 /* now do the same thing for the files that ended up in the sounds dir(s)
3131 but are not referenced as sources in any snapshot.
3134 soundfiles = scanner (sound_path, accept_all_non_peak_files, (void *) 0, false, true);
3136 if (soundfiles == 0) {
3140 /* find all sources, but don't use this snapshot because the
3141 state file on disk still references sources we may have already
3145 find_all_sources_across_snapshots (all_sources, true);
3147 /* add our current source list
3150 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ++i) {
3151 boost::shared_ptr<AudioFileSource> fs;
3153 if ((fs = boost::dynamic_pointer_cast<AudioFileSource> (i->second)) != 0) {
3154 all_sources.insert (fs->path());
3158 for (vector<string*>::iterator x = soundfiles->begin(); x != soundfiles->end(); ++x) {
3163 for (set<string>::iterator i = all_sources.begin(); i != all_sources.end(); ++i) {
3173 unused.push_back (spath);
3177 /* now try to move all unused files into the "dead_sounds" directory(ies) */
3179 for (vector<string>::iterator x = unused.begin(); x != unused.end(); ++x) {
3180 struct stat statbuf;
3182 rep.paths.push_back (*x);
3183 if (stat ((*x).c_str(), &statbuf) == 0) {
3184 rep.space += statbuf.st_size;
3189 /* don't move the file across filesystems, just
3190 stick it in the `dead_sound_dir_name' directory
3191 on whichever filesystem it was already on.
3194 newpath = Glib::path_get_dirname (*x);
3195 newpath = Glib::path_get_dirname (newpath);
3198 newpath += dead_sound_dir_name;
3200 newpath += Glib::path_get_basename ((*x));
3202 if (access (newpath.c_str(), F_OK) == 0) {
3204 /* the new path already exists, try versioning */
3206 char buf[PATH_MAX+1];
3210 snprintf (buf, sizeof (buf), "%s.%d", newpath.c_str(), version);
3213 while (access (newpath_v.c_str(), F_OK) == 0 && version < 999) {
3214 snprintf (buf, sizeof (buf), "%s.%d", newpath.c_str(), ++version);
3218 if (version == 999) {
3219 error << string_compose (_("there are already 1000 files with names like %1; versioning discontinued"),
3223 newpath = newpath_v;
3228 /* it doesn't exist, or we can't read it or something */
3232 if (::rename ((*x).c_str(), newpath.c_str()) != 0) {
3233 error << string_compose (_("cannot rename audio file source from %1 to %2 (%3)"),
3234 (*x), newpath, strerror (errno))
3240 /* see if there an easy to find peakfile for this file, and remove it.
3243 string peakpath = (*x).substr (0, (*x).find_last_of ('.'));
3244 peakpath += ".peak";
3246 if (access (peakpath.c_str(), W_OK) == 0) {
3247 if (::unlink (peakpath.c_str()) != 0) {
3248 error << string_compose (_("cannot remove peakfile %1 for %2 (%3)"),
3249 peakpath, _path, strerror (errno))
3251 /* try to back out */
3252 rename (newpath.c_str(), _path.c_str());
3261 /* dump the history list */
3265 /* save state so we don't end up a session file
3266 referring to non-existent sources.
3272 _state_of_the_state = (StateOfTheState) (_state_of_the_state & ~InCleanup);
3277 Session::cleanup_trash_sources (Session::cleanup_report& rep)
3279 vector<space_and_path>::iterator i;
3280 string dead_sound_dir;
3281 struct dirent* dentry;
3282 struct stat statbuf;
3288 for (i = session_dirs.begin(); i != session_dirs.end(); ++i) {
3290 dead_sound_dir = (*i).path;
3291 dead_sound_dir += dead_sound_dir_name;
3293 if ((dead = opendir (dead_sound_dir.c_str())) == 0) {
3297 while ((dentry = readdir (dead)) != 0) {
3299 /* avoid '.' and '..' */
3301 if ((dentry->d_name[0] == '.' && dentry->d_name[1] == '\0') ||
3302 (dentry->d_name[2] == '\0' && dentry->d_name[0] == '.' && dentry->d_name[1] == '.')) {
3308 fullpath = dead_sound_dir;
3310 fullpath += dentry->d_name;
3312 if (stat (fullpath.c_str(), &statbuf)) {
3316 if (!S_ISREG (statbuf.st_mode)) {
3320 if (unlink (fullpath.c_str())) {
3321 error << string_compose (_("cannot remove dead sound file %1 (%2)"),
3322 fullpath, strerror (errno))
3326 rep.paths.push_back (dentry->d_name);
3327 rep.space += statbuf.st_size;
3338 Session::set_dirty ()
3340 bool was_dirty = dirty();
3342 _state_of_the_state = StateOfTheState (_state_of_the_state | Dirty);
3345 DirtyChanged(); /* EMIT SIGNAL */
3351 Session::set_clean ()
3353 bool was_dirty = dirty();
3355 _state_of_the_state = Clean;
3358 DirtyChanged(); /* EMIT SIGNAL */
3363 Session::add_controllable (Controllable* c)
3365 Glib::Mutex::Lock lm (controllables_lock);
3366 controllables.push_back (c);
3370 Session::remove_controllable (Controllable* c)
3372 if (_state_of_the_state | Deletion) {
3376 Glib::Mutex::Lock lm (controllables_lock);
3377 controllables.remove (c);
3381 Session::controllable_by_id (const PBD::ID& id)
3383 Glib::Mutex::Lock lm (controllables_lock);
3385 for (Controllables::iterator i = controllables.begin(); i != controllables.end(); ++i) {
3386 if ((*i)->id() == id) {
3395 Session::add_instant_xml (XMLNode& node, const std::string& dir)
3397 Stateful::add_instant_xml (node, dir);
3398 Config->add_instant_xml (node, get_user_ardour_path());
3403 Session::save_history (string snapshot_name)
3410 tree.set_root (&history.get_state());
3412 if (snapshot_name.empty()) {
3413 snapshot_name = _current_snapshot_name;
3416 xml_path = _path + snapshot_name + ".history";
3417 cerr << "Saving history to " << xml_path << endmsg;
3419 bak_path = xml_path + ".bak";
3421 if ((access (xml_path.c_str(), F_OK) == 0) &&
3422 (rename (xml_path.c_str(), bak_path.c_str())))
3424 error << _("could not backup old history file, current history not saved.") << endmsg;
3428 if (!tree.write (xml_path))
3430 error << string_compose (_("history could not be saved to %1"), xml_path) << endmsg;
3432 /* don't leave a corrupt file lying around if it is
3436 if (unlink (xml_path.c_str()))
3438 error << string_compose (_("could not remove corrupt history file %1"), xml_path) << endmsg;
3440 if (rename (bak_path.c_str(), xml_path.c_str()))
3442 error << string_compose (_("could not restore history file from backup %1"), bak_path) << endmsg;
3453 Session::restore_history (string snapshot_name)
3459 xmlpath = _path + snapshot_name + ".history";
3460 cerr << string_compose(_("Loading history from '%1'."), xmlpath) << endmsg;
3462 if (access (xmlpath.c_str(), F_OK)) {
3463 error << string_compose(_("%1: session history file \"%2\" doesn't exist!"), _name, xmlpath) << endmsg;
3467 if (!tree.read (xmlpath)) {
3468 error << string_compose(_("Could not understand ardour file %1"), xmlpath) << endmsg;
3472 /* replace history */
3474 for (XMLNodeConstIterator it = tree.root()->children().begin();
3475 it != tree.root()->children().end();
3479 UndoTransaction* ut = new UndoTransaction ();
3482 ut->set_name(t->property("name")->value());
3483 stringstream ss(t->property("tv_sec")->value());
3485 ss.str(t->property("tv_usec")->value());
3487 ut->set_timestamp(tv);
3489 for (XMLNodeConstIterator child_it = t->children().begin();
3490 child_it != t->children().end();
3493 XMLNode *n = *child_it;
3495 if (n->name() == "MementoCommand" ||
3496 n->name() == "MementoUndoCommand" ||
3497 n->name() == "MementoRedoCommand")
3499 c = memento_command_factory(n);
3505 error << string_compose(_("Couldn't figure out how to make a Command out of a %1 XMLNode."), n->name()) << endmsg;