switch MIDI Clock slave code to use DEBUG_TRACE; don't make it require start/stop...
[ardour2.git] / libs / ardour / session_state.cc
blobe222de2221624a1df43ea398569179f483840b9a
1 /*
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.
21 #ifdef WAF_BUILD
22 #include "libardour-config.h"
23 #endif
25 #define __STDC_FORMAT_MACROS 1
26 #include <stdint.h>
28 #include <algorithm>
29 #include <fstream>
30 #include <string>
31 #include <cerrno>
34 #include <cstdio> /* snprintf(3) ... grrr */
35 #include <cmath>
36 #include <unistd.h>
37 #include <sys/stat.h>
38 #include <climits>
39 #include <fcntl.h>
40 #include <poll.h>
41 #include <signal.h>
42 #include <sys/mman.h>
43 #include <sys/time.h>
44 #include <dirent.h>
46 #ifdef HAVE_SYS_VFS_H
47 #include <sys/vfs.h>
48 #else
49 #include <sys/param.h>
50 #include <sys/mount.h>
51 #endif
53 #include <glibmm.h>
54 #include <glibmm/thread.h>
56 #include "midi++/mmc.h"
57 #include "midi++/port.h"
59 #include "pbd/boost_debug.h"
60 #include "pbd/controllable_descriptor.h"
61 #include "pbd/enumwriter.h"
62 #include "pbd/error.h"
63 #include "pbd/pathscanner.h"
64 #include "pbd/pthread_utils.h"
65 #include "pbd/search_path.h"
66 #include "pbd/stacktrace.h"
68 #include "ardour/amp.h"
69 #include "ardour/audio_diskstream.h"
70 #include "ardour/audio_track.h"
71 #include "ardour/audioengine.h"
72 #include "ardour/audiofilesource.h"
73 #include "ardour/audioplaylist.h"
74 #include "ardour/audioregion.h"
75 #include "ardour/auditioner.h"
76 #include "ardour/buffer.h"
77 #include "ardour/butler.h"
78 #include "ardour/configuration.h"
79 #include "ardour/control_protocol_manager.h"
80 #include "ardour/crossfade.h"
81 #include "ardour/cycle_timer.h"
82 #include "ardour/directory_names.h"
83 #include "ardour/filename_extensions.h"
84 #include "ardour/io_processor.h"
85 #include "ardour/location.h"
86 #include "ardour/midi_diskstream.h"
87 #include "ardour/midi_patch_manager.h"
88 #include "ardour/midi_playlist.h"
89 #include "ardour/midi_region.h"
90 #include "ardour/midi_source.h"
91 #include "ardour/midi_track.h"
92 #include "ardour/named_selection.h"
93 #include "ardour/processor.h"
94 #include "ardour/region_factory.h"
95 #include "ardour/route_group.h"
96 #include "ardour/send.h"
97 #include "ardour/session.h"
98 #include "ardour/session_directory.h"
99 #include "ardour/session_metadata.h"
100 #include "ardour/session_state_utils.h"
101 #include "ardour/session_playlists.h"
102 #include "ardour/session_utils.h"
103 #include "ardour/silentfilesource.h"
104 #include "ardour/slave.h"
105 #include "ardour/smf_source.h"
106 #include "ardour/sndfile_helpers.h"
107 #include "ardour/sndfilesource.h"
108 #include "ardour/source_factory.h"
109 #include "ardour/template_utils.h"
110 #include "ardour/tempo.h"
111 #include "ardour/ticker.h"
112 #include "ardour/user_bundle.h"
113 #include "ardour/utils.h"
114 #include "ardour/utils.h"
115 #include "ardour/version.h"
116 #include "ardour/playlist_factory.h"
118 #include "control_protocol/control_protocol.h"
120 #include "i18n.h"
121 #include <locale.h>
123 using namespace std;
124 using namespace ARDOUR;
125 using namespace PBD;
127 void
128 Session::first_stage_init (string fullpath, string snapshot_name)
130 if (fullpath.length() == 0) {
131 destroy ();
132 throw failed_constructor();
135 char buf[PATH_MAX+1];
136 if (!realpath (fullpath.c_str(), buf) && (errno != ENOENT)) {
137 error << string_compose(_("Could not use path %1 (%s)"), buf, strerror(errno)) << endmsg;
138 destroy ();
139 throw failed_constructor();
142 _path = string(buf);
144 if (_path[_path.length()-1] != '/') {
145 _path += '/';
148 if (Glib::file_test (_path, Glib::FILE_TEST_EXISTS) && ::access (_path.c_str(), W_OK)) {
149 _writable = false;
150 } else {
151 _writable = true;
154 /* these two are just provisional settings. set_state()
155 will likely override them.
158 _name = _current_snapshot_name = snapshot_name;
160 set_history_depth (Config->get_history_depth());
162 _current_frame_rate = _engine.frame_rate ();
163 _nominal_frame_rate = _current_frame_rate;
164 _base_frame_rate = _current_frame_rate;
166 _tempo_map = new TempoMap (_current_frame_rate);
167 _tempo_map->StateChanged.connect_same_thread (*this, boost::bind (&Session::tempo_map_changed, this, _1));
170 _non_soloed_outs_muted = false;
171 _listen_cnt = 0;
172 g_atomic_int_set (&processing_prohibited, 0);
173 _transport_speed = 0;
174 _last_transport_speed = 0;
175 _target_transport_speed = 0;
176 auto_play_legal = false;
177 transport_sub_state = 0;
178 _transport_frame = 0;
179 _requested_return_frame = -1;
180 end_location = new Location (0, 0, _("end"), Location::Flags ((Location::IsMark|Location::IsEnd)));
181 start_location = new Location (0, 0, _("start"), Location::Flags ((Location::IsMark|Location::IsStart)));
182 g_atomic_int_set (&_record_status, Disabled);
183 loop_changing = false;
184 play_loop = false;
185 have_looped = false;
186 _last_roll_location = 0;
187 _last_record_location = 0;
188 pending_locate_frame = 0;
189 pending_locate_roll = false;
190 pending_locate_flush = false;
191 state_was_pending = false;
192 set_next_event ();
193 outbound_mtc_timecode_frame = 0;
194 next_quarter_frame_to_send = -1;
195 current_block_size = 0;
196 solo_update_disabled = false;
197 _have_captured = false;
198 _worst_output_latency = 0;
199 _worst_input_latency = 0;
200 _worst_track_latency = 0;
201 _state_of_the_state = StateOfTheState(CannotSave|InitialConnecting|Loading);
202 _was_seamless = Config->get_seamless_loop ();
203 _slave = 0;
204 session_send_mmc = false;
205 session_send_mtc = false;
206 g_atomic_int_set (&_playback_load, 100);
207 g_atomic_int_set (&_capture_load, 100);
208 g_atomic_int_set (&_playback_load_min, 100);
209 g_atomic_int_set (&_capture_load_min, 100);
210 _play_range = false;
211 _exporting = false;
212 _gain_automation_buffer = 0;
213 _pan_automation_buffer = 0;
214 _npan_buffers = 0;
215 pending_abort = false;
216 destructive_index = 0;
217 first_file_data_format_reset = true;
218 first_file_header_format_reset = true;
219 post_export_sync = false;
220 midi_control_ui = 0;
222 AudioDiskstream::allocate_working_buffers();
224 /* default short fade = 15ms */
226 Crossfade::set_short_xfade_length ((nframes_t) floor (config.get_short_xfade_seconds() * frame_rate()));
227 SndFileSource::setup_standard_crossfades (*this, frame_rate());
229 last_mmc_step.tv_sec = 0;
230 last_mmc_step.tv_usec = 0;
231 step_speed = 0.0;
233 /* click sounds are unset by default, which causes us to internal
234 waveforms for clicks.
237 click_length = 0;
238 click_emphasis_length = 0;
239 _clicking = false;
241 process_function = &Session::process_with_events;
243 if (config.get_use_video_sync()) {
244 waiting_for_sync_offset = true;
245 } else {
246 waiting_for_sync_offset = false;
249 last_timecode_when = 0;
250 _timecode_offset = 0;
251 _timecode_offset_negative = true;
252 last_timecode_valid = false;
254 sync_time_vars ();
256 last_rr_session_dir = session_dirs.begin();
257 refresh_disk_space ();
259 // set_default_fade (0.2, 5.0); /* steepness, millisecs */
261 /* slave stuff */
263 average_slave_delta = 1800; // !!! why 1800 ????
264 have_first_delta_accumulator = false;
265 delta_accumulator_cnt = 0;
266 _slave_state = Stopped;
268 _engine.GraphReordered.connect_same_thread (*this, boost::bind (&Session::graph_reordered, this));
270 /* These are all static "per-class" signals */
272 RegionFactory::CheckNewRegion.connect_same_thread (*this, boost::bind (&Session::add_region, this, _1));
273 SourceFactory::SourceCreated.connect_same_thread (*this, boost::bind (&Session::add_source, this, _1));
274 PlaylistFactory::PlaylistCreated.connect_same_thread (*this, boost::bind (&Session::add_playlist, this, _1, _2));
275 Processor::ProcessorCreated.connect_same_thread (*this, boost::bind (&Session::add_processor, this, _1));
276 AutomationList::AutomationListCreated.connect_same_thread (*this, boost::bind (&Session::add_automation_list, this, _1));
277 Controllable::Destroyed.connect_same_thread (*this, boost::bind (&Session::remove_controllable, this, _1));
278 IO::PortCountChanged.connect_same_thread (*this, boost::bind (&Session::ensure_buffers, this, _1));
280 /* stop IO objects from doing stuff until we're ready for them */
282 Delivery::disable_panners ();
283 IO::disable_connecting ();
287 Session::second_stage_init (bool new_session)
289 AudioFileSource::set_peak_dir (_session_dir->peak_path().to_string());
291 if (!new_session) {
292 if (load_state (_current_snapshot_name)) {
293 return -1;
295 remove_empty_sounds ();
298 if (_butler->start_thread()) {
299 return -1;
302 if (start_midi_thread ()) {
303 return -1;
306 // set_state() will call setup_raid_path(), but if it's a new session we need
307 // to call setup_raid_path() here.
309 if (state_tree) {
310 if (set_state (*state_tree->root(), Stateful::loading_state_version)) {
311 return -1;
313 } else {
314 setup_raid_path(_path);
317 /* we can't save till after ::when_engine_running() is called,
318 because otherwise we save state with no connections made.
319 therefore, we reset _state_of_the_state because ::set_state()
320 will have cleared it.
322 we also have to include Loading so that any events that get
323 generated between here and the end of ::when_engine_running()
324 will be processed directly rather than queued.
327 _state_of_the_state = StateOfTheState (_state_of_the_state|CannotSave|Loading);
330 _locations.changed.connect_same_thread (*this, boost::bind (&Session::locations_changed, this));
331 _locations.added.connect_same_thread (*this, boost::bind (&Session::locations_added, this, _1));
332 setup_click_sounds (0);
333 setup_midi_control ();
335 /* Pay attention ... */
337 _engine.Halted.connect_same_thread (*this, boost::bind (&Session::engine_halted, this));
338 _engine.Xrun.connect_same_thread (*this, boost::bind (&Session::xrun_recovery, this));
340 try {
341 when_engine_running();
344 /* handle this one in a different way than all others, so that its clear what happened */
346 catch (AudioEngine::PortRegistrationFailure& err) {
347 error << err.what() << endmsg;
348 return -1;
351 catch (...) {
352 return -1;
355 BootMessage (_("Reset Remote Controls"));
357 send_full_time_code (0);
358 _engine.transport_locate (0);
359 deliver_mmc (MIDI::MachineControl::cmdMmcReset, 0);
360 deliver_mmc (MIDI::MachineControl::cmdLocate, 0);
362 MidiClockTicker::instance().set_session (this);
363 MIDI::Name::MidiPatchManager::instance().set_session (this);
365 /* initial program change will be delivered later; see ::config_changed() */
367 BootMessage (_("Reset Control Protocols"));
369 ControlProtocolManager::instance().set_session (this);
371 config.set_end_marker_is_free (new_session);
373 _state_of_the_state = Clean;
375 DirtyChanged (); /* EMIT SIGNAL */
377 if (state_was_pending) {
378 save_state (_current_snapshot_name);
379 remove_pending_capture_state ();
380 state_was_pending = false;
383 BootMessage (_("Session loading complete"));
385 return 0;
388 string
389 Session::raid_path () const
391 SearchPath raid_search_path;
393 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
394 raid_search_path += sys::path((*i).path);
397 return raid_search_path.to_string ();
400 void
401 Session::setup_raid_path (string path)
403 if (path.empty()) {
404 return;
407 space_and_path sp;
408 string fspath;
410 session_dirs.clear ();
412 SearchPath search_path(path);
413 SearchPath sound_search_path;
414 SearchPath midi_search_path;
416 for (SearchPath::const_iterator i = search_path.begin(); i != search_path.end(); ++i) {
417 sp.path = (*i).to_string ();
418 sp.blocks = 0; // not needed
419 session_dirs.push_back (sp);
421 SessionDirectory sdir(sp.path);
423 sound_search_path += sdir.sound_path ();
424 midi_search_path += sdir.midi_path ();
427 // set the search path for each data type
428 FileSource::set_search_path (DataType::AUDIO, sound_search_path.to_string ());
429 SMFSource::set_search_path (DataType::MIDI, midi_search_path.to_string ());
431 // reset the round-robin soundfile path thingie
432 last_rr_session_dir = session_dirs.begin();
435 bool
436 Session::path_is_within_session (const std::string& path)
438 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
439 if (path.find ((*i).path) == 0) {
440 return true;
443 return false;
447 Session::ensure_subdirs ()
449 string dir;
451 dir = session_directory().peak_path().to_string();
453 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
454 error << string_compose(_("Session: cannot create session peakfile folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
455 return -1;
458 dir = session_directory().sound_path().to_string();
460 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
461 error << string_compose(_("Session: cannot create session sounds dir \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
462 return -1;
465 dir = session_directory().midi_path().to_string();
467 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
468 error << string_compose(_("Session: cannot create session midi dir \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
469 return -1;
472 dir = session_directory().dead_sound_path().to_string();
474 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
475 error << string_compose(_("Session: cannot create session dead sounds folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
476 return -1;
479 dir = session_directory().export_path().to_string();
481 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
482 error << string_compose(_("Session: cannot create session export folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
483 return -1;
486 dir = analysis_dir ();
488 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
489 error << string_compose(_("Session: cannot create session analysis folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
490 return -1;
493 return 0;
497 Session::create (bool& new_session, const string& mix_template, nframes_t initial_length)
500 if (g_mkdir_with_parents (_path.c_str(), 0755) < 0) {
501 error << string_compose(_("Session: cannot create session folder \"%1\" (%2)"), _path, strerror (errno)) << endmsg;
502 return -1;
505 if (ensure_subdirs ()) {
506 return -1;
509 /* check new_session so we don't overwrite an existing one */
511 if (!mix_template.empty()) {
512 std::string in_path = mix_template;
514 ifstream in(in_path.c_str());
516 if (in){
517 string out_path = _path;
518 out_path += _name;
519 out_path += statefile_suffix;
521 ofstream out(out_path.c_str());
523 if (out){
524 out << in.rdbuf();
526 // okay, session is set up. Treat like normal saved
527 // session from now on.
529 new_session = false;
530 return 0;
532 } else {
533 error << string_compose (_("Could not open %1 for writing mix template"), out_path)
534 << endmsg;
535 return -1;
538 } else {
539 error << string_compose (_("Could not open mix template %1 for reading"), in_path)
540 << endmsg;
541 return -1;
546 /* Instantiate metadata */
548 _metadata = new SessionMetadata ();
550 /* set initial start + end point */
552 start_location->set_end (0);
553 _locations.add (start_location);
555 end_location->set_end (initial_length);
556 _locations.add (end_location);
558 _state_of_the_state = Clean;
560 save_state ("");
562 return 0;
567 Session::load_diskstreams (const XMLNode& node)
569 XMLNodeList clist;
570 XMLNodeConstIterator citer;
572 clist = node.children();
574 for (citer = clist.begin(); citer != clist.end(); ++citer) {
576 try {
577 /* diskstreams added automatically by DiskstreamCreated handler */
578 if ((*citer)->name() == "AudioDiskstream" || (*citer)->name() == "DiskStream") {
579 AudioDiskstream* dsp (new AudioDiskstream (*this, **citer));
580 boost::shared_ptr<AudioDiskstream> dstream (dsp);
581 add_diskstream (dstream);
582 } else if ((*citer)->name() == "MidiDiskstream") {
583 boost::shared_ptr<MidiDiskstream> dstream (new MidiDiskstream (*this, **citer));
584 add_diskstream (dstream);
585 } else {
586 error << _("Session: unknown diskstream type in XML") << endmsg;
590 catch (failed_constructor& err) {
591 error << _("Session: could not load diskstream via XML state") << endmsg;
592 return -1;
596 return 0;
599 void
600 Session::maybe_write_autosave()
602 if (dirty() && record_status() != Recording) {
603 save_state("", true);
607 void
608 Session::remove_pending_capture_state ()
610 sys::path pending_state_file_path(_session_dir->root_path());
612 pending_state_file_path /= legalize_for_path (_current_snapshot_name) + pending_suffix;
616 sys::remove (pending_state_file_path);
618 catch(sys::filesystem_error& ex)
620 error << string_compose(_("Could remove pending capture state at path \"%1\" (%2)"),
621 pending_state_file_path.to_string(), ex.what()) << endmsg;
625 /** Rename a state file.
626 * @param snapshot_name Snapshot name.
628 void
629 Session::rename_state (string old_name, string new_name)
631 if (old_name == _current_snapshot_name || old_name == _name) {
632 /* refuse to rename the current snapshot or the "main" one */
633 return;
636 const string old_xml_filename = legalize_for_path (old_name) + statefile_suffix;
637 const string new_xml_filename = legalize_for_path (new_name) + statefile_suffix;
639 const sys::path old_xml_path = _session_dir->root_path() / old_xml_filename;
640 const sys::path new_xml_path = _session_dir->root_path() / new_xml_filename;
644 sys::rename (old_xml_path, new_xml_path);
646 catch (const sys::filesystem_error& err)
648 error << string_compose(_("could not rename snapshot %1 to %2 (%3)"),
649 old_name, new_name, err.what()) << endmsg;
653 /** Remove a state file.
654 * @param snapshot_name Snapshot name.
656 void
657 Session::remove_state (string snapshot_name)
659 if (snapshot_name == _current_snapshot_name || snapshot_name == _name) {
660 // refuse to remove the current snapshot or the "main" one
661 return;
664 sys::path xml_path(_session_dir->root_path());
666 xml_path /= legalize_for_path (snapshot_name) + statefile_suffix;
668 if (!create_backup_file (xml_path)) {
669 // don't remove it if a backup can't be made
670 // create_backup_file will log the error.
671 return;
674 // and delete it
675 sys::remove (xml_path);
679 Session::save_state (string snapshot_name, bool pending)
681 XMLTree tree;
682 sys::path xml_path(_session_dir->root_path());
684 if (!_writable || (_state_of_the_state & CannotSave)) {
685 return 1;
688 if (!_engine.connected ()) {
689 error << _("Ardour's audio engine is not connected and state saving would lose all I/O connections. Session not saved")
690 << endmsg;
691 return 1;
694 /* tell sources we're saving first, in case they write out to a new file
695 * which should be saved with the state rather than the old one */
696 for (SourceMap::const_iterator i = sources.begin(); i != sources.end(); ++i)
697 i->second->session_saved();
699 tree.set_root (&get_state());
701 if (snapshot_name.empty()) {
702 snapshot_name = _current_snapshot_name;
705 if (!pending) {
707 /* proper save: use statefile_suffix (.ardour in English) */
709 xml_path /= legalize_for_path (snapshot_name) + statefile_suffix;
711 /* make a backup copy of the old file */
713 if (sys::exists(xml_path) && !create_backup_file (xml_path)) {
714 // create_backup_file will log the error
715 return -1;
718 } else {
720 /* pending save: use pending_suffix (.pending in English) */
721 xml_path /= legalize_for_path (snapshot_name) + pending_suffix;
724 sys::path tmp_path(_session_dir->root_path());
726 tmp_path /= legalize_for_path (snapshot_name) + temp_suffix;
728 // cerr << "actually writing state to " << xml_path.to_string() << endl;
730 if (!tree.write (tmp_path.to_string())) {
731 error << string_compose (_("state could not be saved to %1"), tmp_path.to_string()) << endmsg;
732 sys::remove (tmp_path);
733 return -1;
735 } else {
737 if (rename (tmp_path.to_string().c_str(), xml_path.to_string().c_str()) != 0) {
738 error << string_compose (_("could not rename temporary session file %1 to %2"),
739 tmp_path.to_string(), xml_path.to_string()) << endmsg;
740 sys::remove (tmp_path);
741 return -1;
745 if (!pending) {
747 save_history (snapshot_name);
749 bool was_dirty = dirty();
751 _state_of_the_state = StateOfTheState (_state_of_the_state & ~Dirty);
753 if (was_dirty) {
754 DirtyChanged (); /* EMIT SIGNAL */
757 StateSaved (snapshot_name); /* EMIT SIGNAL */
760 return 0;
764 Session::restore_state (string snapshot_name)
766 if (load_state (snapshot_name) == 0) {
767 set_state (*state_tree->root(), Stateful::loading_state_version);
770 return 0;
774 Session::load_state (string snapshot_name)
776 delete state_tree;
777 state_tree = 0;
779 state_was_pending = false;
781 /* check for leftover pending state from a crashed capture attempt */
783 sys::path xmlpath(_session_dir->root_path());
784 xmlpath /= legalize_for_path (snapshot_name) + pending_suffix;
786 if (sys::exists (xmlpath)) {
788 /* there is pending state from a crashed capture attempt */
790 if (*AskAboutPendingState()) {
791 state_was_pending = true;
795 if (!state_was_pending) {
796 xmlpath = _session_dir->root_path();
797 xmlpath /= legalize_for_path (snapshot_name) + statefile_suffix;
800 if (!sys::exists (xmlpath)) {
801 error << string_compose(_("%1: session state information file \"%2\" doesn't exist!"), _name, xmlpath.to_string()) << endmsg;
802 return 1;
805 state_tree = new XMLTree;
807 set_dirty();
809 /* writable() really reflects the whole folder, but if for any
810 reason the session state file can't be written to, still
811 make us unwritable.
814 if (::access (xmlpath.to_string().c_str(), W_OK) != 0) {
815 _writable = false;
818 if (!state_tree->read (xmlpath.to_string())) {
819 error << string_compose(_("Could not understand ardour file %1"), xmlpath.to_string()) << endmsg;
820 delete state_tree;
821 state_tree = 0;
822 return -1;
825 XMLNode& root (*state_tree->root());
827 if (root.name() != X_("Session")) {
828 error << string_compose (_("Session file %1 is not an Ardour session"), xmlpath.to_string()) << endmsg;
829 delete state_tree;
830 state_tree = 0;
831 return -1;
834 const XMLProperty* prop;
836 if ((prop = root.property ("version")) == 0) {
837 /* no version implies very old version of Ardour */
838 Stateful::loading_state_version = 1000;
839 } else {
840 int major;
841 int minor;
842 int micro;
844 sscanf (prop->value().c_str(), "%d.%d.%d", &major, &minor, &micro);
845 Stateful::loading_state_version = (major * 1000) + minor;
848 if (Stateful::loading_state_version < CURRENT_SESSION_FILE_VERSION) {
850 sys::path backup_path(_session_dir->root_path());
852 backup_path /= legalize_for_path (snapshot_name) + "-1" + statefile_suffix;
854 // only create a backup once
855 if (sys::exists (backup_path)) {
856 return 0;
859 info << string_compose (_("Copying old session file %1 to %2\nUse %2 with Ardour versions before 2.0 from now on"),
860 xmlpath.to_string(), backup_path.to_string())
861 << endmsg;
865 sys::copy_file (xmlpath, backup_path);
867 catch(sys::filesystem_error& ex)
869 error << string_compose (_("Unable to make backup of state file %1 (%2)"),
870 xmlpath.to_string(), ex.what())
871 << endmsg;
872 return -1;
876 return 0;
880 Session::load_options (const XMLNode& node)
882 LocaleGuard lg (X_("POSIX"));
883 config.set_variables (node);
884 return 0;
887 XMLNode&
888 Session::get_state()
890 return state(true);
893 XMLNode&
894 Session::get_template()
896 /* if we don't disable rec-enable, diskstreams
897 will believe they need to store their capture
898 sources in their state node.
901 disable_record (false);
903 return state(false);
906 XMLNode&
907 Session::state(bool full_state)
909 XMLNode* node = new XMLNode("Session");
910 XMLNode* child;
912 // store libardour version, just in case
913 char buf[16];
914 snprintf(buf, sizeof(buf), "%d.%d.%d", libardour3_major_version, libardour3_minor_version, libardour3_micro_version);
915 node->add_property("version", string(buf));
917 /* store configuration settings */
919 if (full_state) {
921 node->add_property ("name", _name);
922 snprintf (buf, sizeof (buf), "%" PRId32, _nominal_frame_rate);
923 node->add_property ("sample-rate", buf);
925 if (session_dirs.size() > 1) {
927 string p;
929 vector<space_and_path>::iterator i = session_dirs.begin();
930 vector<space_and_path>::iterator next;
932 ++i; /* skip the first one */
933 next = i;
934 ++next;
936 while (i != session_dirs.end()) {
938 p += (*i).path;
940 if (next != session_dirs.end()) {
941 p += ':';
942 } else {
943 break;
946 ++next;
947 ++i;
950 child = node->add_child ("Path");
951 child->add_content (p);
955 /* save the ID counter */
957 snprintf (buf, sizeof (buf), "%" PRIu64, ID::counter());
958 node->add_property ("id-counter", buf);
960 /* various options */
962 node->add_child_nocopy (config.get_variables ());
964 node->add_child_nocopy (_metadata->get_state());
966 child = node->add_child ("Sources");
968 if (full_state) {
969 Glib::Mutex::Lock sl (source_lock);
971 for (SourceMap::iterator siter = sources.begin(); siter != sources.end(); ++siter) {
973 /* Don't save information about non-destructive file sources that are empty */
974 /* FIXME: MIDI breaks if this is made FileSource like it should be... */
976 boost::shared_ptr<AudioFileSource> fs;
977 if ((fs = boost::dynamic_pointer_cast<AudioFileSource> (siter->second)) != 0) {
978 if (!fs->destructive()) {
979 if (fs->length(fs->timeline_position()) == 0) {
980 continue;
985 child->add_child_nocopy (siter->second->get_state());
989 child = node->add_child ("Regions");
991 if (full_state) {
992 Glib::Mutex::Lock rl (region_lock);
994 for (RegionList::const_iterator i = regions.begin(); i != regions.end(); ++i) {
996 /* only store regions not attached to playlists */
998 if (i->second->playlist() == 0) {
999 child->add_child_nocopy (i->second->state (true));
1004 child = node->add_child ("DiskStreams");
1007 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
1008 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
1009 if (!(*i)->hidden()) {
1010 child->add_child_nocopy ((*i)->get_state());
1015 if (full_state) {
1016 node->add_child_nocopy (_locations.get_state());
1017 } else {
1018 // for a template, just create a new Locations, populate it
1019 // with the default start and end, and get the state for that.
1020 Locations loc;
1021 Location* start = new Location(0, 0, _("start"), Location::Flags ((Location::IsMark|Location::IsStart)));
1022 Location* end = new Location(0, 0, _("end"), Location::Flags ((Location::IsMark|Location::IsEnd)));
1023 start->set_end(0);
1024 loc.add (start);
1025 end->set_end(compute_initial_length());
1026 loc.add (end);
1027 node->add_child_nocopy (loc.get_state());
1030 child = node->add_child ("Bundles");
1032 boost::shared_ptr<BundleList> bundles = _bundles.reader ();
1033 for (BundleList::iterator i = bundles->begin(); i != bundles->end(); ++i) {
1034 boost::shared_ptr<UserBundle> b = boost::dynamic_pointer_cast<UserBundle> (*i);
1035 if (b) {
1036 child->add_child_nocopy (b->get_state());
1041 child = node->add_child ("Routes");
1043 boost::shared_ptr<RouteList> r = routes.reader ();
1045 RoutePublicOrderSorter cmp;
1046 RouteList public_order (*r);
1047 public_order.sort (cmp);
1049 for (RouteList::iterator i = public_order.begin(); i != public_order.end(); ++i) {
1050 if (!(*i)->is_hidden()) {
1051 if (full_state) {
1052 child->add_child_nocopy ((*i)->get_state());
1053 } else {
1054 child->add_child_nocopy ((*i)->get_template());
1060 playlists->add_state (node, full_state);
1062 child = node->add_child ("RouteGroups");
1063 for (list<RouteGroup *>::iterator i = _route_groups.begin(); i != _route_groups.end(); ++i) {
1064 child->add_child_nocopy ((*i)->get_state());
1067 if (_click_io) {
1068 child = node->add_child ("Click");
1069 child->add_child_nocopy (_click_io->state (full_state));
1072 if (full_state) {
1073 child = node->add_child ("NamedSelections");
1074 for (NamedSelectionList::iterator i = named_selections.begin(); i != named_selections.end(); ++i) {
1075 if (full_state) {
1076 child->add_child_nocopy ((*i)->get_state());
1081 node->add_child_nocopy (_tempo_map->get_state());
1083 node->add_child_nocopy (get_control_protocol_state());
1085 if (_extra_xml) {
1086 node->add_child_copy (*_extra_xml);
1089 return *node;
1092 XMLNode&
1093 Session::get_control_protocol_state ()
1095 ControlProtocolManager& cpm (ControlProtocolManager::instance());
1096 return cpm.get_state();
1100 Session::set_state (const XMLNode& node, int version)
1102 XMLNodeList nlist;
1103 XMLNode* child;
1104 const XMLProperty* prop;
1105 int ret = -1;
1107 _state_of_the_state = StateOfTheState (_state_of_the_state|CannotSave);
1109 if (node.name() != X_("Session")){
1110 fatal << _("programming error: Session: incorrect XML node sent to set_state()") << endmsg;
1111 return -1;
1114 if ((prop = node.property ("version")) != 0) {
1115 version = atoi (prop->value ()) * 1000;
1118 if ((prop = node.property ("name")) != 0) {
1119 _name = prop->value ();
1122 if ((prop = node.property (X_("sample-rate"))) != 0) {
1124 _nominal_frame_rate = atoi (prop->value());
1126 if (_nominal_frame_rate != _current_frame_rate) {
1127 if (*AskAboutSampleRateMismatch (_nominal_frame_rate, _current_frame_rate)) {
1128 return -1;
1133 setup_raid_path(_session_dir->root_path().to_string());
1135 if ((prop = node.property (X_("id-counter"))) != 0) {
1136 uint64_t x;
1137 sscanf (prop->value().c_str(), "%" PRIu64, &x);
1138 ID::init_counter (x);
1139 } else {
1140 /* old sessions used a timebased counter, so fake
1141 the startup ID counter based on a standard
1142 timestamp.
1144 time_t now;
1145 time (&now);
1146 ID::init_counter (now);
1150 IO::disable_connecting ();
1152 /* Object loading order:
1154 Path
1155 Extra
1156 Options/Config
1157 MIDI Control // relies on data from Options/Config
1158 Metadata
1159 Locations
1160 Sources
1161 AudioRegions
1162 AudioDiskstreams
1163 Connections
1164 Routes
1165 RouteGroups
1166 MixGroups
1167 Click
1168 ControlProtocols
1171 if ((child = find_named_node (node, "Extra")) != 0) {
1172 _extra_xml = new XMLNode (*child);
1175 if (((child = find_named_node (node, "Options")) != 0)) { /* old style */
1176 load_options (*child);
1177 } else if ((child = find_named_node (node, "Config")) != 0) { /* new style */
1178 load_options (*child);
1179 } else {
1180 error << _("Session: XML state has no options section") << endmsg;
1183 if (use_config_midi_ports ()) {
1186 if (version >= 3000) {
1187 if ((child = find_named_node (node, "Metadata")) == 0) {
1188 warning << _("Session: XML state has no metadata section") << endmsg;
1189 } else if (_metadata->set_state (*child, version)) {
1190 goto out;
1194 if ((child = find_named_node (node, "Locations")) == 0) {
1195 error << _("Session: XML state has no locations section") << endmsg;
1196 goto out;
1197 } else if (_locations.set_state (*child, version)) {
1198 goto out;
1201 Location* location;
1203 if ((location = _locations.auto_loop_location()) != 0) {
1204 set_auto_loop_location (location);
1207 if ((location = _locations.auto_punch_location()) != 0) {
1208 set_auto_punch_location (location);
1211 if ((location = _locations.end_location()) == 0) {
1212 _locations.add (end_location);
1213 } else {
1214 delete end_location;
1215 end_location = location;
1218 if ((location = _locations.start_location()) == 0) {
1219 _locations.add (start_location);
1220 } else {
1221 delete start_location;
1222 start_location = location;
1225 AudioFileSource::set_header_position_offset (start_location->start());
1227 if ((child = find_named_node (node, "Sources")) == 0) {
1228 error << _("Session: XML state has no sources section") << endmsg;
1229 goto out;
1230 } else if (load_sources (*child)) {
1231 goto out;
1234 if ((child = find_named_node (node, "Regions")) == 0) {
1235 error << _("Session: XML state has no Regions section") << endmsg;
1236 goto out;
1237 } else if (load_regions (*child)) {
1238 goto out;
1241 if ((child = find_named_node (node, "Playlists")) == 0) {
1242 error << _("Session: XML state has no playlists section") << endmsg;
1243 goto out;
1244 } else if (playlists->load (*this, *child)) {
1245 goto out;
1248 if ((child = find_named_node (node, "UnusedPlaylists")) == 0) {
1249 // this is OK
1250 } else if (playlists->load_unused (*this, *child)) {
1251 goto out;
1254 if ((child = find_named_node (node, "NamedSelections")) != 0) {
1255 if (load_named_selections (*child)) {
1256 goto out;
1260 if ((child = find_named_node (node, "DiskStreams")) == 0) {
1261 error << _("Session: XML state has no diskstreams section") << endmsg;
1262 goto out;
1263 } else if (load_diskstreams (*child)) {
1264 goto out;
1267 if (version >= 3000) {
1268 if ((child = find_named_node (node, "Bundles")) == 0) {
1269 warning << _("Session: XML state has no bundles section") << endmsg;
1270 //goto out;
1271 } else {
1272 /* We can't load Bundles yet as they need to be able
1273 to convert from port names to Port objects, which can't happen until
1274 later */
1275 _bundle_xml_node = new XMLNode (*child);
1279 if ((child = find_named_node (node, "TempoMap")) == 0) {
1280 error << _("Session: XML state has no Tempo Map section") << endmsg;
1281 goto out;
1282 } else if (_tempo_map->set_state (*child, version)) {
1283 goto out;
1286 if ((child = find_named_node (node, "Routes")) == 0) {
1287 error << _("Session: XML state has no routes section") << endmsg;
1288 goto out;
1289 } else if (load_routes (*child, version)) {
1290 goto out;
1293 if (version >= 3000) {
1295 if ((child = find_named_node (node, "RouteGroups")) == 0) {
1296 error << _("Session: XML state has no route groups section") << endmsg;
1297 goto out;
1298 } else if (load_route_groups (*child, version)) {
1299 goto out;
1302 } else if (version < 3000) {
1304 if ((child = find_named_node (node, "EditGroups")) == 0) {
1305 error << _("Session: XML state has no edit groups section") << endmsg;
1306 goto out;
1307 } else if (load_route_groups (*child, version)) {
1308 goto out;
1311 if ((child = find_named_node (node, "MixGroups")) == 0) {
1312 error << _("Session: XML state has no mix groups section") << endmsg;
1313 goto out;
1314 } else if (load_route_groups (*child, version)) {
1315 goto out;
1319 if ((child = find_named_node (node, "Click")) == 0) {
1320 warning << _("Session: XML state has no click section") << endmsg;
1321 } else if (_click_io) {
1322 _click_io->set_state (*child, version);
1325 if ((child = find_named_node (node, "ControlProtocols")) != 0) {
1326 ControlProtocolManager::instance().set_protocol_states (*child);
1329 /* here beginneth the second phase ... */
1331 StateReady (); /* EMIT SIGNAL */
1333 return 0;
1335 out:
1336 return ret;
1340 Session::load_routes (const XMLNode& node, int version)
1342 XMLNodeList nlist;
1343 XMLNodeConstIterator niter;
1344 RouteList new_routes;
1346 nlist = node.children();
1348 set_dirty();
1350 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1352 boost::shared_ptr<Route> route (XMLRouteFactory (**niter, version));
1354 if (route == 0) {
1355 error << _("Session: cannot create Route from XML description.") << endmsg;
1356 return -1;
1359 BootMessage (string_compose (_("Loaded track/bus %1"), route->name()));
1361 new_routes.push_back (route);
1364 add_routes (new_routes, false);
1366 return 0;
1369 boost::shared_ptr<Route>
1370 Session::XMLRouteFactory (const XMLNode& node, int version)
1372 if (node.name() != "Route") {
1373 return boost::shared_ptr<Route> ((Route*) 0);
1376 bool has_diskstream = (node.property ("diskstream") != 0 || node.property ("diskstream-id") != 0);
1378 DataType type = DataType::AUDIO;
1379 const XMLProperty* prop = node.property("default-type");
1380 boost::shared_ptr<Route> ret;
1382 if (prop) {
1383 type = DataType(prop->value());
1386 assert(type != DataType::NIL);
1388 if (has_diskstream) {
1389 if (type == DataType::AUDIO) {
1390 AudioTrack* at = new AudioTrack (*this, node, version);
1391 boost_debug_shared_ptr_mark_interesting (at, "Track");
1392 ret.reset (at);
1394 } else {
1395 ret.reset (new MidiTrack (*this, node, version));
1397 } else {
1398 Route* rt = new Route (*this, node);
1399 boost_debug_shared_ptr_mark_interesting (rt, "Route");
1400 ret.reset (rt);
1403 return ret;
1407 Session::load_regions (const XMLNode& node)
1409 XMLNodeList nlist;
1410 XMLNodeConstIterator niter;
1411 boost::shared_ptr<Region> region;
1413 nlist = node.children();
1415 set_dirty();
1417 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1418 if ((region = XMLRegionFactory (**niter, false)) == 0) {
1419 error << _("Session: cannot create Region from XML description.");
1420 const XMLProperty *name = (**niter).property("name");
1422 if (name) {
1423 error << " " << string_compose (_("Can not load state for region '%1'"), name->value());
1426 error << endmsg;
1430 return 0;
1433 boost::shared_ptr<Region>
1434 Session::XMLRegionFactory (const XMLNode& node, bool full)
1436 const XMLProperty* type = node.property("type");
1438 try {
1440 if ( !type || type->value() == "audio" ) {
1442 return boost::shared_ptr<Region>(XMLAudioRegionFactory (node, full));
1444 } else if (type->value() == "midi") {
1446 return boost::shared_ptr<Region>(XMLMidiRegionFactory (node, full));
1450 } catch (failed_constructor& err) {
1451 return boost::shared_ptr<Region> ();
1454 return boost::shared_ptr<Region> ();
1457 boost::shared_ptr<AudioRegion>
1458 Session::XMLAudioRegionFactory (const XMLNode& node, bool /*full*/)
1460 const XMLProperty* prop;
1461 boost::shared_ptr<Source> source;
1462 boost::shared_ptr<AudioSource> as;
1463 SourceList sources;
1464 SourceList master_sources;
1465 uint32_t nchans = 1;
1466 char buf[128];
1468 if (node.name() != X_("Region")) {
1469 return boost::shared_ptr<AudioRegion>();
1472 if ((prop = node.property (X_("channels"))) != 0) {
1473 nchans = atoi (prop->value().c_str());
1476 if ((prop = node.property ("name")) == 0) {
1477 cerr << "no name for this region\n";
1478 abort ();
1481 if ((prop = node.property (X_("source-0"))) == 0) {
1482 if ((prop = node.property ("source")) == 0) {
1483 error << _("Session: XMLNode describing a AudioRegion is incomplete (no source)") << endmsg;
1484 return boost::shared_ptr<AudioRegion>();
1488 PBD::ID s_id (prop->value());
1490 if ((source = source_by_id (s_id)) == 0) {
1491 error << string_compose(_("Session: XMLNode describing a AudioRegion references an unknown source id =%1"), s_id) << endmsg;
1492 return boost::shared_ptr<AudioRegion>();
1495 as = boost::dynamic_pointer_cast<AudioSource>(source);
1496 if (!as) {
1497 error << string_compose(_("Session: XMLNode describing a AudioRegion references a non-audio source id =%1"), s_id) << endmsg;
1498 return boost::shared_ptr<AudioRegion>();
1501 sources.push_back (as);
1503 /* pickup other channels */
1505 for (uint32_t n=1; n < nchans; ++n) {
1506 snprintf (buf, sizeof(buf), X_("source-%d"), n);
1507 if ((prop = node.property (buf)) != 0) {
1509 PBD::ID id2 (prop->value());
1511 if ((source = source_by_id (id2)) == 0) {
1512 error << string_compose(_("Session: XMLNode describing a AudioRegion references an unknown source id =%1"), id2) << endmsg;
1513 return boost::shared_ptr<AudioRegion>();
1516 as = boost::dynamic_pointer_cast<AudioSource>(source);
1517 if (!as) {
1518 error << string_compose(_("Session: XMLNode describing a AudioRegion references a non-audio source id =%1"), id2) << endmsg;
1519 return boost::shared_ptr<AudioRegion>();
1521 sources.push_back (as);
1525 for (uint32_t n = 0; n < nchans; ++n) {
1526 snprintf (buf, sizeof(buf), X_("master-source-%d"), n);
1527 if ((prop = node.property (buf)) != 0) {
1529 PBD::ID id2 (prop->value());
1531 if ((source = source_by_id (id2)) == 0) {
1532 error << string_compose(_("Session: XMLNode describing a AudioRegion references an unknown source id =%1"), id2) << endmsg;
1533 return boost::shared_ptr<AudioRegion>();
1536 as = boost::dynamic_pointer_cast<AudioSource>(source);
1537 if (!as) {
1538 error << string_compose(_("Session: XMLNode describing a AudioRegion references a non-audio source id =%1"), id2) << endmsg;
1539 return boost::shared_ptr<AudioRegion>();
1541 master_sources.push_back (as);
1545 try {
1546 boost::shared_ptr<AudioRegion> region (boost::dynamic_pointer_cast<AudioRegion> (RegionFactory::create (sources, node)));
1548 /* a final detail: this is the one and only place that we know how long missing files are */
1550 if (region->whole_file()) {
1551 for (SourceList::iterator sx = sources.begin(); sx != sources.end(); ++sx) {
1552 boost::shared_ptr<SilentFileSource> sfp = boost::dynamic_pointer_cast<SilentFileSource> (*sx);
1553 if (sfp) {
1554 sfp->set_length (region->length());
1559 if (!master_sources.empty()) {
1560 if (master_sources.size() != nchans) {
1561 error << _("Session: XMLNode describing an AudioRegion is missing some master sources; ignored") << endmsg;
1562 } else {
1563 region->set_master_sources (master_sources);
1567 return region;
1571 catch (failed_constructor& err) {
1572 return boost::shared_ptr<AudioRegion>();
1576 boost::shared_ptr<MidiRegion>
1577 Session::XMLMidiRegionFactory (const XMLNode& node, bool /*full*/)
1579 const XMLProperty* prop;
1580 boost::shared_ptr<Source> source;
1581 boost::shared_ptr<MidiSource> ms;
1582 SourceList sources;
1583 uint32_t nchans = 1;
1585 if (node.name() != X_("Region")) {
1586 return boost::shared_ptr<MidiRegion>();
1589 if ((prop = node.property (X_("channels"))) != 0) {
1590 nchans = atoi (prop->value().c_str());
1593 if ((prop = node.property ("name")) == 0) {
1594 cerr << "no name for this region\n";
1595 abort ();
1598 // Multiple midi channels? that's just crazy talk
1599 assert(nchans == 1);
1601 if ((prop = node.property (X_("source-0"))) == 0) {
1602 if ((prop = node.property ("source")) == 0) {
1603 error << _("Session: XMLNode describing a MidiRegion is incomplete (no source)") << endmsg;
1604 return boost::shared_ptr<MidiRegion>();
1608 PBD::ID s_id (prop->value());
1610 if ((source = source_by_id (s_id)) == 0) {
1611 error << string_compose(_("Session: XMLNode describing a MidiRegion references an unknown source id =%1"), s_id) << endmsg;
1612 return boost::shared_ptr<MidiRegion>();
1615 ms = boost::dynamic_pointer_cast<MidiSource>(source);
1616 if (!ms) {
1617 error << string_compose(_("Session: XMLNode describing a MidiRegion references a non-midi source id =%1"), s_id) << endmsg;
1618 return boost::shared_ptr<MidiRegion>();
1621 sources.push_back (ms);
1623 try {
1624 boost::shared_ptr<MidiRegion> region (boost::dynamic_pointer_cast<MidiRegion> (RegionFactory::create (sources, node)));
1625 /* a final detail: this is the one and only place that we know how long missing files are */
1627 if (region->whole_file()) {
1628 for (SourceList::iterator sx = sources.begin(); sx != sources.end(); ++sx) {
1629 boost::shared_ptr<SilentFileSource> sfp = boost::dynamic_pointer_cast<SilentFileSource> (*sx);
1630 if (sfp) {
1631 sfp->set_length (region->length());
1636 return region;
1639 catch (failed_constructor& err) {
1640 return boost::shared_ptr<MidiRegion>();
1644 XMLNode&
1645 Session::get_sources_as_xml ()
1648 XMLNode* node = new XMLNode (X_("Sources"));
1649 Glib::Mutex::Lock lm (source_lock);
1651 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ++i) {
1652 node->add_child_nocopy (i->second->get_state());
1655 return *node;
1658 string
1659 Session::path_from_region_name (DataType type, string name, string identifier)
1661 char buf[PATH_MAX+1];
1662 uint32_t n;
1663 SessionDirectory sdir(get_best_session_directory_for_new_source());
1664 sys::path source_dir = ((type == DataType::AUDIO)
1665 ? sdir.sound_path() : sdir.midi_path());
1667 string ext = ((type == DataType::AUDIO) ? ".wav" : ".mid");
1669 for (n = 0; n < 999999; ++n) {
1670 if (identifier.length()) {
1671 snprintf (buf, sizeof(buf), "%s%s%" PRIu32 "%s", name.c_str(),
1672 identifier.c_str(), n, ext.c_str());
1673 } else {
1674 snprintf (buf, sizeof(buf), "%s-%" PRIu32 "%s", name.c_str(),
1675 n, ext.c_str());
1678 sys::path source_path = source_dir / buf;
1680 if (!sys::exists (source_path)) {
1681 return source_path.to_string();
1685 error << string_compose (_("cannot create new file from region name \"%1\" with ident = \"%2\": too many existing files with similar names"),
1686 name, identifier)
1687 << endmsg;
1689 return "";
1694 Session::load_sources (const XMLNode& node)
1696 XMLNodeList nlist;
1697 XMLNodeConstIterator niter;
1698 boost::shared_ptr<Source> source;
1700 nlist = node.children();
1702 set_dirty();
1704 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1705 try {
1706 if ((source = XMLSourceFactory (**niter)) == 0) {
1707 error << _("Session: cannot create Source from XML description.") << endmsg;
1709 } catch (MissingSource& err) {
1710 warning << _("A sound file is missing. It will be replaced by silence.") << endmsg;
1711 source = SourceFactory::createSilent (*this, **niter, max_frames, _current_frame_rate);
1715 return 0;
1718 boost::shared_ptr<Source>
1719 Session::XMLSourceFactory (const XMLNode& node)
1721 if (node.name() != "Source") {
1722 return boost::shared_ptr<Source>();
1725 try {
1726 /* note: do peak building in another thread when loading session state */
1727 return SourceFactory::create (*this, node, true);
1730 catch (failed_constructor& err) {
1731 error << _("Found a sound file that cannot be used by Ardour. Talk to the progammers.") << endmsg;
1732 return boost::shared_ptr<Source>();
1737 Session::save_template (string template_name)
1739 XMLTree tree;
1741 if (_state_of_the_state & CannotSave) {
1742 return -1;
1745 sys::path user_template_dir(user_template_directory());
1749 sys::create_directories (user_template_dir);
1751 catch(sys::filesystem_error& ex)
1753 error << string_compose(_("Could not create mix templates directory \"%1\" (%2)"),
1754 user_template_dir.to_string(), ex.what()) << endmsg;
1755 return -1;
1758 tree.set_root (&get_template());
1760 sys::path template_file_path(user_template_dir);
1761 template_file_path /= template_name + template_suffix;
1763 if (sys::exists (template_file_path))
1765 warning << string_compose(_("Template \"%1\" already exists - new version not created"),
1766 template_file_path.to_string()) << endmsg;
1767 return -1;
1770 if (!tree.write (template_file_path.to_string())) {
1771 error << _("mix template not saved") << endmsg;
1772 return -1;
1775 return 0;
1779 Session::rename_template (string old_name, string new_name)
1781 sys::path old_path (user_template_directory());
1782 old_path /= old_name + template_suffix;
1784 sys::path new_path(user_template_directory());
1785 new_path /= new_name + template_suffix;
1787 if (sys::exists (new_path)) {
1788 warning << string_compose(_("Template \"%1\" already exists - template not renamed"),
1789 new_path.to_string()) << endmsg;
1790 return -1;
1793 try {
1794 sys::rename (old_path, new_path);
1795 return 0;
1796 } catch (...) {
1797 return -1;
1802 Session::delete_template (string name)
1804 sys::path path = user_template_directory();
1805 path /= name + template_suffix;
1807 try {
1808 sys::remove (path);
1809 return 0;
1810 } catch (...) {
1811 return -1;
1815 void
1816 Session::refresh_disk_space ()
1818 #if HAVE_SYS_VFS_H
1819 struct statfs statfsbuf;
1820 vector<space_and_path>::iterator i;
1821 Glib::Mutex::Lock lm (space_lock);
1822 double scale;
1824 /* get freespace on every FS that is part of the session path */
1826 _total_free_4k_blocks = 0;
1828 for (i = session_dirs.begin(); i != session_dirs.end(); ++i) {
1829 statfs ((*i).path.c_str(), &statfsbuf);
1831 scale = statfsbuf.f_bsize/4096.0;
1833 (*i).blocks = (uint32_t) floor (statfsbuf.f_bavail * scale);
1834 _total_free_4k_blocks += (*i).blocks;
1836 #endif
1839 string
1840 Session::get_best_session_directory_for_new_source ()
1842 vector<space_and_path>::iterator i;
1843 string result = _session_dir->root_path().to_string();
1845 /* handle common case without system calls */
1847 if (session_dirs.size() == 1) {
1848 return result;
1851 /* OK, here's the algorithm we're following here:
1853 We want to select which directory to use for
1854 the next file source to be created. Ideally,
1855 we'd like to use a round-robin process so as to
1856 get maximum performance benefits from splitting
1857 the files across multiple disks.
1859 However, in situations without much diskspace, an
1860 RR approach may end up filling up a filesystem
1861 with new files while others still have space.
1862 Its therefore important to pay some attention to
1863 the freespace in the filesystem holding each
1864 directory as well. However, if we did that by
1865 itself, we'd keep creating new files in the file
1866 system with the most space until it was as full
1867 as all others, thus negating any performance
1868 benefits of this RAID-1 like approach.
1870 So, we use a user-configurable space threshold. If
1871 there are at least 2 filesystems with more than this
1872 much space available, we use RR selection between them.
1873 If not, then we pick the filesystem with the most space.
1875 This gets a good balance between the two
1876 approaches.
1879 refresh_disk_space ();
1881 int free_enough = 0;
1883 for (i = session_dirs.begin(); i != session_dirs.end(); ++i) {
1884 if ((*i).blocks * 4096 >= Config->get_disk_choice_space_threshold()) {
1885 free_enough++;
1889 if (free_enough >= 2) {
1890 /* use RR selection process, ensuring that the one
1891 picked works OK.
1894 i = last_rr_session_dir;
1896 do {
1897 if (++i == session_dirs.end()) {
1898 i = session_dirs.begin();
1901 if ((*i).blocks * 4096 >= Config->get_disk_choice_space_threshold()) {
1902 if (create_session_directory ((*i).path)) {
1903 result = (*i).path;
1904 last_rr_session_dir = i;
1905 return result;
1909 } while (i != last_rr_session_dir);
1911 } else {
1913 /* pick FS with the most freespace (and that
1914 seems to actually work ...)
1917 vector<space_and_path> sorted;
1918 space_and_path_ascending_cmp cmp;
1920 sorted = session_dirs;
1921 sort (sorted.begin(), sorted.end(), cmp);
1923 for (i = sorted.begin(); i != sorted.end(); ++i) {
1924 if (create_session_directory ((*i).path)) {
1925 result = (*i).path;
1926 last_rr_session_dir = i;
1927 return result;
1932 return result;
1936 Session::load_named_selections (const XMLNode& node)
1938 XMLNodeList nlist;
1939 XMLNodeConstIterator niter;
1940 NamedSelection *ns;
1942 nlist = node.children();
1944 set_dirty();
1946 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1948 if ((ns = XMLNamedSelectionFactory (**niter)) == 0) {
1949 error << _("Session: cannot create Named Selection from XML description.") << endmsg;
1953 return 0;
1956 NamedSelection *
1957 Session::XMLNamedSelectionFactory (const XMLNode& node)
1959 try {
1960 return new NamedSelection (*this, node);
1963 catch (failed_constructor& err) {
1964 return 0;
1968 string
1969 Session::automation_dir () const
1971 return Glib::build_filename (_path, "automation");
1974 string
1975 Session::analysis_dir () const
1977 return Glib::build_filename (_path, "analysis");
1981 Session::load_bundles (XMLNode const & node)
1983 XMLNodeList nlist = node.children();
1984 XMLNodeConstIterator niter;
1986 set_dirty();
1988 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1989 if ((*niter)->name() == "InputBundle") {
1990 add_bundle (boost::shared_ptr<UserBundle> (new UserBundle (**niter, true)));
1991 } else if ((*niter)->name() == "OutputBundle") {
1992 add_bundle (boost::shared_ptr<UserBundle> (new UserBundle (**niter, false)));
1993 } else {
1994 error << string_compose(_("Unknown node \"%1\" found in Bundles list from state file"), (*niter)->name()) << endmsg;
1995 return -1;
1999 return 0;
2003 Session::load_route_groups (const XMLNode& node, int version)
2005 XMLNodeList nlist = node.children();
2006 XMLNodeConstIterator niter;
2008 set_dirty ();
2010 if (version >= 3000) {
2012 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2013 if ((*niter)->name() == "RouteGroup") {
2014 RouteGroup* rg = new RouteGroup (*this, "");
2015 add_route_group (rg);
2016 rg->set_state (**niter, version);
2020 } else if (version < 3000) {
2022 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2023 if ((*niter)->name() == "EditGroup" || (*niter)->name() == "MixGroup") {
2024 RouteGroup* rg = new RouteGroup (*this, "");
2025 add_route_group (rg);
2026 rg->set_state (**niter, version);
2031 return 0;
2034 void
2035 Session::auto_save()
2037 save_state (_current_snapshot_name);
2040 static bool
2041 state_file_filter (const string &str, void */*arg*/)
2043 return (str.length() > strlen(statefile_suffix) &&
2044 str.find (statefile_suffix) == (str.length() - strlen (statefile_suffix)));
2047 struct string_cmp {
2048 bool operator()(const string* a, const string* b) {
2049 return *a < *b;
2053 static string*
2054 remove_end(string* state)
2056 string statename(*state);
2058 string::size_type start,end;
2059 if ((start = statename.find_last_of ('/')) != string::npos) {
2060 statename = statename.substr (start+1);
2063 if ((end = statename.rfind(".ardour")) == string::npos) {
2064 end = statename.length();
2067 return new string(statename.substr (0, end));
2070 vector<string *> *
2071 Session::possible_states (string path)
2073 PathScanner scanner;
2074 vector<string*>* states = scanner (path, state_file_filter, 0, false, false);
2076 transform(states->begin(), states->end(), states->begin(), remove_end);
2078 string_cmp cmp;
2079 sort (states->begin(), states->end(), cmp);
2081 return states;
2084 vector<string *> *
2085 Session::possible_states () const
2087 return possible_states(_path);
2090 void
2091 Session::add_route_group (RouteGroup* g)
2093 _route_groups.push_back (g);
2094 route_group_added (g); /* EMIT SIGNAL */
2095 set_dirty ();
2098 void
2099 Session::remove_route_group (RouteGroup& rg)
2101 list<RouteGroup*>::iterator i;
2103 if ((i = find (_route_groups.begin(), _route_groups.end(), &rg)) != _route_groups.end()) {
2104 _route_groups.erase (i);
2105 delete &rg;
2107 route_group_removed (); /* EMIT SIGNAL */
2112 RouteGroup *
2113 Session::route_group_by_name (string name)
2115 list<RouteGroup *>::iterator i;
2117 for (i = _route_groups.begin(); i != _route_groups.end(); ++i) {
2118 if ((*i)->name() == name) {
2119 return* i;
2122 return 0;
2125 UndoTransaction*
2126 Session::start_reversible_command (const string& name)
2128 UndoTransaction* trans = new UndoTransaction();
2129 trans->set_name(name);
2130 return trans;
2133 void
2134 Session::finish_reversible_command (UndoTransaction& ut)
2136 struct timeval now;
2137 gettimeofday(&now, 0);
2138 ut.set_timestamp(now);
2139 _history.add (&ut);
2142 void
2143 Session::begin_reversible_command(const string& name)
2145 UndoTransaction* trans = new UndoTransaction();
2146 trans->set_name(name);
2148 if (!_current_trans.empty()) {
2149 _current_trans.top()->add_command (trans);
2150 } else {
2151 _current_trans.push(trans);
2155 void
2156 Session::commit_reversible_command(Command *cmd)
2158 assert(!_current_trans.empty());
2159 struct timeval now;
2161 if (cmd) {
2162 _current_trans.top()->add_command(cmd);
2165 if (_current_trans.top()->empty()) {
2166 _current_trans.pop();
2167 return;
2170 gettimeofday(&now, 0);
2171 _current_trans.top()->set_timestamp(now);
2173 _history.add(_current_trans.top());
2174 _current_trans.pop();
2177 static bool
2178 accept_all_non_peak_files (const string& path, void */*arg*/)
2180 return (path.length() > 5 && path.find (peakfile_suffix) != (path.length() - 5));
2183 static bool
2184 accept_all_state_files (const string& path, void */*arg*/)
2186 return (path.length() > 7 && path.find (".ardour") == (path.length() - 7));
2190 Session::find_all_sources (string path, set<string>& result)
2192 XMLTree tree;
2193 XMLNode* node;
2195 if (!tree.read (path)) {
2196 return -1;
2199 if ((node = find_named_node (*tree.root(), "Sources")) == 0) {
2200 return -2;
2203 XMLNodeList nlist;
2204 XMLNodeConstIterator niter;
2206 nlist = node->children();
2208 set_dirty();
2210 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2212 XMLProperty* prop;
2214 if ((prop = (*niter)->property (X_("type"))) == 0) {
2215 continue;
2218 DataType type (prop->value());
2220 if ((prop = (*niter)->property (X_("name"))) == 0) {
2221 continue;
2224 if (prop->value()[0] == '/') {
2225 /* external file, ignore */
2226 continue;
2229 Glib::ustring found_path;
2230 bool is_new;
2231 uint16_t chan;
2233 if (FileSource::find (type, prop->value(), true, is_new, chan, found_path)) {
2234 result.insert (found_path);
2238 return 0;
2242 Session::find_all_sources_across_snapshots (set<string>& result, bool exclude_this_snapshot)
2244 PathScanner scanner;
2245 vector<string*>* state_files;
2246 string ripped;
2247 string this_snapshot_path;
2249 result.clear ();
2251 ripped = _path;
2253 if (ripped[ripped.length()-1] == '/') {
2254 ripped = ripped.substr (0, ripped.length() - 1);
2257 state_files = scanner (ripped, accept_all_state_files, (void *) 0, false, true);
2259 if (state_files == 0) {
2260 /* impossible! */
2261 return 0;
2264 this_snapshot_path = _path;
2265 this_snapshot_path += legalize_for_path (_current_snapshot_name);
2266 this_snapshot_path += statefile_suffix;
2268 for (vector<string*>::iterator i = state_files->begin(); i != state_files->end(); ++i) {
2270 if (exclude_this_snapshot && **i == this_snapshot_path) {
2271 continue;
2274 if (find_all_sources (**i, result) < 0) {
2275 return -1;
2279 return 0;
2282 struct RegionCounter {
2283 typedef std::map<PBD::ID,boost::shared_ptr<AudioSource> > AudioSourceList;
2284 AudioSourceList::iterator iter;
2285 boost::shared_ptr<Region> region;
2286 uint32_t count;
2288 RegionCounter() : count (0) {}
2292 Session::ask_about_playlist_deletion (boost::shared_ptr<Playlist> p)
2294 return *AskAboutPlaylistDeletion (p);
2298 Session::cleanup_sources (CleanupReport& rep)
2300 // FIXME: needs adaptation to midi
2302 vector<boost::shared_ptr<Source> > dead_sources;
2303 PathScanner scanner;
2304 string sound_path;
2305 vector<space_and_path>::iterator i;
2306 vector<space_and_path>::iterator nexti;
2307 vector<string*>* soundfiles;
2308 vector<string> unused;
2309 set<string> all_sources;
2310 bool used;
2311 string spath;
2312 int ret = -1;
2314 _state_of_the_state = (StateOfTheState) (_state_of_the_state | InCleanup);
2316 /* step 1: consider deleting all unused playlists */
2318 if (playlists->maybe_delete_unused (boost::bind (Session::ask_about_playlist_deletion, _1))) {
2319 ret = 0;
2320 goto out;
2323 /* step 2: find all un-used sources */
2325 rep.paths.clear ();
2326 rep.space = 0;
2328 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ) {
2330 SourceMap::iterator tmp;
2332 tmp = i;
2333 ++tmp;
2335 /* do not bother with files that are zero size, otherwise we remove the current "nascent"
2336 capture files.
2339 if (!playlists->source_use_count(i->second) && i->second->length(i->second->timeline_position()) > 0) {
2340 dead_sources.push_back (i->second);
2341 i->second->drop_references ();
2344 i = tmp;
2347 /* build a list of all the possible sound directories for the session */
2349 for (i = session_dirs.begin(); i != session_dirs.end(); ) {
2351 nexti = i;
2352 ++nexti;
2354 SessionDirectory sdir ((*i).path);
2355 sound_path += sdir.sound_path().to_string();
2357 if (nexti != session_dirs.end()) {
2358 sound_path += ':';
2361 i = nexti;
2364 /* now do the same thing for the files that ended up in the sounds dir(s)
2365 but are not referenced as sources in any snapshot.
2368 soundfiles = scanner (sound_path, accept_all_non_peak_files, (void *) 0, false, true);
2370 if (soundfiles == 0) {
2371 return 0;
2374 /* find all sources, but don't use this snapshot because the
2375 state file on disk still references sources we may have already
2376 dropped.
2379 find_all_sources_across_snapshots (all_sources, true);
2381 /* add our current source list
2384 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ++i) {
2385 boost::shared_ptr<FileSource> fs;
2387 if ((fs = boost::dynamic_pointer_cast<FileSource> (i->second)) != 0) {
2388 all_sources.insert (fs->path());
2392 char tmppath1[PATH_MAX+1];
2393 char tmppath2[PATH_MAX+1];
2395 for (vector<string*>::iterator x = soundfiles->begin(); x != soundfiles->end(); ++x) {
2397 used = false;
2398 spath = **x;
2400 for (set<string>::iterator i = all_sources.begin(); i != all_sources.end(); ++i) {
2402 realpath(spath.c_str(), tmppath1);
2403 realpath((*i).c_str(), tmppath2);
2405 if (strcmp(tmppath1, tmppath2) == 0) {
2406 used = true;
2407 break;
2411 if (!used) {
2412 unused.push_back (spath);
2416 /* now try to move all unused files into the "dead_sounds" directory(ies) */
2418 for (vector<string>::iterator x = unused.begin(); x != unused.end(); ++x) {
2419 struct stat statbuf;
2421 rep.paths.push_back (*x);
2422 if (stat ((*x).c_str(), &statbuf) == 0) {
2423 rep.space += statbuf.st_size;
2426 string newpath;
2428 /* don't move the file across filesystems, just
2429 stick it in the `dead_sound_dir_name' directory
2430 on whichever filesystem it was already on.
2433 if ((*x).find ("/sounds/") != string::npos) {
2435 /* old school, go up 1 level */
2437 newpath = Glib::path_get_dirname (*x); // "sounds"
2438 newpath = Glib::path_get_dirname (newpath); // "session-name"
2440 } else {
2442 /* new school, go up 4 levels */
2444 newpath = Glib::path_get_dirname (*x); // "audiofiles"
2445 newpath = Glib::path_get_dirname (newpath); // "session-name"
2446 newpath = Glib::path_get_dirname (newpath); // "interchange"
2447 newpath = Glib::path_get_dirname (newpath); // "session-dir"
2450 newpath += '/';
2451 newpath += dead_sound_dir_name;
2453 if (g_mkdir_with_parents (newpath.c_str(), 0755) < 0) {
2454 error << string_compose(_("Session: cannot create session peakfile folder \"%1\" (%2)"), newpath, strerror (errno)) << endmsg;
2455 return -1;
2458 newpath += '/';
2459 newpath += Glib::path_get_basename ((*x));
2461 if (access (newpath.c_str(), F_OK) == 0) {
2463 /* the new path already exists, try versioning */
2465 char buf[PATH_MAX+1];
2466 int version = 1;
2467 string newpath_v;
2469 snprintf (buf, sizeof (buf), "%s.%d", newpath.c_str(), version);
2470 newpath_v = buf;
2472 while (access (newpath_v.c_str(), F_OK) == 0 && version < 999) {
2473 snprintf (buf, sizeof (buf), "%s.%d", newpath.c_str(), ++version);
2474 newpath_v = buf;
2477 if (version == 999) {
2478 error << string_compose (_("there are already 1000 files with names like %1; versioning discontinued"),
2479 newpath)
2480 << endmsg;
2481 } else {
2482 newpath = newpath_v;
2485 } else {
2487 /* it doesn't exist, or we can't read it or something */
2491 if (::rename ((*x).c_str(), newpath.c_str()) != 0) {
2492 error << string_compose (_("cannot rename audio file source from %1 to %2 (%3)"),
2493 (*x), newpath, strerror (errno))
2494 << endmsg;
2495 goto out;
2498 /* see if there an easy to find peakfile for this file, and remove it.
2501 string peakpath = (*x).substr (0, (*x).find_last_of ('.'));
2502 peakpath += peakfile_suffix;
2504 if (access (peakpath.c_str(), W_OK) == 0) {
2505 if (::unlink (peakpath.c_str()) != 0) {
2506 error << string_compose (_("cannot remove peakfile %1 for %2 (%3)"),
2507 peakpath, _path, strerror (errno))
2508 << endmsg;
2509 /* try to back out */
2510 rename (newpath.c_str(), _path.c_str());
2511 goto out;
2516 ret = 0;
2518 /* dump the history list */
2520 _history.clear ();
2522 /* save state so we don't end up a session file
2523 referring to non-existent sources.
2526 save_state ("");
2528 out:
2529 _state_of_the_state = (StateOfTheState) (_state_of_the_state & ~InCleanup);
2531 return ret;
2535 Session::cleanup_trash_sources (CleanupReport& rep)
2537 // FIXME: needs adaptation for MIDI
2539 vector<space_and_path>::iterator i;
2540 string dead_sound_dir;
2541 struct dirent* dentry;
2542 struct stat statbuf;
2543 DIR* dead;
2545 rep.paths.clear ();
2546 rep.space = 0;
2548 for (i = session_dirs.begin(); i != session_dirs.end(); ++i) {
2550 dead_sound_dir = (*i).path;
2551 dead_sound_dir += dead_sound_dir_name;
2553 if ((dead = opendir (dead_sound_dir.c_str())) == 0) {
2554 continue;
2557 while ((dentry = readdir (dead)) != 0) {
2559 /* avoid '.' and '..' */
2561 if ((dentry->d_name[0] == '.' && dentry->d_name[1] == '\0') ||
2562 (dentry->d_name[2] == '\0' && dentry->d_name[0] == '.' && dentry->d_name[1] == '.')) {
2563 continue;
2566 string fullpath;
2568 fullpath = dead_sound_dir;
2569 fullpath += '/';
2570 fullpath += dentry->d_name;
2572 if (stat (fullpath.c_str(), &statbuf)) {
2573 continue;
2576 if (!S_ISREG (statbuf.st_mode)) {
2577 continue;
2580 if (unlink (fullpath.c_str())) {
2581 error << string_compose (_("cannot remove dead sound file %1 (%2)"),
2582 fullpath, strerror (errno))
2583 << endmsg;
2586 rep.paths.push_back (dentry->d_name);
2587 rep.space += statbuf.st_size;
2590 closedir (dead);
2594 return 0;
2597 void
2598 Session::set_dirty ()
2600 bool was_dirty = dirty();
2602 _state_of_the_state = StateOfTheState (_state_of_the_state | Dirty);
2605 if (!was_dirty) {
2606 DirtyChanged(); /* EMIT SIGNAL */
2611 void
2612 Session::set_clean ()
2614 bool was_dirty = dirty();
2616 _state_of_the_state = Clean;
2619 if (was_dirty) {
2620 DirtyChanged(); /* EMIT SIGNAL */
2624 void
2625 Session::set_deletion_in_progress ()
2627 _state_of_the_state = StateOfTheState (_state_of_the_state | Deletion);
2630 void
2631 Session::clear_deletion_in_progress ()
2633 _state_of_the_state = StateOfTheState (_state_of_the_state & (~Deletion));
2636 void
2637 Session::add_controllable (boost::shared_ptr<Controllable> c)
2639 /* this adds a controllable to the list managed by the Session.
2640 this is a subset of those managed by the Controllable class
2641 itself, and represents the only ones whose state will be saved
2642 as part of the session.
2645 Glib::Mutex::Lock lm (controllables_lock);
2646 controllables.insert (c);
2649 struct null_deleter { void operator()(void const *) const {} };
2651 void
2652 Session::remove_controllable (Controllable* c)
2654 if (_state_of_the_state | Deletion) {
2655 return;
2658 Glib::Mutex::Lock lm (controllables_lock);
2660 Controllables::iterator x = controllables.find (boost::shared_ptr<Controllable>(c, null_deleter()));
2662 if (x != controllables.end()) {
2663 controllables.erase (x);
2667 boost::shared_ptr<Controllable>
2668 Session::controllable_by_id (const PBD::ID& id)
2670 Glib::Mutex::Lock lm (controllables_lock);
2672 for (Controllables::iterator i = controllables.begin(); i != controllables.end(); ++i) {
2673 if ((*i)->id() == id) {
2674 return *i;
2678 return boost::shared_ptr<Controllable>();
2681 boost::shared_ptr<Controllable>
2682 Session::controllable_by_descriptor (const ControllableDescriptor& desc)
2684 boost::shared_ptr<Controllable> c;
2685 boost::shared_ptr<Route> r;
2687 switch (desc.top_level_type()) {
2688 case ControllableDescriptor::NamedRoute:
2690 std::string str = desc.top_level_name();
2691 if (str == "master") {
2692 r = _master_out;
2693 } else if (str == "control" || str == "listen") {
2694 r = _control_out;
2695 } else {
2696 r = route_by_name (desc.top_level_name());
2698 break;
2701 case ControllableDescriptor::RemoteControlID:
2702 r = route_by_remote_id (desc.rid());
2703 break;
2706 if (!r) {
2707 return c;
2710 switch (desc.subtype()) {
2711 case ControllableDescriptor::Gain:
2712 c = r->gain_control ();
2713 break;
2715 case ControllableDescriptor::Solo:
2716 c = r->solo_control();
2717 break;
2719 case ControllableDescriptor::Mute:
2720 c = r->mute_control();
2721 break;
2723 case ControllableDescriptor::Recenable:
2725 boost::shared_ptr<Track> t = boost::dynamic_pointer_cast<Track>(r);
2727 if (t) {
2728 c = t->rec_enable_control ();
2730 break;
2733 case ControllableDescriptor::Pan:
2734 /* XXX pan control */
2735 break;
2737 case ControllableDescriptor::Balance:
2738 /* XXX simple pan control */
2739 break;
2741 case ControllableDescriptor::PluginParameter:
2743 uint32_t plugin = desc.target (0);
2744 uint32_t parameter_index = desc.target (1);
2746 /* revert to zero based counting */
2748 if (plugin > 0) {
2749 --plugin;
2752 if (parameter_index > 0) {
2753 --parameter_index;
2756 boost::shared_ptr<Processor> p = r->nth_plugin (plugin);
2758 if (p) {
2759 c = boost::dynamic_pointer_cast<ARDOUR::AutomationControl>(
2760 p->data().control(Evoral::Parameter(PluginAutomation, 0, parameter_index)));
2762 break;
2765 case ControllableDescriptor::SendGain:
2767 uint32_t send = desc.target (0);
2769 /* revert to zero-based counting */
2771 if (send > 0) {
2772 --send;
2775 boost::shared_ptr<Processor> p = r->nth_send (send);
2777 if (p) {
2778 boost::shared_ptr<Send> s = boost::dynamic_pointer_cast<Send>(p);
2779 boost::shared_ptr<Amp> a = s->amp();
2781 if (a) {
2782 c = s->amp()->gain_control();
2785 break;
2788 default:
2789 /* relax and return a null pointer */
2790 break;
2793 return c;
2796 void
2797 Session::add_instant_xml (XMLNode& node, bool write_to_config)
2799 if (_writable) {
2800 Stateful::add_instant_xml (node, _path);
2803 if (write_to_config) {
2804 Config->add_instant_xml (node);
2808 XMLNode*
2809 Session::instant_xml (const string& node_name)
2811 return Stateful::instant_xml (node_name, _path);
2815 Session::save_history (string snapshot_name)
2817 XMLTree tree;
2819 if (!_writable) {
2820 return 0;
2823 if (snapshot_name.empty()) {
2824 snapshot_name = _current_snapshot_name;
2827 const string history_filename = legalize_for_path (snapshot_name) + history_suffix;
2828 const string backup_filename = history_filename + backup_suffix;
2829 const sys::path xml_path = _session_dir->root_path() / history_filename;
2830 const sys::path backup_path = _session_dir->root_path() / backup_filename;
2832 if (sys::exists (xml_path)) {
2835 sys::rename (xml_path, backup_path);
2837 catch (const sys::filesystem_error& err)
2839 error << _("could not backup old history file, current history not saved") << endmsg;
2840 return -1;
2844 if (!Config->get_save_history() || Config->get_saved_history_depth() < 0) {
2845 return 0;
2848 tree.set_root (&_history.get_state (Config->get_saved_history_depth()));
2850 if (!tree.write (xml_path.to_string()))
2852 error << string_compose (_("history could not be saved to %1"), xml_path.to_string()) << endmsg;
2856 sys::remove (xml_path);
2857 sys::rename (backup_path, xml_path);
2859 catch (const sys::filesystem_error& err)
2861 error << string_compose (_("could not restore history file from backup %1 (%2)"),
2862 backup_path.to_string(), err.what()) << endmsg;
2865 return -1;
2868 return 0;
2872 Session::restore_history (string snapshot_name)
2874 XMLTree tree;
2876 if (snapshot_name.empty()) {
2877 snapshot_name = _current_snapshot_name;
2880 const string xml_filename = legalize_for_path (snapshot_name) + history_suffix;
2881 const sys::path xml_path = _session_dir->root_path() / xml_filename;
2883 info << "Loading history from " << xml_path.to_string() << endmsg;
2885 if (!sys::exists (xml_path)) {
2886 info << string_compose (_("%1: no history file \"%2\" for this session."),
2887 _name, xml_path.to_string()) << endmsg;
2888 return 1;
2891 if (!tree.read (xml_path.to_string())) {
2892 error << string_compose (_("Could not understand session history file \"%1\""),
2893 xml_path.to_string()) << endmsg;
2894 return -1;
2897 // replace history
2898 _history.clear();
2900 for (XMLNodeConstIterator it = tree.root()->children().begin(); it != tree.root()->children().end(); it++) {
2902 XMLNode *t = *it;
2903 UndoTransaction* ut = new UndoTransaction ();
2904 struct timeval tv;
2906 ut->set_name(t->property("name")->value());
2907 stringstream ss(t->property("tv-sec")->value());
2908 ss >> tv.tv_sec;
2909 ss.str(t->property("tv-usec")->value());
2910 ss >> tv.tv_usec;
2911 ut->set_timestamp(tv);
2913 for (XMLNodeConstIterator child_it = t->children().begin();
2914 child_it != t->children().end(); child_it++)
2916 XMLNode *n = *child_it;
2917 Command *c;
2919 if (n->name() == "MementoCommand" ||
2920 n->name() == "MementoUndoCommand" ||
2921 n->name() == "MementoRedoCommand") {
2923 if ((c = memento_command_factory(n))) {
2924 ut->add_command(c);
2927 } else if (n->name() == "DeltaCommand") {
2928 PBD::ID id(n->property("midi-source")->value());
2929 boost::shared_ptr<MidiSource> midi_source =
2930 boost::dynamic_pointer_cast<MidiSource, Source>(source_by_id(id));
2931 if (midi_source) {
2932 ut->add_command(new MidiModel::DeltaCommand(midi_source->model(), *n));
2933 } else {
2934 error << _("Failed to downcast MidiSource for DeltaCommand") << endmsg;
2937 } else if (n->name() == "DiffCommand") {
2938 PBD::ID id(n->property("midi-source")->value());
2939 boost::shared_ptr<MidiSource> midi_source =
2940 boost::dynamic_pointer_cast<MidiSource, Source>(source_by_id(id));
2941 if (midi_source) {
2942 ut->add_command(new MidiModel::DiffCommand(midi_source->model(), *n));
2943 } else {
2944 error << _("Failed to downcast MidiSource for DeltaCommand") << endmsg;
2947 } else {
2948 error << string_compose(_("Couldn't figure out how to make a Command out of a %1 XMLNode."), n->name()) << endmsg;
2952 _history.add (ut);
2955 return 0;
2958 void
2959 Session::config_changed (std::string p, bool ours)
2961 if (ours) {
2962 set_dirty ();
2965 if (p == "seamless-loop") {
2967 } else if (p == "rf-speed") {
2969 } else if (p == "auto-loop") {
2971 } else if (p == "auto-input") {
2973 if (Config->get_monitoring_model() == HardwareMonitoring && transport_rolling()) {
2974 /* auto-input only makes a difference if we're rolling */
2976 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
2978 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
2979 if ((*i)->record_enabled ()) {
2980 (*i)->monitor_input (!config.get_auto_input());
2985 } else if (p == "punch-in") {
2987 Location* location;
2989 if ((location = _locations.auto_punch_location()) != 0) {
2991 if (config.get_punch_in ()) {
2992 replace_event (SessionEvent::PunchIn, location->start());
2993 } else {
2994 remove_event (location->start(), SessionEvent::PunchIn);
2998 } else if (p == "punch-out") {
3000 Location* location;
3002 if ((location = _locations.auto_punch_location()) != 0) {
3004 if (config.get_punch_out()) {
3005 replace_event (SessionEvent::PunchOut, location->end());
3006 } else {
3007 clear_events (SessionEvent::PunchOut);
3011 } else if (p == "edit-mode") {
3013 Glib::Mutex::Lock lm (playlists->lock);
3015 for (SessionPlaylists::List::iterator i = playlists->playlists.begin(); i != playlists->playlists.end(); ++i) {
3016 (*i)->set_edit_mode (Config->get_edit_mode ());
3019 } else if (p == "use-video-sync") {
3021 waiting_for_sync_offset = config.get_use_video_sync();
3023 } else if (p == "mmc-control") {
3025 //poke_midi_thread ();
3027 } else if (p == "mmc-device-id" || p == "mmc-receive-id") {
3029 if (mmc) {
3030 mmc->set_receive_device_id (Config->get_mmc_receive_device_id());
3033 } else if (p == "mmc-send-id") {
3035 if (mmc) {
3036 mmc->set_send_device_id (Config->get_mmc_send_device_id());
3039 } else if (p == "midi-control") {
3041 //poke_midi_thread ();
3043 } else if (p == "raid-path") {
3045 setup_raid_path (config.get_raid_path());
3047 } else if (p == "timecode-format") {
3049 sync_time_vars ();
3051 } else if (p == "video-pullup") {
3053 sync_time_vars ();
3055 } else if (p == "seamless-loop") {
3057 if (play_loop && transport_rolling()) {
3058 // to reset diskstreams etc
3059 request_play_loop (true);
3062 } else if (p == "rf-speed") {
3064 cumulative_rf_motion = 0;
3065 reset_rf_scale (0);
3067 } else if (p == "click-sound") {
3069 setup_click_sounds (1);
3071 } else if (p == "click-emphasis-sound") {
3073 setup_click_sounds (-1);
3075 } else if (p == "clicking") {
3077 if (Config->get_clicking()) {
3078 if (_click_io && click_data) { // don't require emphasis data
3079 _clicking = true;
3081 } else {
3082 _clicking = false;
3085 } else if (p == "send-mtc") {
3087 /* only set the internal flag if we have
3088 a port.
3091 if (_mtc_port != 0) {
3092 session_send_mtc = Config->get_send_mtc();
3093 if (session_send_mtc) {
3094 /* mark us ready to send */
3095 next_quarter_frame_to_send = 0;
3097 } else {
3098 session_send_mtc = false;
3101 } else if (p == "send-mmc") {
3103 /* only set the internal flag if we have
3104 a port.
3107 if (_mmc_port != 0) {
3108 session_send_mmc = Config->get_send_mmc();
3109 } else {
3110 mmc = 0;
3111 session_send_mmc = false;
3114 } else if (p == "midi-feedback") {
3116 /* only set the internal flag if we have
3117 a port.
3120 if (_mtc_port != 0) {
3121 session_midi_feedback = Config->get_midi_feedback();
3124 } else if (p == "jack-time-master") {
3126 engine().reset_timebase ();
3128 } else if (p == "native-file-header-format") {
3130 if (!first_file_header_format_reset) {
3131 reset_native_file_format ();
3134 first_file_header_format_reset = false;
3136 } else if (p == "native-file-data-format") {
3138 if (!first_file_data_format_reset) {
3139 reset_native_file_format ();
3142 first_file_data_format_reset = false;
3144 } else if (p == "external-sync") {
3145 if (!config.get_external_sync()) {
3146 drop_sync_source ();
3147 } else {
3148 switch_to_sync_source (config.get_sync_source());
3150 } else if (p == "remote-model") {
3151 set_remote_control_ids ();
3152 } else if (p == "denormal-model") {
3153 setup_fpu ();
3154 } else if (p == "history-depth") {
3155 set_history_depth (Config->get_history_depth());
3156 } else if (p == "sync-all-route-ordering") {
3157 sync_order_keys ("session");
3158 } else if (p == "initial-program-change") {
3160 if (_mmc_port && Config->get_initial_program_change() >= 0) {
3161 MIDI::byte buf[2];
3163 buf[0] = MIDI::program; // channel zero by default
3164 buf[1] = (Config->get_initial_program_change() & 0x7f);
3166 _mmc_port->midimsg (buf, sizeof (buf), 0);
3168 } else if (p == "initial-program-change") {
3170 if (_mmc_port && Config->get_initial_program_change() >= 0) {
3171 MIDI::byte* buf = new MIDI::byte[2];
3173 buf[0] = MIDI::program; // channel zero by default
3174 buf[1] = (Config->get_initial_program_change() & 0x7f);
3175 // deliver_midi (_mmc_port, buf, 2);
3177 } else if (p == "solo-mute-override") {
3178 // catch_up_on_solo_mute_override ();
3179 } else if (p == "listen-position") {
3180 listen_position_changed ();
3181 } else if (p == "solo-control-is-listen-control") {
3182 solo_control_mode_changed ();
3186 set_dirty ();
3189 void
3190 Session::set_history_depth (uint32_t d)
3192 _history.set_depth (d);