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 */
45 #include <sys/param.h>
46 #include <sys/mount.h>
49 #ifdef HAVE_SYS_STATVFS_H
50 #include <sys/statvfs.h>
54 #include <glib/gstdio.h>
57 #include <glibmm/thread.h>
59 #include <boost/algorithm/string.hpp>
61 #include "midi++/mmc.h"
62 #include "midi++/port.h"
63 #include "midi++/manager.h"
65 #include "evoral/SMF.hpp"
67 #include "pbd/boost_debug.h"
68 #include "pbd/basename.h"
69 #include "pbd/controllable_descriptor.h"
70 #include "pbd/enumwriter.h"
71 #include "pbd/error.h"
72 #include "pbd/filesystem.h"
73 #include "pbd/file_utils.h"
74 #include "pbd/pathscanner.h"
75 #include "pbd/pthread_utils.h"
76 #include "pbd/search_path.h"
77 #include "pbd/stacktrace.h"
78 #include "pbd/convert.h"
79 #include "pbd/clear_dir.h"
81 #include "ardour/amp.h"
82 #include "ardour/audio_diskstream.h"
83 #include "ardour/audio_track.h"
84 #include "ardour/audioengine.h"
85 #include "ardour/audiofilesource.h"
86 #include "ardour/audioregion.h"
87 #include "ardour/automation_control.h"
88 #include "ardour/butler.h"
89 #include "ardour/control_protocol_manager.h"
90 #include "ardour/directory_names.h"
91 #include "ardour/filename_extensions.h"
92 #include "ardour/location.h"
93 #include "ardour/midi_model.h"
94 #include "ardour/midi_patch_manager.h"
95 #include "ardour/midi_region.h"
96 #include "ardour/midi_source.h"
97 #include "ardour/midi_track.h"
98 #include "ardour/named_selection.h"
99 #include "ardour/pannable.h"
100 #include "ardour/playlist_factory.h"
101 #include "ardour/port.h"
102 #include "ardour/processor.h"
103 #include "ardour/proxy_controllable.h"
104 #include "ardour/recent_sessions.h"
105 #include "ardour/region_factory.h"
106 #include "ardour/route_group.h"
107 #include "ardour/send.h"
108 #include "ardour/session.h"
109 #include "ardour/session_directory.h"
110 #include "ardour/session_metadata.h"
111 #include "ardour/session_playlists.h"
112 #include "ardour/session_state_utils.h"
113 #include "ardour/session_utils.h"
114 #include "ardour/silentfilesource.h"
115 #include "ardour/sndfilesource.h"
116 #include "ardour/source_factory.h"
117 #include "ardour/speakers.h"
118 #include "ardour/template_utils.h"
119 #include "ardour/tempo.h"
120 #include "ardour/ticker.h"
121 #include "ardour/user_bundle.h"
123 #include "control_protocol/control_protocol.h"
129 using namespace ARDOUR;
132 /** @param snapshot_name Snapshot name, without the .ardour prefix */
134 Session::first_stage_init (string fullpath, string snapshot_name)
136 if (fullpath.length() == 0) {
138 throw failed_constructor();
141 char buf[PATH_MAX+1];
142 if (!realpath (fullpath.c_str(), buf) && (errno != ENOENT)) {
143 error << string_compose(_("Could not use path %1 (%s)"), buf, strerror(errno)) << endmsg;
145 throw failed_constructor();
150 if (_path[_path.length()-1] != G_DIR_SEPARATOR) {
151 _path += G_DIR_SEPARATOR;
154 /* these two are just provisional settings. set_state()
155 will likely override them.
158 _name = _current_snapshot_name = snapshot_name;
160 set_history_depth (Config->get_history_depth());
162 _current_frame_rate = _engine.frame_rate ();
163 _nominal_frame_rate = _current_frame_rate;
164 _base_frame_rate = _current_frame_rate;
166 _tempo_map = new TempoMap (_current_frame_rate);
167 _tempo_map->PropertyChanged.connect_same_thread (*this, boost::bind (&Session::tempo_map_changed, this, _1));
170 _non_soloed_outs_muted = false;
172 _solo_isolated_cnt = 0;
173 g_atomic_int_set (&processing_prohibited, 0);
174 _transport_speed = 0;
175 _default_transport_speed = 1.0;
176 _last_transport_speed = 0;
177 _target_transport_speed = 0;
178 auto_play_legal = false;
179 transport_sub_state = 0;
180 _transport_frame = 0;
181 _requested_return_frame = -1;
182 _session_range_location = 0;
183 g_atomic_int_set (&_record_status, Disabled);
184 loop_changing = false;
187 _last_roll_location = 0;
188 _last_roll_or_reversal_location = 0;
189 _last_record_location = 0;
190 pending_locate_frame = 0;
191 pending_locate_roll = false;
192 pending_locate_flush = false;
193 state_was_pending = false;
195 outbound_mtc_timecode_frame = 0;
196 next_quarter_frame_to_send = -1;
197 current_block_size = 0;
198 solo_update_disabled = false;
199 _have_captured = false;
200 _worst_output_latency = 0;
201 _worst_input_latency = 0;
202 _worst_track_latency = 0;
203 _state_of_the_state = StateOfTheState(CannotSave|InitialConnecting|Loading);
204 _was_seamless = Config->get_seamless_loop ();
206 _send_qf_mtc = false;
207 _pframes_since_last_mtc = 0;
208 g_atomic_int_set (&_playback_load, 100);
209 g_atomic_int_set (&_capture_load, 100);
212 pending_abort = false;
213 destructive_index = 0;
214 first_file_data_format_reset = true;
215 first_file_header_format_reset = true;
216 post_export_sync = false;
219 no_questions_about_missing_files = false;
220 _speakers.reset (new Speakers);
222 ignore_route_processor_changes = false;
223 _pre_export_mmc_enabled = false;
225 AudioDiskstream::allocate_working_buffers();
227 /* default short fade = 15ms */
229 SndFileSource::setup_standard_crossfades (*this, frame_rate());
231 last_mmc_step.tv_sec = 0;
232 last_mmc_step.tv_usec = 0;
235 /* click sounds are unset by default, which causes us to internal
236 waveforms for clicks.
240 click_emphasis_length = 0;
243 process_function = &Session::process_with_events;
245 if (config.get_use_video_sync()) {
246 waiting_for_sync_offset = true;
248 waiting_for_sync_offset = false;
251 last_timecode_when = 0;
252 last_timecode_valid = false;
256 last_rr_session_dir = session_dirs.begin();
257 refresh_disk_space ();
259 /* default: assume simple stereo speaker configuration */
261 _speakers->setup_default_speakers (2);
265 average_slave_delta = 1800; // !!! why 1800 ????
266 have_first_delta_accumulator = false;
267 delta_accumulator_cnt = 0;
268 _slave_state = Stopped;
270 _solo_cut_control.reset (new ProxyControllable (_("solo cut control (dB)"), PBD::Controllable::GainLike,
271 boost::bind (&RCConfiguration::set_solo_mute_gain, Config, _1),
272 boost::bind (&RCConfiguration::get_solo_mute_gain, Config)));
273 add_controllable (_solo_cut_control);
275 _engine.GraphReordered.connect_same_thread (*this, boost::bind (&Session::graph_reordered, this));
277 /* These are all static "per-class" signals */
279 SourceFactory::SourceCreated.connect_same_thread (*this, boost::bind (&Session::add_source, this, _1));
280 PlaylistFactory::PlaylistCreated.connect_same_thread (*this, boost::bind (&Session::add_playlist, this, _1, _2));
281 AutomationList::AutomationListCreated.connect_same_thread (*this, boost::bind (&Session::add_automation_list, this, _1));
282 Controllable::Destroyed.connect_same_thread (*this, boost::bind (&Session::remove_controllable, this, _1));
283 IO::PortCountChanged.connect_same_thread (*this, boost::bind (&Session::ensure_buffers, this, _1));
285 /* stop IO objects from doing stuff until we're ready for them */
287 Delivery::disable_panners ();
288 IO::disable_connecting ();
292 Session::second_stage_init ()
294 AudioFileSource::set_peak_dir (_session_dir->peak_path());
297 if (load_state (_current_snapshot_name)) {
302 if (_butler->start_thread()) {
306 if (start_midi_thread ()) {
310 setup_midi_machine_control ();
312 // set_state() will call setup_raid_path(), but if it's a new session we need
313 // to call setup_raid_path() here.
316 if (set_state (*state_tree->root(), Stateful::loading_state_version)) {
320 setup_raid_path(_path);
323 /* we can't save till after ::when_engine_running() is called,
324 because otherwise we save state with no connections made.
325 therefore, we reset _state_of_the_state because ::set_state()
326 will have cleared it.
328 we also have to include Loading so that any events that get
329 generated between here and the end of ::when_engine_running()
330 will be processed directly rather than queued.
333 _state_of_the_state = StateOfTheState (_state_of_the_state|CannotSave|Loading);
335 _locations->changed.connect_same_thread (*this, boost::bind (&Session::locations_changed, this));
336 _locations->added.connect_same_thread (*this, boost::bind (&Session::locations_added, this, _1));
337 setup_click_sounds (0);
338 setup_midi_control ();
340 /* Pay attention ... */
342 _engine.Halted.connect_same_thread (*this, boost::bind (&Session::engine_halted, this));
343 _engine.Xrun.connect_same_thread (*this, boost::bind (&Session::xrun_recovery, this));
345 midi_clock = new MidiClockTicker ();
346 midi_clock->set_session (this);
349 when_engine_running ();
352 /* handle this one in a different way than all others, so that its clear what happened */
354 catch (AudioEngine::PortRegistrationFailure& err) {
355 error << err.what() << endmsg;
363 BootMessage (_("Reset Remote Controls"));
365 send_full_time_code (0);
366 _engine.transport_locate (0);
368 MIDI::Manager::instance()->mmc()->send (MIDI::MachineControlCommand (MIDI::MachineControl::cmdMmcReset));
369 MIDI::Manager::instance()->mmc()->send (MIDI::MachineControlCommand (Timecode::Time ()));
371 MIDI::Name::MidiPatchManager::instance().set_session (this);
373 /* initial program change will be delivered later; see ::config_changed() */
375 _state_of_the_state = Clean;
377 Port::set_connecting_blocked (false);
379 DirtyChanged (); /* EMIT SIGNAL */
381 if (state_was_pending) {
382 save_state (_current_snapshot_name);
383 remove_pending_capture_state ();
384 state_was_pending = false;
387 BootMessage (_("Session loading complete"));
393 Session::raid_path () const
395 SearchPath raid_search_path;
397 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
398 raid_search_path += (*i).path;
401 return raid_search_path.to_string ();
405 Session::setup_raid_path (string path)
414 session_dirs.clear ();
416 SearchPath search_path(path);
417 SearchPath sound_search_path;
418 SearchPath midi_search_path;
420 for (SearchPath::const_iterator i = search_path.begin(); i != search_path.end(); ++i) {
422 sp.blocks = 0; // not needed
423 session_dirs.push_back (sp);
425 SessionDirectory sdir(sp.path);
427 sound_search_path += sdir.sound_path ();
428 midi_search_path += sdir.midi_path ();
431 // reset the round-robin soundfile path thingie
432 last_rr_session_dir = session_dirs.begin();
436 Session::path_is_within_session (const std::string& path)
438 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
439 if (PBD::path_is_within (i->path, path)) {
447 Session::ensure_subdirs ()
451 dir = session_directory().peak_path();
453 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
454 error << string_compose(_("Session: cannot create session peakfile folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
458 dir = session_directory().sound_path();
460 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
461 error << string_compose(_("Session: cannot create session sounds dir \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
465 dir = session_directory().midi_path();
467 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
468 error << string_compose(_("Session: cannot create session midi dir \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
472 dir = session_directory().dead_path();
474 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
475 error << string_compose(_("Session: cannot create session dead sounds folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
479 dir = session_directory().export_path();
481 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
482 error << string_compose(_("Session: cannot create session export folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
486 dir = analysis_dir ();
488 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
489 error << string_compose(_("Session: cannot create session analysis folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
493 dir = plugins_dir ();
495 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
496 error << string_compose(_("Session: cannot create session plugins folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
500 dir = externals_dir ();
502 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
503 error << string_compose(_("Session: cannot create session externals folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
510 /** @param session_template directory containing session template, or empty.
511 * Caller must not hold process lock.
514 Session::create (const string& session_template, BusProfile* bus_profile)
516 if (g_mkdir_with_parents (_path.c_str(), 0755) < 0) {
517 error << string_compose(_("Session: cannot create session folder \"%1\" (%2)"), _path, strerror (errno)) << endmsg;
521 if (ensure_subdirs ()) {
525 _writable = exists_and_writable (_path);
527 if (!session_template.empty()) {
528 std::string in_path = session_template_dir_to_file (session_template);
530 ifstream in(in_path.c_str());
533 string out_path = _path;
535 out_path += statefile_suffix;
537 ofstream out(out_path.c_str());
543 /* Copy plugin state files from template to new session */
544 std::string template_plugins = Glib::build_filename (session_template, X_("plugins"));
545 copy_files (template_plugins, plugins_dir ());
550 error << string_compose (_("Could not open %1 for writing session template"), out_path)
556 error << string_compose (_("Could not open session template %1 for reading"), in_path)
563 /* set initial start + end point */
565 _state_of_the_state = Clean;
567 /* set up Master Out and Control Out if necessary */
572 ChanCount count(DataType::AUDIO, bus_profile->master_out_channels);
574 if (bus_profile->master_out_channels) {
575 boost::shared_ptr<Route> r (new Route (*this, _("master"), Route::MasterOut, DataType::AUDIO));
579 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
580 // boost_debug_shared_ptr_mark_interesting (r.get(), "Route");
583 Glib::Mutex::Lock lm (AudioEngine::instance()->process_lock ());
584 r->input()->ensure_io (count, false, this);
585 r->output()->ensure_io (count, false, this);
591 /* prohibit auto-connect to master, because there isn't one */
592 bus_profile->output_ac = AutoConnectOption (bus_profile->output_ac & ~AutoConnectMaster);
596 add_routes (rl, false, false, false);
599 /* this allows the user to override settings with an environment variable.
602 if (no_auto_connect()) {
603 bus_profile->input_ac = AutoConnectOption (0);
604 bus_profile->output_ac = AutoConnectOption (0);
607 Config->set_input_auto_connect (bus_profile->input_ac);
608 Config->set_output_auto_connect (bus_profile->output_ac);
611 if (Config->get_use_monitor_bus() && bus_profile) {
612 add_monitor_section ();
621 Session::maybe_write_autosave()
623 if (dirty() && record_status() != Recording) {
624 save_state("", true);
629 Session::remove_pending_capture_state ()
631 std::string pending_state_file_path(_session_dir->root_path());
633 pending_state_file_path = Glib::build_filename (pending_state_file_path, legalize_for_path (_current_snapshot_name) + pending_suffix);
635 if (!Glib::file_test (pending_state_file_path, Glib::FILE_TEST_EXISTS)) return;
637 if (g_remove (pending_state_file_path.c_str()) != 0) {
638 error << string_compose(_("Could not remove pending capture state at path \"%1\" (%2)"),
639 pending_state_file_path, g_strerror (errno)) << endmsg;
643 /** Rename a state file.
644 * @param old_name Old snapshot name.
645 * @param new_name New snapshot name.
648 Session::rename_state (string old_name, string new_name)
650 if (old_name == _current_snapshot_name || old_name == _name) {
651 /* refuse to rename the current snapshot or the "main" one */
655 const string old_xml_filename = legalize_for_path (old_name) + statefile_suffix;
656 const string new_xml_filename = legalize_for_path (new_name) + statefile_suffix;
658 const sys::path old_xml_path(Glib::build_filename (_session_dir->root_path(), old_xml_filename));
659 const sys::path new_xml_path(Glib::build_filename (_session_dir->root_path(), new_xml_filename));
663 sys::rename (old_xml_path, new_xml_path);
665 catch (const sys::filesystem_error& err)
667 error << string_compose(_("could not rename snapshot %1 to %2 (%3)"),
668 old_name, new_name, err.what()) << endmsg;
672 /** Remove a state file.
673 * @param snapshot_name Snapshot name.
676 Session::remove_state (string snapshot_name)
678 if (!_writable || snapshot_name == _current_snapshot_name || snapshot_name == _name) {
679 // refuse to remove the current snapshot or the "main" one
683 std::string xml_path(_session_dir->root_path());
685 xml_path = Glib::build_filename (xml_path, legalize_for_path (snapshot_name) + statefile_suffix);
687 if (!create_backup_file (xml_path)) {
688 // don't remove it if a backup can't be made
689 // create_backup_file will log the error.
694 if (g_remove (xml_path.c_str()) != 0) {
695 error << string_compose(_("Could not remove state file at path \"%1\" (%2)"),
696 xml_path, g_strerror (errno)) << endmsg;
700 #ifdef HAVE_JACK_SESSION
702 Session::jack_session_event (jack_session_event_t * event)
706 struct tm local_time;
709 localtime_r (&n, &local_time);
710 strftime (timebuf, sizeof(timebuf), "JS_%FT%T", &local_time);
712 if (event->type == JackSessionSaveTemplate)
714 if (save_template( timebuf )) {
715 event->flags = JackSessionSaveError;
717 string cmd ("ardour3 -P -U ");
718 cmd += event->client_uuid;
722 event->command_line = strdup (cmd.c_str());
727 if (save_state (timebuf)) {
728 event->flags = JackSessionSaveError;
730 sys::path xml_path (_session_dir->root_path());
731 xml_path /= legalize_for_path (timebuf) + statefile_suffix;
733 string cmd ("ardour3 -P -U ");
734 cmd += event->client_uuid;
736 cmd += xml_path.to_string();
739 event->command_line = strdup (cmd.c_str());
743 jack_session_reply (_engine.jack(), event);
745 if (event->type == JackSessionSaveAndQuit) {
746 Quit (); /* EMIT SIGNAL */
749 jack_session_event_free( event );
753 /** @param snapshot_name Name to save under, without .ardour / .pending prefix */
755 Session::save_state (string snapshot_name, bool pending, bool switch_to_snapshot)
758 std::string xml_path(_session_dir->root_path());
760 if (!_writable || (_state_of_the_state & CannotSave)) {
764 if (!_engine.connected ()) {
765 error << string_compose (_("the %1 audio engine is not connected and state saving would lose all I/O connections. Session not saved"),
771 /* tell sources we're saving first, in case they write out to a new file
772 * which should be saved with the state rather than the old one */
773 for (SourceMap::const_iterator i = sources.begin(); i != sources.end(); ++i) {
775 i->second->session_saved();
776 } catch (Evoral::SMF::FileError& e) {
777 error << string_compose ("Could not write to MIDI file %1; MIDI data not saved.", e.file_name ()) << endmsg;
781 tree.set_root (&get_state());
783 if (snapshot_name.empty()) {
784 snapshot_name = _current_snapshot_name;
785 } else if (switch_to_snapshot) {
786 _current_snapshot_name = snapshot_name;
791 /* proper save: use statefile_suffix (.ardour in English) */
793 xml_path = Glib::build_filename (xml_path, legalize_for_path (snapshot_name) + statefile_suffix);
795 /* make a backup copy of the old file */
797 if (sys::exists(xml_path) && !create_backup_file (xml_path)) {
798 // create_backup_file will log the error
804 /* pending save: use pending_suffix (.pending in English) */
805 xml_path = Glib::build_filename (xml_path, legalize_for_path (snapshot_name) + pending_suffix);
808 sys::path tmp_path(_session_dir->root_path());
810 tmp_path /= legalize_for_path (snapshot_name) + temp_suffix;
812 // cerr << "actually writing state to " << xml_path.to_string() << endl;
814 if (!tree.write (tmp_path.to_string())) {
815 error << string_compose (_("state could not be saved to %1"), tmp_path.to_string()) << endmsg;
816 if (g_remove (tmp_path.to_string().c_str()) != 0) {
817 error << string_compose(_("Could not remove temporary state file at path \"%1\" (%2)"),
818 tmp_path.to_string(), g_strerror (errno)) << endmsg;
824 if (::rename (tmp_path.to_string().c_str(), xml_path.c_str()) != 0) {
825 error << string_compose (_("could not rename temporary session file %1 to %2"),
826 tmp_path.to_string(), xml_path) << endmsg;
827 if (g_remove (tmp_path.to_string().c_str()) != 0) {
828 error << string_compose(_("Could not remove temporary state file at path \"%1\" (%2)"),
829 tmp_path.to_string(), g_strerror (errno)) << endmsg;
837 save_history (snapshot_name);
839 bool was_dirty = dirty();
841 _state_of_the_state = StateOfTheState (_state_of_the_state & ~Dirty);
844 DirtyChanged (); /* EMIT SIGNAL */
847 StateSaved (snapshot_name); /* EMIT SIGNAL */
854 Session::restore_state (string snapshot_name)
856 if (load_state (snapshot_name) == 0) {
857 set_state (*state_tree->root(), Stateful::loading_state_version);
864 Session::load_state (string snapshot_name)
869 state_was_pending = false;
871 /* check for leftover pending state from a crashed capture attempt */
873 sys::path xmlpath(_session_dir->root_path());
874 xmlpath /= legalize_for_path (snapshot_name) + pending_suffix;
876 if (sys::exists (xmlpath)) {
878 /* there is pending state from a crashed capture attempt */
880 boost::optional<int> r = AskAboutPendingState();
881 if (r.get_value_or (1)) {
882 state_was_pending = true;
886 if (!state_was_pending) {
887 xmlpath = _session_dir->root_path();
888 xmlpath /= snapshot_name;
891 if (!sys::exists (xmlpath)) {
892 xmlpath = _session_dir->root_path();
893 xmlpath /= legalize_for_path (snapshot_name) + statefile_suffix;
894 if (!sys::exists (xmlpath)) {
895 error << string_compose(_("%1: session state information file \"%2\" doesn't exist!"), _name, xmlpath.to_string()) << endmsg;
900 state_tree = new XMLTree;
904 _writable = exists_and_writable (xmlpath.to_string());
906 if (!state_tree->read (xmlpath.to_string())) {
907 error << string_compose(_("Could not understand ardour file %1"), xmlpath.to_string()) << endmsg;
913 XMLNode& root (*state_tree->root());
915 if (root.name() != X_("Session")) {
916 error << string_compose (_("Session file %1 is not a session"), xmlpath.to_string()) << endmsg;
922 const XMLProperty* prop;
924 if ((prop = root.property ("version")) == 0) {
925 /* no version implies very old version of Ardour */
926 Stateful::loading_state_version = 1000;
928 if (prop->value().find ('.') != string::npos) {
929 /* old school version format */
930 if (prop->value()[0] == '2') {
931 Stateful::loading_state_version = 2000;
933 Stateful::loading_state_version = 3000;
936 Stateful::loading_state_version = atoi (prop->value());
940 if (Stateful::loading_state_version < CURRENT_SESSION_FILE_VERSION && _writable) {
942 sys::path backup_path(_session_dir->root_path());
944 backup_path /= string_compose ("%1-%2%3", legalize_for_path (snapshot_name), Stateful::loading_state_version, statefile_suffix);
946 // only create a backup for a given statefile version once
948 if (!sys::exists (backup_path)) {
950 info << string_compose (_("Copying old session file %1 to %2\nUse %2 with %3 versions before 2.0 from now on"),
951 xmlpath.to_string(), backup_path.to_string(), PROGRAM_NAME)
954 if (!copy_file (xmlpath.to_string(), backup_path.to_string())) {;
964 Session::load_options (const XMLNode& node)
966 LocaleGuard lg (X_("POSIX"));
967 config.set_variables (node);
978 Session::get_template()
980 /* if we don't disable rec-enable, diskstreams
981 will believe they need to store their capture
982 sources in their state node.
985 disable_record (false);
991 Session::state (bool full_state)
993 XMLNode* node = new XMLNode("Session");
997 snprintf(buf, sizeof(buf), "%d", CURRENT_SESSION_FILE_VERSION);
998 node->add_property("version", buf);
1000 /* store configuration settings */
1004 node->add_property ("name", _name);
1005 snprintf (buf, sizeof (buf), "%" PRId64, _nominal_frame_rate);
1006 node->add_property ("sample-rate", buf);
1008 if (session_dirs.size() > 1) {
1012 vector<space_and_path>::iterator i = session_dirs.begin();
1013 vector<space_and_path>::iterator next;
1015 ++i; /* skip the first one */
1019 while (i != session_dirs.end()) {
1023 if (next != session_dirs.end()) {
1033 child = node->add_child ("Path");
1034 child->add_content (p);
1038 /* save the ID counter */
1040 snprintf (buf, sizeof (buf), "%" PRIu64, ID::counter());
1041 node->add_property ("id-counter", buf);
1043 /* save the event ID counter */
1045 snprintf (buf, sizeof (buf), "%d", Evoral::event_id_counter());
1046 node->add_property ("event-counter", buf);
1048 /* various options */
1050 node->add_child_nocopy (config.get_variables ());
1052 node->add_child_nocopy (ARDOUR::SessionMetadata::Metadata()->get_state());
1054 child = node->add_child ("Sources");
1057 Glib::Mutex::Lock sl (source_lock);
1059 for (SourceMap::iterator siter = sources.begin(); siter != sources.end(); ++siter) {
1061 /* Don't save information about non-file Sources, or
1062 * about non-destructive file sources that are empty
1063 * and unused by any regions.
1066 boost::shared_ptr<FileSource> fs;
1068 if ((fs = boost::dynamic_pointer_cast<FileSource> (siter->second)) != 0) {
1070 if (!fs->destructive()) {
1071 if (fs->empty() && !fs->used()) {
1076 child->add_child_nocopy (siter->second->get_state());
1081 child = node->add_child ("Regions");
1084 Glib::Mutex::Lock rl (region_lock);
1085 const RegionFactory::RegionMap& region_map (RegionFactory::all_regions());
1086 for (RegionFactory::RegionMap::const_iterator i = region_map.begin(); i != region_map.end(); ++i) {
1087 boost::shared_ptr<Region> r = i->second;
1088 /* only store regions not attached to playlists */
1089 if (r->playlist() == 0) {
1090 child->add_child_nocopy (r->state ());
1094 RegionFactory::CompoundAssociations& cassocs (RegionFactory::compound_associations());
1096 if (!cassocs.empty()) {
1097 XMLNode* ca = node->add_child (X_("CompoundAssociations"));
1099 for (RegionFactory::CompoundAssociations::iterator i = cassocs.begin(); i != cassocs.end(); ++i) {
1101 XMLNode* can = new XMLNode (X_("CompoundAssociation"));
1102 i->first->id().print (buf, sizeof (buf));
1103 can->add_property (X_("copy"), buf);
1104 i->second->id().print (buf, sizeof (buf));
1105 can->add_property (X_("original"), buf);
1106 ca->add_child_nocopy (*can);
1112 node->add_child_nocopy (_locations->get_state());
1114 // for a template, just create a new Locations, populate it
1115 // with the default start and end, and get the state for that.
1116 Locations loc (*this);
1117 Location* range = new Location (*this, 0, 0, _("session"), Location::IsSessionRange);
1118 range->set (max_framepos, 0);
1120 node->add_child_nocopy (loc.get_state());
1123 child = node->add_child ("Bundles");
1125 boost::shared_ptr<BundleList> bundles = _bundles.reader ();
1126 for (BundleList::iterator i = bundles->begin(); i != bundles->end(); ++i) {
1127 boost::shared_ptr<UserBundle> b = boost::dynamic_pointer_cast<UserBundle> (*i);
1129 child->add_child_nocopy (b->get_state());
1134 child = node->add_child ("Routes");
1136 boost::shared_ptr<RouteList> r = routes.reader ();
1138 RoutePublicOrderSorter cmp;
1139 RouteList public_order (*r);
1140 public_order.sort (cmp);
1142 /* the sort should have put control outs first */
1145 assert (_monitor_out == public_order.front());
1148 for (RouteList::iterator i = public_order.begin(); i != public_order.end(); ++i) {
1149 if (!(*i)->is_hidden()) {
1151 child->add_child_nocopy ((*i)->get_state());
1153 child->add_child_nocopy ((*i)->get_template());
1159 playlists->add_state (node, full_state);
1161 child = node->add_child ("RouteGroups");
1162 for (list<RouteGroup *>::iterator i = _route_groups.begin(); i != _route_groups.end(); ++i) {
1163 child->add_child_nocopy ((*i)->get_state());
1167 XMLNode* gain_child = node->add_child ("Click");
1168 gain_child->add_child_nocopy (_click_io->state (full_state));
1169 gain_child->add_child_nocopy (_click_gain->state (full_state));
1173 XMLNode* ns_child = node->add_child ("NamedSelections");
1174 for (NamedSelectionList::iterator i = named_selections.begin(); i != named_selections.end(); ++i) {
1176 ns_child->add_child_nocopy ((*i)->get_state());
1181 node->add_child_nocopy (_speakers->get_state());
1182 node->add_child_nocopy (_tempo_map->get_state());
1183 node->add_child_nocopy (get_control_protocol_state());
1186 node->add_child_copy (*_extra_xml);
1193 Session::get_control_protocol_state ()
1195 ControlProtocolManager& cpm (ControlProtocolManager::instance());
1196 return cpm.get_state();
1200 Session::set_state (const XMLNode& node, int version)
1204 const XMLProperty* prop;
1207 _state_of_the_state = StateOfTheState (_state_of_the_state|CannotSave);
1209 if (node.name() != X_("Session")) {
1210 fatal << _("programming error: Session: incorrect XML node sent to set_state()") << endmsg;
1214 if ((prop = node.property ("name")) != 0) {
1215 _name = prop->value ();
1218 if ((prop = node.property (X_("sample-rate"))) != 0) {
1220 _nominal_frame_rate = atoi (prop->value());
1222 if (_nominal_frame_rate != _current_frame_rate) {
1223 boost::optional<int> r = AskAboutSampleRateMismatch (_nominal_frame_rate, _current_frame_rate);
1224 if (r.get_value_or (0)) {
1230 setup_raid_path(_session_dir->root_path());
1232 if ((prop = node.property (X_("id-counter"))) != 0) {
1234 sscanf (prop->value().c_str(), "%" PRIu64, &x);
1235 ID::init_counter (x);
1237 /* old sessions used a timebased counter, so fake
1238 the startup ID counter based on a standard
1243 ID::init_counter (now);
1246 if ((prop = node.property (X_("event-counter"))) != 0) {
1247 Evoral::init_event_id_counter (atoi (prop->value()));
1250 IO::disable_connecting ();
1252 Stateful::save_extra_xml (node);
1254 if (((child = find_named_node (node, "Options")) != 0)) { /* old style */
1255 load_options (*child);
1256 } else if ((child = find_named_node (node, "Config")) != 0) { /* new style */
1257 load_options (*child);
1259 error << _("Session: XML state has no options section") << endmsg;
1262 if (version >= 3000) {
1263 if ((child = find_named_node (node, "Metadata")) == 0) {
1264 warning << _("Session: XML state has no metadata section") << endmsg;
1265 } else if ( ARDOUR::SessionMetadata::Metadata()->set_state (*child, version) ) {
1270 if ((child = find_named_node (node, X_("Speakers"))) != 0) {
1271 _speakers->set_state (*child, version);
1274 if ((child = find_named_node (node, "Sources")) == 0) {
1275 error << _("Session: XML state has no sources section") << endmsg;
1277 } else if (load_sources (*child)) {
1281 if ((child = find_named_node (node, "TempoMap")) == 0) {
1282 error << _("Session: XML state has no Tempo Map section") << endmsg;
1284 } else if (_tempo_map->set_state (*child, version)) {
1288 if ((child = find_named_node (node, "Locations")) == 0) {
1289 error << _("Session: XML state has no locations section") << endmsg;
1291 } else if (_locations->set_state (*child, version)) {
1297 if ((location = _locations->auto_loop_location()) != 0) {
1298 set_auto_loop_location (location);
1301 if ((location = _locations->auto_punch_location()) != 0) {
1302 set_auto_punch_location (location);
1305 if ((location = _locations->session_range_location()) != 0) {
1306 delete _session_range_location;
1307 _session_range_location = location;
1310 if (_session_range_location) {
1311 AudioFileSource::set_header_position_offset (_session_range_location->start());
1314 if ((child = find_named_node (node, "Regions")) == 0) {
1315 error << _("Session: XML state has no Regions section") << endmsg;
1317 } else if (load_regions (*child)) {
1321 if ((child = find_named_node (node, "Playlists")) == 0) {
1322 error << _("Session: XML state has no playlists section") << endmsg;
1324 } else if (playlists->load (*this, *child)) {
1328 if ((child = find_named_node (node, "UnusedPlaylists")) == 0) {
1330 } else if (playlists->load_unused (*this, *child)) {
1334 if ((child = find_named_node (node, "CompoundAssociations")) != 0) {
1335 if (load_compounds (*child)) {
1340 if ((child = find_named_node (node, "NamedSelections")) != 0) {
1341 if (load_named_selections (*child)) {
1346 if (version >= 3000) {
1347 if ((child = find_named_node (node, "Bundles")) == 0) {
1348 warning << _("Session: XML state has no bundles section") << endmsg;
1351 /* We can't load Bundles yet as they need to be able
1352 to convert from port names to Port objects, which can't happen until
1354 _bundle_xml_node = new XMLNode (*child);
1358 if (version < 3000) {
1359 if ((child = find_named_node (node, X_("DiskStreams"))) == 0) {
1360 error << _("Session: XML state has no diskstreams section") << endmsg;
1362 } else if (load_diskstreams_2X (*child, version)) {
1367 if ((child = find_named_node (node, "Routes")) == 0) {
1368 error << _("Session: XML state has no routes section") << endmsg;
1370 } else if (load_routes (*child, version)) {
1374 /* our diskstreams list is no longer needed as they are now all owned by their Route */
1375 _diskstreams_2X.clear ();
1377 if (version >= 3000) {
1379 if ((child = find_named_node (node, "RouteGroups")) == 0) {
1380 error << _("Session: XML state has no route groups section") << endmsg;
1382 } else if (load_route_groups (*child, version)) {
1386 } else if (version < 3000) {
1388 if ((child = find_named_node (node, "EditGroups")) == 0) {
1389 error << _("Session: XML state has no edit groups section") << endmsg;
1391 } else if (load_route_groups (*child, version)) {
1395 if ((child = find_named_node (node, "MixGroups")) == 0) {
1396 error << _("Session: XML state has no mix groups section") << endmsg;
1398 } else if (load_route_groups (*child, version)) {
1403 if ((child = find_named_node (node, "Click")) == 0) {
1404 warning << _("Session: XML state has no click section") << endmsg;
1405 } else if (_click_io) {
1406 const XMLNodeList& children (child->children());
1407 XMLNodeList::const_iterator i = children.begin();
1408 _click_io->set_state (**i, version);
1410 if (i != children.end()) {
1411 _click_gain->set_state (**i, version);
1415 if ((child = find_named_node (node, "ControlProtocols")) != 0) {
1416 ControlProtocolManager::instance().set_protocol_states (*child);
1419 update_have_rec_enabled_track ();
1421 /* here beginneth the second phase ... */
1423 StateReady (); /* EMIT SIGNAL */
1432 Session::load_routes (const XMLNode& node, int version)
1435 XMLNodeConstIterator niter;
1436 RouteList new_routes;
1438 nlist = node.children();
1442 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1444 boost::shared_ptr<Route> route;
1445 if (version < 3000) {
1446 route = XMLRouteFactory_2X (**niter, version);
1448 route = XMLRouteFactory (**niter, version);
1452 error << _("Session: cannot create Route from XML description.") << endmsg;
1456 BootMessage (string_compose (_("Loaded track/bus %1"), route->name()));
1458 new_routes.push_back (route);
1461 add_routes (new_routes, false, false, false);
1466 boost::shared_ptr<Route>
1467 Session::XMLRouteFactory (const XMLNode& node, int version)
1469 boost::shared_ptr<Route> ret;
1471 if (node.name() != "Route") {
1475 XMLNode* ds_child = find_named_node (node, X_("Diskstream"));
1477 DataType type = DataType::AUDIO;
1478 const XMLProperty* prop = node.property("default-type");
1481 type = DataType (prop->value());
1484 assert (type != DataType::NIL);
1488 boost::shared_ptr<Track> track;
1490 if (type == DataType::AUDIO) {
1491 track.reset (new AudioTrack (*this, X_("toBeResetFroXML")));
1493 track.reset (new MidiTrack (*this, X_("toBeResetFroXML")));
1496 if (track->init()) {
1500 if (track->set_state (node, version)) {
1504 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
1505 // boost_debug_shared_ptr_mark_interesting (track.get(), "Track");
1510 boost::shared_ptr<Route> r (new Route (*this, X_("toBeResetFroXML")));
1512 if (r->init () == 0 && r->set_state (node, version) == 0) {
1513 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
1514 // boost_debug_shared_ptr_mark_interesting (r.get(), "Route");
1523 boost::shared_ptr<Route>
1524 Session::XMLRouteFactory_2X (const XMLNode& node, int version)
1526 boost::shared_ptr<Route> ret;
1528 if (node.name() != "Route") {
1532 XMLProperty const * ds_prop = node.property (X_("diskstream-id"));
1534 ds_prop = node.property (X_("diskstream"));
1537 DataType type = DataType::AUDIO;
1538 const XMLProperty* prop = node.property("default-type");
1541 type = DataType (prop->value());
1544 assert (type != DataType::NIL);
1548 list<boost::shared_ptr<Diskstream> >::iterator i = _diskstreams_2X.begin ();
1549 while (i != _diskstreams_2X.end() && (*i)->id() != ds_prop->value()) {
1553 if (i == _diskstreams_2X.end()) {
1554 error << _("Could not find diskstream for route") << endmsg;
1555 return boost::shared_ptr<Route> ();
1558 boost::shared_ptr<Track> track;
1560 if (type == DataType::AUDIO) {
1561 track.reset (new AudioTrack (*this, X_("toBeResetFroXML")));
1563 track.reset (new MidiTrack (*this, X_("toBeResetFroXML")));
1566 if (track->init()) {
1570 if (track->set_state (node, version)) {
1574 track->set_diskstream (*i);
1576 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
1577 // boost_debug_shared_ptr_mark_interesting (track.get(), "Track");
1582 boost::shared_ptr<Route> r (new Route (*this, X_("toBeResetFroXML")));
1584 if (r->init () == 0 && r->set_state (node, version) == 0) {
1585 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
1586 // boost_debug_shared_ptr_mark_interesting (r.get(), "Route");
1596 Session::load_regions (const XMLNode& node)
1599 XMLNodeConstIterator niter;
1600 boost::shared_ptr<Region> region;
1602 nlist = node.children();
1606 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1607 if ((region = XMLRegionFactory (**niter, false)) == 0) {
1608 error << _("Session: cannot create Region from XML description.");
1609 const XMLProperty *name = (**niter).property("name");
1612 error << " " << string_compose (_("Can not load state for region '%1'"), name->value());
1623 Session::load_compounds (const XMLNode& node)
1625 XMLNodeList calist = node.children();
1626 XMLNodeConstIterator caiter;
1627 XMLProperty *caprop;
1629 for (caiter = calist.begin(); caiter != calist.end(); ++caiter) {
1630 XMLNode* ca = *caiter;
1634 if ((caprop = ca->property (X_("original"))) == 0) {
1637 orig_id = caprop->value();
1639 if ((caprop = ca->property (X_("copy"))) == 0) {
1642 copy_id = caprop->value();
1644 boost::shared_ptr<Region> orig = RegionFactory::region_by_id (orig_id);
1645 boost::shared_ptr<Region> copy = RegionFactory::region_by_id (copy_id);
1647 if (!orig || !copy) {
1648 warning << string_compose (_("Regions in compound description not found (ID's %1 and %2): ignored"),
1654 RegionFactory::add_compound_association (orig, copy);
1661 Session::load_nested_sources (const XMLNode& node)
1664 XMLNodeConstIterator niter;
1666 nlist = node.children();
1668 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1669 if ((*niter)->name() == "Source") {
1671 /* it may already exist, so don't recreate it unnecessarily
1674 XMLProperty* prop = (*niter)->property (X_("id"));
1676 error << _("Nested source has no ID info in session state file! (ignored)") << endmsg;
1680 ID source_id (prop->value());
1682 if (!source_by_id (source_id)) {
1685 SourceFactory::create (*this, **niter, true);
1687 catch (failed_constructor& err) {
1688 error << string_compose (_("Cannot reconstruct nested source for region %1"), name()) << endmsg;
1695 boost::shared_ptr<Region>
1696 Session::XMLRegionFactory (const XMLNode& node, bool full)
1698 const XMLProperty* type = node.property("type");
1702 const XMLNodeList& nlist = node.children();
1704 for (XMLNodeConstIterator niter = nlist.begin(); niter != nlist.end(); ++niter) {
1705 XMLNode *child = (*niter);
1706 if (child->name() == "NestedSource") {
1707 load_nested_sources (*child);
1711 if (!type || type->value() == "audio") {
1712 return boost::shared_ptr<Region>(XMLAudioRegionFactory (node, full));
1713 } else if (type->value() == "midi") {
1714 return boost::shared_ptr<Region>(XMLMidiRegionFactory (node, full));
1717 } catch (failed_constructor& err) {
1718 return boost::shared_ptr<Region> ();
1721 return boost::shared_ptr<Region> ();
1724 boost::shared_ptr<AudioRegion>
1725 Session::XMLAudioRegionFactory (const XMLNode& node, bool /*full*/)
1727 const XMLProperty* prop;
1728 boost::shared_ptr<Source> source;
1729 boost::shared_ptr<AudioSource> as;
1731 SourceList master_sources;
1732 uint32_t nchans = 1;
1735 if (node.name() != X_("Region")) {
1736 return boost::shared_ptr<AudioRegion>();
1739 if ((prop = node.property (X_("channels"))) != 0) {
1740 nchans = atoi (prop->value().c_str());
1743 if ((prop = node.property ("name")) == 0) {
1744 cerr << "no name for this region\n";
1748 if ((prop = node.property (X_("source-0"))) == 0) {
1749 if ((prop = node.property ("source")) == 0) {
1750 error << _("Session: XMLNode describing a AudioRegion is incomplete (no source)") << endmsg;
1751 return boost::shared_ptr<AudioRegion>();
1755 PBD::ID s_id (prop->value());
1757 if ((source = source_by_id (s_id)) == 0) {
1758 error << string_compose(_("Session: XMLNode describing a AudioRegion references an unknown source id =%1"), s_id) << endmsg;
1759 return boost::shared_ptr<AudioRegion>();
1762 as = boost::dynamic_pointer_cast<AudioSource>(source);
1764 error << string_compose(_("Session: XMLNode describing a AudioRegion references a non-audio source id =%1"), s_id) << endmsg;
1765 return boost::shared_ptr<AudioRegion>();
1768 sources.push_back (as);
1770 /* pickup other channels */
1772 for (uint32_t n=1; n < nchans; ++n) {
1773 snprintf (buf, sizeof(buf), X_("source-%d"), n);
1774 if ((prop = node.property (buf)) != 0) {
1776 PBD::ID id2 (prop->value());
1778 if ((source = source_by_id (id2)) == 0) {
1779 error << string_compose(_("Session: XMLNode describing a AudioRegion references an unknown source id =%1"), id2) << endmsg;
1780 return boost::shared_ptr<AudioRegion>();
1783 as = boost::dynamic_pointer_cast<AudioSource>(source);
1785 error << string_compose(_("Session: XMLNode describing a AudioRegion references a non-audio source id =%1"), id2) << endmsg;
1786 return boost::shared_ptr<AudioRegion>();
1788 sources.push_back (as);
1792 for (uint32_t n = 0; n < nchans; ++n) {
1793 snprintf (buf, sizeof(buf), X_("master-source-%d"), n);
1794 if ((prop = node.property (buf)) != 0) {
1796 PBD::ID id2 (prop->value());
1798 if ((source = source_by_id (id2)) == 0) {
1799 error << string_compose(_("Session: XMLNode describing a AudioRegion references an unknown source id =%1"), id2) << endmsg;
1800 return boost::shared_ptr<AudioRegion>();
1803 as = boost::dynamic_pointer_cast<AudioSource>(source);
1805 error << string_compose(_("Session: XMLNode describing a AudioRegion references a non-audio source id =%1"), id2) << endmsg;
1806 return boost::shared_ptr<AudioRegion>();
1808 master_sources.push_back (as);
1813 boost::shared_ptr<AudioRegion> region (boost::dynamic_pointer_cast<AudioRegion> (RegionFactory::create (sources, node)));
1815 /* a final detail: this is the one and only place that we know how long missing files are */
1817 if (region->whole_file()) {
1818 for (SourceList::iterator sx = sources.begin(); sx != sources.end(); ++sx) {
1819 boost::shared_ptr<SilentFileSource> sfp = boost::dynamic_pointer_cast<SilentFileSource> (*sx);
1821 sfp->set_length (region->length());
1826 if (!master_sources.empty()) {
1827 if (master_sources.size() != nchans) {
1828 error << _("Session: XMLNode describing an AudioRegion is missing some master sources; ignored") << endmsg;
1830 region->set_master_sources (master_sources);
1838 catch (failed_constructor& err) {
1839 return boost::shared_ptr<AudioRegion>();
1843 boost::shared_ptr<MidiRegion>
1844 Session::XMLMidiRegionFactory (const XMLNode& node, bool /*full*/)
1846 const XMLProperty* prop;
1847 boost::shared_ptr<Source> source;
1848 boost::shared_ptr<MidiSource> ms;
1851 if (node.name() != X_("Region")) {
1852 return boost::shared_ptr<MidiRegion>();
1855 if ((prop = node.property ("name")) == 0) {
1856 cerr << "no name for this region\n";
1860 if ((prop = node.property (X_("source-0"))) == 0) {
1861 if ((prop = node.property ("source")) == 0) {
1862 error << _("Session: XMLNode describing a MidiRegion is incomplete (no source)") << endmsg;
1863 return boost::shared_ptr<MidiRegion>();
1867 PBD::ID s_id (prop->value());
1869 if ((source = source_by_id (s_id)) == 0) {
1870 error << string_compose(_("Session: XMLNode describing a MidiRegion references an unknown source id =%1"), s_id) << endmsg;
1871 return boost::shared_ptr<MidiRegion>();
1874 ms = boost::dynamic_pointer_cast<MidiSource>(source);
1876 error << string_compose(_("Session: XMLNode describing a MidiRegion references a non-midi source id =%1"), s_id) << endmsg;
1877 return boost::shared_ptr<MidiRegion>();
1880 sources.push_back (ms);
1883 boost::shared_ptr<MidiRegion> region (boost::dynamic_pointer_cast<MidiRegion> (RegionFactory::create (sources, node)));
1884 /* a final detail: this is the one and only place that we know how long missing files are */
1886 if (region->whole_file()) {
1887 for (SourceList::iterator sx = sources.begin(); sx != sources.end(); ++sx) {
1888 boost::shared_ptr<SilentFileSource> sfp = boost::dynamic_pointer_cast<SilentFileSource> (*sx);
1890 sfp->set_length (region->length());
1898 catch (failed_constructor& err) {
1899 return boost::shared_ptr<MidiRegion>();
1904 Session::get_sources_as_xml ()
1907 XMLNode* node = new XMLNode (X_("Sources"));
1908 Glib::Mutex::Lock lm (source_lock);
1910 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ++i) {
1911 node->add_child_nocopy (i->second->get_state());
1918 Session::path_from_region_name (DataType type, string name, string identifier)
1920 char buf[PATH_MAX+1];
1922 SessionDirectory sdir(get_best_session_directory_for_new_source());
1923 sys::path source_dir = ((type == DataType::AUDIO)
1924 ? sdir.sound_path() : sdir.midi_path());
1926 string ext = native_header_format_extension (config.get_native_file_header_format(), type);
1928 for (n = 0; n < 999999; ++n) {
1929 if (identifier.length()) {
1930 snprintf (buf, sizeof(buf), "%s%s%" PRIu32 "%s", name.c_str(),
1931 identifier.c_str(), n, ext.c_str());
1933 snprintf (buf, sizeof(buf), "%s-%" PRIu32 "%s", name.c_str(),
1937 sys::path source_path = source_dir / buf;
1939 if (!sys::exists (source_path)) {
1940 return source_path.to_string();
1944 error << string_compose (_("cannot create new file from region name \"%1\" with ident = \"%2\": too many existing files with similar names"),
1953 Session::load_sources (const XMLNode& node)
1956 XMLNodeConstIterator niter;
1957 boost::shared_ptr<Source> source;
1959 nlist = node.children();
1963 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1966 if ((source = XMLSourceFactory (**niter)) == 0) {
1967 error << _("Session: cannot create Source from XML description.") << endmsg;
1970 } catch (MissingSource& err) {
1974 if (!no_questions_about_missing_files) {
1975 user_choice = MissingFile (this, err.path, err.type).get_value_or (-1);
1980 switch (user_choice) {
1982 /* user added a new search location, so try again */
1987 /* user asked to quit the entire session load
1992 no_questions_about_missing_files = true;
1996 no_questions_about_missing_files = true;
2001 warning << _("A sound file is missing. It will be replaced by silence.") << endmsg;
2002 source = SourceFactory::createSilent (*this, **niter, max_framecnt, _current_frame_rate);
2011 boost::shared_ptr<Source>
2012 Session::XMLSourceFactory (const XMLNode& node)
2014 if (node.name() != "Source") {
2015 return boost::shared_ptr<Source>();
2019 /* note: do peak building in another thread when loading session state */
2020 return SourceFactory::create (*this, node, true);
2023 catch (failed_constructor& err) {
2024 error << string_compose (_("Found a sound file that cannot be used by %1. Talk to the progammers."), PROGRAM_NAME) << endmsg;
2025 return boost::shared_ptr<Source>();
2030 Session::save_template (string template_name)
2034 if (_state_of_the_state & CannotSave) {
2038 sys::path user_template_dir(user_template_directory());
2042 sys::create_directories (user_template_dir);
2044 catch(sys::filesystem_error& ex)
2046 error << string_compose(_("Could not create templates directory \"%1\" (%2)"),
2047 user_template_dir.to_string(), ex.what()) << endmsg;
2051 tree.set_root (&get_template());
2053 sys::path template_dir_path(user_template_dir);
2055 /* directory to put the template in */
2056 template_dir_path /= template_name;
2057 if (sys::exists (template_dir_path))
2059 warning << string_compose(_("Template \"%1\" already exists - new version not created"),
2060 template_dir_path.to_string()) << endmsg;
2064 sys::create_directories (template_dir_path);
2067 sys::path template_file_path = template_dir_path;
2068 template_file_path /= template_name + template_suffix;
2070 if (!tree.write (template_file_path.to_string())) {
2071 error << _("template not saved") << endmsg;
2075 /* copy plugin state directory */
2077 sys::path template_plugin_state_path = template_dir_path;
2078 template_plugin_state_path /= X_("plugins");
2079 sys::create_directories (template_plugin_state_path);
2080 copy_files (plugins_dir(), template_plugin_state_path.to_string());
2086 Session::refresh_disk_space ()
2088 #if HAVE_SYS_VFS_H && HAVE_SYS_STATVFS_H
2090 Glib::Mutex::Lock lm (space_lock);
2092 /* get freespace on every FS that is part of the session path */
2094 _total_free_4k_blocks = 0;
2095 _total_free_4k_blocks_uncertain = false;
2097 for (vector<space_and_path>::iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
2099 struct statfs statfsbuf;
2100 statfs (i->path.c_str(), &statfsbuf);
2102 double const scale = statfsbuf.f_bsize / 4096.0;
2104 /* See if this filesystem is read-only */
2105 struct statvfs statvfsbuf;
2106 statvfs (i->path.c_str(), &statvfsbuf);
2108 /* f_bavail can be 0 if it is undefined for whatever
2109 filesystem we are looking at; Samba shares mounted
2110 via GVFS are an example of this.
2112 if (statfsbuf.f_bavail == 0) {
2113 /* block count unknown */
2115 i->blocks_unknown = true;
2116 } else if (statvfsbuf.f_flag & ST_RDONLY) {
2117 /* read-only filesystem */
2119 i->blocks_unknown = false;
2121 /* read/write filesystem with known space */
2122 i->blocks = (uint32_t) floor (statfsbuf.f_bavail * scale);
2123 i->blocks_unknown = false;
2126 _total_free_4k_blocks += i->blocks;
2127 if (i->blocks_unknown) {
2128 _total_free_4k_blocks_uncertain = true;
2135 Session::get_best_session_directory_for_new_source ()
2137 vector<space_and_path>::iterator i;
2138 string result = _session_dir->root_path();
2140 /* handle common case without system calls */
2142 if (session_dirs.size() == 1) {
2146 /* OK, here's the algorithm we're following here:
2148 We want to select which directory to use for
2149 the next file source to be created. Ideally,
2150 we'd like to use a round-robin process so as to
2151 get maximum performance benefits from splitting
2152 the files across multiple disks.
2154 However, in situations without much diskspace, an
2155 RR approach may end up filling up a filesystem
2156 with new files while others still have space.
2157 Its therefore important to pay some attention to
2158 the freespace in the filesystem holding each
2159 directory as well. However, if we did that by
2160 itself, we'd keep creating new files in the file
2161 system with the most space until it was as full
2162 as all others, thus negating any performance
2163 benefits of this RAID-1 like approach.
2165 So, we use a user-configurable space threshold. If
2166 there are at least 2 filesystems with more than this
2167 much space available, we use RR selection between them.
2168 If not, then we pick the filesystem with the most space.
2170 This gets a good balance between the two
2174 refresh_disk_space ();
2176 int free_enough = 0;
2178 for (i = session_dirs.begin(); i != session_dirs.end(); ++i) {
2179 if ((*i).blocks * 4096 >= Config->get_disk_choice_space_threshold()) {
2184 if (free_enough >= 2) {
2185 /* use RR selection process, ensuring that the one
2189 i = last_rr_session_dir;
2192 if (++i == session_dirs.end()) {
2193 i = session_dirs.begin();
2196 if ((*i).blocks * 4096 >= Config->get_disk_choice_space_threshold()) {
2197 if (create_session_directory ((*i).path)) {
2199 last_rr_session_dir = i;
2204 } while (i != last_rr_session_dir);
2208 /* pick FS with the most freespace (and that
2209 seems to actually work ...)
2212 vector<space_and_path> sorted;
2213 space_and_path_ascending_cmp cmp;
2215 sorted = session_dirs;
2216 sort (sorted.begin(), sorted.end(), cmp);
2218 for (i = sorted.begin(); i != sorted.end(); ++i) {
2219 if (create_session_directory ((*i).path)) {
2221 last_rr_session_dir = i;
2231 Session::load_named_selections (const XMLNode& node)
2234 XMLNodeConstIterator niter;
2237 nlist = node.children();
2241 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2243 if ((ns = XMLNamedSelectionFactory (**niter)) == 0) {
2244 error << _("Session: cannot create Named Selection from XML description.") << endmsg;
2252 Session::XMLNamedSelectionFactory (const XMLNode& node)
2255 return new NamedSelection (*this, node);
2258 catch (failed_constructor& err) {
2264 Session::automation_dir () const
2266 return Glib::build_filename (_path, "automation");
2270 Session::analysis_dir () const
2272 return Glib::build_filename (_path, "analysis");
2276 Session::plugins_dir () const
2278 return Glib::build_filename (_path, "plugins");
2282 Session::externals_dir () const
2284 return Glib::build_filename (_path, "externals");
2288 Session::load_bundles (XMLNode const & node)
2290 XMLNodeList nlist = node.children();
2291 XMLNodeConstIterator niter;
2295 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2296 if ((*niter)->name() == "InputBundle") {
2297 add_bundle (boost::shared_ptr<UserBundle> (new UserBundle (**niter, true)));
2298 } else if ((*niter)->name() == "OutputBundle") {
2299 add_bundle (boost::shared_ptr<UserBundle> (new UserBundle (**niter, false)));
2301 error << string_compose(_("Unknown node \"%1\" found in Bundles list from state file"), (*niter)->name()) << endmsg;
2310 Session::load_route_groups (const XMLNode& node, int version)
2312 XMLNodeList nlist = node.children();
2313 XMLNodeConstIterator niter;
2317 if (version >= 3000) {
2319 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2320 if ((*niter)->name() == "RouteGroup") {
2321 RouteGroup* rg = new RouteGroup (*this, "");
2322 add_route_group (rg);
2323 rg->set_state (**niter, version);
2327 } else if (version < 3000) {
2329 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2330 if ((*niter)->name() == "EditGroup" || (*niter)->name() == "MixGroup") {
2331 RouteGroup* rg = new RouteGroup (*this, "");
2332 add_route_group (rg);
2333 rg->set_state (**niter, version);
2342 Session::auto_save()
2344 save_state (_current_snapshot_name);
2348 state_file_filter (const string &str, void */*arg*/)
2350 return (str.length() > strlen(statefile_suffix) &&
2351 str.find (statefile_suffix) == (str.length() - strlen (statefile_suffix)));
2355 bool operator()(const string* a, const string* b) {
2361 remove_end(string* state)
2363 string statename(*state);
2365 string::size_type start,end;
2366 if ((start = statename.find_last_of (G_DIR_SEPARATOR)) != string::npos) {
2367 statename = statename.substr (start+1);
2370 if ((end = statename.rfind(".ardour")) == string::npos) {
2371 end = statename.length();
2374 return new string(statename.substr (0, end));
2378 Session::possible_states (string path)
2380 PathScanner scanner;
2381 vector<string*>* states = scanner (path, state_file_filter, 0, false, false);
2383 transform(states->begin(), states->end(), states->begin(), remove_end);
2386 sort (states->begin(), states->end(), cmp);
2392 Session::possible_states () const
2394 return possible_states(_path);
2398 Session::add_route_group (RouteGroup* g)
2400 _route_groups.push_back (g);
2401 route_group_added (g); /* EMIT SIGNAL */
2403 g->RouteAdded.connect_same_thread (*this, boost::bind (&Session::route_added_to_route_group, this, _1, _2));
2404 g->RouteRemoved.connect_same_thread (*this, boost::bind (&Session::route_removed_from_route_group, this, _1, _2));
2405 g->PropertyChanged.connect_same_thread (*this, boost::bind (&Session::route_group_property_changed, this, g));
2411 Session::remove_route_group (RouteGroup& rg)
2413 list<RouteGroup*>::iterator i;
2415 if ((i = find (_route_groups.begin(), _route_groups.end(), &rg)) != _route_groups.end()) {
2416 _route_groups.erase (i);
2419 route_group_removed (); /* EMIT SIGNAL */
2423 /** Set a new order for our route groups, without adding or removing any.
2424 * @param groups Route group list in the new order.
2427 Session::reorder_route_groups (list<RouteGroup*> groups)
2429 _route_groups = groups;
2431 route_groups_reordered (); /* EMIT SIGNAL */
2437 Session::route_group_by_name (string name)
2439 list<RouteGroup *>::iterator i;
2441 for (i = _route_groups.begin(); i != _route_groups.end(); ++i) {
2442 if ((*i)->name() == name) {
2450 Session::all_route_group() const
2452 return *_all_route_group;
2456 Session::add_commands (vector<Command*> const & cmds)
2458 for (vector<Command*>::const_iterator i = cmds.begin(); i != cmds.end(); ++i) {
2464 Session::begin_reversible_command (const string& name)
2466 begin_reversible_command (g_quark_from_string (name.c_str ()));
2469 /** Begin a reversible command using a GQuark to identify it.
2470 * begin_reversible_command() and commit_reversible_command() calls may be nested,
2471 * but there must be as many begin...()s as there are commit...()s.
2474 Session::begin_reversible_command (GQuark q)
2476 /* If nested begin/commit pairs are used, we create just one UndoTransaction
2477 to hold all the commands that are committed. This keeps the order of
2478 commands correct in the history.
2481 if (_current_trans == 0) {
2482 /* start a new transaction */
2483 assert (_current_trans_quarks.empty ());
2484 _current_trans = new UndoTransaction();
2485 _current_trans->set_name (g_quark_to_string (q));
2488 _current_trans_quarks.push_front (q);
2492 Session::commit_reversible_command (Command *cmd)
2494 assert (_current_trans);
2495 assert (!_current_trans_quarks.empty ());
2500 _current_trans->add_command (cmd);
2503 _current_trans_quarks.pop_front ();
2505 if (!_current_trans_quarks.empty ()) {
2506 /* the transaction we're committing is not the top-level one */
2510 if (_current_trans->empty()) {
2511 /* no commands were added to the transaction, so just get rid of it */
2512 delete _current_trans;
2517 gettimeofday (&now, 0);
2518 _current_trans->set_timestamp (now);
2520 _history.add (_current_trans);
2525 accept_all_audio_files (const string& path, void */*arg*/)
2527 if (!Glib::file_test (path, Glib::FILE_TEST_IS_REGULAR)) {
2531 if (!AudioFileSource::safe_audio_file_extension (path)) {
2539 accept_all_midi_files (const string& path, void */*arg*/)
2541 if (!Glib::file_test (path, Glib::FILE_TEST_IS_REGULAR)) {
2545 return ((path.length() > 4 && path.find (".mid") != (path.length() - 4)) ||
2546 (path.length() > 4 && path.find (".smf") != (path.length() - 4)) ||
2547 (path.length() > 5 && path.find (".midi") != (path.length() - 5)));
2551 accept_all_state_files (const string& path, void */*arg*/)
2553 if (!Glib::file_test (path, Glib::FILE_TEST_IS_REGULAR)) {
2557 return (path.length() > 7 && path.find (".ardour") == (path.length() - 7));
2561 Session::find_all_sources (string path, set<string>& result)
2566 if (!tree.read (path)) {
2570 if ((node = find_named_node (*tree.root(), "Sources")) == 0) {
2575 XMLNodeConstIterator niter;
2577 nlist = node->children();
2581 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2585 if ((prop = (*niter)->property (X_("type"))) == 0) {
2589 DataType type (prop->value());
2591 if ((prop = (*niter)->property (X_("name"))) == 0) {
2595 if (Glib::path_is_absolute (prop->value())) {
2596 /* external file, ignore */
2604 if (FileSource::find (*this, type, prop->value(), true, is_new, chan, found_path)) {
2605 result.insert (found_path);
2613 Session::find_all_sources_across_snapshots (set<string>& result, bool exclude_this_snapshot)
2615 PathScanner scanner;
2616 vector<string*>* state_files;
2618 string this_snapshot_path;
2624 if (ripped[ripped.length()-1] == G_DIR_SEPARATOR) {
2625 ripped = ripped.substr (0, ripped.length() - 1);
2628 state_files = scanner (ripped, accept_all_state_files, (void *) 0, false, true);
2630 if (state_files == 0) {
2635 this_snapshot_path = _path;
2636 this_snapshot_path += legalize_for_path (_current_snapshot_name);
2637 this_snapshot_path += statefile_suffix;
2639 for (vector<string*>::iterator i = state_files->begin(); i != state_files->end(); ++i) {
2641 if (exclude_this_snapshot && **i == this_snapshot_path) {
2645 if (find_all_sources (**i, result) < 0) {
2653 struct RegionCounter {
2654 typedef std::map<PBD::ID,boost::shared_ptr<AudioSource> > AudioSourceList;
2655 AudioSourceList::iterator iter;
2656 boost::shared_ptr<Region> region;
2659 RegionCounter() : count (0) {}
2663 Session::ask_about_playlist_deletion (boost::shared_ptr<Playlist> p)
2665 boost::optional<int> r = AskAboutPlaylistDeletion (p);
2666 return r.get_value_or (1);
2670 Session::cleanup_regions ()
2672 const RegionFactory::RegionMap& regions (RegionFactory::regions());
2674 for (RegionFactory::RegionMap::const_iterator i = regions.begin(); i != regions.end(); ++i) {
2676 uint32_t used = playlists->region_use_count (i->second);
2678 if (used == 0 && !i->second->automatic ()) {
2679 RegionFactory::map_remove (i->second);
2683 /* dump the history list */
2690 Session::cleanup_sources (CleanupReport& rep)
2692 // FIXME: needs adaptation to midi
2694 vector<boost::shared_ptr<Source> > dead_sources;
2695 PathScanner scanner;
2698 vector<space_and_path>::iterator i;
2699 vector<space_and_path>::iterator nexti;
2700 vector<string*>* candidates;
2701 vector<string*>* candidates2;
2702 vector<string> unused;
2703 set<string> all_sources;
2708 _state_of_the_state = (StateOfTheState) (_state_of_the_state | InCleanup);
2710 /* consider deleting all unused playlists */
2712 if (playlists->maybe_delete_unused (boost::bind (Session::ask_about_playlist_deletion, _1))) {
2717 /* sync the "all regions" property of each playlist with its current state
2720 playlists->sync_all_regions_with_regions ();
2722 /* find all un-used sources */
2727 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ) {
2729 SourceMap::iterator tmp;
2734 /* do not bother with files that are zero size, otherwise we remove the current "nascent"
2738 if (!i->second->used() && (i->second->length(i->second->timeline_position() > 0))) {
2739 dead_sources.push_back (i->second);
2740 i->second->drop_references ();
2746 /* build a list of all the possible audio directories for the session */
2748 for (i = session_dirs.begin(); i != session_dirs.end(); ) {
2753 SessionDirectory sdir ((*i).path);
2754 audio_path += sdir.sound_path();
2756 if (nexti != session_dirs.end()) {
2764 /* build a list of all the possible midi directories for the session */
2766 for (i = session_dirs.begin(); i != session_dirs.end(); ) {
2771 SessionDirectory sdir ((*i).path);
2772 midi_path += sdir.midi_path();
2774 if (nexti != session_dirs.end()) {
2781 candidates = scanner (audio_path, accept_all_audio_files, (void *) 0, true, true);
2782 candidates2 = scanner (midi_path, accept_all_midi_files, (void *) 0, true, true);
2788 for (vector<string*>::iterator i = candidates2->begin(); i != candidates2->end(); ++i) {
2789 candidates->push_back (*i);
2794 candidates = candidates2; // might still be null
2797 /* find all sources, but don't use this snapshot because the
2798 state file on disk still references sources we may have already
2802 find_all_sources_across_snapshots (all_sources, true);
2804 /* add our current source list
2807 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ) {
2808 boost::shared_ptr<FileSource> fs;
2809 SourceMap::iterator tmp = i;
2812 if ((fs = boost::dynamic_pointer_cast<FileSource> (i->second)) != 0) {
2813 if (playlists->source_use_count (fs) != 0) {
2814 all_sources.insert (fs->path());
2817 /* we might not remove this source from disk, because it may be used
2818 by other snapshots, but its not being used in this version
2819 so lets get rid of it now, along with any representative regions
2823 RegionFactory::remove_regions_using_source (i->second);
2831 char tmppath1[PATH_MAX+1];
2832 char tmppath2[PATH_MAX+1];
2835 for (vector<string*>::iterator x = candidates->begin(); x != candidates->end(); ++x) {
2840 for (set<string>::iterator i = all_sources.begin(); i != all_sources.end(); ++i) {
2842 if (realpath(spath.c_str(), tmppath1) == 0) {
2843 error << string_compose (_("Cannot expand path %1 (%2)"),
2844 spath, strerror (errno)) << endmsg;
2848 if (realpath((*i).c_str(), tmppath2) == 0) {
2849 error << string_compose (_("Cannot expand path %1 (%2)"),
2850 (*i), strerror (errno)) << endmsg;
2854 if (strcmp(tmppath1, tmppath2) == 0) {
2861 unused.push_back (spath);
2870 /* now try to move all unused files into the "dead" directory(ies) */
2872 for (vector<string>::iterator x = unused.begin(); x != unused.end(); ++x) {
2873 struct stat statbuf;
2877 /* don't move the file across filesystems, just
2878 stick it in the `dead_dir_name' directory
2879 on whichever filesystem it was already on.
2882 if ((*x).find ("/sounds/") != string::npos) {
2884 /* old school, go up 1 level */
2886 newpath = Glib::path_get_dirname (*x); // "sounds"
2887 newpath = Glib::path_get_dirname (newpath); // "session-name"
2891 /* new school, go up 4 levels */
2893 newpath = Glib::path_get_dirname (*x); // "audiofiles" or "midifiles"
2894 newpath = Glib::path_get_dirname (newpath); // "session-name"
2895 newpath = Glib::path_get_dirname (newpath); // "interchange"
2896 newpath = Glib::path_get_dirname (newpath); // "session-dir"
2899 newpath = Glib::build_filename (newpath, dead_dir_name);
2901 if (g_mkdir_with_parents (newpath.c_str(), 0755) < 0) {
2902 error << string_compose(_("Session: cannot create dead file folder \"%1\" (%2)"), newpath, strerror (errno)) << endmsg;
2906 newpath = Glib::build_filename (newpath, Glib::path_get_basename ((*x)));
2908 if (Glib::file_test (newpath, Glib::FILE_TEST_EXISTS)) {
2910 /* the new path already exists, try versioning */
2912 char buf[PATH_MAX+1];
2916 snprintf (buf, sizeof (buf), "%s.%d", newpath.c_str(), version);
2919 while (Glib::file_test (newpath_v.c_str(), Glib::FILE_TEST_EXISTS) && version < 999) {
2920 snprintf (buf, sizeof (buf), "%s.%d", newpath.c_str(), ++version);
2924 if (version == 999) {
2925 error << string_compose (_("there are already 1000 files with names like %1; versioning discontinued"),
2929 newpath = newpath_v;
2934 /* it doesn't exist, or we can't read it or something */
2938 stat ((*x).c_str(), &statbuf);
2940 if (::rename ((*x).c_str(), newpath.c_str()) != 0) {
2941 error << string_compose (_("cannot rename unused file source from %1 to %2 (%3)"),
2942 (*x), newpath, strerror (errno))
2947 /* see if there an easy to find peakfile for this file, and remove it.
2950 string base = basename_nosuffix (*x);
2951 base += "%A"; /* this is what we add for the channel suffix of all native files,
2952 or for the first channel of embedded files. it will miss
2953 some peakfiles for other channels
2955 string peakpath = peak_path (base);
2957 if (Glib::file_test (peakpath.c_str(), Glib::FILE_TEST_EXISTS)) {
2958 if (::unlink (peakpath.c_str()) != 0) {
2959 error << string_compose (_("cannot remove peakfile %1 for %2 (%3)"),
2960 peakpath, _path, strerror (errno))
2962 /* try to back out */
2963 ::rename (newpath.c_str(), _path.c_str());
2968 rep.paths.push_back (*x);
2969 rep.space += statbuf.st_size;
2972 /* dump the history list */
2976 /* save state so we don't end up a session file
2977 referring to non-existent sources.
2984 _state_of_the_state = (StateOfTheState) (_state_of_the_state & ~InCleanup);
2990 Session::cleanup_trash_sources (CleanupReport& rep)
2992 // FIXME: needs adaptation for MIDI
2994 vector<space_and_path>::iterator i;
3000 for (i = session_dirs.begin(); i != session_dirs.end(); ++i) {
3002 dead_dir = Glib::build_filename ((*i).path, dead_dir_name);
3004 clear_directory (dead_dir, &rep.space, &rep.paths);
3011 Session::set_dirty ()
3013 bool was_dirty = dirty();
3015 _state_of_the_state = StateOfTheState (_state_of_the_state | Dirty);
3019 DirtyChanged(); /* EMIT SIGNAL */
3025 Session::set_clean ()
3027 bool was_dirty = dirty();
3029 _state_of_the_state = Clean;
3033 DirtyChanged(); /* EMIT SIGNAL */
3038 Session::set_deletion_in_progress ()
3040 _state_of_the_state = StateOfTheState (_state_of_the_state | Deletion);
3044 Session::clear_deletion_in_progress ()
3046 _state_of_the_state = StateOfTheState (_state_of_the_state & (~Deletion));
3050 Session::add_controllable (boost::shared_ptr<Controllable> c)
3052 /* this adds a controllable to the list managed by the Session.
3053 this is a subset of those managed by the Controllable class
3054 itself, and represents the only ones whose state will be saved
3055 as part of the session.
3058 Glib::Mutex::Lock lm (controllables_lock);
3059 controllables.insert (c);
3062 struct null_deleter { void operator()(void const *) const {} };
3065 Session::remove_controllable (Controllable* c)
3067 if (_state_of_the_state & Deletion) {
3071 Glib::Mutex::Lock lm (controllables_lock);
3073 Controllables::iterator x = controllables.find (boost::shared_ptr<Controllable>(c, null_deleter()));
3075 if (x != controllables.end()) {
3076 controllables.erase (x);
3080 boost::shared_ptr<Controllable>
3081 Session::controllable_by_id (const PBD::ID& id)
3083 Glib::Mutex::Lock lm (controllables_lock);
3085 for (Controllables::iterator i = controllables.begin(); i != controllables.end(); ++i) {
3086 if ((*i)->id() == id) {
3091 return boost::shared_ptr<Controllable>();
3094 boost::shared_ptr<Controllable>
3095 Session::controllable_by_descriptor (const ControllableDescriptor& desc)
3097 boost::shared_ptr<Controllable> c;
3098 boost::shared_ptr<Route> r;
3100 switch (desc.top_level_type()) {
3101 case ControllableDescriptor::NamedRoute:
3103 std::string str = desc.top_level_name();
3104 if (str == "master") {
3106 } else if (str == "control" || str == "listen") {
3109 r = route_by_name (desc.top_level_name());
3114 case ControllableDescriptor::RemoteControlID:
3115 r = route_by_remote_id (desc.rid());
3123 switch (desc.subtype()) {
3124 case ControllableDescriptor::Gain:
3125 c = r->gain_control ();
3128 case ControllableDescriptor::Solo:
3129 c = r->solo_control();
3132 case ControllableDescriptor::Mute:
3133 c = r->mute_control();
3136 case ControllableDescriptor::Recenable:
3138 boost::shared_ptr<Track> t = boost::dynamic_pointer_cast<Track>(r);
3141 c = t->rec_enable_control ();
3146 case ControllableDescriptor::PanDirection:
3148 c = r->pannable()->pan_azimuth_control;
3152 case ControllableDescriptor::PanWidth:
3154 c = r->pannable()->pan_width_control;
3158 case ControllableDescriptor::PanElevation:
3160 c = r->pannable()->pan_elevation_control;
3164 case ControllableDescriptor::Balance:
3165 /* XXX simple pan control */
3168 case ControllableDescriptor::PluginParameter:
3170 uint32_t plugin = desc.target (0);
3171 uint32_t parameter_index = desc.target (1);
3173 /* revert to zero based counting */
3179 if (parameter_index > 0) {
3183 boost::shared_ptr<Processor> p = r->nth_plugin (plugin);
3186 c = boost::dynamic_pointer_cast<ARDOUR::AutomationControl>(
3187 p->control(Evoral::Parameter(PluginAutomation, 0, parameter_index)));
3192 case ControllableDescriptor::SendGain:
3194 uint32_t send = desc.target (0);
3196 /* revert to zero-based counting */
3202 boost::shared_ptr<Processor> p = r->nth_send (send);
3205 boost::shared_ptr<Send> s = boost::dynamic_pointer_cast<Send>(p);
3206 boost::shared_ptr<Amp> a = s->amp();
3209 c = s->amp()->gain_control();
3216 /* relax and return a null pointer */
3224 Session::add_instant_xml (XMLNode& node, bool write_to_config)
3227 Stateful::add_instant_xml (node, _path);
3230 if (write_to_config) {
3231 Config->add_instant_xml (node);
3236 Session::instant_xml (const string& node_name)
3238 return Stateful::instant_xml (node_name, _path);
3242 Session::save_history (string snapshot_name)
3250 if (snapshot_name.empty()) {
3251 snapshot_name = _current_snapshot_name;
3254 const string history_filename = legalize_for_path (snapshot_name) + history_suffix;
3255 const string backup_filename = history_filename + backup_suffix;
3256 const sys::path xml_path(Glib::build_filename (_session_dir->root_path(), history_filename));
3257 const sys::path backup_path(Glib::build_filename (_session_dir->root_path(), backup_filename));
3259 if (sys::exists (xml_path)) {
3262 sys::rename (xml_path, backup_path);
3264 catch (const sys::filesystem_error& err)
3266 error << _("could not backup old history file, current history not saved") << endmsg;
3271 if (!Config->get_save_history() || Config->get_saved_history_depth() < 0) {
3275 tree.set_root (&_history.get_state (Config->get_saved_history_depth()));
3277 if (!tree.write (xml_path.to_string()))
3279 error << string_compose (_("history could not be saved to %1"), xml_path.to_string()) << endmsg;
3283 sys::remove (xml_path);
3284 sys::rename (backup_path, xml_path);
3286 catch (const sys::filesystem_error& err)
3288 error << string_compose (_("could not restore history file from backup %1 (%2)"),
3289 backup_path.to_string(), err.what()) << endmsg;
3299 Session::restore_history (string snapshot_name)
3303 if (snapshot_name.empty()) {
3304 snapshot_name = _current_snapshot_name;
3307 const string xml_filename = legalize_for_path (snapshot_name) + history_suffix;
3308 const sys::path xml_path(Glib::build_filename (_session_dir->root_path(), xml_filename));
3310 info << "Loading history from " << xml_path.to_string() << endmsg;
3312 if (!sys::exists (xml_path)) {
3313 info << string_compose (_("%1: no history file \"%2\" for this session."),
3314 _name, xml_path.to_string()) << endmsg;
3318 if (!tree.read (xml_path.to_string())) {
3319 error << string_compose (_("Could not understand session history file \"%1\""),
3320 xml_path.to_string()) << endmsg;
3327 for (XMLNodeConstIterator it = tree.root()->children().begin(); it != tree.root()->children().end(); it++) {
3330 UndoTransaction* ut = new UndoTransaction ();
3333 ut->set_name(t->property("name")->value());
3334 stringstream ss(t->property("tv-sec")->value());
3336 ss.str(t->property("tv-usec")->value());
3338 ut->set_timestamp(tv);
3340 for (XMLNodeConstIterator child_it = t->children().begin();
3341 child_it != t->children().end(); child_it++)
3343 XMLNode *n = *child_it;
3346 if (n->name() == "MementoCommand" ||
3347 n->name() == "MementoUndoCommand" ||
3348 n->name() == "MementoRedoCommand") {
3350 if ((c = memento_command_factory(n))) {
3354 } else if (n->name() == "NoteDiffCommand") {
3355 PBD::ID id (n->property("midi-source")->value());
3356 boost::shared_ptr<MidiSource> midi_source =
3357 boost::dynamic_pointer_cast<MidiSource, Source>(source_by_id(id));
3359 ut->add_command (new MidiModel::NoteDiffCommand(midi_source->model(), *n));
3361 error << _("Failed to downcast MidiSource for NoteDiffCommand") << endmsg;
3364 } else if (n->name() == "SysExDiffCommand") {
3366 PBD::ID id (n->property("midi-source")->value());
3367 boost::shared_ptr<MidiSource> midi_source =
3368 boost::dynamic_pointer_cast<MidiSource, Source>(source_by_id(id));
3370 ut->add_command (new MidiModel::SysExDiffCommand (midi_source->model(), *n));
3372 error << _("Failed to downcast MidiSource for SysExDiffCommand") << endmsg;
3375 } else if (n->name() == "PatchChangeDiffCommand") {
3377 PBD::ID id (n->property("midi-source")->value());
3378 boost::shared_ptr<MidiSource> midi_source =
3379 boost::dynamic_pointer_cast<MidiSource, Source>(source_by_id(id));
3381 ut->add_command (new MidiModel::PatchChangeDiffCommand (midi_source->model(), *n));
3383 error << _("Failed to downcast MidiSource for PatchChangeDiffCommand") << endmsg;
3386 } else if (n->name() == "StatefulDiffCommand") {
3387 if ((c = stateful_diff_command_factory (n))) {
3388 ut->add_command (c);
3391 error << string_compose(_("Couldn't figure out how to make a Command out of a %1 XMLNode."), n->name()) << endmsg;
3402 Session::config_changed (std::string p, bool ours)
3408 if (p == "seamless-loop") {
3410 } else if (p == "rf-speed") {
3412 } else if (p == "auto-loop") {
3414 } else if (p == "auto-input") {
3416 if (Config->get_monitoring_model() == HardwareMonitoring && transport_rolling()) {
3417 /* auto-input only makes a difference if we're rolling */
3418 set_track_monitor_input_status (!config.get_auto_input());
3421 } else if (p == "punch-in") {
3425 if ((location = _locations->auto_punch_location()) != 0) {
3427 if (config.get_punch_in ()) {
3428 replace_event (SessionEvent::PunchIn, location->start());
3430 remove_event (location->start(), SessionEvent::PunchIn);
3434 } else if (p == "punch-out") {
3438 if ((location = _locations->auto_punch_location()) != 0) {
3440 if (config.get_punch_out()) {
3441 replace_event (SessionEvent::PunchOut, location->end());
3443 clear_events (SessionEvent::PunchOut);
3447 } else if (p == "edit-mode") {
3449 Glib::Mutex::Lock lm (playlists->lock);
3451 for (SessionPlaylists::List::iterator i = playlists->playlists.begin(); i != playlists->playlists.end(); ++i) {
3452 (*i)->set_edit_mode (Config->get_edit_mode ());
3455 } else if (p == "use-video-sync") {
3457 waiting_for_sync_offset = config.get_use_video_sync();
3459 } else if (p == "mmc-control") {
3461 //poke_midi_thread ();
3463 } else if (p == "mmc-device-id" || p == "mmc-receive-id" || p == "mmc-receive-device-id") {
3465 MIDI::Manager::instance()->mmc()->set_receive_device_id (Config->get_mmc_receive_device_id());
3467 } else if (p == "mmc-send-id" || p == "mmc-send-device-id") {
3469 MIDI::Manager::instance()->mmc()->set_send_device_id (Config->get_mmc_send_device_id());
3471 } else if (p == "midi-control") {
3473 //poke_midi_thread ();
3475 } else if (p == "raid-path") {
3477 setup_raid_path (config.get_raid_path());
3479 } else if (p == "timecode-format") {
3483 } else if (p == "video-pullup") {
3487 } else if (p == "seamless-loop") {
3489 if (play_loop && transport_rolling()) {
3490 // to reset diskstreams etc
3491 request_play_loop (true);
3494 } else if (p == "rf-speed") {
3496 cumulative_rf_motion = 0;
3499 } else if (p == "click-sound") {
3501 setup_click_sounds (1);
3503 } else if (p == "click-emphasis-sound") {
3505 setup_click_sounds (-1);
3507 } else if (p == "clicking") {
3509 if (Config->get_clicking()) {
3510 if (_click_io && click_data) { // don't require emphasis data
3517 } else if (p == "click-gain") {
3520 _click_gain->set_gain (Config->get_click_gain(), this);
3523 } else if (p == "send-mtc") {
3525 if (Config->get_send_mtc ()) {
3526 /* mark us ready to send */
3527 next_quarter_frame_to_send = 0;
3530 } else if (p == "send-mmc") {
3532 MIDI::Manager::instance()->mmc()->enable_send (Config->get_send_mmc ());
3534 } else if (p == "midi-feedback") {
3536 session_midi_feedback = Config->get_midi_feedback();
3538 } else if (p == "jack-time-master") {
3540 engine().reset_timebase ();
3542 } else if (p == "native-file-header-format") {
3544 if (!first_file_header_format_reset) {
3545 reset_native_file_format ();
3548 first_file_header_format_reset = false;
3550 } else if (p == "native-file-data-format") {
3552 if (!first_file_data_format_reset) {
3553 reset_native_file_format ();
3556 first_file_data_format_reset = false;
3558 } else if (p == "external-sync") {
3559 if (!config.get_external_sync()) {
3560 drop_sync_source ();
3562 switch_to_sync_source (config.get_sync_source());
3564 } else if (p == "remote-model") {
3565 set_remote_control_ids ();
3566 } else if (p == "denormal-model") {
3568 } else if (p == "history-depth") {
3569 set_history_depth (Config->get_history_depth());
3570 } else if (p == "sync-all-route-ordering") {
3571 sync_order_keys ("session");
3572 } else if (p == "initial-program-change") {
3574 if (MIDI::Manager::instance()->mmc()->output_port() && Config->get_initial_program_change() >= 0) {
3577 buf[0] = MIDI::program; // channel zero by default
3578 buf[1] = (Config->get_initial_program_change() & 0x7f);
3580 MIDI::Manager::instance()->mmc()->output_port()->midimsg (buf, sizeof (buf), 0);
3582 } else if (p == "solo-mute-override") {
3583 // catch_up_on_solo_mute_override ();
3584 } else if (p == "listen-position" || p == "pfl-position") {
3585 listen_position_changed ();
3586 } else if (p == "solo-control-is-listen-control") {
3587 solo_control_mode_changed ();
3588 } else if (p == "timecode-offset" || p == "timecode-offset-negative") {
3589 last_timecode_valid = false;
3590 } else if (p == "playback-buffer-seconds") {
3591 AudioSource::allocate_working_buffers (frame_rate());
3592 } else if (p == "automation-thinning-factor") {
3593 Evoral::ControlList::set_thinning_factor (Config->get_automation_thinning_factor());
3600 Session::set_history_depth (uint32_t d)
3602 _history.set_depth (d);
3606 Session::load_diskstreams_2X (XMLNode const & node, int)
3609 XMLNodeConstIterator citer;
3611 clist = node.children();
3613 for (citer = clist.begin(); citer != clist.end(); ++citer) {
3616 /* diskstreams added automatically by DiskstreamCreated handler */
3617 if ((*citer)->name() == "AudioDiskstream" || (*citer)->name() == "DiskStream") {
3618 boost::shared_ptr<AudioDiskstream> dsp (new AudioDiskstream (*this, **citer));
3619 _diskstreams_2X.push_back (dsp);
3621 error << _("Session: unknown diskstream type in XML") << endmsg;
3625 catch (failed_constructor& err) {
3626 error << _("Session: could not load diskstream via XML state") << endmsg;
3634 /** Connect things to the MMC object */
3636 Session::setup_midi_machine_control ()
3638 MIDI::MachineControl* mmc = MIDI::Manager::instance()->mmc ();
3640 mmc->Play.connect_same_thread (*this, boost::bind (&Session::mmc_deferred_play, this, _1));
3641 mmc->DeferredPlay.connect_same_thread (*this, boost::bind (&Session::mmc_deferred_play, this, _1));
3642 mmc->Stop.connect_same_thread (*this, boost::bind (&Session::mmc_stop, this, _1));
3643 mmc->FastForward.connect_same_thread (*this, boost::bind (&Session::mmc_fast_forward, this, _1));
3644 mmc->Rewind.connect_same_thread (*this, boost::bind (&Session::mmc_rewind, this, _1));
3645 mmc->Pause.connect_same_thread (*this, boost::bind (&Session::mmc_pause, this, _1));
3646 mmc->RecordPause.connect_same_thread (*this, boost::bind (&Session::mmc_record_pause, this, _1));
3647 mmc->RecordStrobe.connect_same_thread (*this, boost::bind (&Session::mmc_record_strobe, this, _1));
3648 mmc->RecordExit.connect_same_thread (*this, boost::bind (&Session::mmc_record_exit, this, _1));
3649 mmc->Locate.connect_same_thread (*this, boost::bind (&Session::mmc_locate, this, _1, _2));
3650 mmc->Step.connect_same_thread (*this, boost::bind (&Session::mmc_step, this, _1, _2));
3651 mmc->Shuttle.connect_same_thread (*this, boost::bind (&Session::mmc_shuttle, this, _1, _2, _3));
3652 mmc->TrackRecordStatusChange.connect_same_thread (*this, boost::bind (&Session::mmc_record_enable, this, _1, _2, _3));
3654 /* also handle MIDI SPP because its so common */
3656 mmc->SPPStart.connect_same_thread (*this, boost::bind (&Session::spp_start, this));
3657 mmc->SPPContinue.connect_same_thread (*this, boost::bind (&Session::spp_continue, this));
3658 mmc->SPPStop.connect_same_thread (*this, boost::bind (&Session::spp_stop, this));
3661 boost::shared_ptr<Controllable>
3662 Session::solo_cut_control() const
3664 /* the solo cut control is a bit of an anomaly, at least as of Febrary 2011. There are no other
3665 controls in Ardour that currently get presented to the user in the GUI that require
3666 access as a Controllable and are also NOT owned by some SessionObject (e.g. Route, or MonitorProcessor).
3668 its actually an RCConfiguration parameter, so we use a ProxyControllable to wrap
3669 it up as a Controllable. Changes to the Controllable will just map back to the RCConfiguration
3673 return _solo_cut_control;
3677 Session::rename (const std::string& new_name)
3679 string legal_name = legalize_for_path (new_name);
3685 string const old_sources_root = _session_dir->sources_root();
3687 #define RENAME ::rename
3692 * interchange subdirectory
3696 * Backup files are left unchanged and not renamed.
3699 /* pass one: not 100% safe check that the new directory names don't
3703 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
3708 /* this is a stupid hack because Glib::path_get_dirname() is
3709 * lexical-only, and so passing it /a/b/c/ gives a different
3710 * result than passing it /a/b/c ...
3713 if (oldstr[oldstr.length()-1] == G_DIR_SEPARATOR) {
3714 oldstr = oldstr.substr (0, oldstr.length() - 1);
3717 string base = Glib::path_get_dirname (oldstr);
3718 string p = Glib::path_get_basename (oldstr);
3720 newstr = Glib::build_filename (base, legal_name);
3722 if (Glib::file_test (newstr, Glib::FILE_TEST_EXISTS)) {
3729 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
3734 /* this is a stupid hack because Glib::path_get_dirname() is
3735 * lexical-only, and so passing it /a/b/c/ gives a different
3736 * result than passing it /a/b/c ...
3739 if (oldstr[oldstr.length()-1] == G_DIR_SEPARATOR) {
3740 oldstr = oldstr.substr (0, oldstr.length() - 1);
3743 string base = Glib::path_get_dirname (oldstr);
3744 string p = Glib::path_get_basename (oldstr);
3746 newstr = Glib::build_filename (base, legal_name);
3748 cerr << "Rename " << oldstr << " => " << newstr << endl;
3750 if (RENAME (oldstr.c_str(), newstr.c_str()) != 0) {
3755 (*_session_dir) = newstr;
3760 /* directory below interchange */
3762 v.push_back (newstr);
3763 v.push_back (interchange_dir_name);
3766 oldstr = Glib::build_filename (v);
3769 v.push_back (newstr);
3770 v.push_back (interchange_dir_name);
3771 v.push_back (legal_name);
3773 newstr = Glib::build_filename (v);
3775 cerr << "Rename " << oldstr << " => " << newstr << endl;
3777 if (RENAME (oldstr.c_str(), newstr.c_str()) != 0) {
3784 oldstr = Glib::build_filename (newpath, _current_snapshot_name) + statefile_suffix;
3785 newstr= Glib::build_filename (newpath, legal_name) + statefile_suffix;
3787 cerr << "Rename " << oldstr << " => " << newstr << endl;
3789 if (RENAME (oldstr.c_str(), newstr.c_str()) != 0) {
3796 oldstr = Glib::build_filename (newpath, _current_snapshot_name) + history_suffix;
3798 if (Glib::file_test (oldstr, Glib::FILE_TEST_EXISTS)) {
3799 newstr = Glib::build_filename (newpath, legal_name) + history_suffix;
3801 cerr << "Rename " << oldstr << " => " << newstr << endl;
3803 if (RENAME (oldstr.c_str(), newstr.c_str()) != 0) {
3808 /* update file source paths */
3810 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ++i) {
3811 boost::shared_ptr<FileSource> fs = boost::dynamic_pointer_cast<FileSource> (i->second);
3813 string p = fs->path ();
3814 boost::replace_all (p, old_sources_root, _session_dir->sources_root());
3819 /* remove old name from recent sessions */
3821 remove_recent_sessions (_path);
3824 _current_snapshot_name = new_name;
3829 /* save state again to get everything just right */
3831 save_state (_current_snapshot_name);
3834 /* add to recent sessions */
3836 store_recent_sessions (new_name, _path);