use new Source::used() rather than SessionPlaylists::source_use_count() to determine...
[ardour2.git] / libs / ardour / session_state.cc
blobbcb4f3094f0b719eb60d911f09d26d706d12a7eb
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/port.h"
96 #include "ardour/region_factory.h"
97 #include "ardour/route_group.h"
98 #include "ardour/send.h"
99 #include "ardour/session.h"
100 #include "ardour/session_directory.h"
101 #include "ardour/session_metadata.h"
102 #include "ardour/session_state_utils.h"
103 #include "ardour/session_playlists.h"
104 #include "ardour/session_utils.h"
105 #include "ardour/silentfilesource.h"
106 #include "ardour/slave.h"
107 #include "ardour/smf_source.h"
108 #include "ardour/sndfile_helpers.h"
109 #include "ardour/sndfilesource.h"
110 #include "ardour/source_factory.h"
111 #include "ardour/template_utils.h"
112 #include "ardour/tempo.h"
113 #include "ardour/ticker.h"
114 #include "ardour/user_bundle.h"
115 #include "ardour/utils.h"
116 #include "ardour/utils.h"
117 #include "ardour/version.h"
118 #include "ardour/playlist_factory.h"
120 #include "control_protocol/control_protocol.h"
122 #include "i18n.h"
123 #include <locale.h>
125 using namespace std;
126 using namespace ARDOUR;
127 using namespace PBD;
129 void
130 Session::first_stage_init (string fullpath, string snapshot_name)
132 if (fullpath.length() == 0) {
133 destroy ();
134 throw failed_constructor();
137 char buf[PATH_MAX+1];
138 if (!realpath (fullpath.c_str(), buf) && (errno != ENOENT)) {
139 error << string_compose(_("Could not use path %1 (%s)"), buf, strerror(errno)) << endmsg;
140 destroy ();
141 throw failed_constructor();
144 _path = string(buf);
146 if (_path[_path.length()-1] != '/') {
147 _path += '/';
150 if (Glib::file_test (_path, Glib::FILE_TEST_EXISTS) && ::access (_path.c_str(), W_OK)) {
151 _writable = false;
152 } else {
153 _writable = true;
156 /* these two are just provisional settings. set_state()
157 will likely override them.
160 _name = _current_snapshot_name = snapshot_name;
162 set_history_depth (Config->get_history_depth());
164 _current_frame_rate = _engine.frame_rate ();
165 _nominal_frame_rate = _current_frame_rate;
166 _base_frame_rate = _current_frame_rate;
168 _tempo_map = new TempoMap (_current_frame_rate);
169 _tempo_map->PropertyChanged.connect_same_thread (*this, boost::bind (&Session::tempo_map_changed, this, _1));
172 _non_soloed_outs_muted = false;
173 _listen_cnt = 0;
174 _solo_isolated_cnt = 0;
175 g_atomic_int_set (&processing_prohibited, 0);
176 _transport_speed = 0;
177 _last_transport_speed = 0;
178 _target_transport_speed = 0;
179 auto_play_legal = false;
180 transport_sub_state = 0;
181 _transport_frame = 0;
182 _requested_return_frame = -1;
183 _session_range_location = 0;
184 g_atomic_int_set (&_record_status, Disabled);
185 loop_changing = false;
186 play_loop = false;
187 have_looped = false;
188 _last_roll_location = 0;
189 _last_roll_or_reversal_location = 0;
190 _last_record_location = 0;
191 pending_locate_frame = 0;
192 pending_locate_roll = false;
193 pending_locate_flush = false;
194 state_was_pending = false;
195 set_next_event ();
196 outbound_mtc_timecode_frame = 0;
197 next_quarter_frame_to_send = -1;
198 current_block_size = 0;
199 solo_update_disabled = false;
200 _have_captured = false;
201 _worst_output_latency = 0;
202 _worst_input_latency = 0;
203 _worst_track_latency = 0;
204 _state_of_the_state = StateOfTheState(CannotSave|InitialConnecting|Loading);
205 _was_seamless = Config->get_seamless_loop ();
206 _slave = 0;
207 session_send_mmc = false;
208 session_send_mtc = false;
209 g_atomic_int_set (&_playback_load, 100);
210 g_atomic_int_set (&_capture_load, 100);
211 _play_range = false;
212 _exporting = false;
213 pending_abort = false;
214 destructive_index = 0;
215 first_file_data_format_reset = true;
216 first_file_header_format_reset = true;
217 post_export_sync = false;
218 midi_control_ui = 0;
220 AudioDiskstream::allocate_working_buffers();
222 /* default short fade = 15ms */
224 Crossfade::set_short_xfade_length ((nframes_t) floor (config.get_short_xfade_seconds() * frame_rate()));
225 SndFileSource::setup_standard_crossfades (*this, frame_rate());
227 last_mmc_step.tv_sec = 0;
228 last_mmc_step.tv_usec = 0;
229 step_speed = 0.0;
231 /* click sounds are unset by default, which causes us to internal
232 waveforms for clicks.
235 click_length = 0;
236 click_emphasis_length = 0;
237 _clicking = false;
239 process_function = &Session::process_with_events;
241 if (config.get_use_video_sync()) {
242 waiting_for_sync_offset = true;
243 } else {
244 waiting_for_sync_offset = false;
247 last_timecode_when = 0;
248 _timecode_offset = 0;
249 _timecode_offset_negative = true;
250 last_timecode_valid = false;
252 sync_time_vars ();
254 last_rr_session_dir = session_dirs.begin();
255 refresh_disk_space ();
257 // set_default_fade (0.2, 5.0); /* steepness, millisecs */
259 /* slave stuff */
261 average_slave_delta = 1800; // !!! why 1800 ????
262 have_first_delta_accumulator = false;
263 delta_accumulator_cnt = 0;
264 _slave_state = Stopped;
266 _engine.GraphReordered.connect_same_thread (*this, boost::bind (&Session::graph_reordered, this));
268 /* These are all static "per-class" signals */
270 SourceFactory::SourceCreated.connect_same_thread (*this, boost::bind (&Session::add_source, this, _1));
271 PlaylistFactory::PlaylistCreated.connect_same_thread (*this, boost::bind (&Session::add_playlist, this, _1, _2));
272 AutomationList::AutomationListCreated.connect_same_thread (*this, boost::bind (&Session::add_automation_list, this, _1));
273 Controllable::Destroyed.connect_same_thread (*this, boost::bind (&Session::remove_controllable, this, _1));
274 IO::PortCountChanged.connect_same_thread (*this, boost::bind (&Session::ensure_buffers, this, _1));
276 /* stop IO objects from doing stuff until we're ready for them */
278 Delivery::disable_panners ();
279 IO::disable_connecting ();
283 Session::second_stage_init ()
285 AudioFileSource::set_peak_dir (_session_dir->peak_path().to_string());
287 if (!_is_new) {
288 if (load_state (_current_snapshot_name)) {
289 return -1;
291 remove_empty_sounds ();
294 if (_butler->start_thread()) {
295 return -1;
298 if (start_midi_thread ()) {
299 return -1;
302 // set_state() will call setup_raid_path(), but if it's a new session we need
303 // to call setup_raid_path() here.
305 if (state_tree) {
306 if (set_state (*state_tree->root(), Stateful::loading_state_version)) {
307 return -1;
309 } else {
310 setup_raid_path(_path);
313 /* we can't save till after ::when_engine_running() is called,
314 because otherwise we save state with no connections made.
315 therefore, we reset _state_of_the_state because ::set_state()
316 will have cleared it.
318 we also have to include Loading so that any events that get
319 generated between here and the end of ::when_engine_running()
320 will be processed directly rather than queued.
323 _state_of_the_state = StateOfTheState (_state_of_the_state|CannotSave|Loading);
326 _locations.changed.connect_same_thread (*this, boost::bind (&Session::locations_changed, this));
327 _locations.added.connect_same_thread (*this, boost::bind (&Session::locations_added, this, _1));
328 setup_click_sounds (0);
329 setup_midi_control ();
331 /* Pay attention ... */
333 _engine.Halted.connect_same_thread (*this, boost::bind (&Session::engine_halted, this));
334 _engine.Xrun.connect_same_thread (*this, boost::bind (&Session::xrun_recovery, this));
336 try {
337 when_engine_running ();
340 /* handle this one in a different way than all others, so that its clear what happened */
342 catch (AudioEngine::PortRegistrationFailure& err) {
343 error << err.what() << endmsg;
344 return -1;
347 catch (...) {
348 return -1;
351 BootMessage (_("Reset Remote Controls"));
353 send_full_time_code (0);
354 _engine.transport_locate (0);
355 deliver_mmc (MIDI::MachineControl::cmdMmcReset, 0);
356 deliver_mmc (MIDI::MachineControl::cmdLocate, 0);
358 MidiClockTicker::instance().set_session (this);
359 MIDI::Name::MidiPatchManager::instance().set_session (this);
361 /* initial program change will be delivered later; see ::config_changed() */
363 BootMessage (_("Reset Control Protocols"));
365 ControlProtocolManager::instance().set_session (this);
367 _state_of_the_state = Clean;
369 Port::set_connecting_blocked (false);
371 DirtyChanged (); /* EMIT SIGNAL */
373 if (state_was_pending) {
374 save_state (_current_snapshot_name);
375 remove_pending_capture_state ();
376 state_was_pending = false;
379 BootMessage (_("Session loading complete"));
381 return 0;
384 string
385 Session::raid_path () const
387 SearchPath raid_search_path;
389 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
390 raid_search_path += sys::path((*i).path);
393 return raid_search_path.to_string ();
396 void
397 Session::setup_raid_path (string path)
399 if (path.empty()) {
400 return;
403 space_and_path sp;
404 string fspath;
406 session_dirs.clear ();
408 SearchPath search_path(path);
409 SearchPath sound_search_path;
410 SearchPath midi_search_path;
412 for (SearchPath::const_iterator i = search_path.begin(); i != search_path.end(); ++i) {
413 sp.path = (*i).to_string ();
414 sp.blocks = 0; // not needed
415 session_dirs.push_back (sp);
417 SessionDirectory sdir(sp.path);
419 sound_search_path += sdir.sound_path ();
420 midi_search_path += sdir.midi_path ();
423 // set the search path for each data type
424 FileSource::set_search_path (DataType::AUDIO, sound_search_path.to_string ());
425 SMFSource::set_search_path (DataType::MIDI, midi_search_path.to_string ());
427 // reset the round-robin soundfile path thingie
428 last_rr_session_dir = session_dirs.begin();
431 bool
432 Session::path_is_within_session (const std::string& path)
434 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
435 if (path.find ((*i).path) == 0) {
436 return true;
439 return false;
443 Session::ensure_subdirs ()
445 string dir;
447 dir = session_directory().peak_path().to_string();
449 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
450 error << string_compose(_("Session: cannot create session peakfile folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
451 return -1;
454 dir = session_directory().sound_path().to_string();
456 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
457 error << string_compose(_("Session: cannot create session sounds dir \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
458 return -1;
461 dir = session_directory().midi_path().to_string();
463 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
464 error << string_compose(_("Session: cannot create session midi dir \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
465 return -1;
468 dir = session_directory().dead_sound_path().to_string();
470 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
471 error << string_compose(_("Session: cannot create session dead sounds folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
472 return -1;
475 dir = session_directory().export_path().to_string();
477 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
478 error << string_compose(_("Session: cannot create session export folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
479 return -1;
482 dir = analysis_dir ();
484 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
485 error << string_compose(_("Session: cannot create session analysis folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
486 return -1;
489 return 0;
493 Session::create (const string& mix_template, BusProfile* bus_profile)
496 if (g_mkdir_with_parents (_path.c_str(), 0755) < 0) {
497 error << string_compose(_("Session: cannot create session folder \"%1\" (%2)"), _path, strerror (errno)) << endmsg;
498 return -1;
501 if (ensure_subdirs ()) {
502 return -1;
505 if (!mix_template.empty()) {
506 std::string in_path = mix_template;
508 ifstream in(in_path.c_str());
510 if (in){
511 string out_path = _path;
512 out_path += _name;
513 out_path += statefile_suffix;
515 ofstream out(out_path.c_str());
517 if (out){
518 out << in.rdbuf();
519 _is_new = false;
520 return 0;
522 } else {
523 error << string_compose (_("Could not open %1 for writing mix template"), out_path)
524 << endmsg;
525 return -1;
528 } else {
529 error << string_compose (_("Could not open mix template %1 for reading"), in_path)
530 << endmsg;
531 return -1;
536 /* Instantiate metadata */
538 _metadata = new SessionMetadata ();
540 /* set initial start + end point */
542 _state_of_the_state = Clean;
544 /* set up Master Out and Control Out if necessary */
546 if (bus_profile) {
548 RouteList rl;
549 int control_id = 1;
550 ChanCount count(DataType::AUDIO, bus_profile->master_out_channels);
552 if (bus_profile->master_out_channels) {
553 Route* rt = new Route (*this, _("master"), Route::MasterOut, DataType::AUDIO);
554 if (rt->init ()) {
555 delete rt;
556 return -1;
558 boost_debug_shared_ptr_mark_interesting (rt, "Route");
559 boost::shared_ptr<Route> r (rt);
560 r->input()->ensure_io (count, false, this);
561 r->output()->ensure_io (count, false, this);
562 r->set_remote_control_id (control_id++);
564 rl.push_back (r);
566 if (Config->get_use_monitor_bus()) {
567 Route* rt = new Route (*this, _("monitor"), Route::MonitorOut, DataType::AUDIO);
568 if (rt->init ()) {
569 delete rt;
570 return -1;
572 boost_debug_shared_ptr_mark_interesting (rt, "Route");
573 boost::shared_ptr<Route> r (rt);
574 r->input()->ensure_io (count, false, this);
575 r->output()->ensure_io (count, false, this);
576 r->set_remote_control_id (control_id);
578 rl.push_back (r);
581 } else {
582 /* prohibit auto-connect to master, because there isn't one */
583 bus_profile->output_ac = AutoConnectOption (bus_profile->output_ac & ~AutoConnectMaster);
586 if (!rl.empty()) {
587 add_routes (rl, false);
590 /* this allows the user to override settings with an environment variable.
593 if (no_auto_connect()) {
594 bus_profile->input_ac = AutoConnectOption (0);
595 bus_profile->output_ac = AutoConnectOption (0);
598 Config->set_input_auto_connect (bus_profile->input_ac);
599 Config->set_output_auto_connect (bus_profile->output_ac);
602 save_state ("");
604 return 0;
607 void
608 Session::maybe_write_autosave()
610 if (dirty() && record_status() != Recording) {
611 save_state("", true);
615 void
616 Session::remove_pending_capture_state ()
618 sys::path pending_state_file_path(_session_dir->root_path());
620 pending_state_file_path /= legalize_for_path (_current_snapshot_name) + pending_suffix;
624 sys::remove (pending_state_file_path);
626 catch(sys::filesystem_error& ex)
628 error << string_compose(_("Could remove pending capture state at path \"%1\" (%2)"),
629 pending_state_file_path.to_string(), ex.what()) << endmsg;
633 /** Rename a state file.
634 * @param snapshot_name Snapshot name.
636 void
637 Session::rename_state (string old_name, string new_name)
639 if (old_name == _current_snapshot_name || old_name == _name) {
640 /* refuse to rename the current snapshot or the "main" one */
641 return;
644 const string old_xml_filename = legalize_for_path (old_name) + statefile_suffix;
645 const string new_xml_filename = legalize_for_path (new_name) + statefile_suffix;
647 const sys::path old_xml_path = _session_dir->root_path() / old_xml_filename;
648 const sys::path new_xml_path = _session_dir->root_path() / new_xml_filename;
652 sys::rename (old_xml_path, new_xml_path);
654 catch (const sys::filesystem_error& err)
656 error << string_compose(_("could not rename snapshot %1 to %2 (%3)"),
657 old_name, new_name, err.what()) << endmsg;
661 /** Remove a state file.
662 * @param snapshot_name Snapshot name.
664 void
665 Session::remove_state (string snapshot_name)
667 if (snapshot_name == _current_snapshot_name || snapshot_name == _name) {
668 // refuse to remove the current snapshot or the "main" one
669 return;
672 sys::path xml_path(_session_dir->root_path());
674 xml_path /= legalize_for_path (snapshot_name) + statefile_suffix;
676 if (!create_backup_file (xml_path)) {
677 // don't remove it if a backup can't be made
678 // create_backup_file will log the error.
679 return;
682 // and delete it
683 sys::remove (xml_path);
686 #ifdef HAVE_JACK_SESSION
687 void
688 Session::jack_session_event (jack_session_event_t * event)
690 char timebuf[128];
691 time_t n;
692 struct tm local_time;
694 time (&n);
695 localtime_r (&n, &local_time);
696 strftime (timebuf, sizeof(timebuf), "JS_%FT%T", &local_time);
698 if (event->type == JackSessionSaveTemplate)
700 if (save_template( timebuf )) {
701 event->flags = JackSessionSaveError;
702 } else {
703 string cmd ("ardour3 -P -U ");
704 cmd += event->client_uuid;
705 cmd += " -T ";
706 cmd += timebuf;
708 event->command_line = strdup (cmd.c_str());
711 else
713 if (save_state (timebuf)) {
714 event->flags = JackSessionSaveError;
715 } else {
716 sys::path xml_path (_session_dir->root_path());
717 xml_path /= legalize_for_path (timebuf) + statefile_suffix;
719 string cmd ("ardour3 -P -U ");
720 cmd += event->client_uuid;
721 cmd += " \"";
722 cmd += xml_path.to_string();
723 cmd += '\"';
725 event->command_line = strdup (cmd.c_str());
729 jack_session_reply (_engine.jack(), event);
731 if (event->type == JackSessionSaveAndQuit) {
732 // TODO: make ardour quit.
735 jack_session_event_free( event );
737 #endif
740 Session::save_state (string snapshot_name, bool pending, bool switch_to_snapshot)
742 XMLTree tree;
743 sys::path xml_path(_session_dir->root_path());
745 if (!_writable || (_state_of_the_state & CannotSave)) {
746 return 1;
749 if (!_engine.connected ()) {
750 error << string_compose (_("the %1 audio engine is not connected and state saving would lose all I/O connections. Session not saved"),
751 PROGRAM_NAME)
752 << endmsg;
753 return 1;
756 /* tell sources we're saving first, in case they write out to a new file
757 * which should be saved with the state rather than the old one */
758 for (SourceMap::const_iterator i = sources.begin(); i != sources.end(); ++i) {
759 i->second->session_saved();
762 tree.set_root (&get_state());
764 if (snapshot_name.empty()) {
765 snapshot_name = _current_snapshot_name;
766 } else if (switch_to_snapshot) {
767 _current_snapshot_name = snapshot_name;
770 if (!pending) {
772 /* proper save: use statefile_suffix (.ardour in English) */
774 xml_path /= legalize_for_path (snapshot_name) + statefile_suffix;
776 /* make a backup copy of the old file */
778 if (sys::exists(xml_path) && !create_backup_file (xml_path)) {
779 // create_backup_file will log the error
780 return -1;
783 } else {
785 /* pending save: use pending_suffix (.pending in English) */
786 xml_path /= legalize_for_path (snapshot_name) + pending_suffix;
789 sys::path tmp_path(_session_dir->root_path());
791 tmp_path /= legalize_for_path (snapshot_name) + temp_suffix;
793 // cerr << "actually writing state to " << xml_path.to_string() << endl;
795 if (!tree.write (tmp_path.to_string())) {
796 error << string_compose (_("state could not be saved to %1"), tmp_path.to_string()) << endmsg;
797 sys::remove (tmp_path);
798 return -1;
800 } else {
802 if (rename (tmp_path.to_string().c_str(), xml_path.to_string().c_str()) != 0) {
803 error << string_compose (_("could not rename temporary session file %1 to %2"),
804 tmp_path.to_string(), xml_path.to_string()) << endmsg;
805 sys::remove (tmp_path);
806 return -1;
810 if (!pending) {
812 save_history (snapshot_name);
814 bool was_dirty = dirty();
816 _state_of_the_state = StateOfTheState (_state_of_the_state & ~Dirty);
818 if (was_dirty) {
819 DirtyChanged (); /* EMIT SIGNAL */
822 StateSaved (snapshot_name); /* EMIT SIGNAL */
825 return 0;
829 Session::restore_state (string snapshot_name)
831 if (load_state (snapshot_name) == 0) {
832 set_state (*state_tree->root(), Stateful::loading_state_version);
835 return 0;
839 Session::load_state (string snapshot_name)
841 delete state_tree;
842 state_tree = 0;
844 state_was_pending = false;
846 /* check for leftover pending state from a crashed capture attempt */
848 sys::path xmlpath(_session_dir->root_path());
849 xmlpath /= legalize_for_path (snapshot_name) + pending_suffix;
851 if (sys::exists (xmlpath)) {
853 /* there is pending state from a crashed capture attempt */
855 boost::optional<int> r = AskAboutPendingState();
856 if (r.get_value_or (1)) {
857 state_was_pending = true;
861 if (!state_was_pending) {
862 xmlpath = _session_dir->root_path();
863 xmlpath /= snapshot_name;
866 if (!sys::exists (xmlpath)) {
867 xmlpath = _session_dir->root_path();
868 xmlpath /= legalize_for_path (snapshot_name) + statefile_suffix;
869 if (!sys::exists (xmlpath)) {
870 error << string_compose(_("%1: session state information file \"%2\" doesn't exist!"), _name, xmlpath.to_string()) << endmsg;
871 return 1;
875 state_tree = new XMLTree;
877 set_dirty();
879 /* writable() really reflects the whole folder, but if for any
880 reason the session state file can't be written to, still
881 make us unwritable.
884 if (::access (xmlpath.to_string().c_str(), W_OK) != 0) {
885 _writable = false;
888 if (!state_tree->read (xmlpath.to_string())) {
889 error << string_compose(_("Could not understand ardour file %1"), xmlpath.to_string()) << endmsg;
890 delete state_tree;
891 state_tree = 0;
892 return -1;
895 XMLNode& root (*state_tree->root());
897 if (root.name() != X_("Session")) {
898 error << string_compose (_("Session file %1 is not a session"), xmlpath.to_string()) << endmsg;
899 delete state_tree;
900 state_tree = 0;
901 return -1;
904 const XMLProperty* prop;
906 if ((prop = root.property ("version")) == 0) {
907 /* no version implies very old version of Ardour */
908 Stateful::loading_state_version = 1000;
909 } else {
910 int major;
911 int minor;
912 int micro;
914 sscanf (prop->value().c_str(), "%d.%d.%d", &major, &minor, &micro);
915 Stateful::loading_state_version = (major * 1000) + minor;
918 if (Stateful::loading_state_version < CURRENT_SESSION_FILE_VERSION) {
920 sys::path backup_path(_session_dir->root_path());
922 backup_path /= legalize_for_path (snapshot_name) + "-1" + statefile_suffix;
924 // only create a backup once
925 if (sys::exists (backup_path)) {
926 return 0;
929 info << string_compose (_("Copying old session file %1 to %2\nUse %2 with %3 versions before 2.0 from now on"),
930 xmlpath.to_string(), backup_path.to_string(), PROGRAM_NAME)
931 << endmsg;
935 sys::copy_file (xmlpath, backup_path);
937 catch(sys::filesystem_error& ex)
939 error << string_compose (_("Unable to make backup of state file %1 (%2)"),
940 xmlpath.to_string(), ex.what())
941 << endmsg;
942 return -1;
946 return 0;
950 Session::load_options (const XMLNode& node)
952 LocaleGuard lg (X_("POSIX"));
953 config.set_variables (node);
954 return 0;
957 XMLNode&
958 Session::get_state()
960 return state(true);
963 XMLNode&
964 Session::get_template()
966 /* if we don't disable rec-enable, diskstreams
967 will believe they need to store their capture
968 sources in their state node.
971 disable_record (false);
973 return state(false);
976 XMLNode&
977 Session::state(bool full_state)
979 XMLNode* node = new XMLNode("Session");
980 XMLNode* child;
982 // store libardour version, just in case
983 char buf[16];
984 snprintf(buf, sizeof(buf), "%d.%d.%d", libardour3_major_version, libardour3_minor_version, libardour3_micro_version);
985 node->add_property("version", string(buf));
987 /* store configuration settings */
989 if (full_state) {
991 node->add_property ("name", _name);
992 snprintf (buf, sizeof (buf), "%" PRId32, _nominal_frame_rate);
993 node->add_property ("sample-rate", buf);
995 if (session_dirs.size() > 1) {
997 string p;
999 vector<space_and_path>::iterator i = session_dirs.begin();
1000 vector<space_and_path>::iterator next;
1002 ++i; /* skip the first one */
1003 next = i;
1004 ++next;
1006 while (i != session_dirs.end()) {
1008 p += (*i).path;
1010 if (next != session_dirs.end()) {
1011 p += ':';
1012 } else {
1013 break;
1016 ++next;
1017 ++i;
1020 child = node->add_child ("Path");
1021 child->add_content (p);
1025 /* save the ID counter */
1027 snprintf (buf, sizeof (buf), "%" PRIu64, ID::counter());
1028 node->add_property ("id-counter", buf);
1030 /* various options */
1032 node->add_child_nocopy (config.get_variables ());
1034 node->add_child_nocopy (_metadata->get_state());
1036 child = node->add_child ("Sources");
1038 if (full_state) {
1039 Glib::Mutex::Lock sl (source_lock);
1041 for (SourceMap::iterator siter = sources.begin(); siter != sources.end(); ++siter) {
1043 /* Don't save information about non-destructive file sources that are empty
1044 and unused by any regions.
1047 cerr << "Source " << siter->second->name() << " has UC = " << siter->second->used()
1048 << " length = " << siter->second->length (0)
1049 << endl;
1051 boost::shared_ptr<FileSource> fs;
1052 if ((fs = boost::dynamic_pointer_cast<FileSource> (siter->second)) != 0) {
1053 if (!fs->destructive()) {
1054 if (fs->length(fs->timeline_position()) == 0 && !fs->used()) {
1055 continue;
1060 child->add_child_nocopy (siter->second->get_state());
1064 child = node->add_child ("Regions");
1066 if (full_state) {
1067 Glib::Mutex::Lock rl (region_lock);
1068 const RegionFactory::RegionMap& region_map (RegionFactory::all_regions());
1069 for (RegionFactory::RegionMap::const_iterator i = region_map.begin(); i != region_map.end(); ++i) {
1070 boost::shared_ptr<Region> r = i->second;
1071 /* only store regions not attached to playlists */
1072 if (r->playlist() == 0) {
1073 child->add_child_nocopy (r->state (true));
1078 if (full_state) {
1079 node->add_child_nocopy (_locations.get_state());
1080 } else {
1081 // for a template, just create a new Locations, populate it
1082 // with the default start and end, and get the state for that.
1083 Locations loc;
1084 Location* range = new Location (0, 0, _("session"), Location::IsSessionRange);
1085 range->set (max_frames, 0);
1086 loc.add (range);
1087 node->add_child_nocopy (loc.get_state());
1090 child = node->add_child ("Bundles");
1092 boost::shared_ptr<BundleList> bundles = _bundles.reader ();
1093 for (BundleList::iterator i = bundles->begin(); i != bundles->end(); ++i) {
1094 boost::shared_ptr<UserBundle> b = boost::dynamic_pointer_cast<UserBundle> (*i);
1095 if (b) {
1096 child->add_child_nocopy (b->get_state());
1101 child = node->add_child ("Routes");
1103 boost::shared_ptr<RouteList> r = routes.reader ();
1105 RoutePublicOrderSorter cmp;
1106 RouteList public_order (*r);
1107 public_order.sort (cmp);
1109 /* the sort should have put control outs first */
1111 if (_monitor_out) {
1112 assert (_monitor_out == public_order.front());
1115 for (RouteList::iterator i = public_order.begin(); i != public_order.end(); ++i) {
1116 if (!(*i)->is_hidden()) {
1117 if (full_state) {
1118 child->add_child_nocopy ((*i)->get_state());
1119 } else {
1120 child->add_child_nocopy ((*i)->get_template());
1126 playlists->add_state (node, full_state);
1128 child = node->add_child ("RouteGroups");
1129 for (list<RouteGroup *>::iterator i = _route_groups.begin(); i != _route_groups.end(); ++i) {
1130 child->add_child_nocopy ((*i)->get_state());
1133 if (_click_io) {
1134 child = node->add_child ("Click");
1135 child->add_child_nocopy (_click_io->state (full_state));
1138 if (full_state) {
1139 child = node->add_child ("NamedSelections");
1140 for (NamedSelectionList::iterator i = named_selections.begin(); i != named_selections.end(); ++i) {
1141 if (full_state) {
1142 child->add_child_nocopy ((*i)->get_state());
1147 node->add_child_nocopy (_tempo_map->get_state());
1149 node->add_child_nocopy (get_control_protocol_state());
1151 if (_extra_xml) {
1152 node->add_child_copy (*_extra_xml);
1155 return *node;
1158 XMLNode&
1159 Session::get_control_protocol_state ()
1161 ControlProtocolManager& cpm (ControlProtocolManager::instance());
1162 return cpm.get_state();
1166 Session::set_state (const XMLNode& node, int version)
1168 XMLNodeList nlist;
1169 XMLNode* child;
1170 const XMLProperty* prop;
1171 int ret = -1;
1173 _state_of_the_state = StateOfTheState (_state_of_the_state|CannotSave);
1175 if (node.name() != X_("Session")){
1176 fatal << _("programming error: Session: incorrect XML node sent to set_state()") << endmsg;
1177 return -1;
1180 if ((prop = node.property ("version")) != 0) {
1181 version = atoi (prop->value ()) * 1000;
1184 if ((prop = node.property ("name")) != 0) {
1185 _name = prop->value ();
1188 if ((prop = node.property (X_("sample-rate"))) != 0) {
1190 _nominal_frame_rate = atoi (prop->value());
1192 if (_nominal_frame_rate != _current_frame_rate) {
1193 boost::optional<int> r = AskAboutSampleRateMismatch (_nominal_frame_rate, _current_frame_rate);
1194 if (r.get_value_or (0)) {
1195 return -1;
1200 setup_raid_path(_session_dir->root_path().to_string());
1202 if ((prop = node.property (X_("id-counter"))) != 0) {
1203 uint64_t x;
1204 sscanf (prop->value().c_str(), "%" PRIu64, &x);
1205 ID::init_counter (x);
1206 } else {
1207 /* old sessions used a timebased counter, so fake
1208 the startup ID counter based on a standard
1209 timestamp.
1211 time_t now;
1212 time (&now);
1213 ID::init_counter (now);
1217 IO::disable_connecting ();
1219 /* Object loading order:
1221 Path
1222 Extra
1223 Options/Config
1224 MIDI Control // relies on data from Options/Config
1225 Metadata
1226 Locations
1227 Sources
1228 AudioRegions
1229 Connections
1230 Routes
1231 RouteGroups
1232 MixGroups
1233 Click
1234 ControlProtocols
1237 if ((child = find_named_node (node, "Extra")) != 0) {
1238 _extra_xml = new XMLNode (*child);
1241 if (((child = find_named_node (node, "Options")) != 0)) { /* old style */
1242 load_options (*child);
1243 } else if ((child = find_named_node (node, "Config")) != 0) { /* new style */
1244 load_options (*child);
1245 } else {
1246 error << _("Session: XML state has no options section") << endmsg;
1249 if (use_config_midi_ports ()) {
1252 if (version >= 3000) {
1253 if ((child = find_named_node (node, "Metadata")) == 0) {
1254 warning << _("Session: XML state has no metadata section") << endmsg;
1255 } else if (_metadata->set_state (*child, version)) {
1256 goto out;
1260 if ((child = find_named_node (node, "Locations")) == 0) {
1261 error << _("Session: XML state has no locations section") << endmsg;
1262 goto out;
1263 } else if (_locations.set_state (*child, version)) {
1264 goto out;
1267 Location* location;
1269 if ((location = _locations.auto_loop_location()) != 0) {
1270 set_auto_loop_location (location);
1273 if ((location = _locations.auto_punch_location()) != 0) {
1274 set_auto_punch_location (location);
1277 if ((location = _locations.session_range_location()) != 0) {
1278 delete _session_range_location;
1279 _session_range_location = location;
1282 if (_session_range_location) {
1283 AudioFileSource::set_header_position_offset (_session_range_location->start());
1286 if ((child = find_named_node (node, "Sources")) == 0) {
1287 error << _("Session: XML state has no sources section") << endmsg;
1288 goto out;
1289 } else if (load_sources (*child)) {
1290 goto out;
1293 if ((child = find_named_node (node, "Regions")) == 0) {
1294 error << _("Session: XML state has no Regions section") << endmsg;
1295 goto out;
1296 } else if (load_regions (*child)) {
1297 goto out;
1300 if ((child = find_named_node (node, "Playlists")) == 0) {
1301 error << _("Session: XML state has no playlists section") << endmsg;
1302 goto out;
1303 } else if (playlists->load (*this, *child)) {
1304 goto out;
1307 if ((child = find_named_node (node, "UnusedPlaylists")) == 0) {
1308 // this is OK
1309 } else if (playlists->load_unused (*this, *child)) {
1310 goto out;
1313 if ((child = find_named_node (node, "NamedSelections")) != 0) {
1314 if (load_named_selections (*child)) {
1315 goto out;
1319 if (version >= 3000) {
1320 if ((child = find_named_node (node, "Bundles")) == 0) {
1321 warning << _("Session: XML state has no bundles section") << endmsg;
1322 //goto out;
1323 } else {
1324 /* We can't load Bundles yet as they need to be able
1325 to convert from port names to Port objects, which can't happen until
1326 later */
1327 _bundle_xml_node = new XMLNode (*child);
1331 if ((child = find_named_node (node, "TempoMap")) == 0) {
1332 error << _("Session: XML state has no Tempo Map section") << endmsg;
1333 goto out;
1334 } else if (_tempo_map->set_state (*child, version)) {
1335 goto out;
1338 if (version < 3000) {
1339 if ((child = find_named_node (node, X_("DiskStreams"))) == 0) {
1340 error << _("Session: XML state has no diskstreams section") << endmsg;
1341 goto out;
1342 } else if (load_diskstreams_2X (*child, version)) {
1343 goto out;
1347 if ((child = find_named_node (node, "Routes")) == 0) {
1348 error << _("Session: XML state has no routes section") << endmsg;
1349 goto out;
1350 } else if (load_routes (*child, version)) {
1351 goto out;
1354 /* our diskstreams list is no longer needed as they are now all owned by their Route */
1355 _diskstreams_2X.clear ();
1357 if (version >= 3000) {
1359 if ((child = find_named_node (node, "RouteGroups")) == 0) {
1360 error << _("Session: XML state has no route groups section") << endmsg;
1361 goto out;
1362 } else if (load_route_groups (*child, version)) {
1363 goto out;
1366 } else if (version < 3000) {
1368 if ((child = find_named_node (node, "EditGroups")) == 0) {
1369 error << _("Session: XML state has no edit groups section") << endmsg;
1370 goto out;
1371 } else if (load_route_groups (*child, version)) {
1372 goto out;
1375 if ((child = find_named_node (node, "MixGroups")) == 0) {
1376 error << _("Session: XML state has no mix groups section") << endmsg;
1377 goto out;
1378 } else if (load_route_groups (*child, version)) {
1379 goto out;
1383 if ((child = find_named_node (node, "Click")) == 0) {
1384 warning << _("Session: XML state has no click section") << endmsg;
1385 } else if (_click_io) {
1386 _click_io->set_state (*child, version);
1389 if ((child = find_named_node (node, "ControlProtocols")) != 0) {
1390 ControlProtocolManager::instance().set_protocol_states (*child);
1393 /* here beginneth the second phase ... */
1395 StateReady (); /* EMIT SIGNAL */
1397 return 0;
1399 out:
1400 return ret;
1404 Session::load_routes (const XMLNode& node, int version)
1406 XMLNodeList nlist;
1407 XMLNodeConstIterator niter;
1408 RouteList new_routes;
1410 nlist = node.children();
1412 set_dirty();
1414 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1416 boost::shared_ptr<Route> route;
1417 if (version < 3000) {
1418 route = XMLRouteFactory_2X (**niter, version);
1419 } else {
1420 route = XMLRouteFactory (**niter, version);
1423 if (route == 0) {
1424 error << _("Session: cannot create Route from XML description.") << endmsg;
1425 return -1;
1428 BootMessage (string_compose (_("Loaded track/bus %1"), route->name()));
1430 new_routes.push_back (route);
1433 add_routes (new_routes, false);
1435 return 0;
1438 boost::shared_ptr<Route>
1439 Session::XMLRouteFactory (const XMLNode& node, int version)
1441 boost::shared_ptr<Route> ret;
1443 if (node.name() != "Route") {
1444 return ret;
1447 XMLNode* ds_child = find_named_node (node, X_("Diskstream"));
1449 DataType type = DataType::AUDIO;
1450 const XMLProperty* prop = node.property("default-type");
1452 if (prop) {
1453 type = DataType (prop->value());
1456 assert (type != DataType::NIL);
1458 if (ds_child) {
1460 Track* track;
1462 if (type == DataType::AUDIO) {
1463 track = new AudioTrack (*this, X_("toBeResetFroXML"));
1465 } else {
1466 track = new MidiTrack (*this, X_("toBeResetFroXML"));
1469 if (track->init()) {
1470 delete track;
1471 return ret;
1474 if (track->set_state (node, version)) {
1475 delete track;
1476 return ret;
1479 boost_debug_shared_ptr_mark_interesting (track, "Track");
1480 ret.reset (track);
1482 } else {
1483 Route* rt = new Route (*this, X_("toBeResetFroXML"));
1485 if (rt->init () == 0 && rt->set_state (node, version) == 0) {
1486 boost_debug_shared_ptr_mark_interesting (rt, "Route");
1487 ret.reset (rt);
1488 } else {
1489 delete rt;
1493 return ret;
1496 boost::shared_ptr<Route>
1497 Session::XMLRouteFactory_2X (const XMLNode& node, int version)
1499 boost::shared_ptr<Route> ret;
1501 if (node.name() != "Route") {
1502 return ret;
1505 XMLProperty const * ds_prop = node.property (X_("diskstream-id"));
1506 if (!ds_prop) {
1507 ds_prop = node.property (X_("diskstream"));
1510 DataType type = DataType::AUDIO;
1511 const XMLProperty* prop = node.property("default-type");
1513 if (prop) {
1514 type = DataType (prop->value());
1517 assert (type != DataType::NIL);
1519 if (ds_prop) {
1521 list<boost::shared_ptr<Diskstream> >::iterator i = _diskstreams_2X.begin ();
1522 while (i != _diskstreams_2X.end() && (*i)->id() != ds_prop->value()) {
1523 ++i;
1526 if (i == _diskstreams_2X.end()) {
1527 error << _("Could not find diskstream for route") << endmsg;
1528 return boost::shared_ptr<Route> ();
1531 Track* track;
1533 if (type == DataType::AUDIO) {
1534 track = new AudioTrack (*this, X_("toBeResetFroXML"));
1536 } else {
1537 track = new MidiTrack (*this, X_("toBeResetFroXML"));
1540 if (track->init()) {
1541 delete track;
1542 return ret;
1545 if (track->set_state (node, version)) {
1546 delete track;
1547 return ret;
1550 track->set_diskstream (*i);
1552 boost_debug_shared_ptr_mark_interesting (track, "Track");
1553 ret.reset (track);
1555 } else {
1556 Route* rt = new Route (*this, X_("toBeResetFroXML"));
1558 if (rt->init () == 0 && rt->set_state (node, version) == 0) {
1559 boost_debug_shared_ptr_mark_interesting (rt, "Route");
1560 ret.reset (rt);
1561 } else {
1562 delete rt;
1566 return ret;
1570 Session::load_regions (const XMLNode& node)
1572 XMLNodeList nlist;
1573 XMLNodeConstIterator niter;
1574 boost::shared_ptr<Region> region;
1576 nlist = node.children();
1578 set_dirty();
1580 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1581 if ((region = XMLRegionFactory (**niter, false)) == 0) {
1582 error << _("Session: cannot create Region from XML description.");
1583 const XMLProperty *name = (**niter).property("name");
1585 if (name) {
1586 error << " " << string_compose (_("Can not load state for region '%1'"), name->value());
1589 error << endmsg;
1593 return 0;
1596 boost::shared_ptr<Region>
1597 Session::XMLRegionFactory (const XMLNode& node, bool full)
1599 const XMLProperty* type = node.property("type");
1601 try {
1603 if ( !type || type->value() == "audio" ) {
1605 return boost::shared_ptr<Region>(XMLAudioRegionFactory (node, full));
1607 } else if (type->value() == "midi") {
1609 return boost::shared_ptr<Region>(XMLMidiRegionFactory (node, full));
1613 } catch (failed_constructor& err) {
1614 return boost::shared_ptr<Region> ();
1617 return boost::shared_ptr<Region> ();
1620 boost::shared_ptr<AudioRegion>
1621 Session::XMLAudioRegionFactory (const XMLNode& node, bool /*full*/)
1623 const XMLProperty* prop;
1624 boost::shared_ptr<Source> source;
1625 boost::shared_ptr<AudioSource> as;
1626 SourceList sources;
1627 SourceList master_sources;
1628 uint32_t nchans = 1;
1629 char buf[128];
1631 if (node.name() != X_("Region")) {
1632 return boost::shared_ptr<AudioRegion>();
1635 if ((prop = node.property (X_("channels"))) != 0) {
1636 nchans = atoi (prop->value().c_str());
1639 if ((prop = node.property ("name")) == 0) {
1640 cerr << "no name for this region\n";
1641 abort ();
1644 if ((prop = node.property (X_("source-0"))) == 0) {
1645 if ((prop = node.property ("source")) == 0) {
1646 error << _("Session: XMLNode describing a AudioRegion is incomplete (no source)") << endmsg;
1647 return boost::shared_ptr<AudioRegion>();
1651 PBD::ID s_id (prop->value());
1653 if ((source = source_by_id (s_id)) == 0) {
1654 error << string_compose(_("Session: XMLNode describing a AudioRegion references an unknown source id =%1"), s_id) << endmsg;
1655 return boost::shared_ptr<AudioRegion>();
1658 as = boost::dynamic_pointer_cast<AudioSource>(source);
1659 if (!as) {
1660 error << string_compose(_("Session: XMLNode describing a AudioRegion references a non-audio source id =%1"), s_id) << endmsg;
1661 return boost::shared_ptr<AudioRegion>();
1664 sources.push_back (as);
1666 /* pickup other channels */
1668 for (uint32_t n=1; n < nchans; ++n) {
1669 snprintf (buf, sizeof(buf), X_("source-%d"), n);
1670 if ((prop = node.property (buf)) != 0) {
1672 PBD::ID id2 (prop->value());
1674 if ((source = source_by_id (id2)) == 0) {
1675 error << string_compose(_("Session: XMLNode describing a AudioRegion references an unknown source id =%1"), id2) << endmsg;
1676 return boost::shared_ptr<AudioRegion>();
1679 as = boost::dynamic_pointer_cast<AudioSource>(source);
1680 if (!as) {
1681 error << string_compose(_("Session: XMLNode describing a AudioRegion references a non-audio source id =%1"), id2) << endmsg;
1682 return boost::shared_ptr<AudioRegion>();
1684 sources.push_back (as);
1688 for (uint32_t n = 0; n < nchans; ++n) {
1689 snprintf (buf, sizeof(buf), X_("master-source-%d"), n);
1690 if ((prop = node.property (buf)) != 0) {
1692 PBD::ID id2 (prop->value());
1694 if ((source = source_by_id (id2)) == 0) {
1695 error << string_compose(_("Session: XMLNode describing a AudioRegion references an unknown source id =%1"), id2) << endmsg;
1696 return boost::shared_ptr<AudioRegion>();
1699 as = boost::dynamic_pointer_cast<AudioSource>(source);
1700 if (!as) {
1701 error << string_compose(_("Session: XMLNode describing a AudioRegion references a non-audio source id =%1"), id2) << endmsg;
1702 return boost::shared_ptr<AudioRegion>();
1704 master_sources.push_back (as);
1708 try {
1709 boost::shared_ptr<AudioRegion> region (boost::dynamic_pointer_cast<AudioRegion> (RegionFactory::create (sources, node)));
1711 /* a final detail: this is the one and only place that we know how long missing files are */
1713 if (region->whole_file()) {
1714 for (SourceList::iterator sx = sources.begin(); sx != sources.end(); ++sx) {
1715 boost::shared_ptr<SilentFileSource> sfp = boost::dynamic_pointer_cast<SilentFileSource> (*sx);
1716 if (sfp) {
1717 sfp->set_length (region->length());
1722 if (!master_sources.empty()) {
1723 if (master_sources.size() != nchans) {
1724 error << _("Session: XMLNode describing an AudioRegion is missing some master sources; ignored") << endmsg;
1725 } else {
1726 region->set_master_sources (master_sources);
1730 return region;
1734 catch (failed_constructor& err) {
1735 return boost::shared_ptr<AudioRegion>();
1739 boost::shared_ptr<MidiRegion>
1740 Session::XMLMidiRegionFactory (const XMLNode& node, bool /*full*/)
1742 const XMLProperty* prop;
1743 boost::shared_ptr<Source> source;
1744 boost::shared_ptr<MidiSource> ms;
1745 SourceList sources;
1746 uint32_t nchans = 1;
1748 if (node.name() != X_("Region")) {
1749 return boost::shared_ptr<MidiRegion>();
1752 if ((prop = node.property (X_("channels"))) != 0) {
1753 nchans = atoi (prop->value().c_str());
1756 if ((prop = node.property ("name")) == 0) {
1757 cerr << "no name for this region\n";
1758 abort ();
1761 // Multiple midi channels? that's just crazy talk
1762 assert(nchans == 1);
1764 if ((prop = node.property (X_("source-0"))) == 0) {
1765 if ((prop = node.property ("source")) == 0) {
1766 error << _("Session: XMLNode describing a MidiRegion is incomplete (no source)") << endmsg;
1767 return boost::shared_ptr<MidiRegion>();
1771 PBD::ID s_id (prop->value());
1773 if ((source = source_by_id (s_id)) == 0) {
1774 error << string_compose(_("Session: XMLNode describing a MidiRegion references an unknown source id =%1"), s_id) << endmsg;
1775 return boost::shared_ptr<MidiRegion>();
1778 ms = boost::dynamic_pointer_cast<MidiSource>(source);
1779 if (!ms) {
1780 error << string_compose(_("Session: XMLNode describing a MidiRegion references a non-midi source id =%1"), s_id) << endmsg;
1781 return boost::shared_ptr<MidiRegion>();
1784 sources.push_back (ms);
1786 try {
1787 boost::shared_ptr<MidiRegion> region (boost::dynamic_pointer_cast<MidiRegion> (RegionFactory::create (sources, node)));
1788 /* a final detail: this is the one and only place that we know how long missing files are */
1790 if (region->whole_file()) {
1791 for (SourceList::iterator sx = sources.begin(); sx != sources.end(); ++sx) {
1792 boost::shared_ptr<SilentFileSource> sfp = boost::dynamic_pointer_cast<SilentFileSource> (*sx);
1793 if (sfp) {
1794 sfp->set_length (region->length());
1799 return region;
1802 catch (failed_constructor& err) {
1803 return boost::shared_ptr<MidiRegion>();
1807 XMLNode&
1808 Session::get_sources_as_xml ()
1811 XMLNode* node = new XMLNode (X_("Sources"));
1812 Glib::Mutex::Lock lm (source_lock);
1814 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ++i) {
1815 node->add_child_nocopy (i->second->get_state());
1818 return *node;
1821 string
1822 Session::path_from_region_name (DataType type, string name, string identifier)
1824 char buf[PATH_MAX+1];
1825 uint32_t n;
1826 SessionDirectory sdir(get_best_session_directory_for_new_source());
1827 sys::path source_dir = ((type == DataType::AUDIO)
1828 ? sdir.sound_path() : sdir.midi_path());
1830 string ext = ((type == DataType::AUDIO) ? ".wav" : ".mid");
1832 for (n = 0; n < 999999; ++n) {
1833 if (identifier.length()) {
1834 snprintf (buf, sizeof(buf), "%s%s%" PRIu32 "%s", name.c_str(),
1835 identifier.c_str(), n, ext.c_str());
1836 } else {
1837 snprintf (buf, sizeof(buf), "%s-%" PRIu32 "%s", name.c_str(),
1838 n, ext.c_str());
1841 sys::path source_path = source_dir / buf;
1843 if (!sys::exists (source_path)) {
1844 return source_path.to_string();
1848 error << string_compose (_("cannot create new file from region name \"%1\" with ident = \"%2\": too many existing files with similar names"),
1849 name, identifier)
1850 << endmsg;
1852 return "";
1857 Session::load_sources (const XMLNode& node)
1859 XMLNodeList nlist;
1860 XMLNodeConstIterator niter;
1861 boost::shared_ptr<Source> source;
1863 nlist = node.children();
1865 set_dirty();
1867 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1868 try {
1869 if ((source = XMLSourceFactory (**niter)) == 0) {
1870 error << _("Session: cannot create Source from XML description.") << endmsg;
1872 } catch (MissingSource& err) {
1873 warning << _("A sound file is missing. It will be replaced by silence.") << endmsg;
1874 source = SourceFactory::createSilent (*this, **niter, max_frames, _current_frame_rate);
1878 return 0;
1881 boost::shared_ptr<Source>
1882 Session::XMLSourceFactory (const XMLNode& node)
1884 if (node.name() != "Source") {
1885 return boost::shared_ptr<Source>();
1888 try {
1889 /* note: do peak building in another thread when loading session state */
1890 return SourceFactory::create (*this, node, true);
1893 catch (failed_constructor& err) {
1894 error << string_compose (_("Found a sound file that cannot be used by %1. Talk to the progammers."), PROGRAM_NAME) << endmsg;
1895 return boost::shared_ptr<Source>();
1900 Session::save_template (string template_name)
1902 XMLTree tree;
1904 if (_state_of_the_state & CannotSave) {
1905 return -1;
1908 sys::path user_template_dir(user_template_directory());
1912 sys::create_directories (user_template_dir);
1914 catch(sys::filesystem_error& ex)
1916 error << string_compose(_("Could not create mix templates directory \"%1\" (%2)"),
1917 user_template_dir.to_string(), ex.what()) << endmsg;
1918 return -1;
1921 tree.set_root (&get_template());
1923 sys::path template_file_path(user_template_dir);
1924 template_file_path /= template_name + template_suffix;
1926 if (sys::exists (template_file_path))
1928 warning << string_compose(_("Template \"%1\" already exists - new version not created"),
1929 template_file_path.to_string()) << endmsg;
1930 return -1;
1933 if (!tree.write (template_file_path.to_string())) {
1934 error << _("mix template not saved") << endmsg;
1935 return -1;
1938 return 0;
1942 Session::rename_template (string old_name, string new_name)
1944 sys::path old_path (user_template_directory());
1945 old_path /= old_name + template_suffix;
1947 sys::path new_path(user_template_directory());
1948 new_path /= new_name + template_suffix;
1950 if (sys::exists (new_path)) {
1951 warning << string_compose(_("Template \"%1\" already exists - template not renamed"),
1952 new_path.to_string()) << endmsg;
1953 return -1;
1956 try {
1957 sys::rename (old_path, new_path);
1958 return 0;
1959 } catch (...) {
1960 return -1;
1965 Session::delete_template (string name)
1967 sys::path path = user_template_directory();
1968 path /= name + template_suffix;
1970 try {
1971 sys::remove (path);
1972 return 0;
1973 } catch (...) {
1974 return -1;
1978 void
1979 Session::refresh_disk_space ()
1981 #if HAVE_SYS_VFS_H
1982 struct statfs statfsbuf;
1983 vector<space_and_path>::iterator i;
1984 Glib::Mutex::Lock lm (space_lock);
1985 double scale;
1987 /* get freespace on every FS that is part of the session path */
1989 _total_free_4k_blocks = 0;
1991 for (i = session_dirs.begin(); i != session_dirs.end(); ++i) {
1992 statfs ((*i).path.c_str(), &statfsbuf);
1994 scale = statfsbuf.f_bsize/4096.0;
1996 (*i).blocks = (uint32_t) floor (statfsbuf.f_bavail * scale);
1997 _total_free_4k_blocks += (*i).blocks;
1999 #endif
2002 string
2003 Session::get_best_session_directory_for_new_source ()
2005 vector<space_and_path>::iterator i;
2006 string result = _session_dir->root_path().to_string();
2008 /* handle common case without system calls */
2010 if (session_dirs.size() == 1) {
2011 return result;
2014 /* OK, here's the algorithm we're following here:
2016 We want to select which directory to use for
2017 the next file source to be created. Ideally,
2018 we'd like to use a round-robin process so as to
2019 get maximum performance benefits from splitting
2020 the files across multiple disks.
2022 However, in situations without much diskspace, an
2023 RR approach may end up filling up a filesystem
2024 with new files while others still have space.
2025 Its therefore important to pay some attention to
2026 the freespace in the filesystem holding each
2027 directory as well. However, if we did that by
2028 itself, we'd keep creating new files in the file
2029 system with the most space until it was as full
2030 as all others, thus negating any performance
2031 benefits of this RAID-1 like approach.
2033 So, we use a user-configurable space threshold. If
2034 there are at least 2 filesystems with more than this
2035 much space available, we use RR selection between them.
2036 If not, then we pick the filesystem with the most space.
2038 This gets a good balance between the two
2039 approaches.
2042 refresh_disk_space ();
2044 int free_enough = 0;
2046 for (i = session_dirs.begin(); i != session_dirs.end(); ++i) {
2047 if ((*i).blocks * 4096 >= Config->get_disk_choice_space_threshold()) {
2048 free_enough++;
2052 if (free_enough >= 2) {
2053 /* use RR selection process, ensuring that the one
2054 picked works OK.
2057 i = last_rr_session_dir;
2059 do {
2060 if (++i == session_dirs.end()) {
2061 i = session_dirs.begin();
2064 if ((*i).blocks * 4096 >= Config->get_disk_choice_space_threshold()) {
2065 if (create_session_directory ((*i).path)) {
2066 result = (*i).path;
2067 last_rr_session_dir = i;
2068 return result;
2072 } while (i != last_rr_session_dir);
2074 } else {
2076 /* pick FS with the most freespace (and that
2077 seems to actually work ...)
2080 vector<space_and_path> sorted;
2081 space_and_path_ascending_cmp cmp;
2083 sorted = session_dirs;
2084 sort (sorted.begin(), sorted.end(), cmp);
2086 for (i = sorted.begin(); i != sorted.end(); ++i) {
2087 if (create_session_directory ((*i).path)) {
2088 result = (*i).path;
2089 last_rr_session_dir = i;
2090 return result;
2095 return result;
2099 Session::load_named_selections (const XMLNode& node)
2101 XMLNodeList nlist;
2102 XMLNodeConstIterator niter;
2103 NamedSelection *ns;
2105 nlist = node.children();
2107 set_dirty();
2109 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2111 if ((ns = XMLNamedSelectionFactory (**niter)) == 0) {
2112 error << _("Session: cannot create Named Selection from XML description.") << endmsg;
2116 return 0;
2119 NamedSelection *
2120 Session::XMLNamedSelectionFactory (const XMLNode& node)
2122 try {
2123 return new NamedSelection (*this, node);
2126 catch (failed_constructor& err) {
2127 return 0;
2131 string
2132 Session::automation_dir () const
2134 return Glib::build_filename (_path, "automation");
2137 string
2138 Session::analysis_dir () const
2140 return Glib::build_filename (_path, "analysis");
2144 Session::load_bundles (XMLNode const & node)
2146 XMLNodeList nlist = node.children();
2147 XMLNodeConstIterator niter;
2149 set_dirty();
2151 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2152 if ((*niter)->name() == "InputBundle") {
2153 add_bundle (boost::shared_ptr<UserBundle> (new UserBundle (**niter, true)));
2154 } else if ((*niter)->name() == "OutputBundle") {
2155 add_bundle (boost::shared_ptr<UserBundle> (new UserBundle (**niter, false)));
2156 } else {
2157 error << string_compose(_("Unknown node \"%1\" found in Bundles list from state file"), (*niter)->name()) << endmsg;
2158 return -1;
2162 return 0;
2166 Session::load_route_groups (const XMLNode& node, int version)
2168 XMLNodeList nlist = node.children();
2169 XMLNodeConstIterator niter;
2171 set_dirty ();
2173 if (version >= 3000) {
2175 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2176 if ((*niter)->name() == "RouteGroup") {
2177 RouteGroup* rg = new RouteGroup (*this, "");
2178 add_route_group (rg);
2179 rg->set_state (**niter, version);
2183 } else if (version < 3000) {
2185 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2186 if ((*niter)->name() == "EditGroup" || (*niter)->name() == "MixGroup") {
2187 RouteGroup* rg = new RouteGroup (*this, "");
2188 add_route_group (rg);
2189 rg->set_state (**niter, version);
2194 return 0;
2197 void
2198 Session::auto_save()
2200 save_state (_current_snapshot_name);
2203 static bool
2204 state_file_filter (const string &str, void */*arg*/)
2206 return (str.length() > strlen(statefile_suffix) &&
2207 str.find (statefile_suffix) == (str.length() - strlen (statefile_suffix)));
2210 struct string_cmp {
2211 bool operator()(const string* a, const string* b) {
2212 return *a < *b;
2216 static string*
2217 remove_end(string* state)
2219 string statename(*state);
2221 string::size_type start,end;
2222 if ((start = statename.find_last_of ('/')) != string::npos) {
2223 statename = statename.substr (start+1);
2226 if ((end = statename.rfind(".ardour")) == string::npos) {
2227 end = statename.length();
2230 return new string(statename.substr (0, end));
2233 vector<string *> *
2234 Session::possible_states (string path)
2236 PathScanner scanner;
2237 vector<string*>* states = scanner (path, state_file_filter, 0, false, false);
2239 transform(states->begin(), states->end(), states->begin(), remove_end);
2241 string_cmp cmp;
2242 sort (states->begin(), states->end(), cmp);
2244 return states;
2247 vector<string *> *
2248 Session::possible_states () const
2250 return possible_states(_path);
2253 void
2254 Session::add_route_group (RouteGroup* g)
2256 _route_groups.push_back (g);
2257 route_group_added (g); /* EMIT SIGNAL */
2258 set_dirty ();
2261 void
2262 Session::remove_route_group (RouteGroup& rg)
2264 list<RouteGroup*>::iterator i;
2266 if ((i = find (_route_groups.begin(), _route_groups.end(), &rg)) != _route_groups.end()) {
2267 _route_groups.erase (i);
2268 delete &rg;
2270 route_group_removed (); /* EMIT SIGNAL */
2275 RouteGroup *
2276 Session::route_group_by_name (string name)
2278 list<RouteGroup *>::iterator i;
2280 for (i = _route_groups.begin(); i != _route_groups.end(); ++i) {
2281 if ((*i)->name() == name) {
2282 return* i;
2285 return 0;
2288 UndoTransaction*
2289 Session::start_reversible_command (const string& name)
2291 UndoTransaction* trans = new UndoTransaction();
2292 trans->set_name(name);
2293 return trans;
2296 void
2297 Session::finish_reversible_command (UndoTransaction& ut)
2299 struct timeval now;
2300 gettimeofday(&now, 0);
2301 ut.set_timestamp(now);
2302 _history.add (&ut);
2305 void
2306 Session::begin_reversible_command(const string& name)
2308 UndoTransaction* trans = new UndoTransaction();
2309 trans->set_name(name);
2311 if (!_current_trans.empty()) {
2312 _current_trans.top()->add_command (trans);
2313 } else {
2314 _current_trans.push(trans);
2318 void
2319 Session::commit_reversible_command(Command *cmd)
2321 assert(!_current_trans.empty());
2322 struct timeval now;
2324 if (cmd) {
2325 _current_trans.top()->add_command(cmd);
2328 if (_current_trans.top()->empty()) {
2329 _current_trans.pop();
2330 return;
2333 gettimeofday(&now, 0);
2334 _current_trans.top()->set_timestamp(now);
2336 _history.add(_current_trans.top());
2337 _current_trans.pop();
2340 static bool
2341 accept_all_non_peak_files (const string& path, void */*arg*/)
2343 return (path.length() > 5 && path.find (peakfile_suffix) != (path.length() - 5));
2346 static bool
2347 accept_all_state_files (const string& path, void */*arg*/)
2349 return (path.length() > 7 && path.find (".ardour") == (path.length() - 7));
2353 Session::find_all_sources (string path, set<string>& result)
2355 XMLTree tree;
2356 XMLNode* node;
2358 if (!tree.read (path)) {
2359 return -1;
2362 if ((node = find_named_node (*tree.root(), "Sources")) == 0) {
2363 return -2;
2366 XMLNodeList nlist;
2367 XMLNodeConstIterator niter;
2369 nlist = node->children();
2371 set_dirty();
2373 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2375 XMLProperty* prop;
2377 if ((prop = (*niter)->property (X_("type"))) == 0) {
2378 continue;
2381 DataType type (prop->value());
2383 if ((prop = (*niter)->property (X_("name"))) == 0) {
2384 continue;
2387 if (prop->value()[0] == '/') {
2388 /* external file, ignore */
2389 continue;
2392 Glib::ustring found_path;
2393 bool is_new;
2394 uint16_t chan;
2396 if (FileSource::find (type, prop->value(), true, is_new, chan, found_path)) {
2397 result.insert (found_path);
2401 return 0;
2405 Session::find_all_sources_across_snapshots (set<string>& result, bool exclude_this_snapshot)
2407 PathScanner scanner;
2408 vector<string*>* state_files;
2409 string ripped;
2410 string this_snapshot_path;
2412 result.clear ();
2414 ripped = _path;
2416 if (ripped[ripped.length()-1] == '/') {
2417 ripped = ripped.substr (0, ripped.length() - 1);
2420 state_files = scanner (ripped, accept_all_state_files, (void *) 0, false, true);
2422 if (state_files == 0) {
2423 /* impossible! */
2424 return 0;
2427 this_snapshot_path = _path;
2428 this_snapshot_path += legalize_for_path (_current_snapshot_name);
2429 this_snapshot_path += statefile_suffix;
2431 for (vector<string*>::iterator i = state_files->begin(); i != state_files->end(); ++i) {
2433 if (exclude_this_snapshot && **i == this_snapshot_path) {
2434 continue;
2437 if (find_all_sources (**i, result) < 0) {
2438 return -1;
2442 return 0;
2445 struct RegionCounter {
2446 typedef std::map<PBD::ID,boost::shared_ptr<AudioSource> > AudioSourceList;
2447 AudioSourceList::iterator iter;
2448 boost::shared_ptr<Region> region;
2449 uint32_t count;
2451 RegionCounter() : count (0) {}
2455 Session::ask_about_playlist_deletion (boost::shared_ptr<Playlist> p)
2457 boost::optional<int> r = AskAboutPlaylistDeletion (p);
2458 return r.get_value_or (1);
2462 Session::cleanup_sources (CleanupReport& rep)
2464 // FIXME: needs adaptation to midi
2466 vector<boost::shared_ptr<Source> > dead_sources;
2467 PathScanner scanner;
2468 string sound_path;
2469 vector<space_and_path>::iterator i;
2470 vector<space_and_path>::iterator nexti;
2471 vector<string*>* soundfiles;
2472 vector<string> unused;
2473 set<string> all_sources;
2474 bool used;
2475 string spath;
2476 int ret = -1;
2478 _state_of_the_state = (StateOfTheState) (_state_of_the_state | InCleanup);
2480 /* step 1: consider deleting all unused playlists */
2482 if (playlists->maybe_delete_unused (boost::bind (Session::ask_about_playlist_deletion, _1))) {
2483 ret = 0;
2484 goto out;
2487 /* step 2: find all un-used sources */
2489 rep.paths.clear ();
2490 rep.space = 0;
2492 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ) {
2494 SourceMap::iterator tmp;
2496 tmp = i;
2497 ++tmp;
2499 /* do not bother with files that are zero size, otherwise we remove the current "nascent"
2500 capture files.
2503 if (!i->second->used() && (i->second->length(i->second->timeline_position() > 0))) {
2504 dead_sources.push_back (i->second);
2505 i->second->drop_references ();
2508 i = tmp;
2511 /* build a list of all the possible sound directories for the session */
2513 for (i = session_dirs.begin(); i != session_dirs.end(); ) {
2515 nexti = i;
2516 ++nexti;
2518 SessionDirectory sdir ((*i).path);
2519 sound_path += sdir.sound_path().to_string();
2521 if (nexti != session_dirs.end()) {
2522 sound_path += ':';
2525 i = nexti;
2528 /* now do the same thing for the files that ended up in the sounds dir(s)
2529 but are not referenced as sources in any snapshot.
2532 soundfiles = scanner (sound_path, accept_all_non_peak_files, (void *) 0, false, true);
2534 if (soundfiles == 0) {
2535 return 0;
2538 /* find all sources, but don't use this snapshot because the
2539 state file on disk still references sources we may have already
2540 dropped.
2543 find_all_sources_across_snapshots (all_sources, true);
2545 /* add our current source list
2548 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ++i) {
2549 boost::shared_ptr<FileSource> fs;
2551 if ((fs = boost::dynamic_pointer_cast<FileSource> (i->second)) != 0) {
2552 all_sources.insert (fs->path());
2556 char tmppath1[PATH_MAX+1];
2557 char tmppath2[PATH_MAX+1];
2559 for (vector<string*>::iterator x = soundfiles->begin(); x != soundfiles->end(); ++x) {
2561 used = false;
2562 spath = **x;
2564 for (set<string>::iterator i = all_sources.begin(); i != all_sources.end(); ++i) {
2566 realpath(spath.c_str(), tmppath1);
2567 realpath((*i).c_str(), tmppath2);
2569 if (strcmp(tmppath1, tmppath2) == 0) {
2570 used = true;
2571 break;
2575 if (!used) {
2576 unused.push_back (spath);
2580 /* now try to move all unused files into the "dead_sounds" directory(ies) */
2582 for (vector<string>::iterator x = unused.begin(); x != unused.end(); ++x) {
2583 struct stat statbuf;
2585 rep.paths.push_back (*x);
2586 if (stat ((*x).c_str(), &statbuf) == 0) {
2587 rep.space += statbuf.st_size;
2590 string newpath;
2592 /* don't move the file across filesystems, just
2593 stick it in the `dead_sound_dir_name' directory
2594 on whichever filesystem it was already on.
2597 if ((*x).find ("/sounds/") != string::npos) {
2599 /* old school, go up 1 level */
2601 newpath = Glib::path_get_dirname (*x); // "sounds"
2602 newpath = Glib::path_get_dirname (newpath); // "session-name"
2604 } else {
2606 /* new school, go up 4 levels */
2608 newpath = Glib::path_get_dirname (*x); // "audiofiles"
2609 newpath = Glib::path_get_dirname (newpath); // "session-name"
2610 newpath = Glib::path_get_dirname (newpath); // "interchange"
2611 newpath = Glib::path_get_dirname (newpath); // "session-dir"
2614 newpath += '/';
2615 newpath += dead_sound_dir_name;
2617 if (g_mkdir_with_parents (newpath.c_str(), 0755) < 0) {
2618 error << string_compose(_("Session: cannot create session peakfile folder \"%1\" (%2)"), newpath, strerror (errno)) << endmsg;
2619 return -1;
2622 newpath += '/';
2623 newpath += Glib::path_get_basename ((*x));
2625 if (access (newpath.c_str(), F_OK) == 0) {
2627 /* the new path already exists, try versioning */
2629 char buf[PATH_MAX+1];
2630 int version = 1;
2631 string newpath_v;
2633 snprintf (buf, sizeof (buf), "%s.%d", newpath.c_str(), version);
2634 newpath_v = buf;
2636 while (access (newpath_v.c_str(), F_OK) == 0 && version < 999) {
2637 snprintf (buf, sizeof (buf), "%s.%d", newpath.c_str(), ++version);
2638 newpath_v = buf;
2641 if (version == 999) {
2642 error << string_compose (_("there are already 1000 files with names like %1; versioning discontinued"),
2643 newpath)
2644 << endmsg;
2645 } else {
2646 newpath = newpath_v;
2649 } else {
2651 /* it doesn't exist, or we can't read it or something */
2655 if (::rename ((*x).c_str(), newpath.c_str()) != 0) {
2656 error << string_compose (_("cannot rename audio file source from %1 to %2 (%3)"),
2657 (*x), newpath, strerror (errno))
2658 << endmsg;
2659 goto out;
2662 /* see if there an easy to find peakfile for this file, and remove it.
2665 string peakpath = (*x).substr (0, (*x).find_last_of ('.'));
2666 peakpath += peakfile_suffix;
2668 if (access (peakpath.c_str(), W_OK) == 0) {
2669 if (::unlink (peakpath.c_str()) != 0) {
2670 error << string_compose (_("cannot remove peakfile %1 for %2 (%3)"),
2671 peakpath, _path, strerror (errno))
2672 << endmsg;
2673 /* try to back out */
2674 rename (newpath.c_str(), _path.c_str());
2675 goto out;
2680 ret = 0;
2682 /* dump the history list */
2684 _history.clear ();
2686 /* save state so we don't end up a session file
2687 referring to non-existent sources.
2690 save_state ("");
2692 out:
2693 _state_of_the_state = (StateOfTheState) (_state_of_the_state & ~InCleanup);
2695 return ret;
2699 Session::cleanup_trash_sources (CleanupReport& rep)
2701 // FIXME: needs adaptation for MIDI
2703 vector<space_and_path>::iterator i;
2704 string dead_sound_dir;
2705 struct dirent* dentry;
2706 struct stat statbuf;
2707 DIR* dead;
2709 rep.paths.clear ();
2710 rep.space = 0;
2712 for (i = session_dirs.begin(); i != session_dirs.end(); ++i) {
2714 dead_sound_dir = (*i).path;
2715 dead_sound_dir += dead_sound_dir_name;
2717 if ((dead = opendir (dead_sound_dir.c_str())) == 0) {
2718 continue;
2721 while ((dentry = readdir (dead)) != 0) {
2723 /* avoid '.' and '..' */
2725 if ((dentry->d_name[0] == '.' && dentry->d_name[1] == '\0') ||
2726 (dentry->d_name[2] == '\0' && dentry->d_name[0] == '.' && dentry->d_name[1] == '.')) {
2727 continue;
2730 string fullpath;
2732 fullpath = dead_sound_dir;
2733 fullpath += '/';
2734 fullpath += dentry->d_name;
2736 if (stat (fullpath.c_str(), &statbuf)) {
2737 continue;
2740 if (!S_ISREG (statbuf.st_mode)) {
2741 continue;
2744 if (unlink (fullpath.c_str())) {
2745 error << string_compose (_("cannot remove dead sound file %1 (%2)"),
2746 fullpath, strerror (errno))
2747 << endmsg;
2750 rep.paths.push_back (dentry->d_name);
2751 rep.space += statbuf.st_size;
2754 closedir (dead);
2758 return 0;
2761 void
2762 Session::set_dirty ()
2764 bool was_dirty = dirty();
2766 _state_of_the_state = StateOfTheState (_state_of_the_state | Dirty);
2769 if (!was_dirty) {
2770 DirtyChanged(); /* EMIT SIGNAL */
2775 void
2776 Session::set_clean ()
2778 bool was_dirty = dirty();
2780 _state_of_the_state = Clean;
2783 if (was_dirty) {
2784 DirtyChanged(); /* EMIT SIGNAL */
2788 void
2789 Session::set_deletion_in_progress ()
2791 _state_of_the_state = StateOfTheState (_state_of_the_state | Deletion);
2794 void
2795 Session::clear_deletion_in_progress ()
2797 _state_of_the_state = StateOfTheState (_state_of_the_state & (~Deletion));
2800 void
2801 Session::add_controllable (boost::shared_ptr<Controllable> c)
2803 /* this adds a controllable to the list managed by the Session.
2804 this is a subset of those managed by the Controllable class
2805 itself, and represents the only ones whose state will be saved
2806 as part of the session.
2809 Glib::Mutex::Lock lm (controllables_lock);
2810 controllables.insert (c);
2813 struct null_deleter { void operator()(void const *) const {} };
2815 void
2816 Session::remove_controllable (Controllable* c)
2818 if (_state_of_the_state | Deletion) {
2819 return;
2822 Glib::Mutex::Lock lm (controllables_lock);
2824 Controllables::iterator x = controllables.find (boost::shared_ptr<Controllable>(c, null_deleter()));
2826 if (x != controllables.end()) {
2827 controllables.erase (x);
2831 boost::shared_ptr<Controllable>
2832 Session::controllable_by_id (const PBD::ID& id)
2834 Glib::Mutex::Lock lm (controllables_lock);
2836 for (Controllables::iterator i = controllables.begin(); i != controllables.end(); ++i) {
2837 if ((*i)->id() == id) {
2838 return *i;
2842 return boost::shared_ptr<Controllable>();
2845 boost::shared_ptr<Controllable>
2846 Session::controllable_by_descriptor (const ControllableDescriptor& desc)
2848 boost::shared_ptr<Controllable> c;
2849 boost::shared_ptr<Route> r;
2851 switch (desc.top_level_type()) {
2852 case ControllableDescriptor::NamedRoute:
2854 std::string str = desc.top_level_name();
2855 if (str == "master") {
2856 r = _master_out;
2857 } else if (str == "control" || str == "listen") {
2858 r = _monitor_out;
2859 } else {
2860 r = route_by_name (desc.top_level_name());
2862 break;
2865 case ControllableDescriptor::RemoteControlID:
2866 r = route_by_remote_id (desc.rid());
2867 break;
2870 if (!r) {
2871 return c;
2874 switch (desc.subtype()) {
2875 case ControllableDescriptor::Gain:
2876 c = r->gain_control ();
2877 break;
2879 case ControllableDescriptor::Solo:
2880 c = r->solo_control();
2881 break;
2883 case ControllableDescriptor::Mute:
2884 c = r->mute_control();
2885 break;
2887 case ControllableDescriptor::Recenable:
2889 boost::shared_ptr<Track> t = boost::dynamic_pointer_cast<Track>(r);
2891 if (t) {
2892 c = t->rec_enable_control ();
2894 break;
2897 case ControllableDescriptor::Pan:
2898 /* XXX pan control */
2899 break;
2901 case ControllableDescriptor::Balance:
2902 /* XXX simple pan control */
2903 break;
2905 case ControllableDescriptor::PluginParameter:
2907 uint32_t plugin = desc.target (0);
2908 uint32_t parameter_index = desc.target (1);
2910 /* revert to zero based counting */
2912 if (plugin > 0) {
2913 --plugin;
2916 if (parameter_index > 0) {
2917 --parameter_index;
2920 boost::shared_ptr<Processor> p = r->nth_plugin (plugin);
2922 if (p) {
2923 c = boost::dynamic_pointer_cast<ARDOUR::AutomationControl>(
2924 p->control(Evoral::Parameter(PluginAutomation, 0, parameter_index)));
2926 break;
2929 case ControllableDescriptor::SendGain:
2931 uint32_t send = desc.target (0);
2933 /* revert to zero-based counting */
2935 if (send > 0) {
2936 --send;
2939 boost::shared_ptr<Processor> p = r->nth_send (send);
2941 if (p) {
2942 boost::shared_ptr<Send> s = boost::dynamic_pointer_cast<Send>(p);
2943 boost::shared_ptr<Amp> a = s->amp();
2945 if (a) {
2946 c = s->amp()->gain_control();
2949 break;
2952 default:
2953 /* relax and return a null pointer */
2954 break;
2957 return c;
2960 void
2961 Session::add_instant_xml (XMLNode& node, bool write_to_config)
2963 if (_writable) {
2964 Stateful::add_instant_xml (node, _path);
2967 if (write_to_config) {
2968 Config->add_instant_xml (node);
2972 XMLNode*
2973 Session::instant_xml (const string& node_name)
2975 return Stateful::instant_xml (node_name, _path);
2979 Session::save_history (string snapshot_name)
2981 XMLTree tree;
2983 if (!_writable) {
2984 return 0;
2987 if (snapshot_name.empty()) {
2988 snapshot_name = _current_snapshot_name;
2991 const string history_filename = legalize_for_path (snapshot_name) + history_suffix;
2992 const string backup_filename = history_filename + backup_suffix;
2993 const sys::path xml_path = _session_dir->root_path() / history_filename;
2994 const sys::path backup_path = _session_dir->root_path() / backup_filename;
2996 if (sys::exists (xml_path)) {
2999 sys::rename (xml_path, backup_path);
3001 catch (const sys::filesystem_error& err)
3003 error << _("could not backup old history file, current history not saved") << endmsg;
3004 return -1;
3008 if (!Config->get_save_history() || Config->get_saved_history_depth() < 0) {
3009 return 0;
3012 tree.set_root (&_history.get_state (Config->get_saved_history_depth()));
3014 if (!tree.write (xml_path.to_string()))
3016 error << string_compose (_("history could not be saved to %1"), xml_path.to_string()) << endmsg;
3020 sys::remove (xml_path);
3021 sys::rename (backup_path, xml_path);
3023 catch (const sys::filesystem_error& err)
3025 error << string_compose (_("could not restore history file from backup %1 (%2)"),
3026 backup_path.to_string(), err.what()) << endmsg;
3029 return -1;
3032 return 0;
3036 Session::restore_history (string snapshot_name)
3038 XMLTree tree;
3040 if (snapshot_name.empty()) {
3041 snapshot_name = _current_snapshot_name;
3044 const string xml_filename = legalize_for_path (snapshot_name) + history_suffix;
3045 const sys::path xml_path = _session_dir->root_path() / xml_filename;
3047 info << "Loading history from " << xml_path.to_string() << endmsg;
3049 if (!sys::exists (xml_path)) {
3050 info << string_compose (_("%1: no history file \"%2\" for this session."),
3051 _name, xml_path.to_string()) << endmsg;
3052 return 1;
3055 if (!tree.read (xml_path.to_string())) {
3056 error << string_compose (_("Could not understand session history file \"%1\""),
3057 xml_path.to_string()) << endmsg;
3058 return -1;
3061 // replace history
3062 _history.clear();
3064 for (XMLNodeConstIterator it = tree.root()->children().begin(); it != tree.root()->children().end(); it++) {
3066 XMLNode *t = *it;
3067 UndoTransaction* ut = new UndoTransaction ();
3068 struct timeval tv;
3070 ut->set_name(t->property("name")->value());
3071 stringstream ss(t->property("tv-sec")->value());
3072 ss >> tv.tv_sec;
3073 ss.str(t->property("tv-usec")->value());
3074 ss >> tv.tv_usec;
3075 ut->set_timestamp(tv);
3077 for (XMLNodeConstIterator child_it = t->children().begin();
3078 child_it != t->children().end(); child_it++)
3080 XMLNode *n = *child_it;
3081 Command *c;
3083 if (n->name() == "MementoCommand" ||
3084 n->name() == "MementoUndoCommand" ||
3085 n->name() == "MementoRedoCommand") {
3087 if ((c = memento_command_factory(n))) {
3088 ut->add_command(c);
3091 } else if (n->name() == "DiffCommand") {
3092 PBD::ID id(n->property("midi-source")->value());
3093 boost::shared_ptr<MidiSource> midi_source =
3094 boost::dynamic_pointer_cast<MidiSource, Source>(source_by_id(id));
3095 if (midi_source) {
3096 ut->add_command(new MidiModel::DiffCommand(midi_source->model(), *n));
3097 } else {
3098 error << _("Failed to downcast MidiSource for DiffCommand") << endmsg;
3101 } else if (n->name() == "StatefulDiffCommand") {
3102 if ((c = stateful_diff_command_factory (n))) {
3103 ut->add_command (c);
3105 } else {
3106 error << string_compose(_("Couldn't figure out how to make a Command out of a %1 XMLNode."), n->name()) << endmsg;
3110 _history.add (ut);
3113 return 0;
3116 void
3117 Session::config_changed (std::string p, bool ours)
3119 if (ours) {
3120 set_dirty ();
3123 if (p == "seamless-loop") {
3125 } else if (p == "rf-speed") {
3127 } else if (p == "auto-loop") {
3129 } else if (p == "auto-input") {
3131 if (Config->get_monitoring_model() == HardwareMonitoring && transport_rolling()) {
3132 /* auto-input only makes a difference if we're rolling */
3134 boost::shared_ptr<RouteList> rl = routes.reader ();
3135 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
3136 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
3137 if (tr && tr->record_enabled ()) {
3138 tr->monitor_input (!config.get_auto_input());
3143 } else if (p == "punch-in") {
3145 Location* location;
3147 if ((location = _locations.auto_punch_location()) != 0) {
3149 if (config.get_punch_in ()) {
3150 replace_event (SessionEvent::PunchIn, location->start());
3151 } else {
3152 remove_event (location->start(), SessionEvent::PunchIn);
3156 } else if (p == "punch-out") {
3158 Location* location;
3160 if ((location = _locations.auto_punch_location()) != 0) {
3162 if (config.get_punch_out()) {
3163 replace_event (SessionEvent::PunchOut, location->end());
3164 } else {
3165 clear_events (SessionEvent::PunchOut);
3169 } else if (p == "edit-mode") {
3171 Glib::Mutex::Lock lm (playlists->lock);
3173 for (SessionPlaylists::List::iterator i = playlists->playlists.begin(); i != playlists->playlists.end(); ++i) {
3174 (*i)->set_edit_mode (Config->get_edit_mode ());
3177 } else if (p == "use-video-sync") {
3179 waiting_for_sync_offset = config.get_use_video_sync();
3181 } else if (p == "mmc-control") {
3183 //poke_midi_thread ();
3185 } else if (p == "mmc-device-id" || p == "mmc-receive-id") {
3187 if (mmc) {
3188 mmc->set_receive_device_id (Config->get_mmc_receive_device_id());
3191 } else if (p == "mmc-send-id") {
3193 if (mmc) {
3194 mmc->set_send_device_id (Config->get_mmc_send_device_id());
3197 } else if (p == "midi-control") {
3199 //poke_midi_thread ();
3201 } else if (p == "raid-path") {
3203 setup_raid_path (config.get_raid_path());
3205 } else if (p == "timecode-format") {
3207 sync_time_vars ();
3209 } else if (p == "video-pullup") {
3211 sync_time_vars ();
3213 } else if (p == "seamless-loop") {
3215 if (play_loop && transport_rolling()) {
3216 // to reset diskstreams etc
3217 request_play_loop (true);
3220 } else if (p == "rf-speed") {
3222 cumulative_rf_motion = 0;
3223 reset_rf_scale (0);
3225 } else if (p == "click-sound") {
3227 setup_click_sounds (1);
3229 } else if (p == "click-emphasis-sound") {
3231 setup_click_sounds (-1);
3233 } else if (p == "clicking") {
3235 if (Config->get_clicking()) {
3236 if (_click_io && click_data) { // don't require emphasis data
3237 _clicking = true;
3239 } else {
3240 _clicking = false;
3243 } else if (p == "send-mtc") {
3245 /* only set the internal flag if we have
3246 a port.
3249 if (_mtc_port != 0) {
3250 session_send_mtc = Config->get_send_mtc();
3251 if (session_send_mtc) {
3252 /* mark us ready to send */
3253 next_quarter_frame_to_send = 0;
3255 } else {
3256 session_send_mtc = false;
3259 } else if (p == "send-mmc") {
3261 /* only set the internal flag if we have
3262 a port.
3265 if (_mmc_port != 0) {
3266 session_send_mmc = Config->get_send_mmc();
3267 } else {
3268 mmc = 0;
3269 session_send_mmc = false;
3272 } else if (p == "midi-feedback") {
3274 /* only set the internal flag if we have
3275 a port.
3278 if (_mtc_port != 0) {
3279 session_midi_feedback = Config->get_midi_feedback();
3282 } else if (p == "jack-time-master") {
3284 engine().reset_timebase ();
3286 } else if (p == "native-file-header-format") {
3288 if (!first_file_header_format_reset) {
3289 reset_native_file_format ();
3292 first_file_header_format_reset = false;
3294 } else if (p == "native-file-data-format") {
3296 if (!first_file_data_format_reset) {
3297 reset_native_file_format ();
3300 first_file_data_format_reset = false;
3302 } else if (p == "external-sync") {
3303 if (!config.get_external_sync()) {
3304 drop_sync_source ();
3305 } else {
3306 switch_to_sync_source (config.get_sync_source());
3308 } else if (p == "remote-model") {
3309 set_remote_control_ids ();
3310 } else if (p == "denormal-model") {
3311 setup_fpu ();
3312 } else if (p == "history-depth") {
3313 set_history_depth (Config->get_history_depth());
3314 } else if (p == "sync-all-route-ordering") {
3315 sync_order_keys ("session");
3316 } else if (p == "initial-program-change") {
3318 if (_mmc_port && Config->get_initial_program_change() >= 0) {
3319 MIDI::byte buf[2];
3321 buf[0] = MIDI::program; // channel zero by default
3322 buf[1] = (Config->get_initial_program_change() & 0x7f);
3324 _mmc_port->midimsg (buf, sizeof (buf), 0);
3326 } else if (p == "initial-program-change") {
3328 if (_mmc_port && Config->get_initial_program_change() >= 0) {
3329 MIDI::byte* buf = new MIDI::byte[2];
3331 buf[0] = MIDI::program; // channel zero by default
3332 buf[1] = (Config->get_initial_program_change() & 0x7f);
3333 // deliver_midi (_mmc_port, buf, 2);
3335 } else if (p == "solo-mute-override") {
3336 // catch_up_on_solo_mute_override ();
3337 } else if (p == "listen-position") {
3338 listen_position_changed ();
3339 } else if (p == "solo-control-is-listen-control") {
3340 solo_control_mode_changed ();
3344 set_dirty ();
3347 void
3348 Session::set_history_depth (uint32_t d)
3350 _history.set_depth (d);
3354 Session::load_diskstreams_2X (XMLNode const & node, int)
3356 XMLNodeList clist;
3357 XMLNodeConstIterator citer;
3359 clist = node.children();
3361 for (citer = clist.begin(); citer != clist.end(); ++citer) {
3363 try {
3364 /* diskstreams added automatically by DiskstreamCreated handler */
3365 if ((*citer)->name() == "AudioDiskstream" || (*citer)->name() == "DiskStream") {
3366 boost::shared_ptr<AudioDiskstream> dsp (new AudioDiskstream (*this, **citer));
3367 _diskstreams_2X.push_back (dsp);
3368 } else {
3369 error << _("Session: unknown diskstream type in XML") << endmsg;
3373 catch (failed_constructor& err) {
3374 error << _("Session: could not load diskstream via XML state") << endmsg;
3375 return -1;
3379 return 0;