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 AudioDiskstream::allocate_working_buffers();
230 /* default short fade = 15ms */
232 Crossfade::set_short_xfade_length ((framecnt_t) floor (config.get_short_xfade_seconds() * frame_rate()));
233 SndFileSource::setup_standard_crossfades (*this, frame_rate());
235 last_mmc_step.tv_sec = 0;
236 last_mmc_step.tv_usec = 0;
239 /* click sounds are unset by default, which causes us to internal
240 waveforms for clicks.
244 click_emphasis_length = 0;
247 process_function = &Session::process_with_events;
249 if (config.get_use_video_sync()) {
250 waiting_for_sync_offset = true;
252 waiting_for_sync_offset = false;
255 last_timecode_when = 0;
256 last_timecode_valid = false;
260 last_rr_session_dir = session_dirs.begin();
261 refresh_disk_space ();
263 /* default: assume simple stereo speaker configuration */
265 _speakers->setup_default_speakers (2);
269 average_slave_delta = 1800; // !!! why 1800 ????
270 have_first_delta_accumulator = false;
271 delta_accumulator_cnt = 0;
272 _slave_state = Stopped;
274 _solo_cut_control.reset (new ProxyControllable (_("solo cut control (dB)"), PBD::Controllable::GainLike,
275 boost::bind (&RCConfiguration::set_solo_mute_gain, Config, _1),
276 boost::bind (&RCConfiguration::get_solo_mute_gain, Config)));
277 add_controllable (_solo_cut_control);
279 _engine.GraphReordered.connect_same_thread (*this, boost::bind (&Session::graph_reordered, this));
281 /* These are all static "per-class" signals */
283 SourceFactory::SourceCreated.connect_same_thread (*this, boost::bind (&Session::add_source, this, _1));
284 PlaylistFactory::PlaylistCreated.connect_same_thread (*this, boost::bind (&Session::add_playlist, this, _1, _2));
285 AutomationList::AutomationListCreated.connect_same_thread (*this, boost::bind (&Session::add_automation_list, this, _1));
286 Controllable::Destroyed.connect_same_thread (*this, boost::bind (&Session::remove_controllable, this, _1));
287 IO::PortCountChanged.connect_same_thread (*this, boost::bind (&Session::ensure_buffers, this, _1));
289 /* stop IO objects from doing stuff until we're ready for them */
291 Delivery::disable_panners ();
292 IO::disable_connecting ();
296 Session::second_stage_init ()
298 AudioFileSource::set_peak_dir (_session_dir->peak_path().to_string());
301 if (load_state (_current_snapshot_name)) {
306 if (_butler->start_thread()) {
310 if (start_midi_thread ()) {
314 setup_midi_machine_control ();
316 // set_state() will call setup_raid_path(), but if it's a new session we need
317 // to call setup_raid_path() here.
320 if (set_state (*state_tree->root(), Stateful::loading_state_version)) {
324 setup_raid_path(_path);
327 /* we can't save till after ::when_engine_running() is called,
328 because otherwise we save state with no connections made.
329 therefore, we reset _state_of_the_state because ::set_state()
330 will have cleared it.
332 we also have to include Loading so that any events that get
333 generated between here and the end of ::when_engine_running()
334 will be processed directly rather than queued.
337 _state_of_the_state = StateOfTheState (_state_of_the_state|CannotSave|Loading);
339 _locations->changed.connect_same_thread (*this, boost::bind (&Session::locations_changed, this));
340 _locations->added.connect_same_thread (*this, boost::bind (&Session::locations_added, this, _1));
341 setup_click_sounds (0);
342 setup_midi_control ();
344 /* Pay attention ... */
346 _engine.Halted.connect_same_thread (*this, boost::bind (&Session::engine_halted, this));
347 _engine.Xrun.connect_same_thread (*this, boost::bind (&Session::xrun_recovery, this));
350 when_engine_running ();
353 /* handle this one in a different way than all others, so that its clear what happened */
355 catch (AudioEngine::PortRegistrationFailure& err) {
356 error << err.what() << endmsg;
364 BootMessage (_("Reset Remote Controls"));
366 send_full_time_code (0);
367 _engine.transport_locate (0);
369 MIDI::Manager::instance()->mmc()->send (MIDI::MachineControlCommand (MIDI::MachineControl::cmdMmcReset));
370 MIDI::Manager::instance()->mmc()->send (MIDI::MachineControlCommand (Timecode::Time ()));
372 MidiClockTicker::instance().set_session (this);
373 MIDI::Name::MidiPatchManager::instance().set_session (this);
375 /* initial program change will be delivered later; see ::config_changed() */
377 _state_of_the_state = Clean;
379 Port::set_connecting_blocked (false);
381 DirtyChanged (); /* EMIT SIGNAL */
383 if (state_was_pending) {
384 save_state (_current_snapshot_name);
385 remove_pending_capture_state ();
386 state_was_pending = false;
389 BootMessage (_("Session loading complete"));
395 Session::raid_path () const
397 SearchPath raid_search_path;
399 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
400 raid_search_path += sys::path((*i).path);
403 return raid_search_path.to_string ();
407 Session::setup_raid_path (string path)
416 session_dirs.clear ();
418 SearchPath search_path(path);
419 SearchPath sound_search_path;
420 SearchPath midi_search_path;
422 for (SearchPath::const_iterator i = search_path.begin(); i != search_path.end(); ++i) {
423 sp.path = (*i).to_string ();
424 sp.blocks = 0; // not needed
425 session_dirs.push_back (sp);
427 SessionDirectory sdir(sp.path);
429 sound_search_path += sdir.sound_path ();
430 midi_search_path += sdir.midi_path ();
433 // reset the round-robin soundfile path thingie
434 last_rr_session_dir = session_dirs.begin();
438 Session::path_is_within_session (const std::string& path)
440 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
441 if (path.find ((*i).path) == 0) {
449 Session::ensure_subdirs ()
453 dir = session_directory().peak_path().to_string();
455 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
456 error << string_compose(_("Session: cannot create session peakfile folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
460 dir = session_directory().sound_path().to_string();
462 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
463 error << string_compose(_("Session: cannot create session sounds dir \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
467 dir = session_directory().midi_path().to_string();
469 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
470 error << string_compose(_("Session: cannot create session midi dir \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
474 dir = session_directory().dead_path().to_string();
476 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
477 error << string_compose(_("Session: cannot create session dead sounds folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
481 dir = session_directory().export_path().to_string();
483 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
484 error << string_compose(_("Session: cannot create session export folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
488 dir = analysis_dir ();
490 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
491 error << string_compose(_("Session: cannot create session analysis folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
495 dir = plugins_dir ();
497 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
498 error << string_compose(_("Session: cannot create session plugins folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
505 /** Caller must not hold process lock */
507 Session::create (const string& mix_template, BusProfile* bus_profile)
509 if (g_mkdir_with_parents (_path.c_str(), 0755) < 0) {
510 error << string_compose(_("Session: cannot create session folder \"%1\" (%2)"), _path, strerror (errno)) << endmsg;
514 if (ensure_subdirs ()) {
518 _writable = exists_and_writable (sys::path (_path));
520 if (!mix_template.empty()) {
521 std::string in_path = mix_template;
523 ifstream in(in_path.c_str());
526 string out_path = _path;
528 out_path += statefile_suffix;
530 ofstream out(out_path.c_str());
538 error << string_compose (_("Could not open %1 for writing mix template"), out_path)
544 error << string_compose (_("Could not open mix template %1 for reading"), in_path)
551 /* Instantiate metadata */
553 _metadata = new SessionMetadata ();
555 /* set initial start + end point */
557 _state_of_the_state = Clean;
559 /* set up Master Out and Control Out if necessary */
565 ChanCount count(DataType::AUDIO, bus_profile->master_out_channels);
567 if (bus_profile->master_out_channels) {
568 boost::shared_ptr<Route> r (new Route (*this, _("master"), Route::MasterOut, DataType::AUDIO));
572 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
573 // boost_debug_shared_ptr_mark_interesting (r.get(), "Route");
576 Glib::Mutex::Lock lm (AudioEngine::instance()->process_lock ());
577 r->input()->ensure_io (count, false, this);
578 r->output()->ensure_io (count, false, this);
580 r->set_remote_control_id (control_id++);
584 if (Config->get_use_monitor_bus()) {
585 boost::shared_ptr<Route> r (new Route (*this, _("monitor"), Route::MonitorOut, DataType::AUDIO));
589 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
590 // boost_debug_shared_ptr_mark_interesting (r.get(), "Route");
593 Glib::Mutex::Lock lm (AudioEngine::instance()->process_lock ());
594 r->input()->ensure_io (count, false, this);
595 r->output()->ensure_io (count, false, this);
597 r->set_remote_control_id (control_id);
603 /* prohibit auto-connect to master, because there isn't one */
604 bus_profile->output_ac = AutoConnectOption (bus_profile->output_ac & ~AutoConnectMaster);
608 add_routes (rl, false, false);
611 /* this allows the user to override settings with an environment variable.
614 if (no_auto_connect()) {
615 bus_profile->input_ac = AutoConnectOption (0);
616 bus_profile->output_ac = AutoConnectOption (0);
619 Config->set_input_auto_connect (bus_profile->input_ac);
620 Config->set_output_auto_connect (bus_profile->output_ac);
629 Session::maybe_write_autosave()
631 if (dirty() && record_status() != Recording) {
632 save_state("", true);
637 Session::remove_pending_capture_state ()
639 sys::path pending_state_file_path(_session_dir->root_path());
641 pending_state_file_path /= legalize_for_path (_current_snapshot_name) + pending_suffix;
645 sys::remove (pending_state_file_path);
647 catch(sys::filesystem_error& ex)
649 error << string_compose(_("Could remove pending capture state at path \"%1\" (%2)"),
650 pending_state_file_path.to_string(), ex.what()) << endmsg;
654 /** Rename a state file.
655 * @param old_name Old snapshot name.
656 * @param new_name New snapshot name.
659 Session::rename_state (string old_name, string new_name)
661 if (old_name == _current_snapshot_name || old_name == _name) {
662 /* refuse to rename the current snapshot or the "main" one */
666 const string old_xml_filename = legalize_for_path (old_name) + statefile_suffix;
667 const string new_xml_filename = legalize_for_path (new_name) + statefile_suffix;
669 const sys::path old_xml_path = _session_dir->root_path() / old_xml_filename;
670 const sys::path new_xml_path = _session_dir->root_path() / new_xml_filename;
674 sys::rename (old_xml_path, new_xml_path);
676 catch (const sys::filesystem_error& err)
678 error << string_compose(_("could not rename snapshot %1 to %2 (%3)"),
679 old_name, new_name, err.what()) << endmsg;
683 /** Remove a state file.
684 * @param snapshot_name Snapshot name.
687 Session::remove_state (string snapshot_name)
689 if (snapshot_name == _current_snapshot_name || snapshot_name == _name) {
690 // refuse to remove the current snapshot or the "main" one
694 sys::path xml_path(_session_dir->root_path());
696 xml_path /= legalize_for_path (snapshot_name) + statefile_suffix;
698 if (!create_backup_file (xml_path)) {
699 // don't remove it if a backup can't be made
700 // create_backup_file will log the error.
705 sys::remove (xml_path);
708 #ifdef HAVE_JACK_SESSION
710 Session::jack_session_event (jack_session_event_t * event)
714 struct tm local_time;
717 localtime_r (&n, &local_time);
718 strftime (timebuf, sizeof(timebuf), "JS_%FT%T", &local_time);
720 if (event->type == JackSessionSaveTemplate)
722 if (save_template( timebuf )) {
723 event->flags = JackSessionSaveError;
725 string cmd ("ardour3 -P -U ");
726 cmd += event->client_uuid;
730 event->command_line = strdup (cmd.c_str());
735 if (save_state (timebuf)) {
736 event->flags = JackSessionSaveError;
738 sys::path xml_path (_session_dir->root_path());
739 xml_path /= legalize_for_path (timebuf) + statefile_suffix;
741 string cmd ("ardour3 -P -U ");
742 cmd += event->client_uuid;
744 cmd += xml_path.to_string();
747 event->command_line = strdup (cmd.c_str());
751 jack_session_reply (_engine.jack(), event);
753 if (event->type == JackSessionSaveAndQuit) {
754 Quit (); /* EMIT SIGNAL */
757 jack_session_event_free( event );
761 /** @param snapshot_name Name to save under, without .ardour / .pending prefix */
763 Session::save_state (string snapshot_name, bool pending, bool switch_to_snapshot)
766 sys::path xml_path(_session_dir->root_path());
768 if (!_writable || (_state_of_the_state & CannotSave)) {
772 if (!_engine.connected ()) {
773 error << string_compose (_("the %1 audio engine is not connected and state saving would lose all I/O connections. Session not saved"),
779 /* tell sources we're saving first, in case they write out to a new file
780 * which should be saved with the state rather than the old one */
781 for (SourceMap::const_iterator i = sources.begin(); i != sources.end(); ++i) {
782 i->second->session_saved();
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_file_path(user_template_dir);
2052 template_file_path /= template_name + template_suffix;
2054 if (sys::exists (template_file_path))
2056 warning << string_compose(_("Template \"%1\" already exists - new version not created"),
2057 template_file_path.to_string()) << endmsg;
2061 if (!tree.write (template_file_path.to_string())) {
2062 error << _("template not saved") << endmsg;
2070 Session::rename_template (string old_name, string new_name)
2072 sys::path old_path (user_template_directory());
2073 old_path /= old_name + template_suffix;
2075 sys::path new_path(user_template_directory());
2076 new_path /= new_name + template_suffix;
2078 if (sys::exists (new_path)) {
2079 warning << string_compose(_("Template \"%1\" already exists - template not renamed"),
2080 new_path.to_string()) << endmsg;
2085 sys::rename (old_path, new_path);
2093 Session::delete_template (string name)
2095 sys::path path = user_template_directory();
2096 path /= name + template_suffix;
2107 Session::refresh_disk_space ()
2110 struct statfs statfsbuf;
2111 vector<space_and_path>::iterator i;
2112 Glib::Mutex::Lock lm (space_lock);
2115 /* get freespace on every FS that is part of the session path */
2117 _total_free_4k_blocks = 0;
2119 for (i = session_dirs.begin(); i != session_dirs.end(); ++i) {
2120 statfs ((*i).path.c_str(), &statfsbuf);
2122 scale = statfsbuf.f_bsize/4096.0;
2124 (*i).blocks = (uint32_t) floor (statfsbuf.f_bavail * scale);
2125 _total_free_4k_blocks += (*i).blocks;
2131 Session::get_best_session_directory_for_new_source ()
2133 vector<space_and_path>::iterator i;
2134 string result = _session_dir->root_path().to_string();
2136 /* handle common case without system calls */
2138 if (session_dirs.size() == 1) {
2142 /* OK, here's the algorithm we're following here:
2144 We want to select which directory to use for
2145 the next file source to be created. Ideally,
2146 we'd like to use a round-robin process so as to
2147 get maximum performance benefits from splitting
2148 the files across multiple disks.
2150 However, in situations without much diskspace, an
2151 RR approach may end up filling up a filesystem
2152 with new files while others still have space.
2153 Its therefore important to pay some attention to
2154 the freespace in the filesystem holding each
2155 directory as well. However, if we did that by
2156 itself, we'd keep creating new files in the file
2157 system with the most space until it was as full
2158 as all others, thus negating any performance
2159 benefits of this RAID-1 like approach.
2161 So, we use a user-configurable space threshold. If
2162 there are at least 2 filesystems with more than this
2163 much space available, we use RR selection between them.
2164 If not, then we pick the filesystem with the most space.
2166 This gets a good balance between the two
2170 refresh_disk_space ();
2172 int free_enough = 0;
2174 for (i = session_dirs.begin(); i != session_dirs.end(); ++i) {
2175 if ((*i).blocks * 4096 >= Config->get_disk_choice_space_threshold()) {
2180 if (free_enough >= 2) {
2181 /* use RR selection process, ensuring that the one
2185 i = last_rr_session_dir;
2188 if (++i == session_dirs.end()) {
2189 i = session_dirs.begin();
2192 if ((*i).blocks * 4096 >= Config->get_disk_choice_space_threshold()) {
2193 if (create_session_directory ((*i).path)) {
2195 last_rr_session_dir = i;
2200 } while (i != last_rr_session_dir);
2204 /* pick FS with the most freespace (and that
2205 seems to actually work ...)
2208 vector<space_and_path> sorted;
2209 space_and_path_ascending_cmp cmp;
2211 sorted = session_dirs;
2212 sort (sorted.begin(), sorted.end(), cmp);
2214 for (i = sorted.begin(); i != sorted.end(); ++i) {
2215 if (create_session_directory ((*i).path)) {
2217 last_rr_session_dir = i;
2227 Session::load_named_selections (const XMLNode& node)
2230 XMLNodeConstIterator niter;
2233 nlist = node.children();
2237 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2239 if ((ns = XMLNamedSelectionFactory (**niter)) == 0) {
2240 error << _("Session: cannot create Named Selection from XML description.") << endmsg;
2248 Session::XMLNamedSelectionFactory (const XMLNode& node)
2251 return new NamedSelection (*this, node);
2254 catch (failed_constructor& err) {
2260 Session::automation_dir () const
2262 return Glib::build_filename (_path, "automation");
2266 Session::analysis_dir () const
2268 return Glib::build_filename (_path, "analysis");
2272 Session::plugins_dir () const
2274 return Glib::build_filename (_path, "plugins");
2278 Session::load_bundles (XMLNode const & node)
2280 XMLNodeList nlist = node.children();
2281 XMLNodeConstIterator niter;
2285 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2286 if ((*niter)->name() == "InputBundle") {
2287 add_bundle (boost::shared_ptr<UserBundle> (new UserBundle (**niter, true)));
2288 } else if ((*niter)->name() == "OutputBundle") {
2289 add_bundle (boost::shared_ptr<UserBundle> (new UserBundle (**niter, false)));
2291 error << string_compose(_("Unknown node \"%1\" found in Bundles list from state file"), (*niter)->name()) << endmsg;
2300 Session::load_route_groups (const XMLNode& node, int version)
2302 XMLNodeList nlist = node.children();
2303 XMLNodeConstIterator niter;
2307 if (version >= 3000) {
2309 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2310 if ((*niter)->name() == "RouteGroup") {
2311 RouteGroup* rg = new RouteGroup (*this, "");
2312 add_route_group (rg);
2313 rg->set_state (**niter, version);
2317 } else if (version < 3000) {
2319 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2320 if ((*niter)->name() == "EditGroup" || (*niter)->name() == "MixGroup") {
2321 RouteGroup* rg = new RouteGroup (*this, "");
2322 add_route_group (rg);
2323 rg->set_state (**niter, version);
2332 Session::auto_save()
2334 save_state (_current_snapshot_name);
2338 state_file_filter (const string &str, void */*arg*/)
2340 return (str.length() > strlen(statefile_suffix) &&
2341 str.find (statefile_suffix) == (str.length() - strlen (statefile_suffix)));
2345 bool operator()(const string* a, const string* b) {
2351 remove_end(string* state)
2353 string statename(*state);
2355 string::size_type start,end;
2356 if ((start = statename.find_last_of (G_DIR_SEPARATOR)) != string::npos) {
2357 statename = statename.substr (start+1);
2360 if ((end = statename.rfind(".ardour")) == string::npos) {
2361 end = statename.length();
2364 return new string(statename.substr (0, end));
2368 Session::possible_states (string path)
2370 PathScanner scanner;
2371 vector<string*>* states = scanner (path, state_file_filter, 0, false, false);
2373 transform(states->begin(), states->end(), states->begin(), remove_end);
2376 sort (states->begin(), states->end(), cmp);
2382 Session::possible_states () const
2384 return possible_states(_path);
2388 Session::add_route_group (RouteGroup* g)
2390 _route_groups.push_back (g);
2391 route_group_added (g); /* EMIT SIGNAL */
2393 g->RouteAdded.connect_same_thread (*this, boost::bind (&Session::route_added_to_route_group, this, _1, _2));
2394 g->RouteRemoved.connect_same_thread (*this, boost::bind (&Session::route_removed_from_route_group, this, _1, _2));
2395 g->PropertyChanged.connect_same_thread (*this, boost::bind (&Session::route_group_property_changed, this, g));
2401 Session::remove_route_group (RouteGroup& rg)
2403 list<RouteGroup*>::iterator i;
2405 if ((i = find (_route_groups.begin(), _route_groups.end(), &rg)) != _route_groups.end()) {
2406 _route_groups.erase (i);
2409 route_group_removed (); /* EMIT SIGNAL */
2413 /** Set a new order for our route groups, without adding or removing any.
2414 * @param groups Route group list in the new order.
2417 Session::reorder_route_groups (list<RouteGroup*> groups)
2419 _route_groups = groups;
2421 route_groups_reordered (); /* EMIT SIGNAL */
2427 Session::route_group_by_name (string name)
2429 list<RouteGroup *>::iterator i;
2431 for (i = _route_groups.begin(); i != _route_groups.end(); ++i) {
2432 if ((*i)->name() == name) {
2440 Session::all_route_group() const
2442 return *_all_route_group;
2446 Session::add_commands (vector<Command*> const & cmds)
2448 for (vector<Command*>::const_iterator i = cmds.begin(); i != cmds.end(); ++i) {
2454 Session::begin_reversible_command (const string& name)
2456 begin_reversible_command (g_quark_from_string (name.c_str ()));
2459 /** Begin a reversible command using a GQuark to identify it.
2460 * begin_reversible_command() and commit_reversible_command() calls may be nested,
2461 * but there must be as many begin...()s as there are commit...()s.
2464 Session::begin_reversible_command (GQuark q)
2466 /* If nested begin/commit pairs are used, we create just one UndoTransaction
2467 to hold all the commands that are committed. This keeps the order of
2468 commands correct in the history.
2471 if (_current_trans == 0) {
2472 /* start a new transaction */
2473 assert (_current_trans_quarks.empty ());
2474 _current_trans = new UndoTransaction();
2475 _current_trans->set_name (g_quark_to_string (q));
2478 _current_trans_quarks.push_front (q);
2482 Session::commit_reversible_command (Command *cmd)
2484 assert (_current_trans);
2485 assert (!_current_trans_quarks.empty ());
2490 _current_trans->add_command (cmd);
2493 _current_trans_quarks.pop_front ();
2495 if (!_current_trans_quarks.empty ()) {
2496 /* the transaction we're committing is not the top-level one */
2500 if (_current_trans->empty()) {
2501 /* no commands were added to the transaction, so just get rid of it */
2502 delete _current_trans;
2507 gettimeofday (&now, 0);
2508 _current_trans->set_timestamp (now);
2510 _history.add (_current_trans);
2515 accept_all_audio_files (const string& path, void */*arg*/)
2517 if (!Glib::file_test (path, Glib::FILE_TEST_IS_REGULAR)) {
2521 if (!AudioFileSource::safe_audio_file_extension (path)) {
2529 accept_all_midi_files (const string& path, void */*arg*/)
2531 if (!Glib::file_test (path, Glib::FILE_TEST_IS_REGULAR)) {
2535 return ((path.length() > 4 && path.find (".mid") != (path.length() - 4)) ||
2536 (path.length() > 4 && path.find (".smf") != (path.length() - 4)) ||
2537 (path.length() > 5 && path.find (".midi") != (path.length() - 5)));
2541 accept_all_state_files (const string& path, void */*arg*/)
2543 if (!Glib::file_test (path, Glib::FILE_TEST_IS_REGULAR)) {
2547 return (path.length() > 7 && path.find (".ardour") == (path.length() - 7));
2551 Session::find_all_sources (string path, set<string>& result)
2556 if (!tree.read (path)) {
2560 if ((node = find_named_node (*tree.root(), "Sources")) == 0) {
2565 XMLNodeConstIterator niter;
2567 nlist = node->children();
2571 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2575 if ((prop = (*niter)->property (X_("type"))) == 0) {
2579 DataType type (prop->value());
2581 if ((prop = (*niter)->property (X_("name"))) == 0) {
2585 if (Glib::path_is_absolute (prop->value())) {
2586 /* external file, ignore */
2594 if (FileSource::find (*this, type, prop->value(), true, is_new, chan, found_path)) {
2595 result.insert (found_path);
2603 Session::find_all_sources_across_snapshots (set<string>& result, bool exclude_this_snapshot)
2605 PathScanner scanner;
2606 vector<string*>* state_files;
2608 string this_snapshot_path;
2614 if (ripped[ripped.length()-1] == G_DIR_SEPARATOR) {
2615 ripped = ripped.substr (0, ripped.length() - 1);
2618 state_files = scanner (ripped, accept_all_state_files, (void *) 0, false, true);
2620 if (state_files == 0) {
2625 this_snapshot_path = _path;
2626 this_snapshot_path += legalize_for_path (_current_snapshot_name);
2627 this_snapshot_path += statefile_suffix;
2629 for (vector<string*>::iterator i = state_files->begin(); i != state_files->end(); ++i) {
2631 if (exclude_this_snapshot && **i == this_snapshot_path) {
2635 if (find_all_sources (**i, result) < 0) {
2643 struct RegionCounter {
2644 typedef std::map<PBD::ID,boost::shared_ptr<AudioSource> > AudioSourceList;
2645 AudioSourceList::iterator iter;
2646 boost::shared_ptr<Region> region;
2649 RegionCounter() : count (0) {}
2653 Session::ask_about_playlist_deletion (boost::shared_ptr<Playlist> p)
2655 boost::optional<int> r = AskAboutPlaylistDeletion (p);
2656 return r.get_value_or (1);
2660 Session::cleanup_regions ()
2662 const RegionFactory::RegionMap& regions (RegionFactory::regions());
2664 for (RegionFactory::RegionMap::const_iterator i = regions.begin(); i != regions.end(); ++i) {
2666 uint32_t used = playlists->region_use_count (i->second);
2668 if (used == 0 && !i->second->automatic ()) {
2669 RegionFactory::map_remove (i->second);
2673 /* dump the history list */
2680 Session::cleanup_sources (CleanupReport& rep)
2682 // FIXME: needs adaptation to midi
2684 vector<boost::shared_ptr<Source> > dead_sources;
2685 PathScanner scanner;
2688 vector<space_and_path>::iterator i;
2689 vector<space_and_path>::iterator nexti;
2690 vector<string*>* candidates;
2691 vector<string*>* candidates2;
2692 vector<string> unused;
2693 set<string> all_sources;
2698 _state_of_the_state = (StateOfTheState) (_state_of_the_state | InCleanup);
2700 /* consider deleting all unused playlists */
2702 if (playlists->maybe_delete_unused (boost::bind (Session::ask_about_playlist_deletion, _1))) {
2707 /* sync the "all regions" property of each playlist with its current state
2710 playlists->sync_all_regions_with_regions ();
2712 /* find all un-used sources */
2717 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ) {
2719 SourceMap::iterator tmp;
2724 /* do not bother with files that are zero size, otherwise we remove the current "nascent"
2728 if (!i->second->used() && (i->second->length(i->second->timeline_position() > 0))) {
2729 dead_sources.push_back (i->second);
2730 i->second->drop_references ();
2736 /* build a list of all the possible audio directories for the session */
2738 for (i = session_dirs.begin(); i != session_dirs.end(); ) {
2743 SessionDirectory sdir ((*i).path);
2744 audio_path += sdir.sound_path().to_string();
2746 if (nexti != session_dirs.end()) {
2754 /* build a list of all the possible midi directories for the session */
2756 for (i = session_dirs.begin(); i != session_dirs.end(); ) {
2761 SessionDirectory sdir ((*i).path);
2762 midi_path += sdir.midi_path().to_string();
2764 if (nexti != session_dirs.end()) {
2771 candidates = scanner (audio_path, accept_all_audio_files, (void *) 0, true, true);
2772 candidates2 = scanner (midi_path, accept_all_midi_files, (void *) 0, true, true);
2778 for (vector<string*>::iterator i = candidates2->begin(); i != candidates2->end(); ++i) {
2779 candidates->push_back (*i);
2784 candidates = candidates2; // might still be null
2787 /* find all sources, but don't use this snapshot because the
2788 state file on disk still references sources we may have already
2792 find_all_sources_across_snapshots (all_sources, true);
2794 /* add our current source list
2797 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ) {
2798 boost::shared_ptr<FileSource> fs;
2799 SourceMap::iterator tmp = i;
2802 if ((fs = boost::dynamic_pointer_cast<FileSource> (i->second)) != 0) {
2803 if (playlists->source_use_count (fs) != 0) {
2804 all_sources.insert (fs->path());
2807 /* we might not remove this source from disk, because it may be used
2808 by other snapshots, but its not being used in this version
2809 so lets get rid of it now, along with any representative regions
2813 RegionFactory::remove_regions_using_source (i->second);
2821 char tmppath1[PATH_MAX+1];
2822 char tmppath2[PATH_MAX+1];
2825 for (vector<string*>::iterator x = candidates->begin(); x != candidates->end(); ++x) {
2830 for (set<string>::iterator i = all_sources.begin(); i != all_sources.end(); ++i) {
2832 if (realpath(spath.c_str(), tmppath1) == 0) {
2833 error << string_compose (_("Cannot expand path %1 (%2)"),
2834 spath, strerror (errno)) << endmsg;
2838 if (realpath((*i).c_str(), tmppath2) == 0) {
2839 error << string_compose (_("Cannot expand path %1 (%2)"),
2840 (*i), strerror (errno)) << endmsg;
2844 if (strcmp(tmppath1, tmppath2) == 0) {
2851 unused.push_back (spath);
2860 /* now try to move all unused files into the "dead" directory(ies) */
2862 for (vector<string>::iterator x = unused.begin(); x != unused.end(); ++x) {
2863 struct stat statbuf;
2867 /* don't move the file across filesystems, just
2868 stick it in the `dead_dir_name' directory
2869 on whichever filesystem it was already on.
2872 if ((*x).find ("/sounds/") != string::npos) {
2874 /* old school, go up 1 level */
2876 newpath = Glib::path_get_dirname (*x); // "sounds"
2877 newpath = Glib::path_get_dirname (newpath); // "session-name"
2881 /* new school, go up 4 levels */
2883 newpath = Glib::path_get_dirname (*x); // "audiofiles" or "midifiles"
2884 newpath = Glib::path_get_dirname (newpath); // "session-name"
2885 newpath = Glib::path_get_dirname (newpath); // "interchange"
2886 newpath = Glib::path_get_dirname (newpath); // "session-dir"
2889 newpath = Glib::build_filename (newpath, dead_dir_name);
2891 if (g_mkdir_with_parents (newpath.c_str(), 0755) < 0) {
2892 error << string_compose(_("Session: cannot create dead file folder \"%1\" (%2)"), newpath, strerror (errno)) << endmsg;
2896 newpath = Glib::build_filename (newpath, Glib::path_get_basename ((*x)));
2898 if (Glib::file_test (newpath, Glib::FILE_TEST_EXISTS)) {
2900 /* the new path already exists, try versioning */
2902 char buf[PATH_MAX+1];
2906 snprintf (buf, sizeof (buf), "%s.%d", newpath.c_str(), version);
2909 while (Glib::file_test (newpath_v.c_str(), Glib::FILE_TEST_EXISTS) && version < 999) {
2910 snprintf (buf, sizeof (buf), "%s.%d", newpath.c_str(), ++version);
2914 if (version == 999) {
2915 error << string_compose (_("there are already 1000 files with names like %1; versioning discontinued"),
2919 newpath = newpath_v;
2924 /* it doesn't exist, or we can't read it or something */
2928 stat ((*x).c_str(), &statbuf);
2930 if (::rename ((*x).c_str(), newpath.c_str()) != 0) {
2931 error << string_compose (_("cannot rename unused file source from %1 to %2 (%3)"),
2932 (*x), newpath, strerror (errno))
2937 /* see if there an easy to find peakfile for this file, and remove it.
2940 string base = basename_nosuffix (*x);
2941 base += "%A"; /* this is what we add for the channel suffix of all native files,
2942 or for the first channel of embedded files. it will miss
2943 some peakfiles for other channels
2945 string peakpath = peak_path (base);
2947 if (Glib::file_test (peakpath.c_str(), Glib::FILE_TEST_EXISTS)) {
2948 if (::unlink (peakpath.c_str()) != 0) {
2949 error << string_compose (_("cannot remove peakfile %1 for %2 (%3)"),
2950 peakpath, _path, strerror (errno))
2952 /* try to back out */
2953 ::rename (newpath.c_str(), _path.c_str());
2958 rep.paths.push_back (*x);
2959 rep.space += statbuf.st_size;
2962 /* dump the history list */
2966 /* save state so we don't end up a session file
2967 referring to non-existent sources.
2974 _state_of_the_state = (StateOfTheState) (_state_of_the_state & ~InCleanup);
2980 Session::cleanup_trash_sources (CleanupReport& rep)
2982 // FIXME: needs adaptation for MIDI
2984 vector<space_and_path>::iterator i;
2990 for (i = session_dirs.begin(); i != session_dirs.end(); ++i) {
2992 dead_dir = Glib::build_filename ((*i).path, dead_dir_name);
2994 clear_directory (dead_dir, &rep.space, &rep.paths);
3001 Session::set_dirty ()
3003 bool was_dirty = dirty();
3005 _state_of_the_state = StateOfTheState (_state_of_the_state | Dirty);
3009 DirtyChanged(); /* EMIT SIGNAL */
3015 Session::set_clean ()
3017 bool was_dirty = dirty();
3019 _state_of_the_state = Clean;
3023 DirtyChanged(); /* EMIT SIGNAL */
3028 Session::set_deletion_in_progress ()
3030 _state_of_the_state = StateOfTheState (_state_of_the_state | Deletion);
3034 Session::clear_deletion_in_progress ()
3036 _state_of_the_state = StateOfTheState (_state_of_the_state & (~Deletion));
3040 Session::add_controllable (boost::shared_ptr<Controllable> c)
3042 /* this adds a controllable to the list managed by the Session.
3043 this is a subset of those managed by the Controllable class
3044 itself, and represents the only ones whose state will be saved
3045 as part of the session.
3048 Glib::Mutex::Lock lm (controllables_lock);
3049 controllables.insert (c);
3052 struct null_deleter { void operator()(void const *) const {} };
3055 Session::remove_controllable (Controllable* c)
3057 if (_state_of_the_state | Deletion) {
3061 Glib::Mutex::Lock lm (controllables_lock);
3063 Controllables::iterator x = controllables.find (boost::shared_ptr<Controllable>(c, null_deleter()));
3065 if (x != controllables.end()) {
3066 controllables.erase (x);
3070 boost::shared_ptr<Controllable>
3071 Session::controllable_by_id (const PBD::ID& id)
3073 Glib::Mutex::Lock lm (controllables_lock);
3075 for (Controllables::iterator i = controllables.begin(); i != controllables.end(); ++i) {
3076 if ((*i)->id() == id) {
3081 return boost::shared_ptr<Controllable>();
3084 boost::shared_ptr<Controllable>
3085 Session::controllable_by_descriptor (const ControllableDescriptor& desc)
3087 boost::shared_ptr<Controllable> c;
3088 boost::shared_ptr<Route> r;
3090 switch (desc.top_level_type()) {
3091 case ControllableDescriptor::NamedRoute:
3093 std::string str = desc.top_level_name();
3094 if (str == "master") {
3096 } else if (str == "control" || str == "listen") {
3099 r = route_by_name (desc.top_level_name());
3104 case ControllableDescriptor::RemoteControlID:
3105 r = route_by_remote_id (desc.rid());
3113 switch (desc.subtype()) {
3114 case ControllableDescriptor::Gain:
3115 c = r->gain_control ();
3118 case ControllableDescriptor::Solo:
3119 c = r->solo_control();
3122 case ControllableDescriptor::Mute:
3123 c = r->mute_control();
3126 case ControllableDescriptor::Recenable:
3128 boost::shared_ptr<Track> t = boost::dynamic_pointer_cast<Track>(r);
3131 c = t->rec_enable_control ();
3136 case ControllableDescriptor::PanDirection:
3138 c = r->pannable()->pan_azimuth_control;
3142 case ControllableDescriptor::PanWidth:
3144 c = r->pannable()->pan_width_control;
3148 case ControllableDescriptor::PanElevation:
3150 c = r->pannable()->pan_elevation_control;
3154 case ControllableDescriptor::Balance:
3155 /* XXX simple pan control */
3158 case ControllableDescriptor::PluginParameter:
3160 uint32_t plugin = desc.target (0);
3161 uint32_t parameter_index = desc.target (1);
3163 /* revert to zero based counting */
3169 if (parameter_index > 0) {
3173 boost::shared_ptr<Processor> p = r->nth_plugin (plugin);
3176 c = boost::dynamic_pointer_cast<ARDOUR::AutomationControl>(
3177 p->control(Evoral::Parameter(PluginAutomation, 0, parameter_index)));
3182 case ControllableDescriptor::SendGain:
3184 uint32_t send = desc.target (0);
3186 /* revert to zero-based counting */
3192 boost::shared_ptr<Processor> p = r->nth_send (send);
3195 boost::shared_ptr<Send> s = boost::dynamic_pointer_cast<Send>(p);
3196 boost::shared_ptr<Amp> a = s->amp();
3199 c = s->amp()->gain_control();
3206 /* relax and return a null pointer */
3214 Session::add_instant_xml (XMLNode& node, bool write_to_config)
3217 Stateful::add_instant_xml (node, _path);
3220 if (write_to_config) {
3221 Config->add_instant_xml (node);
3226 Session::instant_xml (const string& node_name)
3228 return Stateful::instant_xml (node_name, _path);
3232 Session::save_history (string snapshot_name)
3240 if (snapshot_name.empty()) {
3241 snapshot_name = _current_snapshot_name;
3244 const string history_filename = legalize_for_path (snapshot_name) + history_suffix;
3245 const string backup_filename = history_filename + backup_suffix;
3246 const sys::path xml_path = _session_dir->root_path() / history_filename;
3247 const sys::path backup_path = _session_dir->root_path() / backup_filename;
3249 if (sys::exists (xml_path)) {
3252 sys::rename (xml_path, backup_path);
3254 catch (const sys::filesystem_error& err)
3256 error << _("could not backup old history file, current history not saved") << endmsg;
3261 if (!Config->get_save_history() || Config->get_saved_history_depth() < 0) {
3265 tree.set_root (&_history.get_state (Config->get_saved_history_depth()));
3267 if (!tree.write (xml_path.to_string()))
3269 error << string_compose (_("history could not be saved to %1"), xml_path.to_string()) << endmsg;
3273 sys::remove (xml_path);
3274 sys::rename (backup_path, xml_path);
3276 catch (const sys::filesystem_error& err)
3278 error << string_compose (_("could not restore history file from backup %1 (%2)"),
3279 backup_path.to_string(), err.what()) << endmsg;
3289 Session::restore_history (string snapshot_name)
3293 if (snapshot_name.empty()) {
3294 snapshot_name = _current_snapshot_name;
3297 const string xml_filename = legalize_for_path (snapshot_name) + history_suffix;
3298 const sys::path xml_path = _session_dir->root_path() / xml_filename;
3300 info << "Loading history from " << xml_path.to_string() << endmsg;
3302 if (!sys::exists (xml_path)) {
3303 info << string_compose (_("%1: no history file \"%2\" for this session."),
3304 _name, xml_path.to_string()) << endmsg;
3308 if (!tree.read (xml_path.to_string())) {
3309 error << string_compose (_("Could not understand session history file \"%1\""),
3310 xml_path.to_string()) << endmsg;
3317 for (XMLNodeConstIterator it = tree.root()->children().begin(); it != tree.root()->children().end(); it++) {
3320 UndoTransaction* ut = new UndoTransaction ();
3323 ut->set_name(t->property("name")->value());
3324 stringstream ss(t->property("tv-sec")->value());
3326 ss.str(t->property("tv-usec")->value());
3328 ut->set_timestamp(tv);
3330 for (XMLNodeConstIterator child_it = t->children().begin();
3331 child_it != t->children().end(); child_it++)
3333 XMLNode *n = *child_it;
3336 if (n->name() == "MementoCommand" ||
3337 n->name() == "MementoUndoCommand" ||
3338 n->name() == "MementoRedoCommand") {
3340 if ((c = memento_command_factory(n))) {
3344 } else if (n->name() == "NoteDiffCommand") {
3345 PBD::ID id (n->property("midi-source")->value());
3346 boost::shared_ptr<MidiSource> midi_source =
3347 boost::dynamic_pointer_cast<MidiSource, Source>(source_by_id(id));
3349 ut->add_command (new MidiModel::NoteDiffCommand(midi_source->model(), *n));
3351 error << _("Failed to downcast MidiSource for NoteDiffCommand") << endmsg;
3354 } else if (n->name() == "SysExDiffCommand") {
3356 PBD::ID id (n->property("midi-source")->value());
3357 boost::shared_ptr<MidiSource> midi_source =
3358 boost::dynamic_pointer_cast<MidiSource, Source>(source_by_id(id));
3360 ut->add_command (new MidiModel::SysExDiffCommand (midi_source->model(), *n));
3362 error << _("Failed to downcast MidiSource for SysExDiffCommand") << endmsg;
3365 } else if (n->name() == "PatchChangeDiffCommand") {
3367 PBD::ID id (n->property("midi-source")->value());
3368 boost::shared_ptr<MidiSource> midi_source =
3369 boost::dynamic_pointer_cast<MidiSource, Source>(source_by_id(id));
3371 ut->add_command (new MidiModel::PatchChangeDiffCommand (midi_source->model(), *n));
3373 error << _("Failed to downcast MidiSource for PatchChangeDiffCommand") << endmsg;
3376 } else if (n->name() == "StatefulDiffCommand") {
3377 if ((c = stateful_diff_command_factory (n))) {
3378 ut->add_command (c);
3381 error << string_compose(_("Couldn't figure out how to make a Command out of a %1 XMLNode."), n->name()) << endmsg;
3392 Session::config_changed (std::string p, bool ours)
3398 if (p == "seamless-loop") {
3400 } else if (p == "rf-speed") {
3402 } else if (p == "auto-loop") {
3404 } else if (p == "auto-input") {
3406 if (Config->get_monitoring_model() == HardwareMonitoring && transport_rolling()) {
3407 /* auto-input only makes a difference if we're rolling */
3408 set_track_monitor_input_status (!config.get_auto_input());
3411 } else if (p == "punch-in") {
3415 if ((location = _locations->auto_punch_location()) != 0) {
3417 if (config.get_punch_in ()) {
3418 replace_event (SessionEvent::PunchIn, location->start());
3420 remove_event (location->start(), SessionEvent::PunchIn);
3424 } else if (p == "punch-out") {
3428 if ((location = _locations->auto_punch_location()) != 0) {
3430 if (config.get_punch_out()) {
3431 replace_event (SessionEvent::PunchOut, location->end());
3433 clear_events (SessionEvent::PunchOut);
3437 } else if (p == "edit-mode") {
3439 Glib::Mutex::Lock lm (playlists->lock);
3441 for (SessionPlaylists::List::iterator i = playlists->playlists.begin(); i != playlists->playlists.end(); ++i) {
3442 (*i)->set_edit_mode (Config->get_edit_mode ());
3445 } else if (p == "use-video-sync") {
3447 waiting_for_sync_offset = config.get_use_video_sync();
3449 } else if (p == "mmc-control") {
3451 //poke_midi_thread ();
3453 } else if (p == "mmc-device-id" || p == "mmc-receive-id" || p == "mmc-receive-device-id") {
3455 MIDI::Manager::instance()->mmc()->set_receive_device_id (Config->get_mmc_receive_device_id());
3457 } else if (p == "mmc-send-id" || p == "mmc-send-device-id") {
3459 MIDI::Manager::instance()->mmc()->set_send_device_id (Config->get_mmc_send_device_id());
3461 } else if (p == "midi-control") {
3463 //poke_midi_thread ();
3465 } else if (p == "raid-path") {
3467 setup_raid_path (config.get_raid_path());
3469 } else if (p == "timecode-format") {
3473 } else if (p == "video-pullup") {
3477 } else if (p == "seamless-loop") {
3479 if (play_loop && transport_rolling()) {
3480 // to reset diskstreams etc
3481 request_play_loop (true);
3484 } else if (p == "rf-speed") {
3486 cumulative_rf_motion = 0;
3489 } else if (p == "click-sound") {
3491 setup_click_sounds (1);
3493 } else if (p == "click-emphasis-sound") {
3495 setup_click_sounds (-1);
3497 } else if (p == "clicking") {
3499 if (Config->get_clicking()) {
3500 if (_click_io && click_data) { // don't require emphasis data
3507 } else if (p == "send-mtc") {
3509 if (Config->get_send_mtc ()) {
3510 /* mark us ready to send */
3511 next_quarter_frame_to_send = 0;
3514 } else if (p == "send-mmc") {
3516 MIDI::Manager::instance()->mmc()->enable_send (Config->get_send_mmc ());
3518 } else if (p == "midi-feedback") {
3520 session_midi_feedback = Config->get_midi_feedback();
3522 } else if (p == "jack-time-master") {
3524 engine().reset_timebase ();
3526 } else if (p == "native-file-header-format") {
3528 if (!first_file_header_format_reset) {
3529 reset_native_file_format ();
3532 first_file_header_format_reset = false;
3534 } else if (p == "native-file-data-format") {
3536 if (!first_file_data_format_reset) {
3537 reset_native_file_format ();
3540 first_file_data_format_reset = false;
3542 } else if (p == "external-sync") {
3543 if (!config.get_external_sync()) {
3544 drop_sync_source ();
3546 switch_to_sync_source (config.get_sync_source());
3548 } else if (p == "remote-model") {
3549 set_remote_control_ids ();
3550 } else if (p == "denormal-model") {
3552 } else if (p == "history-depth") {
3553 set_history_depth (Config->get_history_depth());
3554 } else if (p == "sync-all-route-ordering") {
3555 sync_order_keys ("session");
3556 } else if (p == "initial-program-change") {
3558 if (MIDI::Manager::instance()->mmc()->output_port() && Config->get_initial_program_change() >= 0) {
3561 buf[0] = MIDI::program; // channel zero by default
3562 buf[1] = (Config->get_initial_program_change() & 0x7f);
3564 MIDI::Manager::instance()->mmc()->output_port()->midimsg (buf, sizeof (buf), 0);
3566 } else if (p == "solo-mute-override") {
3567 // catch_up_on_solo_mute_override ();
3568 } else if (p == "listen-position" || p == "pfl-position") {
3569 listen_position_changed ();
3570 } else if (p == "solo-control-is-listen-control") {
3571 solo_control_mode_changed ();
3572 } else if (p == "timecode-offset" || p == "timecode-offset-negative") {
3573 last_timecode_valid = false;
3574 } else if (p == "playback-buffer-seconds") {
3575 AudioSource::allocate_working_buffers (frame_rate());
3582 Session::set_history_depth (uint32_t d)
3584 _history.set_depth (d);
3588 Session::load_diskstreams_2X (XMLNode const & node, int)
3591 XMLNodeConstIterator citer;
3593 clist = node.children();
3595 for (citer = clist.begin(); citer != clist.end(); ++citer) {
3598 /* diskstreams added automatically by DiskstreamCreated handler */
3599 if ((*citer)->name() == "AudioDiskstream" || (*citer)->name() == "DiskStream") {
3600 boost::shared_ptr<AudioDiskstream> dsp (new AudioDiskstream (*this, **citer));
3601 _diskstreams_2X.push_back (dsp);
3603 error << _("Session: unknown diskstream type in XML") << endmsg;
3607 catch (failed_constructor& err) {
3608 error << _("Session: could not load diskstream via XML state") << endmsg;
3616 /** Connect things to the MMC object */
3618 Session::setup_midi_machine_control ()
3620 MIDI::MachineControl* mmc = MIDI::Manager::instance()->mmc ();
3622 mmc->Play.connect_same_thread (*this, boost::bind (&Session::mmc_deferred_play, this, _1));
3623 mmc->DeferredPlay.connect_same_thread (*this, boost::bind (&Session::mmc_deferred_play, this, _1));
3624 mmc->Stop.connect_same_thread (*this, boost::bind (&Session::mmc_stop, this, _1));
3625 mmc->FastForward.connect_same_thread (*this, boost::bind (&Session::mmc_fast_forward, this, _1));
3626 mmc->Rewind.connect_same_thread (*this, boost::bind (&Session::mmc_rewind, this, _1));
3627 mmc->Pause.connect_same_thread (*this, boost::bind (&Session::mmc_pause, this, _1));
3628 mmc->RecordPause.connect_same_thread (*this, boost::bind (&Session::mmc_record_pause, this, _1));
3629 mmc->RecordStrobe.connect_same_thread (*this, boost::bind (&Session::mmc_record_strobe, this, _1));
3630 mmc->RecordExit.connect_same_thread (*this, boost::bind (&Session::mmc_record_exit, this, _1));
3631 mmc->Locate.connect_same_thread (*this, boost::bind (&Session::mmc_locate, this, _1, _2));
3632 mmc->Step.connect_same_thread (*this, boost::bind (&Session::mmc_step, this, _1, _2));
3633 mmc->Shuttle.connect_same_thread (*this, boost::bind (&Session::mmc_shuttle, this, _1, _2, _3));
3634 mmc->TrackRecordStatusChange.connect_same_thread (*this, boost::bind (&Session::mmc_record_enable, this, _1, _2, _3));
3636 /* also handle MIDI SPP because its so common */
3638 mmc->SPPStart.connect_same_thread (*this, boost::bind (&Session::spp_start, this, _1, _2));
3639 mmc->SPPContinue.connect_same_thread (*this, boost::bind (&Session::spp_continue, this, _1, _2));
3640 mmc->SPPStop.connect_same_thread (*this, boost::bind (&Session::spp_stop, this, _1, _2));
3643 boost::shared_ptr<Controllable>
3644 Session::solo_cut_control() const
3646 /* the solo cut control is a bit of an anomaly, at least as of Febrary 2011. There are no other
3647 controls in Ardour that currently get presented to the user in the GUI that require
3648 access as a Controllable and are also NOT owned by some SessionObject (e.g. Route, or MonitorProcessor).
3650 its actually an RCConfiguration parameter, so we use a ProxyControllable to wrap
3651 it up as a Controllable. Changes to the Controllable will just map back to the RCConfiguration
3655 return _solo_cut_control;
3659 Session::rename (const std::string& new_name)
3661 string legal_name = legalize_for_path (new_name);
3667 string const old_sources_root = _session_dir->sources_root().to_string ();
3669 #define RENAME ::rename
3674 * interchange subdirectory
3678 * Backup files are left unchanged and not renamed.
3681 /* pass one: not 100% safe check that the new directory names don't
3685 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
3690 /* this is a stupid hack because Glib::path_get_dirname() is
3691 * lexical-only, and so passing it /a/b/c/ gives a different
3692 * result than passing it /a/b/c ...
3695 if (oldstr[oldstr.length()-1] == G_DIR_SEPARATOR) {
3696 oldstr = oldstr.substr (0, oldstr.length() - 1);
3699 string base = Glib::path_get_dirname (oldstr);
3700 string p = Glib::path_get_basename (oldstr);
3702 newstr = Glib::build_filename (base, legal_name);
3704 if (Glib::file_test (newstr, Glib::FILE_TEST_EXISTS)) {
3711 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
3716 /* this is a stupid hack because Glib::path_get_dirname() is
3717 * lexical-only, and so passing it /a/b/c/ gives a different
3718 * result than passing it /a/b/c ...
3721 if (oldstr[oldstr.length()-1] == G_DIR_SEPARATOR) {
3722 oldstr = oldstr.substr (0, oldstr.length() - 1);
3725 string base = Glib::path_get_dirname (oldstr);
3726 string p = Glib::path_get_basename (oldstr);
3728 newstr = Glib::build_filename (base, legal_name);
3730 cerr << "Rename " << oldstr << " => " << newstr << endl;
3732 if (RENAME (oldstr.c_str(), newstr.c_str()) != 0) {
3737 (*_session_dir) = newstr;
3742 /* directory below interchange */
3744 v.push_back (newstr);
3745 v.push_back (interchange_dir_name);
3748 oldstr = Glib::build_filename (v);
3751 v.push_back (newstr);
3752 v.push_back (interchange_dir_name);
3753 v.push_back (legal_name);
3755 newstr = Glib::build_filename (v);
3757 cerr << "Rename " << oldstr << " => " << newstr << endl;
3759 if (RENAME (oldstr.c_str(), newstr.c_str()) != 0) {
3766 oldstr = Glib::build_filename (newpath, _current_snapshot_name) + statefile_suffix;
3767 newstr= Glib::build_filename (newpath, legal_name) + statefile_suffix;
3769 cerr << "Rename " << oldstr << " => " << newstr << endl;
3771 if (RENAME (oldstr.c_str(), newstr.c_str()) != 0) {
3778 oldstr = Glib::build_filename (newpath, _current_snapshot_name) + history_suffix;
3780 if (Glib::file_test (oldstr, Glib::FILE_TEST_EXISTS)) {
3781 newstr = Glib::build_filename (newpath, legal_name) + history_suffix;
3783 cerr << "Rename " << oldstr << " => " << newstr << endl;
3785 if (RENAME (oldstr.c_str(), newstr.c_str()) != 0) {
3790 /* update file source paths */
3792 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ++i) {
3793 boost::shared_ptr<FileSource> fs = boost::dynamic_pointer_cast<FileSource> (i->second);
3795 string p = fs->path ();
3796 boost::replace_all (p, old_sources_root, _session_dir->sources_root().to_string ());
3801 /* remove old name from recent sessions */
3803 remove_recent_sessions (_path);
3806 _current_snapshot_name = new_name;
3811 /* save state again to get everything just right */
3813 save_state (_current_snapshot_name);
3816 /* add to recent sessions */
3818 store_recent_sessions (new_name, _path);