2 Copyright (C) 1999-2002 Paul Davis
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 #include "libardour-config.h"
31 #include <cstdio> /* snprintf(3) ... grrr */
45 #include <sys/param.h>
46 #include <sys/mount.h>
49 #ifdef HAVE_SYS_STATVFS_H
50 #include <sys/statvfs.h>
54 #include <glib/gstdio.h>
57 #include <glibmm/threads.h>
59 #include <boost/algorithm/string.hpp>
61 #include "midi++/mmc.h"
62 #include "midi++/port.h"
63 #include "midi++/manager.h"
65 #include "evoral/SMF.hpp"
67 #include "pbd/boost_debug.h"
68 #include "pbd/basename.h"
69 #include "pbd/controllable_descriptor.h"
70 #include "pbd/enumwriter.h"
71 #include "pbd/error.h"
72 #include "pbd/file_utils.h"
73 #include "pbd/pathscanner.h"
74 #include "pbd/pthread_utils.h"
75 #include "pbd/stacktrace.h"
76 #include "pbd/convert.h"
77 #include "pbd/clear_dir.h"
79 #include "ardour/amp.h"
80 #include "ardour/audio_diskstream.h"
81 #include "ardour/audio_track.h"
82 #include "ardour/audioengine.h"
83 #include "ardour/audiofilesource.h"
84 #include "ardour/audioregion.h"
85 #include "ardour/automation_control.h"
86 #include "ardour/butler.h"
87 #include "ardour/control_protocol_manager.h"
88 #include "ardour/directory_names.h"
89 #include "ardour/filename_extensions.h"
90 #include "ardour/location.h"
91 #include "ardour/midi_model.h"
92 #include "ardour/midi_patch_manager.h"
93 #include "ardour/midi_region.h"
94 #include "ardour/midi_source.h"
95 #include "ardour/midi_track.h"
96 #include "ardour/pannable.h"
97 #include "ardour/playlist_factory.h"
98 #include "ardour/port.h"
99 #include "ardour/processor.h"
100 #include "ardour/proxy_controllable.h"
101 #include "ardour/recent_sessions.h"
102 #include "ardour/region_factory.h"
103 #include "ardour/route_group.h"
104 #include "ardour/send.h"
105 #include "ardour/session.h"
106 #include "ardour/session_directory.h"
107 #include "ardour/session_metadata.h"
108 #include "ardour/session_playlists.h"
109 #include "ardour/session_state_utils.h"
110 #include "ardour/silentfilesource.h"
111 #include "ardour/sndfilesource.h"
112 #include "ardour/source_factory.h"
113 #include "ardour/speakers.h"
114 #include "ardour/template_utils.h"
115 #include "ardour/tempo.h"
116 #include "ardour/ticker.h"
117 #include "ardour/user_bundle.h"
119 #include "control_protocol/control_protocol.h"
125 using namespace ARDOUR;
128 /** @param snapshot_name Snapshot name, without the .ardour prefix */
130 Session::first_stage_init (string fullpath, string snapshot_name)
132 if (fullpath.length() == 0) {
134 throw failed_constructor();
137 char buf[PATH_MAX+1];
138 if (!realpath (fullpath.c_str(), buf) && (errno != ENOENT)) {
139 error << string_compose(_("Could not use path %1 (%s)"), buf, strerror(errno)) << endmsg;
141 throw failed_constructor();
146 if (_path[_path.length()-1] != G_DIR_SEPARATOR) {
147 _path += G_DIR_SEPARATOR;
150 /* these two are just provisional settings. set_state()
151 will likely override them.
154 _name = _current_snapshot_name = snapshot_name;
156 set_history_depth (Config->get_history_depth());
158 _current_frame_rate = _engine.frame_rate ();
159 _nominal_frame_rate = _current_frame_rate;
160 _base_frame_rate = _current_frame_rate;
162 _tempo_map = new TempoMap (_current_frame_rate);
163 _tempo_map->PropertyChanged.connect_same_thread (*this, boost::bind (&Session::tempo_map_changed, this, _1));
166 _non_soloed_outs_muted = false;
168 _solo_isolated_cnt = 0;
169 g_atomic_int_set (&processing_prohibited, 0);
170 _transport_speed = 0;
171 _default_transport_speed = 1.0;
172 _last_transport_speed = 0;
173 _target_transport_speed = 0;
174 auto_play_legal = false;
175 transport_sub_state = 0;
176 _transport_frame = 0;
177 _requested_return_frame = -1;
178 _session_range_location = 0;
179 g_atomic_int_set (&_record_status, Disabled);
180 loop_changing = false;
183 _last_roll_location = 0;
184 _last_roll_or_reversal_location = 0;
185 _last_record_location = 0;
186 pending_locate_frame = 0;
187 pending_locate_roll = false;
188 pending_locate_flush = false;
189 state_was_pending = false;
191 outbound_mtc_timecode_frame = 0;
192 next_quarter_frame_to_send = -1;
193 current_block_size = 0;
194 solo_update_disabled = false;
195 _have_captured = false;
196 _worst_output_latency = 0;
197 _worst_input_latency = 0;
198 _worst_track_latency = 0;
199 _state_of_the_state = StateOfTheState(CannotSave|InitialConnecting|Loading);
200 _was_seamless = Config->get_seamless_loop ();
202 _send_qf_mtc = false;
203 _pframes_since_last_mtc = 0;
204 g_atomic_int_set (&_playback_load, 100);
205 g_atomic_int_set (&_capture_load, 100);
208 pending_abort = false;
209 _adding_routes_in_progress = false;
210 destructive_index = 0;
211 first_file_data_format_reset = true;
212 first_file_header_format_reset = true;
213 post_export_sync = false;
216 no_questions_about_missing_files = false;
217 _speakers.reset (new Speakers);
219 ignore_route_processor_changes = false;
220 _pre_export_mmc_enabled = false;
222 AudioDiskstream::allocate_working_buffers();
224 /* default short fade = 15ms */
226 SndFileSource::setup_standard_crossfades (*this, frame_rate());
228 last_mmc_step.tv_sec = 0;
229 last_mmc_step.tv_usec = 0;
232 /* click sounds are unset by default, which causes us to internal
233 waveforms for clicks.
237 click_emphasis_length = 0;
240 process_function = &Session::process_with_events;
242 if (config.get_use_video_sync()) {
243 waiting_for_sync_offset = true;
245 waiting_for_sync_offset = false;
248 last_timecode_when = 0;
249 last_timecode_valid = false;
253 last_rr_session_dir = session_dirs.begin();
254 refresh_disk_space ();
256 /* default: assume simple stereo speaker configuration */
258 _speakers->setup_default_speakers (2);
262 average_slave_delta = 1800; // !!! why 1800 ????
263 have_first_delta_accumulator = false;
264 delta_accumulator_cnt = 0;
265 _slave_state = Stopped;
267 _solo_cut_control.reset (new ProxyControllable (_("solo cut control (dB)"), PBD::Controllable::GainLike,
268 boost::bind (&RCConfiguration::set_solo_mute_gain, Config, _1),
269 boost::bind (&RCConfiguration::get_solo_mute_gain, Config)));
270 add_controllable (_solo_cut_control);
272 _engine.GraphReordered.connect_same_thread (*this, boost::bind (&Session::graph_reordered, this));
274 /* These are all static "per-class" signals */
276 SourceFactory::SourceCreated.connect_same_thread (*this, boost::bind (&Session::add_source, this, _1));
277 PlaylistFactory::PlaylistCreated.connect_same_thread (*this, boost::bind (&Session::add_playlist, this, _1, _2));
278 AutomationList::AutomationListCreated.connect_same_thread (*this, boost::bind (&Session::add_automation_list, this, _1));
279 Controllable::Destroyed.connect_same_thread (*this, boost::bind (&Session::remove_controllable, this, _1));
280 IO::PortCountChanged.connect_same_thread (*this, boost::bind (&Session::ensure_buffers, this, _1));
282 /* stop IO objects from doing stuff until we're ready for them */
284 Delivery::disable_panners ();
285 IO::disable_connecting ();
289 Session::second_stage_init ()
291 AudioFileSource::set_peak_dir (_session_dir->peak_path());
294 if (load_state (_current_snapshot_name)) {
299 if (_butler->start_thread()) {
303 if (start_midi_thread ()) {
307 setup_midi_machine_control ();
309 // set_state() will call setup_raid_path(), but if it's a new session we need
310 // to call setup_raid_path() here.
313 if (set_state (*state_tree->root(), Stateful::loading_state_version)) {
317 setup_raid_path(_path);
320 /* we can't save till after ::when_engine_running() is called,
321 because otherwise we save state with no connections made.
322 therefore, we reset _state_of_the_state because ::set_state()
323 will have cleared it.
325 we also have to include Loading so that any events that get
326 generated between here and the end of ::when_engine_running()
327 will be processed directly rather than queued.
330 _state_of_the_state = StateOfTheState (_state_of_the_state|CannotSave|Loading);
332 _locations->changed.connect_same_thread (*this, boost::bind (&Session::locations_changed, this));
333 _locations->added.connect_same_thread (*this, boost::bind (&Session::locations_added, this, _1));
334 setup_click_sounds (0);
335 setup_midi_control ();
337 /* Pay attention ... */
339 _engine.Halted.connect_same_thread (*this, boost::bind (&Session::engine_halted, this));
340 _engine.Xrun.connect_same_thread (*this, boost::bind (&Session::xrun_recovery, this));
342 midi_clock = new MidiClockTicker ();
343 midi_clock->set_session (this);
346 when_engine_running ();
349 /* handle this one in a different way than all others, so that its clear what happened */
351 catch (AudioEngine::PortRegistrationFailure& err) {
352 error << err.what() << endmsg;
360 BootMessage (_("Reset Remote Controls"));
362 send_full_time_code (0);
363 _engine.transport_locate (0);
365 MIDI::Manager::instance()->mmc()->send (MIDI::MachineControlCommand (MIDI::MachineControl::cmdMmcReset));
366 MIDI::Manager::instance()->mmc()->send (MIDI::MachineControlCommand (Timecode::Time ()));
368 MIDI::Name::MidiPatchManager::instance().set_session (this);
371 /* initial program change will be delivered later; see ::config_changed() */
373 _state_of_the_state = Clean;
375 Port::set_connecting_blocked (false);
377 DirtyChanged (); /* EMIT SIGNAL */
379 if (state_was_pending) {
380 save_state (_current_snapshot_name);
381 remove_pending_capture_state ();
382 state_was_pending = false;
385 BootMessage (_("Session loading complete"));
391 Session::raid_path () const
393 SearchPath raid_search_path;
395 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
396 raid_search_path += (*i).path;
399 return raid_search_path.to_string ();
403 Session::setup_raid_path (string path)
412 session_dirs.clear ();
414 SearchPath search_path(path);
415 SearchPath sound_search_path;
416 SearchPath midi_search_path;
418 for (SearchPath::const_iterator i = search_path.begin(); i != search_path.end(); ++i) {
420 sp.blocks = 0; // not needed
421 session_dirs.push_back (sp);
423 SessionDirectory sdir(sp.path);
425 sound_search_path += sdir.sound_path ();
426 midi_search_path += sdir.midi_path ();
429 // reset the round-robin soundfile path thingie
430 last_rr_session_dir = session_dirs.begin();
434 Session::path_is_within_session (const std::string& path)
436 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
437 if (PBD::path_is_within (i->path, path)) {
445 Session::ensure_subdirs ()
449 dir = session_directory().peak_path();
451 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
452 error << string_compose(_("Session: cannot create session peakfile folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
456 dir = session_directory().sound_path();
458 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
459 error << string_compose(_("Session: cannot create session sounds dir \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
463 dir = session_directory().midi_path();
465 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
466 error << string_compose(_("Session: cannot create session midi dir \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
470 dir = session_directory().dead_path();
472 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
473 error << string_compose(_("Session: cannot create session dead sounds folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
477 dir = session_directory().export_path();
479 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
480 error << string_compose(_("Session: cannot create session export folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
484 dir = analysis_dir ();
486 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
487 error << string_compose(_("Session: cannot create session analysis folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
491 dir = plugins_dir ();
493 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
494 error << string_compose(_("Session: cannot create session plugins folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
498 dir = externals_dir ();
500 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
501 error << string_compose(_("Session: cannot create session externals folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
508 /** @param session_template directory containing session template, or empty.
509 * Caller must not hold process lock.
512 Session::create (const string& session_template, BusProfile* bus_profile)
514 if (g_mkdir_with_parents (_path.c_str(), 0755) < 0) {
515 error << string_compose(_("Session: cannot create session folder \"%1\" (%2)"), _path, strerror (errno)) << endmsg;
519 if (ensure_subdirs ()) {
523 _writable = exists_and_writable (_path);
525 if (!session_template.empty()) {
526 std::string in_path = session_template_dir_to_file (session_template);
528 ifstream in(in_path.c_str());
531 string out_path = _path;
533 out_path += statefile_suffix;
535 ofstream out(out_path.c_str());
541 /* Copy plugin state files from template to new session */
542 std::string template_plugins = Glib::build_filename (session_template, X_("plugins"));
543 copy_files (template_plugins, plugins_dir ());
548 error << string_compose (_("Could not open %1 for writing session template"), out_path)
554 error << string_compose (_("Could not open session template %1 for reading"), in_path)
561 /* set initial start + end point */
563 _state_of_the_state = Clean;
565 /* set up Master Out and Control Out if necessary */
570 ChanCount count(DataType::AUDIO, bus_profile->master_out_channels);
572 if (bus_profile->master_out_channels) {
573 boost::shared_ptr<Route> r (new Route (*this, _("master"), Route::MasterOut, DataType::AUDIO));
577 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
578 // boost_debug_shared_ptr_mark_interesting (r.get(), "Route");
581 Glib::Threads::Mutex::Lock lm (AudioEngine::instance()->process_lock ());
582 r->input()->ensure_io (count, false, this);
583 r->output()->ensure_io (count, false, this);
589 /* prohibit auto-connect to master, because there isn't one */
590 bus_profile->output_ac = AutoConnectOption (bus_profile->output_ac & ~AutoConnectMaster);
594 add_routes (rl, false, false, false);
597 /* this allows the user to override settings with an environment variable.
600 if (no_auto_connect()) {
601 bus_profile->input_ac = AutoConnectOption (0);
602 bus_profile->output_ac = AutoConnectOption (0);
605 Config->set_input_auto_connect (bus_profile->input_ac);
606 Config->set_output_auto_connect (bus_profile->output_ac);
609 if (Config->get_use_monitor_bus() && bus_profile) {
610 add_monitor_section ();
619 Session::maybe_write_autosave()
621 if (dirty() && record_status() != Recording) {
622 save_state("", true);
627 Session::remove_pending_capture_state ()
629 std::string pending_state_file_path(_session_dir->root_path());
631 pending_state_file_path = Glib::build_filename (pending_state_file_path, legalize_for_path (_current_snapshot_name) + pending_suffix);
633 if (!Glib::file_test (pending_state_file_path, Glib::FILE_TEST_EXISTS)) return;
635 if (g_remove (pending_state_file_path.c_str()) != 0) {
636 error << string_compose(_("Could not remove pending capture state at path \"%1\" (%2)"),
637 pending_state_file_path, g_strerror (errno)) << endmsg;
641 /** Rename a state file.
642 * @param old_name Old snapshot name.
643 * @param new_name New snapshot name.
646 Session::rename_state (string old_name, string new_name)
648 if (old_name == _current_snapshot_name || old_name == _name) {
649 /* refuse to rename the current snapshot or the "main" one */
653 const string old_xml_filename = legalize_for_path (old_name) + statefile_suffix;
654 const string new_xml_filename = legalize_for_path (new_name) + statefile_suffix;
656 const std::string old_xml_path(Glib::build_filename (_session_dir->root_path(), old_xml_filename));
657 const std::string new_xml_path(Glib::build_filename (_session_dir->root_path(), new_xml_filename));
659 if (::g_rename (old_xml_path.c_str(), new_xml_path.c_str()) != 0) {
660 error << string_compose(_("could not rename snapshot %1 to %2 (%3)"),
661 old_name, new_name, g_strerror(errno)) << endmsg;
665 /** Remove a state file.
666 * @param snapshot_name Snapshot name.
669 Session::remove_state (string snapshot_name)
671 if (!_writable || snapshot_name == _current_snapshot_name || snapshot_name == _name) {
672 // refuse to remove the current snapshot or the "main" one
676 std::string xml_path(_session_dir->root_path());
678 xml_path = Glib::build_filename (xml_path, legalize_for_path (snapshot_name) + statefile_suffix);
680 if (!create_backup_file (xml_path)) {
681 // don't remove it if a backup can't be made
682 // create_backup_file will log the error.
687 if (g_remove (xml_path.c_str()) != 0) {
688 error << string_compose(_("Could not remove session file at path \"%1\" (%2)"),
689 xml_path, g_strerror (errno)) << endmsg;
693 #ifdef HAVE_JACK_SESSION
695 Session::jack_session_event (jack_session_event_t * event)
699 struct tm local_time;
702 localtime_r (&n, &local_time);
703 strftime (timebuf, sizeof(timebuf), "JS_%FT%T", &local_time);
705 if (event->type == JackSessionSaveTemplate)
707 if (save_template( timebuf )) {
708 event->flags = JackSessionSaveError;
710 string cmd ("ardour3 -P -U ");
711 cmd += event->client_uuid;
715 event->command_line = strdup (cmd.c_str());
720 if (save_state (timebuf)) {
721 event->flags = JackSessionSaveError;
723 std::string xml_path (_session_dir->root_path());
724 std::string legalized_filename = legalize_for_path (timebuf) + statefile_suffix;
725 xml_path = Glib::build_filename (xml_path, legalized_filename);
727 string cmd ("ardour3 -P -U ");
728 cmd += event->client_uuid;
733 event->command_line = strdup (cmd.c_str());
737 jack_session_reply (_engine.jack(), event);
739 if (event->type == JackSessionSaveAndQuit) {
740 Quit (); /* EMIT SIGNAL */
743 jack_session_event_free( event );
747 /** @param snapshot_name Name to save under, without .ardour / .pending prefix */
749 Session::save_state (string snapshot_name, bool pending, bool switch_to_snapshot)
752 std::string xml_path(_session_dir->root_path());
754 if (!_writable || (_state_of_the_state & CannotSave)) {
758 if (!_engine.connected ()) {
759 error << string_compose (_("the %1 audio engine is not connected and state saving would lose all I/O connections. Session not saved"),
765 /* tell sources we're saving first, in case they write out to a new file
766 * which should be saved with the state rather than the old one */
767 for (SourceMap::const_iterator i = sources.begin(); i != sources.end(); ++i) {
769 i->second->session_saved();
770 } catch (Evoral::SMF::FileError& e) {
771 error << string_compose ("Could not write to MIDI file %1; MIDI data not saved.", e.file_name ()) << endmsg;
775 tree.set_root (&get_state());
777 if (snapshot_name.empty()) {
778 snapshot_name = _current_snapshot_name;
779 } else if (switch_to_snapshot) {
780 _current_snapshot_name = snapshot_name;
785 /* proper save: use statefile_suffix (.ardour in English) */
787 xml_path = Glib::build_filename (xml_path, legalize_for_path (snapshot_name) + statefile_suffix);
789 /* make a backup copy of the old file */
791 if (Glib::file_test (xml_path, Glib::FILE_TEST_EXISTS) && !create_backup_file (xml_path)) {
792 // create_backup_file will log the error
798 /* pending save: use pending_suffix (.pending in English) */
799 xml_path = Glib::build_filename (xml_path, legalize_for_path (snapshot_name) + pending_suffix);
802 std::string tmp_path(_session_dir->root_path());
803 tmp_path = Glib::build_filename (tmp_path, legalize_for_path (snapshot_name) + temp_suffix);
805 // cerr << "actually writing state to " << xml_path << endl;
807 if (!tree.write (tmp_path)) {
808 error << string_compose (_("state could not be saved to %1"), tmp_path) << endmsg;
809 if (g_remove (tmp_path.c_str()) != 0) {
810 error << string_compose(_("Could not remove temporary session file at path \"%1\" (%2)"),
811 tmp_path, g_strerror (errno)) << endmsg;
817 if (::rename (tmp_path.c_str(), xml_path.c_str()) != 0) {
818 error << string_compose (_("could not rename temporary session file %1 to %2"),
819 tmp_path, xml_path) << endmsg;
820 if (g_remove (tmp_path.c_str()) != 0) {
821 error << string_compose(_("Could not remove temporary session file at path \"%1\" (%2)"),
822 tmp_path, g_strerror (errno)) << endmsg;
830 save_history (snapshot_name);
832 bool was_dirty = dirty();
834 _state_of_the_state = StateOfTheState (_state_of_the_state & ~Dirty);
837 DirtyChanged (); /* EMIT SIGNAL */
840 StateSaved (snapshot_name); /* EMIT SIGNAL */
847 Session::restore_state (string snapshot_name)
849 if (load_state (snapshot_name) == 0) {
850 set_state (*state_tree->root(), Stateful::loading_state_version);
857 Session::load_state (string snapshot_name)
862 state_was_pending = false;
864 /* check for leftover pending state from a crashed capture attempt */
866 std::string xmlpath(_session_dir->root_path());
867 xmlpath = Glib::build_filename (xmlpath, legalize_for_path (snapshot_name) + pending_suffix);
869 if (Glib::file_test (xmlpath, Glib::FILE_TEST_EXISTS)) {
871 /* there is pending state from a crashed capture attempt */
873 boost::optional<int> r = AskAboutPendingState();
874 if (r.get_value_or (1)) {
875 state_was_pending = true;
879 if (!state_was_pending) {
880 xmlpath = Glib::build_filename (_session_dir->root_path(), snapshot_name);
883 if (!Glib::file_test (xmlpath, Glib::FILE_TEST_EXISTS)) {
884 xmlpath = Glib::build_filename (_session_dir->root_path(), legalize_for_path (snapshot_name) + statefile_suffix);
885 if (!Glib::file_test (xmlpath, Glib::FILE_TEST_EXISTS)) {
886 error << string_compose(_("%1: session file \"%2\" doesn't exist!"), _name, xmlpath) << endmsg;
891 state_tree = new XMLTree;
895 _writable = exists_and_writable (xmlpath);
897 if (!state_tree->read (xmlpath)) {
898 error << string_compose(_("Could not understand session file %1"), xmlpath) << endmsg;
904 XMLNode& root (*state_tree->root());
906 if (root.name() != X_("Session")) {
907 error << string_compose (_("Session file %1 is not a session"), xmlpath) << endmsg;
913 const XMLProperty* prop;
915 if ((prop = root.property ("version")) == 0) {
916 /* no version implies very old version of Ardour */
917 Stateful::loading_state_version = 1000;
919 if (prop->value().find ('.') != string::npos) {
920 /* old school version format */
921 if (prop->value()[0] == '2') {
922 Stateful::loading_state_version = 2000;
924 Stateful::loading_state_version = 3000;
927 Stateful::loading_state_version = atoi (prop->value());
931 if (Stateful::loading_state_version < CURRENT_SESSION_FILE_VERSION && _writable) {
933 std::string backup_path(_session_dir->root_path());
934 std::string backup_filename = string_compose ("%1-%2%3", legalize_for_path (snapshot_name), Stateful::loading_state_version, statefile_suffix);
935 backup_path = Glib::build_filename (backup_path, backup_filename);
937 // only create a backup for a given statefile version once
939 if (!Glib::file_test (backup_path, Glib::FILE_TEST_EXISTS)) {
941 info << string_compose (_("Copying old session file %1 to %2\nUse %2 with %3 versions before 2.0 from now on"),
942 xmlpath, backup_path, PROGRAM_NAME)
945 if (!copy_file (xmlpath, backup_path)) {;
955 Session::load_options (const XMLNode& node)
957 LocaleGuard lg (X_("POSIX"));
958 config.set_variables (node);
969 Session::get_template()
971 /* if we don't disable rec-enable, diskstreams
972 will believe they need to store their capture
973 sources in their state node.
976 disable_record (false);
982 Session::state (bool full_state)
984 XMLNode* node = new XMLNode("Session");
988 snprintf(buf, sizeof(buf), "%d", CURRENT_SESSION_FILE_VERSION);
989 node->add_property("version", buf);
991 /* store configuration settings */
995 node->add_property ("name", _name);
996 snprintf (buf, sizeof (buf), "%" PRId64, _nominal_frame_rate);
997 node->add_property ("sample-rate", buf);
999 if (session_dirs.size() > 1) {
1003 vector<space_and_path>::iterator i = session_dirs.begin();
1004 vector<space_and_path>::iterator next;
1006 ++i; /* skip the first one */
1010 while (i != session_dirs.end()) {
1014 if (next != session_dirs.end()) {
1024 child = node->add_child ("Path");
1025 child->add_content (p);
1029 /* save the ID counter */
1031 snprintf (buf, sizeof (buf), "%" PRIu64, ID::counter());
1032 node->add_property ("id-counter", buf);
1034 /* save the event ID counter */
1036 snprintf (buf, sizeof (buf), "%d", Evoral::event_id_counter());
1037 node->add_property ("event-counter", buf);
1039 /* various options */
1041 node->add_child_nocopy (config.get_variables ());
1043 node->add_child_nocopy (ARDOUR::SessionMetadata::Metadata()->get_state());
1045 child = node->add_child ("Sources");
1048 Glib::Threads::Mutex::Lock sl (source_lock);
1050 for (SourceMap::iterator siter = sources.begin(); siter != sources.end(); ++siter) {
1052 /* Don't save information about non-file Sources, or
1053 * about non-destructive file sources that are empty
1054 * and unused by any regions.
1057 boost::shared_ptr<FileSource> fs;
1059 if ((fs = boost::dynamic_pointer_cast<FileSource> (siter->second)) != 0) {
1061 if (!fs->destructive()) {
1062 if (fs->empty() && !fs->used()) {
1067 child->add_child_nocopy (siter->second->get_state());
1072 child = node->add_child ("Regions");
1075 Glib::Threads::Mutex::Lock rl (region_lock);
1076 const RegionFactory::RegionMap& region_map (RegionFactory::all_regions());
1077 for (RegionFactory::RegionMap::const_iterator i = region_map.begin(); i != region_map.end(); ++i) {
1078 boost::shared_ptr<Region> r = i->second;
1079 /* only store regions not attached to playlists */
1080 if (r->playlist() == 0) {
1081 child->add_child_nocopy (r->state ());
1085 RegionFactory::CompoundAssociations& cassocs (RegionFactory::compound_associations());
1087 if (!cassocs.empty()) {
1088 XMLNode* ca = node->add_child (X_("CompoundAssociations"));
1090 for (RegionFactory::CompoundAssociations::iterator i = cassocs.begin(); i != cassocs.end(); ++i) {
1092 XMLNode* can = new XMLNode (X_("CompoundAssociation"));
1093 i->first->id().print (buf, sizeof (buf));
1094 can->add_property (X_("copy"), buf);
1095 i->second->id().print (buf, sizeof (buf));
1096 can->add_property (X_("original"), buf);
1097 ca->add_child_nocopy (*can);
1103 node->add_child_nocopy (_locations->get_state());
1105 // for a template, just create a new Locations, populate it
1106 // with the default start and end, and get the state for that.
1107 Locations loc (*this);
1108 Location* range = new Location (*this, 0, 0, _("session"), Location::IsSessionRange);
1109 range->set (max_framepos, 0);
1111 node->add_child_nocopy (loc.get_state());
1114 child = node->add_child ("Bundles");
1116 boost::shared_ptr<BundleList> bundles = _bundles.reader ();
1117 for (BundleList::iterator i = bundles->begin(); i != bundles->end(); ++i) {
1118 boost::shared_ptr<UserBundle> b = boost::dynamic_pointer_cast<UserBundle> (*i);
1120 child->add_child_nocopy (b->get_state());
1125 child = node->add_child ("Routes");
1127 boost::shared_ptr<RouteList> r = routes.reader ();
1129 RoutePublicOrderSorter cmp;
1130 RouteList public_order (*r);
1131 public_order.sort (cmp);
1133 /* the sort should have put control outs first */
1136 assert (_monitor_out == public_order.front());
1139 for (RouteList::iterator i = public_order.begin(); i != public_order.end(); ++i) {
1140 if (!(*i)->is_hidden()) {
1142 child->add_child_nocopy ((*i)->get_state());
1144 child->add_child_nocopy ((*i)->get_template());
1150 playlists->add_state (node, full_state);
1152 child = node->add_child ("RouteGroups");
1153 for (list<RouteGroup *>::iterator i = _route_groups.begin(); i != _route_groups.end(); ++i) {
1154 child->add_child_nocopy ((*i)->get_state());
1158 XMLNode* gain_child = node->add_child ("Click");
1159 gain_child->add_child_nocopy (_click_io->state (full_state));
1160 gain_child->add_child_nocopy (_click_gain->state (full_state));
1164 XMLNode* ltc_input_child = node->add_child ("LTC-In");
1165 ltc_input_child->add_child_nocopy (_ltc_input->state (full_state));
1169 XMLNode* ltc_output_child = node->add_child ("LTC-Out");
1170 ltc_output_child->add_child_nocopy (_ltc_output->state (full_state));
1173 node->add_child_nocopy (_speakers->get_state());
1174 node->add_child_nocopy (_tempo_map->get_state());
1175 node->add_child_nocopy (get_control_protocol_state());
1178 node->add_child_copy (*_extra_xml);
1185 Session::get_control_protocol_state ()
1187 ControlProtocolManager& cpm (ControlProtocolManager::instance());
1188 return cpm.get_state();
1192 Session::set_state (const XMLNode& node, int version)
1196 const XMLProperty* prop;
1199 _state_of_the_state = StateOfTheState (_state_of_the_state|CannotSave);
1201 if (node.name() != X_("Session")) {
1202 fatal << _("programming error: Session: incorrect XML node sent to set_state()") << endmsg;
1206 if ((prop = node.property ("name")) != 0) {
1207 _name = prop->value ();
1210 if ((prop = node.property (X_("sample-rate"))) != 0) {
1212 _nominal_frame_rate = atoi (prop->value());
1214 if (_nominal_frame_rate != _current_frame_rate) {
1215 boost::optional<int> r = AskAboutSampleRateMismatch (_nominal_frame_rate, _current_frame_rate);
1216 if (r.get_value_or (0)) {
1222 setup_raid_path(_session_dir->root_path());
1224 if ((prop = node.property (X_("id-counter"))) != 0) {
1226 sscanf (prop->value().c_str(), "%" PRIu64, &x);
1227 ID::init_counter (x);
1229 /* old sessions used a timebased counter, so fake
1230 the startup ID counter based on a standard
1235 ID::init_counter (now);
1238 if ((prop = node.property (X_("event-counter"))) != 0) {
1239 Evoral::init_event_id_counter (atoi (prop->value()));
1242 IO::disable_connecting ();
1244 Stateful::save_extra_xml (node);
1246 if (((child = find_named_node (node, "Options")) != 0)) { /* old style */
1247 load_options (*child);
1248 } else if ((child = find_named_node (node, "Config")) != 0) { /* new style */
1249 load_options (*child);
1251 error << _("Session: XML state has no options section") << endmsg;
1254 if (version >= 3000) {
1255 if ((child = find_named_node (node, "Metadata")) == 0) {
1256 warning << _("Session: XML state has no metadata section") << endmsg;
1257 } else if ( ARDOUR::SessionMetadata::Metadata()->set_state (*child, version) ) {
1262 if ((child = find_named_node (node, X_("Speakers"))) != 0) {
1263 _speakers->set_state (*child, version);
1266 if ((child = find_named_node (node, "Sources")) == 0) {
1267 error << _("Session: XML state has no sources section") << endmsg;
1269 } else if (load_sources (*child)) {
1273 if ((child = find_named_node (node, "TempoMap")) == 0) {
1274 error << _("Session: XML state has no Tempo Map section") << endmsg;
1276 } else if (_tempo_map->set_state (*child, version)) {
1280 if ((child = find_named_node (node, "Locations")) == 0) {
1281 error << _("Session: XML state has no locations section") << endmsg;
1283 } else if (_locations->set_state (*child, version)) {
1289 if ((location = _locations->auto_loop_location()) != 0) {
1290 set_auto_loop_location (location);
1293 if ((location = _locations->auto_punch_location()) != 0) {
1294 set_auto_punch_location (location);
1297 if ((location = _locations->session_range_location()) != 0) {
1298 delete _session_range_location;
1299 _session_range_location = location;
1302 if (_session_range_location) {
1303 AudioFileSource::set_header_position_offset (_session_range_location->start());
1306 if ((child = find_named_node (node, "Regions")) == 0) {
1307 error << _("Session: XML state has no Regions section") << endmsg;
1309 } else if (load_regions (*child)) {
1313 if ((child = find_named_node (node, "Playlists")) == 0) {
1314 error << _("Session: XML state has no playlists section") << endmsg;
1316 } else if (playlists->load (*this, *child)) {
1320 if ((child = find_named_node (node, "UnusedPlaylists")) == 0) {
1322 } else if (playlists->load_unused (*this, *child)) {
1326 if ((child = find_named_node (node, "CompoundAssociations")) != 0) {
1327 if (load_compounds (*child)) {
1332 if (version >= 3000) {
1333 if ((child = find_named_node (node, "Bundles")) == 0) {
1334 warning << _("Session: XML state has no bundles section") << endmsg;
1337 /* We can't load Bundles yet as they need to be able
1338 to convert from port names to Port objects, which can't happen until
1340 _bundle_xml_node = new XMLNode (*child);
1344 if (version < 3000) {
1345 if ((child = find_named_node (node, X_("DiskStreams"))) == 0) {
1346 error << _("Session: XML state has no diskstreams section") << endmsg;
1348 } else if (load_diskstreams_2X (*child, version)) {
1353 if ((child = find_named_node (node, "Routes")) == 0) {
1354 error << _("Session: XML state has no routes section") << endmsg;
1356 } else if (load_routes (*child, version)) {
1360 /* our diskstreams list is no longer needed as they are now all owned by their Route */
1361 _diskstreams_2X.clear ();
1363 if (version >= 3000) {
1365 if ((child = find_named_node (node, "RouteGroups")) == 0) {
1366 error << _("Session: XML state has no route groups section") << endmsg;
1368 } else if (load_route_groups (*child, version)) {
1372 } else if (version < 3000) {
1374 if ((child = find_named_node (node, "EditGroups")) == 0) {
1375 error << _("Session: XML state has no edit groups section") << endmsg;
1377 } else if (load_route_groups (*child, version)) {
1381 if ((child = find_named_node (node, "MixGroups")) == 0) {
1382 error << _("Session: XML state has no mix groups section") << endmsg;
1384 } else if (load_route_groups (*child, version)) {
1389 if ((child = find_named_node (node, "Click")) == 0) {
1390 warning << _("Session: XML state has no click section") << endmsg;
1391 } else if (_click_io) {
1392 const XMLNodeList& children (child->children());
1393 XMLNodeList::const_iterator i = children.begin();
1394 _click_io->set_state (**i, version);
1396 if (i != children.end()) {
1397 _click_gain->set_state (**i, version);
1401 if ((child = find_named_node (node, ControlProtocolManager::state_node_name)) != 0) {
1402 ControlProtocolManager::instance().set_state (*child, version);
1405 update_have_rec_enabled_track ();
1407 /* here beginneth the second phase ... */
1409 StateReady (); /* EMIT SIGNAL */
1418 Session::load_routes (const XMLNode& node, int version)
1421 XMLNodeConstIterator niter;
1422 RouteList new_routes;
1424 nlist = node.children();
1428 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1430 boost::shared_ptr<Route> route;
1431 if (version < 3000) {
1432 route = XMLRouteFactory_2X (**niter, version);
1434 route = XMLRouteFactory (**niter, version);
1438 error << _("Session: cannot create Route from XML description.") << endmsg;
1442 BootMessage (string_compose (_("Loaded track/bus %1"), route->name()));
1444 new_routes.push_back (route);
1447 add_routes (new_routes, false, false, false);
1452 boost::shared_ptr<Route>
1453 Session::XMLRouteFactory (const XMLNode& node, int version)
1455 boost::shared_ptr<Route> ret;
1457 if (node.name() != "Route") {
1461 XMLNode* ds_child = find_named_node (node, X_("Diskstream"));
1463 DataType type = DataType::AUDIO;
1464 const XMLProperty* prop = node.property("default-type");
1467 type = DataType (prop->value());
1470 assert (type != DataType::NIL);
1474 boost::shared_ptr<Track> track;
1476 if (type == DataType::AUDIO) {
1477 track.reset (new AudioTrack (*this, X_("toBeResetFroXML")));
1479 track.reset (new MidiTrack (*this, X_("toBeResetFroXML")));
1482 if (track->init()) {
1486 if (track->set_state (node, version)) {
1490 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
1491 // boost_debug_shared_ptr_mark_interesting (track.get(), "Track");
1496 boost::shared_ptr<Route> r (new Route (*this, X_("toBeResetFroXML")));
1498 if (r->init () == 0 && r->set_state (node, version) == 0) {
1499 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
1500 // boost_debug_shared_ptr_mark_interesting (r.get(), "Route");
1509 boost::shared_ptr<Route>
1510 Session::XMLRouteFactory_2X (const XMLNode& node, int version)
1512 boost::shared_ptr<Route> ret;
1514 if (node.name() != "Route") {
1518 XMLProperty const * ds_prop = node.property (X_("diskstream-id"));
1520 ds_prop = node.property (X_("diskstream"));
1523 DataType type = DataType::AUDIO;
1524 const XMLProperty* prop = node.property("default-type");
1527 type = DataType (prop->value());
1530 assert (type != DataType::NIL);
1534 list<boost::shared_ptr<Diskstream> >::iterator i = _diskstreams_2X.begin ();
1535 while (i != _diskstreams_2X.end() && (*i)->id() != ds_prop->value()) {
1539 if (i == _diskstreams_2X.end()) {
1540 error << _("Could not find diskstream for route") << endmsg;
1541 return boost::shared_ptr<Route> ();
1544 boost::shared_ptr<Track> track;
1546 if (type == DataType::AUDIO) {
1547 track.reset (new AudioTrack (*this, X_("toBeResetFroXML")));
1549 track.reset (new MidiTrack (*this, X_("toBeResetFroXML")));
1552 if (track->init()) {
1556 if (track->set_state (node, version)) {
1560 track->set_diskstream (*i);
1562 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
1563 // boost_debug_shared_ptr_mark_interesting (track.get(), "Track");
1568 boost::shared_ptr<Route> r (new Route (*this, X_("toBeResetFroXML")));
1570 if (r->init () == 0 && r->set_state (node, version) == 0) {
1571 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
1572 // boost_debug_shared_ptr_mark_interesting (r.get(), "Route");
1582 Session::load_regions (const XMLNode& node)
1585 XMLNodeConstIterator niter;
1586 boost::shared_ptr<Region> region;
1588 nlist = node.children();
1592 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1593 if ((region = XMLRegionFactory (**niter, false)) == 0) {
1594 error << _("Session: cannot create Region from XML description.");
1595 const XMLProperty *name = (**niter).property("name");
1598 error << " " << string_compose (_("Can not load state for region '%1'"), name->value());
1609 Session::load_compounds (const XMLNode& node)
1611 XMLNodeList calist = node.children();
1612 XMLNodeConstIterator caiter;
1613 XMLProperty *caprop;
1615 for (caiter = calist.begin(); caiter != calist.end(); ++caiter) {
1616 XMLNode* ca = *caiter;
1620 if ((caprop = ca->property (X_("original"))) == 0) {
1623 orig_id = caprop->value();
1625 if ((caprop = ca->property (X_("copy"))) == 0) {
1628 copy_id = caprop->value();
1630 boost::shared_ptr<Region> orig = RegionFactory::region_by_id (orig_id);
1631 boost::shared_ptr<Region> copy = RegionFactory::region_by_id (copy_id);
1633 if (!orig || !copy) {
1634 warning << string_compose (_("Regions in compound description not found (ID's %1 and %2): ignored"),
1640 RegionFactory::add_compound_association (orig, copy);
1647 Session::load_nested_sources (const XMLNode& node)
1650 XMLNodeConstIterator niter;
1652 nlist = node.children();
1654 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1655 if ((*niter)->name() == "Source") {
1657 /* it may already exist, so don't recreate it unnecessarily
1660 XMLProperty* prop = (*niter)->property (X_("id"));
1662 error << _("Nested source has no ID info in session file! (ignored)") << endmsg;
1666 ID source_id (prop->value());
1668 if (!source_by_id (source_id)) {
1671 SourceFactory::create (*this, **niter, true);
1673 catch (failed_constructor& err) {
1674 error << string_compose (_("Cannot reconstruct nested source for region %1"), name()) << endmsg;
1681 boost::shared_ptr<Region>
1682 Session::XMLRegionFactory (const XMLNode& node, bool full)
1684 const XMLProperty* type = node.property("type");
1688 const XMLNodeList& nlist = node.children();
1690 for (XMLNodeConstIterator niter = nlist.begin(); niter != nlist.end(); ++niter) {
1691 XMLNode *child = (*niter);
1692 if (child->name() == "NestedSource") {
1693 load_nested_sources (*child);
1697 if (!type || type->value() == "audio") {
1698 return boost::shared_ptr<Region>(XMLAudioRegionFactory (node, full));
1699 } else if (type->value() == "midi") {
1700 return boost::shared_ptr<Region>(XMLMidiRegionFactory (node, full));
1703 } catch (failed_constructor& err) {
1704 return boost::shared_ptr<Region> ();
1707 return boost::shared_ptr<Region> ();
1710 boost::shared_ptr<AudioRegion>
1711 Session::XMLAudioRegionFactory (const XMLNode& node, bool /*full*/)
1713 const XMLProperty* prop;
1714 boost::shared_ptr<Source> source;
1715 boost::shared_ptr<AudioSource> as;
1717 SourceList master_sources;
1718 uint32_t nchans = 1;
1721 if (node.name() != X_("Region")) {
1722 return boost::shared_ptr<AudioRegion>();
1725 if ((prop = node.property (X_("channels"))) != 0) {
1726 nchans = atoi (prop->value().c_str());
1729 if ((prop = node.property ("name")) == 0) {
1730 cerr << "no name for this region\n";
1734 if ((prop = node.property (X_("source-0"))) == 0) {
1735 if ((prop = node.property ("source")) == 0) {
1736 error << _("Session: XMLNode describing a AudioRegion is incomplete (no source)") << endmsg;
1737 return boost::shared_ptr<AudioRegion>();
1741 PBD::ID s_id (prop->value());
1743 if ((source = source_by_id (s_id)) == 0) {
1744 error << string_compose(_("Session: XMLNode describing a AudioRegion references an unknown source id =%1"), s_id) << endmsg;
1745 return boost::shared_ptr<AudioRegion>();
1748 as = boost::dynamic_pointer_cast<AudioSource>(source);
1750 error << string_compose(_("Session: XMLNode describing a AudioRegion references a non-audio source id =%1"), s_id) << endmsg;
1751 return boost::shared_ptr<AudioRegion>();
1754 sources.push_back (as);
1756 /* pickup other channels */
1758 for (uint32_t n=1; n < nchans; ++n) {
1759 snprintf (buf, sizeof(buf), X_("source-%d"), n);
1760 if ((prop = node.property (buf)) != 0) {
1762 PBD::ID id2 (prop->value());
1764 if ((source = source_by_id (id2)) == 0) {
1765 error << string_compose(_("Session: XMLNode describing a AudioRegion references an unknown source id =%1"), id2) << endmsg;
1766 return boost::shared_ptr<AudioRegion>();
1769 as = boost::dynamic_pointer_cast<AudioSource>(source);
1771 error << string_compose(_("Session: XMLNode describing a AudioRegion references a non-audio source id =%1"), id2) << endmsg;
1772 return boost::shared_ptr<AudioRegion>();
1774 sources.push_back (as);
1778 for (uint32_t n = 0; n < nchans; ++n) {
1779 snprintf (buf, sizeof(buf), X_("master-source-%d"), n);
1780 if ((prop = node.property (buf)) != 0) {
1782 PBD::ID id2 (prop->value());
1784 if ((source = source_by_id (id2)) == 0) {
1785 error << string_compose(_("Session: XMLNode describing a AudioRegion references an unknown source id =%1"), id2) << endmsg;
1786 return boost::shared_ptr<AudioRegion>();
1789 as = boost::dynamic_pointer_cast<AudioSource>(source);
1791 error << string_compose(_("Session: XMLNode describing a AudioRegion references a non-audio source id =%1"), id2) << endmsg;
1792 return boost::shared_ptr<AudioRegion>();
1794 master_sources.push_back (as);
1799 boost::shared_ptr<AudioRegion> region (boost::dynamic_pointer_cast<AudioRegion> (RegionFactory::create (sources, node)));
1801 /* a final detail: this is the one and only place that we know how long missing files are */
1803 if (region->whole_file()) {
1804 for (SourceList::iterator sx = sources.begin(); sx != sources.end(); ++sx) {
1805 boost::shared_ptr<SilentFileSource> sfp = boost::dynamic_pointer_cast<SilentFileSource> (*sx);
1807 sfp->set_length (region->length());
1812 if (!master_sources.empty()) {
1813 if (master_sources.size() != nchans) {
1814 error << _("Session: XMLNode describing an AudioRegion is missing some master sources; ignored") << endmsg;
1816 region->set_master_sources (master_sources);
1824 catch (failed_constructor& err) {
1825 return boost::shared_ptr<AudioRegion>();
1829 boost::shared_ptr<MidiRegion>
1830 Session::XMLMidiRegionFactory (const XMLNode& node, bool /*full*/)
1832 const XMLProperty* prop;
1833 boost::shared_ptr<Source> source;
1834 boost::shared_ptr<MidiSource> ms;
1837 if (node.name() != X_("Region")) {
1838 return boost::shared_ptr<MidiRegion>();
1841 if ((prop = node.property ("name")) == 0) {
1842 cerr << "no name for this region\n";
1846 if ((prop = node.property (X_("source-0"))) == 0) {
1847 if ((prop = node.property ("source")) == 0) {
1848 error << _("Session: XMLNode describing a MidiRegion is incomplete (no source)") << endmsg;
1849 return boost::shared_ptr<MidiRegion>();
1853 PBD::ID s_id (prop->value());
1855 if ((source = source_by_id (s_id)) == 0) {
1856 error << string_compose(_("Session: XMLNode describing a MidiRegion references an unknown source id =%1"), s_id) << endmsg;
1857 return boost::shared_ptr<MidiRegion>();
1860 ms = boost::dynamic_pointer_cast<MidiSource>(source);
1862 error << string_compose(_("Session: XMLNode describing a MidiRegion references a non-midi source id =%1"), s_id) << endmsg;
1863 return boost::shared_ptr<MidiRegion>();
1866 sources.push_back (ms);
1869 boost::shared_ptr<MidiRegion> region (boost::dynamic_pointer_cast<MidiRegion> (RegionFactory::create (sources, node)));
1870 /* a final detail: this is the one and only place that we know how long missing files are */
1872 if (region->whole_file()) {
1873 for (SourceList::iterator sx = sources.begin(); sx != sources.end(); ++sx) {
1874 boost::shared_ptr<SilentFileSource> sfp = boost::dynamic_pointer_cast<SilentFileSource> (*sx);
1876 sfp->set_length (region->length());
1884 catch (failed_constructor& err) {
1885 return boost::shared_ptr<MidiRegion>();
1890 Session::get_sources_as_xml ()
1893 XMLNode* node = new XMLNode (X_("Sources"));
1894 Glib::Threads::Mutex::Lock lm (source_lock);
1896 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ++i) {
1897 node->add_child_nocopy (i->second->get_state());
1904 Session::path_from_region_name (DataType type, string name, string identifier)
1906 char buf[PATH_MAX+1];
1908 SessionDirectory sdir(get_best_session_directory_for_new_source());
1909 std::string source_dir = ((type == DataType::AUDIO)
1910 ? sdir.sound_path() : sdir.midi_path());
1912 string ext = native_header_format_extension (config.get_native_file_header_format(), type);
1914 for (n = 0; n < 999999; ++n) {
1915 if (identifier.length()) {
1916 snprintf (buf, sizeof(buf), "%s%s%" PRIu32 "%s", name.c_str(),
1917 identifier.c_str(), n, ext.c_str());
1919 snprintf (buf, sizeof(buf), "%s-%" PRIu32 "%s", name.c_str(),
1923 std::string source_path = Glib::build_filename (source_dir, buf);
1925 if (!Glib::file_test (source_path, Glib::FILE_TEST_EXISTS)) {
1930 error << string_compose (_("cannot create new file from region name \"%1\" with ident = \"%2\": too many existing files with similar names"),
1939 Session::load_sources (const XMLNode& node)
1942 XMLNodeConstIterator niter;
1943 boost::shared_ptr<Source> source;
1945 nlist = node.children();
1949 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1952 if ((source = XMLSourceFactory (**niter)) == 0) {
1953 error << _("Session: cannot create Source from XML description.") << endmsg;
1956 } catch (MissingSource& err) {
1960 if (!no_questions_about_missing_files) {
1961 user_choice = MissingFile (this, err.path, err.type).get_value_or (-1);
1966 switch (user_choice) {
1968 /* user added a new search location, so try again */
1973 /* user asked to quit the entire session load
1978 no_questions_about_missing_files = true;
1982 no_questions_about_missing_files = true;
1987 warning << _("A sound file is missing. It will be replaced by silence.") << endmsg;
1988 source = SourceFactory::createSilent (*this, **niter, max_framecnt, _current_frame_rate);
1997 boost::shared_ptr<Source>
1998 Session::XMLSourceFactory (const XMLNode& node)
2000 if (node.name() != "Source") {
2001 return boost::shared_ptr<Source>();
2005 /* note: do peak building in another thread when loading session state */
2006 return SourceFactory::create (*this, node, true);
2009 catch (failed_constructor& err) {
2010 error << string_compose (_("Found a sound file that cannot be used by %1. Talk to the progammers."), PROGRAM_NAME) << endmsg;
2011 return boost::shared_ptr<Source>();
2016 Session::save_template (string template_name)
2020 if (_state_of_the_state & CannotSave) {
2024 std::string user_template_dir(user_template_directory());
2026 if (g_mkdir_with_parents (user_template_dir.c_str(), 0755) != 0) {
2027 error << string_compose(_("Could not create templates directory \"%1\" (%2)"),
2028 user_template_dir, g_strerror (errno)) << endmsg;
2032 tree.set_root (&get_template());
2034 std::string template_dir_path(user_template_dir);
2036 /* directory to put the template in */
2037 template_dir_path = Glib::build_filename (template_dir_path, template_name);
2039 if (Glib::file_test (template_dir_path, Glib::FILE_TEST_EXISTS)) {
2040 warning << string_compose(_("Template \"%1\" already exists - new version not created"),
2041 template_dir_path) << endmsg;
2045 if (g_mkdir_with_parents (template_dir_path.c_str(), 0755) != 0) {
2046 error << string_compose(_("Could not create directory for Session template\"%1\" (%2)"),
2047 template_dir_path, g_strerror (errno)) << endmsg;
2052 std::string template_file_path(template_dir_path);
2053 template_file_path = Glib::build_filename (template_file_path, template_name + template_suffix);
2055 if (!tree.write (template_file_path)) {
2056 error << _("template not saved") << endmsg;
2060 /* copy plugin state directory */
2062 std::string template_plugin_state_path(template_dir_path);
2063 template_plugin_state_path = Glib::build_filename (template_plugin_state_path, X_("plugins"));
2065 if (g_mkdir_with_parents (template_plugin_state_path.c_str(), 0755) != 0) {
2066 error << string_compose(_("Could not create directory for Session template plugin state\"%1\" (%2)"),
2067 template_plugin_state_path, g_strerror (errno)) << endmsg;
2071 copy_files (plugins_dir(), template_plugin_state_path);
2077 Session::refresh_disk_space ()
2079 #if HAVE_SYS_VFS_H && HAVE_SYS_STATVFS_H
2081 Glib::Threads::Mutex::Lock lm (space_lock);
2083 /* get freespace on every FS that is part of the session path */
2085 _total_free_4k_blocks = 0;
2086 _total_free_4k_blocks_uncertain = false;
2088 for (vector<space_and_path>::iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
2090 struct statfs statfsbuf;
2091 statfs (i->path.c_str(), &statfsbuf);
2093 double const scale = statfsbuf.f_bsize / 4096.0;
2095 /* See if this filesystem is read-only */
2096 struct statvfs statvfsbuf;
2097 statvfs (i->path.c_str(), &statvfsbuf);
2099 /* f_bavail can be 0 if it is undefined for whatever
2100 filesystem we are looking at; Samba shares mounted
2101 via GVFS are an example of this.
2103 if (statfsbuf.f_bavail == 0) {
2104 /* block count unknown */
2106 i->blocks_unknown = true;
2107 } else if (statvfsbuf.f_flag & ST_RDONLY) {
2108 /* read-only filesystem */
2110 i->blocks_unknown = false;
2112 /* read/write filesystem with known space */
2113 i->blocks = (uint32_t) floor (statfsbuf.f_bavail * scale);
2114 i->blocks_unknown = false;
2117 _total_free_4k_blocks += i->blocks;
2118 if (i->blocks_unknown) {
2119 _total_free_4k_blocks_uncertain = true;
2126 Session::get_best_session_directory_for_new_source ()
2128 vector<space_and_path>::iterator i;
2129 string result = _session_dir->root_path();
2131 /* handle common case without system calls */
2133 if (session_dirs.size() == 1) {
2137 /* OK, here's the algorithm we're following here:
2139 We want to select which directory to use for
2140 the next file source to be created. Ideally,
2141 we'd like to use a round-robin process so as to
2142 get maximum performance benefits from splitting
2143 the files across multiple disks.
2145 However, in situations without much diskspace, an
2146 RR approach may end up filling up a filesystem
2147 with new files while others still have space.
2148 Its therefore important to pay some attention to
2149 the freespace in the filesystem holding each
2150 directory as well. However, if we did that by
2151 itself, we'd keep creating new files in the file
2152 system with the most space until it was as full
2153 as all others, thus negating any performance
2154 benefits of this RAID-1 like approach.
2156 So, we use a user-configurable space threshold. If
2157 there are at least 2 filesystems with more than this
2158 much space available, we use RR selection between them.
2159 If not, then we pick the filesystem with the most space.
2161 This gets a good balance between the two
2165 refresh_disk_space ();
2167 int free_enough = 0;
2169 for (i = session_dirs.begin(); i != session_dirs.end(); ++i) {
2170 if ((*i).blocks * 4096 >= Config->get_disk_choice_space_threshold()) {
2175 if (free_enough >= 2) {
2176 /* use RR selection process, ensuring that the one
2180 i = last_rr_session_dir;
2183 if (++i == session_dirs.end()) {
2184 i = session_dirs.begin();
2187 if ((*i).blocks * 4096 >= Config->get_disk_choice_space_threshold()) {
2188 SessionDirectory sdir(i->path);
2189 if (sdir.create ()) {
2191 last_rr_session_dir = i;
2196 } while (i != last_rr_session_dir);
2200 /* pick FS with the most freespace (and that
2201 seems to actually work ...)
2204 vector<space_and_path> sorted;
2205 space_and_path_ascending_cmp cmp;
2207 sorted = session_dirs;
2208 sort (sorted.begin(), sorted.end(), cmp);
2210 for (i = sorted.begin(); i != sorted.end(); ++i) {
2211 SessionDirectory sdir(i->path);
2212 if (sdir.create ()) {
2214 last_rr_session_dir = i;
2224 Session::automation_dir () const
2226 return Glib::build_filename (_path, "automation");
2230 Session::analysis_dir () const
2232 return Glib::build_filename (_path, "analysis");
2236 Session::plugins_dir () const
2238 return Glib::build_filename (_path, "plugins");
2242 Session::externals_dir () const
2244 return Glib::build_filename (_path, "externals");
2248 Session::load_bundles (XMLNode const & node)
2250 XMLNodeList nlist = node.children();
2251 XMLNodeConstIterator niter;
2255 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2256 if ((*niter)->name() == "InputBundle") {
2257 add_bundle (boost::shared_ptr<UserBundle> (new UserBundle (**niter, true)));
2258 } else if ((*niter)->name() == "OutputBundle") {
2259 add_bundle (boost::shared_ptr<UserBundle> (new UserBundle (**niter, false)));
2261 error << string_compose(_("Unknown node \"%1\" found in Bundles list from session file"), (*niter)->name()) << endmsg;
2270 Session::load_route_groups (const XMLNode& node, int version)
2272 XMLNodeList nlist = node.children();
2273 XMLNodeConstIterator niter;
2277 if (version >= 3000) {
2279 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2280 if ((*niter)->name() == "RouteGroup") {
2281 RouteGroup* rg = new RouteGroup (*this, "");
2282 add_route_group (rg);
2283 rg->set_state (**niter, version);
2287 } else if (version < 3000) {
2289 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2290 if ((*niter)->name() == "EditGroup" || (*niter)->name() == "MixGroup") {
2291 RouteGroup* rg = new RouteGroup (*this, "");
2292 add_route_group (rg);
2293 rg->set_state (**niter, version);
2302 Session::auto_save()
2304 save_state (_current_snapshot_name);
2308 state_file_filter (const string &str, void */*arg*/)
2310 return (str.length() > strlen(statefile_suffix) &&
2311 str.find (statefile_suffix) == (str.length() - strlen (statefile_suffix)));
2315 bool operator()(const string* a, const string* b) {
2321 remove_end(string* state)
2323 string statename(*state);
2325 string::size_type start,end;
2326 if ((start = statename.find_last_of (G_DIR_SEPARATOR)) != string::npos) {
2327 statename = statename.substr (start+1);
2330 if ((end = statename.rfind(".ardour")) == string::npos) {
2331 end = statename.length();
2334 return new string(statename.substr (0, end));
2338 Session::possible_states (string path)
2340 PathScanner scanner;
2341 vector<string*>* states = scanner (path, state_file_filter, 0, false, false);
2343 transform(states->begin(), states->end(), states->begin(), remove_end);
2346 sort (states->begin(), states->end(), cmp);
2352 Session::possible_states () const
2354 return possible_states(_path);
2358 Session::add_route_group (RouteGroup* g)
2360 _route_groups.push_back (g);
2361 route_group_added (g); /* EMIT SIGNAL */
2363 g->RouteAdded.connect_same_thread (*this, boost::bind (&Session::route_added_to_route_group, this, _1, _2));
2364 g->RouteRemoved.connect_same_thread (*this, boost::bind (&Session::route_removed_from_route_group, this, _1, _2));
2365 g->PropertyChanged.connect_same_thread (*this, boost::bind (&Session::route_group_property_changed, this, g));
2371 Session::remove_route_group (RouteGroup& rg)
2373 list<RouteGroup*>::iterator i;
2375 if ((i = find (_route_groups.begin(), _route_groups.end(), &rg)) != _route_groups.end()) {
2376 _route_groups.erase (i);
2379 route_group_removed (); /* EMIT SIGNAL */
2383 /** Set a new order for our route groups, without adding or removing any.
2384 * @param groups Route group list in the new order.
2387 Session::reorder_route_groups (list<RouteGroup*> groups)
2389 _route_groups = groups;
2391 route_groups_reordered (); /* EMIT SIGNAL */
2397 Session::route_group_by_name (string name)
2399 list<RouteGroup *>::iterator i;
2401 for (i = _route_groups.begin(); i != _route_groups.end(); ++i) {
2402 if ((*i)->name() == name) {
2410 Session::all_route_group() const
2412 return *_all_route_group;
2416 Session::add_commands (vector<Command*> const & cmds)
2418 for (vector<Command*>::const_iterator i = cmds.begin(); i != cmds.end(); ++i) {
2424 Session::begin_reversible_command (const string& name)
2426 begin_reversible_command (g_quark_from_string (name.c_str ()));
2429 /** Begin a reversible command using a GQuark to identify it.
2430 * begin_reversible_command() and commit_reversible_command() calls may be nested,
2431 * but there must be as many begin...()s as there are commit...()s.
2434 Session::begin_reversible_command (GQuark q)
2436 /* If nested begin/commit pairs are used, we create just one UndoTransaction
2437 to hold all the commands that are committed. This keeps the order of
2438 commands correct in the history.
2441 if (_current_trans == 0) {
2442 /* start a new transaction */
2443 assert (_current_trans_quarks.empty ());
2444 _current_trans = new UndoTransaction();
2445 _current_trans->set_name (g_quark_to_string (q));
2448 _current_trans_quarks.push_front (q);
2452 Session::commit_reversible_command (Command *cmd)
2454 assert (_current_trans);
2455 assert (!_current_trans_quarks.empty ());
2460 _current_trans->add_command (cmd);
2463 _current_trans_quarks.pop_front ();
2465 if (!_current_trans_quarks.empty ()) {
2466 /* the transaction we're committing is not the top-level one */
2470 if (_current_trans->empty()) {
2471 /* no commands were added to the transaction, so just get rid of it */
2472 delete _current_trans;
2477 gettimeofday (&now, 0);
2478 _current_trans->set_timestamp (now);
2480 _history.add (_current_trans);
2485 accept_all_audio_files (const string& path, void */*arg*/)
2487 if (!Glib::file_test (path, Glib::FILE_TEST_IS_REGULAR)) {
2491 if (!AudioFileSource::safe_audio_file_extension (path)) {
2499 accept_all_midi_files (const string& path, void */*arg*/)
2501 if (!Glib::file_test (path, Glib::FILE_TEST_IS_REGULAR)) {
2505 return ((path.length() > 4 && path.find (".mid") != (path.length() - 4)) ||
2506 (path.length() > 4 && path.find (".smf") != (path.length() - 4)) ||
2507 (path.length() > 5 && path.find (".midi") != (path.length() - 5)));
2511 accept_all_state_files (const string& path, void */*arg*/)
2513 if (!Glib::file_test (path, Glib::FILE_TEST_IS_REGULAR)) {
2517 return (path.length() > 7 && path.find (".ardour") == (path.length() - 7));
2521 Session::find_all_sources (string path, set<string>& result)
2526 if (!tree.read (path)) {
2530 if ((node = find_named_node (*tree.root(), "Sources")) == 0) {
2535 XMLNodeConstIterator niter;
2537 nlist = node->children();
2541 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2545 if ((prop = (*niter)->property (X_("type"))) == 0) {
2549 DataType type (prop->value());
2551 if ((prop = (*niter)->property (X_("name"))) == 0) {
2555 if (Glib::path_is_absolute (prop->value())) {
2556 /* external file, ignore */
2564 if (FileSource::find (*this, type, prop->value(), true, is_new, chan, found_path)) {
2565 result.insert (found_path);
2573 Session::find_all_sources_across_snapshots (set<string>& result, bool exclude_this_snapshot)
2575 PathScanner scanner;
2576 vector<string*>* state_files;
2578 string this_snapshot_path;
2584 if (ripped[ripped.length()-1] == G_DIR_SEPARATOR) {
2585 ripped = ripped.substr (0, ripped.length() - 1);
2588 state_files = scanner (ripped, accept_all_state_files, (void *) 0, true, true);
2590 if (state_files == 0) {
2595 this_snapshot_path = _path;
2596 this_snapshot_path += legalize_for_path (_current_snapshot_name);
2597 this_snapshot_path += statefile_suffix;
2599 for (vector<string*>::iterator i = state_files->begin(); i != state_files->end(); ++i) {
2601 if (exclude_this_snapshot && **i == this_snapshot_path) {
2605 if (find_all_sources (**i, result) < 0) {
2613 struct RegionCounter {
2614 typedef std::map<PBD::ID,boost::shared_ptr<AudioSource> > AudioSourceList;
2615 AudioSourceList::iterator iter;
2616 boost::shared_ptr<Region> region;
2619 RegionCounter() : count (0) {}
2623 Session::ask_about_playlist_deletion (boost::shared_ptr<Playlist> p)
2625 boost::optional<int> r = AskAboutPlaylistDeletion (p);
2626 return r.get_value_or (1);
2630 Session::cleanup_regions ()
2632 const RegionFactory::RegionMap& regions (RegionFactory::regions());
2634 for (RegionFactory::RegionMap::const_iterator i = regions.begin(); i != regions.end(); ++i) {
2636 uint32_t used = playlists->region_use_count (i->second);
2638 if (used == 0 && !i->second->automatic ()) {
2639 RegionFactory::map_remove (i->second);
2643 /* dump the history list */
2650 Session::cleanup_sources (CleanupReport& rep)
2652 // FIXME: needs adaptation to midi
2654 vector<boost::shared_ptr<Source> > dead_sources;
2655 PathScanner scanner;
2658 vector<space_and_path>::iterator i;
2659 vector<space_and_path>::iterator nexti;
2660 vector<string*>* candidates;
2661 vector<string*>* candidates2;
2662 vector<string> unused;
2663 set<string> all_sources;
2668 _state_of_the_state = (StateOfTheState) (_state_of_the_state | InCleanup);
2670 /* consider deleting all unused playlists */
2672 if (playlists->maybe_delete_unused (boost::bind (Session::ask_about_playlist_deletion, _1))) {
2677 /* sync the "all regions" property of each playlist with its current state
2680 playlists->sync_all_regions_with_regions ();
2682 /* find all un-used sources */
2687 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ) {
2689 SourceMap::iterator tmp;
2694 /* do not bother with files that are zero size, otherwise we remove the current "nascent"
2698 if (!i->second->used() && (i->second->length(i->second->timeline_position() > 0))) {
2699 dead_sources.push_back (i->second);
2700 i->second->drop_references ();
2706 /* build a list of all the possible audio directories for the session */
2708 for (i = session_dirs.begin(); i != session_dirs.end(); ) {
2713 SessionDirectory sdir ((*i).path);
2714 audio_path += sdir.sound_path();
2716 if (nexti != session_dirs.end()) {
2724 /* build a list of all the possible midi directories for the session */
2726 for (i = session_dirs.begin(); i != session_dirs.end(); ) {
2731 SessionDirectory sdir ((*i).path);
2732 midi_path += sdir.midi_path();
2734 if (nexti != session_dirs.end()) {
2741 candidates = scanner (audio_path, accept_all_audio_files, (void *) 0, true, true);
2742 candidates2 = scanner (midi_path, accept_all_midi_files, (void *) 0, true, true);
2748 for (vector<string*>::iterator i = candidates2->begin(); i != candidates2->end(); ++i) {
2749 candidates->push_back (*i);
2754 candidates = candidates2; // might still be null
2757 /* find all sources, but don't use this snapshot because the
2758 state file on disk still references sources we may have already
2762 find_all_sources_across_snapshots (all_sources, true);
2764 /* add our current source list
2767 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ) {
2768 boost::shared_ptr<FileSource> fs;
2769 SourceMap::iterator tmp = i;
2772 if ((fs = boost::dynamic_pointer_cast<FileSource> (i->second)) != 0) {
2773 if (playlists->source_use_count (fs) != 0) {
2774 all_sources.insert (fs->path());
2777 /* we might not remove this source from disk, because it may be used
2778 by other snapshots, but its not being used in this version
2779 so lets get rid of it now, along with any representative regions
2783 RegionFactory::remove_regions_using_source (i->second);
2791 char tmppath1[PATH_MAX+1];
2792 char tmppath2[PATH_MAX+1];
2795 for (vector<string*>::iterator x = candidates->begin(); x != candidates->end(); ++x) {
2800 for (set<string>::iterator i = all_sources.begin(); i != all_sources.end(); ++i) {
2802 if (realpath(spath.c_str(), tmppath1) == 0) {
2803 error << string_compose (_("Cannot expand path %1 (%2)"),
2804 spath, strerror (errno)) << endmsg;
2808 if (realpath((*i).c_str(), tmppath2) == 0) {
2809 error << string_compose (_("Cannot expand path %1 (%2)"),
2810 (*i), strerror (errno)) << endmsg;
2814 if (strcmp(tmppath1, tmppath2) == 0) {
2821 unused.push_back (spath);
2830 /* now try to move all unused files into the "dead" directory(ies) */
2832 for (vector<string>::iterator x = unused.begin(); x != unused.end(); ++x) {
2833 struct stat statbuf;
2837 /* don't move the file across filesystems, just
2838 stick it in the `dead_dir_name' directory
2839 on whichever filesystem it was already on.
2842 if ((*x).find ("/sounds/") != string::npos) {
2844 /* old school, go up 1 level */
2846 newpath = Glib::path_get_dirname (*x); // "sounds"
2847 newpath = Glib::path_get_dirname (newpath); // "session-name"
2851 /* new school, go up 4 levels */
2853 newpath = Glib::path_get_dirname (*x); // "audiofiles" or "midifiles"
2854 newpath = Glib::path_get_dirname (newpath); // "session-name"
2855 newpath = Glib::path_get_dirname (newpath); // "interchange"
2856 newpath = Glib::path_get_dirname (newpath); // "session-dir"
2859 newpath = Glib::build_filename (newpath, dead_dir_name);
2861 if (g_mkdir_with_parents (newpath.c_str(), 0755) < 0) {
2862 error << string_compose(_("Session: cannot create dead file folder \"%1\" (%2)"), newpath, strerror (errno)) << endmsg;
2866 newpath = Glib::build_filename (newpath, Glib::path_get_basename ((*x)));
2868 if (Glib::file_test (newpath, Glib::FILE_TEST_EXISTS)) {
2870 /* the new path already exists, try versioning */
2872 char buf[PATH_MAX+1];
2876 snprintf (buf, sizeof (buf), "%s.%d", newpath.c_str(), version);
2879 while (Glib::file_test (newpath_v.c_str(), Glib::FILE_TEST_EXISTS) && version < 999) {
2880 snprintf (buf, sizeof (buf), "%s.%d", newpath.c_str(), ++version);
2884 if (version == 999) {
2885 error << string_compose (_("there are already 1000 files with names like %1; versioning discontinued"),
2889 newpath = newpath_v;
2894 /* it doesn't exist, or we can't read it or something */
2898 stat ((*x).c_str(), &statbuf);
2900 if (::rename ((*x).c_str(), newpath.c_str()) != 0) {
2901 error << string_compose (_("cannot rename unused file source from %1 to %2 (%3)"),
2902 (*x), newpath, strerror (errno))
2907 /* see if there an easy to find peakfile for this file, and remove it.
2910 string base = basename_nosuffix (*x);
2911 base += "%A"; /* this is what we add for the channel suffix of all native files,
2912 or for the first channel of embedded files. it will miss
2913 some peakfiles for other channels
2915 string peakpath = peak_path (base);
2917 if (Glib::file_test (peakpath.c_str(), Glib::FILE_TEST_EXISTS)) {
2918 if (::unlink (peakpath.c_str()) != 0) {
2919 error << string_compose (_("cannot remove peakfile %1 for %2 (%3)"),
2920 peakpath, _path, strerror (errno))
2922 /* try to back out */
2923 ::rename (newpath.c_str(), _path.c_str());
2928 rep.paths.push_back (*x);
2929 rep.space += statbuf.st_size;
2932 /* dump the history list */
2936 /* save state so we don't end up a session file
2937 referring to non-existent sources.
2944 _state_of_the_state = (StateOfTheState) (_state_of_the_state & ~InCleanup);
2950 Session::cleanup_trash_sources (CleanupReport& rep)
2952 // FIXME: needs adaptation for MIDI
2954 vector<space_and_path>::iterator i;
2960 for (i = session_dirs.begin(); i != session_dirs.end(); ++i) {
2962 dead_dir = Glib::build_filename ((*i).path, dead_dir_name);
2964 clear_directory (dead_dir, &rep.space, &rep.paths);
2971 Session::set_dirty ()
2973 bool was_dirty = dirty();
2975 _state_of_the_state = StateOfTheState (_state_of_the_state | Dirty);
2979 DirtyChanged(); /* EMIT SIGNAL */
2985 Session::set_clean ()
2987 bool was_dirty = dirty();
2989 _state_of_the_state = Clean;
2993 DirtyChanged(); /* EMIT SIGNAL */
2998 Session::set_deletion_in_progress ()
3000 _state_of_the_state = StateOfTheState (_state_of_the_state | Deletion);
3004 Session::clear_deletion_in_progress ()
3006 _state_of_the_state = StateOfTheState (_state_of_the_state & (~Deletion));
3010 Session::add_controllable (boost::shared_ptr<Controllable> c)
3012 /* this adds a controllable to the list managed by the Session.
3013 this is a subset of those managed by the Controllable class
3014 itself, and represents the only ones whose state will be saved
3015 as part of the session.
3018 Glib::Threads::Mutex::Lock lm (controllables_lock);
3019 controllables.insert (c);
3022 struct null_deleter { void operator()(void const *) const {} };
3025 Session::remove_controllable (Controllable* c)
3027 if (_state_of_the_state & Deletion) {
3031 Glib::Threads::Mutex::Lock lm (controllables_lock);
3033 Controllables::iterator x = controllables.find (boost::shared_ptr<Controllable>(c, null_deleter()));
3035 if (x != controllables.end()) {
3036 controllables.erase (x);
3040 boost::shared_ptr<Controllable>
3041 Session::controllable_by_id (const PBD::ID& id)
3043 Glib::Threads::Mutex::Lock lm (controllables_lock);
3045 for (Controllables::iterator i = controllables.begin(); i != controllables.end(); ++i) {
3046 if ((*i)->id() == id) {
3051 return boost::shared_ptr<Controllable>();
3054 boost::shared_ptr<Controllable>
3055 Session::controllable_by_descriptor (const ControllableDescriptor& desc)
3057 boost::shared_ptr<Controllable> c;
3058 boost::shared_ptr<Route> r;
3060 switch (desc.top_level_type()) {
3061 case ControllableDescriptor::NamedRoute:
3063 std::string str = desc.top_level_name();
3064 if (str == "master") {
3066 } else if (str == "control" || str == "listen") {
3069 r = route_by_name (desc.top_level_name());
3074 case ControllableDescriptor::RemoteControlID:
3075 r = route_by_remote_id (desc.rid());
3083 switch (desc.subtype()) {
3084 case ControllableDescriptor::Gain:
3085 c = r->gain_control ();
3088 case ControllableDescriptor::Solo:
3089 c = r->solo_control();
3092 case ControllableDescriptor::Mute:
3093 c = r->mute_control();
3096 case ControllableDescriptor::Recenable:
3098 boost::shared_ptr<Track> t = boost::dynamic_pointer_cast<Track>(r);
3101 c = t->rec_enable_control ();
3106 case ControllableDescriptor::PanDirection:
3108 c = r->pannable()->pan_azimuth_control;
3112 case ControllableDescriptor::PanWidth:
3114 c = r->pannable()->pan_width_control;
3118 case ControllableDescriptor::PanElevation:
3120 c = r->pannable()->pan_elevation_control;
3124 case ControllableDescriptor::Balance:
3125 /* XXX simple pan control */
3128 case ControllableDescriptor::PluginParameter:
3130 uint32_t plugin = desc.target (0);
3131 uint32_t parameter_index = desc.target (1);
3133 /* revert to zero based counting */
3139 if (parameter_index > 0) {
3143 boost::shared_ptr<Processor> p = r->nth_plugin (plugin);
3146 c = boost::dynamic_pointer_cast<ARDOUR::AutomationControl>(
3147 p->control(Evoral::Parameter(PluginAutomation, 0, parameter_index)));
3152 case ControllableDescriptor::SendGain:
3154 uint32_t send = desc.target (0);
3156 /* revert to zero-based counting */
3162 boost::shared_ptr<Processor> p = r->nth_send (send);
3165 boost::shared_ptr<Send> s = boost::dynamic_pointer_cast<Send>(p);
3166 boost::shared_ptr<Amp> a = s->amp();
3169 c = s->amp()->gain_control();
3176 /* relax and return a null pointer */
3184 Session::add_instant_xml (XMLNode& node, bool write_to_config)
3187 Stateful::add_instant_xml (node, _path);
3190 if (write_to_config) {
3191 Config->add_instant_xml (node);
3196 Session::instant_xml (const string& node_name)
3198 return Stateful::instant_xml (node_name, _path);
3202 Session::save_history (string snapshot_name)
3210 if (snapshot_name.empty()) {
3211 snapshot_name = _current_snapshot_name;
3214 const string history_filename = legalize_for_path (snapshot_name) + history_suffix;
3215 const string backup_filename = history_filename + backup_suffix;
3216 const std::string xml_path(Glib::build_filename (_session_dir->root_path(), history_filename));
3217 const std::string backup_path(Glib::build_filename (_session_dir->root_path(), backup_filename));
3219 if (Glib::file_test (xml_path, Glib::FILE_TEST_EXISTS)) {
3220 if (::g_rename (xml_path.c_str(), backup_path.c_str()) != 0) {
3221 error << _("could not backup old history file, current history not saved") << endmsg;
3226 if (!Config->get_save_history() || Config->get_saved_history_depth() < 0) {
3230 tree.set_root (&_history.get_state (Config->get_saved_history_depth()));
3232 if (!tree.write (xml_path))
3234 error << string_compose (_("history could not be saved to %1"), xml_path) << endmsg;
3236 if (g_remove (xml_path.c_str()) != 0) {
3237 error << string_compose(_("Could not remove history file at path \"%1\" (%2)"),
3238 xml_path, g_strerror (errno)) << endmsg;
3240 if (::g_rename (backup_path.c_str(), xml_path.c_str()) != 0) {
3241 error << string_compose (_("could not restore history file from backup %1 (%2)"),
3242 backup_path, g_strerror (errno)) << endmsg;
3252 Session::restore_history (string snapshot_name)
3256 if (snapshot_name.empty()) {
3257 snapshot_name = _current_snapshot_name;
3260 const std::string xml_filename = legalize_for_path (snapshot_name) + history_suffix;
3261 const std::string xml_path(Glib::build_filename (_session_dir->root_path(), xml_filename));
3263 info << "Loading history from " << xml_path << endmsg;
3265 if (!Glib::file_test (xml_path, Glib::FILE_TEST_EXISTS)) {
3266 info << string_compose (_("%1: no history file \"%2\" for this session."),
3267 _name, xml_path) << endmsg;
3271 if (!tree.read (xml_path)) {
3272 error << string_compose (_("Could not understand session history file \"%1\""),
3273 xml_path) << endmsg;
3280 for (XMLNodeConstIterator it = tree.root()->children().begin(); it != tree.root()->children().end(); it++) {
3283 UndoTransaction* ut = new UndoTransaction ();
3286 ut->set_name(t->property("name")->value());
3287 stringstream ss(t->property("tv-sec")->value());
3289 ss.str(t->property("tv-usec")->value());
3291 ut->set_timestamp(tv);
3293 for (XMLNodeConstIterator child_it = t->children().begin();
3294 child_it != t->children().end(); child_it++)
3296 XMLNode *n = *child_it;
3299 if (n->name() == "MementoCommand" ||
3300 n->name() == "MementoUndoCommand" ||
3301 n->name() == "MementoRedoCommand") {
3303 if ((c = memento_command_factory(n))) {
3307 } else if (n->name() == "NoteDiffCommand") {
3308 PBD::ID id (n->property("midi-source")->value());
3309 boost::shared_ptr<MidiSource> midi_source =
3310 boost::dynamic_pointer_cast<MidiSource, Source>(source_by_id(id));
3312 ut->add_command (new MidiModel::NoteDiffCommand(midi_source->model(), *n));
3314 error << _("Failed to downcast MidiSource for NoteDiffCommand") << endmsg;
3317 } else if (n->name() == "SysExDiffCommand") {
3319 PBD::ID id (n->property("midi-source")->value());
3320 boost::shared_ptr<MidiSource> midi_source =
3321 boost::dynamic_pointer_cast<MidiSource, Source>(source_by_id(id));
3323 ut->add_command (new MidiModel::SysExDiffCommand (midi_source->model(), *n));
3325 error << _("Failed to downcast MidiSource for SysExDiffCommand") << endmsg;
3328 } else if (n->name() == "PatchChangeDiffCommand") {
3330 PBD::ID id (n->property("midi-source")->value());
3331 boost::shared_ptr<MidiSource> midi_source =
3332 boost::dynamic_pointer_cast<MidiSource, Source>(source_by_id(id));
3334 ut->add_command (new MidiModel::PatchChangeDiffCommand (midi_source->model(), *n));
3336 error << _("Failed to downcast MidiSource for PatchChangeDiffCommand") << endmsg;
3339 } else if (n->name() == "StatefulDiffCommand") {
3340 if ((c = stateful_diff_command_factory (n))) {
3341 ut->add_command (c);
3344 error << string_compose(_("Couldn't figure out how to make a Command out of a %1 XMLNode."), n->name()) << endmsg;
3355 Session::config_changed (std::string p, bool ours)
3361 if (p == "seamless-loop") {
3363 } else if (p == "rf-speed") {
3365 } else if (p == "auto-loop") {
3367 } else if (p == "auto-input") {
3369 if (Config->get_monitoring_model() == HardwareMonitoring && transport_rolling()) {
3370 /* auto-input only makes a difference if we're rolling */
3371 set_track_monitor_input_status (!config.get_auto_input());
3374 } else if (p == "punch-in") {
3378 if ((location = _locations->auto_punch_location()) != 0) {
3380 if (config.get_punch_in ()) {
3381 replace_event (SessionEvent::PunchIn, location->start());
3383 remove_event (location->start(), SessionEvent::PunchIn);
3387 } else if (p == "punch-out") {
3391 if ((location = _locations->auto_punch_location()) != 0) {
3393 if (config.get_punch_out()) {
3394 replace_event (SessionEvent::PunchOut, location->end());
3396 clear_events (SessionEvent::PunchOut);
3400 } else if (p == "edit-mode") {
3402 Glib::Threads::Mutex::Lock lm (playlists->lock);
3404 for (SessionPlaylists::List::iterator i = playlists->playlists.begin(); i != playlists->playlists.end(); ++i) {
3405 (*i)->set_edit_mode (Config->get_edit_mode ());
3408 } else if (p == "use-video-sync") {
3410 waiting_for_sync_offset = config.get_use_video_sync();
3412 } else if (p == "mmc-control") {
3414 //poke_midi_thread ();
3416 } else if (p == "mmc-device-id" || p == "mmc-receive-id" || p == "mmc-receive-device-id") {
3418 MIDI::Manager::instance()->mmc()->set_receive_device_id (Config->get_mmc_receive_device_id());
3420 } else if (p == "mmc-send-id" || p == "mmc-send-device-id") {
3422 MIDI::Manager::instance()->mmc()->set_send_device_id (Config->get_mmc_send_device_id());
3424 } else if (p == "midi-control") {
3426 //poke_midi_thread ();
3428 } else if (p == "raid-path") {
3430 setup_raid_path (config.get_raid_path());
3432 } else if (p == "timecode-format") {
3436 } else if (p == "video-pullup") {
3440 } else if (p == "seamless-loop") {
3442 if (play_loop && transport_rolling()) {
3443 // to reset diskstreams etc
3444 request_play_loop (true);
3447 } else if (p == "rf-speed") {
3449 cumulative_rf_motion = 0;
3452 } else if (p == "click-sound") {
3454 setup_click_sounds (1);
3456 } else if (p == "click-emphasis-sound") {
3458 setup_click_sounds (-1);
3460 } else if (p == "clicking") {
3462 if (Config->get_clicking()) {
3463 if (_click_io && click_data) { // don't require emphasis data
3470 } else if (p == "click-gain") {
3473 _click_gain->set_gain (Config->get_click_gain(), this);
3476 } else if (p == "send-mtc") {
3478 if (Config->get_send_mtc ()) {
3479 /* mark us ready to send */
3480 next_quarter_frame_to_send = 0;
3483 } else if (p == "send-mmc") {
3485 MIDI::Manager::instance()->mmc()->enable_send (Config->get_send_mmc ());
3487 } else if (p == "midi-feedback") {
3489 session_midi_feedback = Config->get_midi_feedback();
3491 } else if (p == "jack-time-master") {
3493 engine().reset_timebase ();
3495 } else if (p == "native-file-header-format") {
3497 if (!first_file_header_format_reset) {
3498 reset_native_file_format ();
3501 first_file_header_format_reset = false;
3503 } else if (p == "native-file-data-format") {
3505 if (!first_file_data_format_reset) {
3506 reset_native_file_format ();
3509 first_file_data_format_reset = false;
3511 } else if (p == "external-sync") {
3512 if (!config.get_external_sync()) {
3513 drop_sync_source ();
3515 switch_to_sync_source (Config->get_sync_source());
3517 } else if (p == "denormal-model") {
3519 } else if (p == "history-depth") {
3520 set_history_depth (Config->get_history_depth());
3521 } else if (p == "remote-model") {
3522 /* XXX DO SOMETHING HERE TO TELL THE GUI THAT WE NEED
3525 } else if (p == "sync-all-route-ordering") {
3527 /* sync to editor order unless mixer is used for remote IDs
3530 switch (Config->get_remote_model()) {
3532 sync_order_keys (EditorSort);
3535 sync_order_keys (EditorSort);
3538 sync_order_keys (MixerSort);
3541 } else if (p == "initial-program-change") {
3543 if (MIDI::Manager::instance()->mmc()->output_port() && Config->get_initial_program_change() >= 0) {
3546 buf[0] = MIDI::program; // channel zero by default
3547 buf[1] = (Config->get_initial_program_change() & 0x7f);
3549 MIDI::Manager::instance()->mmc()->output_port()->midimsg (buf, sizeof (buf), 0);
3551 } else if (p == "solo-mute-override") {
3552 // catch_up_on_solo_mute_override ();
3553 } else if (p == "listen-position" || p == "pfl-position") {
3554 listen_position_changed ();
3555 } else if (p == "solo-control-is-listen-control") {
3556 solo_control_mode_changed ();
3557 } else if (p == "timecode-offset" || p == "timecode-offset-negative") {
3558 last_timecode_valid = false;
3559 } else if (p == "playback-buffer-seconds") {
3560 AudioSource::allocate_working_buffers (frame_rate());
3561 } else if (p == "automation-thinning-factor") {
3562 Evoral::ControlList::set_thinning_factor (Config->get_automation_thinning_factor());
3563 } else if (p == "ltc-source-port") {
3564 reconnect_ltc_input ();
3565 } else if (p == "ltc-sink-port") {
3566 reconnect_ltc_output ();
3567 } else if (p == "timecode-generator-offset") {
3568 ltc_tx_parse_offset();
3575 Session::set_history_depth (uint32_t d)
3577 _history.set_depth (d);
3581 Session::load_diskstreams_2X (XMLNode const & node, int)
3584 XMLNodeConstIterator citer;
3586 clist = node.children();
3588 for (citer = clist.begin(); citer != clist.end(); ++citer) {
3591 /* diskstreams added automatically by DiskstreamCreated handler */
3592 if ((*citer)->name() == "AudioDiskstream" || (*citer)->name() == "DiskStream") {
3593 boost::shared_ptr<AudioDiskstream> dsp (new AudioDiskstream (*this, **citer));
3594 _diskstreams_2X.push_back (dsp);
3596 error << _("Session: unknown diskstream type in XML") << endmsg;
3600 catch (failed_constructor& err) {
3601 error << _("Session: could not load diskstream via XML state") << endmsg;
3609 /** Connect things to the MMC object */
3611 Session::setup_midi_machine_control ()
3613 MIDI::MachineControl* mmc = MIDI::Manager::instance()->mmc ();
3615 mmc->Play.connect_same_thread (*this, boost::bind (&Session::mmc_deferred_play, this, _1));
3616 mmc->DeferredPlay.connect_same_thread (*this, boost::bind (&Session::mmc_deferred_play, this, _1));
3617 mmc->Stop.connect_same_thread (*this, boost::bind (&Session::mmc_stop, this, _1));
3618 mmc->FastForward.connect_same_thread (*this, boost::bind (&Session::mmc_fast_forward, this, _1));
3619 mmc->Rewind.connect_same_thread (*this, boost::bind (&Session::mmc_rewind, this, _1));
3620 mmc->Pause.connect_same_thread (*this, boost::bind (&Session::mmc_pause, this, _1));
3621 mmc->RecordPause.connect_same_thread (*this, boost::bind (&Session::mmc_record_pause, this, _1));
3622 mmc->RecordStrobe.connect_same_thread (*this, boost::bind (&Session::mmc_record_strobe, this, _1));
3623 mmc->RecordExit.connect_same_thread (*this, boost::bind (&Session::mmc_record_exit, this, _1));
3624 mmc->Locate.connect_same_thread (*this, boost::bind (&Session::mmc_locate, this, _1, _2));
3625 mmc->Step.connect_same_thread (*this, boost::bind (&Session::mmc_step, this, _1, _2));
3626 mmc->Shuttle.connect_same_thread (*this, boost::bind (&Session::mmc_shuttle, this, _1, _2, _3));
3627 mmc->TrackRecordStatusChange.connect_same_thread (*this, boost::bind (&Session::mmc_record_enable, this, _1, _2, _3));
3629 /* also handle MIDI SPP because its so common */
3631 mmc->SPPStart.connect_same_thread (*this, boost::bind (&Session::spp_start, this));
3632 mmc->SPPContinue.connect_same_thread (*this, boost::bind (&Session::spp_continue, this));
3633 mmc->SPPStop.connect_same_thread (*this, boost::bind (&Session::spp_stop, this));
3636 boost::shared_ptr<Controllable>
3637 Session::solo_cut_control() const
3639 /* the solo cut control is a bit of an anomaly, at least as of Febrary 2011. There are no other
3640 controls in Ardour that currently get presented to the user in the GUI that require
3641 access as a Controllable and are also NOT owned by some SessionObject (e.g. Route, or MonitorProcessor).
3643 its actually an RCConfiguration parameter, so we use a ProxyControllable to wrap
3644 it up as a Controllable. Changes to the Controllable will just map back to the RCConfiguration
3648 return _solo_cut_control;
3652 Session::rename (const std::string& new_name)
3654 string legal_name = legalize_for_path (new_name);
3660 string const old_sources_root = _session_dir->sources_root();
3662 #define RENAME ::rename
3667 * interchange subdirectory
3671 * Backup files are left unchanged and not renamed.
3674 /* pass one: not 100% safe check that the new directory names don't
3678 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
3683 /* this is a stupid hack because Glib::path_get_dirname() is
3684 * lexical-only, and so passing it /a/b/c/ gives a different
3685 * result than passing it /a/b/c ...
3688 if (oldstr[oldstr.length()-1] == G_DIR_SEPARATOR) {
3689 oldstr = oldstr.substr (0, oldstr.length() - 1);
3692 string base = Glib::path_get_dirname (oldstr);
3693 string p = Glib::path_get_basename (oldstr);
3695 newstr = Glib::build_filename (base, legal_name);
3697 if (Glib::file_test (newstr, Glib::FILE_TEST_EXISTS)) {
3704 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
3709 /* this is a stupid hack because Glib::path_get_dirname() is
3710 * lexical-only, and so passing it /a/b/c/ gives a different
3711 * result than passing it /a/b/c ...
3714 if (oldstr[oldstr.length()-1] == G_DIR_SEPARATOR) {
3715 oldstr = oldstr.substr (0, oldstr.length() - 1);
3718 string base = Glib::path_get_dirname (oldstr);
3719 string p = Glib::path_get_basename (oldstr);
3721 newstr = Glib::build_filename (base, legal_name);
3723 cerr << "Rename " << oldstr << " => " << newstr << endl;
3725 if (RENAME (oldstr.c_str(), newstr.c_str()) != 0) {
3730 (*_session_dir) = newstr;
3735 /* directory below interchange */
3737 v.push_back (newstr);
3738 v.push_back (interchange_dir_name);
3741 oldstr = Glib::build_filename (v);
3744 v.push_back (newstr);
3745 v.push_back (interchange_dir_name);
3746 v.push_back (legal_name);
3748 newstr = Glib::build_filename (v);
3750 cerr << "Rename " << oldstr << " => " << newstr << endl;
3752 if (RENAME (oldstr.c_str(), newstr.c_str()) != 0) {
3759 oldstr = Glib::build_filename (newpath, _current_snapshot_name) + statefile_suffix;
3760 newstr= Glib::build_filename (newpath, legal_name) + statefile_suffix;
3762 cerr << "Rename " << oldstr << " => " << newstr << endl;
3764 if (RENAME (oldstr.c_str(), newstr.c_str()) != 0) {
3771 oldstr = Glib::build_filename (newpath, _current_snapshot_name) + history_suffix;
3773 if (Glib::file_test (oldstr, Glib::FILE_TEST_EXISTS)) {
3774 newstr = Glib::build_filename (newpath, legal_name) + history_suffix;
3776 cerr << "Rename " << oldstr << " => " << newstr << endl;
3778 if (RENAME (oldstr.c_str(), newstr.c_str()) != 0) {
3783 /* update file source paths */
3785 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ++i) {
3786 boost::shared_ptr<FileSource> fs = boost::dynamic_pointer_cast<FileSource> (i->second);
3788 string p = fs->path ();
3789 boost::replace_all (p, old_sources_root, _session_dir->sources_root());
3794 /* remove old name from recent sessions */
3796 remove_recent_sessions (_path);
3799 _current_snapshot_name = new_name;
3804 /* save state again to get everything just right */
3806 save_state (_current_snapshot_name);
3809 /* add to recent sessions */
3811 store_recent_sessions (new_name, _path);