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>
52 #include <glibmm/thread.h>
54 #include <boost/algorithm/string.hpp>
56 #include "midi++/mmc.h"
57 #include "midi++/port.h"
58 #include "midi++/manager.h"
60 #include "pbd/boost_debug.h"
61 #include "pbd/basename.h"
62 #include "pbd/controllable_descriptor.h"
63 #include "pbd/enumwriter.h"
64 #include "pbd/error.h"
65 #include "pbd/pathscanner.h"
66 #include "pbd/pthread_utils.h"
67 #include "pbd/search_path.h"
68 #include "pbd/stacktrace.h"
69 #include "pbd/convert.h"
70 #include "pbd/clear_dir.h"
72 #include "ardour/amp.h"
73 #include "ardour/audio_diskstream.h"
74 #include "ardour/audio_playlist_source.h"
75 #include "ardour/audio_track.h"
76 #include "ardour/audioengine.h"
77 #include "ardour/audiofilesource.h"
78 #include "ardour/audioplaylist.h"
79 #include "ardour/audioregion.h"
80 #include "ardour/auditioner.h"
81 #include "ardour/automation_control.h"
82 #include "ardour/buffer.h"
83 #include "ardour/butler.h"
84 #include "ardour/configuration.h"
85 #include "ardour/control_protocol_manager.h"
86 #include "ardour/crossfade.h"
87 #include "ardour/cycle_timer.h"
88 #include "ardour/directory_names.h"
89 #include "ardour/filename_extensions.h"
90 #include "ardour/io_processor.h"
91 #include "ardour/location.h"
92 #include "ardour/midi_diskstream.h"
93 #include "ardour/midi_model.h"
94 #include "ardour/midi_patch_manager.h"
95 #include "ardour/midi_playlist.h"
96 #include "ardour/midi_region.h"
97 #include "ardour/midi_source.h"
98 #include "ardour/midi_track.h"
99 #include "ardour/named_selection.h"
100 #include "ardour/pannable.h"
101 #include "ardour/processor.h"
102 #include "ardour/port.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_state_utils.h"
112 #include "ardour/session_playlists.h"
113 #include "ardour/session_utils.h"
114 #include "ardour/silentfilesource.h"
115 #include "ardour/slave.h"
116 #include "ardour/smf_source.h"
117 #include "ardour/sndfile_helpers.h"
118 #include "ardour/sndfilesource.h"
119 #include "ardour/source_factory.h"
120 #include "ardour/speakers.h"
121 #include "ardour/template_utils.h"
122 #include "ardour/tempo.h"
123 #include "ardour/ticker.h"
124 #include "ardour/user_bundle.h"
125 #include "ardour/utils.h"
126 #include "ardour/utils.h"
127 #include "ardour/version.h"
128 #include "ardour/playlist_factory.h"
130 #include "control_protocol/control_protocol.h"
136 using namespace ARDOUR;
139 /** @param snapshot_name Snapshot name, without the .ardour prefix */
141 Session::first_stage_init (string fullpath, string snapshot_name)
143 if (fullpath.length() == 0) {
145 throw failed_constructor();
148 char buf[PATH_MAX+1];
149 if (!realpath (fullpath.c_str(), buf) && (errno != ENOENT)) {
150 error << string_compose(_("Could not use path %1 (%s)"), buf, strerror(errno)) << endmsg;
152 throw failed_constructor();
157 if (_path[_path.length()-1] != G_DIR_SEPARATOR) {
158 _path += G_DIR_SEPARATOR;
161 /* these two are just provisional settings. set_state()
162 will likely override them.
165 _name = _current_snapshot_name = snapshot_name;
167 set_history_depth (Config->get_history_depth());
169 _current_frame_rate = _engine.frame_rate ();
170 _nominal_frame_rate = _current_frame_rate;
171 _base_frame_rate = _current_frame_rate;
173 _tempo_map = new TempoMap (_current_frame_rate);
174 _tempo_map->PropertyChanged.connect_same_thread (*this, boost::bind (&Session::tempo_map_changed, this, _1));
177 _non_soloed_outs_muted = false;
179 _solo_isolated_cnt = 0;
180 g_atomic_int_set (&processing_prohibited, 0);
181 _transport_speed = 0;
182 _last_transport_speed = 0;
183 _target_transport_speed = 0;
184 auto_play_legal = false;
185 transport_sub_state = 0;
186 _transport_frame = 0;
187 _requested_return_frame = -1;
188 _session_range_location = 0;
189 g_atomic_int_set (&_record_status, Disabled);
190 loop_changing = false;
193 _last_roll_location = 0;
194 _last_roll_or_reversal_location = 0;
195 _last_record_location = 0;
196 pending_locate_frame = 0;
197 pending_locate_roll = false;
198 pending_locate_flush = false;
199 state_was_pending = false;
201 outbound_mtc_timecode_frame = 0;
202 next_quarter_frame_to_send = -1;
203 current_block_size = 0;
204 solo_update_disabled = false;
205 _have_captured = false;
206 _worst_output_latency = 0;
207 _worst_input_latency = 0;
208 _worst_track_latency = 0;
209 _state_of_the_state = StateOfTheState(CannotSave|InitialConnecting|Loading);
210 _was_seamless = Config->get_seamless_loop ();
212 _send_qf_mtc = false;
213 _pframes_since_last_mtc = 0;
214 g_atomic_int_set (&_playback_load, 100);
215 g_atomic_int_set (&_capture_load, 100);
218 pending_abort = false;
219 destructive_index = 0;
220 first_file_data_format_reset = true;
221 first_file_header_format_reset = true;
222 post_export_sync = false;
225 no_questions_about_missing_files = false;
226 _speakers.reset (new Speakers);
228 ignore_route_processor_changes = false;
230 AudioDiskstream::allocate_working_buffers();
232 /* default short fade = 15ms */
234 Crossfade::set_short_xfade_length ((framecnt_t) floor (config.get_short_xfade_seconds() * frame_rate()));
235 SndFileSource::setup_standard_crossfades (*this, frame_rate());
237 last_mmc_step.tv_sec = 0;
238 last_mmc_step.tv_usec = 0;
241 /* click sounds are unset by default, which causes us to internal
242 waveforms for clicks.
246 click_emphasis_length = 0;
249 process_function = &Session::process_with_events;
251 if (config.get_use_video_sync()) {
252 waiting_for_sync_offset = true;
254 waiting_for_sync_offset = false;
257 last_timecode_when = 0;
258 last_timecode_valid = false;
262 last_rr_session_dir = session_dirs.begin();
263 refresh_disk_space ();
265 /* default: assume simple stereo speaker configuration */
267 _speakers->setup_default_speakers (2);
271 average_slave_delta = 1800; // !!! why 1800 ????
272 have_first_delta_accumulator = false;
273 delta_accumulator_cnt = 0;
274 _slave_state = Stopped;
276 _solo_cut_control.reset (new ProxyControllable (_("solo cut control (dB)"), PBD::Controllable::GainLike,
277 boost::bind (&RCConfiguration::set_solo_mute_gain, Config, _1),
278 boost::bind (&RCConfiguration::get_solo_mute_gain, Config)));
279 add_controllable (_solo_cut_control);
281 _engine.GraphReordered.connect_same_thread (*this, boost::bind (&Session::graph_reordered, this));
283 /* These are all static "per-class" signals */
285 SourceFactory::SourceCreated.connect_same_thread (*this, boost::bind (&Session::add_source, this, _1));
286 PlaylistFactory::PlaylistCreated.connect_same_thread (*this, boost::bind (&Session::add_playlist, this, _1, _2));
287 AutomationList::AutomationListCreated.connect_same_thread (*this, boost::bind (&Session::add_automation_list, this, _1));
288 Controllable::Destroyed.connect_same_thread (*this, boost::bind (&Session::remove_controllable, this, _1));
289 IO::PortCountChanged.connect_same_thread (*this, boost::bind (&Session::ensure_buffers, this, _1));
291 /* stop IO objects from doing stuff until we're ready for them */
293 Delivery::disable_panners ();
294 IO::disable_connecting ();
298 Session::second_stage_init ()
300 AudioFileSource::set_peak_dir (_session_dir->peak_path().to_string());
303 if (load_state (_current_snapshot_name)) {
308 if (_butler->start_thread()) {
312 if (start_midi_thread ()) {
316 setup_midi_machine_control ();
318 // set_state() will call setup_raid_path(), but if it's a new session we need
319 // to call setup_raid_path() here.
322 if (set_state (*state_tree->root(), Stateful::loading_state_version)) {
326 setup_raid_path(_path);
329 /* we can't save till after ::when_engine_running() is called,
330 because otherwise we save state with no connections made.
331 therefore, we reset _state_of_the_state because ::set_state()
332 will have cleared it.
334 we also have to include Loading so that any events that get
335 generated between here and the end of ::when_engine_running()
336 will be processed directly rather than queued.
339 _state_of_the_state = StateOfTheState (_state_of_the_state|CannotSave|Loading);
341 _locations->changed.connect_same_thread (*this, boost::bind (&Session::locations_changed, this));
342 _locations->added.connect_same_thread (*this, boost::bind (&Session::locations_added, this, _1));
343 setup_click_sounds (0);
344 setup_midi_control ();
346 /* Pay attention ... */
348 _engine.Halted.connect_same_thread (*this, boost::bind (&Session::engine_halted, this));
349 _engine.Xrun.connect_same_thread (*this, boost::bind (&Session::xrun_recovery, this));
351 midi_clock = new MidiClockTicker ();
352 midi_clock->set_session (this);
355 when_engine_running ();
358 /* handle this one in a different way than all others, so that its clear what happened */
360 catch (AudioEngine::PortRegistrationFailure& err) {
361 error << err.what() << endmsg;
369 BootMessage (_("Reset Remote Controls"));
371 send_full_time_code (0);
372 _engine.transport_locate (0);
374 MIDI::Manager::instance()->mmc()->send (MIDI::MachineControlCommand (MIDI::MachineControl::cmdMmcReset));
375 MIDI::Manager::instance()->mmc()->send (MIDI::MachineControlCommand (Timecode::Time ()));
377 MIDI::Name::MidiPatchManager::instance().set_session (this);
379 /* initial program change will be delivered later; see ::config_changed() */
381 _state_of_the_state = Clean;
383 Port::set_connecting_blocked (false);
385 DirtyChanged (); /* EMIT SIGNAL */
387 if (state_was_pending) {
388 save_state (_current_snapshot_name);
389 remove_pending_capture_state ();
390 state_was_pending = false;
393 BootMessage (_("Session loading complete"));
399 Session::raid_path () const
401 SearchPath raid_search_path;
403 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
404 raid_search_path += sys::path((*i).path);
407 return raid_search_path.to_string ();
411 Session::setup_raid_path (string path)
420 session_dirs.clear ();
422 SearchPath search_path(path);
423 SearchPath sound_search_path;
424 SearchPath midi_search_path;
426 for (SearchPath::const_iterator i = search_path.begin(); i != search_path.end(); ++i) {
427 sp.path = (*i).to_string ();
428 sp.blocks = 0; // not needed
429 session_dirs.push_back (sp);
431 SessionDirectory sdir(sp.path);
433 sound_search_path += sdir.sound_path ();
434 midi_search_path += sdir.midi_path ();
437 // reset the round-robin soundfile path thingie
438 last_rr_session_dir = session_dirs.begin();
442 Session::path_is_within_session (const std::string& path)
444 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
445 if (path.find ((*i).path) == 0) {
453 Session::ensure_subdirs ()
457 dir = session_directory().peak_path().to_string();
459 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
460 error << string_compose(_("Session: cannot create session peakfile folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
464 dir = session_directory().sound_path().to_string();
466 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
467 error << string_compose(_("Session: cannot create session sounds dir \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
471 dir = session_directory().midi_path().to_string();
473 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
474 error << string_compose(_("Session: cannot create session midi dir \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
478 dir = session_directory().dead_path().to_string();
480 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
481 error << string_compose(_("Session: cannot create session dead sounds folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
485 dir = session_directory().export_path().to_string();
487 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
488 error << string_compose(_("Session: cannot create session export folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
492 dir = analysis_dir ();
494 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
495 error << string_compose(_("Session: cannot create session analysis folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
499 dir = plugins_dir ();
501 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
502 error << string_compose(_("Session: cannot create session plugins folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
509 /** @param session_template directory containing session template, or empty.
510 * Caller must not hold process lock.
513 Session::create (const string& session_template, BusProfile* bus_profile)
515 if (g_mkdir_with_parents (_path.c_str(), 0755) < 0) {
516 error << string_compose(_("Session: cannot create session folder \"%1\" (%2)"), _path, strerror (errno)) << endmsg;
520 if (ensure_subdirs ()) {
524 _writable = exists_and_writable (sys::path (_path));
526 if (!session_template.empty()) {
527 std::string in_path = session_template_dir_to_file (session_template);
529 ifstream in(in_path.c_str());
532 string out_path = _path;
534 out_path += statefile_suffix;
536 ofstream out(out_path.c_str());
542 /* Copy plugin state files from template to new session */
543 sys::path template_plugins = session_template;
544 template_plugins /= X_("plugins");
545 sys::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 /* Instantiate metadata */
565 _metadata = new SessionMetadata ();
567 /* set initial start + end point */
569 _state_of_the_state = Clean;
571 /* set up Master Out and Control Out if necessary */
576 ChanCount count(DataType::AUDIO, bus_profile->master_out_channels);
578 if (bus_profile->master_out_channels) {
579 boost::shared_ptr<Route> r (new Route (*this, _("master"), Route::MasterOut, DataType::AUDIO));
583 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
584 // boost_debug_shared_ptr_mark_interesting (r.get(), "Route");
587 Glib::Mutex::Lock lm (AudioEngine::instance()->process_lock ());
588 r->input()->ensure_io (count, false, this);
589 r->output()->ensure_io (count, false, this);
595 /* prohibit auto-connect to master, because there isn't one */
596 bus_profile->output_ac = AutoConnectOption (bus_profile->output_ac & ~AutoConnectMaster);
600 add_routes (rl, false, false);
603 /* this allows the user to override settings with an environment variable.
606 if (no_auto_connect()) {
607 bus_profile->input_ac = AutoConnectOption (0);
608 bus_profile->output_ac = AutoConnectOption (0);
611 Config->set_input_auto_connect (bus_profile->input_ac);
612 Config->set_output_auto_connect (bus_profile->output_ac);
615 if (Config->get_use_monitor_bus() && bus_profile) {
616 add_monitor_section ();
625 Session::maybe_write_autosave()
627 if (dirty() && record_status() != Recording) {
628 save_state("", true);
633 Session::remove_pending_capture_state ()
635 sys::path pending_state_file_path(_session_dir->root_path());
637 pending_state_file_path /= legalize_for_path (_current_snapshot_name) + pending_suffix;
641 sys::remove (pending_state_file_path);
643 catch(sys::filesystem_error& ex)
645 error << string_compose(_("Could remove pending capture state at path \"%1\" (%2)"),
646 pending_state_file_path.to_string(), ex.what()) << endmsg;
650 /** Rename a state file.
651 * @param old_name Old snapshot name.
652 * @param new_name New snapshot name.
655 Session::rename_state (string old_name, string new_name)
657 if (old_name == _current_snapshot_name || old_name == _name) {
658 /* refuse to rename the current snapshot or the "main" one */
662 const string old_xml_filename = legalize_for_path (old_name) + statefile_suffix;
663 const string new_xml_filename = legalize_for_path (new_name) + statefile_suffix;
665 const sys::path old_xml_path = _session_dir->root_path() / old_xml_filename;
666 const sys::path new_xml_path = _session_dir->root_path() / new_xml_filename;
670 sys::rename (old_xml_path, new_xml_path);
672 catch (const sys::filesystem_error& err)
674 error << string_compose(_("could not rename snapshot %1 to %2 (%3)"),
675 old_name, new_name, err.what()) << endmsg;
679 /** Remove a state file.
680 * @param snapshot_name Snapshot name.
683 Session::remove_state (string snapshot_name)
685 if (snapshot_name == _current_snapshot_name || snapshot_name == _name) {
686 // refuse to remove the current snapshot or the "main" one
690 sys::path xml_path(_session_dir->root_path());
692 xml_path /= legalize_for_path (snapshot_name) + statefile_suffix;
694 if (!create_backup_file (xml_path)) {
695 // don't remove it if a backup can't be made
696 // create_backup_file will log the error.
701 sys::remove (xml_path);
704 #ifdef HAVE_JACK_SESSION
706 Session::jack_session_event (jack_session_event_t * event)
710 struct tm local_time;
713 localtime_r (&n, &local_time);
714 strftime (timebuf, sizeof(timebuf), "JS_%FT%T", &local_time);
716 if (event->type == JackSessionSaveTemplate)
718 if (save_template( timebuf )) {
719 event->flags = JackSessionSaveError;
721 string cmd ("ardour3 -P -U ");
722 cmd += event->client_uuid;
726 event->command_line = strdup (cmd.c_str());
731 if (save_state (timebuf)) {
732 event->flags = JackSessionSaveError;
734 sys::path xml_path (_session_dir->root_path());
735 xml_path /= legalize_for_path (timebuf) + statefile_suffix;
737 string cmd ("ardour3 -P -U ");
738 cmd += event->client_uuid;
740 cmd += xml_path.to_string();
743 event->command_line = strdup (cmd.c_str());
747 jack_session_reply (_engine.jack(), event);
749 if (event->type == JackSessionSaveAndQuit) {
750 Quit (); /* EMIT SIGNAL */
753 jack_session_event_free( event );
757 /** @param snapshot_name Name to save under, without .ardour / .pending prefix */
759 Session::save_state (string snapshot_name, bool pending, bool switch_to_snapshot)
762 sys::path xml_path(_session_dir->root_path());
764 if (!_writable || (_state_of_the_state & CannotSave)) {
768 if (!_engine.connected ()) {
769 error << string_compose (_("the %1 audio engine is not connected and state saving would lose all I/O connections. Session not saved"),
775 /* tell sources we're saving first, in case they write out to a new file
776 * which should be saved with the state rather than the old one */
777 for (SourceMap::const_iterator i = sources.begin(); i != sources.end(); ++i) {
779 i->second->session_saved();
780 } catch (Evoral::SMF::FileError& e) {
781 error << string_compose ("Could not write to MIDI file %1; MIDI data not saved.", e.file_name ()) << endmsg;
785 tree.set_root (&get_state());
787 if (snapshot_name.empty()) {
788 snapshot_name = _current_snapshot_name;
789 } else if (switch_to_snapshot) {
790 _current_snapshot_name = snapshot_name;
795 /* proper save: use statefile_suffix (.ardour in English) */
797 xml_path /= legalize_for_path (snapshot_name) + statefile_suffix;
799 /* make a backup copy of the old file */
801 if (sys::exists(xml_path) && !create_backup_file (xml_path)) {
802 // create_backup_file will log the error
808 /* pending save: use pending_suffix (.pending in English) */
809 xml_path /= legalize_for_path (snapshot_name) + pending_suffix;
812 sys::path tmp_path(_session_dir->root_path());
814 tmp_path /= legalize_for_path (snapshot_name) + temp_suffix;
816 // cerr << "actually writing state to " << xml_path.to_string() << endl;
818 if (!tree.write (tmp_path.to_string())) {
819 error << string_compose (_("state could not be saved to %1"), tmp_path.to_string()) << endmsg;
820 sys::remove (tmp_path);
825 if (::rename (tmp_path.to_string().c_str(), xml_path.to_string().c_str()) != 0) {
826 error << string_compose (_("could not rename temporary session file %1 to %2"),
827 tmp_path.to_string(), xml_path.to_string()) << endmsg;
828 sys::remove (tmp_path);
835 save_history (snapshot_name);
837 bool was_dirty = dirty();
839 _state_of_the_state = StateOfTheState (_state_of_the_state & ~Dirty);
842 DirtyChanged (); /* EMIT SIGNAL */
845 StateSaved (snapshot_name); /* EMIT SIGNAL */
852 Session::restore_state (string snapshot_name)
854 if (load_state (snapshot_name) == 0) {
855 set_state (*state_tree->root(), Stateful::loading_state_version);
862 Session::load_state (string snapshot_name)
867 state_was_pending = false;
869 /* check for leftover pending state from a crashed capture attempt */
871 sys::path xmlpath(_session_dir->root_path());
872 xmlpath /= legalize_for_path (snapshot_name) + pending_suffix;
874 if (sys::exists (xmlpath)) {
876 /* there is pending state from a crashed capture attempt */
878 boost::optional<int> r = AskAboutPendingState();
879 if (r.get_value_or (1)) {
880 state_was_pending = true;
884 if (!state_was_pending) {
885 xmlpath = _session_dir->root_path();
886 xmlpath /= snapshot_name;
889 if (!sys::exists (xmlpath)) {
890 xmlpath = _session_dir->root_path();
891 xmlpath /= legalize_for_path (snapshot_name) + statefile_suffix;
892 if (!sys::exists (xmlpath)) {
893 error << string_compose(_("%1: session state information file \"%2\" doesn't exist!"), _name, xmlpath.to_string()) << endmsg;
898 state_tree = new XMLTree;
902 _writable = exists_and_writable (xmlpath);
904 if (!state_tree->read (xmlpath.to_string())) {
905 error << string_compose(_("Could not understand ardour file %1"), xmlpath.to_string()) << endmsg;
911 XMLNode& root (*state_tree->root());
913 if (root.name() != X_("Session")) {
914 error << string_compose (_("Session file %1 is not a session"), xmlpath.to_string()) << endmsg;
920 const XMLProperty* prop;
922 if ((prop = root.property ("version")) == 0) {
923 /* no version implies very old version of Ardour */
924 Stateful::loading_state_version = 1000;
930 sscanf (prop->value().c_str(), "%d.%d.%d", &major, &minor, µ);
931 Stateful::loading_state_version = (major * 1000) + minor;
934 if (Stateful::loading_state_version < CURRENT_SESSION_FILE_VERSION) {
936 sys::path backup_path(_session_dir->root_path());
938 backup_path /= legalize_for_path (snapshot_name) + "-1" + statefile_suffix;
940 // only create a backup once
941 if (sys::exists (backup_path)) {
945 info << string_compose (_("Copying old session file %1 to %2\nUse %2 with %3 versions before 2.0 from now on"),
946 xmlpath.to_string(), backup_path.to_string(), PROGRAM_NAME)
951 sys::copy_file (xmlpath, backup_path);
953 catch(sys::filesystem_error& ex)
955 error << string_compose (_("Unable to make backup of state file %1 (%2)"),
956 xmlpath.to_string(), ex.what())
966 Session::load_options (const XMLNode& node)
968 LocaleGuard lg (X_("POSIX"));
969 config.set_variables (node);
980 Session::get_template()
982 /* if we don't disable rec-enable, diskstreams
983 will believe they need to store their capture
984 sources in their state node.
987 disable_record (false);
993 Session::state(bool full_state)
995 XMLNode* node = new XMLNode("Session");
998 // store libardour version, just in case
1000 snprintf(buf, sizeof(buf), "%d.%d.%d", libardour3_major_version, libardour3_minor_version, libardour3_micro_version);
1001 node->add_property("version", string(buf));
1003 /* store configuration settings */
1007 node->add_property ("name", _name);
1008 snprintf (buf, sizeof (buf), "%" PRId64, _nominal_frame_rate);
1009 node->add_property ("sample-rate", buf);
1011 if (session_dirs.size() > 1) {
1015 vector<space_and_path>::iterator i = session_dirs.begin();
1016 vector<space_and_path>::iterator next;
1018 ++i; /* skip the first one */
1022 while (i != session_dirs.end()) {
1026 if (next != session_dirs.end()) {
1036 child = node->add_child ("Path");
1037 child->add_content (p);
1041 /* save the ID counter */
1043 snprintf (buf, sizeof (buf), "%" PRIu64, ID::counter());
1044 node->add_property ("id-counter", buf);
1046 /* save the event ID counter */
1048 snprintf (buf, sizeof (buf), "%d", Evoral::event_id_counter());
1049 node->add_property ("event-counter", buf);
1051 /* various options */
1053 node->add_child_nocopy (config.get_variables ());
1055 node->add_child_nocopy (_metadata->get_state());
1057 child = node->add_child ("Sources");
1060 Glib::Mutex::Lock sl (source_lock);
1062 for (SourceMap::iterator siter = sources.begin(); siter != sources.end(); ++siter) {
1064 /* Don't save information about non-file Sources, or
1065 * about non-destructive file sources that are empty
1066 * and unused by any regions.
1069 boost::shared_ptr<FileSource> fs;
1071 if ((fs = boost::dynamic_pointer_cast<FileSource> (siter->second)) != 0) {
1073 if (!fs->destructive()) {
1074 if (fs->empty() && !fs->used()) {
1079 child->add_child_nocopy (siter->second->get_state());
1084 child = node->add_child ("Regions");
1087 Glib::Mutex::Lock rl (region_lock);
1088 const RegionFactory::RegionMap& region_map (RegionFactory::all_regions());
1089 for (RegionFactory::RegionMap::const_iterator i = region_map.begin(); i != region_map.end(); ++i) {
1090 boost::shared_ptr<Region> r = i->second;
1091 /* only store regions not attached to playlists */
1092 if (r->playlist() == 0) {
1093 child->add_child_nocopy (r->state ());
1097 RegionFactory::CompoundAssociations& cassocs (RegionFactory::compound_associations());
1099 if (!cassocs.empty()) {
1100 XMLNode* ca = node->add_child (X_("CompoundAssociations"));
1102 for (RegionFactory::CompoundAssociations::iterator i = cassocs.begin(); i != cassocs.end(); ++i) {
1104 XMLNode* can = new XMLNode (X_("CompoundAssociation"));
1105 i->first->id().print (buf, sizeof (buf));
1106 can->add_property (X_("copy"), buf);
1107 i->second->id().print (buf, sizeof (buf));
1108 can->add_property (X_("original"), buf);
1109 ca->add_child_nocopy (*can);
1115 node->add_child_nocopy (_locations->get_state());
1117 // for a template, just create a new Locations, populate it
1118 // with the default start and end, and get the state for that.
1119 Locations loc (*this);
1120 Location* range = new Location (*this, 0, 0, _("session"), Location::IsSessionRange);
1121 range->set (max_framepos, 0);
1123 node->add_child_nocopy (loc.get_state());
1126 child = node->add_child ("Bundles");
1128 boost::shared_ptr<BundleList> bundles = _bundles.reader ();
1129 for (BundleList::iterator i = bundles->begin(); i != bundles->end(); ++i) {
1130 boost::shared_ptr<UserBundle> b = boost::dynamic_pointer_cast<UserBundle> (*i);
1132 child->add_child_nocopy (b->get_state());
1137 child = node->add_child ("Routes");
1139 boost::shared_ptr<RouteList> r = routes.reader ();
1141 RoutePublicOrderSorter cmp;
1142 RouteList public_order (*r);
1143 public_order.sort (cmp);
1145 /* the sort should have put control outs first */
1148 assert (_monitor_out == public_order.front());
1151 for (RouteList::iterator i = public_order.begin(); i != public_order.end(); ++i) {
1152 if (!(*i)->is_hidden()) {
1154 child->add_child_nocopy ((*i)->get_state());
1156 child->add_child_nocopy ((*i)->get_template());
1162 playlists->add_state (node, full_state);
1164 child = node->add_child ("RouteGroups");
1165 for (list<RouteGroup *>::iterator i = _route_groups.begin(); i != _route_groups.end(); ++i) {
1166 child->add_child_nocopy ((*i)->get_state());
1170 child = node->add_child ("Click");
1171 child->add_child_nocopy (_click_io->state (full_state));
1175 child = node->add_child ("NamedSelections");
1176 for (NamedSelectionList::iterator i = named_selections.begin(); i != named_selections.end(); ++i) {
1178 child->add_child_nocopy ((*i)->get_state());
1183 node->add_child_nocopy (_speakers->get_state());
1184 node->add_child_nocopy (_tempo_map->get_state());
1185 node->add_child_nocopy (get_control_protocol_state());
1188 node->add_child_copy (*_extra_xml);
1195 Session::get_control_protocol_state ()
1197 ControlProtocolManager& cpm (ControlProtocolManager::instance());
1198 return cpm.get_state();
1202 Session::set_state (const XMLNode& node, int version)
1206 const XMLProperty* prop;
1209 _state_of_the_state = StateOfTheState (_state_of_the_state|CannotSave);
1211 if (node.name() != X_("Session")) {
1212 fatal << _("programming error: Session: incorrect XML node sent to set_state()") << endmsg;
1216 if ((prop = node.property ("version")) != 0) {
1217 version = atoi (prop->value ()) * 1000;
1220 if ((prop = node.property ("name")) != 0) {
1221 _name = prop->value ();
1224 if ((prop = node.property (X_("sample-rate"))) != 0) {
1226 _nominal_frame_rate = atoi (prop->value());
1228 if (_nominal_frame_rate != _current_frame_rate) {
1229 boost::optional<int> r = AskAboutSampleRateMismatch (_nominal_frame_rate, _current_frame_rate);
1230 if (r.get_value_or (0)) {
1236 setup_raid_path(_session_dir->root_path().to_string());
1238 if ((prop = node.property (X_("id-counter"))) != 0) {
1240 sscanf (prop->value().c_str(), "%" PRIu64, &x);
1241 ID::init_counter (x);
1243 /* old sessions used a timebased counter, so fake
1244 the startup ID counter based on a standard
1249 ID::init_counter (now);
1252 if ((prop = node.property (X_("event-counter"))) != 0) {
1253 Evoral::init_event_id_counter (atoi (prop->value()));
1256 IO::disable_connecting ();
1258 Stateful::save_extra_xml (node);
1260 if (((child = find_named_node (node, "Options")) != 0)) { /* old style */
1261 load_options (*child);
1262 } else if ((child = find_named_node (node, "Config")) != 0) { /* new style */
1263 load_options (*child);
1265 error << _("Session: XML state has no options section") << endmsg;
1268 if (version >= 3000) {
1269 if ((child = find_named_node (node, "Metadata")) == 0) {
1270 warning << _("Session: XML state has no metadata section") << endmsg;
1271 } else if (_metadata->set_state (*child, version)) {
1276 if ((child = find_named_node (node, X_("Speakers"))) != 0) {
1277 _speakers->set_state (*child, version);
1280 if ((child = find_named_node (node, "Sources")) == 0) {
1281 error << _("Session: XML state has no sources section") << endmsg;
1283 } else if (load_sources (*child)) {
1287 if ((child = find_named_node (node, "TempoMap")) == 0) {
1288 error << _("Session: XML state has no Tempo Map section") << endmsg;
1290 } else if (_tempo_map->set_state (*child, version)) {
1294 if ((child = find_named_node (node, "Locations")) == 0) {
1295 error << _("Session: XML state has no locations section") << endmsg;
1297 } else if (_locations->set_state (*child, version)) {
1303 if ((location = _locations->auto_loop_location()) != 0) {
1304 set_auto_loop_location (location);
1307 if ((location = _locations->auto_punch_location()) != 0) {
1308 set_auto_punch_location (location);
1311 if ((location = _locations->session_range_location()) != 0) {
1312 delete _session_range_location;
1313 _session_range_location = location;
1316 if (_session_range_location) {
1317 AudioFileSource::set_header_position_offset (_session_range_location->start());
1320 if ((child = find_named_node (node, "Regions")) == 0) {
1321 error << _("Session: XML state has no Regions section") << endmsg;
1323 } else if (load_regions (*child)) {
1327 if ((child = find_named_node (node, "Playlists")) == 0) {
1328 error << _("Session: XML state has no playlists section") << endmsg;
1330 } else if (playlists->load (*this, *child)) {
1334 if ((child = find_named_node (node, "UnusedPlaylists")) == 0) {
1336 } else if (playlists->load_unused (*this, *child)) {
1340 if ((child = find_named_node (node, "CompoundAssociations")) != 0) {
1341 if (load_compounds (*child)) {
1346 if ((child = find_named_node (node, "NamedSelections")) != 0) {
1347 if (load_named_selections (*child)) {
1352 if (version >= 3000) {
1353 if ((child = find_named_node (node, "Bundles")) == 0) {
1354 warning << _("Session: XML state has no bundles section") << endmsg;
1357 /* We can't load Bundles yet as they need to be able
1358 to convert from port names to Port objects, which can't happen until
1360 _bundle_xml_node = new XMLNode (*child);
1364 if (version < 3000) {
1365 if ((child = find_named_node (node, X_("DiskStreams"))) == 0) {
1366 error << _("Session: XML state has no diskstreams section") << endmsg;
1368 } else if (load_diskstreams_2X (*child, version)) {
1373 if ((child = find_named_node (node, "Routes")) == 0) {
1374 error << _("Session: XML state has no routes section") << endmsg;
1376 } else if (load_routes (*child, version)) {
1380 /* our diskstreams list is no longer needed as they are now all owned by their Route */
1381 _diskstreams_2X.clear ();
1383 if (version >= 3000) {
1385 if ((child = find_named_node (node, "RouteGroups")) == 0) {
1386 error << _("Session: XML state has no route groups section") << endmsg;
1388 } else if (load_route_groups (*child, version)) {
1392 } else if (version < 3000) {
1394 if ((child = find_named_node (node, "EditGroups")) == 0) {
1395 error << _("Session: XML state has no edit groups section") << endmsg;
1397 } else if (load_route_groups (*child, version)) {
1401 if ((child = find_named_node (node, "MixGroups")) == 0) {
1402 error << _("Session: XML state has no mix groups section") << endmsg;
1404 } else if (load_route_groups (*child, version)) {
1409 if ((child = find_named_node (node, "Click")) == 0) {
1410 warning << _("Session: XML state has no click section") << endmsg;
1411 } else if (_click_io) {
1412 _click_io->set_state (*child, version);
1415 if ((child = find_named_node (node, "ControlProtocols")) != 0) {
1416 ControlProtocolManager::instance().set_protocol_states (*child);
1419 /* here beginneth the second phase ... */
1421 StateReady (); /* EMIT SIGNAL */
1430 Session::load_routes (const XMLNode& node, int version)
1433 XMLNodeConstIterator niter;
1434 RouteList new_routes;
1436 nlist = node.children();
1440 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1442 boost::shared_ptr<Route> route;
1443 if (version < 3000) {
1444 route = XMLRouteFactory_2X (**niter, version);
1446 route = XMLRouteFactory (**niter, version);
1450 error << _("Session: cannot create Route from XML description.") << endmsg;
1454 BootMessage (string_compose (_("Loaded track/bus %1"), route->name()));
1456 new_routes.push_back (route);
1459 add_routes (new_routes, false, false);
1464 boost::shared_ptr<Route>
1465 Session::XMLRouteFactory (const XMLNode& node, int version)
1467 boost::shared_ptr<Route> ret;
1469 if (node.name() != "Route") {
1473 XMLNode* ds_child = find_named_node (node, X_("Diskstream"));
1475 DataType type = DataType::AUDIO;
1476 const XMLProperty* prop = node.property("default-type");
1479 type = DataType (prop->value());
1482 assert (type != DataType::NIL);
1486 boost::shared_ptr<Track> track;
1488 if (type == DataType::AUDIO) {
1489 track.reset (new AudioTrack (*this, X_("toBeResetFroXML")));
1491 track.reset (new MidiTrack (*this, X_("toBeResetFroXML")));
1494 if (track->init()) {
1498 if (track->set_state (node, version)) {
1502 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
1503 // boost_debug_shared_ptr_mark_interesting (track.get(), "Track");
1508 boost::shared_ptr<Route> r (new Route (*this, X_("toBeResetFroXML")));
1510 if (r->init () == 0 && r->set_state (node, version) == 0) {
1511 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
1512 // boost_debug_shared_ptr_mark_interesting (r.get(), "Route");
1521 boost::shared_ptr<Route>
1522 Session::XMLRouteFactory_2X (const XMLNode& node, int version)
1524 boost::shared_ptr<Route> ret;
1526 if (node.name() != "Route") {
1530 XMLProperty const * ds_prop = node.property (X_("diskstream-id"));
1532 ds_prop = node.property (X_("diskstream"));
1535 DataType type = DataType::AUDIO;
1536 const XMLProperty* prop = node.property("default-type");
1539 type = DataType (prop->value());
1542 assert (type != DataType::NIL);
1546 list<boost::shared_ptr<Diskstream> >::iterator i = _diskstreams_2X.begin ();
1547 while (i != _diskstreams_2X.end() && (*i)->id() != ds_prop->value()) {
1551 if (i == _diskstreams_2X.end()) {
1552 error << _("Could not find diskstream for route") << endmsg;
1553 return boost::shared_ptr<Route> ();
1556 boost::shared_ptr<Track> track;
1558 if (type == DataType::AUDIO) {
1559 track.reset (new AudioTrack (*this, X_("toBeResetFroXML")));
1561 track.reset (new MidiTrack (*this, X_("toBeResetFroXML")));
1564 if (track->init()) {
1568 if (track->set_state (node, version)) {
1572 track->set_diskstream (*i);
1574 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
1575 // boost_debug_shared_ptr_mark_interesting (track.get(), "Track");
1580 boost::shared_ptr<Route> r (new Route (*this, X_("toBeResetFroXML")));
1582 if (r->init () == 0 && r->set_state (node, version) == 0) {
1583 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
1584 // boost_debug_shared_ptr_mark_interesting (r.get(), "Route");
1594 Session::load_regions (const XMLNode& node)
1597 XMLNodeConstIterator niter;
1598 boost::shared_ptr<Region> region;
1600 nlist = node.children();
1604 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1605 if ((region = XMLRegionFactory (**niter, false)) == 0) {
1606 error << _("Session: cannot create Region from XML description.");
1607 const XMLProperty *name = (**niter).property("name");
1610 error << " " << string_compose (_("Can not load state for region '%1'"), name->value());
1621 Session::load_compounds (const XMLNode& node)
1623 XMLNodeList calist = node.children();
1624 XMLNodeConstIterator caiter;
1625 XMLProperty *caprop;
1627 for (caiter = calist.begin(); caiter != calist.end(); ++caiter) {
1628 XMLNode* ca = *caiter;
1632 if ((caprop = ca->property (X_("original"))) == 0) {
1635 orig_id = caprop->value();
1637 if ((caprop = ca->property (X_("copy"))) == 0) {
1640 copy_id = caprop->value();
1642 boost::shared_ptr<Region> orig = RegionFactory::region_by_id (orig_id);
1643 boost::shared_ptr<Region> copy = RegionFactory::region_by_id (copy_id);
1645 if (!orig || !copy) {
1646 warning << string_compose (_("Regions in compound description not found (ID's %1 and %2): ignored"),
1652 RegionFactory::add_compound_association (orig, copy);
1659 Session::load_nested_sources (const XMLNode& node)
1662 XMLNodeConstIterator niter;
1664 nlist = node.children();
1666 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1667 if ((*niter)->name() == "Source") {
1669 /* it may already exist, so don't recreate it unnecessarily
1672 XMLProperty* prop = (*niter)->property (X_("id"));
1674 error << _("Nested source has no ID info in session state file! (ignored)") << endmsg;
1678 ID source_id (prop->value());
1680 if (!source_by_id (source_id)) {
1683 SourceFactory::create (*this, **niter, true);
1685 catch (failed_constructor& err) {
1686 error << string_compose (_("Cannot reconstruct nested source for region %1"), name()) << endmsg;
1693 boost::shared_ptr<Region>
1694 Session::XMLRegionFactory (const XMLNode& node, bool full)
1696 const XMLProperty* type = node.property("type");
1700 const XMLNodeList& nlist = node.children();
1702 for (XMLNodeConstIterator niter = nlist.begin(); niter != nlist.end(); ++niter) {
1703 XMLNode *child = (*niter);
1704 if (child->name() == "NestedSource") {
1705 load_nested_sources (*child);
1709 if (!type || type->value() == "audio") {
1710 return boost::shared_ptr<Region>(XMLAudioRegionFactory (node, full));
1711 } else if (type->value() == "midi") {
1712 return boost::shared_ptr<Region>(XMLMidiRegionFactory (node, full));
1715 } catch (failed_constructor& err) {
1716 return boost::shared_ptr<Region> ();
1719 return boost::shared_ptr<Region> ();
1722 boost::shared_ptr<AudioRegion>
1723 Session::XMLAudioRegionFactory (const XMLNode& node, bool /*full*/)
1725 const XMLProperty* prop;
1726 boost::shared_ptr<Source> source;
1727 boost::shared_ptr<AudioSource> as;
1729 SourceList master_sources;
1730 uint32_t nchans = 1;
1733 if (node.name() != X_("Region")) {
1734 return boost::shared_ptr<AudioRegion>();
1737 if ((prop = node.property (X_("channels"))) != 0) {
1738 nchans = atoi (prop->value().c_str());
1741 if ((prop = node.property ("name")) == 0) {
1742 cerr << "no name for this region\n";
1746 if ((prop = node.property (X_("source-0"))) == 0) {
1747 if ((prop = node.property ("source")) == 0) {
1748 error << _("Session: XMLNode describing a AudioRegion is incomplete (no source)") << endmsg;
1749 return boost::shared_ptr<AudioRegion>();
1753 PBD::ID s_id (prop->value());
1755 if ((source = source_by_id (s_id)) == 0) {
1756 error << string_compose(_("Session: XMLNode describing a AudioRegion references an unknown source id =%1"), s_id) << endmsg;
1757 return boost::shared_ptr<AudioRegion>();
1760 as = boost::dynamic_pointer_cast<AudioSource>(source);
1762 error << string_compose(_("Session: XMLNode describing a AudioRegion references a non-audio source id =%1"), s_id) << endmsg;
1763 return boost::shared_ptr<AudioRegion>();
1766 sources.push_back (as);
1768 /* pickup other channels */
1770 for (uint32_t n=1; n < nchans; ++n) {
1771 snprintf (buf, sizeof(buf), X_("source-%d"), n);
1772 if ((prop = node.property (buf)) != 0) {
1774 PBD::ID id2 (prop->value());
1776 if ((source = source_by_id (id2)) == 0) {
1777 error << string_compose(_("Session: XMLNode describing a AudioRegion references an unknown source id =%1"), id2) << endmsg;
1778 return boost::shared_ptr<AudioRegion>();
1781 as = boost::dynamic_pointer_cast<AudioSource>(source);
1783 error << string_compose(_("Session: XMLNode describing a AudioRegion references a non-audio source id =%1"), id2) << endmsg;
1784 return boost::shared_ptr<AudioRegion>();
1786 sources.push_back (as);
1790 for (uint32_t n = 0; n < nchans; ++n) {
1791 snprintf (buf, sizeof(buf), X_("master-source-%d"), n);
1792 if ((prop = node.property (buf)) != 0) {
1794 PBD::ID id2 (prop->value());
1796 if ((source = source_by_id (id2)) == 0) {
1797 error << string_compose(_("Session: XMLNode describing a AudioRegion references an unknown source id =%1"), id2) << endmsg;
1798 return boost::shared_ptr<AudioRegion>();
1801 as = boost::dynamic_pointer_cast<AudioSource>(source);
1803 error << string_compose(_("Session: XMLNode describing a AudioRegion references a non-audio source id =%1"), id2) << endmsg;
1804 return boost::shared_ptr<AudioRegion>();
1806 master_sources.push_back (as);
1811 boost::shared_ptr<AudioRegion> region (boost::dynamic_pointer_cast<AudioRegion> (RegionFactory::create (sources, node)));
1813 /* a final detail: this is the one and only place that we know how long missing files are */
1815 if (region->whole_file()) {
1816 for (SourceList::iterator sx = sources.begin(); sx != sources.end(); ++sx) {
1817 boost::shared_ptr<SilentFileSource> sfp = boost::dynamic_pointer_cast<SilentFileSource> (*sx);
1819 sfp->set_length (region->length());
1824 if (!master_sources.empty()) {
1825 if (master_sources.size() != nchans) {
1826 error << _("Session: XMLNode describing an AudioRegion is missing some master sources; ignored") << endmsg;
1828 region->set_master_sources (master_sources);
1836 catch (failed_constructor& err) {
1837 return boost::shared_ptr<AudioRegion>();
1841 boost::shared_ptr<MidiRegion>
1842 Session::XMLMidiRegionFactory (const XMLNode& node, bool /*full*/)
1844 const XMLProperty* prop;
1845 boost::shared_ptr<Source> source;
1846 boost::shared_ptr<MidiSource> ms;
1849 if (node.name() != X_("Region")) {
1850 return boost::shared_ptr<MidiRegion>();
1853 if ((prop = node.property ("name")) == 0) {
1854 cerr << "no name for this region\n";
1858 if ((prop = node.property (X_("source-0"))) == 0) {
1859 if ((prop = node.property ("source")) == 0) {
1860 error << _("Session: XMLNode describing a MidiRegion is incomplete (no source)") << endmsg;
1861 return boost::shared_ptr<MidiRegion>();
1865 PBD::ID s_id (prop->value());
1867 if ((source = source_by_id (s_id)) == 0) {
1868 error << string_compose(_("Session: XMLNode describing a MidiRegion references an unknown source id =%1"), s_id) << endmsg;
1869 return boost::shared_ptr<MidiRegion>();
1872 ms = boost::dynamic_pointer_cast<MidiSource>(source);
1874 error << string_compose(_("Session: XMLNode describing a MidiRegion references a non-midi source id =%1"), s_id) << endmsg;
1875 return boost::shared_ptr<MidiRegion>();
1878 sources.push_back (ms);
1881 boost::shared_ptr<MidiRegion> region (boost::dynamic_pointer_cast<MidiRegion> (RegionFactory::create (sources, node)));
1882 /* a final detail: this is the one and only place that we know how long missing files are */
1884 if (region->whole_file()) {
1885 for (SourceList::iterator sx = sources.begin(); sx != sources.end(); ++sx) {
1886 boost::shared_ptr<SilentFileSource> sfp = boost::dynamic_pointer_cast<SilentFileSource> (*sx);
1888 sfp->set_length (region->length());
1896 catch (failed_constructor& err) {
1897 return boost::shared_ptr<MidiRegion>();
1902 Session::get_sources_as_xml ()
1905 XMLNode* node = new XMLNode (X_("Sources"));
1906 Glib::Mutex::Lock lm (source_lock);
1908 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ++i) {
1909 node->add_child_nocopy (i->second->get_state());
1916 Session::path_from_region_name (DataType type, string name, string identifier)
1918 char buf[PATH_MAX+1];
1920 SessionDirectory sdir(get_best_session_directory_for_new_source());
1921 sys::path source_dir = ((type == DataType::AUDIO)
1922 ? sdir.sound_path() : sdir.midi_path());
1924 string ext = native_header_format_extension (config.get_native_file_header_format(), type);
1926 for (n = 0; n < 999999; ++n) {
1927 if (identifier.length()) {
1928 snprintf (buf, sizeof(buf), "%s%s%" PRIu32 "%s", name.c_str(),
1929 identifier.c_str(), n, ext.c_str());
1931 snprintf (buf, sizeof(buf), "%s-%" PRIu32 "%s", name.c_str(),
1935 sys::path source_path = source_dir / buf;
1937 if (!sys::exists (source_path)) {
1938 return source_path.to_string();
1942 error << string_compose (_("cannot create new file from region name \"%1\" with ident = \"%2\": too many existing files with similar names"),
1951 Session::load_sources (const XMLNode& node)
1954 XMLNodeConstIterator niter;
1955 boost::shared_ptr<Source> source;
1957 nlist = node.children();
1961 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1964 if ((source = XMLSourceFactory (**niter)) == 0) {
1965 error << _("Session: cannot create Source from XML description.") << endmsg;
1968 } catch (MissingSource& err) {
1972 if (!no_questions_about_missing_files) {
1973 user_choice = MissingFile (this, err.path, err.type).get_value_or (-1);
1978 switch (user_choice) {
1980 /* user added a new search location, so try again */
1985 /* user asked to quit the entire session load
1990 no_questions_about_missing_files = true;
1994 no_questions_about_missing_files = true;
1999 warning << _("A sound file is missing. It will be replaced by silence.") << endmsg;
2000 source = SourceFactory::createSilent (*this, **niter, max_framecnt, _current_frame_rate);
2009 boost::shared_ptr<Source>
2010 Session::XMLSourceFactory (const XMLNode& node)
2012 if (node.name() != "Source") {
2013 return boost::shared_ptr<Source>();
2017 /* note: do peak building in another thread when loading session state */
2018 return SourceFactory::create (*this, node, true);
2021 catch (failed_constructor& err) {
2022 error << string_compose (_("Found a sound file that cannot be used by %1. Talk to the progammers."), PROGRAM_NAME) << endmsg;
2023 return boost::shared_ptr<Source>();
2028 Session::save_template (string template_name)
2032 if (_state_of_the_state & CannotSave) {
2036 sys::path user_template_dir(user_template_directory());
2040 sys::create_directories (user_template_dir);
2042 catch(sys::filesystem_error& ex)
2044 error << string_compose(_("Could not create templates directory \"%1\" (%2)"),
2045 user_template_dir.to_string(), ex.what()) << endmsg;
2049 tree.set_root (&get_template());
2051 sys::path template_dir_path(user_template_dir);
2053 /* directory to put the template in */
2054 template_dir_path /= template_name;
2055 if (sys::exists (template_dir_path))
2057 warning << string_compose(_("Template \"%1\" already exists - new version not created"),
2058 template_dir_path.to_string()) << endmsg;
2062 sys::create_directories (template_dir_path);
2065 sys::path template_file_path = template_dir_path;
2066 template_file_path /= template_name + template_suffix;
2068 if (!tree.write (template_file_path.to_string())) {
2069 error << _("template not saved") << endmsg;
2073 /* copy plugin state directory */
2075 sys::path template_plugin_state_path = template_dir_path;
2076 template_plugin_state_path /= X_("plugins");
2077 sys::create_directories (template_plugin_state_path);
2078 sys::copy_files (plugins_dir(), template_plugin_state_path);
2084 Session::refresh_disk_space ()
2087 struct statfs statfsbuf;
2088 vector<space_and_path>::iterator i;
2089 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;
2096 for (i = session_dirs.begin(); i != session_dirs.end(); ++i) {
2097 statfs ((*i).path.c_str(), &statfsbuf);
2099 scale = statfsbuf.f_bsize/4096.0;
2101 (*i).blocks = (uint32_t) floor (statfsbuf.f_bavail * scale);
2102 _total_free_4k_blocks += (*i).blocks;
2108 Session::get_best_session_directory_for_new_source ()
2110 vector<space_and_path>::iterator i;
2111 string result = _session_dir->root_path().to_string();
2113 /* handle common case without system calls */
2115 if (session_dirs.size() == 1) {
2119 /* OK, here's the algorithm we're following here:
2121 We want to select which directory to use for
2122 the next file source to be created. Ideally,
2123 we'd like to use a round-robin process so as to
2124 get maximum performance benefits from splitting
2125 the files across multiple disks.
2127 However, in situations without much diskspace, an
2128 RR approach may end up filling up a filesystem
2129 with new files while others still have space.
2130 Its therefore important to pay some attention to
2131 the freespace in the filesystem holding each
2132 directory as well. However, if we did that by
2133 itself, we'd keep creating new files in the file
2134 system with the most space until it was as full
2135 as all others, thus negating any performance
2136 benefits of this RAID-1 like approach.
2138 So, we use a user-configurable space threshold. If
2139 there are at least 2 filesystems with more than this
2140 much space available, we use RR selection between them.
2141 If not, then we pick the filesystem with the most space.
2143 This gets a good balance between the two
2147 refresh_disk_space ();
2149 int free_enough = 0;
2151 for (i = session_dirs.begin(); i != session_dirs.end(); ++i) {
2152 if ((*i).blocks * 4096 >= Config->get_disk_choice_space_threshold()) {
2157 if (free_enough >= 2) {
2158 /* use RR selection process, ensuring that the one
2162 i = last_rr_session_dir;
2165 if (++i == session_dirs.end()) {
2166 i = session_dirs.begin();
2169 if ((*i).blocks * 4096 >= Config->get_disk_choice_space_threshold()) {
2170 if (create_session_directory ((*i).path)) {
2172 last_rr_session_dir = i;
2177 } while (i != last_rr_session_dir);
2181 /* pick FS with the most freespace (and that
2182 seems to actually work ...)
2185 vector<space_and_path> sorted;
2186 space_and_path_ascending_cmp cmp;
2188 sorted = session_dirs;
2189 sort (sorted.begin(), sorted.end(), cmp);
2191 for (i = sorted.begin(); i != sorted.end(); ++i) {
2192 if (create_session_directory ((*i).path)) {
2194 last_rr_session_dir = i;
2204 Session::load_named_selections (const XMLNode& node)
2207 XMLNodeConstIterator niter;
2210 nlist = node.children();
2214 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2216 if ((ns = XMLNamedSelectionFactory (**niter)) == 0) {
2217 error << _("Session: cannot create Named Selection from XML description.") << endmsg;
2225 Session::XMLNamedSelectionFactory (const XMLNode& node)
2228 return new NamedSelection (*this, node);
2231 catch (failed_constructor& err) {
2237 Session::automation_dir () const
2239 return Glib::build_filename (_path, "automation");
2243 Session::analysis_dir () const
2245 return Glib::build_filename (_path, "analysis");
2249 Session::plugins_dir () const
2251 return Glib::build_filename (_path, "plugins");
2255 Session::load_bundles (XMLNode const & node)
2257 XMLNodeList nlist = node.children();
2258 XMLNodeConstIterator niter;
2262 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2263 if ((*niter)->name() == "InputBundle") {
2264 add_bundle (boost::shared_ptr<UserBundle> (new UserBundle (**niter, true)));
2265 } else if ((*niter)->name() == "OutputBundle") {
2266 add_bundle (boost::shared_ptr<UserBundle> (new UserBundle (**niter, false)));
2268 error << string_compose(_("Unknown node \"%1\" found in Bundles list from state file"), (*niter)->name()) << endmsg;
2277 Session::load_route_groups (const XMLNode& node, int version)
2279 XMLNodeList nlist = node.children();
2280 XMLNodeConstIterator niter;
2284 if (version >= 3000) {
2286 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2287 if ((*niter)->name() == "RouteGroup") {
2288 RouteGroup* rg = new RouteGroup (*this, "");
2289 add_route_group (rg);
2290 rg->set_state (**niter, version);
2294 } else if (version < 3000) {
2296 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2297 if ((*niter)->name() == "EditGroup" || (*niter)->name() == "MixGroup") {
2298 RouteGroup* rg = new RouteGroup (*this, "");
2299 add_route_group (rg);
2300 rg->set_state (**niter, version);
2309 Session::auto_save()
2311 save_state (_current_snapshot_name);
2315 state_file_filter (const string &str, void */*arg*/)
2317 return (str.length() > strlen(statefile_suffix) &&
2318 str.find (statefile_suffix) == (str.length() - strlen (statefile_suffix)));
2322 bool operator()(const string* a, const string* b) {
2328 remove_end(string* state)
2330 string statename(*state);
2332 string::size_type start,end;
2333 if ((start = statename.find_last_of (G_DIR_SEPARATOR)) != string::npos) {
2334 statename = statename.substr (start+1);
2337 if ((end = statename.rfind(".ardour")) == string::npos) {
2338 end = statename.length();
2341 return new string(statename.substr (0, end));
2345 Session::possible_states (string path)
2347 PathScanner scanner;
2348 vector<string*>* states = scanner (path, state_file_filter, 0, false, false);
2350 transform(states->begin(), states->end(), states->begin(), remove_end);
2353 sort (states->begin(), states->end(), cmp);
2359 Session::possible_states () const
2361 return possible_states(_path);
2365 Session::add_route_group (RouteGroup* g)
2367 _route_groups.push_back (g);
2368 route_group_added (g); /* EMIT SIGNAL */
2370 g->RouteAdded.connect_same_thread (*this, boost::bind (&Session::route_added_to_route_group, this, _1, _2));
2371 g->RouteRemoved.connect_same_thread (*this, boost::bind (&Session::route_removed_from_route_group, this, _1, _2));
2372 g->PropertyChanged.connect_same_thread (*this, boost::bind (&Session::route_group_property_changed, this, g));
2378 Session::remove_route_group (RouteGroup& rg)
2380 list<RouteGroup*>::iterator i;
2382 if ((i = find (_route_groups.begin(), _route_groups.end(), &rg)) != _route_groups.end()) {
2383 _route_groups.erase (i);
2386 route_group_removed (); /* EMIT SIGNAL */
2390 /** Set a new order for our route groups, without adding or removing any.
2391 * @param groups Route group list in the new order.
2394 Session::reorder_route_groups (list<RouteGroup*> groups)
2396 _route_groups = groups;
2398 route_groups_reordered (); /* EMIT SIGNAL */
2404 Session::route_group_by_name (string name)
2406 list<RouteGroup *>::iterator i;
2408 for (i = _route_groups.begin(); i != _route_groups.end(); ++i) {
2409 if ((*i)->name() == name) {
2417 Session::all_route_group() const
2419 return *_all_route_group;
2423 Session::add_commands (vector<Command*> const & cmds)
2425 for (vector<Command*>::const_iterator i = cmds.begin(); i != cmds.end(); ++i) {
2431 Session::begin_reversible_command (const string& name)
2433 begin_reversible_command (g_quark_from_string (name.c_str ()));
2436 /** Begin a reversible command using a GQuark to identify it.
2437 * begin_reversible_command() and commit_reversible_command() calls may be nested,
2438 * but there must be as many begin...()s as there are commit...()s.
2441 Session::begin_reversible_command (GQuark q)
2443 /* If nested begin/commit pairs are used, we create just one UndoTransaction
2444 to hold all the commands that are committed. This keeps the order of
2445 commands correct in the history.
2448 if (_current_trans == 0) {
2449 /* start a new transaction */
2450 assert (_current_trans_quarks.empty ());
2451 _current_trans = new UndoTransaction();
2452 _current_trans->set_name (g_quark_to_string (q));
2455 _current_trans_quarks.push_front (q);
2459 Session::commit_reversible_command (Command *cmd)
2461 assert (_current_trans);
2462 assert (!_current_trans_quarks.empty ());
2467 _current_trans->add_command (cmd);
2470 _current_trans_quarks.pop_front ();
2472 if (!_current_trans_quarks.empty ()) {
2473 /* the transaction we're committing is not the top-level one */
2477 if (_current_trans->empty()) {
2478 /* no commands were added to the transaction, so just get rid of it */
2479 delete _current_trans;
2484 gettimeofday (&now, 0);
2485 _current_trans->set_timestamp (now);
2487 _history.add (_current_trans);
2492 accept_all_audio_files (const string& path, void */*arg*/)
2494 if (!Glib::file_test (path, Glib::FILE_TEST_IS_REGULAR)) {
2498 if (!AudioFileSource::safe_audio_file_extension (path)) {
2506 accept_all_midi_files (const string& path, void */*arg*/)
2508 if (!Glib::file_test (path, Glib::FILE_TEST_IS_REGULAR)) {
2512 return ((path.length() > 4 && path.find (".mid") != (path.length() - 4)) ||
2513 (path.length() > 4 && path.find (".smf") != (path.length() - 4)) ||
2514 (path.length() > 5 && path.find (".midi") != (path.length() - 5)));
2518 accept_all_state_files (const string& path, void */*arg*/)
2520 if (!Glib::file_test (path, Glib::FILE_TEST_IS_REGULAR)) {
2524 return (path.length() > 7 && path.find (".ardour") == (path.length() - 7));
2528 Session::find_all_sources (string path, set<string>& result)
2533 if (!tree.read (path)) {
2537 if ((node = find_named_node (*tree.root(), "Sources")) == 0) {
2542 XMLNodeConstIterator niter;
2544 nlist = node->children();
2548 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2552 if ((prop = (*niter)->property (X_("type"))) == 0) {
2556 DataType type (prop->value());
2558 if ((prop = (*niter)->property (X_("name"))) == 0) {
2562 if (Glib::path_is_absolute (prop->value())) {
2563 /* external file, ignore */
2571 if (FileSource::find (*this, type, prop->value(), true, is_new, chan, found_path)) {
2572 result.insert (found_path);
2580 Session::find_all_sources_across_snapshots (set<string>& result, bool exclude_this_snapshot)
2582 PathScanner scanner;
2583 vector<string*>* state_files;
2585 string this_snapshot_path;
2591 if (ripped[ripped.length()-1] == G_DIR_SEPARATOR) {
2592 ripped = ripped.substr (0, ripped.length() - 1);
2595 state_files = scanner (ripped, accept_all_state_files, (void *) 0, false, true);
2597 if (state_files == 0) {
2602 this_snapshot_path = _path;
2603 this_snapshot_path += legalize_for_path (_current_snapshot_name);
2604 this_snapshot_path += statefile_suffix;
2606 for (vector<string*>::iterator i = state_files->begin(); i != state_files->end(); ++i) {
2608 if (exclude_this_snapshot && **i == this_snapshot_path) {
2612 if (find_all_sources (**i, result) < 0) {
2620 struct RegionCounter {
2621 typedef std::map<PBD::ID,boost::shared_ptr<AudioSource> > AudioSourceList;
2622 AudioSourceList::iterator iter;
2623 boost::shared_ptr<Region> region;
2626 RegionCounter() : count (0) {}
2630 Session::ask_about_playlist_deletion (boost::shared_ptr<Playlist> p)
2632 boost::optional<int> r = AskAboutPlaylistDeletion (p);
2633 return r.get_value_or (1);
2637 Session::cleanup_regions ()
2639 const RegionFactory::RegionMap& regions (RegionFactory::regions());
2641 for (RegionFactory::RegionMap::const_iterator i = regions.begin(); i != regions.end(); ++i) {
2643 uint32_t used = playlists->region_use_count (i->second);
2645 if (used == 0 && !i->second->automatic ()) {
2646 RegionFactory::map_remove (i->second);
2650 /* dump the history list */
2657 Session::cleanup_sources (CleanupReport& rep)
2659 // FIXME: needs adaptation to midi
2661 vector<boost::shared_ptr<Source> > dead_sources;
2662 PathScanner scanner;
2665 vector<space_and_path>::iterator i;
2666 vector<space_and_path>::iterator nexti;
2667 vector<string*>* candidates;
2668 vector<string*>* candidates2;
2669 vector<string> unused;
2670 set<string> all_sources;
2675 _state_of_the_state = (StateOfTheState) (_state_of_the_state | InCleanup);
2677 /* consider deleting all unused playlists */
2679 if (playlists->maybe_delete_unused (boost::bind (Session::ask_about_playlist_deletion, _1))) {
2684 /* sync the "all regions" property of each playlist with its current state
2687 playlists->sync_all_regions_with_regions ();
2689 /* find all un-used sources */
2694 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ) {
2696 SourceMap::iterator tmp;
2701 /* do not bother with files that are zero size, otherwise we remove the current "nascent"
2705 if (!i->second->used() && (i->second->length(i->second->timeline_position() > 0))) {
2706 dead_sources.push_back (i->second);
2707 i->second->drop_references ();
2713 /* build a list of all the possible audio directories for the session */
2715 for (i = session_dirs.begin(); i != session_dirs.end(); ) {
2720 SessionDirectory sdir ((*i).path);
2721 audio_path += sdir.sound_path().to_string();
2723 if (nexti != session_dirs.end()) {
2731 /* build a list of all the possible midi directories for the session */
2733 for (i = session_dirs.begin(); i != session_dirs.end(); ) {
2738 SessionDirectory sdir ((*i).path);
2739 midi_path += sdir.midi_path().to_string();
2741 if (nexti != session_dirs.end()) {
2748 candidates = scanner (audio_path, accept_all_audio_files, (void *) 0, true, true);
2749 candidates2 = scanner (midi_path, accept_all_midi_files, (void *) 0, true, true);
2755 for (vector<string*>::iterator i = candidates2->begin(); i != candidates2->end(); ++i) {
2756 candidates->push_back (*i);
2761 candidates = candidates2; // might still be null
2764 /* find all sources, but don't use this snapshot because the
2765 state file on disk still references sources we may have already
2769 find_all_sources_across_snapshots (all_sources, true);
2771 /* add our current source list
2774 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ) {
2775 boost::shared_ptr<FileSource> fs;
2776 SourceMap::iterator tmp = i;
2779 if ((fs = boost::dynamic_pointer_cast<FileSource> (i->second)) != 0) {
2780 if (playlists->source_use_count (fs) != 0) {
2781 all_sources.insert (fs->path());
2784 /* we might not remove this source from disk, because it may be used
2785 by other snapshots, but its not being used in this version
2786 so lets get rid of it now, along with any representative regions
2790 RegionFactory::remove_regions_using_source (i->second);
2798 char tmppath1[PATH_MAX+1];
2799 char tmppath2[PATH_MAX+1];
2802 for (vector<string*>::iterator x = candidates->begin(); x != candidates->end(); ++x) {
2807 for (set<string>::iterator i = all_sources.begin(); i != all_sources.end(); ++i) {
2809 if (realpath(spath.c_str(), tmppath1) == 0) {
2810 error << string_compose (_("Cannot expand path %1 (%2)"),
2811 spath, strerror (errno)) << endmsg;
2815 if (realpath((*i).c_str(), tmppath2) == 0) {
2816 error << string_compose (_("Cannot expand path %1 (%2)"),
2817 (*i), strerror (errno)) << endmsg;
2821 if (strcmp(tmppath1, tmppath2) == 0) {
2828 unused.push_back (spath);
2837 /* now try to move all unused files into the "dead" directory(ies) */
2839 for (vector<string>::iterator x = unused.begin(); x != unused.end(); ++x) {
2840 struct stat statbuf;
2844 /* don't move the file across filesystems, just
2845 stick it in the `dead_dir_name' directory
2846 on whichever filesystem it was already on.
2849 if ((*x).find ("/sounds/") != string::npos) {
2851 /* old school, go up 1 level */
2853 newpath = Glib::path_get_dirname (*x); // "sounds"
2854 newpath = Glib::path_get_dirname (newpath); // "session-name"
2858 /* new school, go up 4 levels */
2860 newpath = Glib::path_get_dirname (*x); // "audiofiles" or "midifiles"
2861 newpath = Glib::path_get_dirname (newpath); // "session-name"
2862 newpath = Glib::path_get_dirname (newpath); // "interchange"
2863 newpath = Glib::path_get_dirname (newpath); // "session-dir"
2866 newpath = Glib::build_filename (newpath, dead_dir_name);
2868 if (g_mkdir_with_parents (newpath.c_str(), 0755) < 0) {
2869 error << string_compose(_("Session: cannot create dead file folder \"%1\" (%2)"), newpath, strerror (errno)) << endmsg;
2873 newpath = Glib::build_filename (newpath, Glib::path_get_basename ((*x)));
2875 if (Glib::file_test (newpath, Glib::FILE_TEST_EXISTS)) {
2877 /* the new path already exists, try versioning */
2879 char buf[PATH_MAX+1];
2883 snprintf (buf, sizeof (buf), "%s.%d", newpath.c_str(), version);
2886 while (Glib::file_test (newpath_v.c_str(), Glib::FILE_TEST_EXISTS) && version < 999) {
2887 snprintf (buf, sizeof (buf), "%s.%d", newpath.c_str(), ++version);
2891 if (version == 999) {
2892 error << string_compose (_("there are already 1000 files with names like %1; versioning discontinued"),
2896 newpath = newpath_v;
2901 /* it doesn't exist, or we can't read it or something */
2905 stat ((*x).c_str(), &statbuf);
2907 if (::rename ((*x).c_str(), newpath.c_str()) != 0) {
2908 error << string_compose (_("cannot rename unused file source from %1 to %2 (%3)"),
2909 (*x), newpath, strerror (errno))
2914 /* see if there an easy to find peakfile for this file, and remove it.
2917 string base = basename_nosuffix (*x);
2918 base += "%A"; /* this is what we add for the channel suffix of all native files,
2919 or for the first channel of embedded files. it will miss
2920 some peakfiles for other channels
2922 string peakpath = peak_path (base);
2924 if (Glib::file_test (peakpath.c_str(), Glib::FILE_TEST_EXISTS)) {
2925 if (::unlink (peakpath.c_str()) != 0) {
2926 error << string_compose (_("cannot remove peakfile %1 for %2 (%3)"),
2927 peakpath, _path, strerror (errno))
2929 /* try to back out */
2930 ::rename (newpath.c_str(), _path.c_str());
2935 rep.paths.push_back (*x);
2936 rep.space += statbuf.st_size;
2939 /* dump the history list */
2943 /* save state so we don't end up a session file
2944 referring to non-existent sources.
2951 _state_of_the_state = (StateOfTheState) (_state_of_the_state & ~InCleanup);
2957 Session::cleanup_trash_sources (CleanupReport& rep)
2959 // FIXME: needs adaptation for MIDI
2961 vector<space_and_path>::iterator i;
2967 for (i = session_dirs.begin(); i != session_dirs.end(); ++i) {
2969 dead_dir = Glib::build_filename ((*i).path, dead_dir_name);
2971 clear_directory (dead_dir, &rep.space, &rep.paths);
2978 Session::set_dirty ()
2980 bool was_dirty = dirty();
2982 _state_of_the_state = StateOfTheState (_state_of_the_state | Dirty);
2986 DirtyChanged(); /* EMIT SIGNAL */
2992 Session::set_clean ()
2994 bool was_dirty = dirty();
2996 _state_of_the_state = Clean;
3000 DirtyChanged(); /* EMIT SIGNAL */
3005 Session::set_deletion_in_progress ()
3007 _state_of_the_state = StateOfTheState (_state_of_the_state | Deletion);
3011 Session::clear_deletion_in_progress ()
3013 _state_of_the_state = StateOfTheState (_state_of_the_state & (~Deletion));
3017 Session::add_controllable (boost::shared_ptr<Controllable> c)
3019 /* this adds a controllable to the list managed by the Session.
3020 this is a subset of those managed by the Controllable class
3021 itself, and represents the only ones whose state will be saved
3022 as part of the session.
3025 Glib::Mutex::Lock lm (controllables_lock);
3026 controllables.insert (c);
3029 struct null_deleter { void operator()(void const *) const {} };
3032 Session::remove_controllable (Controllable* c)
3034 if (_state_of_the_state | Deletion) {
3038 Glib::Mutex::Lock lm (controllables_lock);
3040 Controllables::iterator x = controllables.find (boost::shared_ptr<Controllable>(c, null_deleter()));
3042 if (x != controllables.end()) {
3043 controllables.erase (x);
3047 boost::shared_ptr<Controllable>
3048 Session::controllable_by_id (const PBD::ID& id)
3050 Glib::Mutex::Lock lm (controllables_lock);
3052 for (Controllables::iterator i = controllables.begin(); i != controllables.end(); ++i) {
3053 if ((*i)->id() == id) {
3058 return boost::shared_ptr<Controllable>();
3061 boost::shared_ptr<Controllable>
3062 Session::controllable_by_descriptor (const ControllableDescriptor& desc)
3064 boost::shared_ptr<Controllable> c;
3065 boost::shared_ptr<Route> r;
3067 switch (desc.top_level_type()) {
3068 case ControllableDescriptor::NamedRoute:
3070 std::string str = desc.top_level_name();
3071 if (str == "master") {
3073 } else if (str == "control" || str == "listen") {
3076 r = route_by_name (desc.top_level_name());
3081 case ControllableDescriptor::RemoteControlID:
3082 r = route_by_remote_id (desc.rid());
3090 switch (desc.subtype()) {
3091 case ControllableDescriptor::Gain:
3092 c = r->gain_control ();
3095 case ControllableDescriptor::Solo:
3096 c = r->solo_control();
3099 case ControllableDescriptor::Mute:
3100 c = r->mute_control();
3103 case ControllableDescriptor::Recenable:
3105 boost::shared_ptr<Track> t = boost::dynamic_pointer_cast<Track>(r);
3108 c = t->rec_enable_control ();
3113 case ControllableDescriptor::PanDirection:
3115 c = r->pannable()->pan_azimuth_control;
3119 case ControllableDescriptor::PanWidth:
3121 c = r->pannable()->pan_width_control;
3125 case ControllableDescriptor::PanElevation:
3127 c = r->pannable()->pan_elevation_control;
3131 case ControllableDescriptor::Balance:
3132 /* XXX simple pan control */
3135 case ControllableDescriptor::PluginParameter:
3137 uint32_t plugin = desc.target (0);
3138 uint32_t parameter_index = desc.target (1);
3140 /* revert to zero based counting */
3146 if (parameter_index > 0) {
3150 boost::shared_ptr<Processor> p = r->nth_plugin (plugin);
3153 c = boost::dynamic_pointer_cast<ARDOUR::AutomationControl>(
3154 p->control(Evoral::Parameter(PluginAutomation, 0, parameter_index)));
3159 case ControllableDescriptor::SendGain:
3161 uint32_t send = desc.target (0);
3163 /* revert to zero-based counting */
3169 boost::shared_ptr<Processor> p = r->nth_send (send);
3172 boost::shared_ptr<Send> s = boost::dynamic_pointer_cast<Send>(p);
3173 boost::shared_ptr<Amp> a = s->amp();
3176 c = s->amp()->gain_control();
3183 /* relax and return a null pointer */
3191 Session::add_instant_xml (XMLNode& node, bool write_to_config)
3194 Stateful::add_instant_xml (node, _path);
3197 if (write_to_config) {
3198 Config->add_instant_xml (node);
3203 Session::instant_xml (const string& node_name)
3205 return Stateful::instant_xml (node_name, _path);
3209 Session::save_history (string snapshot_name)
3217 if (snapshot_name.empty()) {
3218 snapshot_name = _current_snapshot_name;
3221 const string history_filename = legalize_for_path (snapshot_name) + history_suffix;
3222 const string backup_filename = history_filename + backup_suffix;
3223 const sys::path xml_path = _session_dir->root_path() / history_filename;
3224 const sys::path backup_path = _session_dir->root_path() / backup_filename;
3226 if (sys::exists (xml_path)) {
3229 sys::rename (xml_path, backup_path);
3231 catch (const sys::filesystem_error& err)
3233 error << _("could not backup old history file, current history not saved") << endmsg;
3238 if (!Config->get_save_history() || Config->get_saved_history_depth() < 0) {
3242 tree.set_root (&_history.get_state (Config->get_saved_history_depth()));
3244 if (!tree.write (xml_path.to_string()))
3246 error << string_compose (_("history could not be saved to %1"), xml_path.to_string()) << endmsg;
3250 sys::remove (xml_path);
3251 sys::rename (backup_path, xml_path);
3253 catch (const sys::filesystem_error& err)
3255 error << string_compose (_("could not restore history file from backup %1 (%2)"),
3256 backup_path.to_string(), err.what()) << endmsg;
3266 Session::restore_history (string snapshot_name)
3270 if (snapshot_name.empty()) {
3271 snapshot_name = _current_snapshot_name;
3274 const string xml_filename = legalize_for_path (snapshot_name) + history_suffix;
3275 const sys::path xml_path = _session_dir->root_path() / xml_filename;
3277 info << "Loading history from " << xml_path.to_string() << endmsg;
3279 if (!sys::exists (xml_path)) {
3280 info << string_compose (_("%1: no history file \"%2\" for this session."),
3281 _name, xml_path.to_string()) << endmsg;
3285 if (!tree.read (xml_path.to_string())) {
3286 error << string_compose (_("Could not understand session history file \"%1\""),
3287 xml_path.to_string()) << endmsg;
3294 for (XMLNodeConstIterator it = tree.root()->children().begin(); it != tree.root()->children().end(); it++) {
3297 UndoTransaction* ut = new UndoTransaction ();
3300 ut->set_name(t->property("name")->value());
3301 stringstream ss(t->property("tv-sec")->value());
3303 ss.str(t->property("tv-usec")->value());
3305 ut->set_timestamp(tv);
3307 for (XMLNodeConstIterator child_it = t->children().begin();
3308 child_it != t->children().end(); child_it++)
3310 XMLNode *n = *child_it;
3313 if (n->name() == "MementoCommand" ||
3314 n->name() == "MementoUndoCommand" ||
3315 n->name() == "MementoRedoCommand") {
3317 if ((c = memento_command_factory(n))) {
3321 } else if (n->name() == "NoteDiffCommand") {
3322 PBD::ID id (n->property("midi-source")->value());
3323 boost::shared_ptr<MidiSource> midi_source =
3324 boost::dynamic_pointer_cast<MidiSource, Source>(source_by_id(id));
3326 ut->add_command (new MidiModel::NoteDiffCommand(midi_source->model(), *n));
3328 error << _("Failed to downcast MidiSource for NoteDiffCommand") << endmsg;
3331 } else if (n->name() == "SysExDiffCommand") {
3333 PBD::ID id (n->property("midi-source")->value());
3334 boost::shared_ptr<MidiSource> midi_source =
3335 boost::dynamic_pointer_cast<MidiSource, Source>(source_by_id(id));
3337 ut->add_command (new MidiModel::SysExDiffCommand (midi_source->model(), *n));
3339 error << _("Failed to downcast MidiSource for SysExDiffCommand") << endmsg;
3342 } else if (n->name() == "PatchChangeDiffCommand") {
3344 PBD::ID id (n->property("midi-source")->value());
3345 boost::shared_ptr<MidiSource> midi_source =
3346 boost::dynamic_pointer_cast<MidiSource, Source>(source_by_id(id));
3348 ut->add_command (new MidiModel::PatchChangeDiffCommand (midi_source->model(), *n));
3350 error << _("Failed to downcast MidiSource for PatchChangeDiffCommand") << endmsg;
3353 } else if (n->name() == "StatefulDiffCommand") {
3354 if ((c = stateful_diff_command_factory (n))) {
3355 ut->add_command (c);
3358 error << string_compose(_("Couldn't figure out how to make a Command out of a %1 XMLNode."), n->name()) << endmsg;
3369 Session::config_changed (std::string p, bool ours)
3375 if (p == "seamless-loop") {
3377 } else if (p == "rf-speed") {
3379 } else if (p == "auto-loop") {
3381 } else if (p == "auto-input") {
3383 if (Config->get_monitoring_model() == HardwareMonitoring && transport_rolling()) {
3384 /* auto-input only makes a difference if we're rolling */
3385 set_track_monitor_input_status (!config.get_auto_input());
3388 } else if (p == "punch-in") {
3392 if ((location = _locations->auto_punch_location()) != 0) {
3394 if (config.get_punch_in ()) {
3395 replace_event (SessionEvent::PunchIn, location->start());
3397 remove_event (location->start(), SessionEvent::PunchIn);
3401 } else if (p == "punch-out") {
3405 if ((location = _locations->auto_punch_location()) != 0) {
3407 if (config.get_punch_out()) {
3408 replace_event (SessionEvent::PunchOut, location->end());
3410 clear_events (SessionEvent::PunchOut);
3414 } else if (p == "edit-mode") {
3416 Glib::Mutex::Lock lm (playlists->lock);
3418 for (SessionPlaylists::List::iterator i = playlists->playlists.begin(); i != playlists->playlists.end(); ++i) {
3419 (*i)->set_edit_mode (Config->get_edit_mode ());
3422 } else if (p == "use-video-sync") {
3424 waiting_for_sync_offset = config.get_use_video_sync();
3426 } else if (p == "mmc-control") {
3428 //poke_midi_thread ();
3430 } else if (p == "mmc-device-id" || p == "mmc-receive-id" || p == "mmc-receive-device-id") {
3432 MIDI::Manager::instance()->mmc()->set_receive_device_id (Config->get_mmc_receive_device_id());
3434 } else if (p == "mmc-send-id" || p == "mmc-send-device-id") {
3436 MIDI::Manager::instance()->mmc()->set_send_device_id (Config->get_mmc_send_device_id());
3438 } else if (p == "midi-control") {
3440 //poke_midi_thread ();
3442 } else if (p == "raid-path") {
3444 setup_raid_path (config.get_raid_path());
3446 } else if (p == "timecode-format") {
3450 } else if (p == "video-pullup") {
3454 } else if (p == "seamless-loop") {
3456 if (play_loop && transport_rolling()) {
3457 // to reset diskstreams etc
3458 request_play_loop (true);
3461 } else if (p == "rf-speed") {
3463 cumulative_rf_motion = 0;
3466 } else if (p == "click-sound") {
3468 setup_click_sounds (1);
3470 } else if (p == "click-emphasis-sound") {
3472 setup_click_sounds (-1);
3474 } else if (p == "clicking") {
3476 if (Config->get_clicking()) {
3477 if (_click_io && click_data) { // don't require emphasis data
3484 } else if (p == "send-mtc") {
3486 if (Config->get_send_mtc ()) {
3487 /* mark us ready to send */
3488 next_quarter_frame_to_send = 0;
3491 } else if (p == "send-mmc") {
3493 MIDI::Manager::instance()->mmc()->enable_send (Config->get_send_mmc ());
3495 } else if (p == "midi-feedback") {
3497 session_midi_feedback = Config->get_midi_feedback();
3499 } else if (p == "jack-time-master") {
3501 engine().reset_timebase ();
3503 } else if (p == "native-file-header-format") {
3505 if (!first_file_header_format_reset) {
3506 reset_native_file_format ();
3509 first_file_header_format_reset = false;
3511 } else if (p == "native-file-data-format") {
3513 if (!first_file_data_format_reset) {
3514 reset_native_file_format ();
3517 first_file_data_format_reset = false;
3519 } else if (p == "external-sync") {
3520 if (!config.get_external_sync()) {
3521 drop_sync_source ();
3523 switch_to_sync_source (config.get_sync_source());
3525 } else if (p == "remote-model") {
3526 set_remote_control_ids ();
3527 } else if (p == "denormal-model") {
3529 } else if (p == "history-depth") {
3530 set_history_depth (Config->get_history_depth());
3531 } else if (p == "sync-all-route-ordering") {
3532 sync_order_keys ("session");
3533 } else if (p == "initial-program-change") {
3535 if (MIDI::Manager::instance()->mmc()->output_port() && Config->get_initial_program_change() >= 0) {
3538 buf[0] = MIDI::program; // channel zero by default
3539 buf[1] = (Config->get_initial_program_change() & 0x7f);
3541 MIDI::Manager::instance()->mmc()->output_port()->midimsg (buf, sizeof (buf), 0);
3543 } else if (p == "solo-mute-override") {
3544 // catch_up_on_solo_mute_override ();
3545 } else if (p == "listen-position" || p == "pfl-position") {
3546 listen_position_changed ();
3547 } else if (p == "solo-control-is-listen-control") {
3548 solo_control_mode_changed ();
3549 } else if (p == "timecode-offset" || p == "timecode-offset-negative") {
3550 last_timecode_valid = false;
3551 } else if (p == "playback-buffer-seconds") {
3552 AudioSource::allocate_working_buffers (frame_rate());
3559 Session::set_history_depth (uint32_t d)
3561 _history.set_depth (d);
3565 Session::load_diskstreams_2X (XMLNode const & node, int)
3568 XMLNodeConstIterator citer;
3570 clist = node.children();
3572 for (citer = clist.begin(); citer != clist.end(); ++citer) {
3575 /* diskstreams added automatically by DiskstreamCreated handler */
3576 if ((*citer)->name() == "AudioDiskstream" || (*citer)->name() == "DiskStream") {
3577 boost::shared_ptr<AudioDiskstream> dsp (new AudioDiskstream (*this, **citer));
3578 _diskstreams_2X.push_back (dsp);
3580 error << _("Session: unknown diskstream type in XML") << endmsg;
3584 catch (failed_constructor& err) {
3585 error << _("Session: could not load diskstream via XML state") << endmsg;
3593 /** Connect things to the MMC object */
3595 Session::setup_midi_machine_control ()
3597 MIDI::MachineControl* mmc = MIDI::Manager::instance()->mmc ();
3599 mmc->Play.connect_same_thread (*this, boost::bind (&Session::mmc_deferred_play, this, _1));
3600 mmc->DeferredPlay.connect_same_thread (*this, boost::bind (&Session::mmc_deferred_play, this, _1));
3601 mmc->Stop.connect_same_thread (*this, boost::bind (&Session::mmc_stop, this, _1));
3602 mmc->FastForward.connect_same_thread (*this, boost::bind (&Session::mmc_fast_forward, this, _1));
3603 mmc->Rewind.connect_same_thread (*this, boost::bind (&Session::mmc_rewind, this, _1));
3604 mmc->Pause.connect_same_thread (*this, boost::bind (&Session::mmc_pause, this, _1));
3605 mmc->RecordPause.connect_same_thread (*this, boost::bind (&Session::mmc_record_pause, this, _1));
3606 mmc->RecordStrobe.connect_same_thread (*this, boost::bind (&Session::mmc_record_strobe, this, _1));
3607 mmc->RecordExit.connect_same_thread (*this, boost::bind (&Session::mmc_record_exit, this, _1));
3608 mmc->Locate.connect_same_thread (*this, boost::bind (&Session::mmc_locate, this, _1, _2));
3609 mmc->Step.connect_same_thread (*this, boost::bind (&Session::mmc_step, this, _1, _2));
3610 mmc->Shuttle.connect_same_thread (*this, boost::bind (&Session::mmc_shuttle, this, _1, _2, _3));
3611 mmc->TrackRecordStatusChange.connect_same_thread (*this, boost::bind (&Session::mmc_record_enable, this, _1, _2, _3));
3613 /* also handle MIDI SPP because its so common */
3615 mmc->SPPStart.connect_same_thread (*this, boost::bind (&Session::spp_start, this, _1, _2));
3616 mmc->SPPContinue.connect_same_thread (*this, boost::bind (&Session::spp_continue, this, _1, _2));
3617 mmc->SPPStop.connect_same_thread (*this, boost::bind (&Session::spp_stop, this, _1, _2));
3620 boost::shared_ptr<Controllable>
3621 Session::solo_cut_control() const
3623 /* the solo cut control is a bit of an anomaly, at least as of Febrary 2011. There are no other
3624 controls in Ardour that currently get presented to the user in the GUI that require
3625 access as a Controllable and are also NOT owned by some SessionObject (e.g. Route, or MonitorProcessor).
3627 its actually an RCConfiguration parameter, so we use a ProxyControllable to wrap
3628 it up as a Controllable. Changes to the Controllable will just map back to the RCConfiguration
3632 return _solo_cut_control;
3636 Session::rename (const std::string& new_name)
3638 string legal_name = legalize_for_path (new_name);
3644 string const old_sources_root = _session_dir->sources_root().to_string ();
3646 #define RENAME ::rename
3651 * interchange subdirectory
3655 * Backup files are left unchanged and not renamed.
3658 /* pass one: not 100% safe check that the new directory names don't
3662 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
3667 /* this is a stupid hack because Glib::path_get_dirname() is
3668 * lexical-only, and so passing it /a/b/c/ gives a different
3669 * result than passing it /a/b/c ...
3672 if (oldstr[oldstr.length()-1] == G_DIR_SEPARATOR) {
3673 oldstr = oldstr.substr (0, oldstr.length() - 1);
3676 string base = Glib::path_get_dirname (oldstr);
3677 string p = Glib::path_get_basename (oldstr);
3679 newstr = Glib::build_filename (base, legal_name);
3681 if (Glib::file_test (newstr, Glib::FILE_TEST_EXISTS)) {
3688 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
3693 /* this is a stupid hack because Glib::path_get_dirname() is
3694 * lexical-only, and so passing it /a/b/c/ gives a different
3695 * result than passing it /a/b/c ...
3698 if (oldstr[oldstr.length()-1] == G_DIR_SEPARATOR) {
3699 oldstr = oldstr.substr (0, oldstr.length() - 1);
3702 string base = Glib::path_get_dirname (oldstr);
3703 string p = Glib::path_get_basename (oldstr);
3705 newstr = Glib::build_filename (base, legal_name);
3707 cerr << "Rename " << oldstr << " => " << newstr << endl;
3709 if (RENAME (oldstr.c_str(), newstr.c_str()) != 0) {
3714 (*_session_dir) = newstr;
3719 /* directory below interchange */
3721 v.push_back (newstr);
3722 v.push_back (interchange_dir_name);
3725 oldstr = Glib::build_filename (v);
3728 v.push_back (newstr);
3729 v.push_back (interchange_dir_name);
3730 v.push_back (legal_name);
3732 newstr = Glib::build_filename (v);
3734 cerr << "Rename " << oldstr << " => " << newstr << endl;
3736 if (RENAME (oldstr.c_str(), newstr.c_str()) != 0) {
3743 oldstr = Glib::build_filename (newpath, _current_snapshot_name) + statefile_suffix;
3744 newstr= Glib::build_filename (newpath, legal_name) + statefile_suffix;
3746 cerr << "Rename " << oldstr << " => " << newstr << endl;
3748 if (RENAME (oldstr.c_str(), newstr.c_str()) != 0) {
3755 oldstr = Glib::build_filename (newpath, _current_snapshot_name) + history_suffix;
3757 if (Glib::file_test (oldstr, Glib::FILE_TEST_EXISTS)) {
3758 newstr = Glib::build_filename (newpath, legal_name) + history_suffix;
3760 cerr << "Rename " << oldstr << " => " << newstr << endl;
3762 if (RENAME (oldstr.c_str(), newstr.c_str()) != 0) {
3767 /* update file source paths */
3769 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ++i) {
3770 boost::shared_ptr<FileSource> fs = boost::dynamic_pointer_cast<FileSource> (i->second);
3772 string p = fs->path ();
3773 boost::replace_all (p, old_sources_root, _session_dir->sources_root().to_string ());
3778 /* remove old name from recent sessions */
3780 remove_recent_sessions (_path);
3783 _current_snapshot_name = new_name;
3788 /* save state again to get everything just right */
3790 save_state (_current_snapshot_name);
3793 /* add to recent sessions */
3795 store_recent_sessions (new_name, _path);