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 if (boost::dynamic_pointer_cast<AudioRegion>(r)) {
1082 child->add_child_nocopy ((boost::dynamic_pointer_cast<AudioRegion>(r))->get_basic_state ());
1084 child->add_child_nocopy (r->get_state ());
1089 RegionFactory::CompoundAssociations& cassocs (RegionFactory::compound_associations());
1091 if (!cassocs.empty()) {
1092 XMLNode* ca = node->add_child (X_("CompoundAssociations"));
1094 for (RegionFactory::CompoundAssociations::iterator i = cassocs.begin(); i != cassocs.end(); ++i) {
1096 XMLNode* can = new XMLNode (X_("CompoundAssociation"));
1097 i->first->id().print (buf, sizeof (buf));
1098 can->add_property (X_("copy"), buf);
1099 i->second->id().print (buf, sizeof (buf));
1100 can->add_property (X_("original"), buf);
1101 ca->add_child_nocopy (*can);
1107 node->add_child_nocopy (_locations->get_state());
1109 // for a template, just create a new Locations, populate it
1110 // with the default start and end, and get the state for that.
1111 Locations loc (*this);
1112 Location* range = new Location (*this, 0, 0, _("session"), Location::IsSessionRange);
1113 range->set (max_framepos, 0);
1115 node->add_child_nocopy (loc.get_state());
1118 child = node->add_child ("Bundles");
1120 boost::shared_ptr<BundleList> bundles = _bundles.reader ();
1121 for (BundleList::iterator i = bundles->begin(); i != bundles->end(); ++i) {
1122 boost::shared_ptr<UserBundle> b = boost::dynamic_pointer_cast<UserBundle> (*i);
1124 child->add_child_nocopy (b->get_state());
1129 child = node->add_child ("Routes");
1131 boost::shared_ptr<RouteList> r = routes.reader ();
1133 RoutePublicOrderSorter cmp;
1134 RouteList public_order (*r);
1135 public_order.sort (cmp);
1137 /* the sort should have put control outs first */
1140 assert (_monitor_out == public_order.front());
1143 for (RouteList::iterator i = public_order.begin(); i != public_order.end(); ++i) {
1144 if (!(*i)->is_hidden()) {
1146 child->add_child_nocopy ((*i)->get_state());
1148 child->add_child_nocopy ((*i)->get_template());
1154 playlists->add_state (node, full_state);
1156 child = node->add_child ("RouteGroups");
1157 for (list<RouteGroup *>::iterator i = _route_groups.begin(); i != _route_groups.end(); ++i) {
1158 child->add_child_nocopy ((*i)->get_state());
1162 XMLNode* gain_child = node->add_child ("Click");
1163 gain_child->add_child_nocopy (_click_io->state (full_state));
1164 gain_child->add_child_nocopy (_click_gain->state (full_state));
1168 XMLNode* ltc_input_child = node->add_child ("LTC-In");
1169 ltc_input_child->add_child_nocopy (_ltc_input->state (full_state));
1173 XMLNode* ltc_output_child = node->add_child ("LTC-Out");
1174 ltc_output_child->add_child_nocopy (_ltc_output->state (full_state));
1177 node->add_child_nocopy (_speakers->get_state());
1178 node->add_child_nocopy (_tempo_map->get_state());
1179 node->add_child_nocopy (get_control_protocol_state());
1182 node->add_child_copy (*_extra_xml);
1189 Session::get_control_protocol_state ()
1191 ControlProtocolManager& cpm (ControlProtocolManager::instance());
1192 return cpm.get_state();
1196 Session::set_state (const XMLNode& node, int version)
1200 const XMLProperty* prop;
1203 _state_of_the_state = StateOfTheState (_state_of_the_state|CannotSave);
1205 if (node.name() != X_("Session")) {
1206 fatal << _("programming error: Session: incorrect XML node sent to set_state()") << endmsg;
1210 if ((prop = node.property ("name")) != 0) {
1211 _name = prop->value ();
1214 if ((prop = node.property (X_("sample-rate"))) != 0) {
1216 _nominal_frame_rate = atoi (prop->value());
1218 if (_nominal_frame_rate != _current_frame_rate) {
1219 boost::optional<int> r = AskAboutSampleRateMismatch (_nominal_frame_rate, _current_frame_rate);
1220 if (r.get_value_or (0)) {
1226 setup_raid_path(_session_dir->root_path());
1228 if ((prop = node.property (X_("id-counter"))) != 0) {
1230 sscanf (prop->value().c_str(), "%" PRIu64, &x);
1231 ID::init_counter (x);
1233 /* old sessions used a timebased counter, so fake
1234 the startup ID counter based on a standard
1239 ID::init_counter (now);
1242 if ((prop = node.property (X_("event-counter"))) != 0) {
1243 Evoral::init_event_id_counter (atoi (prop->value()));
1246 IO::disable_connecting ();
1248 Stateful::save_extra_xml (node);
1250 if (((child = find_named_node (node, "Options")) != 0)) { /* old style */
1251 load_options (*child);
1252 } else if ((child = find_named_node (node, "Config")) != 0) { /* new style */
1253 load_options (*child);
1255 error << _("Session: XML state has no options section") << endmsg;
1258 if (version >= 3000) {
1259 if ((child = find_named_node (node, "Metadata")) == 0) {
1260 warning << _("Session: XML state has no metadata section") << endmsg;
1261 } else if ( ARDOUR::SessionMetadata::Metadata()->set_state (*child, version) ) {
1266 if ((child = find_named_node (node, X_("Speakers"))) != 0) {
1267 _speakers->set_state (*child, version);
1270 if ((child = find_named_node (node, "Sources")) == 0) {
1271 error << _("Session: XML state has no sources section") << endmsg;
1273 } else if (load_sources (*child)) {
1277 if ((child = find_named_node (node, "TempoMap")) == 0) {
1278 error << _("Session: XML state has no Tempo Map section") << endmsg;
1280 } else if (_tempo_map->set_state (*child, version)) {
1284 if ((child = find_named_node (node, "Locations")) == 0) {
1285 error << _("Session: XML state has no locations section") << endmsg;
1287 } else if (_locations->set_state (*child, version)) {
1293 if ((location = _locations->auto_loop_location()) != 0) {
1294 set_auto_loop_location (location);
1297 if ((location = _locations->auto_punch_location()) != 0) {
1298 set_auto_punch_location (location);
1301 if ((location = _locations->session_range_location()) != 0) {
1302 delete _session_range_location;
1303 _session_range_location = location;
1306 if (_session_range_location) {
1307 AudioFileSource::set_header_position_offset (_session_range_location->start());
1310 if ((child = find_named_node (node, "Regions")) == 0) {
1311 error << _("Session: XML state has no Regions section") << endmsg;
1313 } else if (load_regions (*child)) {
1317 if ((child = find_named_node (node, "Playlists")) == 0) {
1318 error << _("Session: XML state has no playlists section") << endmsg;
1320 } else if (playlists->load (*this, *child)) {
1324 if ((child = find_named_node (node, "UnusedPlaylists")) == 0) {
1326 } else if (playlists->load_unused (*this, *child)) {
1330 if ((child = find_named_node (node, "CompoundAssociations")) != 0) {
1331 if (load_compounds (*child)) {
1336 if (version >= 3000) {
1337 if ((child = find_named_node (node, "Bundles")) == 0) {
1338 warning << _("Session: XML state has no bundles section") << endmsg;
1341 /* We can't load Bundles yet as they need to be able
1342 to convert from port names to Port objects, which can't happen until
1344 _bundle_xml_node = new XMLNode (*child);
1348 if (version < 3000) {
1349 if ((child = find_named_node (node, X_("DiskStreams"))) == 0) {
1350 error << _("Session: XML state has no diskstreams section") << endmsg;
1352 } else if (load_diskstreams_2X (*child, version)) {
1357 if ((child = find_named_node (node, "Routes")) == 0) {
1358 error << _("Session: XML state has no routes section") << endmsg;
1360 } else if (load_routes (*child, version)) {
1364 /* our diskstreams list is no longer needed as they are now all owned by their Route */
1365 _diskstreams_2X.clear ();
1367 if (version >= 3000) {
1369 if ((child = find_named_node (node, "RouteGroups")) == 0) {
1370 error << _("Session: XML state has no route groups section") << endmsg;
1372 } else if (load_route_groups (*child, version)) {
1376 } else if (version < 3000) {
1378 if ((child = find_named_node (node, "EditGroups")) == 0) {
1379 error << _("Session: XML state has no edit groups section") << endmsg;
1381 } else if (load_route_groups (*child, version)) {
1385 if ((child = find_named_node (node, "MixGroups")) == 0) {
1386 error << _("Session: XML state has no mix groups section") << endmsg;
1388 } else if (load_route_groups (*child, version)) {
1393 if ((child = find_named_node (node, "Click")) == 0) {
1394 warning << _("Session: XML state has no click section") << endmsg;
1395 } else if (_click_io) {
1396 const XMLNodeList& children (child->children());
1397 XMLNodeList::const_iterator i = children.begin();
1398 _click_io->set_state (**i, version);
1400 if (i != children.end()) {
1401 _click_gain->set_state (**i, version);
1405 if ((child = find_named_node (node, ControlProtocolManager::state_node_name)) != 0) {
1406 ControlProtocolManager::instance().set_state (*child, version);
1409 update_have_rec_enabled_track ();
1411 /* here beginneth the second phase ... */
1413 StateReady (); /* EMIT SIGNAL */
1422 Session::load_routes (const XMLNode& node, int version)
1425 XMLNodeConstIterator niter;
1426 RouteList new_routes;
1428 nlist = node.children();
1432 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1434 boost::shared_ptr<Route> route;
1435 if (version < 3000) {
1436 route = XMLRouteFactory_2X (**niter, version);
1438 route = XMLRouteFactory (**niter, version);
1442 error << _("Session: cannot create Route from XML description.") << endmsg;
1446 BootMessage (string_compose (_("Loaded track/bus %1"), route->name()));
1448 new_routes.push_back (route);
1451 add_routes (new_routes, false, false, false);
1456 boost::shared_ptr<Route>
1457 Session::XMLRouteFactory (const XMLNode& node, int version)
1459 boost::shared_ptr<Route> ret;
1461 if (node.name() != "Route") {
1465 XMLNode* ds_child = find_named_node (node, X_("Diskstream"));
1467 DataType type = DataType::AUDIO;
1468 const XMLProperty* prop = node.property("default-type");
1471 type = DataType (prop->value());
1474 assert (type != DataType::NIL);
1478 boost::shared_ptr<Track> track;
1480 if (type == DataType::AUDIO) {
1481 track.reset (new AudioTrack (*this, X_("toBeResetFroXML")));
1483 track.reset (new MidiTrack (*this, X_("toBeResetFroXML")));
1486 if (track->init()) {
1490 if (track->set_state (node, version)) {
1494 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
1495 // boost_debug_shared_ptr_mark_interesting (track.get(), "Track");
1500 boost::shared_ptr<Route> r (new Route (*this, X_("toBeResetFroXML")));
1502 if (r->init () == 0 && r->set_state (node, version) == 0) {
1503 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
1504 // boost_debug_shared_ptr_mark_interesting (r.get(), "Route");
1513 boost::shared_ptr<Route>
1514 Session::XMLRouteFactory_2X (const XMLNode& node, int version)
1516 boost::shared_ptr<Route> ret;
1518 if (node.name() != "Route") {
1522 XMLProperty const * ds_prop = node.property (X_("diskstream-id"));
1524 ds_prop = node.property (X_("diskstream"));
1527 DataType type = DataType::AUDIO;
1528 const XMLProperty* prop = node.property("default-type");
1531 type = DataType (prop->value());
1534 assert (type != DataType::NIL);
1538 list<boost::shared_ptr<Diskstream> >::iterator i = _diskstreams_2X.begin ();
1539 while (i != _diskstreams_2X.end() && (*i)->id() != ds_prop->value()) {
1543 if (i == _diskstreams_2X.end()) {
1544 error << _("Could not find diskstream for route") << endmsg;
1545 return boost::shared_ptr<Route> ();
1548 boost::shared_ptr<Track> track;
1550 if (type == DataType::AUDIO) {
1551 track.reset (new AudioTrack (*this, X_("toBeResetFroXML")));
1553 track.reset (new MidiTrack (*this, X_("toBeResetFroXML")));
1556 if (track->init()) {
1560 if (track->set_state (node, version)) {
1564 track->set_diskstream (*i);
1566 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
1567 // boost_debug_shared_ptr_mark_interesting (track.get(), "Track");
1572 boost::shared_ptr<Route> r (new Route (*this, X_("toBeResetFroXML")));
1574 if (r->init () == 0 && r->set_state (node, version) == 0) {
1575 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
1576 // boost_debug_shared_ptr_mark_interesting (r.get(), "Route");
1586 Session::load_regions (const XMLNode& node)
1589 XMLNodeConstIterator niter;
1590 boost::shared_ptr<Region> region;
1592 nlist = node.children();
1596 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1597 if ((region = XMLRegionFactory (**niter, false)) == 0) {
1598 error << _("Session: cannot create Region from XML description.");
1599 const XMLProperty *name = (**niter).property("name");
1602 error << " " << string_compose (_("Can not load state for region '%1'"), name->value());
1613 Session::load_compounds (const XMLNode& node)
1615 XMLNodeList calist = node.children();
1616 XMLNodeConstIterator caiter;
1617 XMLProperty *caprop;
1619 for (caiter = calist.begin(); caiter != calist.end(); ++caiter) {
1620 XMLNode* ca = *caiter;
1624 if ((caprop = ca->property (X_("original"))) == 0) {
1627 orig_id = caprop->value();
1629 if ((caprop = ca->property (X_("copy"))) == 0) {
1632 copy_id = caprop->value();
1634 boost::shared_ptr<Region> orig = RegionFactory::region_by_id (orig_id);
1635 boost::shared_ptr<Region> copy = RegionFactory::region_by_id (copy_id);
1637 if (!orig || !copy) {
1638 warning << string_compose (_("Regions in compound description not found (ID's %1 and %2): ignored"),
1644 RegionFactory::add_compound_association (orig, copy);
1651 Session::load_nested_sources (const XMLNode& node)
1654 XMLNodeConstIterator niter;
1656 nlist = node.children();
1658 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1659 if ((*niter)->name() == "Source") {
1661 /* it may already exist, so don't recreate it unnecessarily
1664 XMLProperty* prop = (*niter)->property (X_("id"));
1666 error << _("Nested source has no ID info in session file! (ignored)") << endmsg;
1670 ID source_id (prop->value());
1672 if (!source_by_id (source_id)) {
1675 SourceFactory::create (*this, **niter, true);
1677 catch (failed_constructor& err) {
1678 error << string_compose (_("Cannot reconstruct nested source for region %1"), name()) << endmsg;
1685 boost::shared_ptr<Region>
1686 Session::XMLRegionFactory (const XMLNode& node, bool full)
1688 const XMLProperty* type = node.property("type");
1692 const XMLNodeList& nlist = node.children();
1694 for (XMLNodeConstIterator niter = nlist.begin(); niter != nlist.end(); ++niter) {
1695 XMLNode *child = (*niter);
1696 if (child->name() == "NestedSource") {
1697 load_nested_sources (*child);
1701 if (!type || type->value() == "audio") {
1702 return boost::shared_ptr<Region>(XMLAudioRegionFactory (node, full));
1703 } else if (type->value() == "midi") {
1704 return boost::shared_ptr<Region>(XMLMidiRegionFactory (node, full));
1707 } catch (failed_constructor& err) {
1708 return boost::shared_ptr<Region> ();
1711 return boost::shared_ptr<Region> ();
1714 boost::shared_ptr<AudioRegion>
1715 Session::XMLAudioRegionFactory (const XMLNode& node, bool /*full*/)
1717 const XMLProperty* prop;
1718 boost::shared_ptr<Source> source;
1719 boost::shared_ptr<AudioSource> as;
1721 SourceList master_sources;
1722 uint32_t nchans = 1;
1725 if (node.name() != X_("Region")) {
1726 return boost::shared_ptr<AudioRegion>();
1729 if ((prop = node.property (X_("channels"))) != 0) {
1730 nchans = atoi (prop->value().c_str());
1733 if ((prop = node.property ("name")) == 0) {
1734 cerr << "no name for this region\n";
1738 if ((prop = node.property (X_("source-0"))) == 0) {
1739 if ((prop = node.property ("source")) == 0) {
1740 error << _("Session: XMLNode describing a AudioRegion is incomplete (no source)") << endmsg;
1741 return boost::shared_ptr<AudioRegion>();
1745 PBD::ID s_id (prop->value());
1747 if ((source = source_by_id (s_id)) == 0) {
1748 error << string_compose(_("Session: XMLNode describing a AudioRegion references an unknown source id =%1"), s_id) << endmsg;
1749 return boost::shared_ptr<AudioRegion>();
1752 as = boost::dynamic_pointer_cast<AudioSource>(source);
1754 error << string_compose(_("Session: XMLNode describing a AudioRegion references a non-audio source id =%1"), s_id) << endmsg;
1755 return boost::shared_ptr<AudioRegion>();
1758 sources.push_back (as);
1760 /* pickup other channels */
1762 for (uint32_t n=1; n < nchans; ++n) {
1763 snprintf (buf, sizeof(buf), X_("source-%d"), n);
1764 if ((prop = node.property (buf)) != 0) {
1766 PBD::ID id2 (prop->value());
1768 if ((source = source_by_id (id2)) == 0) {
1769 error << string_compose(_("Session: XMLNode describing a AudioRegion references an unknown source id =%1"), id2) << endmsg;
1770 return boost::shared_ptr<AudioRegion>();
1773 as = boost::dynamic_pointer_cast<AudioSource>(source);
1775 error << string_compose(_("Session: XMLNode describing a AudioRegion references a non-audio source id =%1"), id2) << endmsg;
1776 return boost::shared_ptr<AudioRegion>();
1778 sources.push_back (as);
1782 for (uint32_t n = 0; n < nchans; ++n) {
1783 snprintf (buf, sizeof(buf), X_("master-source-%d"), n);
1784 if ((prop = node.property (buf)) != 0) {
1786 PBD::ID id2 (prop->value());
1788 if ((source = source_by_id (id2)) == 0) {
1789 error << string_compose(_("Session: XMLNode describing a AudioRegion references an unknown source id =%1"), id2) << endmsg;
1790 return boost::shared_ptr<AudioRegion>();
1793 as = boost::dynamic_pointer_cast<AudioSource>(source);
1795 error << string_compose(_("Session: XMLNode describing a AudioRegion references a non-audio source id =%1"), id2) << endmsg;
1796 return boost::shared_ptr<AudioRegion>();
1798 master_sources.push_back (as);
1803 boost::shared_ptr<AudioRegion> region (boost::dynamic_pointer_cast<AudioRegion> (RegionFactory::create (sources, node)));
1805 /* a final detail: this is the one and only place that we know how long missing files are */
1807 if (region->whole_file()) {
1808 for (SourceList::iterator sx = sources.begin(); sx != sources.end(); ++sx) {
1809 boost::shared_ptr<SilentFileSource> sfp = boost::dynamic_pointer_cast<SilentFileSource> (*sx);
1811 sfp->set_length (region->length());
1816 if (!master_sources.empty()) {
1817 if (master_sources.size() != nchans) {
1818 error << _("Session: XMLNode describing an AudioRegion is missing some master sources; ignored") << endmsg;
1820 region->set_master_sources (master_sources);
1828 catch (failed_constructor& err) {
1829 return boost::shared_ptr<AudioRegion>();
1833 boost::shared_ptr<MidiRegion>
1834 Session::XMLMidiRegionFactory (const XMLNode& node, bool /*full*/)
1836 const XMLProperty* prop;
1837 boost::shared_ptr<Source> source;
1838 boost::shared_ptr<MidiSource> ms;
1841 if (node.name() != X_("Region")) {
1842 return boost::shared_ptr<MidiRegion>();
1845 if ((prop = node.property ("name")) == 0) {
1846 cerr << "no name for this region\n";
1850 if ((prop = node.property (X_("source-0"))) == 0) {
1851 if ((prop = node.property ("source")) == 0) {
1852 error << _("Session: XMLNode describing a MidiRegion is incomplete (no source)") << endmsg;
1853 return boost::shared_ptr<MidiRegion>();
1857 PBD::ID s_id (prop->value());
1859 if ((source = source_by_id (s_id)) == 0) {
1860 error << string_compose(_("Session: XMLNode describing a MidiRegion references an unknown source id =%1"), s_id) << endmsg;
1861 return boost::shared_ptr<MidiRegion>();
1864 ms = boost::dynamic_pointer_cast<MidiSource>(source);
1866 error << string_compose(_("Session: XMLNode describing a MidiRegion references a non-midi source id =%1"), s_id) << endmsg;
1867 return boost::shared_ptr<MidiRegion>();
1870 sources.push_back (ms);
1873 boost::shared_ptr<MidiRegion> region (boost::dynamic_pointer_cast<MidiRegion> (RegionFactory::create (sources, node)));
1874 /* a final detail: this is the one and only place that we know how long missing files are */
1876 if (region->whole_file()) {
1877 for (SourceList::iterator sx = sources.begin(); sx != sources.end(); ++sx) {
1878 boost::shared_ptr<SilentFileSource> sfp = boost::dynamic_pointer_cast<SilentFileSource> (*sx);
1880 sfp->set_length (region->length());
1888 catch (failed_constructor& err) {
1889 return boost::shared_ptr<MidiRegion>();
1894 Session::get_sources_as_xml ()
1897 XMLNode* node = new XMLNode (X_("Sources"));
1898 Glib::Threads::Mutex::Lock lm (source_lock);
1900 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ++i) {
1901 node->add_child_nocopy (i->second->get_state());
1908 Session::path_from_region_name (DataType type, string name, string identifier)
1910 char buf[PATH_MAX+1];
1912 SessionDirectory sdir(get_best_session_directory_for_new_source());
1913 std::string source_dir = ((type == DataType::AUDIO)
1914 ? sdir.sound_path() : sdir.midi_path());
1916 string ext = native_header_format_extension (config.get_native_file_header_format(), type);
1918 for (n = 0; n < 999999; ++n) {
1919 if (identifier.length()) {
1920 snprintf (buf, sizeof(buf), "%s%s%" PRIu32 "%s", name.c_str(),
1921 identifier.c_str(), n, ext.c_str());
1923 snprintf (buf, sizeof(buf), "%s-%" PRIu32 "%s", name.c_str(),
1927 std::string source_path = Glib::build_filename (source_dir, buf);
1929 if (!Glib::file_test (source_path, Glib::FILE_TEST_EXISTS)) {
1934 error << string_compose (_("cannot create new file from region name \"%1\" with ident = \"%2\": too many existing files with similar names"),
1943 Session::load_sources (const XMLNode& node)
1946 XMLNodeConstIterator niter;
1947 boost::shared_ptr<Source> source;
1949 nlist = node.children();
1953 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1956 if ((source = XMLSourceFactory (**niter)) == 0) {
1957 error << _("Session: cannot create Source from XML description.") << endmsg;
1960 } catch (MissingSource& err) {
1964 if (!no_questions_about_missing_files) {
1965 user_choice = MissingFile (this, err.path, err.type).get_value_or (-1);
1970 switch (user_choice) {
1972 /* user added a new search location, so try again */
1977 /* user asked to quit the entire session load
1982 no_questions_about_missing_files = true;
1986 no_questions_about_missing_files = true;
1991 warning << _("A sound file is missing. It will be replaced by silence.") << endmsg;
1992 source = SourceFactory::createSilent (*this, **niter, max_framecnt, _current_frame_rate);
2001 boost::shared_ptr<Source>
2002 Session::XMLSourceFactory (const XMLNode& node)
2004 if (node.name() != "Source") {
2005 return boost::shared_ptr<Source>();
2009 /* note: do peak building in another thread when loading session state */
2010 return SourceFactory::create (*this, node, true);
2013 catch (failed_constructor& err) {
2014 error << string_compose (_("Found a sound file that cannot be used by %1. Talk to the progammers."), PROGRAM_NAME) << endmsg;
2015 return boost::shared_ptr<Source>();
2020 Session::save_template (string template_name)
2024 if (_state_of_the_state & CannotSave) {
2028 std::string user_template_dir(user_template_directory());
2030 if (g_mkdir_with_parents (user_template_dir.c_str(), 0755) != 0) {
2031 error << string_compose(_("Could not create templates directory \"%1\" (%2)"),
2032 user_template_dir, g_strerror (errno)) << endmsg;
2036 tree.set_root (&get_template());
2038 std::string template_dir_path(user_template_dir);
2040 /* directory to put the template in */
2041 template_dir_path = Glib::build_filename (template_dir_path, template_name);
2043 if (Glib::file_test (template_dir_path, Glib::FILE_TEST_EXISTS)) {
2044 warning << string_compose(_("Template \"%1\" already exists - new version not created"),
2045 template_dir_path) << endmsg;
2049 if (g_mkdir_with_parents (template_dir_path.c_str(), 0755) != 0) {
2050 error << string_compose(_("Could not create directory for Session template\"%1\" (%2)"),
2051 template_dir_path, g_strerror (errno)) << endmsg;
2056 std::string template_file_path(template_dir_path);
2057 template_file_path = Glib::build_filename (template_file_path, template_name + template_suffix);
2059 if (!tree.write (template_file_path)) {
2060 error << _("template not saved") << endmsg;
2064 /* copy plugin state directory */
2066 std::string template_plugin_state_path(template_dir_path);
2067 template_plugin_state_path = Glib::build_filename (template_plugin_state_path, X_("plugins"));
2069 if (g_mkdir_with_parents (template_plugin_state_path.c_str(), 0755) != 0) {
2070 error << string_compose(_("Could not create directory for Session template plugin state\"%1\" (%2)"),
2071 template_plugin_state_path, g_strerror (errno)) << endmsg;
2075 copy_files (plugins_dir(), template_plugin_state_path);
2081 Session::refresh_disk_space ()
2083 #if HAVE_SYS_VFS_H && HAVE_SYS_STATVFS_H
2085 Glib::Threads::Mutex::Lock lm (space_lock);
2087 /* get freespace on every FS that is part of the session path */
2089 _total_free_4k_blocks = 0;
2090 _total_free_4k_blocks_uncertain = false;
2092 for (vector<space_and_path>::iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
2094 struct statfs statfsbuf;
2095 statfs (i->path.c_str(), &statfsbuf);
2097 double const scale = statfsbuf.f_bsize / 4096.0;
2099 /* See if this filesystem is read-only */
2100 struct statvfs statvfsbuf;
2101 statvfs (i->path.c_str(), &statvfsbuf);
2103 /* f_bavail can be 0 if it is undefined for whatever
2104 filesystem we are looking at; Samba shares mounted
2105 via GVFS are an example of this.
2107 if (statfsbuf.f_bavail == 0) {
2108 /* block count unknown */
2110 i->blocks_unknown = true;
2111 } else if (statvfsbuf.f_flag & ST_RDONLY) {
2112 /* read-only filesystem */
2114 i->blocks_unknown = false;
2116 /* read/write filesystem with known space */
2117 i->blocks = (uint32_t) floor (statfsbuf.f_bavail * scale);
2118 i->blocks_unknown = false;
2121 _total_free_4k_blocks += i->blocks;
2122 if (i->blocks_unknown) {
2123 _total_free_4k_blocks_uncertain = true;
2130 Session::get_best_session_directory_for_new_source ()
2132 vector<space_and_path>::iterator i;
2133 string result = _session_dir->root_path();
2135 /* handle common case without system calls */
2137 if (session_dirs.size() == 1) {
2141 /* OK, here's the algorithm we're following here:
2143 We want to select which directory to use for
2144 the next file source to be created. Ideally,
2145 we'd like to use a round-robin process so as to
2146 get maximum performance benefits from splitting
2147 the files across multiple disks.
2149 However, in situations without much diskspace, an
2150 RR approach may end up filling up a filesystem
2151 with new files while others still have space.
2152 Its therefore important to pay some attention to
2153 the freespace in the filesystem holding each
2154 directory as well. However, if we did that by
2155 itself, we'd keep creating new files in the file
2156 system with the most space until it was as full
2157 as all others, thus negating any performance
2158 benefits of this RAID-1 like approach.
2160 So, we use a user-configurable space threshold. If
2161 there are at least 2 filesystems with more than this
2162 much space available, we use RR selection between them.
2163 If not, then we pick the filesystem with the most space.
2165 This gets a good balance between the two
2169 refresh_disk_space ();
2171 int free_enough = 0;
2173 for (i = session_dirs.begin(); i != session_dirs.end(); ++i) {
2174 if ((*i).blocks * 4096 >= Config->get_disk_choice_space_threshold()) {
2179 if (free_enough >= 2) {
2180 /* use RR selection process, ensuring that the one
2184 i = last_rr_session_dir;
2187 if (++i == session_dirs.end()) {
2188 i = session_dirs.begin();
2191 if ((*i).blocks * 4096 >= Config->get_disk_choice_space_threshold()) {
2192 SessionDirectory sdir(i->path);
2193 if (sdir.create ()) {
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 SessionDirectory sdir(i->path);
2216 if (sdir.create ()) {
2218 last_rr_session_dir = i;
2228 Session::automation_dir () const
2230 return Glib::build_filename (_path, "automation");
2234 Session::analysis_dir () const
2236 return Glib::build_filename (_path, "analysis");
2240 Session::plugins_dir () const
2242 return Glib::build_filename (_path, "plugins");
2246 Session::externals_dir () const
2248 return Glib::build_filename (_path, "externals");
2252 Session::load_bundles (XMLNode const & node)
2254 XMLNodeList nlist = node.children();
2255 XMLNodeConstIterator niter;
2259 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2260 if ((*niter)->name() == "InputBundle") {
2261 add_bundle (boost::shared_ptr<UserBundle> (new UserBundle (**niter, true)));
2262 } else if ((*niter)->name() == "OutputBundle") {
2263 add_bundle (boost::shared_ptr<UserBundle> (new UserBundle (**niter, false)));
2265 error << string_compose(_("Unknown node \"%1\" found in Bundles list from session file"), (*niter)->name()) << endmsg;
2274 Session::load_route_groups (const XMLNode& node, int version)
2276 XMLNodeList nlist = node.children();
2277 XMLNodeConstIterator niter;
2281 if (version >= 3000) {
2283 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2284 if ((*niter)->name() == "RouteGroup") {
2285 RouteGroup* rg = new RouteGroup (*this, "");
2286 add_route_group (rg);
2287 rg->set_state (**niter, version);
2291 } else if (version < 3000) {
2293 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2294 if ((*niter)->name() == "EditGroup" || (*niter)->name() == "MixGroup") {
2295 RouteGroup* rg = new RouteGroup (*this, "");
2296 add_route_group (rg);
2297 rg->set_state (**niter, version);
2306 Session::auto_save()
2308 save_state (_current_snapshot_name);
2312 state_file_filter (const string &str, void */*arg*/)
2314 return (str.length() > strlen(statefile_suffix) &&
2315 str.find (statefile_suffix) == (str.length() - strlen (statefile_suffix)));
2319 bool operator()(const string* a, const string* b) {
2325 remove_end(string* state)
2327 string statename(*state);
2329 string::size_type start,end;
2330 if ((start = statename.find_last_of (G_DIR_SEPARATOR)) != string::npos) {
2331 statename = statename.substr (start+1);
2334 if ((end = statename.rfind(".ardour")) == string::npos) {
2335 end = statename.length();
2338 return new string(statename.substr (0, end));
2342 Session::possible_states (string path)
2344 PathScanner scanner;
2345 vector<string*>* states = scanner (path, state_file_filter, 0, false, false);
2347 transform(states->begin(), states->end(), states->begin(), remove_end);
2350 sort (states->begin(), states->end(), cmp);
2356 Session::possible_states () const
2358 return possible_states(_path);
2362 Session::add_route_group (RouteGroup* g)
2364 _route_groups.push_back (g);
2365 route_group_added (g); /* EMIT SIGNAL */
2367 g->RouteAdded.connect_same_thread (*this, boost::bind (&Session::route_added_to_route_group, this, _1, _2));
2368 g->RouteRemoved.connect_same_thread (*this, boost::bind (&Session::route_removed_from_route_group, this, _1, _2));
2369 g->PropertyChanged.connect_same_thread (*this, boost::bind (&Session::route_group_property_changed, this, g));
2375 Session::remove_route_group (RouteGroup& rg)
2377 list<RouteGroup*>::iterator i;
2379 if ((i = find (_route_groups.begin(), _route_groups.end(), &rg)) != _route_groups.end()) {
2380 _route_groups.erase (i);
2383 route_group_removed (); /* EMIT SIGNAL */
2387 /** Set a new order for our route groups, without adding or removing any.
2388 * @param groups Route group list in the new order.
2391 Session::reorder_route_groups (list<RouteGroup*> groups)
2393 _route_groups = groups;
2395 route_groups_reordered (); /* EMIT SIGNAL */
2401 Session::route_group_by_name (string name)
2403 list<RouteGroup *>::iterator i;
2405 for (i = _route_groups.begin(); i != _route_groups.end(); ++i) {
2406 if ((*i)->name() == name) {
2414 Session::all_route_group() const
2416 return *_all_route_group;
2420 Session::add_commands (vector<Command*> const & cmds)
2422 for (vector<Command*>::const_iterator i = cmds.begin(); i != cmds.end(); ++i) {
2428 Session::begin_reversible_command (const string& name)
2430 begin_reversible_command (g_quark_from_string (name.c_str ()));
2433 /** Begin a reversible command using a GQuark to identify it.
2434 * begin_reversible_command() and commit_reversible_command() calls may be nested,
2435 * but there must be as many begin...()s as there are commit...()s.
2438 Session::begin_reversible_command (GQuark q)
2440 /* If nested begin/commit pairs are used, we create just one UndoTransaction
2441 to hold all the commands that are committed. This keeps the order of
2442 commands correct in the history.
2445 if (_current_trans == 0) {
2446 /* start a new transaction */
2447 assert (_current_trans_quarks.empty ());
2448 _current_trans = new UndoTransaction();
2449 _current_trans->set_name (g_quark_to_string (q));
2452 _current_trans_quarks.push_front (q);
2456 Session::commit_reversible_command (Command *cmd)
2458 assert (_current_trans);
2459 assert (!_current_trans_quarks.empty ());
2464 _current_trans->add_command (cmd);
2467 _current_trans_quarks.pop_front ();
2469 if (!_current_trans_quarks.empty ()) {
2470 /* the transaction we're committing is not the top-level one */
2474 if (_current_trans->empty()) {
2475 /* no commands were added to the transaction, so just get rid of it */
2476 delete _current_trans;
2481 gettimeofday (&now, 0);
2482 _current_trans->set_timestamp (now);
2484 _history.add (_current_trans);
2489 accept_all_audio_files (const string& path, void */*arg*/)
2491 if (!Glib::file_test (path, Glib::FILE_TEST_IS_REGULAR)) {
2495 if (!AudioFileSource::safe_audio_file_extension (path)) {
2503 accept_all_midi_files (const string& path, void */*arg*/)
2505 if (!Glib::file_test (path, Glib::FILE_TEST_IS_REGULAR)) {
2509 return ((path.length() > 4 && path.find (".mid") != (path.length() - 4)) ||
2510 (path.length() > 4 && path.find (".smf") != (path.length() - 4)) ||
2511 (path.length() > 5 && path.find (".midi") != (path.length() - 5)));
2515 accept_all_state_files (const string& path, void */*arg*/)
2517 if (!Glib::file_test (path, Glib::FILE_TEST_IS_REGULAR)) {
2521 return (path.length() > 7 && path.find (".ardour") == (path.length() - 7));
2525 Session::find_all_sources (string path, set<string>& result)
2530 if (!tree.read (path)) {
2534 if ((node = find_named_node (*tree.root(), "Sources")) == 0) {
2539 XMLNodeConstIterator niter;
2541 nlist = node->children();
2545 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2549 if ((prop = (*niter)->property (X_("type"))) == 0) {
2553 DataType type (prop->value());
2555 if ((prop = (*niter)->property (X_("name"))) == 0) {
2559 if (Glib::path_is_absolute (prop->value())) {
2560 /* external file, ignore */
2568 if (FileSource::find (*this, type, prop->value(), true, is_new, chan, found_path)) {
2569 result.insert (found_path);
2577 Session::find_all_sources_across_snapshots (set<string>& result, bool exclude_this_snapshot)
2579 PathScanner scanner;
2580 vector<string*>* state_files;
2582 string this_snapshot_path;
2588 if (ripped[ripped.length()-1] == G_DIR_SEPARATOR) {
2589 ripped = ripped.substr (0, ripped.length() - 1);
2592 state_files = scanner (ripped, accept_all_state_files, (void *) 0, true, true);
2594 if (state_files == 0) {
2599 this_snapshot_path = _path;
2600 this_snapshot_path += legalize_for_path (_current_snapshot_name);
2601 this_snapshot_path += statefile_suffix;
2603 for (vector<string*>::iterator i = state_files->begin(); i != state_files->end(); ++i) {
2605 if (exclude_this_snapshot && **i == this_snapshot_path) {
2609 if (find_all_sources (**i, result) < 0) {
2617 struct RegionCounter {
2618 typedef std::map<PBD::ID,boost::shared_ptr<AudioSource> > AudioSourceList;
2619 AudioSourceList::iterator iter;
2620 boost::shared_ptr<Region> region;
2623 RegionCounter() : count (0) {}
2627 Session::ask_about_playlist_deletion (boost::shared_ptr<Playlist> p)
2629 boost::optional<int> r = AskAboutPlaylistDeletion (p);
2630 return r.get_value_or (1);
2634 Session::cleanup_regions ()
2636 const RegionFactory::RegionMap& regions (RegionFactory::regions());
2638 for (RegionFactory::RegionMap::const_iterator i = regions.begin(); i != regions.end(); ++i) {
2640 uint32_t used = playlists->region_use_count (i->second);
2642 if (used == 0 && !i->second->automatic ()) {
2643 RegionFactory::map_remove (i->second);
2647 /* dump the history list */
2654 Session::cleanup_sources (CleanupReport& rep)
2656 // FIXME: needs adaptation to midi
2658 vector<boost::shared_ptr<Source> > dead_sources;
2659 PathScanner scanner;
2662 vector<space_and_path>::iterator i;
2663 vector<space_and_path>::iterator nexti;
2664 vector<string*>* candidates;
2665 vector<string*>* candidates2;
2666 vector<string> unused;
2667 set<string> all_sources;
2672 _state_of_the_state = (StateOfTheState) (_state_of_the_state | InCleanup);
2674 /* consider deleting all unused playlists */
2676 if (playlists->maybe_delete_unused (boost::bind (Session::ask_about_playlist_deletion, _1))) {
2681 /* sync the "all regions" property of each playlist with its current state
2684 playlists->sync_all_regions_with_regions ();
2686 /* find all un-used sources */
2691 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ) {
2693 SourceMap::iterator tmp;
2698 /* do not bother with files that are zero size, otherwise we remove the current "nascent"
2702 if (!i->second->used() && (i->second->length(i->second->timeline_position() > 0))) {
2703 dead_sources.push_back (i->second);
2704 i->second->drop_references ();
2710 /* build a list of all the possible audio directories for the session */
2712 for (i = session_dirs.begin(); i != session_dirs.end(); ) {
2717 SessionDirectory sdir ((*i).path);
2718 audio_path += sdir.sound_path();
2720 if (nexti != session_dirs.end()) {
2728 /* build a list of all the possible midi directories for the session */
2730 for (i = session_dirs.begin(); i != session_dirs.end(); ) {
2735 SessionDirectory sdir ((*i).path);
2736 midi_path += sdir.midi_path();
2738 if (nexti != session_dirs.end()) {
2745 candidates = scanner (audio_path, accept_all_audio_files, (void *) 0, true, true);
2746 candidates2 = scanner (midi_path, accept_all_midi_files, (void *) 0, true, true);
2752 for (vector<string*>::iterator i = candidates2->begin(); i != candidates2->end(); ++i) {
2753 candidates->push_back (*i);
2758 candidates = candidates2; // might still be null
2761 /* find all sources, but don't use this snapshot because the
2762 state file on disk still references sources we may have already
2766 find_all_sources_across_snapshots (all_sources, true);
2768 /* add our current source list
2771 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ) {
2772 boost::shared_ptr<FileSource> fs;
2773 SourceMap::iterator tmp = i;
2776 if ((fs = boost::dynamic_pointer_cast<FileSource> (i->second)) != 0) {
2777 if (playlists->source_use_count (fs) != 0) {
2778 all_sources.insert (fs->path());
2781 /* we might not remove this source from disk, because it may be used
2782 by other snapshots, but its not being used in this version
2783 so lets get rid of it now, along with any representative regions
2787 RegionFactory::remove_regions_using_source (i->second);
2795 char tmppath1[PATH_MAX+1];
2796 char tmppath2[PATH_MAX+1];
2799 for (vector<string*>::iterator x = candidates->begin(); x != candidates->end(); ++x) {
2804 for (set<string>::iterator i = all_sources.begin(); i != all_sources.end(); ++i) {
2806 if (realpath(spath.c_str(), tmppath1) == 0) {
2807 error << string_compose (_("Cannot expand path %1 (%2)"),
2808 spath, strerror (errno)) << endmsg;
2812 if (realpath((*i).c_str(), tmppath2) == 0) {
2813 error << string_compose (_("Cannot expand path %1 (%2)"),
2814 (*i), strerror (errno)) << endmsg;
2818 if (strcmp(tmppath1, tmppath2) == 0) {
2825 unused.push_back (spath);
2834 /* now try to move all unused files into the "dead" directory(ies) */
2836 for (vector<string>::iterator x = unused.begin(); x != unused.end(); ++x) {
2837 struct stat statbuf;
2841 /* don't move the file across filesystems, just
2842 stick it in the `dead_dir_name' directory
2843 on whichever filesystem it was already on.
2846 if ((*x).find ("/sounds/") != string::npos) {
2848 /* old school, go up 1 level */
2850 newpath = Glib::path_get_dirname (*x); // "sounds"
2851 newpath = Glib::path_get_dirname (newpath); // "session-name"
2855 /* new school, go up 4 levels */
2857 newpath = Glib::path_get_dirname (*x); // "audiofiles" or "midifiles"
2858 newpath = Glib::path_get_dirname (newpath); // "session-name"
2859 newpath = Glib::path_get_dirname (newpath); // "interchange"
2860 newpath = Glib::path_get_dirname (newpath); // "session-dir"
2863 newpath = Glib::build_filename (newpath, dead_dir_name);
2865 if (g_mkdir_with_parents (newpath.c_str(), 0755) < 0) {
2866 error << string_compose(_("Session: cannot create dead file folder \"%1\" (%2)"), newpath, strerror (errno)) << endmsg;
2870 newpath = Glib::build_filename (newpath, Glib::path_get_basename ((*x)));
2872 if (Glib::file_test (newpath, Glib::FILE_TEST_EXISTS)) {
2874 /* the new path already exists, try versioning */
2876 char buf[PATH_MAX+1];
2880 snprintf (buf, sizeof (buf), "%s.%d", newpath.c_str(), version);
2883 while (Glib::file_test (newpath_v.c_str(), Glib::FILE_TEST_EXISTS) && version < 999) {
2884 snprintf (buf, sizeof (buf), "%s.%d", newpath.c_str(), ++version);
2888 if (version == 999) {
2889 error << string_compose (_("there are already 1000 files with names like %1; versioning discontinued"),
2893 newpath = newpath_v;
2898 /* it doesn't exist, or we can't read it or something */
2902 stat ((*x).c_str(), &statbuf);
2904 if (::rename ((*x).c_str(), newpath.c_str()) != 0) {
2905 error << string_compose (_("cannot rename unused file source from %1 to %2 (%3)"),
2906 (*x), newpath, strerror (errno))
2911 /* see if there an easy to find peakfile for this file, and remove it.
2914 string base = basename_nosuffix (*x);
2915 base += "%A"; /* this is what we add for the channel suffix of all native files,
2916 or for the first channel of embedded files. it will miss
2917 some peakfiles for other channels
2919 string peakpath = peak_path (base);
2921 if (Glib::file_test (peakpath.c_str(), Glib::FILE_TEST_EXISTS)) {
2922 if (::unlink (peakpath.c_str()) != 0) {
2923 error << string_compose (_("cannot remove peakfile %1 for %2 (%3)"),
2924 peakpath, _path, strerror (errno))
2926 /* try to back out */
2927 ::rename (newpath.c_str(), _path.c_str());
2932 rep.paths.push_back (*x);
2933 rep.space += statbuf.st_size;
2936 /* dump the history list */
2940 /* save state so we don't end up a session file
2941 referring to non-existent sources.
2948 _state_of_the_state = (StateOfTheState) (_state_of_the_state & ~InCleanup);
2954 Session::cleanup_trash_sources (CleanupReport& rep)
2956 // FIXME: needs adaptation for MIDI
2958 vector<space_and_path>::iterator i;
2964 for (i = session_dirs.begin(); i != session_dirs.end(); ++i) {
2966 dead_dir = Glib::build_filename ((*i).path, dead_dir_name);
2968 clear_directory (dead_dir, &rep.space, &rep.paths);
2975 Session::set_dirty ()
2977 bool was_dirty = dirty();
2979 _state_of_the_state = StateOfTheState (_state_of_the_state | Dirty);
2983 DirtyChanged(); /* EMIT SIGNAL */
2989 Session::set_clean ()
2991 bool was_dirty = dirty();
2993 _state_of_the_state = Clean;
2997 DirtyChanged(); /* EMIT SIGNAL */
3002 Session::set_deletion_in_progress ()
3004 _state_of_the_state = StateOfTheState (_state_of_the_state | Deletion);
3008 Session::clear_deletion_in_progress ()
3010 _state_of_the_state = StateOfTheState (_state_of_the_state & (~Deletion));
3014 Session::add_controllable (boost::shared_ptr<Controllable> c)
3016 /* this adds a controllable to the list managed by the Session.
3017 this is a subset of those managed by the Controllable class
3018 itself, and represents the only ones whose state will be saved
3019 as part of the session.
3022 Glib::Threads::Mutex::Lock lm (controllables_lock);
3023 controllables.insert (c);
3026 struct null_deleter { void operator()(void const *) const {} };
3029 Session::remove_controllable (Controllable* c)
3031 if (_state_of_the_state & Deletion) {
3035 Glib::Threads::Mutex::Lock lm (controllables_lock);
3037 Controllables::iterator x = controllables.find (boost::shared_ptr<Controllable>(c, null_deleter()));
3039 if (x != controllables.end()) {
3040 controllables.erase (x);
3044 boost::shared_ptr<Controllable>
3045 Session::controllable_by_id (const PBD::ID& id)
3047 Glib::Threads::Mutex::Lock lm (controllables_lock);
3049 for (Controllables::iterator i = controllables.begin(); i != controllables.end(); ++i) {
3050 if ((*i)->id() == id) {
3055 return boost::shared_ptr<Controllable>();
3058 boost::shared_ptr<Controllable>
3059 Session::controllable_by_descriptor (const ControllableDescriptor& desc)
3061 boost::shared_ptr<Controllable> c;
3062 boost::shared_ptr<Route> r;
3064 switch (desc.top_level_type()) {
3065 case ControllableDescriptor::NamedRoute:
3067 std::string str = desc.top_level_name();
3068 if (str == "master") {
3070 } else if (str == "control" || str == "listen") {
3073 r = route_by_name (desc.top_level_name());
3078 case ControllableDescriptor::RemoteControlID:
3079 r = route_by_remote_id (desc.rid());
3087 switch (desc.subtype()) {
3088 case ControllableDescriptor::Gain:
3089 c = r->gain_control ();
3092 case ControllableDescriptor::Solo:
3093 c = r->solo_control();
3096 case ControllableDescriptor::Mute:
3097 c = r->mute_control();
3100 case ControllableDescriptor::Recenable:
3102 boost::shared_ptr<Track> t = boost::dynamic_pointer_cast<Track>(r);
3105 c = t->rec_enable_control ();
3110 case ControllableDescriptor::PanDirection:
3112 c = r->pannable()->pan_azimuth_control;
3116 case ControllableDescriptor::PanWidth:
3118 c = r->pannable()->pan_width_control;
3122 case ControllableDescriptor::PanElevation:
3124 c = r->pannable()->pan_elevation_control;
3128 case ControllableDescriptor::Balance:
3129 /* XXX simple pan control */
3132 case ControllableDescriptor::PluginParameter:
3134 uint32_t plugin = desc.target (0);
3135 uint32_t parameter_index = desc.target (1);
3137 /* revert to zero based counting */
3143 if (parameter_index > 0) {
3147 boost::shared_ptr<Processor> p = r->nth_plugin (plugin);
3150 c = boost::dynamic_pointer_cast<ARDOUR::AutomationControl>(
3151 p->control(Evoral::Parameter(PluginAutomation, 0, parameter_index)));
3156 case ControllableDescriptor::SendGain:
3158 uint32_t send = desc.target (0);
3160 /* revert to zero-based counting */
3166 boost::shared_ptr<Processor> p = r->nth_send (send);
3169 boost::shared_ptr<Send> s = boost::dynamic_pointer_cast<Send>(p);
3170 boost::shared_ptr<Amp> a = s->amp();
3173 c = s->amp()->gain_control();
3180 /* relax and return a null pointer */
3188 Session::add_instant_xml (XMLNode& node, bool write_to_config)
3191 Stateful::add_instant_xml (node, _path);
3194 if (write_to_config) {
3195 Config->add_instant_xml (node);
3200 Session::instant_xml (const string& node_name)
3202 return Stateful::instant_xml (node_name, _path);
3206 Session::save_history (string snapshot_name)
3214 if (snapshot_name.empty()) {
3215 snapshot_name = _current_snapshot_name;
3218 const string history_filename = legalize_for_path (snapshot_name) + history_suffix;
3219 const string backup_filename = history_filename + backup_suffix;
3220 const std::string xml_path(Glib::build_filename (_session_dir->root_path(), history_filename));
3221 const std::string backup_path(Glib::build_filename (_session_dir->root_path(), backup_filename));
3223 if (Glib::file_test (xml_path, Glib::FILE_TEST_EXISTS)) {
3224 if (::g_rename (xml_path.c_str(), backup_path.c_str()) != 0) {
3225 error << _("could not backup old history file, current history not saved") << endmsg;
3230 if (!Config->get_save_history() || Config->get_saved_history_depth() < 0) {
3234 tree.set_root (&_history.get_state (Config->get_saved_history_depth()));
3236 if (!tree.write (xml_path))
3238 error << string_compose (_("history could not be saved to %1"), xml_path) << endmsg;
3240 if (g_remove (xml_path.c_str()) != 0) {
3241 error << string_compose(_("Could not remove history file at path \"%1\" (%2)"),
3242 xml_path, g_strerror (errno)) << endmsg;
3244 if (::g_rename (backup_path.c_str(), xml_path.c_str()) != 0) {
3245 error << string_compose (_("could not restore history file from backup %1 (%2)"),
3246 backup_path, g_strerror (errno)) << endmsg;
3256 Session::restore_history (string snapshot_name)
3260 if (snapshot_name.empty()) {
3261 snapshot_name = _current_snapshot_name;
3264 const std::string xml_filename = legalize_for_path (snapshot_name) + history_suffix;
3265 const std::string xml_path(Glib::build_filename (_session_dir->root_path(), xml_filename));
3267 info << "Loading history from " << xml_path << endmsg;
3269 if (!Glib::file_test (xml_path, Glib::FILE_TEST_EXISTS)) {
3270 info << string_compose (_("%1: no history file \"%2\" for this session."),
3271 _name, xml_path) << endmsg;
3275 if (!tree.read (xml_path)) {
3276 error << string_compose (_("Could not understand session history file \"%1\""),
3277 xml_path) << endmsg;
3284 for (XMLNodeConstIterator it = tree.root()->children().begin(); it != tree.root()->children().end(); it++) {
3287 UndoTransaction* ut = new UndoTransaction ();
3290 ut->set_name(t->property("name")->value());
3291 stringstream ss(t->property("tv-sec")->value());
3293 ss.str(t->property("tv-usec")->value());
3295 ut->set_timestamp(tv);
3297 for (XMLNodeConstIterator child_it = t->children().begin();
3298 child_it != t->children().end(); child_it++)
3300 XMLNode *n = *child_it;
3303 if (n->name() == "MementoCommand" ||
3304 n->name() == "MementoUndoCommand" ||
3305 n->name() == "MementoRedoCommand") {
3307 if ((c = memento_command_factory(n))) {
3311 } else if (n->name() == "NoteDiffCommand") {
3312 PBD::ID id (n->property("midi-source")->value());
3313 boost::shared_ptr<MidiSource> midi_source =
3314 boost::dynamic_pointer_cast<MidiSource, Source>(source_by_id(id));
3316 ut->add_command (new MidiModel::NoteDiffCommand(midi_source->model(), *n));
3318 error << _("Failed to downcast MidiSource for NoteDiffCommand") << endmsg;
3321 } else if (n->name() == "SysExDiffCommand") {
3323 PBD::ID id (n->property("midi-source")->value());
3324 boost::shared_ptr<MidiSource> midi_source =
3325 boost::dynamic_pointer_cast<MidiSource, Source>(source_by_id(id));
3327 ut->add_command (new MidiModel::SysExDiffCommand (midi_source->model(), *n));
3329 error << _("Failed to downcast MidiSource for SysExDiffCommand") << endmsg;
3332 } else if (n->name() == "PatchChangeDiffCommand") {
3334 PBD::ID id (n->property("midi-source")->value());
3335 boost::shared_ptr<MidiSource> midi_source =
3336 boost::dynamic_pointer_cast<MidiSource, Source>(source_by_id(id));
3338 ut->add_command (new MidiModel::PatchChangeDiffCommand (midi_source->model(), *n));
3340 error << _("Failed to downcast MidiSource for PatchChangeDiffCommand") << endmsg;
3343 } else if (n->name() == "StatefulDiffCommand") {
3344 if ((c = stateful_diff_command_factory (n))) {
3345 ut->add_command (c);
3348 error << string_compose(_("Couldn't figure out how to make a Command out of a %1 XMLNode."), n->name()) << endmsg;
3359 Session::config_changed (std::string p, bool ours)
3365 if (p == "seamless-loop") {
3367 } else if (p == "rf-speed") {
3369 } else if (p == "auto-loop") {
3371 } else if (p == "auto-input") {
3373 if (Config->get_monitoring_model() == HardwareMonitoring && transport_rolling()) {
3374 /* auto-input only makes a difference if we're rolling */
3375 set_track_monitor_input_status (!config.get_auto_input());
3378 } else if (p == "punch-in") {
3382 if ((location = _locations->auto_punch_location()) != 0) {
3384 if (config.get_punch_in ()) {
3385 replace_event (SessionEvent::PunchIn, location->start());
3387 remove_event (location->start(), SessionEvent::PunchIn);
3391 } else if (p == "punch-out") {
3395 if ((location = _locations->auto_punch_location()) != 0) {
3397 if (config.get_punch_out()) {
3398 replace_event (SessionEvent::PunchOut, location->end());
3400 clear_events (SessionEvent::PunchOut);
3404 } else if (p == "edit-mode") {
3406 Glib::Threads::Mutex::Lock lm (playlists->lock);
3408 for (SessionPlaylists::List::iterator i = playlists->playlists.begin(); i != playlists->playlists.end(); ++i) {
3409 (*i)->set_edit_mode (Config->get_edit_mode ());
3412 } else if (p == "use-video-sync") {
3414 waiting_for_sync_offset = config.get_use_video_sync();
3416 } else if (p == "mmc-control") {
3418 //poke_midi_thread ();
3420 } else if (p == "mmc-device-id" || p == "mmc-receive-id" || p == "mmc-receive-device-id") {
3422 MIDI::Manager::instance()->mmc()->set_receive_device_id (Config->get_mmc_receive_device_id());
3424 } else if (p == "mmc-send-id" || p == "mmc-send-device-id") {
3426 MIDI::Manager::instance()->mmc()->set_send_device_id (Config->get_mmc_send_device_id());
3428 } else if (p == "midi-control") {
3430 //poke_midi_thread ();
3432 } else if (p == "raid-path") {
3434 setup_raid_path (config.get_raid_path());
3436 } else if (p == "timecode-format") {
3440 } else if (p == "video-pullup") {
3444 } else if (p == "seamless-loop") {
3446 if (play_loop && transport_rolling()) {
3447 // to reset diskstreams etc
3448 request_play_loop (true);
3451 } else if (p == "rf-speed") {
3453 cumulative_rf_motion = 0;
3456 } else if (p == "click-sound") {
3458 setup_click_sounds (1);
3460 } else if (p == "click-emphasis-sound") {
3462 setup_click_sounds (-1);
3464 } else if (p == "clicking") {
3466 if (Config->get_clicking()) {
3467 if (_click_io && click_data) { // don't require emphasis data
3474 } else if (p == "click-gain") {
3477 _click_gain->set_gain (Config->get_click_gain(), this);
3480 } else if (p == "send-mtc") {
3482 if (Config->get_send_mtc ()) {
3483 /* mark us ready to send */
3484 next_quarter_frame_to_send = 0;
3487 } else if (p == "send-mmc") {
3489 MIDI::Manager::instance()->mmc()->enable_send (Config->get_send_mmc ());
3491 } else if (p == "midi-feedback") {
3493 session_midi_feedback = Config->get_midi_feedback();
3495 } else if (p == "jack-time-master") {
3497 engine().reset_timebase ();
3499 } else if (p == "native-file-header-format") {
3501 if (!first_file_header_format_reset) {
3502 reset_native_file_format ();
3505 first_file_header_format_reset = false;
3507 } else if (p == "native-file-data-format") {
3509 if (!first_file_data_format_reset) {
3510 reset_native_file_format ();
3513 first_file_data_format_reset = false;
3515 } else if (p == "external-sync") {
3516 if (!config.get_external_sync()) {
3517 drop_sync_source ();
3519 switch_to_sync_source (Config->get_sync_source());
3521 } else if (p == "denormal-model") {
3523 } else if (p == "history-depth") {
3524 set_history_depth (Config->get_history_depth());
3525 } else if (p == "remote-model") {
3526 /* XXX DO SOMETHING HERE TO TELL THE GUI THAT WE NEED
3529 } else if (p == "sync-all-route-ordering") {
3531 /* sync to editor order unless mixer is used for remote IDs
3534 switch (Config->get_remote_model()) {
3536 sync_order_keys (EditorSort);
3539 sync_order_keys (EditorSort);
3542 sync_order_keys (MixerSort);
3545 } else if (p == "initial-program-change") {
3547 if (MIDI::Manager::instance()->mmc()->output_port() && Config->get_initial_program_change() >= 0) {
3550 buf[0] = MIDI::program; // channel zero by default
3551 buf[1] = (Config->get_initial_program_change() & 0x7f);
3553 MIDI::Manager::instance()->mmc()->output_port()->midimsg (buf, sizeof (buf), 0);
3555 } else if (p == "solo-mute-override") {
3556 // catch_up_on_solo_mute_override ();
3557 } else if (p == "listen-position" || p == "pfl-position") {
3558 listen_position_changed ();
3559 } else if (p == "solo-control-is-listen-control") {
3560 solo_control_mode_changed ();
3561 } else if (p == "timecode-offset" || p == "timecode-offset-negative") {
3562 last_timecode_valid = false;
3563 } else if (p == "playback-buffer-seconds") {
3564 AudioSource::allocate_working_buffers (frame_rate());
3565 } else if (p == "automation-thinning-factor") {
3566 Evoral::ControlList::set_thinning_factor (Config->get_automation_thinning_factor());
3567 } else if (p == "ltc-source-port") {
3568 reconnect_ltc_input ();
3569 } else if (p == "ltc-sink-port") {
3570 reconnect_ltc_output ();
3571 } else if (p == "timecode-generator-offset") {
3572 ltc_tx_parse_offset();
3579 Session::set_history_depth (uint32_t d)
3581 _history.set_depth (d);
3585 Session::load_diskstreams_2X (XMLNode const & node, int)
3588 XMLNodeConstIterator citer;
3590 clist = node.children();
3592 for (citer = clist.begin(); citer != clist.end(); ++citer) {
3595 /* diskstreams added automatically by DiskstreamCreated handler */
3596 if ((*citer)->name() == "AudioDiskstream" || (*citer)->name() == "DiskStream") {
3597 boost::shared_ptr<AudioDiskstream> dsp (new AudioDiskstream (*this, **citer));
3598 _diskstreams_2X.push_back (dsp);
3600 error << _("Session: unknown diskstream type in XML") << endmsg;
3604 catch (failed_constructor& err) {
3605 error << _("Session: could not load diskstream via XML state") << endmsg;
3613 /** Connect things to the MMC object */
3615 Session::setup_midi_machine_control ()
3617 MIDI::MachineControl* mmc = MIDI::Manager::instance()->mmc ();
3619 mmc->Play.connect_same_thread (*this, boost::bind (&Session::mmc_deferred_play, this, _1));
3620 mmc->DeferredPlay.connect_same_thread (*this, boost::bind (&Session::mmc_deferred_play, this, _1));
3621 mmc->Stop.connect_same_thread (*this, boost::bind (&Session::mmc_stop, this, _1));
3622 mmc->FastForward.connect_same_thread (*this, boost::bind (&Session::mmc_fast_forward, this, _1));
3623 mmc->Rewind.connect_same_thread (*this, boost::bind (&Session::mmc_rewind, this, _1));
3624 mmc->Pause.connect_same_thread (*this, boost::bind (&Session::mmc_pause, this, _1));
3625 mmc->RecordPause.connect_same_thread (*this, boost::bind (&Session::mmc_record_pause, this, _1));
3626 mmc->RecordStrobe.connect_same_thread (*this, boost::bind (&Session::mmc_record_strobe, this, _1));
3627 mmc->RecordExit.connect_same_thread (*this, boost::bind (&Session::mmc_record_exit, this, _1));
3628 mmc->Locate.connect_same_thread (*this, boost::bind (&Session::mmc_locate, this, _1, _2));
3629 mmc->Step.connect_same_thread (*this, boost::bind (&Session::mmc_step, this, _1, _2));
3630 mmc->Shuttle.connect_same_thread (*this, boost::bind (&Session::mmc_shuttle, this, _1, _2, _3));
3631 mmc->TrackRecordStatusChange.connect_same_thread (*this, boost::bind (&Session::mmc_record_enable, this, _1, _2, _3));
3633 /* also handle MIDI SPP because its so common */
3635 mmc->SPPStart.connect_same_thread (*this, boost::bind (&Session::spp_start, this));
3636 mmc->SPPContinue.connect_same_thread (*this, boost::bind (&Session::spp_continue, this));
3637 mmc->SPPStop.connect_same_thread (*this, boost::bind (&Session::spp_stop, this));
3640 boost::shared_ptr<Controllable>
3641 Session::solo_cut_control() const
3643 /* the solo cut control is a bit of an anomaly, at least as of Febrary 2011. There are no other
3644 controls in Ardour that currently get presented to the user in the GUI that require
3645 access as a Controllable and are also NOT owned by some SessionObject (e.g. Route, or MonitorProcessor).
3647 its actually an RCConfiguration parameter, so we use a ProxyControllable to wrap
3648 it up as a Controllable. Changes to the Controllable will just map back to the RCConfiguration
3652 return _solo_cut_control;
3656 Session::rename (const std::string& new_name)
3658 string legal_name = legalize_for_path (new_name);
3664 string const old_sources_root = _session_dir->sources_root();
3666 #define RENAME ::rename
3671 * interchange subdirectory
3675 * Backup files are left unchanged and not renamed.
3678 /* pass one: not 100% safe check that the new directory names don't
3682 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
3687 /* this is a stupid hack because Glib::path_get_dirname() is
3688 * lexical-only, and so passing it /a/b/c/ gives a different
3689 * result than passing it /a/b/c ...
3692 if (oldstr[oldstr.length()-1] == G_DIR_SEPARATOR) {
3693 oldstr = oldstr.substr (0, oldstr.length() - 1);
3696 string base = Glib::path_get_dirname (oldstr);
3697 string p = Glib::path_get_basename (oldstr);
3699 newstr = Glib::build_filename (base, legal_name);
3701 if (Glib::file_test (newstr, Glib::FILE_TEST_EXISTS)) {
3708 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
3713 /* this is a stupid hack because Glib::path_get_dirname() is
3714 * lexical-only, and so passing it /a/b/c/ gives a different
3715 * result than passing it /a/b/c ...
3718 if (oldstr[oldstr.length()-1] == G_DIR_SEPARATOR) {
3719 oldstr = oldstr.substr (0, oldstr.length() - 1);
3722 string base = Glib::path_get_dirname (oldstr);
3723 string p = Glib::path_get_basename (oldstr);
3725 newstr = Glib::build_filename (base, legal_name);
3727 cerr << "Rename " << oldstr << " => " << newstr << endl;
3729 if (RENAME (oldstr.c_str(), newstr.c_str()) != 0) {
3734 (*_session_dir) = newstr;
3739 /* directory below interchange */
3741 v.push_back (newstr);
3742 v.push_back (interchange_dir_name);
3745 oldstr = Glib::build_filename (v);
3748 v.push_back (newstr);
3749 v.push_back (interchange_dir_name);
3750 v.push_back (legal_name);
3752 newstr = Glib::build_filename (v);
3754 cerr << "Rename " << oldstr << " => " << newstr << endl;
3756 if (RENAME (oldstr.c_str(), newstr.c_str()) != 0) {
3763 oldstr = Glib::build_filename (newpath, _current_snapshot_name) + statefile_suffix;
3764 newstr= Glib::build_filename (newpath, legal_name) + statefile_suffix;
3766 cerr << "Rename " << oldstr << " => " << newstr << endl;
3768 if (RENAME (oldstr.c_str(), newstr.c_str()) != 0) {
3775 oldstr = Glib::build_filename (newpath, _current_snapshot_name) + history_suffix;
3777 if (Glib::file_test (oldstr, Glib::FILE_TEST_EXISTS)) {
3778 newstr = Glib::build_filename (newpath, legal_name) + history_suffix;
3780 cerr << "Rename " << oldstr << " => " << newstr << endl;
3782 if (RENAME (oldstr.c_str(), newstr.c_str()) != 0) {
3787 /* update file source paths */
3789 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ++i) {
3790 boost::shared_ptr<FileSource> fs = boost::dynamic_pointer_cast<FileSource> (i->second);
3792 string p = fs->path ();
3793 boost::replace_all (p, old_sources_root, _session_dir->sources_root());
3798 /* remove old name from recent sessions */
3800 remove_recent_sessions (_path);
3803 _current_snapshot_name = new_name;
3808 /* save state again to get everything just right */
3810 save_state (_current_snapshot_name);
3813 /* add to recent sessions */
3815 store_recent_sessions (new_name, _path);