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 destructive_index = 0;
210 first_file_data_format_reset = true;
211 first_file_header_format_reset = true;
212 post_export_sync = false;
215 no_questions_about_missing_files = false;
216 _speakers.reset (new Speakers);
218 ignore_route_processor_changes = false;
219 _pre_export_mmc_enabled = false;
221 AudioDiskstream::allocate_working_buffers();
223 /* default short fade = 15ms */
225 SndFileSource::setup_standard_crossfades (*this, frame_rate());
227 last_mmc_step.tv_sec = 0;
228 last_mmc_step.tv_usec = 0;
231 /* click sounds are unset by default, which causes us to internal
232 waveforms for clicks.
236 click_emphasis_length = 0;
239 process_function = &Session::process_with_events;
241 if (config.get_use_video_sync()) {
242 waiting_for_sync_offset = true;
244 waiting_for_sync_offset = false;
247 last_timecode_when = 0;
248 last_timecode_valid = false;
252 last_rr_session_dir = session_dirs.begin();
253 refresh_disk_space ();
255 /* default: assume simple stereo speaker configuration */
257 _speakers->setup_default_speakers (2);
261 average_slave_delta = 1800; // !!! why 1800 ????
262 have_first_delta_accumulator = false;
263 delta_accumulator_cnt = 0;
264 _slave_state = Stopped;
266 _solo_cut_control.reset (new ProxyControllable (_("solo cut control (dB)"), PBD::Controllable::GainLike,
267 boost::bind (&RCConfiguration::set_solo_mute_gain, Config, _1),
268 boost::bind (&RCConfiguration::get_solo_mute_gain, Config)));
269 add_controllable (_solo_cut_control);
271 _engine.GraphReordered.connect_same_thread (*this, boost::bind (&Session::graph_reordered, this));
273 /* These are all static "per-class" signals */
275 SourceFactory::SourceCreated.connect_same_thread (*this, boost::bind (&Session::add_source, this, _1));
276 PlaylistFactory::PlaylistCreated.connect_same_thread (*this, boost::bind (&Session::add_playlist, this, _1, _2));
277 AutomationList::AutomationListCreated.connect_same_thread (*this, boost::bind (&Session::add_automation_list, this, _1));
278 Controllable::Destroyed.connect_same_thread (*this, boost::bind (&Session::remove_controllable, this, _1));
279 IO::PortCountChanged.connect_same_thread (*this, boost::bind (&Session::ensure_buffers, this, _1));
281 /* stop IO objects from doing stuff until we're ready for them */
283 Delivery::disable_panners ();
284 IO::disable_connecting ();
288 Session::second_stage_init ()
290 AudioFileSource::set_peak_dir (_session_dir->peak_path());
293 if (load_state (_current_snapshot_name)) {
298 if (_butler->start_thread()) {
302 if (start_midi_thread ()) {
306 setup_midi_machine_control ();
308 // set_state() will call setup_raid_path(), but if it's a new session we need
309 // to call setup_raid_path() here.
312 if (set_state (*state_tree->root(), Stateful::loading_state_version)) {
316 setup_raid_path(_path);
319 /* we can't save till after ::when_engine_running() is called,
320 because otherwise we save state with no connections made.
321 therefore, we reset _state_of_the_state because ::set_state()
322 will have cleared it.
324 we also have to include Loading so that any events that get
325 generated between here and the end of ::when_engine_running()
326 will be processed directly rather than queued.
329 _state_of_the_state = StateOfTheState (_state_of_the_state|CannotSave|Loading);
331 _locations->changed.connect_same_thread (*this, boost::bind (&Session::locations_changed, this));
332 _locations->added.connect_same_thread (*this, boost::bind (&Session::locations_added, this, _1));
333 setup_click_sounds (0);
334 setup_midi_control ();
336 /* Pay attention ... */
338 _engine.Halted.connect_same_thread (*this, boost::bind (&Session::engine_halted, this));
339 _engine.Xrun.connect_same_thread (*this, boost::bind (&Session::xrun_recovery, this));
341 midi_clock = new MidiClockTicker ();
342 midi_clock->set_session (this);
345 when_engine_running ();
348 /* handle this one in a different way than all others, so that its clear what happened */
350 catch (AudioEngine::PortRegistrationFailure& err) {
351 error << err.what() << endmsg;
359 BootMessage (_("Reset Remote Controls"));
361 send_full_time_code (0);
362 _engine.transport_locate (0);
364 MIDI::Manager::instance()->mmc()->send (MIDI::MachineControlCommand (MIDI::MachineControl::cmdMmcReset));
365 MIDI::Manager::instance()->mmc()->send (MIDI::MachineControlCommand (Timecode::Time ()));
367 MIDI::Name::MidiPatchManager::instance().set_session (this);
372 /* initial program change will be delivered later; see ::config_changed() */
374 _state_of_the_state = Clean;
376 Port::set_connecting_blocked (false);
378 DirtyChanged (); /* EMIT SIGNAL */
380 if (state_was_pending) {
381 save_state (_current_snapshot_name);
382 remove_pending_capture_state ();
383 state_was_pending = false;
386 BootMessage (_("Session loading complete"));
392 Session::raid_path () const
394 SearchPath raid_search_path;
396 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
397 raid_search_path += (*i).path;
400 return raid_search_path.to_string ();
404 Session::setup_raid_path (string path)
413 session_dirs.clear ();
415 SearchPath search_path(path);
416 SearchPath sound_search_path;
417 SearchPath midi_search_path;
419 for (SearchPath::const_iterator i = search_path.begin(); i != search_path.end(); ++i) {
421 sp.blocks = 0; // not needed
422 session_dirs.push_back (sp);
424 SessionDirectory sdir(sp.path);
426 sound_search_path += sdir.sound_path ();
427 midi_search_path += sdir.midi_path ();
430 // reset the round-robin soundfile path thingie
431 last_rr_session_dir = session_dirs.begin();
435 Session::path_is_within_session (const std::string& path)
437 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
438 if (PBD::path_is_within (i->path, path)) {
446 Session::ensure_subdirs ()
450 dir = session_directory().peak_path();
452 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
453 error << string_compose(_("Session: cannot create session peakfile folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
457 dir = session_directory().sound_path();
459 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
460 error << string_compose(_("Session: cannot create session sounds dir \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
464 dir = session_directory().midi_path();
466 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
467 error << string_compose(_("Session: cannot create session midi dir \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
471 dir = session_directory().dead_path();
473 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
474 error << string_compose(_("Session: cannot create session dead sounds folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
478 dir = session_directory().export_path();
480 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
481 error << string_compose(_("Session: cannot create session export folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
485 dir = analysis_dir ();
487 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
488 error << string_compose(_("Session: cannot create session analysis folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
492 dir = plugins_dir ();
494 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
495 error << string_compose(_("Session: cannot create session plugins folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
499 dir = externals_dir ();
501 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
502 error << string_compose(_("Session: cannot create session externals folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
509 /** @param session_template directory containing session template, or empty.
510 * Caller must not hold process lock.
513 Session::create (const string& session_template, BusProfile* bus_profile)
515 if (g_mkdir_with_parents (_path.c_str(), 0755) < 0) {
516 error << string_compose(_("Session: cannot create session folder \"%1\" (%2)"), _path, strerror (errno)) << endmsg;
520 if (ensure_subdirs ()) {
524 _writable = exists_and_writable (_path);
526 if (!session_template.empty()) {
527 std::string in_path = session_template_dir_to_file (session_template);
529 ifstream in(in_path.c_str());
532 string out_path = _path;
534 out_path += statefile_suffix;
536 ofstream out(out_path.c_str());
542 /* Copy plugin state files from template to new session */
543 std::string template_plugins = Glib::build_filename (session_template, X_("plugins"));
544 copy_files (template_plugins, plugins_dir ());
549 error << string_compose (_("Could not open %1 for writing session template"), out_path)
555 error << string_compose (_("Could not open session template %1 for reading"), in_path)
562 /* set initial start + end point */
564 _state_of_the_state = Clean;
566 /* set up Master Out and Control Out if necessary */
571 ChanCount count(DataType::AUDIO, bus_profile->master_out_channels);
573 if (bus_profile->master_out_channels) {
574 boost::shared_ptr<Route> r (new Route (*this, _("master"), Route::MasterOut, DataType::AUDIO));
578 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
579 // boost_debug_shared_ptr_mark_interesting (r.get(), "Route");
582 Glib::Threads::Mutex::Lock lm (AudioEngine::instance()->process_lock ());
583 r->input()->ensure_io (count, false, this);
584 r->output()->ensure_io (count, false, this);
590 /* prohibit auto-connect to master, because there isn't one */
591 bus_profile->output_ac = AutoConnectOption (bus_profile->output_ac & ~AutoConnectMaster);
595 add_routes (rl, false, false, false);
598 /* this allows the user to override settings with an environment variable.
601 if (no_auto_connect()) {
602 bus_profile->input_ac = AutoConnectOption (0);
603 bus_profile->output_ac = AutoConnectOption (0);
606 Config->set_input_auto_connect (bus_profile->input_ac);
607 Config->set_output_auto_connect (bus_profile->output_ac);
610 if (Config->get_use_monitor_bus() && bus_profile) {
611 add_monitor_section ();
620 Session::maybe_write_autosave()
622 if (dirty() && record_status() != Recording) {
623 save_state("", true);
628 Session::remove_pending_capture_state ()
630 std::string pending_state_file_path(_session_dir->root_path());
632 pending_state_file_path = Glib::build_filename (pending_state_file_path, legalize_for_path (_current_snapshot_name) + pending_suffix);
634 if (!Glib::file_test (pending_state_file_path, Glib::FILE_TEST_EXISTS)) return;
636 if (g_remove (pending_state_file_path.c_str()) != 0) {
637 error << string_compose(_("Could not remove pending capture state at path \"%1\" (%2)"),
638 pending_state_file_path, g_strerror (errno)) << endmsg;
642 /** Rename a state file.
643 * @param old_name Old snapshot name.
644 * @param new_name New snapshot name.
647 Session::rename_state (string old_name, string new_name)
649 if (old_name == _current_snapshot_name || old_name == _name) {
650 /* refuse to rename the current snapshot or the "main" one */
654 const string old_xml_filename = legalize_for_path (old_name) + statefile_suffix;
655 const string new_xml_filename = legalize_for_path (new_name) + statefile_suffix;
657 const std::string old_xml_path(Glib::build_filename (_session_dir->root_path(), old_xml_filename));
658 const std::string new_xml_path(Glib::build_filename (_session_dir->root_path(), new_xml_filename));
660 if (::g_rename (old_xml_path.c_str(), new_xml_path.c_str()) != 0) {
661 error << string_compose(_("could not rename snapshot %1 to %2 (%3)"),
662 old_name, new_name, g_strerror(errno)) << endmsg;
666 /** Remove a state file.
667 * @param snapshot_name Snapshot name.
670 Session::remove_state (string snapshot_name)
672 if (!_writable || snapshot_name == _current_snapshot_name || snapshot_name == _name) {
673 // refuse to remove the current snapshot or the "main" one
677 std::string xml_path(_session_dir->root_path());
679 xml_path = Glib::build_filename (xml_path, legalize_for_path (snapshot_name) + statefile_suffix);
681 if (!create_backup_file (xml_path)) {
682 // don't remove it if a backup can't be made
683 // create_backup_file will log the error.
688 if (g_remove (xml_path.c_str()) != 0) {
689 error << string_compose(_("Could not remove state file at path \"%1\" (%2)"),
690 xml_path, g_strerror (errno)) << endmsg;
694 #ifdef HAVE_JACK_SESSION
696 Session::jack_session_event (jack_session_event_t * event)
700 struct tm local_time;
703 localtime_r (&n, &local_time);
704 strftime (timebuf, sizeof(timebuf), "JS_%FT%T", &local_time);
706 if (event->type == JackSessionSaveTemplate)
708 if (save_template( timebuf )) {
709 event->flags = JackSessionSaveError;
711 string cmd ("ardour3 -P -U ");
712 cmd += event->client_uuid;
716 event->command_line = strdup (cmd.c_str());
721 if (save_state (timebuf)) {
722 event->flags = JackSessionSaveError;
724 std::string xml_path (_session_dir->root_path());
725 std::string legalized_filename = legalize_for_path (timebuf) + statefile_suffix;
726 xml_path = Glib::build_filename (xml_path, legalized_filename);
728 string cmd ("ardour3 -P -U ");
729 cmd += event->client_uuid;
734 event->command_line = strdup (cmd.c_str());
738 jack_session_reply (_engine.jack(), event);
740 if (event->type == JackSessionSaveAndQuit) {
741 Quit (); /* EMIT SIGNAL */
744 jack_session_event_free( event );
748 /** @param snapshot_name Name to save under, without .ardour / .pending prefix */
750 Session::save_state (string snapshot_name, bool pending, bool switch_to_snapshot)
753 std::string xml_path(_session_dir->root_path());
755 if (!_writable || (_state_of_the_state & CannotSave)) {
759 if (!_engine.connected ()) {
760 error << string_compose (_("the %1 audio engine is not connected and state saving would lose all I/O connections. Session not saved"),
766 /* tell sources we're saving first, in case they write out to a new file
767 * which should be saved with the state rather than the old one */
768 for (SourceMap::const_iterator i = sources.begin(); i != sources.end(); ++i) {
770 i->second->session_saved();
771 } catch (Evoral::SMF::FileError& e) {
772 error << string_compose ("Could not write to MIDI file %1; MIDI data not saved.", e.file_name ()) << endmsg;
776 tree.set_root (&get_state());
778 if (snapshot_name.empty()) {
779 snapshot_name = _current_snapshot_name;
780 } else if (switch_to_snapshot) {
781 _current_snapshot_name = snapshot_name;
786 /* proper save: use statefile_suffix (.ardour in English) */
788 xml_path = Glib::build_filename (xml_path, legalize_for_path (snapshot_name) + statefile_suffix);
790 /* make a backup copy of the old file */
792 if (Glib::file_test (xml_path, Glib::FILE_TEST_EXISTS) && !create_backup_file (xml_path)) {
793 // create_backup_file will log the error
799 /* pending save: use pending_suffix (.pending in English) */
800 xml_path = Glib::build_filename (xml_path, legalize_for_path (snapshot_name) + pending_suffix);
803 std::string tmp_path(_session_dir->root_path());
804 tmp_path = Glib::build_filename (tmp_path, legalize_for_path (snapshot_name) + temp_suffix);
806 // cerr << "actually writing state to " << xml_path << endl;
808 if (!tree.write (tmp_path)) {
809 error << string_compose (_("state could not be saved to %1"), tmp_path) << endmsg;
810 if (g_remove (tmp_path.c_str()) != 0) {
811 error << string_compose(_("Could not remove temporary state file at path \"%1\" (%2)"),
812 tmp_path, g_strerror (errno)) << endmsg;
818 if (::rename (tmp_path.c_str(), xml_path.c_str()) != 0) {
819 error << string_compose (_("could not rename temporary session file %1 to %2"),
820 tmp_path, xml_path) << endmsg;
821 if (g_remove (tmp_path.c_str()) != 0) {
822 error << string_compose(_("Could not remove temporary state file at path \"%1\" (%2)"),
823 tmp_path, g_strerror (errno)) << endmsg;
831 save_history (snapshot_name);
833 bool was_dirty = dirty();
835 _state_of_the_state = StateOfTheState (_state_of_the_state & ~Dirty);
838 DirtyChanged (); /* EMIT SIGNAL */
841 StateSaved (snapshot_name); /* EMIT SIGNAL */
848 Session::restore_state (string snapshot_name)
850 if (load_state (snapshot_name) == 0) {
851 set_state (*state_tree->root(), Stateful::loading_state_version);
858 Session::load_state (string snapshot_name)
863 state_was_pending = false;
865 /* check for leftover pending state from a crashed capture attempt */
867 std::string xmlpath(_session_dir->root_path());
868 xmlpath = Glib::build_filename (xmlpath, legalize_for_path (snapshot_name) + pending_suffix);
870 if (Glib::file_test (xmlpath, Glib::FILE_TEST_EXISTS)) {
872 /* there is pending state from a crashed capture attempt */
874 boost::optional<int> r = AskAboutPendingState();
875 if (r.get_value_or (1)) {
876 state_was_pending = true;
880 if (!state_was_pending) {
881 xmlpath = Glib::build_filename (_session_dir->root_path(), snapshot_name);
884 if (!Glib::file_test (xmlpath, Glib::FILE_TEST_EXISTS)) {
885 xmlpath = Glib::build_filename (_session_dir->root_path(), legalize_for_path (snapshot_name) + statefile_suffix);
886 if (!Glib::file_test (xmlpath, Glib::FILE_TEST_EXISTS)) {
887 error << string_compose(_("%1: session state information file \"%2\" doesn't exist!"), _name, xmlpath) << endmsg;
892 state_tree = new XMLTree;
896 _writable = exists_and_writable (xmlpath);
898 if (!state_tree->read (xmlpath)) {
899 error << string_compose(_("Could not understand ardour file %1"), xmlpath) << endmsg;
905 XMLNode& root (*state_tree->root());
907 if (root.name() != X_("Session")) {
908 error << string_compose (_("Session file %1 is not a session"), xmlpath) << endmsg;
914 const XMLProperty* prop;
916 if ((prop = root.property ("version")) == 0) {
917 /* no version implies very old version of Ardour */
918 Stateful::loading_state_version = 1000;
920 if (prop->value().find ('.') != string::npos) {
921 /* old school version format */
922 if (prop->value()[0] == '2') {
923 Stateful::loading_state_version = 2000;
925 Stateful::loading_state_version = 3000;
928 Stateful::loading_state_version = atoi (prop->value());
932 if (Stateful::loading_state_version < CURRENT_SESSION_FILE_VERSION && _writable) {
934 std::string backup_path(_session_dir->root_path());
935 std::string backup_filename = string_compose ("%1-%2%3", legalize_for_path (snapshot_name), Stateful::loading_state_version, statefile_suffix);
936 backup_path = Glib::build_filename (backup_path, backup_filename);
938 // only create a backup for a given statefile version once
940 if (!Glib::file_test (backup_path, Glib::FILE_TEST_EXISTS)) {
942 info << string_compose (_("Copying old session file %1 to %2\nUse %2 with %3 versions before 2.0 from now on"),
943 xmlpath, backup_path, PROGRAM_NAME)
946 if (!copy_file (xmlpath, backup_path)) {;
956 Session::load_options (const XMLNode& node)
958 LocaleGuard lg (X_("POSIX"));
959 config.set_variables (node);
970 Session::get_template()
972 /* if we don't disable rec-enable, diskstreams
973 will believe they need to store their capture
974 sources in their state node.
977 disable_record (false);
983 Session::state (bool full_state)
985 XMLNode* node = new XMLNode("Session");
989 snprintf(buf, sizeof(buf), "%d", CURRENT_SESSION_FILE_VERSION);
990 node->add_property("version", buf);
992 /* store configuration settings */
996 node->add_property ("name", _name);
997 snprintf (buf, sizeof (buf), "%" PRId64, _nominal_frame_rate);
998 node->add_property ("sample-rate", buf);
1000 if (session_dirs.size() > 1) {
1004 vector<space_and_path>::iterator i = session_dirs.begin();
1005 vector<space_and_path>::iterator next;
1007 ++i; /* skip the first one */
1011 while (i != session_dirs.end()) {
1015 if (next != session_dirs.end()) {
1025 child = node->add_child ("Path");
1026 child->add_content (p);
1030 /* save the ID counter */
1032 snprintf (buf, sizeof (buf), "%" PRIu64, ID::counter());
1033 node->add_property ("id-counter", buf);
1035 /* save the event ID counter */
1037 snprintf (buf, sizeof (buf), "%d", Evoral::event_id_counter());
1038 node->add_property ("event-counter", buf);
1040 /* various options */
1042 node->add_child_nocopy (config.get_variables ());
1044 node->add_child_nocopy (ARDOUR::SessionMetadata::Metadata()->get_state());
1046 child = node->add_child ("Sources");
1049 Glib::Threads::Mutex::Lock sl (source_lock);
1051 for (SourceMap::iterator siter = sources.begin(); siter != sources.end(); ++siter) {
1053 /* Don't save information about non-file Sources, or
1054 * about non-destructive file sources that are empty
1055 * and unused by any regions.
1058 boost::shared_ptr<FileSource> fs;
1060 if ((fs = boost::dynamic_pointer_cast<FileSource> (siter->second)) != 0) {
1062 if (!fs->destructive()) {
1063 if (fs->empty() && !fs->used()) {
1068 child->add_child_nocopy (siter->second->get_state());
1073 child = node->add_child ("Regions");
1076 Glib::Threads::Mutex::Lock rl (region_lock);
1077 const RegionFactory::RegionMap& region_map (RegionFactory::all_regions());
1078 for (RegionFactory::RegionMap::const_iterator i = region_map.begin(); i != region_map.end(); ++i) {
1079 boost::shared_ptr<Region> r = i->second;
1080 /* only store regions not attached to playlists */
1081 if (r->playlist() == 0) {
1082 child->add_child_nocopy (r->state ());
1086 RegionFactory::CompoundAssociations& cassocs (RegionFactory::compound_associations());
1088 if (!cassocs.empty()) {
1089 XMLNode* ca = node->add_child (X_("CompoundAssociations"));
1091 for (RegionFactory::CompoundAssociations::iterator i = cassocs.begin(); i != cassocs.end(); ++i) {
1093 XMLNode* can = new XMLNode (X_("CompoundAssociation"));
1094 i->first->id().print (buf, sizeof (buf));
1095 can->add_property (X_("copy"), buf);
1096 i->second->id().print (buf, sizeof (buf));
1097 can->add_property (X_("original"), buf);
1098 ca->add_child_nocopy (*can);
1104 node->add_child_nocopy (_locations->get_state());
1106 // for a template, just create a new Locations, populate it
1107 // with the default start and end, and get the state for that.
1108 Locations loc (*this);
1109 Location* range = new Location (*this, 0, 0, _("session"), Location::IsSessionRange);
1110 range->set (max_framepos, 0);
1112 node->add_child_nocopy (loc.get_state());
1115 child = node->add_child ("Bundles");
1117 boost::shared_ptr<BundleList> bundles = _bundles.reader ();
1118 for (BundleList::iterator i = bundles->begin(); i != bundles->end(); ++i) {
1119 boost::shared_ptr<UserBundle> b = boost::dynamic_pointer_cast<UserBundle> (*i);
1121 child->add_child_nocopy (b->get_state());
1126 child = node->add_child ("Routes");
1128 boost::shared_ptr<RouteList> r = routes.reader ();
1130 RoutePublicOrderSorter cmp;
1131 RouteList public_order (*r);
1132 public_order.sort (cmp);
1134 /* the sort should have put control outs first */
1137 assert (_monitor_out == public_order.front());
1140 for (RouteList::iterator i = public_order.begin(); i != public_order.end(); ++i) {
1141 if (!(*i)->is_hidden()) {
1143 child->add_child_nocopy ((*i)->get_state());
1145 child->add_child_nocopy ((*i)->get_template());
1151 playlists->add_state (node, full_state);
1153 child = node->add_child ("RouteGroups");
1154 for (list<RouteGroup *>::iterator i = _route_groups.begin(); i != _route_groups.end(); ++i) {
1155 child->add_child_nocopy ((*i)->get_state());
1159 XMLNode* gain_child = node->add_child ("Click");
1160 gain_child->add_child_nocopy (_click_io->state (full_state));
1161 gain_child->add_child_nocopy (_click_gain->state (full_state));
1165 XMLNode* ltc_input_child = node->add_child ("LTC-In");
1166 ltc_input_child->add_child_nocopy (_ltc_input->state (full_state));
1170 XMLNode* ltc_output_child = node->add_child ("LTC-Out");
1171 ltc_output_child->add_child_nocopy (_ltc_output->state (full_state));
1174 node->add_child_nocopy (_speakers->get_state());
1175 node->add_child_nocopy (_tempo_map->get_state());
1176 node->add_child_nocopy (get_control_protocol_state());
1179 node->add_child_copy (*_extra_xml);
1186 Session::get_control_protocol_state ()
1188 ControlProtocolManager& cpm (ControlProtocolManager::instance());
1189 return cpm.get_state();
1193 Session::set_state (const XMLNode& node, int version)
1197 const XMLProperty* prop;
1200 _state_of_the_state = StateOfTheState (_state_of_the_state|CannotSave);
1202 if (node.name() != X_("Session")) {
1203 fatal << _("programming error: Session: incorrect XML node sent to set_state()") << endmsg;
1207 if ((prop = node.property ("name")) != 0) {
1208 _name = prop->value ();
1211 if ((prop = node.property (X_("sample-rate"))) != 0) {
1213 _nominal_frame_rate = atoi (prop->value());
1215 if (_nominal_frame_rate != _current_frame_rate) {
1216 boost::optional<int> r = AskAboutSampleRateMismatch (_nominal_frame_rate, _current_frame_rate);
1217 if (r.get_value_or (0)) {
1223 setup_raid_path(_session_dir->root_path());
1225 if ((prop = node.property (X_("id-counter"))) != 0) {
1227 sscanf (prop->value().c_str(), "%" PRIu64, &x);
1228 ID::init_counter (x);
1230 /* old sessions used a timebased counter, so fake
1231 the startup ID counter based on a standard
1236 ID::init_counter (now);
1239 if ((prop = node.property (X_("event-counter"))) != 0) {
1240 Evoral::init_event_id_counter (atoi (prop->value()));
1243 IO::disable_connecting ();
1245 Stateful::save_extra_xml (node);
1247 if (((child = find_named_node (node, "Options")) != 0)) { /* old style */
1248 load_options (*child);
1249 } else if ((child = find_named_node (node, "Config")) != 0) { /* new style */
1250 load_options (*child);
1252 error << _("Session: XML state has no options section") << endmsg;
1255 if (version >= 3000) {
1256 if ((child = find_named_node (node, "Metadata")) == 0) {
1257 warning << _("Session: XML state has no metadata section") << endmsg;
1258 } else if ( ARDOUR::SessionMetadata::Metadata()->set_state (*child, version) ) {
1263 if ((child = find_named_node (node, X_("Speakers"))) != 0) {
1264 _speakers->set_state (*child, version);
1267 if ((child = find_named_node (node, "Sources")) == 0) {
1268 error << _("Session: XML state has no sources section") << endmsg;
1270 } else if (load_sources (*child)) {
1274 if ((child = find_named_node (node, "TempoMap")) == 0) {
1275 error << _("Session: XML state has no Tempo Map section") << endmsg;
1277 } else if (_tempo_map->set_state (*child, version)) {
1281 if ((child = find_named_node (node, "Locations")) == 0) {
1282 error << _("Session: XML state has no locations section") << endmsg;
1284 } else if (_locations->set_state (*child, version)) {
1290 if ((location = _locations->auto_loop_location()) != 0) {
1291 set_auto_loop_location (location);
1294 if ((location = _locations->auto_punch_location()) != 0) {
1295 set_auto_punch_location (location);
1298 if ((location = _locations->session_range_location()) != 0) {
1299 delete _session_range_location;
1300 _session_range_location = location;
1303 if (_session_range_location) {
1304 AudioFileSource::set_header_position_offset (_session_range_location->start());
1307 if ((child = find_named_node (node, "Regions")) == 0) {
1308 error << _("Session: XML state has no Regions section") << endmsg;
1310 } else if (load_regions (*child)) {
1314 if ((child = find_named_node (node, "Playlists")) == 0) {
1315 error << _("Session: XML state has no playlists section") << endmsg;
1317 } else if (playlists->load (*this, *child)) {
1321 if ((child = find_named_node (node, "UnusedPlaylists")) == 0) {
1323 } else if (playlists->load_unused (*this, *child)) {
1327 if ((child = find_named_node (node, "CompoundAssociations")) != 0) {
1328 if (load_compounds (*child)) {
1333 if (version >= 3000) {
1334 if ((child = find_named_node (node, "Bundles")) == 0) {
1335 warning << _("Session: XML state has no bundles section") << endmsg;
1338 /* We can't load Bundles yet as they need to be able
1339 to convert from port names to Port objects, which can't happen until
1341 _bundle_xml_node = new XMLNode (*child);
1345 if (version < 3000) {
1346 if ((child = find_named_node (node, X_("DiskStreams"))) == 0) {
1347 error << _("Session: XML state has no diskstreams section") << endmsg;
1349 } else if (load_diskstreams_2X (*child, version)) {
1354 if ((child = find_named_node (node, "Routes")) == 0) {
1355 error << _("Session: XML state has no routes section") << endmsg;
1357 } else if (load_routes (*child, version)) {
1361 /* our diskstreams list is no longer needed as they are now all owned by their Route */
1362 _diskstreams_2X.clear ();
1364 if (version >= 3000) {
1366 if ((child = find_named_node (node, "RouteGroups")) == 0) {
1367 error << _("Session: XML state has no route groups section") << endmsg;
1369 } else if (load_route_groups (*child, version)) {
1373 } else if (version < 3000) {
1375 if ((child = find_named_node (node, "EditGroups")) == 0) {
1376 error << _("Session: XML state has no edit groups section") << endmsg;
1378 } else if (load_route_groups (*child, version)) {
1382 if ((child = find_named_node (node, "MixGroups")) == 0) {
1383 error << _("Session: XML state has no mix groups section") << endmsg;
1385 } else if (load_route_groups (*child, version)) {
1390 if ((child = find_named_node (node, "Click")) == 0) {
1391 warning << _("Session: XML state has no click section") << endmsg;
1392 } else if (_click_io) {
1393 const XMLNodeList& children (child->children());
1394 XMLNodeList::const_iterator i = children.begin();
1395 _click_io->set_state (**i, version);
1397 if (i != children.end()) {
1398 _click_gain->set_state (**i, version);
1402 if ((child = find_named_node (node, ControlProtocolManager::state_node_name)) != 0) {
1403 ControlProtocolManager::instance().set_state (*child, version);
1406 update_have_rec_enabled_track ();
1408 /* here beginneth the second phase ... */
1410 StateReady (); /* EMIT SIGNAL */
1419 Session::load_routes (const XMLNode& node, int version)
1422 XMLNodeConstIterator niter;
1423 RouteList new_routes;
1425 nlist = node.children();
1429 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1431 boost::shared_ptr<Route> route;
1432 if (version < 3000) {
1433 route = XMLRouteFactory_2X (**niter, version);
1435 route = XMLRouteFactory (**niter, version);
1439 error << _("Session: cannot create Route from XML description.") << endmsg;
1443 BootMessage (string_compose (_("Loaded track/bus %1"), route->name()));
1445 new_routes.push_back (route);
1448 add_routes (new_routes, false, false, false);
1453 boost::shared_ptr<Route>
1454 Session::XMLRouteFactory (const XMLNode& node, int version)
1456 boost::shared_ptr<Route> ret;
1458 if (node.name() != "Route") {
1462 XMLNode* ds_child = find_named_node (node, X_("Diskstream"));
1464 DataType type = DataType::AUDIO;
1465 const XMLProperty* prop = node.property("default-type");
1468 type = DataType (prop->value());
1471 assert (type != DataType::NIL);
1475 boost::shared_ptr<Track> track;
1477 if (type == DataType::AUDIO) {
1478 track.reset (new AudioTrack (*this, X_("toBeResetFroXML")));
1480 track.reset (new MidiTrack (*this, X_("toBeResetFroXML")));
1483 if (track->init()) {
1487 if (track->set_state (node, version)) {
1491 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
1492 // boost_debug_shared_ptr_mark_interesting (track.get(), "Track");
1497 boost::shared_ptr<Route> r (new Route (*this, X_("toBeResetFroXML")));
1499 if (r->init () == 0 && r->set_state (node, version) == 0) {
1500 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
1501 // boost_debug_shared_ptr_mark_interesting (r.get(), "Route");
1510 boost::shared_ptr<Route>
1511 Session::XMLRouteFactory_2X (const XMLNode& node, int version)
1513 boost::shared_ptr<Route> ret;
1515 if (node.name() != "Route") {
1519 XMLProperty const * ds_prop = node.property (X_("diskstream-id"));
1521 ds_prop = node.property (X_("diskstream"));
1524 DataType type = DataType::AUDIO;
1525 const XMLProperty* prop = node.property("default-type");
1528 type = DataType (prop->value());
1531 assert (type != DataType::NIL);
1535 list<boost::shared_ptr<Diskstream> >::iterator i = _diskstreams_2X.begin ();
1536 while (i != _diskstreams_2X.end() && (*i)->id() != ds_prop->value()) {
1540 if (i == _diskstreams_2X.end()) {
1541 error << _("Could not find diskstream for route") << endmsg;
1542 return boost::shared_ptr<Route> ();
1545 boost::shared_ptr<Track> track;
1547 if (type == DataType::AUDIO) {
1548 track.reset (new AudioTrack (*this, X_("toBeResetFroXML")));
1550 track.reset (new MidiTrack (*this, X_("toBeResetFroXML")));
1553 if (track->init()) {
1557 if (track->set_state (node, version)) {
1561 track->set_diskstream (*i);
1563 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
1564 // boost_debug_shared_ptr_mark_interesting (track.get(), "Track");
1569 boost::shared_ptr<Route> r (new Route (*this, X_("toBeResetFroXML")));
1571 if (r->init () == 0 && r->set_state (node, version) == 0) {
1572 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
1573 // boost_debug_shared_ptr_mark_interesting (r.get(), "Route");
1583 Session::load_regions (const XMLNode& node)
1586 XMLNodeConstIterator niter;
1587 boost::shared_ptr<Region> region;
1589 nlist = node.children();
1593 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1594 if ((region = XMLRegionFactory (**niter, false)) == 0) {
1595 error << _("Session: cannot create Region from XML description.");
1596 const XMLProperty *name = (**niter).property("name");
1599 error << " " << string_compose (_("Can not load state for region '%1'"), name->value());
1610 Session::load_compounds (const XMLNode& node)
1612 XMLNodeList calist = node.children();
1613 XMLNodeConstIterator caiter;
1614 XMLProperty *caprop;
1616 for (caiter = calist.begin(); caiter != calist.end(); ++caiter) {
1617 XMLNode* ca = *caiter;
1621 if ((caprop = ca->property (X_("original"))) == 0) {
1624 orig_id = caprop->value();
1626 if ((caprop = ca->property (X_("copy"))) == 0) {
1629 copy_id = caprop->value();
1631 boost::shared_ptr<Region> orig = RegionFactory::region_by_id (orig_id);
1632 boost::shared_ptr<Region> copy = RegionFactory::region_by_id (copy_id);
1634 if (!orig || !copy) {
1635 warning << string_compose (_("Regions in compound description not found (ID's %1 and %2): ignored"),
1641 RegionFactory::add_compound_association (orig, copy);
1648 Session::load_nested_sources (const XMLNode& node)
1651 XMLNodeConstIterator niter;
1653 nlist = node.children();
1655 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1656 if ((*niter)->name() == "Source") {
1658 /* it may already exist, so don't recreate it unnecessarily
1661 XMLProperty* prop = (*niter)->property (X_("id"));
1663 error << _("Nested source has no ID info in session state file! (ignored)") << endmsg;
1667 ID source_id (prop->value());
1669 if (!source_by_id (source_id)) {
1672 SourceFactory::create (*this, **niter, true);
1674 catch (failed_constructor& err) {
1675 error << string_compose (_("Cannot reconstruct nested source for region %1"), name()) << endmsg;
1682 boost::shared_ptr<Region>
1683 Session::XMLRegionFactory (const XMLNode& node, bool full)
1685 const XMLProperty* type = node.property("type");
1689 const XMLNodeList& nlist = node.children();
1691 for (XMLNodeConstIterator niter = nlist.begin(); niter != nlist.end(); ++niter) {
1692 XMLNode *child = (*niter);
1693 if (child->name() == "NestedSource") {
1694 load_nested_sources (*child);
1698 if (!type || type->value() == "audio") {
1699 return boost::shared_ptr<Region>(XMLAudioRegionFactory (node, full));
1700 } else if (type->value() == "midi") {
1701 return boost::shared_ptr<Region>(XMLMidiRegionFactory (node, full));
1704 } catch (failed_constructor& err) {
1705 return boost::shared_ptr<Region> ();
1708 return boost::shared_ptr<Region> ();
1711 boost::shared_ptr<AudioRegion>
1712 Session::XMLAudioRegionFactory (const XMLNode& node, bool /*full*/)
1714 const XMLProperty* prop;
1715 boost::shared_ptr<Source> source;
1716 boost::shared_ptr<AudioSource> as;
1718 SourceList master_sources;
1719 uint32_t nchans = 1;
1722 if (node.name() != X_("Region")) {
1723 return boost::shared_ptr<AudioRegion>();
1726 if ((prop = node.property (X_("channels"))) != 0) {
1727 nchans = atoi (prop->value().c_str());
1730 if ((prop = node.property ("name")) == 0) {
1731 cerr << "no name for this region\n";
1735 if ((prop = node.property (X_("source-0"))) == 0) {
1736 if ((prop = node.property ("source")) == 0) {
1737 error << _("Session: XMLNode describing a AudioRegion is incomplete (no source)") << endmsg;
1738 return boost::shared_ptr<AudioRegion>();
1742 PBD::ID s_id (prop->value());
1744 if ((source = source_by_id (s_id)) == 0) {
1745 error << string_compose(_("Session: XMLNode describing a AudioRegion references an unknown source id =%1"), s_id) << endmsg;
1746 return boost::shared_ptr<AudioRegion>();
1749 as = boost::dynamic_pointer_cast<AudioSource>(source);
1751 error << string_compose(_("Session: XMLNode describing a AudioRegion references a non-audio source id =%1"), s_id) << endmsg;
1752 return boost::shared_ptr<AudioRegion>();
1755 sources.push_back (as);
1757 /* pickup other channels */
1759 for (uint32_t n=1; n < nchans; ++n) {
1760 snprintf (buf, sizeof(buf), X_("source-%d"), n);
1761 if ((prop = node.property (buf)) != 0) {
1763 PBD::ID id2 (prop->value());
1765 if ((source = source_by_id (id2)) == 0) {
1766 error << string_compose(_("Session: XMLNode describing a AudioRegion references an unknown source id =%1"), id2) << endmsg;
1767 return boost::shared_ptr<AudioRegion>();
1770 as = boost::dynamic_pointer_cast<AudioSource>(source);
1772 error << string_compose(_("Session: XMLNode describing a AudioRegion references a non-audio source id =%1"), id2) << endmsg;
1773 return boost::shared_ptr<AudioRegion>();
1775 sources.push_back (as);
1779 for (uint32_t n = 0; n < nchans; ++n) {
1780 snprintf (buf, sizeof(buf), X_("master-source-%d"), n);
1781 if ((prop = node.property (buf)) != 0) {
1783 PBD::ID id2 (prop->value());
1785 if ((source = source_by_id (id2)) == 0) {
1786 error << string_compose(_("Session: XMLNode describing a AudioRegion references an unknown source id =%1"), id2) << endmsg;
1787 return boost::shared_ptr<AudioRegion>();
1790 as = boost::dynamic_pointer_cast<AudioSource>(source);
1792 error << string_compose(_("Session: XMLNode describing a AudioRegion references a non-audio source id =%1"), id2) << endmsg;
1793 return boost::shared_ptr<AudioRegion>();
1795 master_sources.push_back (as);
1800 boost::shared_ptr<AudioRegion> region (boost::dynamic_pointer_cast<AudioRegion> (RegionFactory::create (sources, node)));
1802 /* a final detail: this is the one and only place that we know how long missing files are */
1804 if (region->whole_file()) {
1805 for (SourceList::iterator sx = sources.begin(); sx != sources.end(); ++sx) {
1806 boost::shared_ptr<SilentFileSource> sfp = boost::dynamic_pointer_cast<SilentFileSource> (*sx);
1808 sfp->set_length (region->length());
1813 if (!master_sources.empty()) {
1814 if (master_sources.size() != nchans) {
1815 error << _("Session: XMLNode describing an AudioRegion is missing some master sources; ignored") << endmsg;
1817 region->set_master_sources (master_sources);
1825 catch (failed_constructor& err) {
1826 return boost::shared_ptr<AudioRegion>();
1830 boost::shared_ptr<MidiRegion>
1831 Session::XMLMidiRegionFactory (const XMLNode& node, bool /*full*/)
1833 const XMLProperty* prop;
1834 boost::shared_ptr<Source> source;
1835 boost::shared_ptr<MidiSource> ms;
1838 if (node.name() != X_("Region")) {
1839 return boost::shared_ptr<MidiRegion>();
1842 if ((prop = node.property ("name")) == 0) {
1843 cerr << "no name for this region\n";
1847 if ((prop = node.property (X_("source-0"))) == 0) {
1848 if ((prop = node.property ("source")) == 0) {
1849 error << _("Session: XMLNode describing a MidiRegion is incomplete (no source)") << endmsg;
1850 return boost::shared_ptr<MidiRegion>();
1854 PBD::ID s_id (prop->value());
1856 if ((source = source_by_id (s_id)) == 0) {
1857 error << string_compose(_("Session: XMLNode describing a MidiRegion references an unknown source id =%1"), s_id) << endmsg;
1858 return boost::shared_ptr<MidiRegion>();
1861 ms = boost::dynamic_pointer_cast<MidiSource>(source);
1863 error << string_compose(_("Session: XMLNode describing a MidiRegion references a non-midi source id =%1"), s_id) << endmsg;
1864 return boost::shared_ptr<MidiRegion>();
1867 sources.push_back (ms);
1870 boost::shared_ptr<MidiRegion> region (boost::dynamic_pointer_cast<MidiRegion> (RegionFactory::create (sources, node)));
1871 /* a final detail: this is the one and only place that we know how long missing files are */
1873 if (region->whole_file()) {
1874 for (SourceList::iterator sx = sources.begin(); sx != sources.end(); ++sx) {
1875 boost::shared_ptr<SilentFileSource> sfp = boost::dynamic_pointer_cast<SilentFileSource> (*sx);
1877 sfp->set_length (region->length());
1885 catch (failed_constructor& err) {
1886 return boost::shared_ptr<MidiRegion>();
1891 Session::get_sources_as_xml ()
1894 XMLNode* node = new XMLNode (X_("Sources"));
1895 Glib::Threads::Mutex::Lock lm (source_lock);
1897 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ++i) {
1898 node->add_child_nocopy (i->second->get_state());
1905 Session::path_from_region_name (DataType type, string name, string identifier)
1907 char buf[PATH_MAX+1];
1909 SessionDirectory sdir(get_best_session_directory_for_new_source());
1910 std::string source_dir = ((type == DataType::AUDIO)
1911 ? sdir.sound_path() : sdir.midi_path());
1913 string ext = native_header_format_extension (config.get_native_file_header_format(), type);
1915 for (n = 0; n < 999999; ++n) {
1916 if (identifier.length()) {
1917 snprintf (buf, sizeof(buf), "%s%s%" PRIu32 "%s", name.c_str(),
1918 identifier.c_str(), n, ext.c_str());
1920 snprintf (buf, sizeof(buf), "%s-%" PRIu32 "%s", name.c_str(),
1924 std::string source_path = Glib::build_filename (source_dir, buf);
1926 if (!Glib::file_test (source_path, Glib::FILE_TEST_EXISTS)) {
1931 error << string_compose (_("cannot create new file from region name \"%1\" with ident = \"%2\": too many existing files with similar names"),
1940 Session::load_sources (const XMLNode& node)
1943 XMLNodeConstIterator niter;
1944 boost::shared_ptr<Source> source;
1946 nlist = node.children();
1950 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1953 if ((source = XMLSourceFactory (**niter)) == 0) {
1954 error << _("Session: cannot create Source from XML description.") << endmsg;
1957 } catch (MissingSource& err) {
1961 if (!no_questions_about_missing_files) {
1962 user_choice = MissingFile (this, err.path, err.type).get_value_or (-1);
1967 switch (user_choice) {
1969 /* user added a new search location, so try again */
1974 /* user asked to quit the entire session load
1979 no_questions_about_missing_files = true;
1983 no_questions_about_missing_files = true;
1988 warning << _("A sound file is missing. It will be replaced by silence.") << endmsg;
1989 source = SourceFactory::createSilent (*this, **niter, max_framecnt, _current_frame_rate);
1998 boost::shared_ptr<Source>
1999 Session::XMLSourceFactory (const XMLNode& node)
2001 if (node.name() != "Source") {
2002 return boost::shared_ptr<Source>();
2006 /* note: do peak building in another thread when loading session state */
2007 return SourceFactory::create (*this, node, true);
2010 catch (failed_constructor& err) {
2011 error << string_compose (_("Found a sound file that cannot be used by %1. Talk to the progammers."), PROGRAM_NAME) << endmsg;
2012 return boost::shared_ptr<Source>();
2017 Session::save_template (string template_name)
2021 if (_state_of_the_state & CannotSave) {
2025 std::string user_template_dir(user_template_directory());
2027 if (g_mkdir_with_parents (user_template_dir.c_str(), 0755) != 0) {
2028 error << string_compose(_("Could not create templates directory \"%1\" (%2)"),
2029 user_template_dir, g_strerror (errno)) << endmsg;
2033 tree.set_root (&get_template());
2035 std::string template_dir_path(user_template_dir);
2037 /* directory to put the template in */
2038 template_dir_path = Glib::build_filename (template_dir_path, template_name);
2040 if (Glib::file_test (template_dir_path, Glib::FILE_TEST_EXISTS)) {
2041 warning << string_compose(_("Template \"%1\" already exists - new version not created"),
2042 template_dir_path) << endmsg;
2046 if (g_mkdir_with_parents (template_dir_path.c_str(), 0755) != 0) {
2047 error << string_compose(_("Could not create directory for Session template\"%1\" (%2)"),
2048 template_dir_path, g_strerror (errno)) << endmsg;
2053 std::string template_file_path(template_dir_path);
2054 template_file_path = Glib::build_filename (template_file_path, template_name + template_suffix);
2056 if (!tree.write (template_file_path)) {
2057 error << _("template not saved") << endmsg;
2061 /* copy plugin state directory */
2063 std::string template_plugin_state_path(template_dir_path);
2064 template_plugin_state_path = Glib::build_filename (template_plugin_state_path, X_("plugins"));
2066 if (g_mkdir_with_parents (template_plugin_state_path.c_str(), 0755) != 0) {
2067 error << string_compose(_("Could not create directory for Session template plugin state\"%1\" (%2)"),
2068 template_plugin_state_path, g_strerror (errno)) << endmsg;
2072 copy_files (plugins_dir(), template_plugin_state_path);
2078 Session::refresh_disk_space ()
2080 #if HAVE_SYS_VFS_H && HAVE_SYS_STATVFS_H
2082 Glib::Threads::Mutex::Lock lm (space_lock);
2084 /* get freespace on every FS that is part of the session path */
2086 _total_free_4k_blocks = 0;
2087 _total_free_4k_blocks_uncertain = false;
2089 for (vector<space_and_path>::iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
2091 struct statfs statfsbuf;
2092 statfs (i->path.c_str(), &statfsbuf);
2094 double const scale = statfsbuf.f_bsize / 4096.0;
2096 /* See if this filesystem is read-only */
2097 struct statvfs statvfsbuf;
2098 statvfs (i->path.c_str(), &statvfsbuf);
2100 /* f_bavail can be 0 if it is undefined for whatever
2101 filesystem we are looking at; Samba shares mounted
2102 via GVFS are an example of this.
2104 if (statfsbuf.f_bavail == 0) {
2105 /* block count unknown */
2107 i->blocks_unknown = true;
2108 } else if (statvfsbuf.f_flag & ST_RDONLY) {
2109 /* read-only filesystem */
2111 i->blocks_unknown = false;
2113 /* read/write filesystem with known space */
2114 i->blocks = (uint32_t) floor (statfsbuf.f_bavail * scale);
2115 i->blocks_unknown = false;
2118 _total_free_4k_blocks += i->blocks;
2119 if (i->blocks_unknown) {
2120 _total_free_4k_blocks_uncertain = true;
2127 Session::get_best_session_directory_for_new_source ()
2129 vector<space_and_path>::iterator i;
2130 string result = _session_dir->root_path();
2132 /* handle common case without system calls */
2134 if (session_dirs.size() == 1) {
2138 /* OK, here's the algorithm we're following here:
2140 We want to select which directory to use for
2141 the next file source to be created. Ideally,
2142 we'd like to use a round-robin process so as to
2143 get maximum performance benefits from splitting
2144 the files across multiple disks.
2146 However, in situations without much diskspace, an
2147 RR approach may end up filling up a filesystem
2148 with new files while others still have space.
2149 Its therefore important to pay some attention to
2150 the freespace in the filesystem holding each
2151 directory as well. However, if we did that by
2152 itself, we'd keep creating new files in the file
2153 system with the most space until it was as full
2154 as all others, thus negating any performance
2155 benefits of this RAID-1 like approach.
2157 So, we use a user-configurable space threshold. If
2158 there are at least 2 filesystems with more than this
2159 much space available, we use RR selection between them.
2160 If not, then we pick the filesystem with the most space.
2162 This gets a good balance between the two
2166 refresh_disk_space ();
2168 int free_enough = 0;
2170 for (i = session_dirs.begin(); i != session_dirs.end(); ++i) {
2171 if ((*i).blocks * 4096 >= Config->get_disk_choice_space_threshold()) {
2176 if (free_enough >= 2) {
2177 /* use RR selection process, ensuring that the one
2181 i = last_rr_session_dir;
2184 if (++i == session_dirs.end()) {
2185 i = session_dirs.begin();
2188 if ((*i).blocks * 4096 >= Config->get_disk_choice_space_threshold()) {
2189 SessionDirectory sdir(i->path);
2190 if (sdir.create ()) {
2192 last_rr_session_dir = i;
2197 } while (i != last_rr_session_dir);
2201 /* pick FS with the most freespace (and that
2202 seems to actually work ...)
2205 vector<space_and_path> sorted;
2206 space_and_path_ascending_cmp cmp;
2208 sorted = session_dirs;
2209 sort (sorted.begin(), sorted.end(), cmp);
2211 for (i = sorted.begin(); i != sorted.end(); ++i) {
2212 SessionDirectory sdir(i->path);
2213 if (sdir.create ()) {
2215 last_rr_session_dir = i;
2225 Session::automation_dir () const
2227 return Glib::build_filename (_path, "automation");
2231 Session::analysis_dir () const
2233 return Glib::build_filename (_path, "analysis");
2237 Session::plugins_dir () const
2239 return Glib::build_filename (_path, "plugins");
2243 Session::externals_dir () const
2245 return Glib::build_filename (_path, "externals");
2249 Session::load_bundles (XMLNode const & node)
2251 XMLNodeList nlist = node.children();
2252 XMLNodeConstIterator niter;
2256 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2257 if ((*niter)->name() == "InputBundle") {
2258 add_bundle (boost::shared_ptr<UserBundle> (new UserBundle (**niter, true)));
2259 } else if ((*niter)->name() == "OutputBundle") {
2260 add_bundle (boost::shared_ptr<UserBundle> (new UserBundle (**niter, false)));
2262 error << string_compose(_("Unknown node \"%1\" found in Bundles list from state file"), (*niter)->name()) << endmsg;
2271 Session::load_route_groups (const XMLNode& node, int version)
2273 XMLNodeList nlist = node.children();
2274 XMLNodeConstIterator niter;
2278 if (version >= 3000) {
2280 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2281 if ((*niter)->name() == "RouteGroup") {
2282 RouteGroup* rg = new RouteGroup (*this, "");
2283 add_route_group (rg);
2284 rg->set_state (**niter, version);
2288 } else if (version < 3000) {
2290 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2291 if ((*niter)->name() == "EditGroup" || (*niter)->name() == "MixGroup") {
2292 RouteGroup* rg = new RouteGroup (*this, "");
2293 add_route_group (rg);
2294 rg->set_state (**niter, version);
2303 Session::auto_save()
2305 save_state (_current_snapshot_name);
2309 state_file_filter (const string &str, void */*arg*/)
2311 return (str.length() > strlen(statefile_suffix) &&
2312 str.find (statefile_suffix) == (str.length() - strlen (statefile_suffix)));
2316 bool operator()(const string* a, const string* b) {
2322 remove_end(string* state)
2324 string statename(*state);
2326 string::size_type start,end;
2327 if ((start = statename.find_last_of (G_DIR_SEPARATOR)) != string::npos) {
2328 statename = statename.substr (start+1);
2331 if ((end = statename.rfind(".ardour")) == string::npos) {
2332 end = statename.length();
2335 return new string(statename.substr (0, end));
2339 Session::possible_states (string path)
2341 PathScanner scanner;
2342 vector<string*>* states = scanner (path, state_file_filter, 0, false, false);
2344 transform(states->begin(), states->end(), states->begin(), remove_end);
2347 sort (states->begin(), states->end(), cmp);
2353 Session::possible_states () const
2355 return possible_states(_path);
2359 Session::add_route_group (RouteGroup* g)
2361 _route_groups.push_back (g);
2362 route_group_added (g); /* EMIT SIGNAL */
2364 g->RouteAdded.connect_same_thread (*this, boost::bind (&Session::route_added_to_route_group, this, _1, _2));
2365 g->RouteRemoved.connect_same_thread (*this, boost::bind (&Session::route_removed_from_route_group, this, _1, _2));
2366 g->PropertyChanged.connect_same_thread (*this, boost::bind (&Session::route_group_property_changed, this, g));
2372 Session::remove_route_group (RouteGroup& rg)
2374 list<RouteGroup*>::iterator i;
2376 if ((i = find (_route_groups.begin(), _route_groups.end(), &rg)) != _route_groups.end()) {
2377 _route_groups.erase (i);
2380 route_group_removed (); /* EMIT SIGNAL */
2384 /** Set a new order for our route groups, without adding or removing any.
2385 * @param groups Route group list in the new order.
2388 Session::reorder_route_groups (list<RouteGroup*> groups)
2390 _route_groups = groups;
2392 route_groups_reordered (); /* EMIT SIGNAL */
2398 Session::route_group_by_name (string name)
2400 list<RouteGroup *>::iterator i;
2402 for (i = _route_groups.begin(); i != _route_groups.end(); ++i) {
2403 if ((*i)->name() == name) {
2411 Session::all_route_group() const
2413 return *_all_route_group;
2417 Session::add_commands (vector<Command*> const & cmds)
2419 for (vector<Command*>::const_iterator i = cmds.begin(); i != cmds.end(); ++i) {
2425 Session::begin_reversible_command (const string& name)
2427 begin_reversible_command (g_quark_from_string (name.c_str ()));
2430 /** Begin a reversible command using a GQuark to identify it.
2431 * begin_reversible_command() and commit_reversible_command() calls may be nested,
2432 * but there must be as many begin...()s as there are commit...()s.
2435 Session::begin_reversible_command (GQuark q)
2437 /* If nested begin/commit pairs are used, we create just one UndoTransaction
2438 to hold all the commands that are committed. This keeps the order of
2439 commands correct in the history.
2442 if (_current_trans == 0) {
2443 /* start a new transaction */
2444 assert (_current_trans_quarks.empty ());
2445 _current_trans = new UndoTransaction();
2446 _current_trans->set_name (g_quark_to_string (q));
2449 _current_trans_quarks.push_front (q);
2453 Session::commit_reversible_command (Command *cmd)
2455 assert (_current_trans);
2456 assert (!_current_trans_quarks.empty ());
2461 _current_trans->add_command (cmd);
2464 _current_trans_quarks.pop_front ();
2466 if (!_current_trans_quarks.empty ()) {
2467 /* the transaction we're committing is not the top-level one */
2471 if (_current_trans->empty()) {
2472 /* no commands were added to the transaction, so just get rid of it */
2473 delete _current_trans;
2478 gettimeofday (&now, 0);
2479 _current_trans->set_timestamp (now);
2481 _history.add (_current_trans);
2486 accept_all_audio_files (const string& path, void */*arg*/)
2488 if (!Glib::file_test (path, Glib::FILE_TEST_IS_REGULAR)) {
2492 if (!AudioFileSource::safe_audio_file_extension (path)) {
2500 accept_all_midi_files (const string& path, void */*arg*/)
2502 if (!Glib::file_test (path, Glib::FILE_TEST_IS_REGULAR)) {
2506 return ((path.length() > 4 && path.find (".mid") != (path.length() - 4)) ||
2507 (path.length() > 4 && path.find (".smf") != (path.length() - 4)) ||
2508 (path.length() > 5 && path.find (".midi") != (path.length() - 5)));
2512 accept_all_state_files (const string& path, void */*arg*/)
2514 if (!Glib::file_test (path, Glib::FILE_TEST_IS_REGULAR)) {
2518 return (path.length() > 7 && path.find (".ardour") == (path.length() - 7));
2522 Session::find_all_sources (string path, set<string>& result)
2527 if (!tree.read (path)) {
2531 if ((node = find_named_node (*tree.root(), "Sources")) == 0) {
2536 XMLNodeConstIterator niter;
2538 nlist = node->children();
2542 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2546 if ((prop = (*niter)->property (X_("type"))) == 0) {
2550 DataType type (prop->value());
2552 if ((prop = (*niter)->property (X_("name"))) == 0) {
2556 if (Glib::path_is_absolute (prop->value())) {
2557 /* external file, ignore */
2565 if (FileSource::find (*this, type, prop->value(), true, is_new, chan, found_path)) {
2566 result.insert (found_path);
2574 Session::find_all_sources_across_snapshots (set<string>& result, bool exclude_this_snapshot)
2576 PathScanner scanner;
2577 vector<string*>* state_files;
2579 string this_snapshot_path;
2585 if (ripped[ripped.length()-1] == G_DIR_SEPARATOR) {
2586 ripped = ripped.substr (0, ripped.length() - 1);
2589 state_files = scanner (ripped, accept_all_state_files, (void *) 0, true, true);
2591 if (state_files == 0) {
2596 this_snapshot_path = _path;
2597 this_snapshot_path += legalize_for_path (_current_snapshot_name);
2598 this_snapshot_path += statefile_suffix;
2600 for (vector<string*>::iterator i = state_files->begin(); i != state_files->end(); ++i) {
2602 if (exclude_this_snapshot && **i == this_snapshot_path) {
2606 if (find_all_sources (**i, result) < 0) {
2614 struct RegionCounter {
2615 typedef std::map<PBD::ID,boost::shared_ptr<AudioSource> > AudioSourceList;
2616 AudioSourceList::iterator iter;
2617 boost::shared_ptr<Region> region;
2620 RegionCounter() : count (0) {}
2624 Session::ask_about_playlist_deletion (boost::shared_ptr<Playlist> p)
2626 boost::optional<int> r = AskAboutPlaylistDeletion (p);
2627 return r.get_value_or (1);
2631 Session::cleanup_regions ()
2633 const RegionFactory::RegionMap& regions (RegionFactory::regions());
2635 for (RegionFactory::RegionMap::const_iterator i = regions.begin(); i != regions.end(); ++i) {
2637 uint32_t used = playlists->region_use_count (i->second);
2639 if (used == 0 && !i->second->automatic ()) {
2640 RegionFactory::map_remove (i->second);
2644 /* dump the history list */
2651 Session::cleanup_sources (CleanupReport& rep)
2653 // FIXME: needs adaptation to midi
2655 vector<boost::shared_ptr<Source> > dead_sources;
2656 PathScanner scanner;
2659 vector<space_and_path>::iterator i;
2660 vector<space_and_path>::iterator nexti;
2661 vector<string*>* candidates;
2662 vector<string*>* candidates2;
2663 vector<string> unused;
2664 set<string> all_sources;
2669 _state_of_the_state = (StateOfTheState) (_state_of_the_state | InCleanup);
2671 /* consider deleting all unused playlists */
2673 if (playlists->maybe_delete_unused (boost::bind (Session::ask_about_playlist_deletion, _1))) {
2678 /* sync the "all regions" property of each playlist with its current state
2681 playlists->sync_all_regions_with_regions ();
2683 /* find all un-used sources */
2688 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ) {
2690 SourceMap::iterator tmp;
2695 /* do not bother with files that are zero size, otherwise we remove the current "nascent"
2699 if (!i->second->used() && (i->second->length(i->second->timeline_position() > 0))) {
2700 dead_sources.push_back (i->second);
2701 i->second->drop_references ();
2707 /* build a list of all the possible audio directories for the session */
2709 for (i = session_dirs.begin(); i != session_dirs.end(); ) {
2714 SessionDirectory sdir ((*i).path);
2715 audio_path += sdir.sound_path();
2717 if (nexti != session_dirs.end()) {
2725 /* build a list of all the possible midi directories for the session */
2727 for (i = session_dirs.begin(); i != session_dirs.end(); ) {
2732 SessionDirectory sdir ((*i).path);
2733 midi_path += sdir.midi_path();
2735 if (nexti != session_dirs.end()) {
2742 candidates = scanner (audio_path, accept_all_audio_files, (void *) 0, true, true);
2743 candidates2 = scanner (midi_path, accept_all_midi_files, (void *) 0, true, true);
2749 for (vector<string*>::iterator i = candidates2->begin(); i != candidates2->end(); ++i) {
2750 candidates->push_back (*i);
2755 candidates = candidates2; // might still be null
2758 /* find all sources, but don't use this snapshot because the
2759 state file on disk still references sources we may have already
2763 find_all_sources_across_snapshots (all_sources, true);
2765 /* add our current source list
2768 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ) {
2769 boost::shared_ptr<FileSource> fs;
2770 SourceMap::iterator tmp = i;
2773 if ((fs = boost::dynamic_pointer_cast<FileSource> (i->second)) != 0) {
2774 if (playlists->source_use_count (fs) != 0) {
2775 all_sources.insert (fs->path());
2778 /* we might not remove this source from disk, because it may be used
2779 by other snapshots, but its not being used in this version
2780 so lets get rid of it now, along with any representative regions
2784 RegionFactory::remove_regions_using_source (i->second);
2792 char tmppath1[PATH_MAX+1];
2793 char tmppath2[PATH_MAX+1];
2796 for (vector<string*>::iterator x = candidates->begin(); x != candidates->end(); ++x) {
2801 for (set<string>::iterator i = all_sources.begin(); i != all_sources.end(); ++i) {
2803 if (realpath(spath.c_str(), tmppath1) == 0) {
2804 error << string_compose (_("Cannot expand path %1 (%2)"),
2805 spath, strerror (errno)) << endmsg;
2809 if (realpath((*i).c_str(), tmppath2) == 0) {
2810 error << string_compose (_("Cannot expand path %1 (%2)"),
2811 (*i), strerror (errno)) << endmsg;
2815 if (strcmp(tmppath1, tmppath2) == 0) {
2822 unused.push_back (spath);
2831 /* now try to move all unused files into the "dead" directory(ies) */
2833 for (vector<string>::iterator x = unused.begin(); x != unused.end(); ++x) {
2834 struct stat statbuf;
2838 /* don't move the file across filesystems, just
2839 stick it in the `dead_dir_name' directory
2840 on whichever filesystem it was already on.
2843 if ((*x).find ("/sounds/") != string::npos) {
2845 /* old school, go up 1 level */
2847 newpath = Glib::path_get_dirname (*x); // "sounds"
2848 newpath = Glib::path_get_dirname (newpath); // "session-name"
2852 /* new school, go up 4 levels */
2854 newpath = Glib::path_get_dirname (*x); // "audiofiles" or "midifiles"
2855 newpath = Glib::path_get_dirname (newpath); // "session-name"
2856 newpath = Glib::path_get_dirname (newpath); // "interchange"
2857 newpath = Glib::path_get_dirname (newpath); // "session-dir"
2860 newpath = Glib::build_filename (newpath, dead_dir_name);
2862 if (g_mkdir_with_parents (newpath.c_str(), 0755) < 0) {
2863 error << string_compose(_("Session: cannot create dead file folder \"%1\" (%2)"), newpath, strerror (errno)) << endmsg;
2867 newpath = Glib::build_filename (newpath, Glib::path_get_basename ((*x)));
2869 if (Glib::file_test (newpath, Glib::FILE_TEST_EXISTS)) {
2871 /* the new path already exists, try versioning */
2873 char buf[PATH_MAX+1];
2877 snprintf (buf, sizeof (buf), "%s.%d", newpath.c_str(), version);
2880 while (Glib::file_test (newpath_v.c_str(), Glib::FILE_TEST_EXISTS) && version < 999) {
2881 snprintf (buf, sizeof (buf), "%s.%d", newpath.c_str(), ++version);
2885 if (version == 999) {
2886 error << string_compose (_("there are already 1000 files with names like %1; versioning discontinued"),
2890 newpath = newpath_v;
2895 /* it doesn't exist, or we can't read it or something */
2899 stat ((*x).c_str(), &statbuf);
2901 if (::rename ((*x).c_str(), newpath.c_str()) != 0) {
2902 error << string_compose (_("cannot rename unused file source from %1 to %2 (%3)"),
2903 (*x), newpath, strerror (errno))
2908 /* see if there an easy to find peakfile for this file, and remove it.
2911 string base = basename_nosuffix (*x);
2912 base += "%A"; /* this is what we add for the channel suffix of all native files,
2913 or for the first channel of embedded files. it will miss
2914 some peakfiles for other channels
2916 string peakpath = peak_path (base);
2918 if (Glib::file_test (peakpath.c_str(), Glib::FILE_TEST_EXISTS)) {
2919 if (::unlink (peakpath.c_str()) != 0) {
2920 error << string_compose (_("cannot remove peakfile %1 for %2 (%3)"),
2921 peakpath, _path, strerror (errno))
2923 /* try to back out */
2924 ::rename (newpath.c_str(), _path.c_str());
2929 rep.paths.push_back (*x);
2930 rep.space += statbuf.st_size;
2933 /* dump the history list */
2937 /* save state so we don't end up a session file
2938 referring to non-existent sources.
2945 _state_of_the_state = (StateOfTheState) (_state_of_the_state & ~InCleanup);
2951 Session::cleanup_trash_sources (CleanupReport& rep)
2953 // FIXME: needs adaptation for MIDI
2955 vector<space_and_path>::iterator i;
2961 for (i = session_dirs.begin(); i != session_dirs.end(); ++i) {
2963 dead_dir = Glib::build_filename ((*i).path, dead_dir_name);
2965 clear_directory (dead_dir, &rep.space, &rep.paths);
2972 Session::set_dirty ()
2974 bool was_dirty = dirty();
2976 _state_of_the_state = StateOfTheState (_state_of_the_state | Dirty);
2980 DirtyChanged(); /* EMIT SIGNAL */
2986 Session::set_clean ()
2988 bool was_dirty = dirty();
2990 _state_of_the_state = Clean;
2994 DirtyChanged(); /* EMIT SIGNAL */
2999 Session::set_deletion_in_progress ()
3001 _state_of_the_state = StateOfTheState (_state_of_the_state | Deletion);
3005 Session::clear_deletion_in_progress ()
3007 _state_of_the_state = StateOfTheState (_state_of_the_state & (~Deletion));
3011 Session::add_controllable (boost::shared_ptr<Controllable> c)
3013 /* this adds a controllable to the list managed by the Session.
3014 this is a subset of those managed by the Controllable class
3015 itself, and represents the only ones whose state will be saved
3016 as part of the session.
3019 Glib::Threads::Mutex::Lock lm (controllables_lock);
3020 controllables.insert (c);
3023 struct null_deleter { void operator()(void const *) const {} };
3026 Session::remove_controllable (Controllable* c)
3028 if (_state_of_the_state & Deletion) {
3032 Glib::Threads::Mutex::Lock lm (controllables_lock);
3034 Controllables::iterator x = controllables.find (boost::shared_ptr<Controllable>(c, null_deleter()));
3036 if (x != controllables.end()) {
3037 controllables.erase (x);
3041 boost::shared_ptr<Controllable>
3042 Session::controllable_by_id (const PBD::ID& id)
3044 Glib::Threads::Mutex::Lock lm (controllables_lock);
3046 for (Controllables::iterator i = controllables.begin(); i != controllables.end(); ++i) {
3047 if ((*i)->id() == id) {
3052 return boost::shared_ptr<Controllable>();
3055 boost::shared_ptr<Controllable>
3056 Session::controllable_by_descriptor (const ControllableDescriptor& desc)
3058 boost::shared_ptr<Controllable> c;
3059 boost::shared_ptr<Route> r;
3061 switch (desc.top_level_type()) {
3062 case ControllableDescriptor::NamedRoute:
3064 std::string str = desc.top_level_name();
3065 if (str == "master") {
3067 } else if (str == "control" || str == "listen") {
3070 r = route_by_name (desc.top_level_name());
3075 case ControllableDescriptor::RemoteControlID:
3076 r = route_by_remote_id (desc.rid());
3084 switch (desc.subtype()) {
3085 case ControllableDescriptor::Gain:
3086 c = r->gain_control ();
3089 case ControllableDescriptor::Solo:
3090 c = r->solo_control();
3093 case ControllableDescriptor::Mute:
3094 c = r->mute_control();
3097 case ControllableDescriptor::Recenable:
3099 boost::shared_ptr<Track> t = boost::dynamic_pointer_cast<Track>(r);
3102 c = t->rec_enable_control ();
3107 case ControllableDescriptor::PanDirection:
3109 c = r->pannable()->pan_azimuth_control;
3113 case ControllableDescriptor::PanWidth:
3115 c = r->pannable()->pan_width_control;
3119 case ControllableDescriptor::PanElevation:
3121 c = r->pannable()->pan_elevation_control;
3125 case ControllableDescriptor::Balance:
3126 /* XXX simple pan control */
3129 case ControllableDescriptor::PluginParameter:
3131 uint32_t plugin = desc.target (0);
3132 uint32_t parameter_index = desc.target (1);
3134 /* revert to zero based counting */
3140 if (parameter_index > 0) {
3144 boost::shared_ptr<Processor> p = r->nth_plugin (plugin);
3147 c = boost::dynamic_pointer_cast<ARDOUR::AutomationControl>(
3148 p->control(Evoral::Parameter(PluginAutomation, 0, parameter_index)));
3153 case ControllableDescriptor::SendGain:
3155 uint32_t send = desc.target (0);
3157 /* revert to zero-based counting */
3163 boost::shared_ptr<Processor> p = r->nth_send (send);
3166 boost::shared_ptr<Send> s = boost::dynamic_pointer_cast<Send>(p);
3167 boost::shared_ptr<Amp> a = s->amp();
3170 c = s->amp()->gain_control();
3177 /* relax and return a null pointer */
3185 Session::add_instant_xml (XMLNode& node, bool write_to_config)
3188 Stateful::add_instant_xml (node, _path);
3191 if (write_to_config) {
3192 Config->add_instant_xml (node);
3197 Session::instant_xml (const string& node_name)
3199 return Stateful::instant_xml (node_name, _path);
3203 Session::save_history (string snapshot_name)
3211 if (snapshot_name.empty()) {
3212 snapshot_name = _current_snapshot_name;
3215 const string history_filename = legalize_for_path (snapshot_name) + history_suffix;
3216 const string backup_filename = history_filename + backup_suffix;
3217 const std::string xml_path(Glib::build_filename (_session_dir->root_path(), history_filename));
3218 const std::string backup_path(Glib::build_filename (_session_dir->root_path(), backup_filename));
3220 if (Glib::file_test (xml_path, Glib::FILE_TEST_EXISTS)) {
3221 if (::g_rename (xml_path.c_str(), backup_path.c_str()) != 0) {
3222 error << _("could not backup old history file, current history not saved") << endmsg;
3227 if (!Config->get_save_history() || Config->get_saved_history_depth() < 0) {
3231 tree.set_root (&_history.get_state (Config->get_saved_history_depth()));
3233 if (!tree.write (xml_path))
3235 error << string_compose (_("history could not be saved to %1"), xml_path) << endmsg;
3237 if (g_remove (xml_path.c_str()) != 0) {
3238 error << string_compose(_("Could not remove history file at path \"%1\" (%2)"),
3239 xml_path, g_strerror (errno)) << endmsg;
3241 if (::g_rename (backup_path.c_str(), xml_path.c_str()) != 0) {
3242 error << string_compose (_("could not restore history file from backup %1 (%2)"),
3243 backup_path, g_strerror (errno)) << endmsg;
3253 Session::restore_history (string snapshot_name)
3257 if (snapshot_name.empty()) {
3258 snapshot_name = _current_snapshot_name;
3261 const std::string xml_filename = legalize_for_path (snapshot_name) + history_suffix;
3262 const std::string xml_path(Glib::build_filename (_session_dir->root_path(), xml_filename));
3264 info << "Loading history from " << xml_path << endmsg;
3266 if (!Glib::file_test (xml_path, Glib::FILE_TEST_EXISTS)) {
3267 info << string_compose (_("%1: no history file \"%2\" for this session."),
3268 _name, xml_path) << endmsg;
3272 if (!tree.read (xml_path)) {
3273 error << string_compose (_("Could not understand session history file \"%1\""),
3274 xml_path) << endmsg;
3281 for (XMLNodeConstIterator it = tree.root()->children().begin(); it != tree.root()->children().end(); it++) {
3284 UndoTransaction* ut = new UndoTransaction ();
3287 ut->set_name(t->property("name")->value());
3288 stringstream ss(t->property("tv-sec")->value());
3290 ss.str(t->property("tv-usec")->value());
3292 ut->set_timestamp(tv);
3294 for (XMLNodeConstIterator child_it = t->children().begin();
3295 child_it != t->children().end(); child_it++)
3297 XMLNode *n = *child_it;
3300 if (n->name() == "MementoCommand" ||
3301 n->name() == "MementoUndoCommand" ||
3302 n->name() == "MementoRedoCommand") {
3304 if ((c = memento_command_factory(n))) {
3308 } else if (n->name() == "NoteDiffCommand") {
3309 PBD::ID id (n->property("midi-source")->value());
3310 boost::shared_ptr<MidiSource> midi_source =
3311 boost::dynamic_pointer_cast<MidiSource, Source>(source_by_id(id));
3313 ut->add_command (new MidiModel::NoteDiffCommand(midi_source->model(), *n));
3315 error << _("Failed to downcast MidiSource for NoteDiffCommand") << endmsg;
3318 } else if (n->name() == "SysExDiffCommand") {
3320 PBD::ID id (n->property("midi-source")->value());
3321 boost::shared_ptr<MidiSource> midi_source =
3322 boost::dynamic_pointer_cast<MidiSource, Source>(source_by_id(id));
3324 ut->add_command (new MidiModel::SysExDiffCommand (midi_source->model(), *n));
3326 error << _("Failed to downcast MidiSource for SysExDiffCommand") << endmsg;
3329 } else if (n->name() == "PatchChangeDiffCommand") {
3331 PBD::ID id (n->property("midi-source")->value());
3332 boost::shared_ptr<MidiSource> midi_source =
3333 boost::dynamic_pointer_cast<MidiSource, Source>(source_by_id(id));
3335 ut->add_command (new MidiModel::PatchChangeDiffCommand (midi_source->model(), *n));
3337 error << _("Failed to downcast MidiSource for PatchChangeDiffCommand") << endmsg;
3340 } else if (n->name() == "StatefulDiffCommand") {
3341 if ((c = stateful_diff_command_factory (n))) {
3342 ut->add_command (c);
3345 error << string_compose(_("Couldn't figure out how to make a Command out of a %1 XMLNode."), n->name()) << endmsg;
3356 Session::config_changed (std::string p, bool ours)
3362 if (p == "seamless-loop") {
3364 } else if (p == "rf-speed") {
3366 } else if (p == "auto-loop") {
3368 } else if (p == "auto-input") {
3370 if (Config->get_monitoring_model() == HardwareMonitoring && transport_rolling()) {
3371 /* auto-input only makes a difference if we're rolling */
3372 set_track_monitor_input_status (!config.get_auto_input());
3375 } else if (p == "punch-in") {
3379 if ((location = _locations->auto_punch_location()) != 0) {
3381 if (config.get_punch_in ()) {
3382 replace_event (SessionEvent::PunchIn, location->start());
3384 remove_event (location->start(), SessionEvent::PunchIn);
3388 } else if (p == "punch-out") {
3392 if ((location = _locations->auto_punch_location()) != 0) {
3394 if (config.get_punch_out()) {
3395 replace_event (SessionEvent::PunchOut, location->end());
3397 clear_events (SessionEvent::PunchOut);
3401 } else if (p == "edit-mode") {
3403 Glib::Threads::Mutex::Lock lm (playlists->lock);
3405 for (SessionPlaylists::List::iterator i = playlists->playlists.begin(); i != playlists->playlists.end(); ++i) {
3406 (*i)->set_edit_mode (Config->get_edit_mode ());
3409 } else if (p == "use-video-sync") {
3411 waiting_for_sync_offset = config.get_use_video_sync();
3413 } else if (p == "mmc-control") {
3415 //poke_midi_thread ();
3417 } else if (p == "mmc-device-id" || p == "mmc-receive-id" || p == "mmc-receive-device-id") {
3419 MIDI::Manager::instance()->mmc()->set_receive_device_id (Config->get_mmc_receive_device_id());
3421 } else if (p == "mmc-send-id" || p == "mmc-send-device-id") {
3423 MIDI::Manager::instance()->mmc()->set_send_device_id (Config->get_mmc_send_device_id());
3425 } else if (p == "midi-control") {
3427 //poke_midi_thread ();
3429 } else if (p == "raid-path") {
3431 setup_raid_path (config.get_raid_path());
3433 } else if (p == "timecode-format") {
3437 } else if (p == "video-pullup") {
3441 } else if (p == "seamless-loop") {
3443 if (play_loop && transport_rolling()) {
3444 // to reset diskstreams etc
3445 request_play_loop (true);
3448 } else if (p == "rf-speed") {
3450 cumulative_rf_motion = 0;
3453 } else if (p == "click-sound") {
3455 setup_click_sounds (1);
3457 } else if (p == "click-emphasis-sound") {
3459 setup_click_sounds (-1);
3461 } else if (p == "clicking") {
3463 if (Config->get_clicking()) {
3464 if (_click_io && click_data) { // don't require emphasis data
3471 } else if (p == "click-gain") {
3474 _click_gain->set_gain (Config->get_click_gain(), this);
3477 } else if (p == "send-mtc") {
3479 if (Config->get_send_mtc ()) {
3480 /* mark us ready to send */
3481 next_quarter_frame_to_send = 0;
3484 } else if (p == "send-mmc") {
3486 MIDI::Manager::instance()->mmc()->enable_send (Config->get_send_mmc ());
3488 } else if (p == "midi-feedback") {
3490 session_midi_feedback = Config->get_midi_feedback();
3492 } else if (p == "jack-time-master") {
3494 engine().reset_timebase ();
3496 } else if (p == "native-file-header-format") {
3498 if (!first_file_header_format_reset) {
3499 reset_native_file_format ();
3502 first_file_header_format_reset = false;
3504 } else if (p == "native-file-data-format") {
3506 if (!first_file_data_format_reset) {
3507 reset_native_file_format ();
3510 first_file_data_format_reset = false;
3512 } else if (p == "external-sync") {
3513 if (!config.get_external_sync()) {
3514 drop_sync_source ();
3516 switch_to_sync_source (Config->get_sync_source());
3518 } else if (p == "denormal-model") {
3520 } else if (p == "history-depth") {
3521 set_history_depth (Config->get_history_depth());
3522 } else if (p == "remote-model") {
3523 /* XXX DO SOMETHING HERE TO TELL THE GUI THAT WE NEED
3526 } else if (p == "sync-all-route-ordering") {
3528 /* sync to editor order unless mixer is used for remote IDs
3531 switch (Config->get_remote_model()) {
3533 sync_order_keys (EditorSort);
3536 sync_order_keys (EditorSort);
3539 sync_order_keys (MixerSort);
3542 } else if (p == "initial-program-change") {
3544 if (MIDI::Manager::instance()->mmc()->output_port() && Config->get_initial_program_change() >= 0) {
3547 buf[0] = MIDI::program; // channel zero by default
3548 buf[1] = (Config->get_initial_program_change() & 0x7f);
3550 MIDI::Manager::instance()->mmc()->output_port()->midimsg (buf, sizeof (buf), 0);
3552 } else if (p == "solo-mute-override") {
3553 // catch_up_on_solo_mute_override ();
3554 } else if (p == "listen-position" || p == "pfl-position") {
3555 listen_position_changed ();
3556 } else if (p == "solo-control-is-listen-control") {
3557 solo_control_mode_changed ();
3558 } else if (p == "timecode-offset" || p == "timecode-offset-negative") {
3559 last_timecode_valid = false;
3560 } else if (p == "playback-buffer-seconds") {
3561 AudioSource::allocate_working_buffers (frame_rate());
3562 } else if (p == "automation-thinning-factor") {
3563 Evoral::ControlList::set_thinning_factor (Config->get_automation_thinning_factor());
3564 } else if (p == "ltc-source-port") {
3565 reconnect_ltc_input ();
3566 } else if (p == "ltc-sink-port") {
3567 reconnect_ltc_output ();
3569 } else if (p == "timecode-generator-offset") {
3570 ltc_tx_parse_offset();
3578 Session::set_history_depth (uint32_t d)
3580 _history.set_depth (d);
3584 Session::load_diskstreams_2X (XMLNode const & node, int)
3587 XMLNodeConstIterator citer;
3589 clist = node.children();
3591 for (citer = clist.begin(); citer != clist.end(); ++citer) {
3594 /* diskstreams added automatically by DiskstreamCreated handler */
3595 if ((*citer)->name() == "AudioDiskstream" || (*citer)->name() == "DiskStream") {
3596 boost::shared_ptr<AudioDiskstream> dsp (new AudioDiskstream (*this, **citer));
3597 _diskstreams_2X.push_back (dsp);
3599 error << _("Session: unknown diskstream type in XML") << endmsg;
3603 catch (failed_constructor& err) {
3604 error << _("Session: could not load diskstream via XML state") << endmsg;
3612 /** Connect things to the MMC object */
3614 Session::setup_midi_machine_control ()
3616 MIDI::MachineControl* mmc = MIDI::Manager::instance()->mmc ();
3618 mmc->Play.connect_same_thread (*this, boost::bind (&Session::mmc_deferred_play, this, _1));
3619 mmc->DeferredPlay.connect_same_thread (*this, boost::bind (&Session::mmc_deferred_play, this, _1));
3620 mmc->Stop.connect_same_thread (*this, boost::bind (&Session::mmc_stop, this, _1));
3621 mmc->FastForward.connect_same_thread (*this, boost::bind (&Session::mmc_fast_forward, this, _1));
3622 mmc->Rewind.connect_same_thread (*this, boost::bind (&Session::mmc_rewind, this, _1));
3623 mmc->Pause.connect_same_thread (*this, boost::bind (&Session::mmc_pause, this, _1));
3624 mmc->RecordPause.connect_same_thread (*this, boost::bind (&Session::mmc_record_pause, this, _1));
3625 mmc->RecordStrobe.connect_same_thread (*this, boost::bind (&Session::mmc_record_strobe, this, _1));
3626 mmc->RecordExit.connect_same_thread (*this, boost::bind (&Session::mmc_record_exit, this, _1));
3627 mmc->Locate.connect_same_thread (*this, boost::bind (&Session::mmc_locate, this, _1, _2));
3628 mmc->Step.connect_same_thread (*this, boost::bind (&Session::mmc_step, this, _1, _2));
3629 mmc->Shuttle.connect_same_thread (*this, boost::bind (&Session::mmc_shuttle, this, _1, _2, _3));
3630 mmc->TrackRecordStatusChange.connect_same_thread (*this, boost::bind (&Session::mmc_record_enable, this, _1, _2, _3));
3632 /* also handle MIDI SPP because its so common */
3634 mmc->SPPStart.connect_same_thread (*this, boost::bind (&Session::spp_start, this));
3635 mmc->SPPContinue.connect_same_thread (*this, boost::bind (&Session::spp_continue, this));
3636 mmc->SPPStop.connect_same_thread (*this, boost::bind (&Session::spp_stop, this));
3639 boost::shared_ptr<Controllable>
3640 Session::solo_cut_control() const
3642 /* the solo cut control is a bit of an anomaly, at least as of Febrary 2011. There are no other
3643 controls in Ardour that currently get presented to the user in the GUI that require
3644 access as a Controllable and are also NOT owned by some SessionObject (e.g. Route, or MonitorProcessor).
3646 its actually an RCConfiguration parameter, so we use a ProxyControllable to wrap
3647 it up as a Controllable. Changes to the Controllable will just map back to the RCConfiguration
3651 return _solo_cut_control;
3655 Session::rename (const std::string& new_name)
3657 string legal_name = legalize_for_path (new_name);
3663 string const old_sources_root = _session_dir->sources_root();
3665 #define RENAME ::rename
3670 * interchange subdirectory
3674 * Backup files are left unchanged and not renamed.
3677 /* pass one: not 100% safe check that the new directory names don't
3681 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
3686 /* this is a stupid hack because Glib::path_get_dirname() is
3687 * lexical-only, and so passing it /a/b/c/ gives a different
3688 * result than passing it /a/b/c ...
3691 if (oldstr[oldstr.length()-1] == G_DIR_SEPARATOR) {
3692 oldstr = oldstr.substr (0, oldstr.length() - 1);
3695 string base = Glib::path_get_dirname (oldstr);
3696 string p = Glib::path_get_basename (oldstr);
3698 newstr = Glib::build_filename (base, legal_name);
3700 if (Glib::file_test (newstr, Glib::FILE_TEST_EXISTS)) {
3707 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
3712 /* this is a stupid hack because Glib::path_get_dirname() is
3713 * lexical-only, and so passing it /a/b/c/ gives a different
3714 * result than passing it /a/b/c ...
3717 if (oldstr[oldstr.length()-1] == G_DIR_SEPARATOR) {
3718 oldstr = oldstr.substr (0, oldstr.length() - 1);
3721 string base = Glib::path_get_dirname (oldstr);
3722 string p = Glib::path_get_basename (oldstr);
3724 newstr = Glib::build_filename (base, legal_name);
3726 cerr << "Rename " << oldstr << " => " << newstr << endl;
3728 if (RENAME (oldstr.c_str(), newstr.c_str()) != 0) {
3733 (*_session_dir) = newstr;
3738 /* directory below interchange */
3740 v.push_back (newstr);
3741 v.push_back (interchange_dir_name);
3744 oldstr = Glib::build_filename (v);
3747 v.push_back (newstr);
3748 v.push_back (interchange_dir_name);
3749 v.push_back (legal_name);
3751 newstr = Glib::build_filename (v);
3753 cerr << "Rename " << oldstr << " => " << newstr << endl;
3755 if (RENAME (oldstr.c_str(), newstr.c_str()) != 0) {
3762 oldstr = Glib::build_filename (newpath, _current_snapshot_name) + statefile_suffix;
3763 newstr= Glib::build_filename (newpath, legal_name) + statefile_suffix;
3765 cerr << "Rename " << oldstr << " => " << newstr << endl;
3767 if (RENAME (oldstr.c_str(), newstr.c_str()) != 0) {
3774 oldstr = Glib::build_filename (newpath, _current_snapshot_name) + history_suffix;
3776 if (Glib::file_test (oldstr, Glib::FILE_TEST_EXISTS)) {
3777 newstr = Glib::build_filename (newpath, legal_name) + history_suffix;
3779 cerr << "Rename " << oldstr << " => " << newstr << endl;
3781 if (RENAME (oldstr.c_str(), newstr.c_str()) != 0) {
3786 /* update file source paths */
3788 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ++i) {
3789 boost::shared_ptr<FileSource> fs = boost::dynamic_pointer_cast<FileSource> (i->second);
3791 string p = fs->path ();
3792 boost::replace_all (p, old_sources_root, _session_dir->sources_root());
3797 /* remove old name from recent sessions */
3799 remove_recent_sessions (_path);
3802 _current_snapshot_name = new_name;
3807 /* save state again to get everything just right */
3809 save_state (_current_snapshot_name);
3812 /* add to recent sessions */
3814 store_recent_sessions (new_name, _path);