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.
22 #include "libardour-config.h"
31 #include <cstdio> /* snprintf(3) ... grrr */
43 #ifdef HAVE_SYS_STATVFS_H
44 #include <sys/statvfs.h>
48 #include <glib/gstdio.h>
51 #include <glibmm/threads.h>
53 #include <boost/algorithm/string.hpp>
55 #include "midi++/mmc.h"
56 #include "midi++/port.h"
57 #include "midi++/manager.h"
59 #include "evoral/SMF.hpp"
61 #include "pbd/boost_debug.h"
62 #include "pbd/basename.h"
63 #include "pbd/controllable_descriptor.h"
64 #include "pbd/enumwriter.h"
65 #include "pbd/error.h"
66 #include "pbd/file_utils.h"
67 #include "pbd/pathexpand.h"
68 #include "pbd/pathscanner.h"
69 #include "pbd/pthread_utils.h"
70 #include "pbd/stacktrace.h"
71 #include "pbd/convert.h"
72 #include "pbd/clear_dir.h"
73 #include "pbd/localtime_r.h"
75 #include "ardour/amp.h"
76 #include "ardour/audio_diskstream.h"
77 #include "ardour/audio_track.h"
78 #include "ardour/audioengine.h"
79 #include "ardour/audiofilesource.h"
80 #include "ardour/audioregion.h"
81 #include "ardour/automation_control.h"
82 #include "ardour/butler.h"
83 #include "ardour/control_protocol_manager.h"
84 #include "ardour/directory_names.h"
85 #include "ardour/filename_extensions.h"
86 #include "ardour/location.h"
87 #include "ardour/midi_model.h"
88 #include "ardour/midi_patch_manager.h"
89 #include "ardour/midi_region.h"
90 #include "ardour/midi_source.h"
91 #include "ardour/midi_track.h"
92 #include "ardour/pannable.h"
93 #include "ardour/playlist_factory.h"
94 #include "ardour/port.h"
95 #include "ardour/processor.h"
96 #include "ardour/proxy_controllable.h"
97 #include "ardour/recent_sessions.h"
98 #include "ardour/region_factory.h"
99 #include "ardour/route_group.h"
100 #include "ardour/send.h"
101 #include "ardour/session.h"
102 #include "ardour/session_directory.h"
103 #include "ardour/session_metadata.h"
104 #include "ardour/session_playlists.h"
105 #include "ardour/session_state_utils.h"
106 #include "ardour/silentfilesource.h"
107 #include "ardour/sndfilesource.h"
108 #include "ardour/source_factory.h"
109 #include "ardour/speakers.h"
110 #include "ardour/template_utils.h"
111 #include "ardour/tempo.h"
112 #include "ardour/ticker.h"
113 #include "ardour/user_bundle.h"
115 #include "control_protocol/control_protocol.h"
121 using namespace ARDOUR;
124 /** @param snapshot_name Snapshot name, without the .ardour prefix */
126 Session::first_stage_init (string fullpath, string snapshot_name)
128 if (fullpath.length() == 0) {
130 throw failed_constructor();
133 _path = canonical_path (fullpath);
135 if (_path[_path.length()-1] != G_DIR_SEPARATOR) {
136 _path += G_DIR_SEPARATOR;
139 /* these two are just provisional settings. set_state()
140 will likely override them.
143 _name = _current_snapshot_name = snapshot_name;
145 set_history_depth (Config->get_history_depth());
147 _current_frame_rate = _engine.frame_rate ();
148 _nominal_frame_rate = _current_frame_rate;
149 _base_frame_rate = _current_frame_rate;
151 _tempo_map = new TempoMap (_current_frame_rate);
152 _tempo_map->PropertyChanged.connect_same_thread (*this, boost::bind (&Session::tempo_map_changed, this, _1));
155 _non_soloed_outs_muted = false;
157 _solo_isolated_cnt = 0;
158 g_atomic_int_set (&processing_prohibited, 0);
159 _transport_speed = 0;
160 _default_transport_speed = 1.0;
161 _last_transport_speed = 0;
162 _target_transport_speed = 0;
163 auto_play_legal = false;
164 transport_sub_state = 0;
165 _transport_frame = 0;
166 _requested_return_frame = -1;
167 _session_range_location = 0;
168 g_atomic_int_set (&_record_status, Disabled);
169 loop_changing = false;
172 _last_roll_location = 0;
173 _last_roll_or_reversal_location = 0;
174 _last_record_location = 0;
175 pending_locate_frame = 0;
176 pending_locate_roll = false;
177 pending_locate_flush = false;
178 state_was_pending = false;
180 outbound_mtc_timecode_frame = 0;
181 next_quarter_frame_to_send = -1;
182 current_block_size = 0;
183 solo_update_disabled = false;
184 _have_captured = false;
185 _worst_output_latency = 0;
186 _worst_input_latency = 0;
187 _worst_track_latency = 0;
188 _state_of_the_state = StateOfTheState(CannotSave|InitialConnecting|Loading);
189 _was_seamless = Config->get_seamless_loop ();
191 _send_qf_mtc = false;
192 _pframes_since_last_mtc = 0;
193 g_atomic_int_set (&_playback_load, 100);
194 g_atomic_int_set (&_capture_load, 100);
197 pending_abort = false;
198 _adding_routes_in_progress = false;
199 destructive_index = 0;
200 first_file_data_format_reset = true;
201 first_file_header_format_reset = true;
202 post_export_sync = false;
205 no_questions_about_missing_files = false;
206 _speakers.reset (new Speakers);
208 ignore_route_processor_changes = false;
209 _pre_export_mmc_enabled = false;
211 AudioDiskstream::allocate_working_buffers();
213 /* default short fade = 15ms */
215 SndFileSource::setup_standard_crossfades (*this, frame_rate());
217 last_mmc_step.tv_sec = 0;
218 last_mmc_step.tv_usec = 0;
221 /* click sounds are unset by default, which causes us to internal
222 waveforms for clicks.
226 click_emphasis_length = 0;
229 process_function = &Session::process_with_events;
231 if (config.get_use_video_sync()) {
232 waiting_for_sync_offset = true;
234 waiting_for_sync_offset = false;
237 last_timecode_when = 0;
238 last_timecode_valid = false;
242 last_rr_session_dir = session_dirs.begin();
243 refresh_disk_space ();
245 /* default: assume simple stereo speaker configuration */
247 _speakers->setup_default_speakers (2);
251 average_slave_delta = 1800; // !!! why 1800 ????
252 have_first_delta_accumulator = false;
253 delta_accumulator_cnt = 0;
254 _slave_state = Stopped;
256 _solo_cut_control.reset (new ProxyControllable (_("solo cut control (dB)"), PBD::Controllable::GainLike,
257 boost::bind (&RCConfiguration::set_solo_mute_gain, Config, _1),
258 boost::bind (&RCConfiguration::get_solo_mute_gain, Config)));
259 add_controllable (_solo_cut_control);
261 _engine.GraphReordered.connect_same_thread (*this, boost::bind (&Session::graph_reordered, this));
263 /* These are all static "per-class" signals */
265 SourceFactory::SourceCreated.connect_same_thread (*this, boost::bind (&Session::add_source, this, _1));
266 PlaylistFactory::PlaylistCreated.connect_same_thread (*this, boost::bind (&Session::add_playlist, this, _1, _2));
267 AutomationList::AutomationListCreated.connect_same_thread (*this, boost::bind (&Session::add_automation_list, this, _1));
268 Controllable::Destroyed.connect_same_thread (*this, boost::bind (&Session::remove_controllable, this, _1));
269 IO::PortCountChanged.connect_same_thread (*this, boost::bind (&Session::ensure_buffers, this, _1));
271 /* stop IO objects from doing stuff until we're ready for them */
273 Delivery::disable_panners ();
274 IO::disable_connecting ();
278 Session::second_stage_init ()
280 AudioFileSource::set_peak_dir (_session_dir->peak_path());
283 if (load_state (_current_snapshot_name)) {
288 if (_butler->start_thread()) {
292 if (start_midi_thread ()) {
296 setup_midi_machine_control ();
298 // set_state() will call setup_raid_path(), but if it's a new session we need
299 // to call setup_raid_path() here.
302 if (set_state (*state_tree->root(), Stateful::loading_state_version)) {
306 setup_raid_path(_path);
309 /* we can't save till after ::when_engine_running() is called,
310 because otherwise we save state with no connections made.
311 therefore, we reset _state_of_the_state because ::set_state()
312 will have cleared it.
314 we also have to include Loading so that any events that get
315 generated between here and the end of ::when_engine_running()
316 will be processed directly rather than queued.
319 _state_of_the_state = StateOfTheState (_state_of_the_state|CannotSave|Loading);
321 _locations->changed.connect_same_thread (*this, boost::bind (&Session::locations_changed, this));
322 _locations->added.connect_same_thread (*this, boost::bind (&Session::locations_added, this, _1));
323 setup_click_sounds (0);
324 setup_midi_control ();
326 /* Pay attention ... */
328 _engine.Halted.connect_same_thread (*this, boost::bind (&Session::engine_halted, this));
329 _engine.Xrun.connect_same_thread (*this, boost::bind (&Session::xrun_recovery, this));
331 midi_clock = new MidiClockTicker ();
332 midi_clock->set_session (this);
335 when_engine_running ();
338 /* handle this one in a different way than all others, so that its clear what happened */
340 catch (AudioEngine::PortRegistrationFailure& err) {
341 error << err.what() << endmsg;
349 BootMessage (_("Reset Remote Controls"));
351 send_full_time_code (0);
352 _engine.transport_locate (0);
354 MIDI::Manager::instance()->mmc()->send (MIDI::MachineControlCommand (MIDI::MachineControl::cmdMmcReset));
355 MIDI::Manager::instance()->mmc()->send (MIDI::MachineControlCommand (Timecode::Time ()));
357 MIDI::Name::MidiPatchManager::instance().set_session (this);
360 /* initial program change will be delivered later; see ::config_changed() */
362 _state_of_the_state = Clean;
364 Port::set_connecting_blocked (false);
366 DirtyChanged (); /* EMIT SIGNAL */
368 if (state_was_pending) {
369 save_state (_current_snapshot_name);
370 remove_pending_capture_state ();
371 state_was_pending = false;
374 BootMessage (_("Session loading complete"));
380 Session::raid_path () const
382 SearchPath raid_search_path;
384 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
385 raid_search_path += (*i).path;
388 return raid_search_path.to_string ();
392 Session::setup_raid_path (string path)
401 session_dirs.clear ();
403 SearchPath search_path(path);
404 SearchPath sound_search_path;
405 SearchPath midi_search_path;
407 for (SearchPath::const_iterator i = search_path.begin(); i != search_path.end(); ++i) {
409 sp.blocks = 0; // not needed
410 session_dirs.push_back (sp);
412 SessionDirectory sdir(sp.path);
414 sound_search_path += sdir.sound_path ();
415 midi_search_path += sdir.midi_path ();
418 // reset the round-robin soundfile path thingie
419 last_rr_session_dir = session_dirs.begin();
423 Session::path_is_within_session (const std::string& path)
425 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
426 if (PBD::path_is_within (i->path, path)) {
434 Session::ensure_subdirs ()
438 dir = session_directory().peak_path();
440 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
441 error << string_compose(_("Session: cannot create session peakfile folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
445 dir = session_directory().sound_path();
447 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
448 error << string_compose(_("Session: cannot create session sounds dir \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
452 dir = session_directory().midi_path();
454 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
455 error << string_compose(_("Session: cannot create session midi dir \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
459 dir = session_directory().dead_path();
461 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
462 error << string_compose(_("Session: cannot create session dead sounds folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
466 dir = session_directory().export_path();
468 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
469 error << string_compose(_("Session: cannot create session export folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
473 dir = analysis_dir ();
475 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
476 error << string_compose(_("Session: cannot create session analysis folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
480 dir = plugins_dir ();
482 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
483 error << string_compose(_("Session: cannot create session plugins folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
487 dir = externals_dir ();
489 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
490 error << string_compose(_("Session: cannot create session externals folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
497 /** @param session_template directory containing session template, or empty.
498 * Caller must not hold process lock.
501 Session::create (const string& session_template, BusProfile* bus_profile)
503 if (g_mkdir_with_parents (_path.c_str(), 0755) < 0) {
504 error << string_compose(_("Session: cannot create session folder \"%1\" (%2)"), _path, strerror (errno)) << endmsg;
508 if (ensure_subdirs ()) {
512 _writable = exists_and_writable (_path);
514 if (!session_template.empty()) {
515 std::string in_path = session_template_dir_to_file (session_template);
517 ifstream in(in_path.c_str());
520 string out_path = _path;
522 out_path += statefile_suffix;
524 ofstream out(out_path.c_str());
530 /* Copy plugin state files from template to new session */
531 std::string template_plugins = Glib::build_filename (session_template, X_("plugins"));
532 copy_files (template_plugins, plugins_dir ());
537 error << string_compose (_("Could not open %1 for writing session template"), out_path)
543 error << string_compose (_("Could not open session template %1 for reading"), in_path)
550 /* set initial start + end point */
552 _state_of_the_state = Clean;
554 /* set up Master Out and Control Out if necessary */
559 ChanCount count(DataType::AUDIO, bus_profile->master_out_channels);
561 if (bus_profile->master_out_channels) {
562 boost::shared_ptr<Route> r (new Route (*this, _("master"), Route::MasterOut, DataType::AUDIO));
566 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
567 // boost_debug_shared_ptr_mark_interesting (r.get(), "Route");
570 Glib::Threads::Mutex::Lock lm (AudioEngine::instance()->process_lock ());
571 r->input()->ensure_io (count, false, this);
572 r->output()->ensure_io (count, false, this);
578 /* prohibit auto-connect to master, because there isn't one */
579 bus_profile->output_ac = AutoConnectOption (bus_profile->output_ac & ~AutoConnectMaster);
583 add_routes (rl, false, false, false);
586 /* this allows the user to override settings with an environment variable.
589 if (no_auto_connect()) {
590 bus_profile->input_ac = AutoConnectOption (0);
591 bus_profile->output_ac = AutoConnectOption (0);
594 Config->set_input_auto_connect (bus_profile->input_ac);
595 Config->set_output_auto_connect (bus_profile->output_ac);
598 if (Config->get_use_monitor_bus() && bus_profile) {
599 add_monitor_section ();
608 Session::maybe_write_autosave()
610 if (dirty() && record_status() != Recording) {
611 save_state("", true);
616 Session::remove_pending_capture_state ()
618 std::string pending_state_file_path(_session_dir->root_path());
620 pending_state_file_path = Glib::build_filename (pending_state_file_path, legalize_for_path (_current_snapshot_name) + pending_suffix);
622 if (!Glib::file_test (pending_state_file_path, Glib::FILE_TEST_EXISTS)) return;
624 if (g_remove (pending_state_file_path.c_str()) != 0) {
625 error << string_compose(_("Could not remove pending capture state at path \"%1\" (%2)"),
626 pending_state_file_path, g_strerror (errno)) << endmsg;
630 /** Rename a state file.
631 * @param old_name Old snapshot name.
632 * @param new_name New snapshot name.
635 Session::rename_state (string old_name, string new_name)
637 if (old_name == _current_snapshot_name || old_name == _name) {
638 /* refuse to rename the current snapshot or the "main" one */
642 const string old_xml_filename = legalize_for_path (old_name) + statefile_suffix;
643 const string new_xml_filename = legalize_for_path (new_name) + statefile_suffix;
645 const std::string old_xml_path(Glib::build_filename (_session_dir->root_path(), old_xml_filename));
646 const std::string new_xml_path(Glib::build_filename (_session_dir->root_path(), new_xml_filename));
648 if (::g_rename (old_xml_path.c_str(), new_xml_path.c_str()) != 0) {
649 error << string_compose(_("could not rename snapshot %1 to %2 (%3)"),
650 old_name, new_name, g_strerror(errno)) << endmsg;
654 /** Remove a state file.
655 * @param snapshot_name Snapshot name.
658 Session::remove_state (string snapshot_name)
660 if (!_writable || snapshot_name == _current_snapshot_name || snapshot_name == _name) {
661 // refuse to remove the current snapshot or the "main" one
665 std::string xml_path(_session_dir->root_path());
667 xml_path = Glib::build_filename (xml_path, legalize_for_path (snapshot_name) + statefile_suffix);
669 if (!create_backup_file (xml_path)) {
670 // don't remove it if a backup can't be made
671 // create_backup_file will log the error.
676 if (g_remove (xml_path.c_str()) != 0) {
677 error << string_compose(_("Could not remove session file at path \"%1\" (%2)"),
678 xml_path, g_strerror (errno)) << endmsg;
682 #ifdef HAVE_JACK_SESSION
684 Session::jack_session_event (jack_session_event_t * event)
686 char timebuf[128], *tmp;
688 struct tm local_time;
691 localtime_r (&n, &local_time);
692 strftime (timebuf, sizeof(timebuf), "JS_%FT%T", &local_time);
694 while ((tmp = strchr(timebuf, ':'))) { *tmp = '.'; }
696 if (event->type == JackSessionSaveTemplate)
698 if (save_template( timebuf )) {
699 event->flags = JackSessionSaveError;
701 string cmd ("ardour3 -P -U ");
702 cmd += event->client_uuid;
706 event->command_line = strdup (cmd.c_str());
711 if (save_state (timebuf)) {
712 event->flags = JackSessionSaveError;
714 std::string xml_path (_session_dir->root_path());
715 std::string legalized_filename = legalize_for_path (timebuf) + statefile_suffix;
716 xml_path = Glib::build_filename (xml_path, legalized_filename);
718 string cmd ("ardour3 -P -U ");
719 cmd += event->client_uuid;
724 event->command_line = strdup (cmd.c_str());
728 jack_session_reply (_engine.jack(), event);
730 if (event->type == JackSessionSaveAndQuit) {
731 Quit (); /* EMIT SIGNAL */
734 jack_session_event_free( event );
738 /** @param snapshot_name Name to save under, without .ardour / .pending prefix */
740 Session::save_state (string snapshot_name, bool pending, bool switch_to_snapshot)
743 std::string xml_path(_session_dir->root_path());
745 if (!_writable || (_state_of_the_state & CannotSave)) {
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"),
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) {
760 i->second->session_saved();
761 } catch (Evoral::SMF::FileError& e) {
762 error << string_compose ("Could not write to MIDI file %1; MIDI data not saved.", e.file_name ()) << endmsg;
766 SaveSession (); /* EMIT SIGNAL */
768 tree.set_root (&get_state());
770 if (snapshot_name.empty()) {
771 snapshot_name = _current_snapshot_name;
772 } else if (switch_to_snapshot) {
773 _current_snapshot_name = snapshot_name;
778 /* proper save: use statefile_suffix (.ardour in English) */
780 xml_path = Glib::build_filename (xml_path, legalize_for_path (snapshot_name) + statefile_suffix);
782 /* make a backup copy of the old file */
784 if (Glib::file_test (xml_path, Glib::FILE_TEST_EXISTS) && !create_backup_file (xml_path)) {
785 // create_backup_file will log the error
791 /* pending save: use pending_suffix (.pending in English) */
792 xml_path = Glib::build_filename (xml_path, legalize_for_path (snapshot_name) + pending_suffix);
795 std::string tmp_path(_session_dir->root_path());
796 tmp_path = Glib::build_filename (tmp_path, legalize_for_path (snapshot_name) + temp_suffix);
798 // cerr << "actually writing state to " << xml_path << endl;
800 if (!tree.write (tmp_path)) {
801 error << string_compose (_("state could not be saved to %1"), tmp_path) << endmsg;
802 if (g_remove (tmp_path.c_str()) != 0) {
803 error << string_compose(_("Could not remove temporary session file at path \"%1\" (%2)"),
804 tmp_path, g_strerror (errno)) << endmsg;
810 if (::g_rename (tmp_path.c_str(), xml_path.c_str()) != 0) {
811 error << string_compose (_("could not rename temporary session file %1 to %2 (%3)"),
812 tmp_path, xml_path, g_strerror(errno)) << endmsg;
813 if (g_remove (tmp_path.c_str()) != 0) {
814 error << string_compose(_("Could not remove temporary session file at path \"%1\" (%2)"),
815 tmp_path, g_strerror (errno)) << endmsg;
823 save_history (snapshot_name);
825 bool was_dirty = dirty();
827 _state_of_the_state = StateOfTheState (_state_of_the_state & ~Dirty);
830 DirtyChanged (); /* EMIT SIGNAL */
833 StateSaved (snapshot_name); /* EMIT SIGNAL */
840 Session::restore_state (string snapshot_name)
842 if (load_state (snapshot_name) == 0) {
843 set_state (*state_tree->root(), Stateful::loading_state_version);
850 Session::load_state (string snapshot_name)
855 state_was_pending = false;
857 /* check for leftover pending state from a crashed capture attempt */
859 std::string xmlpath(_session_dir->root_path());
860 xmlpath = Glib::build_filename (xmlpath, legalize_for_path (snapshot_name) + pending_suffix);
862 if (Glib::file_test (xmlpath, Glib::FILE_TEST_EXISTS)) {
864 /* there is pending state from a crashed capture attempt */
866 boost::optional<int> r = AskAboutPendingState();
867 if (r.get_value_or (1)) {
868 state_was_pending = true;
872 if (!state_was_pending) {
873 xmlpath = Glib::build_filename (_session_dir->root_path(), snapshot_name);
876 if (!Glib::file_test (xmlpath, Glib::FILE_TEST_EXISTS)) {
877 xmlpath = Glib::build_filename (_session_dir->root_path(), legalize_for_path (snapshot_name) + statefile_suffix);
878 if (!Glib::file_test (xmlpath, Glib::FILE_TEST_EXISTS)) {
879 error << string_compose(_("%1: session file \"%2\" doesn't exist!"), _name, xmlpath) << endmsg;
884 state_tree = new XMLTree;
888 _writable = exists_and_writable (xmlpath);
890 if (!state_tree->read (xmlpath)) {
891 error << string_compose(_("Could not understand session file %1"), xmlpath) << endmsg;
897 XMLNode& root (*state_tree->root());
899 if (root.name() != X_("Session")) {
900 error << string_compose (_("Session file %1 is not a session"), xmlpath) << endmsg;
906 const XMLProperty* prop;
908 if ((prop = root.property ("version")) == 0) {
909 /* no version implies very old version of Ardour */
910 Stateful::loading_state_version = 1000;
912 if (prop->value().find ('.') != string::npos) {
913 /* old school version format */
914 if (prop->value()[0] == '2') {
915 Stateful::loading_state_version = 2000;
917 Stateful::loading_state_version = 3000;
920 Stateful::loading_state_version = atoi (prop->value());
924 if (Stateful::loading_state_version < CURRENT_SESSION_FILE_VERSION && _writable) {
926 std::string backup_path(_session_dir->root_path());
927 std::string backup_filename = string_compose ("%1-%2%3", legalize_for_path (snapshot_name), Stateful::loading_state_version, statefile_suffix);
928 backup_path = Glib::build_filename (backup_path, backup_filename);
930 // only create a backup for a given statefile version once
932 if (!Glib::file_test (backup_path, Glib::FILE_TEST_EXISTS)) {
934 VersionMismatch (xmlpath, backup_path);
936 if (!copy_file (xmlpath, backup_path)) {;
946 Session::load_options (const XMLNode& node)
948 LocaleGuard lg (X_("POSIX"));
949 config.set_variables (node);
960 Session::get_template()
962 /* if we don't disable rec-enable, diskstreams
963 will believe they need to store their capture
964 sources in their state node.
967 disable_record (false);
973 Session::state (bool full_state)
975 XMLNode* node = new XMLNode("Session");
979 snprintf(buf, sizeof(buf), "%d", CURRENT_SESSION_FILE_VERSION);
980 node->add_property("version", buf);
982 /* store configuration settings */
986 node->add_property ("name", _name);
987 snprintf (buf, sizeof (buf), "%" PRId64, _nominal_frame_rate);
988 node->add_property ("sample-rate", buf);
990 if (session_dirs.size() > 1) {
994 vector<space_and_path>::iterator i = session_dirs.begin();
995 vector<space_and_path>::iterator next;
997 ++i; /* skip the first one */
1001 while (i != session_dirs.end()) {
1005 if (next != session_dirs.end()) {
1015 child = node->add_child ("Path");
1016 child->add_content (p);
1020 /* save the ID counter */
1022 snprintf (buf, sizeof (buf), "%" PRIu64, ID::counter());
1023 node->add_property ("id-counter", buf);
1025 /* save the event ID counter */
1027 snprintf (buf, sizeof (buf), "%d", Evoral::event_id_counter());
1028 node->add_property ("event-counter", buf);
1030 /* various options */
1032 node->add_child_nocopy (config.get_variables ());
1034 node->add_child_nocopy (ARDOUR::SessionMetadata::Metadata()->get_state());
1036 child = node->add_child ("Sources");
1039 Glib::Threads::Mutex::Lock sl (source_lock);
1041 for (SourceMap::iterator siter = sources.begin(); siter != sources.end(); ++siter) {
1043 /* Don't save information about non-file Sources, or
1044 * about non-destructive file sources that are empty
1045 * and unused by any regions.
1048 boost::shared_ptr<FileSource> fs;
1050 if ((fs = boost::dynamic_pointer_cast<FileSource> (siter->second)) != 0) {
1052 if (!fs->destructive()) {
1053 if (fs->empty() && !fs->used()) {
1058 child->add_child_nocopy (siter->second->get_state());
1063 child = node->add_child ("Regions");
1066 Glib::Threads::Mutex::Lock rl (region_lock);
1067 const RegionFactory::RegionMap& region_map (RegionFactory::all_regions());
1068 for (RegionFactory::RegionMap::const_iterator i = region_map.begin(); i != region_map.end(); ++i) {
1069 boost::shared_ptr<Region> r = i->second;
1070 /* only store regions not attached to playlists */
1071 if (r->playlist() == 0) {
1072 if (boost::dynamic_pointer_cast<AudioRegion>(r)) {
1073 child->add_child_nocopy ((boost::dynamic_pointer_cast<AudioRegion>(r))->get_basic_state ());
1075 child->add_child_nocopy (r->get_state ());
1080 RegionFactory::CompoundAssociations& cassocs (RegionFactory::compound_associations());
1082 if (!cassocs.empty()) {
1083 XMLNode* ca = node->add_child (X_("CompoundAssociations"));
1085 for (RegionFactory::CompoundAssociations::iterator i = cassocs.begin(); i != cassocs.end(); ++i) {
1087 XMLNode* can = new XMLNode (X_("CompoundAssociation"));
1088 i->first->id().print (buf, sizeof (buf));
1089 can->add_property (X_("copy"), buf);
1090 i->second->id().print (buf, sizeof (buf));
1091 can->add_property (X_("original"), buf);
1092 ca->add_child_nocopy (*can);
1098 node->add_child_nocopy (_locations->get_state());
1100 // for a template, just create a new Locations, populate it
1101 // with the default start and end, and get the state for that.
1102 Locations loc (*this);
1103 Location* range = new Location (*this, 0, 0, _("session"), Location::IsSessionRange);
1104 range->set (max_framepos, 0);
1106 node->add_child_nocopy (loc.get_state());
1109 child = node->add_child ("Bundles");
1111 boost::shared_ptr<BundleList> bundles = _bundles.reader ();
1112 for (BundleList::iterator i = bundles->begin(); i != bundles->end(); ++i) {
1113 boost::shared_ptr<UserBundle> b = boost::dynamic_pointer_cast<UserBundle> (*i);
1115 child->add_child_nocopy (b->get_state());
1120 child = node->add_child ("Routes");
1122 boost::shared_ptr<RouteList> r = routes.reader ();
1124 RoutePublicOrderSorter cmp;
1125 RouteList public_order (*r);
1126 public_order.sort (cmp);
1128 /* the sort should have put control outs first */
1131 assert (_monitor_out == public_order.front());
1134 for (RouteList::iterator i = public_order.begin(); i != public_order.end(); ++i) {
1135 if (!(*i)->is_auditioner()) {
1137 child->add_child_nocopy ((*i)->get_state());
1139 child->add_child_nocopy ((*i)->get_template());
1145 playlists->add_state (node, full_state);
1147 child = node->add_child ("RouteGroups");
1148 for (list<RouteGroup *>::iterator i = _route_groups.begin(); i != _route_groups.end(); ++i) {
1149 child->add_child_nocopy ((*i)->get_state());
1153 XMLNode* gain_child = node->add_child ("Click");
1154 gain_child->add_child_nocopy (_click_io->state (full_state));
1155 gain_child->add_child_nocopy (_click_gain->state (full_state));
1159 XMLNode* ltc_input_child = node->add_child ("LTC-In");
1160 ltc_input_child->add_child_nocopy (_ltc_input->state (full_state));
1164 XMLNode* ltc_output_child = node->add_child ("LTC-Out");
1165 ltc_output_child->add_child_nocopy (_ltc_output->state (full_state));
1168 node->add_child_nocopy (_speakers->get_state());
1169 node->add_child_nocopy (_tempo_map->get_state());
1170 node->add_child_nocopy (get_control_protocol_state());
1173 node->add_child_copy (*_extra_xml);
1180 Session::get_control_protocol_state ()
1182 ControlProtocolManager& cpm (ControlProtocolManager::instance());
1183 return cpm.get_state();
1187 Session::set_state (const XMLNode& node, int version)
1191 const XMLProperty* prop;
1194 _state_of_the_state = StateOfTheState (_state_of_the_state|CannotSave);
1196 if (node.name() != X_("Session")) {
1197 fatal << _("programming error: Session: incorrect XML node sent to set_state()") << endmsg;
1201 if ((prop = node.property ("name")) != 0) {
1202 _name = prop->value ();
1205 if ((prop = node.property (X_("sample-rate"))) != 0) {
1207 _nominal_frame_rate = atoi (prop->value());
1209 if (_nominal_frame_rate != _current_frame_rate) {
1210 boost::optional<int> r = AskAboutSampleRateMismatch (_nominal_frame_rate, _current_frame_rate);
1211 if (r.get_value_or (0)) {
1217 setup_raid_path(_session_dir->root_path());
1219 if ((prop = node.property (X_("id-counter"))) != 0) {
1221 sscanf (prop->value().c_str(), "%" PRIu64, &x);
1222 ID::init_counter (x);
1224 /* old sessions used a timebased counter, so fake
1225 the startup ID counter based on a standard
1230 ID::init_counter (now);
1233 if ((prop = node.property (X_("event-counter"))) != 0) {
1234 Evoral::init_event_id_counter (atoi (prop->value()));
1237 IO::disable_connecting ();
1239 Stateful::save_extra_xml (node);
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);
1246 error << _("Session: XML state has no options section") << endmsg;
1249 if (version >= 3000) {
1250 if ((child = find_named_node (node, "Metadata")) == 0) {
1251 warning << _("Session: XML state has no metadata section") << endmsg;
1252 } else if ( ARDOUR::SessionMetadata::Metadata()->set_state (*child, version) ) {
1257 if ((child = find_named_node (node, X_("Speakers"))) != 0) {
1258 _speakers->set_state (*child, version);
1261 if ((child = find_named_node (node, "Sources")) == 0) {
1262 error << _("Session: XML state has no sources section") << endmsg;
1264 } else if (load_sources (*child)) {
1268 if ((child = find_named_node (node, "TempoMap")) == 0) {
1269 error << _("Session: XML state has no Tempo Map section") << endmsg;
1271 } else if (_tempo_map->set_state (*child, version)) {
1275 if ((child = find_named_node (node, "Locations")) == 0) {
1276 error << _("Session: XML state has no locations section") << endmsg;
1278 } else if (_locations->set_state (*child, version)) {
1284 if ((location = _locations->auto_loop_location()) != 0) {
1285 set_auto_loop_location (location);
1288 if ((location = _locations->auto_punch_location()) != 0) {
1289 set_auto_punch_location (location);
1292 if ((location = _locations->session_range_location()) != 0) {
1293 delete _session_range_location;
1294 _session_range_location = location;
1297 if (_session_range_location) {
1298 AudioFileSource::set_header_position_offset (_session_range_location->start());
1301 if ((child = find_named_node (node, "Regions")) == 0) {
1302 error << _("Session: XML state has no Regions section") << endmsg;
1304 } else if (load_regions (*child)) {
1308 if ((child = find_named_node (node, "Playlists")) == 0) {
1309 error << _("Session: XML state has no playlists section") << endmsg;
1311 } else if (playlists->load (*this, *child)) {
1315 if ((child = find_named_node (node, "UnusedPlaylists")) == 0) {
1317 } else if (playlists->load_unused (*this, *child)) {
1321 if ((child = find_named_node (node, "CompoundAssociations")) != 0) {
1322 if (load_compounds (*child)) {
1327 if (version >= 3000) {
1328 if ((child = find_named_node (node, "Bundles")) == 0) {
1329 warning << _("Session: XML state has no bundles section") << endmsg;
1332 /* We can't load Bundles yet as they need to be able
1333 to convert from port names to Port objects, which can't happen until
1335 _bundle_xml_node = new XMLNode (*child);
1339 if (version < 3000) {
1340 if ((child = find_named_node (node, X_("DiskStreams"))) == 0) {
1341 error << _("Session: XML state has no diskstreams section") << endmsg;
1343 } else if (load_diskstreams_2X (*child, version)) {
1348 if ((child = find_named_node (node, "Routes")) == 0) {
1349 error << _("Session: XML state has no routes section") << endmsg;
1351 } else if (load_routes (*child, version)) {
1355 /* our diskstreams list is no longer needed as they are now all owned by their Route */
1356 _diskstreams_2X.clear ();
1358 if (version >= 3000) {
1360 if ((child = find_named_node (node, "RouteGroups")) == 0) {
1361 error << _("Session: XML state has no route groups section") << endmsg;
1363 } else if (load_route_groups (*child, version)) {
1367 } else if (version < 3000) {
1369 if ((child = find_named_node (node, "EditGroups")) == 0) {
1370 error << _("Session: XML state has no edit groups section") << endmsg;
1372 } else if (load_route_groups (*child, version)) {
1376 if ((child = find_named_node (node, "MixGroups")) == 0) {
1377 error << _("Session: XML state has no mix groups section") << endmsg;
1379 } else if (load_route_groups (*child, version)) {
1384 if ((child = find_named_node (node, "Click")) == 0) {
1385 warning << _("Session: XML state has no click section") << endmsg;
1386 } else if (_click_io) {
1387 const XMLNodeList& children (child->children());
1388 XMLNodeList::const_iterator i = children.begin();
1389 _click_io->set_state (**i, version);
1391 if (i != children.end()) {
1392 _click_gain->set_state (**i, version);
1396 if ((child = find_named_node (node, ControlProtocolManager::state_node_name)) != 0) {
1397 ControlProtocolManager::instance().set_state (*child, version);
1400 update_have_rec_enabled_track ();
1402 /* here beginneth the second phase ... */
1404 StateReady (); /* EMIT SIGNAL */
1413 Session::load_routes (const XMLNode& node, int version)
1416 XMLNodeConstIterator niter;
1417 RouteList new_routes;
1419 nlist = node.children();
1423 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1425 boost::shared_ptr<Route> route;
1426 if (version < 3000) {
1427 route = XMLRouteFactory_2X (**niter, version);
1429 route = XMLRouteFactory (**niter, version);
1433 error << _("Session: cannot create Route from XML description.") << endmsg;
1437 BootMessage (string_compose (_("Loaded track/bus %1"), route->name()));
1439 new_routes.push_back (route);
1442 add_routes (new_routes, false, false, false);
1447 boost::shared_ptr<Route>
1448 Session::XMLRouteFactory (const XMLNode& node, int version)
1450 boost::shared_ptr<Route> ret;
1452 if (node.name() != "Route") {
1456 XMLNode* ds_child = find_named_node (node, X_("Diskstream"));
1458 DataType type = DataType::AUDIO;
1459 const XMLProperty* prop = node.property("default-type");
1462 type = DataType (prop->value());
1465 assert (type != DataType::NIL);
1469 boost::shared_ptr<Track> track;
1471 if (type == DataType::AUDIO) {
1472 track.reset (new AudioTrack (*this, X_("toBeResetFroXML")));
1474 track.reset (new MidiTrack (*this, X_("toBeResetFroXML")));
1477 if (track->init()) {
1481 if (track->set_state (node, version)) {
1485 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
1486 // boost_debug_shared_ptr_mark_interesting (track.get(), "Track");
1491 boost::shared_ptr<Route> r (new Route (*this, X_("toBeResetFroXML")));
1493 if (r->init () == 0 && r->set_state (node, version) == 0) {
1494 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
1495 // boost_debug_shared_ptr_mark_interesting (r.get(), "Route");
1504 boost::shared_ptr<Route>
1505 Session::XMLRouteFactory_2X (const XMLNode& node, int version)
1507 boost::shared_ptr<Route> ret;
1509 if (node.name() != "Route") {
1513 XMLProperty const * ds_prop = node.property (X_("diskstream-id"));
1515 ds_prop = node.property (X_("diskstream"));
1518 DataType type = DataType::AUDIO;
1519 const XMLProperty* prop = node.property("default-type");
1522 type = DataType (prop->value());
1525 assert (type != DataType::NIL);
1529 list<boost::shared_ptr<Diskstream> >::iterator i = _diskstreams_2X.begin ();
1530 while (i != _diskstreams_2X.end() && (*i)->id() != ds_prop->value()) {
1534 if (i == _diskstreams_2X.end()) {
1535 error << _("Could not find diskstream for route") << endmsg;
1536 return boost::shared_ptr<Route> ();
1539 boost::shared_ptr<Track> track;
1541 if (type == DataType::AUDIO) {
1542 track.reset (new AudioTrack (*this, X_("toBeResetFroXML")));
1544 track.reset (new MidiTrack (*this, X_("toBeResetFroXML")));
1547 if (track->init()) {
1551 if (track->set_state (node, version)) {
1555 track->set_diskstream (*i);
1557 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
1558 // boost_debug_shared_ptr_mark_interesting (track.get(), "Track");
1563 boost::shared_ptr<Route> r (new Route (*this, X_("toBeResetFroXML")));
1565 if (r->init () == 0 && r->set_state (node, version) == 0) {
1566 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
1567 // boost_debug_shared_ptr_mark_interesting (r.get(), "Route");
1577 Session::load_regions (const XMLNode& node)
1580 XMLNodeConstIterator niter;
1581 boost::shared_ptr<Region> region;
1583 nlist = node.children();
1587 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1588 if ((region = XMLRegionFactory (**niter, false)) == 0) {
1589 error << _("Session: cannot create Region from XML description.");
1590 const XMLProperty *name = (**niter).property("name");
1593 error << " " << string_compose (_("Can not load state for region '%1'"), name->value());
1604 Session::load_compounds (const XMLNode& node)
1606 XMLNodeList calist = node.children();
1607 XMLNodeConstIterator caiter;
1608 XMLProperty *caprop;
1610 for (caiter = calist.begin(); caiter != calist.end(); ++caiter) {
1611 XMLNode* ca = *caiter;
1615 if ((caprop = ca->property (X_("original"))) == 0) {
1618 orig_id = caprop->value();
1620 if ((caprop = ca->property (X_("copy"))) == 0) {
1623 copy_id = caprop->value();
1625 boost::shared_ptr<Region> orig = RegionFactory::region_by_id (orig_id);
1626 boost::shared_ptr<Region> copy = RegionFactory::region_by_id (copy_id);
1628 if (!orig || !copy) {
1629 warning << string_compose (_("Regions in compound description not found (ID's %1 and %2): ignored"),
1635 RegionFactory::add_compound_association (orig, copy);
1642 Session::load_nested_sources (const XMLNode& node)
1645 XMLNodeConstIterator niter;
1647 nlist = node.children();
1649 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1650 if ((*niter)->name() == "Source") {
1652 /* it may already exist, so don't recreate it unnecessarily
1655 XMLProperty* prop = (*niter)->property (X_("id"));
1657 error << _("Nested source has no ID info in session file! (ignored)") << endmsg;
1661 ID source_id (prop->value());
1663 if (!source_by_id (source_id)) {
1666 SourceFactory::create (*this, **niter, true);
1668 catch (failed_constructor& err) {
1669 error << string_compose (_("Cannot reconstruct nested source for region %1"), name()) << endmsg;
1676 boost::shared_ptr<Region>
1677 Session::XMLRegionFactory (const XMLNode& node, bool full)
1679 const XMLProperty* type = node.property("type");
1683 const XMLNodeList& nlist = node.children();
1685 for (XMLNodeConstIterator niter = nlist.begin(); niter != nlist.end(); ++niter) {
1686 XMLNode *child = (*niter);
1687 if (child->name() == "NestedSource") {
1688 load_nested_sources (*child);
1692 if (!type || type->value() == "audio") {
1693 return boost::shared_ptr<Region>(XMLAudioRegionFactory (node, full));
1694 } else if (type->value() == "midi") {
1695 return boost::shared_ptr<Region>(XMLMidiRegionFactory (node, full));
1698 } catch (failed_constructor& err) {
1699 return boost::shared_ptr<Region> ();
1702 return boost::shared_ptr<Region> ();
1705 boost::shared_ptr<AudioRegion>
1706 Session::XMLAudioRegionFactory (const XMLNode& node, bool /*full*/)
1708 const XMLProperty* prop;
1709 boost::shared_ptr<Source> source;
1710 boost::shared_ptr<AudioSource> as;
1712 SourceList master_sources;
1713 uint32_t nchans = 1;
1716 if (node.name() != X_("Region")) {
1717 return boost::shared_ptr<AudioRegion>();
1720 if ((prop = node.property (X_("channels"))) != 0) {
1721 nchans = atoi (prop->value().c_str());
1724 if ((prop = node.property ("name")) == 0) {
1725 cerr << "no name for this region\n";
1729 if ((prop = node.property (X_("source-0"))) == 0) {
1730 if ((prop = node.property ("source")) == 0) {
1731 error << _("Session: XMLNode describing a AudioRegion is incomplete (no source)") << endmsg;
1732 return boost::shared_ptr<AudioRegion>();
1736 PBD::ID s_id (prop->value());
1738 if ((source = source_by_id (s_id)) == 0) {
1739 error << string_compose(_("Session: XMLNode describing a AudioRegion references an unknown source id =%1"), s_id) << endmsg;
1740 return boost::shared_ptr<AudioRegion>();
1743 as = boost::dynamic_pointer_cast<AudioSource>(source);
1745 error << string_compose(_("Session: XMLNode describing a AudioRegion references a non-audio source id =%1"), s_id) << endmsg;
1746 return boost::shared_ptr<AudioRegion>();
1749 sources.push_back (as);
1751 /* pickup other channels */
1753 for (uint32_t n=1; n < nchans; ++n) {
1754 snprintf (buf, sizeof(buf), X_("source-%d"), n);
1755 if ((prop = node.property (buf)) != 0) {
1757 PBD::ID id2 (prop->value());
1759 if ((source = source_by_id (id2)) == 0) {
1760 error << string_compose(_("Session: XMLNode describing a AudioRegion references an unknown source id =%1"), id2) << endmsg;
1761 return boost::shared_ptr<AudioRegion>();
1764 as = boost::dynamic_pointer_cast<AudioSource>(source);
1766 error << string_compose(_("Session: XMLNode describing a AudioRegion references a non-audio source id =%1"), id2) << endmsg;
1767 return boost::shared_ptr<AudioRegion>();
1769 sources.push_back (as);
1773 for (uint32_t n = 0; n < nchans; ++n) {
1774 snprintf (buf, sizeof(buf), X_("master-source-%d"), n);
1775 if ((prop = node.property (buf)) != 0) {
1777 PBD::ID id2 (prop->value());
1779 if ((source = source_by_id (id2)) == 0) {
1780 error << string_compose(_("Session: XMLNode describing a AudioRegion references an unknown source id =%1"), id2) << endmsg;
1781 return boost::shared_ptr<AudioRegion>();
1784 as = boost::dynamic_pointer_cast<AudioSource>(source);
1786 error << string_compose(_("Session: XMLNode describing a AudioRegion references a non-audio source id =%1"), id2) << endmsg;
1787 return boost::shared_ptr<AudioRegion>();
1789 master_sources.push_back (as);
1794 boost::shared_ptr<AudioRegion> region (boost::dynamic_pointer_cast<AudioRegion> (RegionFactory::create (sources, node)));
1796 /* a final detail: this is the one and only place that we know how long missing files are */
1798 if (region->whole_file()) {
1799 for (SourceList::iterator sx = sources.begin(); sx != sources.end(); ++sx) {
1800 boost::shared_ptr<SilentFileSource> sfp = boost::dynamic_pointer_cast<SilentFileSource> (*sx);
1802 sfp->set_length (region->length());
1807 if (!master_sources.empty()) {
1808 if (master_sources.size() != nchans) {
1809 error << _("Session: XMLNode describing an AudioRegion is missing some master sources; ignored") << endmsg;
1811 region->set_master_sources (master_sources);
1819 catch (failed_constructor& err) {
1820 return boost::shared_ptr<AudioRegion>();
1824 boost::shared_ptr<MidiRegion>
1825 Session::XMLMidiRegionFactory (const XMLNode& node, bool /*full*/)
1827 const XMLProperty* prop;
1828 boost::shared_ptr<Source> source;
1829 boost::shared_ptr<MidiSource> ms;
1832 if (node.name() != X_("Region")) {
1833 return boost::shared_ptr<MidiRegion>();
1836 if ((prop = node.property ("name")) == 0) {
1837 cerr << "no name for this region\n";
1841 if ((prop = node.property (X_("source-0"))) == 0) {
1842 if ((prop = node.property ("source")) == 0) {
1843 error << _("Session: XMLNode describing a MidiRegion is incomplete (no source)") << endmsg;
1844 return boost::shared_ptr<MidiRegion>();
1848 PBD::ID s_id (prop->value());
1850 if ((source = source_by_id (s_id)) == 0) {
1851 error << string_compose(_("Session: XMLNode describing a MidiRegion references an unknown source id =%1"), s_id) << endmsg;
1852 return boost::shared_ptr<MidiRegion>();
1855 ms = boost::dynamic_pointer_cast<MidiSource>(source);
1857 error << string_compose(_("Session: XMLNode describing a MidiRegion references a non-midi source id =%1"), s_id) << endmsg;
1858 return boost::shared_ptr<MidiRegion>();
1861 sources.push_back (ms);
1864 boost::shared_ptr<MidiRegion> region (boost::dynamic_pointer_cast<MidiRegion> (RegionFactory::create (sources, node)));
1865 /* a final detail: this is the one and only place that we know how long missing files are */
1867 if (region->whole_file()) {
1868 for (SourceList::iterator sx = sources.begin(); sx != sources.end(); ++sx) {
1869 boost::shared_ptr<SilentFileSource> sfp = boost::dynamic_pointer_cast<SilentFileSource> (*sx);
1871 sfp->set_length (region->length());
1879 catch (failed_constructor& err) {
1880 return boost::shared_ptr<MidiRegion>();
1885 Session::get_sources_as_xml ()
1888 XMLNode* node = new XMLNode (X_("Sources"));
1889 Glib::Threads::Mutex::Lock lm (source_lock);
1891 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ++i) {
1892 node->add_child_nocopy (i->second->get_state());
1899 Session::path_from_region_name (DataType type, string name, string identifier)
1901 char buf[PATH_MAX+1];
1903 SessionDirectory sdir(get_best_session_directory_for_new_source());
1904 std::string source_dir = ((type == DataType::AUDIO)
1905 ? sdir.sound_path() : sdir.midi_path());
1907 string ext = native_header_format_extension (config.get_native_file_header_format(), type);
1909 for (n = 0; n < 999999; ++n) {
1910 if (identifier.length()) {
1911 snprintf (buf, sizeof(buf), "%s%s%" PRIu32 "%s", name.c_str(),
1912 identifier.c_str(), n, ext.c_str());
1914 snprintf (buf, sizeof(buf), "%s-%" PRIu32 "%s", name.c_str(),
1918 std::string source_path = Glib::build_filename (source_dir, buf);
1920 if (!Glib::file_test (source_path, Glib::FILE_TEST_EXISTS)) {
1925 error << string_compose (_("cannot create new file from region name \"%1\" with ident = \"%2\": too many existing files with similar names"),
1934 Session::load_sources (const XMLNode& node)
1937 XMLNodeConstIterator niter;
1938 boost::shared_ptr<Source> source;
1940 nlist = node.children();
1944 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1947 if ((source = XMLSourceFactory (**niter)) == 0) {
1948 error << _("Session: cannot create Source from XML description.") << endmsg;
1951 } catch (MissingSource& err) {
1955 if (!no_questions_about_missing_files) {
1956 user_choice = MissingFile (this, err.path, err.type).get_value_or (-1);
1961 switch (user_choice) {
1963 /* user added a new search location, so try again */
1968 /* user asked to quit the entire session load
1973 no_questions_about_missing_files = true;
1977 no_questions_about_missing_files = true;
1982 warning << _("A sound file is missing. It will be replaced by silence.") << endmsg;
1983 source = SourceFactory::createSilent (*this, **niter, max_framecnt, _current_frame_rate);
1992 boost::shared_ptr<Source>
1993 Session::XMLSourceFactory (const XMLNode& node)
1995 if (node.name() != "Source") {
1996 return boost::shared_ptr<Source>();
2000 /* note: do peak building in another thread when loading session state */
2001 return SourceFactory::create (*this, node, true);
2004 catch (failed_constructor& err) {
2005 error << string_compose (_("Found a sound file that cannot be used by %1. Talk to the progammers."), PROGRAM_NAME) << endmsg;
2006 return boost::shared_ptr<Source>();
2011 Session::save_template (string template_name)
2015 if (_state_of_the_state & CannotSave) {
2019 std::string user_template_dir(user_template_directory());
2021 if (g_mkdir_with_parents (user_template_dir.c_str(), 0755) != 0) {
2022 error << string_compose(_("Could not create templates directory \"%1\" (%2)"),
2023 user_template_dir, g_strerror (errno)) << endmsg;
2027 tree.set_root (&get_template());
2029 std::string template_dir_path(user_template_dir);
2031 /* directory to put the template in */
2032 template_dir_path = Glib::build_filename (template_dir_path, template_name);
2034 if (Glib::file_test (template_dir_path, Glib::FILE_TEST_EXISTS)) {
2035 warning << string_compose(_("Template \"%1\" already exists - new version not created"),
2036 template_dir_path) << endmsg;
2040 if (g_mkdir_with_parents (template_dir_path.c_str(), 0755) != 0) {
2041 error << string_compose(_("Could not create directory for Session template\"%1\" (%2)"),
2042 template_dir_path, g_strerror (errno)) << endmsg;
2047 std::string template_file_path(template_dir_path);
2048 template_file_path = Glib::build_filename (template_file_path, template_name + template_suffix);
2050 if (!tree.write (template_file_path)) {
2051 error << _("template not saved") << endmsg;
2055 /* copy plugin state directory */
2057 std::string template_plugin_state_path(template_dir_path);
2058 template_plugin_state_path = Glib::build_filename (template_plugin_state_path, X_("plugins"));
2060 if (g_mkdir_with_parents (template_plugin_state_path.c_str(), 0755) != 0) {
2061 error << string_compose(_("Could not create directory for Session template plugin state\"%1\" (%2)"),
2062 template_plugin_state_path, g_strerror (errno)) << endmsg;
2066 copy_files (plugins_dir(), template_plugin_state_path);
2072 Session::refresh_disk_space ()
2074 #if __APPLE__ || (HAVE_SYS_VFS_H && HAVE_SYS_STATVFS_H)
2076 Glib::Threads::Mutex::Lock lm (space_lock);
2078 /* get freespace on every FS that is part of the session path */
2080 _total_free_4k_blocks = 0;
2081 _total_free_4k_blocks_uncertain = false;
2083 for (vector<space_and_path>::iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
2085 struct statfs statfsbuf;
2086 statfs (i->path.c_str(), &statfsbuf);
2088 double const scale = statfsbuf.f_bsize / 4096.0;
2090 /* See if this filesystem is read-only */
2091 struct statvfs statvfsbuf;
2092 statvfs (i->path.c_str(), &statvfsbuf);
2094 /* f_bavail can be 0 if it is undefined for whatever
2095 filesystem we are looking at; Samba shares mounted
2096 via GVFS are an example of this.
2098 if (statfsbuf.f_bavail == 0) {
2099 /* block count unknown */
2101 i->blocks_unknown = true;
2102 } else if (statvfsbuf.f_flag & ST_RDONLY) {
2103 /* read-only filesystem */
2105 i->blocks_unknown = false;
2107 /* read/write filesystem with known space */
2108 i->blocks = (uint32_t) floor (statfsbuf.f_bavail * scale);
2109 i->blocks_unknown = false;
2112 _total_free_4k_blocks += i->blocks;
2113 if (i->blocks_unknown) {
2114 _total_free_4k_blocks_uncertain = true;
2121 Session::get_best_session_directory_for_new_source ()
2123 vector<space_and_path>::iterator i;
2124 string result = _session_dir->root_path();
2126 /* handle common case without system calls */
2128 if (session_dirs.size() == 1) {
2132 /* OK, here's the algorithm we're following here:
2134 We want to select which directory to use for
2135 the next file source to be created. Ideally,
2136 we'd like to use a round-robin process so as to
2137 get maximum performance benefits from splitting
2138 the files across multiple disks.
2140 However, in situations without much diskspace, an
2141 RR approach may end up filling up a filesystem
2142 with new files while others still have space.
2143 Its therefore important to pay some attention to
2144 the freespace in the filesystem holding each
2145 directory as well. However, if we did that by
2146 itself, we'd keep creating new files in the file
2147 system with the most space until it was as full
2148 as all others, thus negating any performance
2149 benefits of this RAID-1 like approach.
2151 So, we use a user-configurable space threshold. If
2152 there are at least 2 filesystems with more than this
2153 much space available, we use RR selection between them.
2154 If not, then we pick the filesystem with the most space.
2156 This gets a good balance between the two
2160 refresh_disk_space ();
2162 int free_enough = 0;
2164 for (i = session_dirs.begin(); i != session_dirs.end(); ++i) {
2165 if ((*i).blocks * 4096 >= Config->get_disk_choice_space_threshold()) {
2170 if (free_enough >= 2) {
2171 /* use RR selection process, ensuring that the one
2175 i = last_rr_session_dir;
2178 if (++i == session_dirs.end()) {
2179 i = session_dirs.begin();
2182 if ((*i).blocks * 4096 >= Config->get_disk_choice_space_threshold()) {
2183 SessionDirectory sdir(i->path);
2184 if (sdir.create ()) {
2186 last_rr_session_dir = i;
2191 } while (i != last_rr_session_dir);
2195 /* pick FS with the most freespace (and that
2196 seems to actually work ...)
2199 vector<space_and_path> sorted;
2200 space_and_path_ascending_cmp cmp;
2202 sorted = session_dirs;
2203 sort (sorted.begin(), sorted.end(), cmp);
2205 for (i = sorted.begin(); i != sorted.end(); ++i) {
2206 SessionDirectory sdir(i->path);
2207 if (sdir.create ()) {
2209 last_rr_session_dir = i;
2219 Session::automation_dir () const
2221 return Glib::build_filename (_path, "automation");
2225 Session::analysis_dir () const
2227 return Glib::build_filename (_path, "analysis");
2231 Session::plugins_dir () const
2233 return Glib::build_filename (_path, "plugins");
2237 Session::externals_dir () const
2239 return Glib::build_filename (_path, "externals");
2243 Session::load_bundles (XMLNode const & node)
2245 XMLNodeList nlist = node.children();
2246 XMLNodeConstIterator niter;
2250 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2251 if ((*niter)->name() == "InputBundle") {
2252 add_bundle (boost::shared_ptr<UserBundle> (new UserBundle (**niter, true)));
2253 } else if ((*niter)->name() == "OutputBundle") {
2254 add_bundle (boost::shared_ptr<UserBundle> (new UserBundle (**niter, false)));
2256 error << string_compose(_("Unknown node \"%1\" found in Bundles list from session file"), (*niter)->name()) << endmsg;
2265 Session::load_route_groups (const XMLNode& node, int version)
2267 XMLNodeList nlist = node.children();
2268 XMLNodeConstIterator niter;
2272 if (version >= 3000) {
2274 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2275 if ((*niter)->name() == "RouteGroup") {
2276 RouteGroup* rg = new RouteGroup (*this, "");
2277 add_route_group (rg);
2278 rg->set_state (**niter, version);
2282 } else if (version < 3000) {
2284 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2285 if ((*niter)->name() == "EditGroup" || (*niter)->name() == "MixGroup") {
2286 RouteGroup* rg = new RouteGroup (*this, "");
2287 add_route_group (rg);
2288 rg->set_state (**niter, version);
2297 Session::auto_save()
2299 save_state (_current_snapshot_name);
2303 state_file_filter (const string &str, void */*arg*/)
2305 return (str.length() > strlen(statefile_suffix) &&
2306 str.find (statefile_suffix) == (str.length() - strlen (statefile_suffix)));
2310 bool operator()(const string* a, const string* b) {
2316 remove_end(string* state)
2318 string statename(*state);
2320 string::size_type start,end;
2321 if ((start = statename.find_last_of (G_DIR_SEPARATOR)) != string::npos) {
2322 statename = statename.substr (start+1);
2325 if ((end = statename.rfind(".ardour")) == string::npos) {
2326 end = statename.length();
2329 return new string(statename.substr (0, end));
2333 Session::possible_states (string path)
2335 PathScanner scanner;
2336 vector<string*>* states = scanner (path, state_file_filter, 0, false, false);
2338 transform(states->begin(), states->end(), states->begin(), remove_end);
2341 sort (states->begin(), states->end(), cmp);
2347 Session::possible_states () const
2349 return possible_states(_path);
2353 Session::add_route_group (RouteGroup* g)
2355 _route_groups.push_back (g);
2356 route_group_added (g); /* EMIT SIGNAL */
2358 g->RouteAdded.connect_same_thread (*this, boost::bind (&Session::route_added_to_route_group, this, _1, _2));
2359 g->RouteRemoved.connect_same_thread (*this, boost::bind (&Session::route_removed_from_route_group, this, _1, _2));
2360 g->PropertyChanged.connect_same_thread (*this, boost::bind (&Session::route_group_property_changed, this, g));
2366 Session::remove_route_group (RouteGroup& rg)
2368 list<RouteGroup*>::iterator i;
2370 if ((i = find (_route_groups.begin(), _route_groups.end(), &rg)) != _route_groups.end()) {
2371 _route_groups.erase (i);
2374 route_group_removed (); /* EMIT SIGNAL */
2378 /** Set a new order for our route groups, without adding or removing any.
2379 * @param groups Route group list in the new order.
2382 Session::reorder_route_groups (list<RouteGroup*> groups)
2384 _route_groups = groups;
2386 route_groups_reordered (); /* EMIT SIGNAL */
2392 Session::route_group_by_name (string name)
2394 list<RouteGroup *>::iterator i;
2396 for (i = _route_groups.begin(); i != _route_groups.end(); ++i) {
2397 if ((*i)->name() == name) {
2405 Session::all_route_group() const
2407 return *_all_route_group;
2411 Session::add_commands (vector<Command*> const & cmds)
2413 for (vector<Command*>::const_iterator i = cmds.begin(); i != cmds.end(); ++i) {
2419 Session::begin_reversible_command (const string& name)
2421 begin_reversible_command (g_quark_from_string (name.c_str ()));
2424 /** Begin a reversible command using a GQuark to identify it.
2425 * begin_reversible_command() and commit_reversible_command() calls may be nested,
2426 * but there must be as many begin...()s as there are commit...()s.
2429 Session::begin_reversible_command (GQuark q)
2431 /* If nested begin/commit pairs are used, we create just one UndoTransaction
2432 to hold all the commands that are committed. This keeps the order of
2433 commands correct in the history.
2436 if (_current_trans == 0) {
2437 /* start a new transaction */
2438 assert (_current_trans_quarks.empty ());
2439 _current_trans = new UndoTransaction();
2440 _current_trans->set_name (g_quark_to_string (q));
2443 _current_trans_quarks.push_front (q);
2447 Session::commit_reversible_command (Command *cmd)
2449 assert (_current_trans);
2450 assert (!_current_trans_quarks.empty ());
2455 _current_trans->add_command (cmd);
2458 _current_trans_quarks.pop_front ();
2460 if (!_current_trans_quarks.empty ()) {
2461 /* the transaction we're committing is not the top-level one */
2465 if (_current_trans->empty()) {
2466 /* no commands were added to the transaction, so just get rid of it */
2467 delete _current_trans;
2472 gettimeofday (&now, 0);
2473 _current_trans->set_timestamp (now);
2475 _history.add (_current_trans);
2480 accept_all_audio_files (const string& path, void */*arg*/)
2482 if (!Glib::file_test (path, Glib::FILE_TEST_IS_REGULAR)) {
2486 if (!AudioFileSource::safe_audio_file_extension (path)) {
2494 accept_all_midi_files (const string& path, void */*arg*/)
2496 if (!Glib::file_test (path, Glib::FILE_TEST_IS_REGULAR)) {
2500 return ((path.length() > 4 && path.find (".mid") != (path.length() - 4)) ||
2501 (path.length() > 4 && path.find (".smf") != (path.length() - 4)) ||
2502 (path.length() > 5 && path.find (".midi") != (path.length() - 5)));
2506 accept_all_state_files (const string& path, void */*arg*/)
2508 if (!Glib::file_test (path, Glib::FILE_TEST_IS_REGULAR)) {
2512 return (path.length() > 7 && path.find (".ardour") == (path.length() - 7));
2516 Session::find_all_sources (string path, set<string>& result)
2521 if (!tree.read (path)) {
2525 if ((node = find_named_node (*tree.root(), "Sources")) == 0) {
2530 XMLNodeConstIterator niter;
2532 nlist = node->children();
2536 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2540 if ((prop = (*niter)->property (X_("type"))) == 0) {
2544 DataType type (prop->value());
2546 if ((prop = (*niter)->property (X_("name"))) == 0) {
2550 if (Glib::path_is_absolute (prop->value())) {
2551 /* external file, ignore */
2559 if (FileSource::find (*this, type, prop->value(), true, is_new, chan, found_path)) {
2560 result.insert (found_path);
2568 Session::find_all_sources_across_snapshots (set<string>& result, bool exclude_this_snapshot)
2570 PathScanner scanner;
2571 vector<string*>* state_files;
2573 string this_snapshot_path;
2579 if (ripped[ripped.length()-1] == G_DIR_SEPARATOR) {
2580 ripped = ripped.substr (0, ripped.length() - 1);
2583 state_files = scanner (ripped, accept_all_state_files, (void *) 0, true, true);
2585 if (state_files == 0) {
2590 this_snapshot_path = _path;
2591 this_snapshot_path += legalize_for_path (_current_snapshot_name);
2592 this_snapshot_path += statefile_suffix;
2594 for (vector<string*>::iterator i = state_files->begin(); i != state_files->end(); ++i) {
2596 if (exclude_this_snapshot && **i == this_snapshot_path) {
2600 if (find_all_sources (**i, result) < 0) {
2608 struct RegionCounter {
2609 typedef std::map<PBD::ID,boost::shared_ptr<AudioSource> > AudioSourceList;
2610 AudioSourceList::iterator iter;
2611 boost::shared_ptr<Region> region;
2614 RegionCounter() : count (0) {}
2618 Session::ask_about_playlist_deletion (boost::shared_ptr<Playlist> p)
2620 boost::optional<int> r = AskAboutPlaylistDeletion (p);
2621 return r.get_value_or (1);
2625 Session::cleanup_regions ()
2627 const RegionFactory::RegionMap& regions (RegionFactory::regions());
2629 for (RegionFactory::RegionMap::const_iterator i = regions.begin(); i != regions.end(); ++i) {
2631 uint32_t used = playlists->region_use_count (i->second);
2633 if (used == 0 && !i->second->automatic ()) {
2634 RegionFactory::map_remove (i->second);
2638 /* dump the history list */
2645 Session::cleanup_sources (CleanupReport& rep)
2647 // FIXME: needs adaptation to midi
2649 vector<boost::shared_ptr<Source> > dead_sources;
2650 PathScanner scanner;
2653 vector<space_and_path>::iterator i;
2654 vector<space_and_path>::iterator nexti;
2655 vector<string*>* candidates;
2656 vector<string*>* candidates2;
2657 vector<string> unused;
2658 set<string> all_sources;
2665 _state_of_the_state = (StateOfTheState) (_state_of_the_state | InCleanup);
2667 /* consider deleting all unused playlists */
2669 if (playlists->maybe_delete_unused (boost::bind (Session::ask_about_playlist_deletion, _1))) {
2674 /* sync the "all regions" property of each playlist with its current state
2677 playlists->sync_all_regions_with_regions ();
2679 /* find all un-used sources */
2684 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ) {
2686 SourceMap::iterator tmp;
2691 /* do not bother with files that are zero size, otherwise we remove the current "nascent"
2695 if (!i->second->used() && (i->second->length(i->second->timeline_position() > 0))) {
2696 dead_sources.push_back (i->second);
2697 i->second->drop_references ();
2703 /* build a list of all the possible audio directories for the session */
2705 for (i = session_dirs.begin(); i != session_dirs.end(); ) {
2710 SessionDirectory sdir ((*i).path);
2711 audio_path += sdir.sound_path();
2713 if (nexti != session_dirs.end()) {
2721 /* build a list of all the possible midi directories for the session */
2723 for (i = session_dirs.begin(); i != session_dirs.end(); ) {
2728 SessionDirectory sdir ((*i).path);
2729 midi_path += sdir.midi_path();
2731 if (nexti != session_dirs.end()) {
2738 candidates = scanner (audio_path, accept_all_audio_files, (void *) 0, true, true);
2739 candidates2 = scanner (midi_path, accept_all_midi_files, (void *) 0, true, true);
2745 for (vector<string*>::iterator i = candidates2->begin(); i != candidates2->end(); ++i) {
2746 candidates->push_back (*i);
2751 candidates = candidates2; // might still be null
2754 /* find all sources, but don't use this snapshot because the
2755 state file on disk still references sources we may have already
2759 find_all_sources_across_snapshots (all_sources, true);
2761 /* add our current source list
2764 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ) {
2765 boost::shared_ptr<FileSource> fs;
2766 SourceMap::iterator tmp = i;
2769 if ((fs = boost::dynamic_pointer_cast<FileSource> (i->second)) != 0) {
2770 if (playlists->source_use_count (fs) != 0) {
2771 all_sources.insert (fs->path());
2774 /* we might not remove this source from disk, because it may be used
2775 by other snapshots, but its not being used in this version
2776 so lets get rid of it now, along with any representative regions
2780 RegionFactory::remove_regions_using_source (i->second);
2789 for (vector<string*>::iterator x = candidates->begin(); x != candidates->end(); ++x) {
2794 for (set<string>::iterator i = all_sources.begin(); i != all_sources.end(); ++i) {
2796 tmppath1 = canonical_path (spath);
2797 tmppath2 = canonical_path ((*i));
2799 if (tmppath1 == tmppath2) {
2806 unused.push_back (spath);
2815 /* now try to move all unused files into the "dead" directory(ies) */
2817 for (vector<string>::iterator x = unused.begin(); x != unused.end(); ++x) {
2818 struct stat statbuf;
2822 /* don't move the file across filesystems, just
2823 stick it in the `dead_dir_name' directory
2824 on whichever filesystem it was already on.
2827 if ((*x).find ("/sounds/") != string::npos) {
2829 /* old school, go up 1 level */
2831 newpath = Glib::path_get_dirname (*x); // "sounds"
2832 newpath = Glib::path_get_dirname (newpath); // "session-name"
2836 /* new school, go up 4 levels */
2838 newpath = Glib::path_get_dirname (*x); // "audiofiles" or "midifiles"
2839 newpath = Glib::path_get_dirname (newpath); // "session-name"
2840 newpath = Glib::path_get_dirname (newpath); // "interchange"
2841 newpath = Glib::path_get_dirname (newpath); // "session-dir"
2844 newpath = Glib::build_filename (newpath, dead_dir_name);
2846 if (g_mkdir_with_parents (newpath.c_str(), 0755) < 0) {
2847 error << string_compose(_("Session: cannot create dead file folder \"%1\" (%2)"), newpath, strerror (errno)) << endmsg;
2851 newpath = Glib::build_filename (newpath, Glib::path_get_basename ((*x)));
2853 if (Glib::file_test (newpath, Glib::FILE_TEST_EXISTS)) {
2855 /* the new path already exists, try versioning */
2857 char buf[PATH_MAX+1];
2861 snprintf (buf, sizeof (buf), "%s.%d", newpath.c_str(), version);
2864 while (Glib::file_test (newpath_v.c_str(), Glib::FILE_TEST_EXISTS) && version < 999) {
2865 snprintf (buf, sizeof (buf), "%s.%d", newpath.c_str(), ++version);
2869 if (version == 999) {
2870 error << string_compose (_("there are already 1000 files with names like %1; versioning discontinued"),
2874 newpath = newpath_v;
2879 /* it doesn't exist, or we can't read it or something */
2883 stat ((*x).c_str(), &statbuf);
2885 if (::rename ((*x).c_str(), newpath.c_str()) != 0) {
2886 error << string_compose (_("cannot rename unused file source from %1 to %2 (%3)"),
2887 (*x), newpath, strerror (errno))
2892 /* see if there an easy to find peakfile for this file, and remove it.
2895 string base = basename_nosuffix (*x);
2896 base += "%A"; /* this is what we add for the channel suffix of all native files,
2897 or for the first channel of embedded files. it will miss
2898 some peakfiles for other channels
2900 string peakpath = peak_path (base);
2902 if (Glib::file_test (peakpath.c_str(), Glib::FILE_TEST_EXISTS)) {
2903 if (::g_unlink (peakpath.c_str()) != 0) {
2904 error << string_compose (_("cannot remove peakfile %1 for %2 (%3)"),
2905 peakpath, _path, strerror (errno))
2907 /* try to back out */
2908 ::rename (newpath.c_str(), _path.c_str());
2913 rep.paths.push_back (*x);
2914 rep.space += statbuf.st_size;
2917 /* dump the history list */
2921 /* save state so we don't end up a session file
2922 referring to non-existent sources.
2929 _state_of_the_state = (StateOfTheState) (_state_of_the_state & ~InCleanup);
2935 Session::cleanup_trash_sources (CleanupReport& rep)
2937 // FIXME: needs adaptation for MIDI
2939 vector<space_and_path>::iterator i;
2945 for (i = session_dirs.begin(); i != session_dirs.end(); ++i) {
2947 dead_dir = Glib::build_filename ((*i).path, dead_dir_name);
2949 clear_directory (dead_dir, &rep.space, &rep.paths);
2956 Session::set_dirty ()
2958 bool was_dirty = dirty();
2960 _state_of_the_state = StateOfTheState (_state_of_the_state | Dirty);
2964 DirtyChanged(); /* EMIT SIGNAL */
2970 Session::set_clean ()
2972 bool was_dirty = dirty();
2974 _state_of_the_state = Clean;
2978 DirtyChanged(); /* EMIT SIGNAL */
2983 Session::set_deletion_in_progress ()
2985 _state_of_the_state = StateOfTheState (_state_of_the_state | Deletion);
2989 Session::clear_deletion_in_progress ()
2991 _state_of_the_state = StateOfTheState (_state_of_the_state & (~Deletion));
2995 Session::add_controllable (boost::shared_ptr<Controllable> c)
2997 /* this adds a controllable to the list managed by the Session.
2998 this is a subset of those managed by the Controllable class
2999 itself, and represents the only ones whose state will be saved
3000 as part of the session.
3003 Glib::Threads::Mutex::Lock lm (controllables_lock);
3004 controllables.insert (c);
3007 struct null_deleter { void operator()(void const *) const {} };
3010 Session::remove_controllable (Controllable* c)
3012 if (_state_of_the_state & Deletion) {
3016 Glib::Threads::Mutex::Lock lm (controllables_lock);
3018 Controllables::iterator x = controllables.find (boost::shared_ptr<Controllable>(c, null_deleter()));
3020 if (x != controllables.end()) {
3021 controllables.erase (x);
3025 boost::shared_ptr<Controllable>
3026 Session::controllable_by_id (const PBD::ID& id)
3028 Glib::Threads::Mutex::Lock lm (controllables_lock);
3030 for (Controllables::iterator i = controllables.begin(); i != controllables.end(); ++i) {
3031 if ((*i)->id() == id) {
3036 return boost::shared_ptr<Controllable>();
3039 boost::shared_ptr<Controllable>
3040 Session::controllable_by_descriptor (const ControllableDescriptor& desc)
3042 boost::shared_ptr<Controllable> c;
3043 boost::shared_ptr<Route> r;
3045 switch (desc.top_level_type()) {
3046 case ControllableDescriptor::NamedRoute:
3048 std::string str = desc.top_level_name();
3049 if (str == "master") {
3051 } else if (str == "control" || str == "listen") {
3054 r = route_by_name (desc.top_level_name());
3059 case ControllableDescriptor::RemoteControlID:
3060 r = route_by_remote_id (desc.rid());
3068 switch (desc.subtype()) {
3069 case ControllableDescriptor::Gain:
3070 c = r->gain_control ();
3073 case ControllableDescriptor::Solo:
3074 c = r->solo_control();
3077 case ControllableDescriptor::Mute:
3078 c = r->mute_control();
3081 case ControllableDescriptor::Recenable:
3083 boost::shared_ptr<Track> t = boost::dynamic_pointer_cast<Track>(r);
3086 c = t->rec_enable_control ();
3091 case ControllableDescriptor::PanDirection:
3093 c = r->pannable()->pan_azimuth_control;
3097 case ControllableDescriptor::PanWidth:
3099 c = r->pannable()->pan_width_control;
3103 case ControllableDescriptor::PanElevation:
3105 c = r->pannable()->pan_elevation_control;
3109 case ControllableDescriptor::Balance:
3110 /* XXX simple pan control */
3113 case ControllableDescriptor::PluginParameter:
3115 uint32_t plugin = desc.target (0);
3116 uint32_t parameter_index = desc.target (1);
3118 /* revert to zero based counting */
3124 if (parameter_index > 0) {
3128 boost::shared_ptr<Processor> p = r->nth_plugin (plugin);
3131 c = boost::dynamic_pointer_cast<ARDOUR::AutomationControl>(
3132 p->control(Evoral::Parameter(PluginAutomation, 0, parameter_index)));
3137 case ControllableDescriptor::SendGain:
3139 uint32_t send = desc.target (0);
3141 /* revert to zero-based counting */
3147 boost::shared_ptr<Processor> p = r->nth_send (send);
3150 boost::shared_ptr<Send> s = boost::dynamic_pointer_cast<Send>(p);
3151 boost::shared_ptr<Amp> a = s->amp();
3154 c = s->amp()->gain_control();
3161 /* relax and return a null pointer */
3169 Session::add_instant_xml (XMLNode& node, bool write_to_config)
3172 Stateful::add_instant_xml (node, _path);
3175 if (write_to_config) {
3176 Config->add_instant_xml (node);
3181 Session::instant_xml (const string& node_name)
3183 return Stateful::instant_xml (node_name, _path);
3187 Session::save_history (string snapshot_name)
3195 if (snapshot_name.empty()) {
3196 snapshot_name = _current_snapshot_name;
3199 const string history_filename = legalize_for_path (snapshot_name) + history_suffix;
3200 const string backup_filename = history_filename + backup_suffix;
3201 const std::string xml_path(Glib::build_filename (_session_dir->root_path(), history_filename));
3202 const std::string backup_path(Glib::build_filename (_session_dir->root_path(), backup_filename));
3204 if (Glib::file_test (xml_path, Glib::FILE_TEST_EXISTS)) {
3205 if (::g_rename (xml_path.c_str(), backup_path.c_str()) != 0) {
3206 error << _("could not backup old history file, current history not saved") << endmsg;
3211 if (!Config->get_save_history() || Config->get_saved_history_depth() < 0) {
3215 tree.set_root (&_history.get_state (Config->get_saved_history_depth()));
3217 if (!tree.write (xml_path))
3219 error << string_compose (_("history could not be saved to %1"), xml_path) << endmsg;
3221 if (g_remove (xml_path.c_str()) != 0) {
3222 error << string_compose(_("Could not remove history file at path \"%1\" (%2)"),
3223 xml_path, g_strerror (errno)) << endmsg;
3225 if (::g_rename (backup_path.c_str(), xml_path.c_str()) != 0) {
3226 error << string_compose (_("could not restore history file from backup %1 (%2)"),
3227 backup_path, g_strerror (errno)) << endmsg;
3237 Session::restore_history (string snapshot_name)
3241 if (snapshot_name.empty()) {
3242 snapshot_name = _current_snapshot_name;
3245 const std::string xml_filename = legalize_for_path (snapshot_name) + history_suffix;
3246 const std::string xml_path(Glib::build_filename (_session_dir->root_path(), xml_filename));
3248 info << "Loading history from " << xml_path << endmsg;
3250 if (!Glib::file_test (xml_path, Glib::FILE_TEST_EXISTS)) {
3251 info << string_compose (_("%1: no history file \"%2\" for this session."),
3252 _name, xml_path) << endmsg;
3256 if (!tree.read (xml_path)) {
3257 error << string_compose (_("Could not understand session history file \"%1\""),
3258 xml_path) << endmsg;
3265 for (XMLNodeConstIterator it = tree.root()->children().begin(); it != tree.root()->children().end(); it++) {
3268 UndoTransaction* ut = new UndoTransaction ();
3271 ut->set_name(t->property("name")->value());
3272 stringstream ss(t->property("tv-sec")->value());
3274 ss.str(t->property("tv-usec")->value());
3276 ut->set_timestamp(tv);
3278 for (XMLNodeConstIterator child_it = t->children().begin();
3279 child_it != t->children().end(); child_it++)
3281 XMLNode *n = *child_it;
3284 if (n->name() == "MementoCommand" ||
3285 n->name() == "MementoUndoCommand" ||
3286 n->name() == "MementoRedoCommand") {
3288 if ((c = memento_command_factory(n))) {
3292 } else if (n->name() == "NoteDiffCommand") {
3293 PBD::ID id (n->property("midi-source")->value());
3294 boost::shared_ptr<MidiSource> midi_source =
3295 boost::dynamic_pointer_cast<MidiSource, Source>(source_by_id(id));
3297 ut->add_command (new MidiModel::NoteDiffCommand(midi_source->model(), *n));
3299 error << _("Failed to downcast MidiSource for NoteDiffCommand") << endmsg;
3302 } else if (n->name() == "SysExDiffCommand") {
3304 PBD::ID id (n->property("midi-source")->value());
3305 boost::shared_ptr<MidiSource> midi_source =
3306 boost::dynamic_pointer_cast<MidiSource, Source>(source_by_id(id));
3308 ut->add_command (new MidiModel::SysExDiffCommand (midi_source->model(), *n));
3310 error << _("Failed to downcast MidiSource for SysExDiffCommand") << endmsg;
3313 } else if (n->name() == "PatchChangeDiffCommand") {
3315 PBD::ID id (n->property("midi-source")->value());
3316 boost::shared_ptr<MidiSource> midi_source =
3317 boost::dynamic_pointer_cast<MidiSource, Source>(source_by_id(id));
3319 ut->add_command (new MidiModel::PatchChangeDiffCommand (midi_source->model(), *n));
3321 error << _("Failed to downcast MidiSource for PatchChangeDiffCommand") << endmsg;
3324 } else if (n->name() == "StatefulDiffCommand") {
3325 if ((c = stateful_diff_command_factory (n))) {
3326 ut->add_command (c);
3329 error << string_compose(_("Couldn't figure out how to make a Command out of a %1 XMLNode."), n->name()) << endmsg;
3340 Session::config_changed (std::string p, bool ours)
3346 if (p == "seamless-loop") {
3348 } else if (p == "rf-speed") {
3350 } else if (p == "auto-loop") {
3352 } else if (p == "auto-input") {
3354 if (Config->get_monitoring_model() == HardwareMonitoring && transport_rolling()) {
3355 /* auto-input only makes a difference if we're rolling */
3356 set_track_monitor_input_status (!config.get_auto_input());
3359 } else if (p == "punch-in") {
3363 if ((location = _locations->auto_punch_location()) != 0) {
3365 if (config.get_punch_in ()) {
3366 replace_event (SessionEvent::PunchIn, location->start());
3368 remove_event (location->start(), SessionEvent::PunchIn);
3372 } else if (p == "punch-out") {
3376 if ((location = _locations->auto_punch_location()) != 0) {
3378 if (config.get_punch_out()) {
3379 replace_event (SessionEvent::PunchOut, location->end());
3381 clear_events (SessionEvent::PunchOut);
3385 } else if (p == "edit-mode") {
3387 Glib::Threads::Mutex::Lock lm (playlists->lock);
3389 for (SessionPlaylists::List::iterator i = playlists->playlists.begin(); i != playlists->playlists.end(); ++i) {
3390 (*i)->set_edit_mode (Config->get_edit_mode ());
3393 } else if (p == "use-video-sync") {
3395 waiting_for_sync_offset = config.get_use_video_sync();
3397 } else if (p == "mmc-control") {
3399 //poke_midi_thread ();
3401 } else if (p == "mmc-device-id" || p == "mmc-receive-id" || p == "mmc-receive-device-id") {
3403 MIDI::Manager::instance()->mmc()->set_receive_device_id (Config->get_mmc_receive_device_id());
3405 } else if (p == "mmc-send-id" || p == "mmc-send-device-id") {
3407 MIDI::Manager::instance()->mmc()->set_send_device_id (Config->get_mmc_send_device_id());
3409 } else if (p == "midi-control") {
3411 //poke_midi_thread ();
3413 } else if (p == "raid-path") {
3415 setup_raid_path (config.get_raid_path());
3417 } else if (p == "timecode-format") {
3421 } else if (p == "video-pullup") {
3425 } else if (p == "seamless-loop") {
3427 if (play_loop && transport_rolling()) {
3428 // to reset diskstreams etc
3429 request_play_loop (true);
3432 } else if (p == "rf-speed") {
3434 cumulative_rf_motion = 0;
3437 } else if (p == "click-sound") {
3439 setup_click_sounds (1);
3441 } else if (p == "click-emphasis-sound") {
3443 setup_click_sounds (-1);
3445 } else if (p == "clicking") {
3447 if (Config->get_clicking()) {
3448 if (_click_io && click_data) { // don't require emphasis data
3455 } else if (p == "click-gain") {
3458 _click_gain->set_gain (Config->get_click_gain(), this);
3461 } else if (p == "send-mtc") {
3463 if (Config->get_send_mtc ()) {
3464 /* mark us ready to send */
3465 next_quarter_frame_to_send = 0;
3468 } else if (p == "send-mmc") {
3470 MIDI::Manager::instance()->mmc()->enable_send (Config->get_send_mmc ());
3472 } else if (p == "midi-feedback") {
3474 session_midi_feedback = Config->get_midi_feedback();
3476 } else if (p == "jack-time-master") {
3478 engine().reset_timebase ();
3480 } else if (p == "native-file-header-format") {
3482 if (!first_file_header_format_reset) {
3483 reset_native_file_format ();
3486 first_file_header_format_reset = false;
3488 } else if (p == "native-file-data-format") {
3490 if (!first_file_data_format_reset) {
3491 reset_native_file_format ();
3494 first_file_data_format_reset = false;
3496 } else if (p == "external-sync") {
3497 if (!config.get_external_sync()) {
3498 drop_sync_source ();
3500 switch_to_sync_source (Config->get_sync_source());
3502 } else if (p == "denormal-model") {
3504 } else if (p == "history-depth") {
3505 set_history_depth (Config->get_history_depth());
3506 } else if (p == "remote-model") {
3507 /* XXX DO SOMETHING HERE TO TELL THE GUI THAT WE NEED
3510 } else if (p == "sync-all-route-ordering") {
3512 /* sync to editor order unless mixer is used for remote IDs
3515 switch (Config->get_remote_model()) {
3517 sync_order_keys (EditorSort);
3520 sync_order_keys (EditorSort);
3523 sync_order_keys (MixerSort);
3526 } else if (p == "initial-program-change") {
3528 if (MIDI::Manager::instance()->mmc()->output_port() && Config->get_initial_program_change() >= 0) {
3531 buf[0] = MIDI::program; // channel zero by default
3532 buf[1] = (Config->get_initial_program_change() & 0x7f);
3534 MIDI::Manager::instance()->mmc()->output_port()->midimsg (buf, sizeof (buf), 0);
3536 } else if (p == "solo-mute-override") {
3537 // catch_up_on_solo_mute_override ();
3538 } else if (p == "listen-position" || p == "pfl-position") {
3539 listen_position_changed ();
3540 } else if (p == "solo-control-is-listen-control") {
3541 solo_control_mode_changed ();
3542 } else if (p == "timecode-offset" || p == "timecode-offset-negative") {
3543 last_timecode_valid = false;
3544 } else if (p == "playback-buffer-seconds") {
3545 AudioSource::allocate_working_buffers (frame_rate());
3546 } else if (p == "automation-thinning-factor") {
3547 Evoral::ControlList::set_thinning_factor (Config->get_automation_thinning_factor());
3548 } else if (p == "ltc-source-port") {
3549 reconnect_ltc_input ();
3550 } else if (p == "ltc-sink-port") {
3551 reconnect_ltc_output ();
3552 } else if (p == "timecode-generator-offset") {
3553 ltc_tx_parse_offset();
3560 Session::set_history_depth (uint32_t d)
3562 _history.set_depth (d);
3566 Session::load_diskstreams_2X (XMLNode const & node, int)
3569 XMLNodeConstIterator citer;
3571 clist = node.children();
3573 for (citer = clist.begin(); citer != clist.end(); ++citer) {
3576 /* diskstreams added automatically by DiskstreamCreated handler */
3577 if ((*citer)->name() == "AudioDiskstream" || (*citer)->name() == "DiskStream") {
3578 boost::shared_ptr<AudioDiskstream> dsp (new AudioDiskstream (*this, **citer));
3579 _diskstreams_2X.push_back (dsp);
3581 error << _("Session: unknown diskstream type in XML") << endmsg;
3585 catch (failed_constructor& err) {
3586 error << _("Session: could not load diskstream via XML state") << endmsg;
3594 /** Connect things to the MMC object */
3596 Session::setup_midi_machine_control ()
3598 MIDI::MachineControl* mmc = MIDI::Manager::instance()->mmc ();
3600 mmc->Play.connect_same_thread (*this, boost::bind (&Session::mmc_deferred_play, this, _1));
3601 mmc->DeferredPlay.connect_same_thread (*this, boost::bind (&Session::mmc_deferred_play, this, _1));
3602 mmc->Stop.connect_same_thread (*this, boost::bind (&Session::mmc_stop, this, _1));
3603 mmc->FastForward.connect_same_thread (*this, boost::bind (&Session::mmc_fast_forward, this, _1));
3604 mmc->Rewind.connect_same_thread (*this, boost::bind (&Session::mmc_rewind, this, _1));
3605 mmc->Pause.connect_same_thread (*this, boost::bind (&Session::mmc_pause, this, _1));
3606 mmc->RecordPause.connect_same_thread (*this, boost::bind (&Session::mmc_record_pause, this, _1));
3607 mmc->RecordStrobe.connect_same_thread (*this, boost::bind (&Session::mmc_record_strobe, this, _1));
3608 mmc->RecordExit.connect_same_thread (*this, boost::bind (&Session::mmc_record_exit, this, _1));
3609 mmc->Locate.connect_same_thread (*this, boost::bind (&Session::mmc_locate, this, _1, _2));
3610 mmc->Step.connect_same_thread (*this, boost::bind (&Session::mmc_step, this, _1, _2));
3611 mmc->Shuttle.connect_same_thread (*this, boost::bind (&Session::mmc_shuttle, this, _1, _2, _3));
3612 mmc->TrackRecordStatusChange.connect_same_thread (*this, boost::bind (&Session::mmc_record_enable, this, _1, _2, _3));
3614 /* also handle MIDI SPP because its so common */
3616 mmc->SPPStart.connect_same_thread (*this, boost::bind (&Session::spp_start, this));
3617 mmc->SPPContinue.connect_same_thread (*this, boost::bind (&Session::spp_continue, this));
3618 mmc->SPPStop.connect_same_thread (*this, boost::bind (&Session::spp_stop, this));
3621 boost::shared_ptr<Controllable>
3622 Session::solo_cut_control() const
3624 /* the solo cut control is a bit of an anomaly, at least as of Febrary 2011. There are no other
3625 controls in Ardour that currently get presented to the user in the GUI that require
3626 access as a Controllable and are also NOT owned by some SessionObject (e.g. Route, or MonitorProcessor).
3628 its actually an RCConfiguration parameter, so we use a ProxyControllable to wrap
3629 it up as a Controllable. Changes to the Controllable will just map back to the RCConfiguration
3633 return _solo_cut_control;
3637 Session::rename (const std::string& new_name)
3639 string legal_name = legalize_for_path (new_name);
3645 string const old_sources_root = _session_dir->sources_root();
3647 #define RENAME ::rename
3652 * interchange subdirectory
3656 * Backup files are left unchanged and not renamed.
3659 /* pass one: not 100% safe check that the new directory names don't
3663 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
3668 /* this is a stupid hack because Glib::path_get_dirname() is
3669 * lexical-only, and so passing it /a/b/c/ gives a different
3670 * result than passing it /a/b/c ...
3673 if (oldstr[oldstr.length()-1] == G_DIR_SEPARATOR) {
3674 oldstr = oldstr.substr (0, oldstr.length() - 1);
3677 string base = Glib::path_get_dirname (oldstr);
3678 string p = Glib::path_get_basename (oldstr);
3680 newstr = Glib::build_filename (base, legal_name);
3682 if (Glib::file_test (newstr, Glib::FILE_TEST_EXISTS)) {
3689 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
3694 /* this is a stupid hack because Glib::path_get_dirname() is
3695 * lexical-only, and so passing it /a/b/c/ gives a different
3696 * result than passing it /a/b/c ...
3699 if (oldstr[oldstr.length()-1] == G_DIR_SEPARATOR) {
3700 oldstr = oldstr.substr (0, oldstr.length() - 1);
3703 string base = Glib::path_get_dirname (oldstr);
3704 string p = Glib::path_get_basename (oldstr);
3706 newstr = Glib::build_filename (base, legal_name);
3708 cerr << "Rename " << oldstr << " => " << newstr << endl;
3710 if (RENAME (oldstr.c_str(), newstr.c_str()) != 0) {
3715 (*_session_dir) = newstr;
3720 /* directory below interchange */
3722 v.push_back (newstr);
3723 v.push_back (interchange_dir_name);
3726 oldstr = Glib::build_filename (v);
3729 v.push_back (newstr);
3730 v.push_back (interchange_dir_name);
3731 v.push_back (legal_name);
3733 newstr = Glib::build_filename (v);
3735 cerr << "Rename " << oldstr << " => " << newstr << endl;
3737 if (RENAME (oldstr.c_str(), newstr.c_str()) != 0) {
3744 oldstr = Glib::build_filename (newpath, _current_snapshot_name) + statefile_suffix;
3745 newstr= Glib::build_filename (newpath, legal_name) + statefile_suffix;
3747 cerr << "Rename " << oldstr << " => " << newstr << endl;
3749 if (RENAME (oldstr.c_str(), newstr.c_str()) != 0) {
3756 oldstr = Glib::build_filename (newpath, _current_snapshot_name) + history_suffix;
3758 if (Glib::file_test (oldstr, Glib::FILE_TEST_EXISTS)) {
3759 newstr = Glib::build_filename (newpath, legal_name) + history_suffix;
3761 cerr << "Rename " << oldstr << " => " << newstr << endl;
3763 if (RENAME (oldstr.c_str(), newstr.c_str()) != 0) {
3768 /* update file source paths */
3770 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ++i) {
3771 boost::shared_ptr<FileSource> fs = boost::dynamic_pointer_cast<FileSource> (i->second);
3773 string p = fs->path ();
3774 boost::replace_all (p, old_sources_root, _session_dir->sources_root());
3779 /* remove old name from recent sessions */
3781 remove_recent_sessions (_path);
3784 _current_snapshot_name = new_name;
3789 /* save state again to get everything just right */
3791 save_state (_current_snapshot_name);
3794 /* add to recent sessions */
3796 store_recent_sessions (new_name, _path);