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>
56 #include <glibmm/thread.h>
58 #include <boost/algorithm/string.hpp>
60 #include "midi++/mmc.h"
61 #include "midi++/port.h"
62 #include "midi++/manager.h"
64 #include "evoral/SMF.hpp"
66 #include "pbd/boost_debug.h"
67 #include "pbd/basename.h"
68 #include "pbd/controllable_descriptor.h"
69 #include "pbd/enumwriter.h"
70 #include "pbd/error.h"
71 #include "pbd/pathscanner.h"
72 #include "pbd/pthread_utils.h"
73 #include "pbd/search_path.h"
74 #include "pbd/stacktrace.h"
75 #include "pbd/convert.h"
76 #include "pbd/clear_dir.h"
78 #include "ardour/amp.h"
79 #include "ardour/audio_diskstream.h"
80 #include "ardour/audio_track.h"
81 #include "ardour/audioengine.h"
82 #include "ardour/audiofilesource.h"
83 #include "ardour/audioregion.h"
84 #include "ardour/automation_control.h"
85 #include "ardour/butler.h"
86 #include "ardour/control_protocol_manager.h"
87 #include "ardour/directory_names.h"
88 #include "ardour/filename_extensions.h"
89 #include "ardour/location.h"
90 #include "ardour/midi_model.h"
91 #include "ardour/midi_patch_manager.h"
92 #include "ardour/midi_region.h"
93 #include "ardour/midi_source.h"
94 #include "ardour/midi_track.h"
95 #include "ardour/named_selection.h"
96 #include "ardour/pannable.h"
97 #include "ardour/playlist_factory.h"
98 #include "ardour/port.h"
99 #include "ardour/processor.h"
100 #include "ardour/proxy_controllable.h"
101 #include "ardour/recent_sessions.h"
102 #include "ardour/region_factory.h"
103 #include "ardour/route_group.h"
104 #include "ardour/send.h"
105 #include "ardour/session.h"
106 #include "ardour/session_directory.h"
107 #include "ardour/session_metadata.h"
108 #include "ardour/session_playlists.h"
109 #include "ardour/session_state_utils.h"
110 #include "ardour/session_utils.h"
111 #include "ardour/silentfilesource.h"
112 #include "ardour/sndfilesource.h"
113 #include "ardour/source_factory.h"
114 #include "ardour/speakers.h"
115 #include "ardour/template_utils.h"
116 #include "ardour/tempo.h"
117 #include "ardour/ticker.h"
118 #include "ardour/user_bundle.h"
120 #include "control_protocol/control_protocol.h"
126 using namespace ARDOUR;
129 /** @param snapshot_name Snapshot name, without the .ardour prefix */
131 Session::first_stage_init (string fullpath, string snapshot_name)
133 if (fullpath.length() == 0) {
135 throw failed_constructor();
138 char buf[PATH_MAX+1];
139 if (!realpath (fullpath.c_str(), buf) && (errno != ENOENT)) {
140 error << string_compose(_("Could not use path %1 (%s)"), buf, strerror(errno)) << endmsg;
142 throw failed_constructor();
147 if (_path[_path.length()-1] != G_DIR_SEPARATOR) {
148 _path += G_DIR_SEPARATOR;
151 /* these two are just provisional settings. set_state()
152 will likely override them.
155 _name = _current_snapshot_name = snapshot_name;
157 set_history_depth (Config->get_history_depth());
159 _current_frame_rate = _engine.frame_rate ();
160 _nominal_frame_rate = _current_frame_rate;
161 _base_frame_rate = _current_frame_rate;
163 _tempo_map = new TempoMap (_current_frame_rate);
164 _tempo_map->PropertyChanged.connect_same_thread (*this, boost::bind (&Session::tempo_map_changed, this, _1));
167 _non_soloed_outs_muted = false;
169 _solo_isolated_cnt = 0;
170 g_atomic_int_set (&processing_prohibited, 0);
171 _transport_speed = 0;
172 _default_transport_speed = 1.0;
173 _last_transport_speed = 0;
174 _target_transport_speed = 0;
175 auto_play_legal = false;
176 transport_sub_state = 0;
177 _transport_frame = 0;
178 _requested_return_frame = -1;
179 _session_range_location = 0;
180 g_atomic_int_set (&_record_status, Disabled);
181 loop_changing = false;
184 _last_roll_location = 0;
185 _last_roll_or_reversal_location = 0;
186 _last_record_location = 0;
187 pending_locate_frame = 0;
188 pending_locate_roll = false;
189 pending_locate_flush = false;
190 state_was_pending = false;
192 outbound_mtc_timecode_frame = 0;
193 next_quarter_frame_to_send = -1;
194 current_block_size = 0;
195 solo_update_disabled = false;
196 _have_captured = false;
197 _worst_output_latency = 0;
198 _worst_input_latency = 0;
199 _worst_track_latency = 0;
200 _state_of_the_state = StateOfTheState(CannotSave|InitialConnecting|Loading);
201 _was_seamless = Config->get_seamless_loop ();
203 _send_qf_mtc = false;
204 _pframes_since_last_mtc = 0;
205 g_atomic_int_set (&_playback_load, 100);
206 g_atomic_int_set (&_capture_load, 100);
209 pending_abort = false;
210 destructive_index = 0;
211 first_file_data_format_reset = true;
212 first_file_header_format_reset = true;
213 post_export_sync = false;
216 no_questions_about_missing_files = false;
217 _speakers.reset (new Speakers);
219 ignore_route_processor_changes = false;
220 _pre_export_mmc_enabled = false;
222 AudioDiskstream::allocate_working_buffers();
224 /* default short fade = 15ms */
226 SndFileSource::setup_standard_crossfades (*this, frame_rate());
228 last_mmc_step.tv_sec = 0;
229 last_mmc_step.tv_usec = 0;
232 /* click sounds are unset by default, which causes us to internal
233 waveforms for clicks.
237 click_emphasis_length = 0;
240 process_function = &Session::process_with_events;
242 if (config.get_use_video_sync()) {
243 waiting_for_sync_offset = true;
245 waiting_for_sync_offset = false;
248 last_timecode_when = 0;
249 last_timecode_valid = false;
253 last_rr_session_dir = session_dirs.begin();
254 refresh_disk_space ();
256 /* default: assume simple stereo speaker configuration */
258 _speakers->setup_default_speakers (2);
262 average_slave_delta = 1800; // !!! why 1800 ????
263 have_first_delta_accumulator = false;
264 delta_accumulator_cnt = 0;
265 _slave_state = Stopped;
267 _solo_cut_control.reset (new ProxyControllable (_("solo cut control (dB)"), PBD::Controllable::GainLike,
268 boost::bind (&RCConfiguration::set_solo_mute_gain, Config, _1),
269 boost::bind (&RCConfiguration::get_solo_mute_gain, Config)));
270 add_controllable (_solo_cut_control);
272 _engine.GraphReordered.connect_same_thread (*this, boost::bind (&Session::graph_reordered, this));
274 /* These are all static "per-class" signals */
276 SourceFactory::SourceCreated.connect_same_thread (*this, boost::bind (&Session::add_source, this, _1));
277 PlaylistFactory::PlaylistCreated.connect_same_thread (*this, boost::bind (&Session::add_playlist, this, _1, _2));
278 AutomationList::AutomationListCreated.connect_same_thread (*this, boost::bind (&Session::add_automation_list, this, _1));
279 Controllable::Destroyed.connect_same_thread (*this, boost::bind (&Session::remove_controllable, this, _1));
280 IO::PortCountChanged.connect_same_thread (*this, boost::bind (&Session::ensure_buffers, this, _1));
282 /* stop IO objects from doing stuff until we're ready for them */
284 Delivery::disable_panners ();
285 IO::disable_connecting ();
289 Session::second_stage_init ()
291 AudioFileSource::set_peak_dir (_session_dir->peak_path());
294 if (load_state (_current_snapshot_name)) {
299 if (_butler->start_thread()) {
303 if (start_midi_thread ()) {
307 setup_midi_machine_control ();
309 // set_state() will call setup_raid_path(), but if it's a new session we need
310 // to call setup_raid_path() here.
313 if (set_state (*state_tree->root(), Stateful::loading_state_version)) {
317 setup_raid_path(_path);
320 /* we can't save till after ::when_engine_running() is called,
321 because otherwise we save state with no connections made.
322 therefore, we reset _state_of_the_state because ::set_state()
323 will have cleared it.
325 we also have to include Loading so that any events that get
326 generated between here and the end of ::when_engine_running()
327 will be processed directly rather than queued.
330 _state_of_the_state = StateOfTheState (_state_of_the_state|CannotSave|Loading);
332 _locations->changed.connect_same_thread (*this, boost::bind (&Session::locations_changed, this));
333 _locations->added.connect_same_thread (*this, boost::bind (&Session::locations_added, this, _1));
334 setup_click_sounds (0);
335 setup_midi_control ();
337 /* Pay attention ... */
339 _engine.Halted.connect_same_thread (*this, boost::bind (&Session::engine_halted, this));
340 _engine.Xrun.connect_same_thread (*this, boost::bind (&Session::xrun_recovery, this));
342 midi_clock = new MidiClockTicker ();
343 midi_clock->set_session (this);
346 when_engine_running ();
349 /* handle this one in a different way than all others, so that its clear what happened */
351 catch (AudioEngine::PortRegistrationFailure& err) {
352 error << err.what() << endmsg;
360 BootMessage (_("Reset Remote Controls"));
362 send_full_time_code (0);
363 _engine.transport_locate (0);
365 MIDI::Manager::instance()->mmc()->send (MIDI::MachineControlCommand (MIDI::MachineControl::cmdMmcReset));
366 MIDI::Manager::instance()->mmc()->send (MIDI::MachineControlCommand (Timecode::Time ()));
368 MIDI::Name::MidiPatchManager::instance().set_session (this);
370 /* initial program change will be delivered later; see ::config_changed() */
372 _state_of_the_state = Clean;
374 Port::set_connecting_blocked (false);
376 DirtyChanged (); /* EMIT SIGNAL */
378 if (state_was_pending) {
379 save_state (_current_snapshot_name);
380 remove_pending_capture_state ();
381 state_was_pending = false;
384 BootMessage (_("Session loading complete"));
390 Session::raid_path () const
392 SearchPath raid_search_path;
394 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
395 raid_search_path += (*i).path;
398 return raid_search_path.to_string ();
402 Session::setup_raid_path (string path)
411 session_dirs.clear ();
413 SearchPath search_path(path);
414 SearchPath sound_search_path;
415 SearchPath midi_search_path;
417 for (SearchPath::const_iterator i = search_path.begin(); i != search_path.end(); ++i) {
419 sp.blocks = 0; // not needed
420 session_dirs.push_back (sp);
422 SessionDirectory sdir(sp.path);
424 sound_search_path += sdir.sound_path ();
425 midi_search_path += sdir.midi_path ();
428 // reset the round-robin soundfile path thingie
429 last_rr_session_dir = session_dirs.begin();
433 Session::path_is_within_session (const std::string& path)
435 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
436 if (PBD::sys::path_is_within (i->path, path)) {
444 Session::ensure_subdirs ()
448 dir = session_directory().peak_path();
450 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
451 error << string_compose(_("Session: cannot create session peakfile folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
455 dir = session_directory().sound_path();
457 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
458 error << string_compose(_("Session: cannot create session sounds dir \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
462 dir = session_directory().midi_path();
464 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
465 error << string_compose(_("Session: cannot create session midi dir \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
469 dir = session_directory().dead_path();
471 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
472 error << string_compose(_("Session: cannot create session dead sounds folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
476 dir = session_directory().export_path();
478 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
479 error << string_compose(_("Session: cannot create session export folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
483 dir = analysis_dir ();
485 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
486 error << string_compose(_("Session: cannot create session analysis folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
490 dir = plugins_dir ();
492 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
493 error << string_compose(_("Session: cannot create session plugins folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
497 dir = externals_dir ();
499 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
500 error << string_compose(_("Session: cannot create session externals folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
507 /** @param session_template directory containing session template, or empty.
508 * Caller must not hold process lock.
511 Session::create (const string& session_template, BusProfile* bus_profile)
513 if (g_mkdir_with_parents (_path.c_str(), 0755) < 0) {
514 error << string_compose(_("Session: cannot create session folder \"%1\" (%2)"), _path, strerror (errno)) << endmsg;
518 if (ensure_subdirs ()) {
522 _writable = exists_and_writable (sys::path (_path));
524 if (!session_template.empty()) {
525 std::string in_path = session_template_dir_to_file (session_template);
527 ifstream in(in_path.c_str());
530 string out_path = _path;
532 out_path += statefile_suffix;
534 ofstream out(out_path.c_str());
540 /* Copy plugin state files from template to new session */
541 sys::path template_plugins = session_template;
542 template_plugins /= X_("plugins");
543 sys::copy_files (template_plugins, plugins_dir ());
548 error << string_compose (_("Could not open %1 for writing session template"), out_path)
554 error << string_compose (_("Could not open session template %1 for reading"), in_path)
561 /* set initial start + end point */
563 _state_of_the_state = Clean;
565 /* set up Master Out and Control Out if necessary */
570 ChanCount count(DataType::AUDIO, bus_profile->master_out_channels);
572 if (bus_profile->master_out_channels) {
573 boost::shared_ptr<Route> r (new Route (*this, _("master"), Route::MasterOut, DataType::AUDIO));
577 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
578 // boost_debug_shared_ptr_mark_interesting (r.get(), "Route");
581 Glib::Mutex::Lock lm (AudioEngine::instance()->process_lock ());
582 r->input()->ensure_io (count, false, this);
583 r->output()->ensure_io (count, false, this);
589 /* prohibit auto-connect to master, because there isn't one */
590 bus_profile->output_ac = AutoConnectOption (bus_profile->output_ac & ~AutoConnectMaster);
594 add_routes (rl, false, false, false);
597 /* this allows the user to override settings with an environment variable.
600 if (no_auto_connect()) {
601 bus_profile->input_ac = AutoConnectOption (0);
602 bus_profile->output_ac = AutoConnectOption (0);
605 Config->set_input_auto_connect (bus_profile->input_ac);
606 Config->set_output_auto_connect (bus_profile->output_ac);
609 if (Config->get_use_monitor_bus() && bus_profile) {
610 add_monitor_section ();
619 Session::maybe_write_autosave()
621 if (dirty() && record_status() != Recording) {
622 save_state("", true);
627 Session::remove_pending_capture_state ()
629 sys::path pending_state_file_path(_session_dir->root_path());
631 pending_state_file_path /= legalize_for_path (_current_snapshot_name) + pending_suffix;
635 sys::remove (pending_state_file_path);
637 catch(sys::filesystem_error& ex)
639 error << string_compose(_("Could remove pending capture state at path \"%1\" (%2)"),
640 pending_state_file_path.to_string(), ex.what()) << endmsg;
644 /** Rename a state file.
645 * @param old_name Old snapshot name.
646 * @param new_name New snapshot name.
649 Session::rename_state (string old_name, string new_name)
651 if (old_name == _current_snapshot_name || old_name == _name) {
652 /* refuse to rename the current snapshot or the "main" one */
656 const string old_xml_filename = legalize_for_path (old_name) + statefile_suffix;
657 const string new_xml_filename = legalize_for_path (new_name) + statefile_suffix;
659 const sys::path old_xml_path(Glib::build_filename (_session_dir->root_path(), old_xml_filename));
660 const sys::path new_xml_path(Glib::build_filename (_session_dir->root_path(), new_xml_filename));
664 sys::rename (old_xml_path, new_xml_path);
666 catch (const sys::filesystem_error& err)
668 error << string_compose(_("could not rename snapshot %1 to %2 (%3)"),
669 old_name, new_name, err.what()) << endmsg;
673 /** Remove a state file.
674 * @param snapshot_name Snapshot name.
677 Session::remove_state (string snapshot_name)
679 if (!_writable || snapshot_name == _current_snapshot_name || snapshot_name == _name) {
680 // refuse to remove the current snapshot or the "main" one
684 std::string xml_path(_session_dir->root_path());
686 xml_path = Glib::build_filename (xml_path, legalize_for_path (snapshot_name) + statefile_suffix);
688 if (!create_backup_file (xml_path)) {
689 // don't remove it if a backup can't be made
690 // create_backup_file will log the error.
695 sys::remove (xml_path);
698 #ifdef HAVE_JACK_SESSION
700 Session::jack_session_event (jack_session_event_t * event)
704 struct tm local_time;
707 localtime_r (&n, &local_time);
708 strftime (timebuf, sizeof(timebuf), "JS_%FT%T", &local_time);
710 if (event->type == JackSessionSaveTemplate)
712 if (save_template( timebuf )) {
713 event->flags = JackSessionSaveError;
715 string cmd ("ardour3 -P -U ");
716 cmd += event->client_uuid;
720 event->command_line = strdup (cmd.c_str());
725 if (save_state (timebuf)) {
726 event->flags = JackSessionSaveError;
728 sys::path xml_path (_session_dir->root_path());
729 xml_path /= legalize_for_path (timebuf) + statefile_suffix;
731 string cmd ("ardour3 -P -U ");
732 cmd += event->client_uuid;
734 cmd += xml_path.to_string();
737 event->command_line = strdup (cmd.c_str());
741 jack_session_reply (_engine.jack(), event);
743 if (event->type == JackSessionSaveAndQuit) {
744 Quit (); /* EMIT SIGNAL */
747 jack_session_event_free( event );
751 /** @param snapshot_name Name to save under, without .ardour / .pending prefix */
753 Session::save_state (string snapshot_name, bool pending, bool switch_to_snapshot)
756 std::string xml_path(_session_dir->root_path());
758 if (!_writable || (_state_of_the_state & CannotSave)) {
762 if (!_engine.connected ()) {
763 error << string_compose (_("the %1 audio engine is not connected and state saving would lose all I/O connections. Session not saved"),
769 /* tell sources we're saving first, in case they write out to a new file
770 * which should be saved with the state rather than the old one */
771 for (SourceMap::const_iterator i = sources.begin(); i != sources.end(); ++i) {
773 i->second->session_saved();
774 } catch (Evoral::SMF::FileError& e) {
775 error << string_compose ("Could not write to MIDI file %1; MIDI data not saved.", e.file_name ()) << endmsg;
779 tree.set_root (&get_state());
781 if (snapshot_name.empty()) {
782 snapshot_name = _current_snapshot_name;
783 } else if (switch_to_snapshot) {
784 _current_snapshot_name = snapshot_name;
789 /* proper save: use statefile_suffix (.ardour in English) */
791 xml_path = Glib::build_filename (xml_path, legalize_for_path (snapshot_name) + statefile_suffix);
793 /* make a backup copy of the old file */
795 if (sys::exists(xml_path) && !create_backup_file (xml_path)) {
796 // create_backup_file will log the error
802 /* pending save: use pending_suffix (.pending in English) */
803 xml_path = Glib::build_filename (xml_path, legalize_for_path (snapshot_name) + pending_suffix);
806 sys::path tmp_path(_session_dir->root_path());
808 tmp_path /= legalize_for_path (snapshot_name) + temp_suffix;
810 // cerr << "actually writing state to " << xml_path.to_string() << endl;
812 if (!tree.write (tmp_path.to_string())) {
813 error << string_compose (_("state could not be saved to %1"), tmp_path.to_string()) << endmsg;
814 sys::remove (tmp_path);
819 if (::rename (tmp_path.to_string().c_str(), xml_path.c_str()) != 0) {
820 error << string_compose (_("could not rename temporary session file %1 to %2"),
821 tmp_path.to_string(), xml_path) << endmsg;
822 sys::remove (tmp_path);
829 save_history (snapshot_name);
831 bool was_dirty = dirty();
833 _state_of_the_state = StateOfTheState (_state_of_the_state & ~Dirty);
836 DirtyChanged (); /* EMIT SIGNAL */
839 StateSaved (snapshot_name); /* EMIT SIGNAL */
846 Session::restore_state (string snapshot_name)
848 if (load_state (snapshot_name) == 0) {
849 set_state (*state_tree->root(), Stateful::loading_state_version);
856 Session::load_state (string snapshot_name)
861 state_was_pending = false;
863 /* check for leftover pending state from a crashed capture attempt */
865 sys::path xmlpath(_session_dir->root_path());
866 xmlpath /= legalize_for_path (snapshot_name) + pending_suffix;
868 if (sys::exists (xmlpath)) {
870 /* there is pending state from a crashed capture attempt */
872 boost::optional<int> r = AskAboutPendingState();
873 if (r.get_value_or (1)) {
874 state_was_pending = true;
878 if (!state_was_pending) {
879 xmlpath = _session_dir->root_path();
880 xmlpath /= snapshot_name;
883 if (!sys::exists (xmlpath)) {
884 xmlpath = _session_dir->root_path();
885 xmlpath /= legalize_for_path (snapshot_name) + statefile_suffix;
886 if (!sys::exists (xmlpath)) {
887 error << string_compose(_("%1: session state information file \"%2\" doesn't exist!"), _name, xmlpath.to_string()) << endmsg;
892 state_tree = new XMLTree;
896 _writable = exists_and_writable (xmlpath);
898 if (!state_tree->read (xmlpath.to_string())) {
899 error << string_compose(_("Could not understand ardour file %1"), xmlpath.to_string()) << endmsg;
905 XMLNode& root (*state_tree->root());
907 if (root.name() != X_("Session")) {
908 error << string_compose (_("Session file %1 is not a session"), xmlpath.to_string()) << endmsg;
914 const XMLProperty* prop;
916 if ((prop = root.property ("version")) == 0) {
917 /* no version implies very old version of Ardour */
918 Stateful::loading_state_version = 1000;
920 if (prop->value().find ('.') != string::npos) {
921 /* old school version format */
922 if (prop->value()[0] == '2') {
923 Stateful::loading_state_version = 2000;
925 Stateful::loading_state_version = 3000;
928 Stateful::loading_state_version = atoi (prop->value());
932 if (Stateful::loading_state_version < CURRENT_SESSION_FILE_VERSION && _writable) {
934 sys::path backup_path(_session_dir->root_path());
936 backup_path /= string_compose ("%1-%2%3", legalize_for_path (snapshot_name), Stateful::loading_state_version, statefile_suffix);
938 // only create a backup for a given statefile version once
940 if (!sys::exists (backup_path)) {
942 info << string_compose (_("Copying old session file %1 to %2\nUse %2 with %3 versions before 2.0 from now on"),
943 xmlpath.to_string(), backup_path.to_string(), PROGRAM_NAME)
947 sys::copy_file (xmlpath, backup_path);
949 } catch (sys::filesystem_error& ex) {
951 error << string_compose (_("Unable to make backup of state file %1 (%2)"),
952 xmlpath.to_string(), ex.what())
963 Session::load_options (const XMLNode& node)
965 LocaleGuard lg (X_("POSIX"));
966 config.set_variables (node);
977 Session::get_template()
979 /* if we don't disable rec-enable, diskstreams
980 will believe they need to store their capture
981 sources in their state node.
984 disable_record (false);
990 Session::state (bool full_state)
992 XMLNode* node = new XMLNode("Session");
996 snprintf(buf, sizeof(buf), "%d", CURRENT_SESSION_FILE_VERSION);
997 node->add_property("version", buf);
999 /* store configuration settings */
1003 node->add_property ("name", _name);
1004 snprintf (buf, sizeof (buf), "%" PRId64, _nominal_frame_rate);
1005 node->add_property ("sample-rate", buf);
1007 if (session_dirs.size() > 1) {
1011 vector<space_and_path>::iterator i = session_dirs.begin();
1012 vector<space_and_path>::iterator next;
1014 ++i; /* skip the first one */
1018 while (i != session_dirs.end()) {
1022 if (next != session_dirs.end()) {
1032 child = node->add_child ("Path");
1033 child->add_content (p);
1037 /* save the ID counter */
1039 snprintf (buf, sizeof (buf), "%" PRIu64, ID::counter());
1040 node->add_property ("id-counter", buf);
1042 /* save the event ID counter */
1044 snprintf (buf, sizeof (buf), "%d", Evoral::event_id_counter());
1045 node->add_property ("event-counter", buf);
1047 /* various options */
1049 node->add_child_nocopy (config.get_variables ());
1051 node->add_child_nocopy (ARDOUR::SessionMetadata::Metadata()->get_state());
1053 child = node->add_child ("Sources");
1056 Glib::Mutex::Lock sl (source_lock);
1058 for (SourceMap::iterator siter = sources.begin(); siter != sources.end(); ++siter) {
1060 /* Don't save information about non-file Sources, or
1061 * about non-destructive file sources that are empty
1062 * and unused by any regions.
1065 boost::shared_ptr<FileSource> fs;
1067 if ((fs = boost::dynamic_pointer_cast<FileSource> (siter->second)) != 0) {
1069 if (!fs->destructive()) {
1070 if (fs->empty() && !fs->used()) {
1075 child->add_child_nocopy (siter->second->get_state());
1080 child = node->add_child ("Regions");
1083 Glib::Mutex::Lock rl (region_lock);
1084 const RegionFactory::RegionMap& region_map (RegionFactory::all_regions());
1085 for (RegionFactory::RegionMap::const_iterator i = region_map.begin(); i != region_map.end(); ++i) {
1086 boost::shared_ptr<Region> r = i->second;
1087 /* only store regions not attached to playlists */
1088 if (r->playlist() == 0) {
1089 child->add_child_nocopy (r->state ());
1093 RegionFactory::CompoundAssociations& cassocs (RegionFactory::compound_associations());
1095 if (!cassocs.empty()) {
1096 XMLNode* ca = node->add_child (X_("CompoundAssociations"));
1098 for (RegionFactory::CompoundAssociations::iterator i = cassocs.begin(); i != cassocs.end(); ++i) {
1100 XMLNode* can = new XMLNode (X_("CompoundAssociation"));
1101 i->first->id().print (buf, sizeof (buf));
1102 can->add_property (X_("copy"), buf);
1103 i->second->id().print (buf, sizeof (buf));
1104 can->add_property (X_("original"), buf);
1105 ca->add_child_nocopy (*can);
1111 node->add_child_nocopy (_locations->get_state());
1113 // for a template, just create a new Locations, populate it
1114 // with the default start and end, and get the state for that.
1115 Locations loc (*this);
1116 Location* range = new Location (*this, 0, 0, _("session"), Location::IsSessionRange);
1117 range->set (max_framepos, 0);
1119 node->add_child_nocopy (loc.get_state());
1122 child = node->add_child ("Bundles");
1124 boost::shared_ptr<BundleList> bundles = _bundles.reader ();
1125 for (BundleList::iterator i = bundles->begin(); i != bundles->end(); ++i) {
1126 boost::shared_ptr<UserBundle> b = boost::dynamic_pointer_cast<UserBundle> (*i);
1128 child->add_child_nocopy (b->get_state());
1133 child = node->add_child ("Routes");
1135 boost::shared_ptr<RouteList> r = routes.reader ();
1137 RoutePublicOrderSorter cmp;
1138 RouteList public_order (*r);
1139 public_order.sort (cmp);
1141 /* the sort should have put control outs first */
1144 assert (_monitor_out == public_order.front());
1147 for (RouteList::iterator i = public_order.begin(); i != public_order.end(); ++i) {
1148 if (!(*i)->is_hidden()) {
1150 child->add_child_nocopy ((*i)->get_state());
1152 child->add_child_nocopy ((*i)->get_template());
1158 playlists->add_state (node, full_state);
1160 child = node->add_child ("RouteGroups");
1161 for (list<RouteGroup *>::iterator i = _route_groups.begin(); i != _route_groups.end(); ++i) {
1162 child->add_child_nocopy ((*i)->get_state());
1166 XMLNode* gain_child = node->add_child ("Click");
1167 gain_child->add_child_nocopy (_click_io->state (full_state));
1168 gain_child->add_child_nocopy (_click_gain->state (full_state));
1172 XMLNode* ns_child = node->add_child ("NamedSelections");
1173 for (NamedSelectionList::iterator i = named_selections.begin(); i != named_selections.end(); ++i) {
1175 ns_child->add_child_nocopy ((*i)->get_state());
1180 node->add_child_nocopy (_speakers->get_state());
1181 node->add_child_nocopy (_tempo_map->get_state());
1182 node->add_child_nocopy (get_control_protocol_state());
1185 node->add_child_copy (*_extra_xml);
1192 Session::get_control_protocol_state ()
1194 ControlProtocolManager& cpm (ControlProtocolManager::instance());
1195 return cpm.get_state();
1199 Session::set_state (const XMLNode& node, int version)
1203 const XMLProperty* prop;
1206 _state_of_the_state = StateOfTheState (_state_of_the_state|CannotSave);
1208 if (node.name() != X_("Session")) {
1209 fatal << _("programming error: Session: incorrect XML node sent to set_state()") << endmsg;
1213 if ((prop = node.property ("name")) != 0) {
1214 _name = prop->value ();
1217 if ((prop = node.property (X_("sample-rate"))) != 0) {
1219 _nominal_frame_rate = atoi (prop->value());
1221 if (_nominal_frame_rate != _current_frame_rate) {
1222 boost::optional<int> r = AskAboutSampleRateMismatch (_nominal_frame_rate, _current_frame_rate);
1223 if (r.get_value_or (0)) {
1229 setup_raid_path(_session_dir->root_path());
1231 if ((prop = node.property (X_("id-counter"))) != 0) {
1233 sscanf (prop->value().c_str(), "%" PRIu64, &x);
1234 ID::init_counter (x);
1236 /* old sessions used a timebased counter, so fake
1237 the startup ID counter based on a standard
1242 ID::init_counter (now);
1245 if ((prop = node.property (X_("event-counter"))) != 0) {
1246 Evoral::init_event_id_counter (atoi (prop->value()));
1249 IO::disable_connecting ();
1251 Stateful::save_extra_xml (node);
1253 if (((child = find_named_node (node, "Options")) != 0)) { /* old style */
1254 load_options (*child);
1255 } else if ((child = find_named_node (node, "Config")) != 0) { /* new style */
1256 load_options (*child);
1258 error << _("Session: XML state has no options section") << endmsg;
1261 if (version >= 3000) {
1262 if ((child = find_named_node (node, "Metadata")) == 0) {
1263 warning << _("Session: XML state has no metadata section") << endmsg;
1264 } else if ( ARDOUR::SessionMetadata::Metadata()->set_state (*child, version) ) {
1269 if ((child = find_named_node (node, X_("Speakers"))) != 0) {
1270 _speakers->set_state (*child, version);
1273 if ((child = find_named_node (node, "Sources")) == 0) {
1274 error << _("Session: XML state has no sources section") << endmsg;
1276 } else if (load_sources (*child)) {
1280 if ((child = find_named_node (node, "TempoMap")) == 0) {
1281 error << _("Session: XML state has no Tempo Map section") << endmsg;
1283 } else if (_tempo_map->set_state (*child, version)) {
1287 if ((child = find_named_node (node, "Locations")) == 0) {
1288 error << _("Session: XML state has no locations section") << endmsg;
1290 } else if (_locations->set_state (*child, version)) {
1296 if ((location = _locations->auto_loop_location()) != 0) {
1297 set_auto_loop_location (location);
1300 if ((location = _locations->auto_punch_location()) != 0) {
1301 set_auto_punch_location (location);
1304 if ((location = _locations->session_range_location()) != 0) {
1305 delete _session_range_location;
1306 _session_range_location = location;
1309 if (_session_range_location) {
1310 AudioFileSource::set_header_position_offset (_session_range_location->start());
1313 if ((child = find_named_node (node, "Regions")) == 0) {
1314 error << _("Session: XML state has no Regions section") << endmsg;
1316 } else if (load_regions (*child)) {
1320 if ((child = find_named_node (node, "Playlists")) == 0) {
1321 error << _("Session: XML state has no playlists section") << endmsg;
1323 } else if (playlists->load (*this, *child)) {
1327 if ((child = find_named_node (node, "UnusedPlaylists")) == 0) {
1329 } else if (playlists->load_unused (*this, *child)) {
1333 if ((child = find_named_node (node, "CompoundAssociations")) != 0) {
1334 if (load_compounds (*child)) {
1339 if ((child = find_named_node (node, "NamedSelections")) != 0) {
1340 if (load_named_selections (*child)) {
1345 if (version >= 3000) {
1346 if ((child = find_named_node (node, "Bundles")) == 0) {
1347 warning << _("Session: XML state has no bundles section") << endmsg;
1350 /* We can't load Bundles yet as they need to be able
1351 to convert from port names to Port objects, which can't happen until
1353 _bundle_xml_node = new XMLNode (*child);
1357 if (version < 3000) {
1358 if ((child = find_named_node (node, X_("DiskStreams"))) == 0) {
1359 error << _("Session: XML state has no diskstreams section") << endmsg;
1361 } else if (load_diskstreams_2X (*child, version)) {
1366 if ((child = find_named_node (node, "Routes")) == 0) {
1367 error << _("Session: XML state has no routes section") << endmsg;
1369 } else if (load_routes (*child, version)) {
1373 /* our diskstreams list is no longer needed as they are now all owned by their Route */
1374 _diskstreams_2X.clear ();
1376 if (version >= 3000) {
1378 if ((child = find_named_node (node, "RouteGroups")) == 0) {
1379 error << _("Session: XML state has no route groups section") << endmsg;
1381 } else if (load_route_groups (*child, version)) {
1385 } else if (version < 3000) {
1387 if ((child = find_named_node (node, "EditGroups")) == 0) {
1388 error << _("Session: XML state has no edit groups section") << endmsg;
1390 } else if (load_route_groups (*child, version)) {
1394 if ((child = find_named_node (node, "MixGroups")) == 0) {
1395 error << _("Session: XML state has no mix groups section") << endmsg;
1397 } else if (load_route_groups (*child, version)) {
1402 if ((child = find_named_node (node, "Click")) == 0) {
1403 warning << _("Session: XML state has no click section") << endmsg;
1404 } else if (_click_io) {
1405 const XMLNodeList& children (child->children());
1406 XMLNodeList::const_iterator i = children.begin();
1407 _click_io->set_state (**i, version);
1409 if (i != children.end()) {
1410 _click_gain->set_state (**i, version);
1414 if ((child = find_named_node (node, "ControlProtocols")) != 0) {
1415 ControlProtocolManager::instance().set_protocol_states (*child);
1418 update_have_rec_enabled_track ();
1420 /* here beginneth the second phase ... */
1422 StateReady (); /* EMIT SIGNAL */
1431 Session::load_routes (const XMLNode& node, int version)
1434 XMLNodeConstIterator niter;
1435 RouteList new_routes;
1437 nlist = node.children();
1441 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1443 boost::shared_ptr<Route> route;
1444 if (version < 3000) {
1445 route = XMLRouteFactory_2X (**niter, version);
1447 route = XMLRouteFactory (**niter, version);
1451 error << _("Session: cannot create Route from XML description.") << endmsg;
1455 BootMessage (string_compose (_("Loaded track/bus %1"), route->name()));
1457 new_routes.push_back (route);
1460 add_routes (new_routes, false, false, false);
1465 boost::shared_ptr<Route>
1466 Session::XMLRouteFactory (const XMLNode& node, int version)
1468 boost::shared_ptr<Route> ret;
1470 if (node.name() != "Route") {
1474 XMLNode* ds_child = find_named_node (node, X_("Diskstream"));
1476 DataType type = DataType::AUDIO;
1477 const XMLProperty* prop = node.property("default-type");
1480 type = DataType (prop->value());
1483 assert (type != DataType::NIL);
1487 boost::shared_ptr<Track> track;
1489 if (type == DataType::AUDIO) {
1490 track.reset (new AudioTrack (*this, X_("toBeResetFroXML")));
1492 track.reset (new MidiTrack (*this, X_("toBeResetFroXML")));
1495 if (track->init()) {
1499 if (track->set_state (node, version)) {
1503 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
1504 // boost_debug_shared_ptr_mark_interesting (track.get(), "Track");
1509 boost::shared_ptr<Route> r (new Route (*this, X_("toBeResetFroXML")));
1511 if (r->init () == 0 && r->set_state (node, version) == 0) {
1512 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
1513 // boost_debug_shared_ptr_mark_interesting (r.get(), "Route");
1522 boost::shared_ptr<Route>
1523 Session::XMLRouteFactory_2X (const XMLNode& node, int version)
1525 boost::shared_ptr<Route> ret;
1527 if (node.name() != "Route") {
1531 XMLProperty const * ds_prop = node.property (X_("diskstream-id"));
1533 ds_prop = node.property (X_("diskstream"));
1536 DataType type = DataType::AUDIO;
1537 const XMLProperty* prop = node.property("default-type");
1540 type = DataType (prop->value());
1543 assert (type != DataType::NIL);
1547 list<boost::shared_ptr<Diskstream> >::iterator i = _diskstreams_2X.begin ();
1548 while (i != _diskstreams_2X.end() && (*i)->id() != ds_prop->value()) {
1552 if (i == _diskstreams_2X.end()) {
1553 error << _("Could not find diskstream for route") << endmsg;
1554 return boost::shared_ptr<Route> ();
1557 boost::shared_ptr<Track> track;
1559 if (type == DataType::AUDIO) {
1560 track.reset (new AudioTrack (*this, X_("toBeResetFroXML")));
1562 track.reset (new MidiTrack (*this, X_("toBeResetFroXML")));
1565 if (track->init()) {
1569 if (track->set_state (node, version)) {
1573 track->set_diskstream (*i);
1575 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
1576 // boost_debug_shared_ptr_mark_interesting (track.get(), "Track");
1581 boost::shared_ptr<Route> r (new Route (*this, X_("toBeResetFroXML")));
1583 if (r->init () == 0 && r->set_state (node, version) == 0) {
1584 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
1585 // boost_debug_shared_ptr_mark_interesting (r.get(), "Route");
1595 Session::load_regions (const XMLNode& node)
1598 XMLNodeConstIterator niter;
1599 boost::shared_ptr<Region> region;
1601 nlist = node.children();
1605 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1606 if ((region = XMLRegionFactory (**niter, false)) == 0) {
1607 error << _("Session: cannot create Region from XML description.");
1608 const XMLProperty *name = (**niter).property("name");
1611 error << " " << string_compose (_("Can not load state for region '%1'"), name->value());
1622 Session::load_compounds (const XMLNode& node)
1624 XMLNodeList calist = node.children();
1625 XMLNodeConstIterator caiter;
1626 XMLProperty *caprop;
1628 for (caiter = calist.begin(); caiter != calist.end(); ++caiter) {
1629 XMLNode* ca = *caiter;
1633 if ((caprop = ca->property (X_("original"))) == 0) {
1636 orig_id = caprop->value();
1638 if ((caprop = ca->property (X_("copy"))) == 0) {
1641 copy_id = caprop->value();
1643 boost::shared_ptr<Region> orig = RegionFactory::region_by_id (orig_id);
1644 boost::shared_ptr<Region> copy = RegionFactory::region_by_id (copy_id);
1646 if (!orig || !copy) {
1647 warning << string_compose (_("Regions in compound description not found (ID's %1 and %2): ignored"),
1653 RegionFactory::add_compound_association (orig, copy);
1660 Session::load_nested_sources (const XMLNode& node)
1663 XMLNodeConstIterator niter;
1665 nlist = node.children();
1667 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1668 if ((*niter)->name() == "Source") {
1670 /* it may already exist, so don't recreate it unnecessarily
1673 XMLProperty* prop = (*niter)->property (X_("id"));
1675 error << _("Nested source has no ID info in session state file! (ignored)") << endmsg;
1679 ID source_id (prop->value());
1681 if (!source_by_id (source_id)) {
1684 SourceFactory::create (*this, **niter, true);
1686 catch (failed_constructor& err) {
1687 error << string_compose (_("Cannot reconstruct nested source for region %1"), name()) << endmsg;
1694 boost::shared_ptr<Region>
1695 Session::XMLRegionFactory (const XMLNode& node, bool full)
1697 const XMLProperty* type = node.property("type");
1701 const XMLNodeList& nlist = node.children();
1703 for (XMLNodeConstIterator niter = nlist.begin(); niter != nlist.end(); ++niter) {
1704 XMLNode *child = (*niter);
1705 if (child->name() == "NestedSource") {
1706 load_nested_sources (*child);
1710 if (!type || type->value() == "audio") {
1711 return boost::shared_ptr<Region>(XMLAudioRegionFactory (node, full));
1712 } else if (type->value() == "midi") {
1713 return boost::shared_ptr<Region>(XMLMidiRegionFactory (node, full));
1716 } catch (failed_constructor& err) {
1717 return boost::shared_ptr<Region> ();
1720 return boost::shared_ptr<Region> ();
1723 boost::shared_ptr<AudioRegion>
1724 Session::XMLAudioRegionFactory (const XMLNode& node, bool /*full*/)
1726 const XMLProperty* prop;
1727 boost::shared_ptr<Source> source;
1728 boost::shared_ptr<AudioSource> as;
1730 SourceList master_sources;
1731 uint32_t nchans = 1;
1734 if (node.name() != X_("Region")) {
1735 return boost::shared_ptr<AudioRegion>();
1738 if ((prop = node.property (X_("channels"))) != 0) {
1739 nchans = atoi (prop->value().c_str());
1742 if ((prop = node.property ("name")) == 0) {
1743 cerr << "no name for this region\n";
1747 if ((prop = node.property (X_("source-0"))) == 0) {
1748 if ((prop = node.property ("source")) == 0) {
1749 error << _("Session: XMLNode describing a AudioRegion is incomplete (no source)") << endmsg;
1750 return boost::shared_ptr<AudioRegion>();
1754 PBD::ID s_id (prop->value());
1756 if ((source = source_by_id (s_id)) == 0) {
1757 error << string_compose(_("Session: XMLNode describing a AudioRegion references an unknown source id =%1"), s_id) << endmsg;
1758 return boost::shared_ptr<AudioRegion>();
1761 as = boost::dynamic_pointer_cast<AudioSource>(source);
1763 error << string_compose(_("Session: XMLNode describing a AudioRegion references a non-audio source id =%1"), s_id) << endmsg;
1764 return boost::shared_ptr<AudioRegion>();
1767 sources.push_back (as);
1769 /* pickup other channels */
1771 for (uint32_t n=1; n < nchans; ++n) {
1772 snprintf (buf, sizeof(buf), X_("source-%d"), n);
1773 if ((prop = node.property (buf)) != 0) {
1775 PBD::ID id2 (prop->value());
1777 if ((source = source_by_id (id2)) == 0) {
1778 error << string_compose(_("Session: XMLNode describing a AudioRegion references an unknown source id =%1"), id2) << endmsg;
1779 return boost::shared_ptr<AudioRegion>();
1782 as = boost::dynamic_pointer_cast<AudioSource>(source);
1784 error << string_compose(_("Session: XMLNode describing a AudioRegion references a non-audio source id =%1"), id2) << endmsg;
1785 return boost::shared_ptr<AudioRegion>();
1787 sources.push_back (as);
1791 for (uint32_t n = 0; n < nchans; ++n) {
1792 snprintf (buf, sizeof(buf), X_("master-source-%d"), n);
1793 if ((prop = node.property (buf)) != 0) {
1795 PBD::ID id2 (prop->value());
1797 if ((source = source_by_id (id2)) == 0) {
1798 error << string_compose(_("Session: XMLNode describing a AudioRegion references an unknown source id =%1"), id2) << endmsg;
1799 return boost::shared_ptr<AudioRegion>();
1802 as = boost::dynamic_pointer_cast<AudioSource>(source);
1804 error << string_compose(_("Session: XMLNode describing a AudioRegion references a non-audio source id =%1"), id2) << endmsg;
1805 return boost::shared_ptr<AudioRegion>();
1807 master_sources.push_back (as);
1812 boost::shared_ptr<AudioRegion> region (boost::dynamic_pointer_cast<AudioRegion> (RegionFactory::create (sources, node)));
1814 /* a final detail: this is the one and only place that we know how long missing files are */
1816 if (region->whole_file()) {
1817 for (SourceList::iterator sx = sources.begin(); sx != sources.end(); ++sx) {
1818 boost::shared_ptr<SilentFileSource> sfp = boost::dynamic_pointer_cast<SilentFileSource> (*sx);
1820 sfp->set_length (region->length());
1825 if (!master_sources.empty()) {
1826 if (master_sources.size() != nchans) {
1827 error << _("Session: XMLNode describing an AudioRegion is missing some master sources; ignored") << endmsg;
1829 region->set_master_sources (master_sources);
1837 catch (failed_constructor& err) {
1838 return boost::shared_ptr<AudioRegion>();
1842 boost::shared_ptr<MidiRegion>
1843 Session::XMLMidiRegionFactory (const XMLNode& node, bool /*full*/)
1845 const XMLProperty* prop;
1846 boost::shared_ptr<Source> source;
1847 boost::shared_ptr<MidiSource> ms;
1850 if (node.name() != X_("Region")) {
1851 return boost::shared_ptr<MidiRegion>();
1854 if ((prop = node.property ("name")) == 0) {
1855 cerr << "no name for this region\n";
1859 if ((prop = node.property (X_("source-0"))) == 0) {
1860 if ((prop = node.property ("source")) == 0) {
1861 error << _("Session: XMLNode describing a MidiRegion is incomplete (no source)") << endmsg;
1862 return boost::shared_ptr<MidiRegion>();
1866 PBD::ID s_id (prop->value());
1868 if ((source = source_by_id (s_id)) == 0) {
1869 error << string_compose(_("Session: XMLNode describing a MidiRegion references an unknown source id =%1"), s_id) << endmsg;
1870 return boost::shared_ptr<MidiRegion>();
1873 ms = boost::dynamic_pointer_cast<MidiSource>(source);
1875 error << string_compose(_("Session: XMLNode describing a MidiRegion references a non-midi source id =%1"), s_id) << endmsg;
1876 return boost::shared_ptr<MidiRegion>();
1879 sources.push_back (ms);
1882 boost::shared_ptr<MidiRegion> region (boost::dynamic_pointer_cast<MidiRegion> (RegionFactory::create (sources, node)));
1883 /* a final detail: this is the one and only place that we know how long missing files are */
1885 if (region->whole_file()) {
1886 for (SourceList::iterator sx = sources.begin(); sx != sources.end(); ++sx) {
1887 boost::shared_ptr<SilentFileSource> sfp = boost::dynamic_pointer_cast<SilentFileSource> (*sx);
1889 sfp->set_length (region->length());
1897 catch (failed_constructor& err) {
1898 return boost::shared_ptr<MidiRegion>();
1903 Session::get_sources_as_xml ()
1906 XMLNode* node = new XMLNode (X_("Sources"));
1907 Glib::Mutex::Lock lm (source_lock);
1909 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ++i) {
1910 node->add_child_nocopy (i->second->get_state());
1917 Session::path_from_region_name (DataType type, string name, string identifier)
1919 char buf[PATH_MAX+1];
1921 SessionDirectory sdir(get_best_session_directory_for_new_source());
1922 sys::path source_dir = ((type == DataType::AUDIO)
1923 ? sdir.sound_path() : sdir.midi_path());
1925 string ext = native_header_format_extension (config.get_native_file_header_format(), type);
1927 for (n = 0; n < 999999; ++n) {
1928 if (identifier.length()) {
1929 snprintf (buf, sizeof(buf), "%s%s%" PRIu32 "%s", name.c_str(),
1930 identifier.c_str(), n, ext.c_str());
1932 snprintf (buf, sizeof(buf), "%s-%" PRIu32 "%s", name.c_str(),
1936 sys::path source_path = source_dir / buf;
1938 if (!sys::exists (source_path)) {
1939 return source_path.to_string();
1943 error << string_compose (_("cannot create new file from region name \"%1\" with ident = \"%2\": too many existing files with similar names"),
1952 Session::load_sources (const XMLNode& node)
1955 XMLNodeConstIterator niter;
1956 boost::shared_ptr<Source> source;
1958 nlist = node.children();
1962 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1965 if ((source = XMLSourceFactory (**niter)) == 0) {
1966 error << _("Session: cannot create Source from XML description.") << endmsg;
1969 } catch (MissingSource& err) {
1973 if (!no_questions_about_missing_files) {
1974 user_choice = MissingFile (this, err.path, err.type).get_value_or (-1);
1979 switch (user_choice) {
1981 /* user added a new search location, so try again */
1986 /* user asked to quit the entire session load
1991 no_questions_about_missing_files = true;
1995 no_questions_about_missing_files = true;
2000 warning << _("A sound file is missing. It will be replaced by silence.") << endmsg;
2001 source = SourceFactory::createSilent (*this, **niter, max_framecnt, _current_frame_rate);
2010 boost::shared_ptr<Source>
2011 Session::XMLSourceFactory (const XMLNode& node)
2013 if (node.name() != "Source") {
2014 return boost::shared_ptr<Source>();
2018 /* note: do peak building in another thread when loading session state */
2019 return SourceFactory::create (*this, node, true);
2022 catch (failed_constructor& err) {
2023 error << string_compose (_("Found a sound file that cannot be used by %1. Talk to the progammers."), PROGRAM_NAME) << endmsg;
2024 return boost::shared_ptr<Source>();
2029 Session::save_template (string template_name)
2033 if (_state_of_the_state & CannotSave) {
2037 sys::path user_template_dir(user_template_directory());
2041 sys::create_directories (user_template_dir);
2043 catch(sys::filesystem_error& ex)
2045 error << string_compose(_("Could not create templates directory \"%1\" (%2)"),
2046 user_template_dir.to_string(), ex.what()) << endmsg;
2050 tree.set_root (&get_template());
2052 sys::path template_dir_path(user_template_dir);
2054 /* directory to put the template in */
2055 template_dir_path /= template_name;
2056 if (sys::exists (template_dir_path))
2058 warning << string_compose(_("Template \"%1\" already exists - new version not created"),
2059 template_dir_path.to_string()) << endmsg;
2063 sys::create_directories (template_dir_path);
2066 sys::path template_file_path = template_dir_path;
2067 template_file_path /= template_name + template_suffix;
2069 if (!tree.write (template_file_path.to_string())) {
2070 error << _("template not saved") << endmsg;
2074 /* copy plugin state directory */
2076 sys::path template_plugin_state_path = template_dir_path;
2077 template_plugin_state_path /= X_("plugins");
2078 sys::create_directories (template_plugin_state_path);
2079 sys::copy_files (plugins_dir(), template_plugin_state_path);
2085 Session::refresh_disk_space ()
2087 #if HAVE_SYS_VFS_H && HAVE_SYS_STATVFS_H
2089 Glib::Mutex::Lock lm (space_lock);
2091 /* get freespace on every FS that is part of the session path */
2093 _total_free_4k_blocks = 0;
2094 _total_free_4k_blocks_uncertain = false;
2096 for (vector<space_and_path>::iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
2098 struct statfs statfsbuf;
2099 statfs (i->path.c_str(), &statfsbuf);
2101 double const scale = statfsbuf.f_bsize / 4096.0;
2103 /* See if this filesystem is read-only */
2104 struct statvfs statvfsbuf;
2105 statvfs (i->path.c_str(), &statvfsbuf);
2107 /* f_bavail can be 0 if it is undefined for whatever
2108 filesystem we are looking at; Samba shares mounted
2109 via GVFS are an example of this.
2111 if (statfsbuf.f_bavail == 0) {
2112 /* block count unknown */
2114 i->blocks_unknown = true;
2115 } else if (statvfsbuf.f_flag & ST_RDONLY) {
2116 /* read-only filesystem */
2118 i->blocks_unknown = false;
2120 /* read/write filesystem with known space */
2121 i->blocks = (uint32_t) floor (statfsbuf.f_bavail * scale);
2122 i->blocks_unknown = false;
2125 _total_free_4k_blocks += i->blocks;
2126 if (i->blocks_unknown) {
2127 _total_free_4k_blocks_uncertain = true;
2134 Session::get_best_session_directory_for_new_source ()
2136 vector<space_and_path>::iterator i;
2137 string result = _session_dir->root_path();
2139 /* handle common case without system calls */
2141 if (session_dirs.size() == 1) {
2145 /* OK, here's the algorithm we're following here:
2147 We want to select which directory to use for
2148 the next file source to be created. Ideally,
2149 we'd like to use a round-robin process so as to
2150 get maximum performance benefits from splitting
2151 the files across multiple disks.
2153 However, in situations without much diskspace, an
2154 RR approach may end up filling up a filesystem
2155 with new files while others still have space.
2156 Its therefore important to pay some attention to
2157 the freespace in the filesystem holding each
2158 directory as well. However, if we did that by
2159 itself, we'd keep creating new files in the file
2160 system with the most space until it was as full
2161 as all others, thus negating any performance
2162 benefits of this RAID-1 like approach.
2164 So, we use a user-configurable space threshold. If
2165 there are at least 2 filesystems with more than this
2166 much space available, we use RR selection between them.
2167 If not, then we pick the filesystem with the most space.
2169 This gets a good balance between the two
2173 refresh_disk_space ();
2175 int free_enough = 0;
2177 for (i = session_dirs.begin(); i != session_dirs.end(); ++i) {
2178 if ((*i).blocks * 4096 >= Config->get_disk_choice_space_threshold()) {
2183 if (free_enough >= 2) {
2184 /* use RR selection process, ensuring that the one
2188 i = last_rr_session_dir;
2191 if (++i == session_dirs.end()) {
2192 i = session_dirs.begin();
2195 if ((*i).blocks * 4096 >= Config->get_disk_choice_space_threshold()) {
2196 if (create_session_directory ((*i).path)) {
2198 last_rr_session_dir = i;
2203 } while (i != last_rr_session_dir);
2207 /* pick FS with the most freespace (and that
2208 seems to actually work ...)
2211 vector<space_and_path> sorted;
2212 space_and_path_ascending_cmp cmp;
2214 sorted = session_dirs;
2215 sort (sorted.begin(), sorted.end(), cmp);
2217 for (i = sorted.begin(); i != sorted.end(); ++i) {
2218 if (create_session_directory ((*i).path)) {
2220 last_rr_session_dir = i;
2230 Session::load_named_selections (const XMLNode& node)
2233 XMLNodeConstIterator niter;
2236 nlist = node.children();
2240 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2242 if ((ns = XMLNamedSelectionFactory (**niter)) == 0) {
2243 error << _("Session: cannot create Named Selection from XML description.") << endmsg;
2251 Session::XMLNamedSelectionFactory (const XMLNode& node)
2254 return new NamedSelection (*this, node);
2257 catch (failed_constructor& err) {
2263 Session::automation_dir () const
2265 return Glib::build_filename (_path, "automation");
2269 Session::analysis_dir () const
2271 return Glib::build_filename (_path, "analysis");
2275 Session::plugins_dir () const
2277 return Glib::build_filename (_path, "plugins");
2281 Session::externals_dir () const
2283 return Glib::build_filename (_path, "externals");
2287 Session::load_bundles (XMLNode const & node)
2289 XMLNodeList nlist = node.children();
2290 XMLNodeConstIterator niter;
2294 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2295 if ((*niter)->name() == "InputBundle") {
2296 add_bundle (boost::shared_ptr<UserBundle> (new UserBundle (**niter, true)));
2297 } else if ((*niter)->name() == "OutputBundle") {
2298 add_bundle (boost::shared_ptr<UserBundle> (new UserBundle (**niter, false)));
2300 error << string_compose(_("Unknown node \"%1\" found in Bundles list from state file"), (*niter)->name()) << endmsg;
2309 Session::load_route_groups (const XMLNode& node, int version)
2311 XMLNodeList nlist = node.children();
2312 XMLNodeConstIterator niter;
2316 if (version >= 3000) {
2318 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2319 if ((*niter)->name() == "RouteGroup") {
2320 RouteGroup* rg = new RouteGroup (*this, "");
2321 add_route_group (rg);
2322 rg->set_state (**niter, version);
2326 } else if (version < 3000) {
2328 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2329 if ((*niter)->name() == "EditGroup" || (*niter)->name() == "MixGroup") {
2330 RouteGroup* rg = new RouteGroup (*this, "");
2331 add_route_group (rg);
2332 rg->set_state (**niter, version);
2341 Session::auto_save()
2343 save_state (_current_snapshot_name);
2347 state_file_filter (const string &str, void */*arg*/)
2349 return (str.length() > strlen(statefile_suffix) &&
2350 str.find (statefile_suffix) == (str.length() - strlen (statefile_suffix)));
2354 bool operator()(const string* a, const string* b) {
2360 remove_end(string* state)
2362 string statename(*state);
2364 string::size_type start,end;
2365 if ((start = statename.find_last_of (G_DIR_SEPARATOR)) != string::npos) {
2366 statename = statename.substr (start+1);
2369 if ((end = statename.rfind(".ardour")) == string::npos) {
2370 end = statename.length();
2373 return new string(statename.substr (0, end));
2377 Session::possible_states (string path)
2379 PathScanner scanner;
2380 vector<string*>* states = scanner (path, state_file_filter, 0, false, false);
2382 transform(states->begin(), states->end(), states->begin(), remove_end);
2385 sort (states->begin(), states->end(), cmp);
2391 Session::possible_states () const
2393 return possible_states(_path);
2397 Session::add_route_group (RouteGroup* g)
2399 _route_groups.push_back (g);
2400 route_group_added (g); /* EMIT SIGNAL */
2402 g->RouteAdded.connect_same_thread (*this, boost::bind (&Session::route_added_to_route_group, this, _1, _2));
2403 g->RouteRemoved.connect_same_thread (*this, boost::bind (&Session::route_removed_from_route_group, this, _1, _2));
2404 g->PropertyChanged.connect_same_thread (*this, boost::bind (&Session::route_group_property_changed, this, g));
2410 Session::remove_route_group (RouteGroup& rg)
2412 list<RouteGroup*>::iterator i;
2414 if ((i = find (_route_groups.begin(), _route_groups.end(), &rg)) != _route_groups.end()) {
2415 _route_groups.erase (i);
2418 route_group_removed (); /* EMIT SIGNAL */
2422 /** Set a new order for our route groups, without adding or removing any.
2423 * @param groups Route group list in the new order.
2426 Session::reorder_route_groups (list<RouteGroup*> groups)
2428 _route_groups = groups;
2430 route_groups_reordered (); /* EMIT SIGNAL */
2436 Session::route_group_by_name (string name)
2438 list<RouteGroup *>::iterator i;
2440 for (i = _route_groups.begin(); i != _route_groups.end(); ++i) {
2441 if ((*i)->name() == name) {
2449 Session::all_route_group() const
2451 return *_all_route_group;
2455 Session::add_commands (vector<Command*> const & cmds)
2457 for (vector<Command*>::const_iterator i = cmds.begin(); i != cmds.end(); ++i) {
2463 Session::begin_reversible_command (const string& name)
2465 begin_reversible_command (g_quark_from_string (name.c_str ()));
2468 /** Begin a reversible command using a GQuark to identify it.
2469 * begin_reversible_command() and commit_reversible_command() calls may be nested,
2470 * but there must be as many begin...()s as there are commit...()s.
2473 Session::begin_reversible_command (GQuark q)
2475 /* If nested begin/commit pairs are used, we create just one UndoTransaction
2476 to hold all the commands that are committed. This keeps the order of
2477 commands correct in the history.
2480 if (_current_trans == 0) {
2481 /* start a new transaction */
2482 assert (_current_trans_quarks.empty ());
2483 _current_trans = new UndoTransaction();
2484 _current_trans->set_name (g_quark_to_string (q));
2487 _current_trans_quarks.push_front (q);
2491 Session::commit_reversible_command (Command *cmd)
2493 assert (_current_trans);
2494 assert (!_current_trans_quarks.empty ());
2499 _current_trans->add_command (cmd);
2502 _current_trans_quarks.pop_front ();
2504 if (!_current_trans_quarks.empty ()) {
2505 /* the transaction we're committing is not the top-level one */
2509 if (_current_trans->empty()) {
2510 /* no commands were added to the transaction, so just get rid of it */
2511 delete _current_trans;
2516 gettimeofday (&now, 0);
2517 _current_trans->set_timestamp (now);
2519 _history.add (_current_trans);
2524 accept_all_audio_files (const string& path, void */*arg*/)
2526 if (!Glib::file_test (path, Glib::FILE_TEST_IS_REGULAR)) {
2530 if (!AudioFileSource::safe_audio_file_extension (path)) {
2538 accept_all_midi_files (const string& path, void */*arg*/)
2540 if (!Glib::file_test (path, Glib::FILE_TEST_IS_REGULAR)) {
2544 return ((path.length() > 4 && path.find (".mid") != (path.length() - 4)) ||
2545 (path.length() > 4 && path.find (".smf") != (path.length() - 4)) ||
2546 (path.length() > 5 && path.find (".midi") != (path.length() - 5)));
2550 accept_all_state_files (const string& path, void */*arg*/)
2552 if (!Glib::file_test (path, Glib::FILE_TEST_IS_REGULAR)) {
2556 return (path.length() > 7 && path.find (".ardour") == (path.length() - 7));
2560 Session::find_all_sources (string path, set<string>& result)
2565 if (!tree.read (path)) {
2569 if ((node = find_named_node (*tree.root(), "Sources")) == 0) {
2574 XMLNodeConstIterator niter;
2576 nlist = node->children();
2580 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2584 if ((prop = (*niter)->property (X_("type"))) == 0) {
2588 DataType type (prop->value());
2590 if ((prop = (*niter)->property (X_("name"))) == 0) {
2594 if (Glib::path_is_absolute (prop->value())) {
2595 /* external file, ignore */
2603 if (FileSource::find (*this, type, prop->value(), true, is_new, chan, found_path)) {
2604 result.insert (found_path);
2612 Session::find_all_sources_across_snapshots (set<string>& result, bool exclude_this_snapshot)
2614 PathScanner scanner;
2615 vector<string*>* state_files;
2617 string this_snapshot_path;
2623 if (ripped[ripped.length()-1] == G_DIR_SEPARATOR) {
2624 ripped = ripped.substr (0, ripped.length() - 1);
2627 state_files = scanner (ripped, accept_all_state_files, (void *) 0, false, true);
2629 if (state_files == 0) {
2634 this_snapshot_path = _path;
2635 this_snapshot_path += legalize_for_path (_current_snapshot_name);
2636 this_snapshot_path += statefile_suffix;
2638 for (vector<string*>::iterator i = state_files->begin(); i != state_files->end(); ++i) {
2640 if (exclude_this_snapshot && **i == this_snapshot_path) {
2644 if (find_all_sources (**i, result) < 0) {
2652 struct RegionCounter {
2653 typedef std::map<PBD::ID,boost::shared_ptr<AudioSource> > AudioSourceList;
2654 AudioSourceList::iterator iter;
2655 boost::shared_ptr<Region> region;
2658 RegionCounter() : count (0) {}
2662 Session::ask_about_playlist_deletion (boost::shared_ptr<Playlist> p)
2664 boost::optional<int> r = AskAboutPlaylistDeletion (p);
2665 return r.get_value_or (1);
2669 Session::cleanup_regions ()
2671 const RegionFactory::RegionMap& regions (RegionFactory::regions());
2673 for (RegionFactory::RegionMap::const_iterator i = regions.begin(); i != regions.end(); ++i) {
2675 uint32_t used = playlists->region_use_count (i->second);
2677 if (used == 0 && !i->second->automatic ()) {
2678 RegionFactory::map_remove (i->second);
2682 /* dump the history list */
2689 Session::cleanup_sources (CleanupReport& rep)
2691 // FIXME: needs adaptation to midi
2693 vector<boost::shared_ptr<Source> > dead_sources;
2694 PathScanner scanner;
2697 vector<space_and_path>::iterator i;
2698 vector<space_and_path>::iterator nexti;
2699 vector<string*>* candidates;
2700 vector<string*>* candidates2;
2701 vector<string> unused;
2702 set<string> all_sources;
2707 _state_of_the_state = (StateOfTheState) (_state_of_the_state | InCleanup);
2709 /* consider deleting all unused playlists */
2711 if (playlists->maybe_delete_unused (boost::bind (Session::ask_about_playlist_deletion, _1))) {
2716 /* sync the "all regions" property of each playlist with its current state
2719 playlists->sync_all_regions_with_regions ();
2721 /* find all un-used sources */
2726 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ) {
2728 SourceMap::iterator tmp;
2733 /* do not bother with files that are zero size, otherwise we remove the current "nascent"
2737 if (!i->second->used() && (i->second->length(i->second->timeline_position() > 0))) {
2738 dead_sources.push_back (i->second);
2739 i->second->drop_references ();
2745 /* build a list of all the possible audio directories for the session */
2747 for (i = session_dirs.begin(); i != session_dirs.end(); ) {
2752 SessionDirectory sdir ((*i).path);
2753 audio_path += sdir.sound_path();
2755 if (nexti != session_dirs.end()) {
2763 /* build a list of all the possible midi directories for the session */
2765 for (i = session_dirs.begin(); i != session_dirs.end(); ) {
2770 SessionDirectory sdir ((*i).path);
2771 midi_path += sdir.midi_path();
2773 if (nexti != session_dirs.end()) {
2780 candidates = scanner (audio_path, accept_all_audio_files, (void *) 0, true, true);
2781 candidates2 = scanner (midi_path, accept_all_midi_files, (void *) 0, true, true);
2787 for (vector<string*>::iterator i = candidates2->begin(); i != candidates2->end(); ++i) {
2788 candidates->push_back (*i);
2793 candidates = candidates2; // might still be null
2796 /* find all sources, but don't use this snapshot because the
2797 state file on disk still references sources we may have already
2801 find_all_sources_across_snapshots (all_sources, true);
2803 /* add our current source list
2806 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ) {
2807 boost::shared_ptr<FileSource> fs;
2808 SourceMap::iterator tmp = i;
2811 if ((fs = boost::dynamic_pointer_cast<FileSource> (i->second)) != 0) {
2812 if (playlists->source_use_count (fs) != 0) {
2813 all_sources.insert (fs->path());
2816 /* we might not remove this source from disk, because it may be used
2817 by other snapshots, but its not being used in this version
2818 so lets get rid of it now, along with any representative regions
2822 RegionFactory::remove_regions_using_source (i->second);
2830 char tmppath1[PATH_MAX+1];
2831 char tmppath2[PATH_MAX+1];
2834 for (vector<string*>::iterator x = candidates->begin(); x != candidates->end(); ++x) {
2839 for (set<string>::iterator i = all_sources.begin(); i != all_sources.end(); ++i) {
2841 if (realpath(spath.c_str(), tmppath1) == 0) {
2842 error << string_compose (_("Cannot expand path %1 (%2)"),
2843 spath, strerror (errno)) << endmsg;
2847 if (realpath((*i).c_str(), tmppath2) == 0) {
2848 error << string_compose (_("Cannot expand path %1 (%2)"),
2849 (*i), strerror (errno)) << endmsg;
2853 if (strcmp(tmppath1, tmppath2) == 0) {
2860 unused.push_back (spath);
2869 /* now try to move all unused files into the "dead" directory(ies) */
2871 for (vector<string>::iterator x = unused.begin(); x != unused.end(); ++x) {
2872 struct stat statbuf;
2876 /* don't move the file across filesystems, just
2877 stick it in the `dead_dir_name' directory
2878 on whichever filesystem it was already on.
2881 if ((*x).find ("/sounds/") != string::npos) {
2883 /* old school, go up 1 level */
2885 newpath = Glib::path_get_dirname (*x); // "sounds"
2886 newpath = Glib::path_get_dirname (newpath); // "session-name"
2890 /* new school, go up 4 levels */
2892 newpath = Glib::path_get_dirname (*x); // "audiofiles" or "midifiles"
2893 newpath = Glib::path_get_dirname (newpath); // "session-name"
2894 newpath = Glib::path_get_dirname (newpath); // "interchange"
2895 newpath = Glib::path_get_dirname (newpath); // "session-dir"
2898 newpath = Glib::build_filename (newpath, dead_dir_name);
2900 if (g_mkdir_with_parents (newpath.c_str(), 0755) < 0) {
2901 error << string_compose(_("Session: cannot create dead file folder \"%1\" (%2)"), newpath, strerror (errno)) << endmsg;
2905 newpath = Glib::build_filename (newpath, Glib::path_get_basename ((*x)));
2907 if (Glib::file_test (newpath, Glib::FILE_TEST_EXISTS)) {
2909 /* the new path already exists, try versioning */
2911 char buf[PATH_MAX+1];
2915 snprintf (buf, sizeof (buf), "%s.%d", newpath.c_str(), version);
2918 while (Glib::file_test (newpath_v.c_str(), Glib::FILE_TEST_EXISTS) && version < 999) {
2919 snprintf (buf, sizeof (buf), "%s.%d", newpath.c_str(), ++version);
2923 if (version == 999) {
2924 error << string_compose (_("there are already 1000 files with names like %1; versioning discontinued"),
2928 newpath = newpath_v;
2933 /* it doesn't exist, or we can't read it or something */
2937 stat ((*x).c_str(), &statbuf);
2939 if (::rename ((*x).c_str(), newpath.c_str()) != 0) {
2940 error << string_compose (_("cannot rename unused file source from %1 to %2 (%3)"),
2941 (*x), newpath, strerror (errno))
2946 /* see if there an easy to find peakfile for this file, and remove it.
2949 string base = basename_nosuffix (*x);
2950 base += "%A"; /* this is what we add for the channel suffix of all native files,
2951 or for the first channel of embedded files. it will miss
2952 some peakfiles for other channels
2954 string peakpath = peak_path (base);
2956 if (Glib::file_test (peakpath.c_str(), Glib::FILE_TEST_EXISTS)) {
2957 if (::unlink (peakpath.c_str()) != 0) {
2958 error << string_compose (_("cannot remove peakfile %1 for %2 (%3)"),
2959 peakpath, _path, strerror (errno))
2961 /* try to back out */
2962 ::rename (newpath.c_str(), _path.c_str());
2967 rep.paths.push_back (*x);
2968 rep.space += statbuf.st_size;
2971 /* dump the history list */
2975 /* save state so we don't end up a session file
2976 referring to non-existent sources.
2983 _state_of_the_state = (StateOfTheState) (_state_of_the_state & ~InCleanup);
2989 Session::cleanup_trash_sources (CleanupReport& rep)
2991 // FIXME: needs adaptation for MIDI
2993 vector<space_and_path>::iterator i;
2999 for (i = session_dirs.begin(); i != session_dirs.end(); ++i) {
3001 dead_dir = Glib::build_filename ((*i).path, dead_dir_name);
3003 clear_directory (dead_dir, &rep.space, &rep.paths);
3010 Session::set_dirty ()
3012 bool was_dirty = dirty();
3014 _state_of_the_state = StateOfTheState (_state_of_the_state | Dirty);
3018 DirtyChanged(); /* EMIT SIGNAL */
3024 Session::set_clean ()
3026 bool was_dirty = dirty();
3028 _state_of_the_state = Clean;
3032 DirtyChanged(); /* EMIT SIGNAL */
3037 Session::set_deletion_in_progress ()
3039 _state_of_the_state = StateOfTheState (_state_of_the_state | Deletion);
3043 Session::clear_deletion_in_progress ()
3045 _state_of_the_state = StateOfTheState (_state_of_the_state & (~Deletion));
3049 Session::add_controllable (boost::shared_ptr<Controllable> c)
3051 /* this adds a controllable to the list managed by the Session.
3052 this is a subset of those managed by the Controllable class
3053 itself, and represents the only ones whose state will be saved
3054 as part of the session.
3057 Glib::Mutex::Lock lm (controllables_lock);
3058 controllables.insert (c);
3061 struct null_deleter { void operator()(void const *) const {} };
3064 Session::remove_controllable (Controllable* c)
3066 if (_state_of_the_state & Deletion) {
3070 Glib::Mutex::Lock lm (controllables_lock);
3072 Controllables::iterator x = controllables.find (boost::shared_ptr<Controllable>(c, null_deleter()));
3074 if (x != controllables.end()) {
3075 controllables.erase (x);
3079 boost::shared_ptr<Controllable>
3080 Session::controllable_by_id (const PBD::ID& id)
3082 Glib::Mutex::Lock lm (controllables_lock);
3084 for (Controllables::iterator i = controllables.begin(); i != controllables.end(); ++i) {
3085 if ((*i)->id() == id) {
3090 return boost::shared_ptr<Controllable>();
3093 boost::shared_ptr<Controllable>
3094 Session::controllable_by_descriptor (const ControllableDescriptor& desc)
3096 boost::shared_ptr<Controllable> c;
3097 boost::shared_ptr<Route> r;
3099 switch (desc.top_level_type()) {
3100 case ControllableDescriptor::NamedRoute:
3102 std::string str = desc.top_level_name();
3103 if (str == "master") {
3105 } else if (str == "control" || str == "listen") {
3108 r = route_by_name (desc.top_level_name());
3113 case ControllableDescriptor::RemoteControlID:
3114 r = route_by_remote_id (desc.rid());
3122 switch (desc.subtype()) {
3123 case ControllableDescriptor::Gain:
3124 c = r->gain_control ();
3127 case ControllableDescriptor::Solo:
3128 c = r->solo_control();
3131 case ControllableDescriptor::Mute:
3132 c = r->mute_control();
3135 case ControllableDescriptor::Recenable:
3137 boost::shared_ptr<Track> t = boost::dynamic_pointer_cast<Track>(r);
3140 c = t->rec_enable_control ();
3145 case ControllableDescriptor::PanDirection:
3147 c = r->pannable()->pan_azimuth_control;
3151 case ControllableDescriptor::PanWidth:
3153 c = r->pannable()->pan_width_control;
3157 case ControllableDescriptor::PanElevation:
3159 c = r->pannable()->pan_elevation_control;
3163 case ControllableDescriptor::Balance:
3164 /* XXX simple pan control */
3167 case ControllableDescriptor::PluginParameter:
3169 uint32_t plugin = desc.target (0);
3170 uint32_t parameter_index = desc.target (1);
3172 /* revert to zero based counting */
3178 if (parameter_index > 0) {
3182 boost::shared_ptr<Processor> p = r->nth_plugin (plugin);
3185 c = boost::dynamic_pointer_cast<ARDOUR::AutomationControl>(
3186 p->control(Evoral::Parameter(PluginAutomation, 0, parameter_index)));
3191 case ControllableDescriptor::SendGain:
3193 uint32_t send = desc.target (0);
3195 /* revert to zero-based counting */
3201 boost::shared_ptr<Processor> p = r->nth_send (send);
3204 boost::shared_ptr<Send> s = boost::dynamic_pointer_cast<Send>(p);
3205 boost::shared_ptr<Amp> a = s->amp();
3208 c = s->amp()->gain_control();
3215 /* relax and return a null pointer */
3223 Session::add_instant_xml (XMLNode& node, bool write_to_config)
3226 Stateful::add_instant_xml (node, _path);
3229 if (write_to_config) {
3230 Config->add_instant_xml (node);
3235 Session::instant_xml (const string& node_name)
3237 return Stateful::instant_xml (node_name, _path);
3241 Session::save_history (string snapshot_name)
3249 if (snapshot_name.empty()) {
3250 snapshot_name = _current_snapshot_name;
3253 const string history_filename = legalize_for_path (snapshot_name) + history_suffix;
3254 const string backup_filename = history_filename + backup_suffix;
3255 const sys::path xml_path(Glib::build_filename (_session_dir->root_path(), history_filename));
3256 const sys::path backup_path(Glib::build_filename (_session_dir->root_path(), backup_filename));
3258 if (sys::exists (xml_path)) {
3261 sys::rename (xml_path, backup_path);
3263 catch (const sys::filesystem_error& err)
3265 error << _("could not backup old history file, current history not saved") << endmsg;
3270 if (!Config->get_save_history() || Config->get_saved_history_depth() < 0) {
3274 tree.set_root (&_history.get_state (Config->get_saved_history_depth()));
3276 if (!tree.write (xml_path.to_string()))
3278 error << string_compose (_("history could not be saved to %1"), xml_path.to_string()) << endmsg;
3282 sys::remove (xml_path);
3283 sys::rename (backup_path, xml_path);
3285 catch (const sys::filesystem_error& err)
3287 error << string_compose (_("could not restore history file from backup %1 (%2)"),
3288 backup_path.to_string(), err.what()) << endmsg;
3298 Session::restore_history (string snapshot_name)
3302 if (snapshot_name.empty()) {
3303 snapshot_name = _current_snapshot_name;
3306 const string xml_filename = legalize_for_path (snapshot_name) + history_suffix;
3307 const sys::path xml_path(Glib::build_filename (_session_dir->root_path(), xml_filename));
3309 info << "Loading history from " << xml_path.to_string() << endmsg;
3311 if (!sys::exists (xml_path)) {
3312 info << string_compose (_("%1: no history file \"%2\" for this session."),
3313 _name, xml_path.to_string()) << endmsg;
3317 if (!tree.read (xml_path.to_string())) {
3318 error << string_compose (_("Could not understand session history file \"%1\""),
3319 xml_path.to_string()) << endmsg;
3326 for (XMLNodeConstIterator it = tree.root()->children().begin(); it != tree.root()->children().end(); it++) {
3329 UndoTransaction* ut = new UndoTransaction ();
3332 ut->set_name(t->property("name")->value());
3333 stringstream ss(t->property("tv-sec")->value());
3335 ss.str(t->property("tv-usec")->value());
3337 ut->set_timestamp(tv);
3339 for (XMLNodeConstIterator child_it = t->children().begin();
3340 child_it != t->children().end(); child_it++)
3342 XMLNode *n = *child_it;
3345 if (n->name() == "MementoCommand" ||
3346 n->name() == "MementoUndoCommand" ||
3347 n->name() == "MementoRedoCommand") {
3349 if ((c = memento_command_factory(n))) {
3353 } else if (n->name() == "NoteDiffCommand") {
3354 PBD::ID id (n->property("midi-source")->value());
3355 boost::shared_ptr<MidiSource> midi_source =
3356 boost::dynamic_pointer_cast<MidiSource, Source>(source_by_id(id));
3358 ut->add_command (new MidiModel::NoteDiffCommand(midi_source->model(), *n));
3360 error << _("Failed to downcast MidiSource for NoteDiffCommand") << endmsg;
3363 } else if (n->name() == "SysExDiffCommand") {
3365 PBD::ID id (n->property("midi-source")->value());
3366 boost::shared_ptr<MidiSource> midi_source =
3367 boost::dynamic_pointer_cast<MidiSource, Source>(source_by_id(id));
3369 ut->add_command (new MidiModel::SysExDiffCommand (midi_source->model(), *n));
3371 error << _("Failed to downcast MidiSource for SysExDiffCommand") << endmsg;
3374 } else if (n->name() == "PatchChangeDiffCommand") {
3376 PBD::ID id (n->property("midi-source")->value());
3377 boost::shared_ptr<MidiSource> midi_source =
3378 boost::dynamic_pointer_cast<MidiSource, Source>(source_by_id(id));
3380 ut->add_command (new MidiModel::PatchChangeDiffCommand (midi_source->model(), *n));
3382 error << _("Failed to downcast MidiSource for PatchChangeDiffCommand") << endmsg;
3385 } else if (n->name() == "StatefulDiffCommand") {
3386 if ((c = stateful_diff_command_factory (n))) {
3387 ut->add_command (c);
3390 error << string_compose(_("Couldn't figure out how to make a Command out of a %1 XMLNode."), n->name()) << endmsg;
3401 Session::config_changed (std::string p, bool ours)
3407 if (p == "seamless-loop") {
3409 } else if (p == "rf-speed") {
3411 } else if (p == "auto-loop") {
3413 } else if (p == "auto-input") {
3415 if (Config->get_monitoring_model() == HardwareMonitoring && transport_rolling()) {
3416 /* auto-input only makes a difference if we're rolling */
3417 set_track_monitor_input_status (!config.get_auto_input());
3420 } else if (p == "punch-in") {
3424 if ((location = _locations->auto_punch_location()) != 0) {
3426 if (config.get_punch_in ()) {
3427 replace_event (SessionEvent::PunchIn, location->start());
3429 remove_event (location->start(), SessionEvent::PunchIn);
3433 } else if (p == "punch-out") {
3437 if ((location = _locations->auto_punch_location()) != 0) {
3439 if (config.get_punch_out()) {
3440 replace_event (SessionEvent::PunchOut, location->end());
3442 clear_events (SessionEvent::PunchOut);
3446 } else if (p == "edit-mode") {
3448 Glib::Mutex::Lock lm (playlists->lock);
3450 for (SessionPlaylists::List::iterator i = playlists->playlists.begin(); i != playlists->playlists.end(); ++i) {
3451 (*i)->set_edit_mode (Config->get_edit_mode ());
3454 } else if (p == "use-video-sync") {
3456 waiting_for_sync_offset = config.get_use_video_sync();
3458 } else if (p == "mmc-control") {
3460 //poke_midi_thread ();
3462 } else if (p == "mmc-device-id" || p == "mmc-receive-id" || p == "mmc-receive-device-id") {
3464 MIDI::Manager::instance()->mmc()->set_receive_device_id (Config->get_mmc_receive_device_id());
3466 } else if (p == "mmc-send-id" || p == "mmc-send-device-id") {
3468 MIDI::Manager::instance()->mmc()->set_send_device_id (Config->get_mmc_send_device_id());
3470 } else if (p == "midi-control") {
3472 //poke_midi_thread ();
3474 } else if (p == "raid-path") {
3476 setup_raid_path (config.get_raid_path());
3478 } else if (p == "timecode-format") {
3482 } else if (p == "video-pullup") {
3486 } else if (p == "seamless-loop") {
3488 if (play_loop && transport_rolling()) {
3489 // to reset diskstreams etc
3490 request_play_loop (true);
3493 } else if (p == "rf-speed") {
3495 cumulative_rf_motion = 0;
3498 } else if (p == "click-sound") {
3500 setup_click_sounds (1);
3502 } else if (p == "click-emphasis-sound") {
3504 setup_click_sounds (-1);
3506 } else if (p == "clicking") {
3508 if (Config->get_clicking()) {
3509 if (_click_io && click_data) { // don't require emphasis data
3516 } else if (p == "click-gain") {
3519 _click_gain->set_gain (Config->get_click_gain(), this);
3522 } else if (p == "send-mtc") {
3524 if (Config->get_send_mtc ()) {
3525 /* mark us ready to send */
3526 next_quarter_frame_to_send = 0;
3529 } else if (p == "send-mmc") {
3531 MIDI::Manager::instance()->mmc()->enable_send (Config->get_send_mmc ());
3533 } else if (p == "midi-feedback") {
3535 session_midi_feedback = Config->get_midi_feedback();
3537 } else if (p == "jack-time-master") {
3539 engine().reset_timebase ();
3541 } else if (p == "native-file-header-format") {
3543 if (!first_file_header_format_reset) {
3544 reset_native_file_format ();
3547 first_file_header_format_reset = false;
3549 } else if (p == "native-file-data-format") {
3551 if (!first_file_data_format_reset) {
3552 reset_native_file_format ();
3555 first_file_data_format_reset = false;
3557 } else if (p == "external-sync") {
3558 if (!config.get_external_sync()) {
3559 drop_sync_source ();
3561 switch_to_sync_source (config.get_sync_source());
3563 } else if (p == "remote-model") {
3564 set_remote_control_ids ();
3565 } else if (p == "denormal-model") {
3567 } else if (p == "history-depth") {
3568 set_history_depth (Config->get_history_depth());
3569 } else if (p == "sync-all-route-ordering") {
3570 sync_order_keys ("session");
3571 } else if (p == "initial-program-change") {
3573 if (MIDI::Manager::instance()->mmc()->output_port() && Config->get_initial_program_change() >= 0) {
3576 buf[0] = MIDI::program; // channel zero by default
3577 buf[1] = (Config->get_initial_program_change() & 0x7f);
3579 MIDI::Manager::instance()->mmc()->output_port()->midimsg (buf, sizeof (buf), 0);
3581 } else if (p == "solo-mute-override") {
3582 // catch_up_on_solo_mute_override ();
3583 } else if (p == "listen-position" || p == "pfl-position") {
3584 listen_position_changed ();
3585 } else if (p == "solo-control-is-listen-control") {
3586 solo_control_mode_changed ();
3587 } else if (p == "timecode-offset" || p == "timecode-offset-negative") {
3588 last_timecode_valid = false;
3589 } else if (p == "playback-buffer-seconds") {
3590 AudioSource::allocate_working_buffers (frame_rate());
3591 } else if (p == "automation-thinning-factor") {
3592 Evoral::ControlList::set_thinning_factor (Config->get_automation_thinning_factor());
3599 Session::set_history_depth (uint32_t d)
3601 _history.set_depth (d);
3605 Session::load_diskstreams_2X (XMLNode const & node, int)
3608 XMLNodeConstIterator citer;
3610 clist = node.children();
3612 for (citer = clist.begin(); citer != clist.end(); ++citer) {
3615 /* diskstreams added automatically by DiskstreamCreated handler */
3616 if ((*citer)->name() == "AudioDiskstream" || (*citer)->name() == "DiskStream") {
3617 boost::shared_ptr<AudioDiskstream> dsp (new AudioDiskstream (*this, **citer));
3618 _diskstreams_2X.push_back (dsp);
3620 error << _("Session: unknown diskstream type in XML") << endmsg;
3624 catch (failed_constructor& err) {
3625 error << _("Session: could not load diskstream via XML state") << endmsg;
3633 /** Connect things to the MMC object */
3635 Session::setup_midi_machine_control ()
3637 MIDI::MachineControl* mmc = MIDI::Manager::instance()->mmc ();
3639 mmc->Play.connect_same_thread (*this, boost::bind (&Session::mmc_deferred_play, this, _1));
3640 mmc->DeferredPlay.connect_same_thread (*this, boost::bind (&Session::mmc_deferred_play, this, _1));
3641 mmc->Stop.connect_same_thread (*this, boost::bind (&Session::mmc_stop, this, _1));
3642 mmc->FastForward.connect_same_thread (*this, boost::bind (&Session::mmc_fast_forward, this, _1));
3643 mmc->Rewind.connect_same_thread (*this, boost::bind (&Session::mmc_rewind, this, _1));
3644 mmc->Pause.connect_same_thread (*this, boost::bind (&Session::mmc_pause, this, _1));
3645 mmc->RecordPause.connect_same_thread (*this, boost::bind (&Session::mmc_record_pause, this, _1));
3646 mmc->RecordStrobe.connect_same_thread (*this, boost::bind (&Session::mmc_record_strobe, this, _1));
3647 mmc->RecordExit.connect_same_thread (*this, boost::bind (&Session::mmc_record_exit, this, _1));
3648 mmc->Locate.connect_same_thread (*this, boost::bind (&Session::mmc_locate, this, _1, _2));
3649 mmc->Step.connect_same_thread (*this, boost::bind (&Session::mmc_step, this, _1, _2));
3650 mmc->Shuttle.connect_same_thread (*this, boost::bind (&Session::mmc_shuttle, this, _1, _2, _3));
3651 mmc->TrackRecordStatusChange.connect_same_thread (*this, boost::bind (&Session::mmc_record_enable, this, _1, _2, _3));
3653 /* also handle MIDI SPP because its so common */
3655 mmc->SPPStart.connect_same_thread (*this, boost::bind (&Session::spp_start, this));
3656 mmc->SPPContinue.connect_same_thread (*this, boost::bind (&Session::spp_continue, this));
3657 mmc->SPPStop.connect_same_thread (*this, boost::bind (&Session::spp_stop, this));
3660 boost::shared_ptr<Controllable>
3661 Session::solo_cut_control() const
3663 /* the solo cut control is a bit of an anomaly, at least as of Febrary 2011. There are no other
3664 controls in Ardour that currently get presented to the user in the GUI that require
3665 access as a Controllable and are also NOT owned by some SessionObject (e.g. Route, or MonitorProcessor).
3667 its actually an RCConfiguration parameter, so we use a ProxyControllable to wrap
3668 it up as a Controllable. Changes to the Controllable will just map back to the RCConfiguration
3672 return _solo_cut_control;
3676 Session::rename (const std::string& new_name)
3678 string legal_name = legalize_for_path (new_name);
3684 string const old_sources_root = _session_dir->sources_root();
3686 #define RENAME ::rename
3691 * interchange subdirectory
3695 * Backup files are left unchanged and not renamed.
3698 /* pass one: not 100% safe check that the new directory names don't
3702 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
3707 /* this is a stupid hack because Glib::path_get_dirname() is
3708 * lexical-only, and so passing it /a/b/c/ gives a different
3709 * result than passing it /a/b/c ...
3712 if (oldstr[oldstr.length()-1] == G_DIR_SEPARATOR) {
3713 oldstr = oldstr.substr (0, oldstr.length() - 1);
3716 string base = Glib::path_get_dirname (oldstr);
3717 string p = Glib::path_get_basename (oldstr);
3719 newstr = Glib::build_filename (base, legal_name);
3721 if (Glib::file_test (newstr, Glib::FILE_TEST_EXISTS)) {
3728 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
3733 /* this is a stupid hack because Glib::path_get_dirname() is
3734 * lexical-only, and so passing it /a/b/c/ gives a different
3735 * result than passing it /a/b/c ...
3738 if (oldstr[oldstr.length()-1] == G_DIR_SEPARATOR) {
3739 oldstr = oldstr.substr (0, oldstr.length() - 1);
3742 string base = Glib::path_get_dirname (oldstr);
3743 string p = Glib::path_get_basename (oldstr);
3745 newstr = Glib::build_filename (base, legal_name);
3747 cerr << "Rename " << oldstr << " => " << newstr << endl;
3749 if (RENAME (oldstr.c_str(), newstr.c_str()) != 0) {
3754 (*_session_dir) = newstr;
3759 /* directory below interchange */
3761 v.push_back (newstr);
3762 v.push_back (interchange_dir_name);
3765 oldstr = Glib::build_filename (v);
3768 v.push_back (newstr);
3769 v.push_back (interchange_dir_name);
3770 v.push_back (legal_name);
3772 newstr = Glib::build_filename (v);
3774 cerr << "Rename " << oldstr << " => " << newstr << endl;
3776 if (RENAME (oldstr.c_str(), newstr.c_str()) != 0) {
3783 oldstr = Glib::build_filename (newpath, _current_snapshot_name) + statefile_suffix;
3784 newstr= Glib::build_filename (newpath, legal_name) + statefile_suffix;
3786 cerr << "Rename " << oldstr << " => " << newstr << endl;
3788 if (RENAME (oldstr.c_str(), newstr.c_str()) != 0) {
3795 oldstr = Glib::build_filename (newpath, _current_snapshot_name) + history_suffix;
3797 if (Glib::file_test (oldstr, Glib::FILE_TEST_EXISTS)) {
3798 newstr = Glib::build_filename (newpath, legal_name) + history_suffix;
3800 cerr << "Rename " << oldstr << " => " << newstr << endl;
3802 if (RENAME (oldstr.c_str(), newstr.c_str()) != 0) {
3807 /* update file source paths */
3809 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ++i) {
3810 boost::shared_ptr<FileSource> fs = boost::dynamic_pointer_cast<FileSource> (i->second);
3812 string p = fs->path ();
3813 boost::replace_all (p, old_sources_root, _session_dir->sources_root());
3818 /* remove old name from recent sessions */
3820 remove_recent_sessions (_path);
3823 _current_snapshot_name = new_name;
3828 /* save state again to get everything just right */
3830 save_state (_current_snapshot_name);
3833 /* add to recent sessions */
3835 store_recent_sessions (new_name, _path);