would you look at that! all those changes just to make the auditioner work again...
[ardour2.git] / libs / ardour / session_state.cc
blob4c0dcfd72d51735c5d7b91fe9ba0581327b00d8a
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"
67 #include "pbd/convert.h"
69 #include "ardour/amp.h"
70 #include "ardour/audio_diskstream.h"
71 #include "ardour/audio_track.h"
72 #include "ardour/audioengine.h"
73 #include "ardour/audiofilesource.h"
74 #include "ardour/audioplaylist.h"
75 #include "ardour/audioregion.h"
76 #include "ardour/auditioner.h"
77 #include "ardour/buffer.h"
78 #include "ardour/butler.h"
79 #include "ardour/configuration.h"
80 #include "ardour/control_protocol_manager.h"
81 #include "ardour/crossfade.h"
82 #include "ardour/cycle_timer.h"
83 #include "ardour/directory_names.h"
84 #include "ardour/filename_extensions.h"
85 #include "ardour/io_processor.h"
86 #include "ardour/location.h"
87 #include "ardour/midi_diskstream.h"
88 #include "ardour/midi_patch_manager.h"
89 #include "ardour/midi_playlist.h"
90 #include "ardour/midi_region.h"
91 #include "ardour/midi_source.h"
92 #include "ardour/midi_track.h"
93 #include "ardour/named_selection.h"
94 #include "ardour/processor.h"
95 #include "ardour/region_factory.h"
96 #include "ardour/route_group.h"
97 #include "ardour/send.h"
98 #include "ardour/session.h"
99 #include "ardour/session_directory.h"
100 #include "ardour/session_metadata.h"
101 #include "ardour/session_state_utils.h"
102 #include "ardour/session_playlists.h"
103 #include "ardour/session_utils.h"
104 #include "ardour/silentfilesource.h"
105 #include "ardour/slave.h"
106 #include "ardour/smf_source.h"
107 #include "ardour/sndfile_helpers.h"
108 #include "ardour/sndfilesource.h"
109 #include "ardour/source_factory.h"
110 #include "ardour/template_utils.h"
111 #include "ardour/tempo.h"
112 #include "ardour/ticker.h"
113 #include "ardour/user_bundle.h"
114 #include "ardour/utils.h"
115 #include "ardour/utils.h"
116 #include "ardour/version.h"
117 #include "ardour/playlist_factory.h"
119 #include "control_protocol/control_protocol.h"
121 #include "i18n.h"
122 #include <locale.h>
124 using namespace std;
125 using namespace ARDOUR;
126 using namespace PBD;
128 void
129 Session::first_stage_init (string fullpath, string snapshot_name)
131 if (fullpath.length() == 0) {
132 destroy ();
133 throw failed_constructor();
136 char buf[PATH_MAX+1];
137 if (!realpath (fullpath.c_str(), buf) && (errno != ENOENT)) {
138 error << string_compose(_("Could not use path %1 (%s)"), buf, strerror(errno)) << endmsg;
139 destroy ();
140 throw failed_constructor();
143 _path = string(buf);
145 if (_path[_path.length()-1] != '/') {
146 _path += '/';
149 if (Glib::file_test (_path, Glib::FILE_TEST_EXISTS) && ::access (_path.c_str(), W_OK)) {
150 _writable = false;
151 } else {
152 _writable = true;
155 /* these two are just provisional settings. set_state()
156 will likely override them.
159 _name = _current_snapshot_name = snapshot_name;
161 set_history_depth (Config->get_history_depth());
163 _current_frame_rate = _engine.frame_rate ();
164 _nominal_frame_rate = _current_frame_rate;
165 _base_frame_rate = _current_frame_rate;
167 _tempo_map = new TempoMap (_current_frame_rate);
168 _tempo_map->PropertyChanged.connect_same_thread (*this, boost::bind (&Session::tempo_map_changed, this, _1));
171 _non_soloed_outs_muted = false;
172 _listen_cnt = 0;
173 g_atomic_int_set (&processing_prohibited, 0);
174 _transport_speed = 0;
175 _last_transport_speed = 0;
176 _target_transport_speed = 0;
177 auto_play_legal = false;
178 transport_sub_state = 0;
179 _transport_frame = 0;
180 _requested_return_frame = -1;
181 end_location = new Location (0, 0, _("end"), Location::Flags ((Location::IsMark|Location::IsEnd)));
182 start_location = new Location (0, 0, _("start"), Location::Flags ((Location::IsMark|Location::IsStart)));
183 g_atomic_int_set (&_record_status, Disabled);
184 loop_changing = false;
185 play_loop = false;
186 have_looped = false;
187 _last_roll_location = 0;
188 _last_record_location = 0;
189 pending_locate_frame = 0;
190 pending_locate_roll = false;
191 pending_locate_flush = false;
192 state_was_pending = false;
193 set_next_event ();
194 outbound_mtc_timecode_frame = 0;
195 next_quarter_frame_to_send = -1;
196 current_block_size = 0;
197 solo_update_disabled = false;
198 _have_captured = false;
199 _worst_output_latency = 0;
200 _worst_input_latency = 0;
201 _worst_track_latency = 0;
202 _state_of_the_state = StateOfTheState(CannotSave|InitialConnecting|Loading);
203 _was_seamless = Config->get_seamless_loop ();
204 _slave = 0;
205 session_send_mmc = false;
206 session_send_mtc = false;
207 g_atomic_int_set (&_playback_load, 100);
208 g_atomic_int_set (&_capture_load, 100);
209 g_atomic_int_set (&_playback_load_min, 100);
210 g_atomic_int_set (&_capture_load_min, 100);
211 _play_range = false;
212 _exporting = false;
213 _gain_automation_buffer = 0;
214 _pan_automation_buffer = 0;
215 _npan_buffers = 0;
216 pending_abort = false;
217 destructive_index = 0;
218 first_file_data_format_reset = true;
219 first_file_header_format_reset = true;
220 post_export_sync = false;
221 midi_control_ui = 0;
223 AudioDiskstream::allocate_working_buffers();
225 /* default short fade = 15ms */
227 Crossfade::set_short_xfade_length ((nframes_t) floor (config.get_short_xfade_seconds() * frame_rate()));
228 SndFileSource::setup_standard_crossfades (*this, frame_rate());
230 last_mmc_step.tv_sec = 0;
231 last_mmc_step.tv_usec = 0;
232 step_speed = 0.0;
234 /* click sounds are unset by default, which causes us to internal
235 waveforms for clicks.
238 click_length = 0;
239 click_emphasis_length = 0;
240 _clicking = false;
242 process_function = &Session::process_with_events;
244 if (config.get_use_video_sync()) {
245 waiting_for_sync_offset = true;
246 } else {
247 waiting_for_sync_offset = false;
250 last_timecode_when = 0;
251 _timecode_offset = 0;
252 _timecode_offset_negative = true;
253 last_timecode_valid = false;
255 sync_time_vars ();
257 last_rr_session_dir = session_dirs.begin();
258 refresh_disk_space ();
260 // set_default_fade (0.2, 5.0); /* steepness, millisecs */
262 /* slave stuff */
264 average_slave_delta = 1800; // !!! why 1800 ????
265 have_first_delta_accumulator = false;
266 delta_accumulator_cnt = 0;
267 _slave_state = Stopped;
269 _engine.GraphReordered.connect_same_thread (*this, boost::bind (&Session::graph_reordered, this));
271 /* These are all static "per-class" signals */
273 RegionFactory::CheckNewRegion.connect_same_thread (*this, boost::bind (&Session::add_region, this, _1));
274 SourceFactory::SourceCreated.connect_same_thread (*this, boost::bind (&Session::add_source, this, _1));
275 PlaylistFactory::PlaylistCreated.connect_same_thread (*this, boost::bind (&Session::add_playlist, this, _1, _2));
276 Processor::ProcessorCreated.connect_same_thread (*this, boost::bind (&Session::add_processor, this, _1));
277 AutomationList::AutomationListCreated.connect_same_thread (*this, boost::bind (&Session::add_automation_list, this, _1));
278 Controllable::Destroyed.connect_same_thread (*this, boost::bind (&Session::remove_controllable, this, _1));
279 IO::PortCountChanged.connect_same_thread (*this, boost::bind (&Session::ensure_buffers, this, _1));
281 /* stop IO objects from doing stuff until we're ready for them */
283 Delivery::disable_panners ();
284 IO::disable_connecting ();
288 Session::second_stage_init ()
290 AudioFileSource::set_peak_dir (_session_dir->peak_path().to_string());
292 if (!_is_new) {
293 if (load_state (_current_snapshot_name)) {
294 return -1;
296 remove_empty_sounds ();
299 if (_butler->start_thread()) {
300 return -1;
303 if (start_midi_thread ()) {
304 return -1;
307 // set_state() will call setup_raid_path(), but if it's a new session we need
308 // to call setup_raid_path() here.
310 if (state_tree) {
311 if (set_state (*state_tree->root(), Stateful::loading_state_version)) {
312 return -1;
314 } else {
315 setup_raid_path(_path);
318 /* we can't save till after ::when_engine_running() is called,
319 because otherwise we save state with no connections made.
320 therefore, we reset _state_of_the_state because ::set_state()
321 will have cleared it.
323 we also have to include Loading so that any events that get
324 generated between here and the end of ::when_engine_running()
325 will be processed directly rather than queued.
328 _state_of_the_state = StateOfTheState (_state_of_the_state|CannotSave|Loading);
331 _locations.changed.connect_same_thread (*this, boost::bind (&Session::locations_changed, this));
332 _locations.added.connect_same_thread (*this, boost::bind (&Session::locations_added, this, _1));
333 setup_click_sounds (0);
334 setup_midi_control ();
336 /* Pay attention ... */
338 _engine.Halted.connect_same_thread (*this, boost::bind (&Session::engine_halted, this));
339 _engine.Xrun.connect_same_thread (*this, boost::bind (&Session::xrun_recovery, this));
341 try {
342 when_engine_running ();
345 /* handle this one in a different way than all others, so that its clear what happened */
347 catch (AudioEngine::PortRegistrationFailure& err) {
348 error << err.what() << endmsg;
349 return -1;
352 catch (...) {
353 return -1;
356 BootMessage (_("Reset Remote Controls"));
358 send_full_time_code (0);
359 _engine.transport_locate (0);
360 deliver_mmc (MIDI::MachineControl::cmdMmcReset, 0);
361 deliver_mmc (MIDI::MachineControl::cmdLocate, 0);
363 MidiClockTicker::instance().set_session (this);
364 MIDI::Name::MidiPatchManager::instance().set_session (this);
366 /* initial program change will be delivered later; see ::config_changed() */
368 BootMessage (_("Reset Control Protocols"));
370 ControlProtocolManager::instance().set_session (this);
372 config.set_end_marker_is_free (_is_new);
374 _state_of_the_state = Clean;
376 DirtyChanged (); /* EMIT SIGNAL */
378 if (state_was_pending) {
379 save_state (_current_snapshot_name);
380 remove_pending_capture_state ();
381 state_was_pending = false;
384 BootMessage (_("Session loading complete"));
386 return 0;
389 string
390 Session::raid_path () const
392 SearchPath raid_search_path;
394 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
395 raid_search_path += sys::path((*i).path);
398 return raid_search_path.to_string ();
401 void
402 Session::setup_raid_path (string path)
404 if (path.empty()) {
405 return;
408 space_and_path sp;
409 string fspath;
411 session_dirs.clear ();
413 SearchPath search_path(path);
414 SearchPath sound_search_path;
415 SearchPath midi_search_path;
417 for (SearchPath::const_iterator i = search_path.begin(); i != search_path.end(); ++i) {
418 sp.path = (*i).to_string ();
419 sp.blocks = 0; // not needed
420 session_dirs.push_back (sp);
422 SessionDirectory sdir(sp.path);
424 sound_search_path += sdir.sound_path ();
425 midi_search_path += sdir.midi_path ();
428 // set the search path for each data type
429 FileSource::set_search_path (DataType::AUDIO, sound_search_path.to_string ());
430 SMFSource::set_search_path (DataType::MIDI, midi_search_path.to_string ());
432 // reset the round-robin soundfile path thingie
433 last_rr_session_dir = session_dirs.begin();
436 bool
437 Session::path_is_within_session (const std::string& path)
439 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
440 if (path.find ((*i).path) == 0) {
441 return true;
444 return false;
448 Session::ensure_subdirs ()
450 string dir;
452 dir = session_directory().peak_path().to_string();
454 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
455 error << string_compose(_("Session: cannot create session peakfile folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
456 return -1;
459 dir = session_directory().sound_path().to_string();
461 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
462 error << string_compose(_("Session: cannot create session sounds dir \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
463 return -1;
466 dir = session_directory().midi_path().to_string();
468 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
469 error << string_compose(_("Session: cannot create session midi dir \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
470 return -1;
473 dir = session_directory().dead_sound_path().to_string();
475 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
476 error << string_compose(_("Session: cannot create session dead sounds folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
477 return -1;
480 dir = session_directory().export_path().to_string();
482 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
483 error << string_compose(_("Session: cannot create session export folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
484 return -1;
487 dir = analysis_dir ();
489 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
490 error << string_compose(_("Session: cannot create session analysis folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
491 return -1;
494 return 0;
498 Session::create (const string& mix_template, nframes_t initial_length, BusProfile* bus_profile)
501 if (g_mkdir_with_parents (_path.c_str(), 0755) < 0) {
502 error << string_compose(_("Session: cannot create session folder \"%1\" (%2)"), _path, strerror (errno)) << endmsg;
503 return -1;
506 if (ensure_subdirs ()) {
507 return -1;
510 if (!mix_template.empty()) {
511 std::string in_path = mix_template;
513 ifstream in(in_path.c_str());
515 if (in){
516 string out_path = _path;
517 out_path += _name;
518 out_path += statefile_suffix;
520 ofstream out(out_path.c_str());
522 if (out){
523 out << in.rdbuf();
524 return 0;
526 } else {
527 error << string_compose (_("Could not open %1 for writing mix template"), out_path)
528 << endmsg;
529 return -1;
532 } else {
533 error << string_compose (_("Could not open mix template %1 for reading"), in_path)
534 << endmsg;
535 return -1;
540 /* Instantiate metadata */
542 _metadata = new SessionMetadata ();
544 /* set initial start + end point */
546 start_location->set_end (0);
547 _locations.add (start_location);
549 end_location->set_end (initial_length);
550 _locations.add (end_location);
552 _state_of_the_state = Clean;
554 /* set up Master Out and Control Out if necessary */
556 if (bus_profile) {
558 RouteList rl;
559 int control_id = 1;
560 ChanCount count(DataType::AUDIO, bus_profile->master_out_channels);
562 if (bus_profile->master_out_channels) {
563 Route* rt = new Route (*this, _("master"), Route::MasterOut, DataType::AUDIO);
564 if (rt->init ()) {
565 delete rt;
566 return -1;
568 boost_debug_shared_ptr_mark_interesting (rt, "Route");
569 boost::shared_ptr<Route> r (rt);
570 r->input()->ensure_io (count, false, this);
571 r->output()->ensure_io (count, false, this);
572 r->set_remote_control_id (control_id++);
574 rl.push_back (r);
576 if (Config->get_use_monitor_bus()) {
577 Route* rt = new Route (*this, _("monitor"), Route::MonitorOut, DataType::AUDIO);
578 if (rt->init ()) {
579 delete rt;
580 return -1;
582 boost_debug_shared_ptr_mark_interesting (rt, "Route");
583 boost::shared_ptr<Route> r (rt);
584 r->input()->ensure_io (count, false, this);
585 r->output()->ensure_io (count, false, this);
586 r->set_remote_control_id (control_id);
588 rl.push_back (r);
591 } else {
592 /* prohibit auto-connect to master, because there isn't one */
593 bus_profile->output_ac = AutoConnectOption (bus_profile->output_ac & ~AutoConnectMaster);
596 if (!rl.empty()) {
597 add_routes (rl, false);
600 /* this allows the user to override settings with an environment variable.
603 if (no_auto_connect()) {
604 bus_profile->input_ac = AutoConnectOption (0);
605 bus_profile->output_ac = AutoConnectOption (0);
608 Config->set_input_auto_connect (bus_profile->input_ac);
609 Config->set_output_auto_connect (bus_profile->output_ac);
612 save_state ("");
614 return 0;
619 Session::load_diskstreams (const XMLNode& node)
621 XMLNodeList clist;
622 XMLNodeConstIterator citer;
624 clist = node.children();
626 for (citer = clist.begin(); citer != clist.end(); ++citer) {
628 try {
629 /* diskstreams added automatically by DiskstreamCreated handler */
630 if ((*citer)->name() == "AudioDiskstream" || (*citer)->name() == "DiskStream") {
631 AudioDiskstream* dsp (new AudioDiskstream (*this, **citer));
632 boost::shared_ptr<AudioDiskstream> dstream (dsp);
633 add_diskstream (dstream);
634 } else if ((*citer)->name() == "MidiDiskstream") {
635 boost::shared_ptr<MidiDiskstream> dstream (new MidiDiskstream (*this, **citer));
636 add_diskstream (dstream);
637 } else {
638 error << _("Session: unknown diskstream type in XML") << endmsg;
642 catch (failed_constructor& err) {
643 error << _("Session: could not load diskstream via XML state") << endmsg;
644 return -1;
648 return 0;
651 void
652 Session::maybe_write_autosave()
654 if (dirty() && record_status() != Recording) {
655 save_state("", true);
659 void
660 Session::remove_pending_capture_state ()
662 sys::path pending_state_file_path(_session_dir->root_path());
664 pending_state_file_path /= legalize_for_path (_current_snapshot_name) + pending_suffix;
668 sys::remove (pending_state_file_path);
670 catch(sys::filesystem_error& ex)
672 error << string_compose(_("Could remove pending capture state at path \"%1\" (%2)"),
673 pending_state_file_path.to_string(), ex.what()) << endmsg;
677 /** Rename a state file.
678 * @param snapshot_name Snapshot name.
680 void
681 Session::rename_state (string old_name, string new_name)
683 if (old_name == _current_snapshot_name || old_name == _name) {
684 /* refuse to rename the current snapshot or the "main" one */
685 return;
688 const string old_xml_filename = legalize_for_path (old_name) + statefile_suffix;
689 const string new_xml_filename = legalize_for_path (new_name) + statefile_suffix;
691 const sys::path old_xml_path = _session_dir->root_path() / old_xml_filename;
692 const sys::path new_xml_path = _session_dir->root_path() / new_xml_filename;
696 sys::rename (old_xml_path, new_xml_path);
698 catch (const sys::filesystem_error& err)
700 error << string_compose(_("could not rename snapshot %1 to %2 (%3)"),
701 old_name, new_name, err.what()) << endmsg;
705 /** Remove a state file.
706 * @param snapshot_name Snapshot name.
708 void
709 Session::remove_state (string snapshot_name)
711 if (snapshot_name == _current_snapshot_name || snapshot_name == _name) {
712 // refuse to remove the current snapshot or the "main" one
713 return;
716 sys::path xml_path(_session_dir->root_path());
718 xml_path /= legalize_for_path (snapshot_name) + statefile_suffix;
720 if (!create_backup_file (xml_path)) {
721 // don't remove it if a backup can't be made
722 // create_backup_file will log the error.
723 return;
726 // and delete it
727 sys::remove (xml_path);
731 Session::save_state (string snapshot_name, bool pending)
733 XMLTree tree;
734 sys::path xml_path(_session_dir->root_path());
736 if (!_writable || (_state_of_the_state & CannotSave)) {
737 return 1;
740 if (!_engine.connected ()) {
741 error << string_compose (_("the %1 audio engine is not connected and state saving would lose all I/O connections. Session not saved"),
742 PROGRAM_NAME)
743 << endmsg;
744 return 1;
747 /* tell sources we're saving first, in case they write out to a new file
748 * which should be saved with the state rather than the old one */
749 for (SourceMap::const_iterator i = sources.begin(); i != sources.end(); ++i)
750 i->second->session_saved();
752 tree.set_root (&get_state());
754 if (snapshot_name.empty()) {
755 snapshot_name = _current_snapshot_name;
758 if (!pending) {
760 /* proper save: use statefile_suffix (.ardour in English) */
762 xml_path /= legalize_for_path (snapshot_name) + statefile_suffix;
764 /* make a backup copy of the old file */
766 if (sys::exists(xml_path) && !create_backup_file (xml_path)) {
767 // create_backup_file will log the error
768 return -1;
771 } else {
773 /* pending save: use pending_suffix (.pending in English) */
774 xml_path /= legalize_for_path (snapshot_name) + pending_suffix;
777 sys::path tmp_path(_session_dir->root_path());
779 tmp_path /= legalize_for_path (snapshot_name) + temp_suffix;
781 // cerr << "actually writing state to " << xml_path.to_string() << endl;
783 if (!tree.write (tmp_path.to_string())) {
784 error << string_compose (_("state could not be saved to %1"), tmp_path.to_string()) << endmsg;
785 sys::remove (tmp_path);
786 return -1;
788 } else {
790 if (rename (tmp_path.to_string().c_str(), xml_path.to_string().c_str()) != 0) {
791 error << string_compose (_("could not rename temporary session file %1 to %2"),
792 tmp_path.to_string(), xml_path.to_string()) << endmsg;
793 sys::remove (tmp_path);
794 return -1;
798 if (!pending) {
800 save_history (snapshot_name);
802 bool was_dirty = dirty();
804 _state_of_the_state = StateOfTheState (_state_of_the_state & ~Dirty);
806 if (was_dirty) {
807 DirtyChanged (); /* EMIT SIGNAL */
810 StateSaved (snapshot_name); /* EMIT SIGNAL */
813 return 0;
817 Session::restore_state (string snapshot_name)
819 if (load_state (snapshot_name) == 0) {
820 set_state (*state_tree->root(), Stateful::loading_state_version);
823 return 0;
827 Session::load_state (string snapshot_name)
829 delete state_tree;
830 state_tree = 0;
832 state_was_pending = false;
834 /* check for leftover pending state from a crashed capture attempt */
836 sys::path xmlpath(_session_dir->root_path());
837 xmlpath /= legalize_for_path (snapshot_name) + pending_suffix;
839 if (sys::exists (xmlpath)) {
841 /* there is pending state from a crashed capture attempt */
843 if (*AskAboutPendingState()) {
844 state_was_pending = true;
848 if (!state_was_pending) {
849 xmlpath = _session_dir->root_path();
850 xmlpath /= legalize_for_path (snapshot_name) + statefile_suffix;
853 if (!sys::exists (xmlpath)) {
854 error << string_compose(_("%1: session state information file \"%2\" doesn't exist!"), _name, xmlpath.to_string()) << endmsg;
855 return 1;
858 state_tree = new XMLTree;
860 set_dirty();
862 /* writable() really reflects the whole folder, but if for any
863 reason the session state file can't be written to, still
864 make us unwritable.
867 if (::access (xmlpath.to_string().c_str(), W_OK) != 0) {
868 _writable = false;
871 if (!state_tree->read (xmlpath.to_string())) {
872 error << string_compose(_("Could not understand ardour file %1"), xmlpath.to_string()) << endmsg;
873 delete state_tree;
874 state_tree = 0;
875 return -1;
878 XMLNode& root (*state_tree->root());
880 if (root.name() != X_("Session")) {
881 error << string_compose (_("Session file %1 is not a session"), xmlpath.to_string()) << endmsg;
882 delete state_tree;
883 state_tree = 0;
884 return -1;
887 const XMLProperty* prop;
889 if ((prop = root.property ("version")) == 0) {
890 /* no version implies very old version of Ardour */
891 Stateful::loading_state_version = 1000;
892 } else {
893 int major;
894 int minor;
895 int micro;
897 sscanf (prop->value().c_str(), "%d.%d.%d", &major, &minor, &micro);
898 Stateful::loading_state_version = (major * 1000) + minor;
901 if (Stateful::loading_state_version < CURRENT_SESSION_FILE_VERSION) {
903 sys::path backup_path(_session_dir->root_path());
905 backup_path /= legalize_for_path (snapshot_name) + "-1" + statefile_suffix;
907 // only create a backup once
908 if (sys::exists (backup_path)) {
909 return 0;
912 info << string_compose (_("Copying old session file %1 to %2\nUse %2 with %3 versions before 2.0 from now on"),
913 xmlpath.to_string(), backup_path.to_string(), PROGRAM_NAME)
914 << endmsg;
918 sys::copy_file (xmlpath, backup_path);
920 catch(sys::filesystem_error& ex)
922 error << string_compose (_("Unable to make backup of state file %1 (%2)"),
923 xmlpath.to_string(), ex.what())
924 << endmsg;
925 return -1;
929 return 0;
933 Session::load_options (const XMLNode& node)
935 LocaleGuard lg (X_("POSIX"));
936 config.set_variables (node);
937 return 0;
940 XMLNode&
941 Session::get_state()
943 return state(true);
946 XMLNode&
947 Session::get_template()
949 /* if we don't disable rec-enable, diskstreams
950 will believe they need to store their capture
951 sources in their state node.
954 disable_record (false);
956 return state(false);
959 XMLNode&
960 Session::state(bool full_state)
962 XMLNode* node = new XMLNode("Session");
963 XMLNode* child;
965 // store libardour version, just in case
966 char buf[16];
967 snprintf(buf, sizeof(buf), "%d.%d.%d", libardour3_major_version, libardour3_minor_version, libardour3_micro_version);
968 node->add_property("version", string(buf));
970 /* store configuration settings */
972 if (full_state) {
974 node->add_property ("name", _name);
975 snprintf (buf, sizeof (buf), "%" PRId32, _nominal_frame_rate);
976 node->add_property ("sample-rate", buf);
978 if (session_dirs.size() > 1) {
980 string p;
982 vector<space_and_path>::iterator i = session_dirs.begin();
983 vector<space_and_path>::iterator next;
985 ++i; /* skip the first one */
986 next = i;
987 ++next;
989 while (i != session_dirs.end()) {
991 p += (*i).path;
993 if (next != session_dirs.end()) {
994 p += ':';
995 } else {
996 break;
999 ++next;
1000 ++i;
1003 child = node->add_child ("Path");
1004 child->add_content (p);
1008 /* save the ID counter */
1010 snprintf (buf, sizeof (buf), "%" PRIu64, ID::counter());
1011 node->add_property ("id-counter", buf);
1013 /* various options */
1015 node->add_child_nocopy (config.get_variables ());
1017 node->add_child_nocopy (_metadata->get_state());
1019 child = node->add_child ("Sources");
1021 if (full_state) {
1022 Glib::Mutex::Lock sl (source_lock);
1024 for (SourceMap::iterator siter = sources.begin(); siter != sources.end(); ++siter) {
1026 /* Don't save information about non-destructive file sources that are empty */
1027 /* FIXME: MIDI breaks if this is made FileSource like it should be... */
1029 boost::shared_ptr<AudioFileSource> fs;
1030 if ((fs = boost::dynamic_pointer_cast<AudioFileSource> (siter->second)) != 0) {
1031 if (!fs->destructive()) {
1032 if (fs->length(fs->timeline_position()) == 0) {
1033 continue;
1038 child->add_child_nocopy (siter->second->get_state());
1042 child = node->add_child ("Regions");
1044 if (full_state) {
1045 Glib::Mutex::Lock rl (region_lock);
1046 const RegionFactory::RegionMap& region_map (RegionFactory::all_regions());
1047 for (RegionFactory::RegionMap::const_iterator i = region_map.begin(); i != region_map.end(); ++i) {
1048 boost::shared_ptr<Region> r = i->second;
1049 /* only store regions not attached to playlists */
1050 if (r->playlist() == 0) {
1051 child->add_child_nocopy (r->state (true));
1056 child = node->add_child ("DiskStreams");
1059 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
1060 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
1061 if (!(*i)->hidden()) {
1062 child->add_child_nocopy ((*i)->get_state());
1067 if (full_state) {
1068 node->add_child_nocopy (_locations.get_state());
1069 } else {
1070 // for a template, just create a new Locations, populate it
1071 // with the default start and end, and get the state for that.
1072 Locations loc;
1073 Location* start = new Location(0, 0, _("start"), Location::Flags ((Location::IsMark|Location::IsStart)));
1074 Location* end = new Location(0, 0, _("end"), Location::Flags ((Location::IsMark|Location::IsEnd)));
1075 start->set_end(0);
1076 loc.add (start);
1077 end->set_end(compute_initial_length());
1078 loc.add (end);
1079 node->add_child_nocopy (loc.get_state());
1082 child = node->add_child ("Bundles");
1084 boost::shared_ptr<BundleList> bundles = _bundles.reader ();
1085 for (BundleList::iterator i = bundles->begin(); i != bundles->end(); ++i) {
1086 boost::shared_ptr<UserBundle> b = boost::dynamic_pointer_cast<UserBundle> (*i);
1087 if (b) {
1088 child->add_child_nocopy (b->get_state());
1093 child = node->add_child ("Routes");
1095 boost::shared_ptr<RouteList> r = routes.reader ();
1097 RoutePublicOrderSorter cmp;
1098 RouteList public_order (*r);
1099 public_order.sort (cmp);
1101 /* the sort should have put control outs first */
1103 if (_monitor_out) {
1104 assert (_monitor_out == public_order.front());
1107 for (RouteList::iterator i = public_order.begin(); i != public_order.end(); ++i) {
1108 if (!(*i)->is_hidden()) {
1109 if (full_state) {
1110 child->add_child_nocopy ((*i)->get_state());
1111 } else {
1112 child->add_child_nocopy ((*i)->get_template());
1118 playlists->add_state (node, full_state);
1120 child = node->add_child ("RouteGroups");
1121 for (list<RouteGroup *>::iterator i = _route_groups.begin(); i != _route_groups.end(); ++i) {
1122 child->add_child_nocopy ((*i)->get_state());
1125 if (_click_io) {
1126 child = node->add_child ("Click");
1127 child->add_child_nocopy (_click_io->state (full_state));
1130 if (full_state) {
1131 child = node->add_child ("NamedSelections");
1132 for (NamedSelectionList::iterator i = named_selections.begin(); i != named_selections.end(); ++i) {
1133 if (full_state) {
1134 child->add_child_nocopy ((*i)->get_state());
1139 node->add_child_nocopy (_tempo_map->get_state());
1141 node->add_child_nocopy (get_control_protocol_state());
1143 if (_extra_xml) {
1144 node->add_child_copy (*_extra_xml);
1147 return *node;
1150 XMLNode&
1151 Session::get_control_protocol_state ()
1153 ControlProtocolManager& cpm (ControlProtocolManager::instance());
1154 return cpm.get_state();
1158 Session::set_state (const XMLNode& node, int version)
1160 XMLNodeList nlist;
1161 XMLNode* child;
1162 const XMLProperty* prop;
1163 int ret = -1;
1165 _state_of_the_state = StateOfTheState (_state_of_the_state|CannotSave);
1167 if (node.name() != X_("Session")){
1168 fatal << _("programming error: Session: incorrect XML node sent to set_state()") << endmsg;
1169 return -1;
1172 if ((prop = node.property ("version")) != 0) {
1173 version = atoi (prop->value ()) * 1000;
1176 if ((prop = node.property ("name")) != 0) {
1177 _name = prop->value ();
1180 if ((prop = node.property (X_("sample-rate"))) != 0) {
1182 _nominal_frame_rate = atoi (prop->value());
1184 if (_nominal_frame_rate != _current_frame_rate) {
1185 if (*AskAboutSampleRateMismatch (_nominal_frame_rate, _current_frame_rate)) {
1186 return -1;
1191 setup_raid_path(_session_dir->root_path().to_string());
1193 if ((prop = node.property (X_("id-counter"))) != 0) {
1194 uint64_t x;
1195 sscanf (prop->value().c_str(), "%" PRIu64, &x);
1196 ID::init_counter (x);
1197 } else {
1198 /* old sessions used a timebased counter, so fake
1199 the startup ID counter based on a standard
1200 timestamp.
1202 time_t now;
1203 time (&now);
1204 ID::init_counter (now);
1208 IO::disable_connecting ();
1210 /* Object loading order:
1212 Path
1213 Extra
1214 Options/Config
1215 MIDI Control // relies on data from Options/Config
1216 Metadata
1217 Locations
1218 Sources
1219 AudioRegions
1220 AudioDiskstreams
1221 Connections
1222 Routes
1223 RouteGroups
1224 MixGroups
1225 Click
1226 ControlProtocols
1229 if ((child = find_named_node (node, "Extra")) != 0) {
1230 _extra_xml = new XMLNode (*child);
1233 if (((child = find_named_node (node, "Options")) != 0)) { /* old style */
1234 load_options (*child);
1235 } else if ((child = find_named_node (node, "Config")) != 0) { /* new style */
1236 load_options (*child);
1237 } else {
1238 error << _("Session: XML state has no options section") << endmsg;
1241 if (use_config_midi_ports ()) {
1244 if (version >= 3000) {
1245 if ((child = find_named_node (node, "Metadata")) == 0) {
1246 warning << _("Session: XML state has no metadata section") << endmsg;
1247 } else if (_metadata->set_state (*child, version)) {
1248 goto out;
1252 if ((child = find_named_node (node, "Locations")) == 0) {
1253 error << _("Session: XML state has no locations section") << endmsg;
1254 goto out;
1255 } else if (_locations.set_state (*child, version)) {
1256 goto out;
1259 Location* location;
1261 if ((location = _locations.auto_loop_location()) != 0) {
1262 set_auto_loop_location (location);
1265 if ((location = _locations.auto_punch_location()) != 0) {
1266 set_auto_punch_location (location);
1269 if ((location = _locations.end_location()) == 0) {
1270 _locations.add (end_location);
1271 } else {
1272 delete end_location;
1273 end_location = location;
1276 if ((location = _locations.start_location()) == 0) {
1277 _locations.add (start_location);
1278 } else {
1279 delete start_location;
1280 start_location = location;
1283 AudioFileSource::set_header_position_offset (start_location->start());
1285 if ((child = find_named_node (node, "Sources")) == 0) {
1286 error << _("Session: XML state has no sources section") << endmsg;
1287 goto out;
1288 } else if (load_sources (*child)) {
1289 goto out;
1292 if ((child = find_named_node (node, "Regions")) == 0) {
1293 error << _("Session: XML state has no Regions section") << endmsg;
1294 goto out;
1295 } else if (load_regions (*child)) {
1296 goto out;
1299 if ((child = find_named_node (node, "Playlists")) == 0) {
1300 error << _("Session: XML state has no playlists section") << endmsg;
1301 goto out;
1302 } else if (playlists->load (*this, *child)) {
1303 goto out;
1306 if ((child = find_named_node (node, "UnusedPlaylists")) == 0) {
1307 // this is OK
1308 } else if (playlists->load_unused (*this, *child)) {
1309 goto out;
1312 if ((child = find_named_node (node, "NamedSelections")) != 0) {
1313 if (load_named_selections (*child)) {
1314 goto out;
1318 if ((child = find_named_node (node, "DiskStreams")) == 0) {
1319 error << _("Session: XML state has no diskstreams section") << endmsg;
1320 goto out;
1321 } else if (load_diskstreams (*child)) {
1322 goto out;
1325 if (version >= 3000) {
1326 if ((child = find_named_node (node, "Bundles")) == 0) {
1327 warning << _("Session: XML state has no bundles section") << endmsg;
1328 //goto out;
1329 } else {
1330 /* We can't load Bundles yet as they need to be able
1331 to convert from port names to Port objects, which can't happen until
1332 later */
1333 _bundle_xml_node = new XMLNode (*child);
1337 if ((child = find_named_node (node, "TempoMap")) == 0) {
1338 error << _("Session: XML state has no Tempo Map section") << endmsg;
1339 goto out;
1340 } else if (_tempo_map->set_state (*child, version)) {
1341 goto out;
1344 if ((child = find_named_node (node, "Routes")) == 0) {
1345 error << _("Session: XML state has no routes section") << endmsg;
1346 goto out;
1347 } else if (load_routes (*child, version)) {
1348 goto out;
1351 if (version >= 3000) {
1353 if ((child = find_named_node (node, "RouteGroups")) == 0) {
1354 error << _("Session: XML state has no route groups section") << endmsg;
1355 goto out;
1356 } else if (load_route_groups (*child, version)) {
1357 goto out;
1360 } else if (version < 3000) {
1362 if ((child = find_named_node (node, "EditGroups")) == 0) {
1363 error << _("Session: XML state has no edit groups section") << endmsg;
1364 goto out;
1365 } else if (load_route_groups (*child, version)) {
1366 goto out;
1369 if ((child = find_named_node (node, "MixGroups")) == 0) {
1370 error << _("Session: XML state has no mix groups section") << endmsg;
1371 goto out;
1372 } else if (load_route_groups (*child, version)) {
1373 goto out;
1377 if ((child = find_named_node (node, "Click")) == 0) {
1378 warning << _("Session: XML state has no click section") << endmsg;
1379 } else if (_click_io) {
1380 _click_io->set_state (*child, version);
1383 if ((child = find_named_node (node, "ControlProtocols")) != 0) {
1384 ControlProtocolManager::instance().set_protocol_states (*child);
1387 /* here beginneth the second phase ... */
1389 StateReady (); /* EMIT SIGNAL */
1391 return 0;
1393 out:
1394 return ret;
1398 Session::load_routes (const XMLNode& node, int version)
1400 XMLNodeList nlist;
1401 XMLNodeConstIterator niter;
1402 RouteList new_routes;
1404 nlist = node.children();
1406 set_dirty();
1408 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1410 boost::shared_ptr<Route> route (XMLRouteFactory (**niter, version));
1412 if (route == 0) {
1413 error << _("Session: cannot create Route from XML description.") << endmsg;
1414 return -1;
1417 BootMessage (string_compose (_("Loaded track/bus %1"), route->name()));
1419 new_routes.push_back (route);
1422 add_routes (new_routes, false);
1424 return 0;
1427 boost::shared_ptr<Route>
1428 Session::XMLRouteFactory (const XMLNode& node, int version)
1430 boost::shared_ptr<Route> ret;
1432 if (node.name() != "Route") {
1433 return ret;
1436 const XMLProperty* dsprop;
1438 if ((dsprop = node.property (X_("diskstream-id"))) == 0) {
1439 dsprop = node.property (X_("diskstream"));
1442 DataType type = DataType::AUDIO;
1443 const XMLProperty* prop = node.property("default-type");
1445 if (prop) {
1446 type = DataType (prop->value());
1449 assert (type != DataType::NIL);
1451 if (dsprop) {
1453 boost::shared_ptr<Diskstream> ds;
1454 PBD::ID diskstream_id (dsprop->value());
1455 PBD::ID zero ("0");
1457 /* this wierd hack is used when creating
1458 tracks from a template. We have a special
1459 ID for the diskstream that means "you
1460 should create a new diskstream here, not
1461 look for an old one."
1464 if (diskstream_id != zero) {
1466 ds = diskstream_by_id (diskstream_id);
1468 if (!ds) {
1469 error << string_compose (_("cannot find diskstream ID %1"), diskstream_id.to_s()) << endmsg;
1470 return ret;
1474 Track* track;
1476 if (type == DataType::AUDIO) {
1477 track = new AudioTrack (*this, X_("toBeResetFroXML"));
1479 } else {
1480 track = new MidiTrack (*this, X_("toBeResetFroXML"));
1483 if (track->init()) {
1484 delete track;
1485 return ret;
1488 if (ds) {
1489 track->set_diskstream (ds);
1490 } else {
1491 track->use_new_diskstream ();
1494 if (track->set_state (node, version)) {
1495 delete track;
1496 return ret;
1499 boost_debug_shared_ptr_mark_interesting (track, "Track");
1500 ret.reset (track);
1502 } else {
1503 Route* rt = new Route (*this, X_("toBeResetFroXML"));
1505 if (rt->init () == 0 && rt->set_state (node, version) == 0) {
1506 boost_debug_shared_ptr_mark_interesting (rt, "Route");
1507 ret.reset (rt);
1508 } else {
1509 delete rt;
1513 return ret;
1517 Session::load_regions (const XMLNode& node)
1519 XMLNodeList nlist;
1520 XMLNodeConstIterator niter;
1521 boost::shared_ptr<Region> region;
1523 nlist = node.children();
1525 set_dirty();
1527 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1528 if ((region = XMLRegionFactory (**niter, false)) == 0) {
1529 error << _("Session: cannot create Region from XML description.");
1530 const XMLProperty *name = (**niter).property("name");
1532 if (name) {
1533 error << " " << string_compose (_("Can not load state for region '%1'"), name->value());
1536 error << endmsg;
1540 return 0;
1543 boost::shared_ptr<Region>
1544 Session::XMLRegionFactory (const XMLNode& node, bool full)
1546 const XMLProperty* type = node.property("type");
1548 try {
1550 if ( !type || type->value() == "audio" ) {
1552 return boost::shared_ptr<Region>(XMLAudioRegionFactory (node, full));
1554 } else if (type->value() == "midi") {
1556 return boost::shared_ptr<Region>(XMLMidiRegionFactory (node, full));
1560 } catch (failed_constructor& err) {
1561 return boost::shared_ptr<Region> ();
1564 return boost::shared_ptr<Region> ();
1567 boost::shared_ptr<AudioRegion>
1568 Session::XMLAudioRegionFactory (const XMLNode& node, bool /*full*/)
1570 const XMLProperty* prop;
1571 boost::shared_ptr<Source> source;
1572 boost::shared_ptr<AudioSource> as;
1573 SourceList sources;
1574 SourceList master_sources;
1575 uint32_t nchans = 1;
1576 char buf[128];
1578 if (node.name() != X_("Region")) {
1579 return boost::shared_ptr<AudioRegion>();
1582 if ((prop = node.property (X_("channels"))) != 0) {
1583 nchans = atoi (prop->value().c_str());
1586 if ((prop = node.property ("name")) == 0) {
1587 cerr << "no name for this region\n";
1588 abort ();
1591 if ((prop = node.property (X_("source-0"))) == 0) {
1592 if ((prop = node.property ("source")) == 0) {
1593 error << _("Session: XMLNode describing a AudioRegion is incomplete (no source)") << endmsg;
1594 return boost::shared_ptr<AudioRegion>();
1598 PBD::ID s_id (prop->value());
1600 if ((source = source_by_id (s_id)) == 0) {
1601 error << string_compose(_("Session: XMLNode describing a AudioRegion references an unknown source id =%1"), s_id) << endmsg;
1602 return boost::shared_ptr<AudioRegion>();
1605 as = boost::dynamic_pointer_cast<AudioSource>(source);
1606 if (!as) {
1607 error << string_compose(_("Session: XMLNode describing a AudioRegion references a non-audio source id =%1"), s_id) << endmsg;
1608 return boost::shared_ptr<AudioRegion>();
1611 sources.push_back (as);
1613 /* pickup other channels */
1615 for (uint32_t n=1; n < nchans; ++n) {
1616 snprintf (buf, sizeof(buf), X_("source-%d"), n);
1617 if ((prop = node.property (buf)) != 0) {
1619 PBD::ID id2 (prop->value());
1621 if ((source = source_by_id (id2)) == 0) {
1622 error << string_compose(_("Session: XMLNode describing a AudioRegion references an unknown source id =%1"), id2) << endmsg;
1623 return boost::shared_ptr<AudioRegion>();
1626 as = boost::dynamic_pointer_cast<AudioSource>(source);
1627 if (!as) {
1628 error << string_compose(_("Session: XMLNode describing a AudioRegion references a non-audio source id =%1"), id2) << endmsg;
1629 return boost::shared_ptr<AudioRegion>();
1631 sources.push_back (as);
1635 for (uint32_t n = 0; n < nchans; ++n) {
1636 snprintf (buf, sizeof(buf), X_("master-source-%d"), n);
1637 if ((prop = node.property (buf)) != 0) {
1639 PBD::ID id2 (prop->value());
1641 if ((source = source_by_id (id2)) == 0) {
1642 error << string_compose(_("Session: XMLNode describing a AudioRegion references an unknown source id =%1"), id2) << endmsg;
1643 return boost::shared_ptr<AudioRegion>();
1646 as = boost::dynamic_pointer_cast<AudioSource>(source);
1647 if (!as) {
1648 error << string_compose(_("Session: XMLNode describing a AudioRegion references a non-audio source id =%1"), id2) << endmsg;
1649 return boost::shared_ptr<AudioRegion>();
1651 master_sources.push_back (as);
1655 try {
1656 boost::shared_ptr<AudioRegion> region (boost::dynamic_pointer_cast<AudioRegion> (RegionFactory::create (sources, node)));
1658 /* a final detail: this is the one and only place that we know how long missing files are */
1660 if (region->whole_file()) {
1661 for (SourceList::iterator sx = sources.begin(); sx != sources.end(); ++sx) {
1662 boost::shared_ptr<SilentFileSource> sfp = boost::dynamic_pointer_cast<SilentFileSource> (*sx);
1663 if (sfp) {
1664 sfp->set_length (region->length());
1669 if (!master_sources.empty()) {
1670 if (master_sources.size() != nchans) {
1671 error << _("Session: XMLNode describing an AudioRegion is missing some master sources; ignored") << endmsg;
1672 } else {
1673 region->set_master_sources (master_sources);
1677 return region;
1681 catch (failed_constructor& err) {
1682 return boost::shared_ptr<AudioRegion>();
1686 boost::shared_ptr<MidiRegion>
1687 Session::XMLMidiRegionFactory (const XMLNode& node, bool /*full*/)
1689 const XMLProperty* prop;
1690 boost::shared_ptr<Source> source;
1691 boost::shared_ptr<MidiSource> ms;
1692 SourceList sources;
1693 uint32_t nchans = 1;
1695 if (node.name() != X_("Region")) {
1696 return boost::shared_ptr<MidiRegion>();
1699 if ((prop = node.property (X_("channels"))) != 0) {
1700 nchans = atoi (prop->value().c_str());
1703 if ((prop = node.property ("name")) == 0) {
1704 cerr << "no name for this region\n";
1705 abort ();
1708 // Multiple midi channels? that's just crazy talk
1709 assert(nchans == 1);
1711 if ((prop = node.property (X_("source-0"))) == 0) {
1712 if ((prop = node.property ("source")) == 0) {
1713 error << _("Session: XMLNode describing a MidiRegion is incomplete (no source)") << endmsg;
1714 return boost::shared_ptr<MidiRegion>();
1718 PBD::ID s_id (prop->value());
1720 if ((source = source_by_id (s_id)) == 0) {
1721 error << string_compose(_("Session: XMLNode describing a MidiRegion references an unknown source id =%1"), s_id) << endmsg;
1722 return boost::shared_ptr<MidiRegion>();
1725 ms = boost::dynamic_pointer_cast<MidiSource>(source);
1726 if (!ms) {
1727 error << string_compose(_("Session: XMLNode describing a MidiRegion references a non-midi source id =%1"), s_id) << endmsg;
1728 return boost::shared_ptr<MidiRegion>();
1731 sources.push_back (ms);
1733 try {
1734 boost::shared_ptr<MidiRegion> region (boost::dynamic_pointer_cast<MidiRegion> (RegionFactory::create (sources, node)));
1735 /* a final detail: this is the one and only place that we know how long missing files are */
1737 if (region->whole_file()) {
1738 for (SourceList::iterator sx = sources.begin(); sx != sources.end(); ++sx) {
1739 boost::shared_ptr<SilentFileSource> sfp = boost::dynamic_pointer_cast<SilentFileSource> (*sx);
1740 if (sfp) {
1741 sfp->set_length (region->length());
1746 return region;
1749 catch (failed_constructor& err) {
1750 return boost::shared_ptr<MidiRegion>();
1754 XMLNode&
1755 Session::get_sources_as_xml ()
1758 XMLNode* node = new XMLNode (X_("Sources"));
1759 Glib::Mutex::Lock lm (source_lock);
1761 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ++i) {
1762 node->add_child_nocopy (i->second->get_state());
1765 return *node;
1768 string
1769 Session::path_from_region_name (DataType type, string name, string identifier)
1771 char buf[PATH_MAX+1];
1772 uint32_t n;
1773 SessionDirectory sdir(get_best_session_directory_for_new_source());
1774 sys::path source_dir = ((type == DataType::AUDIO)
1775 ? sdir.sound_path() : sdir.midi_path());
1777 string ext = ((type == DataType::AUDIO) ? ".wav" : ".mid");
1779 for (n = 0; n < 999999; ++n) {
1780 if (identifier.length()) {
1781 snprintf (buf, sizeof(buf), "%s%s%" PRIu32 "%s", name.c_str(),
1782 identifier.c_str(), n, ext.c_str());
1783 } else {
1784 snprintf (buf, sizeof(buf), "%s-%" PRIu32 "%s", name.c_str(),
1785 n, ext.c_str());
1788 sys::path source_path = source_dir / buf;
1790 if (!sys::exists (source_path)) {
1791 return source_path.to_string();
1795 error << string_compose (_("cannot create new file from region name \"%1\" with ident = \"%2\": too many existing files with similar names"),
1796 name, identifier)
1797 << endmsg;
1799 return "";
1804 Session::load_sources (const XMLNode& node)
1806 XMLNodeList nlist;
1807 XMLNodeConstIterator niter;
1808 boost::shared_ptr<Source> source;
1810 nlist = node.children();
1812 set_dirty();
1814 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1815 try {
1816 if ((source = XMLSourceFactory (**niter)) == 0) {
1817 error << _("Session: cannot create Source from XML description.") << endmsg;
1819 } catch (MissingSource& err) {
1820 warning << _("A sound file is missing. It will be replaced by silence.") << endmsg;
1821 source = SourceFactory::createSilent (*this, **niter, max_frames, _current_frame_rate);
1825 return 0;
1828 boost::shared_ptr<Source>
1829 Session::XMLSourceFactory (const XMLNode& node)
1831 if (node.name() != "Source") {
1832 return boost::shared_ptr<Source>();
1835 try {
1836 /* note: do peak building in another thread when loading session state */
1837 return SourceFactory::create (*this, node, true);
1840 catch (failed_constructor& err) {
1841 error << string_compose (_("Found a sound file that cannot be used by %1. Talk to the progammers."), PROGRAM_NAME) << endmsg;
1842 return boost::shared_ptr<Source>();
1847 Session::save_template (string template_name)
1849 XMLTree tree;
1851 if (_state_of_the_state & CannotSave) {
1852 return -1;
1855 sys::path user_template_dir(user_template_directory());
1859 sys::create_directories (user_template_dir);
1861 catch(sys::filesystem_error& ex)
1863 error << string_compose(_("Could not create mix templates directory \"%1\" (%2)"),
1864 user_template_dir.to_string(), ex.what()) << endmsg;
1865 return -1;
1868 tree.set_root (&get_template());
1870 sys::path template_file_path(user_template_dir);
1871 template_file_path /= template_name + template_suffix;
1873 if (sys::exists (template_file_path))
1875 warning << string_compose(_("Template \"%1\" already exists - new version not created"),
1876 template_file_path.to_string()) << endmsg;
1877 return -1;
1880 if (!tree.write (template_file_path.to_string())) {
1881 error << _("mix template not saved") << endmsg;
1882 return -1;
1885 return 0;
1889 Session::rename_template (string old_name, string new_name)
1891 sys::path old_path (user_template_directory());
1892 old_path /= old_name + template_suffix;
1894 sys::path new_path(user_template_directory());
1895 new_path /= new_name + template_suffix;
1897 if (sys::exists (new_path)) {
1898 warning << string_compose(_("Template \"%1\" already exists - template not renamed"),
1899 new_path.to_string()) << endmsg;
1900 return -1;
1903 try {
1904 sys::rename (old_path, new_path);
1905 return 0;
1906 } catch (...) {
1907 return -1;
1912 Session::delete_template (string name)
1914 sys::path path = user_template_directory();
1915 path /= name + template_suffix;
1917 try {
1918 sys::remove (path);
1919 return 0;
1920 } catch (...) {
1921 return -1;
1925 void
1926 Session::refresh_disk_space ()
1928 #if HAVE_SYS_VFS_H
1929 struct statfs statfsbuf;
1930 vector<space_and_path>::iterator i;
1931 Glib::Mutex::Lock lm (space_lock);
1932 double scale;
1934 /* get freespace on every FS that is part of the session path */
1936 _total_free_4k_blocks = 0;
1938 for (i = session_dirs.begin(); i != session_dirs.end(); ++i) {
1939 statfs ((*i).path.c_str(), &statfsbuf);
1941 scale = statfsbuf.f_bsize/4096.0;
1943 (*i).blocks = (uint32_t) floor (statfsbuf.f_bavail * scale);
1944 _total_free_4k_blocks += (*i).blocks;
1946 #endif
1949 string
1950 Session::get_best_session_directory_for_new_source ()
1952 vector<space_and_path>::iterator i;
1953 string result = _session_dir->root_path().to_string();
1955 /* handle common case without system calls */
1957 if (session_dirs.size() == 1) {
1958 return result;
1961 /* OK, here's the algorithm we're following here:
1963 We want to select which directory to use for
1964 the next file source to be created. Ideally,
1965 we'd like to use a round-robin process so as to
1966 get maximum performance benefits from splitting
1967 the files across multiple disks.
1969 However, in situations without much diskspace, an
1970 RR approach may end up filling up a filesystem
1971 with new files while others still have space.
1972 Its therefore important to pay some attention to
1973 the freespace in the filesystem holding each
1974 directory as well. However, if we did that by
1975 itself, we'd keep creating new files in the file
1976 system with the most space until it was as full
1977 as all others, thus negating any performance
1978 benefits of this RAID-1 like approach.
1980 So, we use a user-configurable space threshold. If
1981 there are at least 2 filesystems with more than this
1982 much space available, we use RR selection between them.
1983 If not, then we pick the filesystem with the most space.
1985 This gets a good balance between the two
1986 approaches.
1989 refresh_disk_space ();
1991 int free_enough = 0;
1993 for (i = session_dirs.begin(); i != session_dirs.end(); ++i) {
1994 if ((*i).blocks * 4096 >= Config->get_disk_choice_space_threshold()) {
1995 free_enough++;
1999 if (free_enough >= 2) {
2000 /* use RR selection process, ensuring that the one
2001 picked works OK.
2004 i = last_rr_session_dir;
2006 do {
2007 if (++i == session_dirs.end()) {
2008 i = session_dirs.begin();
2011 if ((*i).blocks * 4096 >= Config->get_disk_choice_space_threshold()) {
2012 if (create_session_directory ((*i).path)) {
2013 result = (*i).path;
2014 last_rr_session_dir = i;
2015 return result;
2019 } while (i != last_rr_session_dir);
2021 } else {
2023 /* pick FS with the most freespace (and that
2024 seems to actually work ...)
2027 vector<space_and_path> sorted;
2028 space_and_path_ascending_cmp cmp;
2030 sorted = session_dirs;
2031 sort (sorted.begin(), sorted.end(), cmp);
2033 for (i = sorted.begin(); i != sorted.end(); ++i) {
2034 if (create_session_directory ((*i).path)) {
2035 result = (*i).path;
2036 last_rr_session_dir = i;
2037 return result;
2042 return result;
2046 Session::load_named_selections (const XMLNode& node)
2048 XMLNodeList nlist;
2049 XMLNodeConstIterator niter;
2050 NamedSelection *ns;
2052 nlist = node.children();
2054 set_dirty();
2056 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2058 if ((ns = XMLNamedSelectionFactory (**niter)) == 0) {
2059 error << _("Session: cannot create Named Selection from XML description.") << endmsg;
2063 return 0;
2066 NamedSelection *
2067 Session::XMLNamedSelectionFactory (const XMLNode& node)
2069 try {
2070 return new NamedSelection (*this, node);
2073 catch (failed_constructor& err) {
2074 return 0;
2078 string
2079 Session::automation_dir () const
2081 return Glib::build_filename (_path, "automation");
2084 string
2085 Session::analysis_dir () const
2087 return Glib::build_filename (_path, "analysis");
2091 Session::load_bundles (XMLNode const & node)
2093 XMLNodeList nlist = node.children();
2094 XMLNodeConstIterator niter;
2096 set_dirty();
2098 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2099 if ((*niter)->name() == "InputBundle") {
2100 add_bundle (boost::shared_ptr<UserBundle> (new UserBundle (**niter, true)));
2101 } else if ((*niter)->name() == "OutputBundle") {
2102 add_bundle (boost::shared_ptr<UserBundle> (new UserBundle (**niter, false)));
2103 } else {
2104 error << string_compose(_("Unknown node \"%1\" found in Bundles list from state file"), (*niter)->name()) << endmsg;
2105 return -1;
2109 return 0;
2113 Session::load_route_groups (const XMLNode& node, int version)
2115 XMLNodeList nlist = node.children();
2116 XMLNodeConstIterator niter;
2118 set_dirty ();
2120 if (version >= 3000) {
2122 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2123 if ((*niter)->name() == "RouteGroup") {
2124 RouteGroup* rg = new RouteGroup (*this, "");
2125 add_route_group (rg);
2126 rg->set_state (**niter, version);
2130 } else if (version < 3000) {
2132 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2133 if ((*niter)->name() == "EditGroup" || (*niter)->name() == "MixGroup") {
2134 RouteGroup* rg = new RouteGroup (*this, "");
2135 add_route_group (rg);
2136 rg->set_state (**niter, version);
2141 return 0;
2144 void
2145 Session::auto_save()
2147 save_state (_current_snapshot_name);
2150 static bool
2151 state_file_filter (const string &str, void */*arg*/)
2153 return (str.length() > strlen(statefile_suffix) &&
2154 str.find (statefile_suffix) == (str.length() - strlen (statefile_suffix)));
2157 struct string_cmp {
2158 bool operator()(const string* a, const string* b) {
2159 return *a < *b;
2163 static string*
2164 remove_end(string* state)
2166 string statename(*state);
2168 string::size_type start,end;
2169 if ((start = statename.find_last_of ('/')) != string::npos) {
2170 statename = statename.substr (start+1);
2173 if ((end = statename.rfind(".ardour")) == string::npos) {
2174 end = statename.length();
2177 return new string(statename.substr (0, end));
2180 vector<string *> *
2181 Session::possible_states (string path)
2183 PathScanner scanner;
2184 vector<string*>* states = scanner (path, state_file_filter, 0, false, false);
2186 transform(states->begin(), states->end(), states->begin(), remove_end);
2188 string_cmp cmp;
2189 sort (states->begin(), states->end(), cmp);
2191 return states;
2194 vector<string *> *
2195 Session::possible_states () const
2197 return possible_states(_path);
2200 void
2201 Session::add_route_group (RouteGroup* g)
2203 _route_groups.push_back (g);
2204 route_group_added (g); /* EMIT SIGNAL */
2205 set_dirty ();
2208 void
2209 Session::remove_route_group (RouteGroup& rg)
2211 list<RouteGroup*>::iterator i;
2213 if ((i = find (_route_groups.begin(), _route_groups.end(), &rg)) != _route_groups.end()) {
2214 _route_groups.erase (i);
2215 delete &rg;
2217 route_group_removed (); /* EMIT SIGNAL */
2222 RouteGroup *
2223 Session::route_group_by_name (string name)
2225 list<RouteGroup *>::iterator i;
2227 for (i = _route_groups.begin(); i != _route_groups.end(); ++i) {
2228 if ((*i)->name() == name) {
2229 return* i;
2232 return 0;
2235 UndoTransaction*
2236 Session::start_reversible_command (const string& name)
2238 UndoTransaction* trans = new UndoTransaction();
2239 trans->set_name(name);
2240 return trans;
2243 void
2244 Session::finish_reversible_command (UndoTransaction& ut)
2246 struct timeval now;
2247 gettimeofday(&now, 0);
2248 ut.set_timestamp(now);
2249 _history.add (&ut);
2252 void
2253 Session::begin_reversible_command(const string& name)
2255 UndoTransaction* trans = new UndoTransaction();
2256 trans->set_name(name);
2258 if (!_current_trans.empty()) {
2259 _current_trans.top()->add_command (trans);
2260 } else {
2261 _current_trans.push(trans);
2265 void
2266 Session::commit_reversible_command(Command *cmd)
2268 assert(!_current_trans.empty());
2269 struct timeval now;
2271 if (cmd) {
2272 _current_trans.top()->add_command(cmd);
2275 if (_current_trans.top()->empty()) {
2276 _current_trans.pop();
2277 return;
2280 gettimeofday(&now, 0);
2281 _current_trans.top()->set_timestamp(now);
2283 _history.add(_current_trans.top());
2284 _current_trans.pop();
2287 static bool
2288 accept_all_non_peak_files (const string& path, void */*arg*/)
2290 return (path.length() > 5 && path.find (peakfile_suffix) != (path.length() - 5));
2293 static bool
2294 accept_all_state_files (const string& path, void */*arg*/)
2296 return (path.length() > 7 && path.find (".ardour") == (path.length() - 7));
2300 Session::find_all_sources (string path, set<string>& result)
2302 XMLTree tree;
2303 XMLNode* node;
2305 if (!tree.read (path)) {
2306 return -1;
2309 if ((node = find_named_node (*tree.root(), "Sources")) == 0) {
2310 return -2;
2313 XMLNodeList nlist;
2314 XMLNodeConstIterator niter;
2316 nlist = node->children();
2318 set_dirty();
2320 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2322 XMLProperty* prop;
2324 if ((prop = (*niter)->property (X_("type"))) == 0) {
2325 continue;
2328 DataType type (prop->value());
2330 if ((prop = (*niter)->property (X_("name"))) == 0) {
2331 continue;
2334 if (prop->value()[0] == '/') {
2335 /* external file, ignore */
2336 continue;
2339 Glib::ustring found_path;
2340 bool is_new;
2341 uint16_t chan;
2343 if (FileSource::find (type, prop->value(), true, is_new, chan, found_path)) {
2344 result.insert (found_path);
2348 return 0;
2352 Session::find_all_sources_across_snapshots (set<string>& result, bool exclude_this_snapshot)
2354 PathScanner scanner;
2355 vector<string*>* state_files;
2356 string ripped;
2357 string this_snapshot_path;
2359 result.clear ();
2361 ripped = _path;
2363 if (ripped[ripped.length()-1] == '/') {
2364 ripped = ripped.substr (0, ripped.length() - 1);
2367 state_files = scanner (ripped, accept_all_state_files, (void *) 0, false, true);
2369 if (state_files == 0) {
2370 /* impossible! */
2371 return 0;
2374 this_snapshot_path = _path;
2375 this_snapshot_path += legalize_for_path (_current_snapshot_name);
2376 this_snapshot_path += statefile_suffix;
2378 for (vector<string*>::iterator i = state_files->begin(); i != state_files->end(); ++i) {
2380 if (exclude_this_snapshot && **i == this_snapshot_path) {
2381 continue;
2384 if (find_all_sources (**i, result) < 0) {
2385 return -1;
2389 return 0;
2392 struct RegionCounter {
2393 typedef std::map<PBD::ID,boost::shared_ptr<AudioSource> > AudioSourceList;
2394 AudioSourceList::iterator iter;
2395 boost::shared_ptr<Region> region;
2396 uint32_t count;
2398 RegionCounter() : count (0) {}
2402 Session::ask_about_playlist_deletion (boost::shared_ptr<Playlist> p)
2404 return *AskAboutPlaylistDeletion (p);
2408 Session::cleanup_sources (CleanupReport& rep)
2410 // FIXME: needs adaptation to midi
2412 vector<boost::shared_ptr<Source> > dead_sources;
2413 PathScanner scanner;
2414 string sound_path;
2415 vector<space_and_path>::iterator i;
2416 vector<space_and_path>::iterator nexti;
2417 vector<string*>* soundfiles;
2418 vector<string> unused;
2419 set<string> all_sources;
2420 bool used;
2421 string spath;
2422 int ret = -1;
2424 _state_of_the_state = (StateOfTheState) (_state_of_the_state | InCleanup);
2426 /* step 1: consider deleting all unused playlists */
2428 if (playlists->maybe_delete_unused (boost::bind (Session::ask_about_playlist_deletion, _1))) {
2429 ret = 0;
2430 goto out;
2433 /* step 2: find all un-used sources */
2435 rep.paths.clear ();
2436 rep.space = 0;
2438 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ) {
2440 SourceMap::iterator tmp;
2442 tmp = i;
2443 ++tmp;
2445 /* do not bother with files that are zero size, otherwise we remove the current "nascent"
2446 capture files.
2449 if (!playlists->source_use_count(i->second) && i->second->length(i->second->timeline_position()) > 0) {
2450 dead_sources.push_back (i->second);
2451 i->second->drop_references ();
2454 i = tmp;
2457 /* build a list of all the possible sound directories for the session */
2459 for (i = session_dirs.begin(); i != session_dirs.end(); ) {
2461 nexti = i;
2462 ++nexti;
2464 SessionDirectory sdir ((*i).path);
2465 sound_path += sdir.sound_path().to_string();
2467 if (nexti != session_dirs.end()) {
2468 sound_path += ':';
2471 i = nexti;
2474 /* now do the same thing for the files that ended up in the sounds dir(s)
2475 but are not referenced as sources in any snapshot.
2478 soundfiles = scanner (sound_path, accept_all_non_peak_files, (void *) 0, false, true);
2480 if (soundfiles == 0) {
2481 return 0;
2484 /* find all sources, but don't use this snapshot because the
2485 state file on disk still references sources we may have already
2486 dropped.
2489 find_all_sources_across_snapshots (all_sources, true);
2491 /* add our current source list
2494 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ++i) {
2495 boost::shared_ptr<FileSource> fs;
2497 if ((fs = boost::dynamic_pointer_cast<FileSource> (i->second)) != 0) {
2498 all_sources.insert (fs->path());
2502 char tmppath1[PATH_MAX+1];
2503 char tmppath2[PATH_MAX+1];
2505 for (vector<string*>::iterator x = soundfiles->begin(); x != soundfiles->end(); ++x) {
2507 used = false;
2508 spath = **x;
2510 for (set<string>::iterator i = all_sources.begin(); i != all_sources.end(); ++i) {
2512 realpath(spath.c_str(), tmppath1);
2513 realpath((*i).c_str(), tmppath2);
2515 if (strcmp(tmppath1, tmppath2) == 0) {
2516 used = true;
2517 break;
2521 if (!used) {
2522 unused.push_back (spath);
2526 /* now try to move all unused files into the "dead_sounds" directory(ies) */
2528 for (vector<string>::iterator x = unused.begin(); x != unused.end(); ++x) {
2529 struct stat statbuf;
2531 rep.paths.push_back (*x);
2532 if (stat ((*x).c_str(), &statbuf) == 0) {
2533 rep.space += statbuf.st_size;
2536 string newpath;
2538 /* don't move the file across filesystems, just
2539 stick it in the `dead_sound_dir_name' directory
2540 on whichever filesystem it was already on.
2543 if ((*x).find ("/sounds/") != string::npos) {
2545 /* old school, go up 1 level */
2547 newpath = Glib::path_get_dirname (*x); // "sounds"
2548 newpath = Glib::path_get_dirname (newpath); // "session-name"
2550 } else {
2552 /* new school, go up 4 levels */
2554 newpath = Glib::path_get_dirname (*x); // "audiofiles"
2555 newpath = Glib::path_get_dirname (newpath); // "session-name"
2556 newpath = Glib::path_get_dirname (newpath); // "interchange"
2557 newpath = Glib::path_get_dirname (newpath); // "session-dir"
2560 newpath += '/';
2561 newpath += dead_sound_dir_name;
2563 if (g_mkdir_with_parents (newpath.c_str(), 0755) < 0) {
2564 error << string_compose(_("Session: cannot create session peakfile folder \"%1\" (%2)"), newpath, strerror (errno)) << endmsg;
2565 return -1;
2568 newpath += '/';
2569 newpath += Glib::path_get_basename ((*x));
2571 if (access (newpath.c_str(), F_OK) == 0) {
2573 /* the new path already exists, try versioning */
2575 char buf[PATH_MAX+1];
2576 int version = 1;
2577 string newpath_v;
2579 snprintf (buf, sizeof (buf), "%s.%d", newpath.c_str(), version);
2580 newpath_v = buf;
2582 while (access (newpath_v.c_str(), F_OK) == 0 && version < 999) {
2583 snprintf (buf, sizeof (buf), "%s.%d", newpath.c_str(), ++version);
2584 newpath_v = buf;
2587 if (version == 999) {
2588 error << string_compose (_("there are already 1000 files with names like %1; versioning discontinued"),
2589 newpath)
2590 << endmsg;
2591 } else {
2592 newpath = newpath_v;
2595 } else {
2597 /* it doesn't exist, or we can't read it or something */
2601 if (::rename ((*x).c_str(), newpath.c_str()) != 0) {
2602 error << string_compose (_("cannot rename audio file source from %1 to %2 (%3)"),
2603 (*x), newpath, strerror (errno))
2604 << endmsg;
2605 goto out;
2608 /* see if there an easy to find peakfile for this file, and remove it.
2611 string peakpath = (*x).substr (0, (*x).find_last_of ('.'));
2612 peakpath += peakfile_suffix;
2614 if (access (peakpath.c_str(), W_OK) == 0) {
2615 if (::unlink (peakpath.c_str()) != 0) {
2616 error << string_compose (_("cannot remove peakfile %1 for %2 (%3)"),
2617 peakpath, _path, strerror (errno))
2618 << endmsg;
2619 /* try to back out */
2620 rename (newpath.c_str(), _path.c_str());
2621 goto out;
2626 ret = 0;
2628 /* dump the history list */
2630 _history.clear ();
2632 /* save state so we don't end up a session file
2633 referring to non-existent sources.
2636 save_state ("");
2638 out:
2639 _state_of_the_state = (StateOfTheState) (_state_of_the_state & ~InCleanup);
2641 return ret;
2645 Session::cleanup_trash_sources (CleanupReport& rep)
2647 // FIXME: needs adaptation for MIDI
2649 vector<space_and_path>::iterator i;
2650 string dead_sound_dir;
2651 struct dirent* dentry;
2652 struct stat statbuf;
2653 DIR* dead;
2655 rep.paths.clear ();
2656 rep.space = 0;
2658 for (i = session_dirs.begin(); i != session_dirs.end(); ++i) {
2660 dead_sound_dir = (*i).path;
2661 dead_sound_dir += dead_sound_dir_name;
2663 if ((dead = opendir (dead_sound_dir.c_str())) == 0) {
2664 continue;
2667 while ((dentry = readdir (dead)) != 0) {
2669 /* avoid '.' and '..' */
2671 if ((dentry->d_name[0] == '.' && dentry->d_name[1] == '\0') ||
2672 (dentry->d_name[2] == '\0' && dentry->d_name[0] == '.' && dentry->d_name[1] == '.')) {
2673 continue;
2676 string fullpath;
2678 fullpath = dead_sound_dir;
2679 fullpath += '/';
2680 fullpath += dentry->d_name;
2682 if (stat (fullpath.c_str(), &statbuf)) {
2683 continue;
2686 if (!S_ISREG (statbuf.st_mode)) {
2687 continue;
2690 if (unlink (fullpath.c_str())) {
2691 error << string_compose (_("cannot remove dead sound file %1 (%2)"),
2692 fullpath, strerror (errno))
2693 << endmsg;
2696 rep.paths.push_back (dentry->d_name);
2697 rep.space += statbuf.st_size;
2700 closedir (dead);
2704 return 0;
2707 void
2708 Session::set_dirty ()
2710 bool was_dirty = dirty();
2712 _state_of_the_state = StateOfTheState (_state_of_the_state | Dirty);
2715 if (!was_dirty) {
2716 DirtyChanged(); /* EMIT SIGNAL */
2721 void
2722 Session::set_clean ()
2724 bool was_dirty = dirty();
2726 _state_of_the_state = Clean;
2729 if (was_dirty) {
2730 DirtyChanged(); /* EMIT SIGNAL */
2734 void
2735 Session::set_deletion_in_progress ()
2737 _state_of_the_state = StateOfTheState (_state_of_the_state | Deletion);
2740 void
2741 Session::clear_deletion_in_progress ()
2743 _state_of_the_state = StateOfTheState (_state_of_the_state & (~Deletion));
2746 void
2747 Session::add_controllable (boost::shared_ptr<Controllable> c)
2749 /* this adds a controllable to the list managed by the Session.
2750 this is a subset of those managed by the Controllable class
2751 itself, and represents the only ones whose state will be saved
2752 as part of the session.
2755 Glib::Mutex::Lock lm (controllables_lock);
2756 controllables.insert (c);
2759 struct null_deleter { void operator()(void const *) const {} };
2761 void
2762 Session::remove_controllable (Controllable* c)
2764 if (_state_of_the_state | Deletion) {
2765 return;
2768 Glib::Mutex::Lock lm (controllables_lock);
2770 Controllables::iterator x = controllables.find (boost::shared_ptr<Controllable>(c, null_deleter()));
2772 if (x != controllables.end()) {
2773 controllables.erase (x);
2777 boost::shared_ptr<Controllable>
2778 Session::controllable_by_id (const PBD::ID& id)
2780 Glib::Mutex::Lock lm (controllables_lock);
2782 for (Controllables::iterator i = controllables.begin(); i != controllables.end(); ++i) {
2783 if ((*i)->id() == id) {
2784 return *i;
2788 return boost::shared_ptr<Controllable>();
2791 boost::shared_ptr<Controllable>
2792 Session::controllable_by_descriptor (const ControllableDescriptor& desc)
2794 boost::shared_ptr<Controllable> c;
2795 boost::shared_ptr<Route> r;
2797 switch (desc.top_level_type()) {
2798 case ControllableDescriptor::NamedRoute:
2800 std::string str = desc.top_level_name();
2801 if (str == "master") {
2802 r = _master_out;
2803 } else if (str == "control" || str == "listen") {
2804 r = _monitor_out;
2805 } else {
2806 r = route_by_name (desc.top_level_name());
2808 break;
2811 case ControllableDescriptor::RemoteControlID:
2812 r = route_by_remote_id (desc.rid());
2813 break;
2816 if (!r) {
2817 return c;
2820 switch (desc.subtype()) {
2821 case ControllableDescriptor::Gain:
2822 c = r->gain_control ();
2823 break;
2825 case ControllableDescriptor::Solo:
2826 c = r->solo_control();
2827 break;
2829 case ControllableDescriptor::Mute:
2830 c = r->mute_control();
2831 break;
2833 case ControllableDescriptor::Recenable:
2835 boost::shared_ptr<Track> t = boost::dynamic_pointer_cast<Track>(r);
2837 if (t) {
2838 c = t->rec_enable_control ();
2840 break;
2843 case ControllableDescriptor::Pan:
2844 /* XXX pan control */
2845 break;
2847 case ControllableDescriptor::Balance:
2848 /* XXX simple pan control */
2849 break;
2851 case ControllableDescriptor::PluginParameter:
2853 uint32_t plugin = desc.target (0);
2854 uint32_t parameter_index = desc.target (1);
2856 /* revert to zero based counting */
2858 if (plugin > 0) {
2859 --plugin;
2862 if (parameter_index > 0) {
2863 --parameter_index;
2866 boost::shared_ptr<Processor> p = r->nth_plugin (plugin);
2868 if (p) {
2869 c = boost::dynamic_pointer_cast<ARDOUR::AutomationControl>(
2870 p->control(Evoral::Parameter(PluginAutomation, 0, parameter_index)));
2872 break;
2875 case ControllableDescriptor::SendGain:
2877 uint32_t send = desc.target (0);
2879 /* revert to zero-based counting */
2881 if (send > 0) {
2882 --send;
2885 boost::shared_ptr<Processor> p = r->nth_send (send);
2887 if (p) {
2888 boost::shared_ptr<Send> s = boost::dynamic_pointer_cast<Send>(p);
2889 boost::shared_ptr<Amp> a = s->amp();
2891 if (a) {
2892 c = s->amp()->gain_control();
2895 break;
2898 default:
2899 /* relax and return a null pointer */
2900 break;
2903 return c;
2906 void
2907 Session::add_instant_xml (XMLNode& node, bool write_to_config)
2909 if (_writable) {
2910 Stateful::add_instant_xml (node, _path);
2913 if (write_to_config) {
2914 Config->add_instant_xml (node);
2918 XMLNode*
2919 Session::instant_xml (const string& node_name)
2921 return Stateful::instant_xml (node_name, _path);
2925 Session::save_history (string snapshot_name)
2927 XMLTree tree;
2929 if (!_writable) {
2930 return 0;
2933 if (snapshot_name.empty()) {
2934 snapshot_name = _current_snapshot_name;
2937 const string history_filename = legalize_for_path (snapshot_name) + history_suffix;
2938 const string backup_filename = history_filename + backup_suffix;
2939 const sys::path xml_path = _session_dir->root_path() / history_filename;
2940 const sys::path backup_path = _session_dir->root_path() / backup_filename;
2942 if (sys::exists (xml_path)) {
2945 sys::rename (xml_path, backup_path);
2947 catch (const sys::filesystem_error& err)
2949 error << _("could not backup old history file, current history not saved") << endmsg;
2950 return -1;
2954 if (!Config->get_save_history() || Config->get_saved_history_depth() < 0) {
2955 return 0;
2958 tree.set_root (&_history.get_state (Config->get_saved_history_depth()));
2960 if (!tree.write (xml_path.to_string()))
2962 error << string_compose (_("history could not be saved to %1"), xml_path.to_string()) << endmsg;
2966 sys::remove (xml_path);
2967 sys::rename (backup_path, xml_path);
2969 catch (const sys::filesystem_error& err)
2971 error << string_compose (_("could not restore history file from backup %1 (%2)"),
2972 backup_path.to_string(), err.what()) << endmsg;
2975 return -1;
2978 return 0;
2982 Session::restore_history (string snapshot_name)
2984 XMLTree tree;
2986 if (snapshot_name.empty()) {
2987 snapshot_name = _current_snapshot_name;
2990 const string xml_filename = legalize_for_path (snapshot_name) + history_suffix;
2991 const sys::path xml_path = _session_dir->root_path() / xml_filename;
2993 info << "Loading history from " << xml_path.to_string() << endmsg;
2995 if (!sys::exists (xml_path)) {
2996 info << string_compose (_("%1: no history file \"%2\" for this session."),
2997 _name, xml_path.to_string()) << endmsg;
2998 return 1;
3001 if (!tree.read (xml_path.to_string())) {
3002 error << string_compose (_("Could not understand session history file \"%1\""),
3003 xml_path.to_string()) << endmsg;
3004 return -1;
3007 // replace history
3008 _history.clear();
3010 for (XMLNodeConstIterator it = tree.root()->children().begin(); it != tree.root()->children().end(); it++) {
3012 XMLNode *t = *it;
3013 UndoTransaction* ut = new UndoTransaction ();
3014 struct timeval tv;
3016 ut->set_name(t->property("name")->value());
3017 stringstream ss(t->property("tv-sec")->value());
3018 ss >> tv.tv_sec;
3019 ss.str(t->property("tv-usec")->value());
3020 ss >> tv.tv_usec;
3021 ut->set_timestamp(tv);
3023 for (XMLNodeConstIterator child_it = t->children().begin();
3024 child_it != t->children().end(); child_it++)
3026 XMLNode *n = *child_it;
3027 Command *c;
3029 if (n->name() == "MementoCommand" ||
3030 n->name() == "MementoUndoCommand" ||
3031 n->name() == "MementoRedoCommand") {
3033 if ((c = memento_command_factory(n))) {
3034 ut->add_command(c);
3037 } else if (n->name() == "DeltaCommand") {
3038 PBD::ID id(n->property("midi-source")->value());
3039 boost::shared_ptr<MidiSource> midi_source =
3040 boost::dynamic_pointer_cast<MidiSource, Source>(source_by_id(id));
3041 if (midi_source) {
3042 ut->add_command(new MidiModel::DeltaCommand(midi_source->model(), *n));
3043 } else {
3044 error << _("Failed to downcast MidiSource for DeltaCommand") << endmsg;
3047 } else if (n->name() == "DiffCommand") {
3048 PBD::ID id(n->property("midi-source")->value());
3049 boost::shared_ptr<MidiSource> midi_source =
3050 boost::dynamic_pointer_cast<MidiSource, Source>(source_by_id(id));
3051 if (midi_source) {
3052 ut->add_command(new MidiModel::DiffCommand(midi_source->model(), *n));
3053 } else {
3054 error << _("Failed to downcast MidiSource for DeltaCommand") << endmsg;
3057 } else if (n->name() == "StatefulDiffCommand") {
3058 if ((c = stateful_diff_command_factory (n))) {
3059 ut->add_command (c);
3061 } else {
3062 error << string_compose(_("Couldn't figure out how to make a Command out of a %1 XMLNode."), n->name()) << endmsg;
3066 _history.add (ut);
3069 return 0;
3072 void
3073 Session::config_changed (std::string p, bool ours)
3075 if (ours) {
3076 set_dirty ();
3079 if (p == "seamless-loop") {
3081 } else if (p == "rf-speed") {
3083 } else if (p == "auto-loop") {
3085 } else if (p == "auto-input") {
3087 if (Config->get_monitoring_model() == HardwareMonitoring && transport_rolling()) {
3088 /* auto-input only makes a difference if we're rolling */
3090 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
3092 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
3093 if ((*i)->record_enabled ()) {
3094 (*i)->monitor_input (!config.get_auto_input());
3099 } else if (p == "punch-in") {
3101 Location* location;
3103 if ((location = _locations.auto_punch_location()) != 0) {
3105 if (config.get_punch_in ()) {
3106 replace_event (SessionEvent::PunchIn, location->start());
3107 } else {
3108 remove_event (location->start(), SessionEvent::PunchIn);
3112 } else if (p == "punch-out") {
3114 Location* location;
3116 if ((location = _locations.auto_punch_location()) != 0) {
3118 if (config.get_punch_out()) {
3119 replace_event (SessionEvent::PunchOut, location->end());
3120 } else {
3121 clear_events (SessionEvent::PunchOut);
3125 } else if (p == "edit-mode") {
3127 Glib::Mutex::Lock lm (playlists->lock);
3129 for (SessionPlaylists::List::iterator i = playlists->playlists.begin(); i != playlists->playlists.end(); ++i) {
3130 (*i)->set_edit_mode (Config->get_edit_mode ());
3133 } else if (p == "use-video-sync") {
3135 waiting_for_sync_offset = config.get_use_video_sync();
3137 } else if (p == "mmc-control") {
3139 //poke_midi_thread ();
3141 } else if (p == "mmc-device-id" || p == "mmc-receive-id") {
3143 if (mmc) {
3144 mmc->set_receive_device_id (Config->get_mmc_receive_device_id());
3147 } else if (p == "mmc-send-id") {
3149 if (mmc) {
3150 mmc->set_send_device_id (Config->get_mmc_send_device_id());
3153 } else if (p == "midi-control") {
3155 //poke_midi_thread ();
3157 } else if (p == "raid-path") {
3159 setup_raid_path (config.get_raid_path());
3161 } else if (p == "timecode-format") {
3163 sync_time_vars ();
3165 } else if (p == "video-pullup") {
3167 sync_time_vars ();
3169 } else if (p == "seamless-loop") {
3171 if (play_loop && transport_rolling()) {
3172 // to reset diskstreams etc
3173 request_play_loop (true);
3176 } else if (p == "rf-speed") {
3178 cumulative_rf_motion = 0;
3179 reset_rf_scale (0);
3181 } else if (p == "click-sound") {
3183 setup_click_sounds (1);
3185 } else if (p == "click-emphasis-sound") {
3187 setup_click_sounds (-1);
3189 } else if (p == "clicking") {
3191 if (Config->get_clicking()) {
3192 if (_click_io && click_data) { // don't require emphasis data
3193 _clicking = true;
3195 } else {
3196 _clicking = false;
3199 } else if (p == "send-mtc") {
3201 /* only set the internal flag if we have
3202 a port.
3205 if (_mtc_port != 0) {
3206 session_send_mtc = Config->get_send_mtc();
3207 if (session_send_mtc) {
3208 /* mark us ready to send */
3209 next_quarter_frame_to_send = 0;
3211 } else {
3212 session_send_mtc = false;
3215 } else if (p == "send-mmc") {
3217 /* only set the internal flag if we have
3218 a port.
3221 if (_mmc_port != 0) {
3222 session_send_mmc = Config->get_send_mmc();
3223 } else {
3224 mmc = 0;
3225 session_send_mmc = false;
3228 } else if (p == "midi-feedback") {
3230 /* only set the internal flag if we have
3231 a port.
3234 if (_mtc_port != 0) {
3235 session_midi_feedback = Config->get_midi_feedback();
3238 } else if (p == "jack-time-master") {
3240 engine().reset_timebase ();
3242 } else if (p == "native-file-header-format") {
3244 if (!first_file_header_format_reset) {
3245 reset_native_file_format ();
3248 first_file_header_format_reset = false;
3250 } else if (p == "native-file-data-format") {
3252 if (!first_file_data_format_reset) {
3253 reset_native_file_format ();
3256 first_file_data_format_reset = false;
3258 } else if (p == "external-sync") {
3259 if (!config.get_external_sync()) {
3260 drop_sync_source ();
3261 } else {
3262 switch_to_sync_source (config.get_sync_source());
3264 } else if (p == "remote-model") {
3265 set_remote_control_ids ();
3266 } else if (p == "denormal-model") {
3267 setup_fpu ();
3268 } else if (p == "history-depth") {
3269 set_history_depth (Config->get_history_depth());
3270 } else if (p == "sync-all-route-ordering") {
3271 sync_order_keys ("session");
3272 } else if (p == "initial-program-change") {
3274 if (_mmc_port && Config->get_initial_program_change() >= 0) {
3275 MIDI::byte buf[2];
3277 buf[0] = MIDI::program; // channel zero by default
3278 buf[1] = (Config->get_initial_program_change() & 0x7f);
3280 _mmc_port->midimsg (buf, sizeof (buf), 0);
3282 } else if (p == "initial-program-change") {
3284 if (_mmc_port && Config->get_initial_program_change() >= 0) {
3285 MIDI::byte* buf = new MIDI::byte[2];
3287 buf[0] = MIDI::program; // channel zero by default
3288 buf[1] = (Config->get_initial_program_change() & 0x7f);
3289 // deliver_midi (_mmc_port, buf, 2);
3291 } else if (p == "solo-mute-override") {
3292 // catch_up_on_solo_mute_override ();
3293 } else if (p == "listen-position") {
3294 listen_position_changed ();
3295 } else if (p == "solo-control-is-listen-control") {
3296 solo_control_mode_changed ();
3300 set_dirty ();
3303 void
3304 Session::set_history_depth (uint32_t d)
3306 _history.set_depth (d);