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));
1164 node->add_child_nocopy (_speakers->get_state());
1165 node->add_child_nocopy (_tempo_map->get_state());
1166 node->add_child_nocopy (get_control_protocol_state());
1169 node->add_child_copy (*_extra_xml);
1176 Session::get_control_protocol_state ()
1178 ControlProtocolManager& cpm (ControlProtocolManager::instance());
1179 return cpm.get_state();
1183 Session::set_state (const XMLNode& node, int version)
1187 const XMLProperty* prop;
1190 _state_of_the_state = StateOfTheState (_state_of_the_state|CannotSave);
1192 if (node.name() != X_("Session")) {
1193 fatal << _("programming error: Session: incorrect XML node sent to set_state()") << endmsg;
1197 if ((prop = node.property ("name")) != 0) {
1198 _name = prop->value ();
1201 if ((prop = node.property (X_("sample-rate"))) != 0) {
1203 _nominal_frame_rate = atoi (prop->value());
1205 if (_nominal_frame_rate != _current_frame_rate) {
1206 boost::optional<int> r = AskAboutSampleRateMismatch (_nominal_frame_rate, _current_frame_rate);
1207 if (r.get_value_or (0)) {
1213 setup_raid_path(_session_dir->root_path());
1215 if ((prop = node.property (X_("id-counter"))) != 0) {
1217 sscanf (prop->value().c_str(), "%" PRIu64, &x);
1218 ID::init_counter (x);
1220 /* old sessions used a timebased counter, so fake
1221 the startup ID counter based on a standard
1226 ID::init_counter (now);
1229 if ((prop = node.property (X_("event-counter"))) != 0) {
1230 Evoral::init_event_id_counter (atoi (prop->value()));
1233 IO::disable_connecting ();
1235 Stateful::save_extra_xml (node);
1237 if (((child = find_named_node (node, "Options")) != 0)) { /* old style */
1238 load_options (*child);
1239 } else if ((child = find_named_node (node, "Config")) != 0) { /* new style */
1240 load_options (*child);
1242 error << _("Session: XML state has no options section") << endmsg;
1245 if (version >= 3000) {
1246 if ((child = find_named_node (node, "Metadata")) == 0) {
1247 warning << _("Session: XML state has no metadata section") << endmsg;
1248 } else if ( ARDOUR::SessionMetadata::Metadata()->set_state (*child, version) ) {
1253 if ((child = find_named_node (node, X_("Speakers"))) != 0) {
1254 _speakers->set_state (*child, version);
1257 if ((child = find_named_node (node, "Sources")) == 0) {
1258 error << _("Session: XML state has no sources section") << endmsg;
1260 } else if (load_sources (*child)) {
1264 if ((child = find_named_node (node, "TempoMap")) == 0) {
1265 error << _("Session: XML state has no Tempo Map section") << endmsg;
1267 } else if (_tempo_map->set_state (*child, version)) {
1271 if ((child = find_named_node (node, "Locations")) == 0) {
1272 error << _("Session: XML state has no locations section") << endmsg;
1274 } else if (_locations->set_state (*child, version)) {
1280 if ((location = _locations->auto_loop_location()) != 0) {
1281 set_auto_loop_location (location);
1284 if ((location = _locations->auto_punch_location()) != 0) {
1285 set_auto_punch_location (location);
1288 if ((location = _locations->session_range_location()) != 0) {
1289 delete _session_range_location;
1290 _session_range_location = location;
1293 if (_session_range_location) {
1294 AudioFileSource::set_header_position_offset (_session_range_location->start());
1297 if ((child = find_named_node (node, "Regions")) == 0) {
1298 error << _("Session: XML state has no Regions section") << endmsg;
1300 } else if (load_regions (*child)) {
1304 if ((child = find_named_node (node, "Playlists")) == 0) {
1305 error << _("Session: XML state has no playlists section") << endmsg;
1307 } else if (playlists->load (*this, *child)) {
1311 if ((child = find_named_node (node, "UnusedPlaylists")) == 0) {
1313 } else if (playlists->load_unused (*this, *child)) {
1317 if ((child = find_named_node (node, "CompoundAssociations")) != 0) {
1318 if (load_compounds (*child)) {
1323 if (version >= 3000) {
1324 if ((child = find_named_node (node, "Bundles")) == 0) {
1325 warning << _("Session: XML state has no bundles section") << endmsg;
1328 /* We can't load Bundles yet as they need to be able
1329 to convert from port names to Port objects, which can't happen until
1331 _bundle_xml_node = new XMLNode (*child);
1335 if (version < 3000) {
1336 if ((child = find_named_node (node, X_("DiskStreams"))) == 0) {
1337 error << _("Session: XML state has no diskstreams section") << endmsg;
1339 } else if (load_diskstreams_2X (*child, version)) {
1344 if ((child = find_named_node (node, "Routes")) == 0) {
1345 error << _("Session: XML state has no routes section") << endmsg;
1347 } else if (load_routes (*child, version)) {
1351 /* our diskstreams list is no longer needed as they are now all owned by their Route */
1352 _diskstreams_2X.clear ();
1354 if (version >= 3000) {
1356 if ((child = find_named_node (node, "RouteGroups")) == 0) {
1357 error << _("Session: XML state has no route groups section") << endmsg;
1359 } else if (load_route_groups (*child, version)) {
1363 } else if (version < 3000) {
1365 if ((child = find_named_node (node, "EditGroups")) == 0) {
1366 error << _("Session: XML state has no edit groups section") << endmsg;
1368 } else if (load_route_groups (*child, version)) {
1372 if ((child = find_named_node (node, "MixGroups")) == 0) {
1373 error << _("Session: XML state has no mix groups section") << endmsg;
1375 } else if (load_route_groups (*child, version)) {
1380 if ((child = find_named_node (node, "Click")) == 0) {
1381 warning << _("Session: XML state has no click section") << endmsg;
1382 } else if (_click_io) {
1383 const XMLNodeList& children (child->children());
1384 XMLNodeList::const_iterator i = children.begin();
1385 _click_io->set_state (**i, version);
1387 if (i != children.end()) {
1388 _click_gain->set_state (**i, version);
1392 if ((child = find_named_node (node, ControlProtocolManager::state_node_name)) != 0) {
1393 ControlProtocolManager::instance().set_state (*child, version);
1396 update_have_rec_enabled_track ();
1398 /* here beginneth the second phase ... */
1400 StateReady (); /* EMIT SIGNAL */
1409 Session::load_routes (const XMLNode& node, int version)
1412 XMLNodeConstIterator niter;
1413 RouteList new_routes;
1415 nlist = node.children();
1419 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1421 boost::shared_ptr<Route> route;
1422 if (version < 3000) {
1423 route = XMLRouteFactory_2X (**niter, version);
1425 route = XMLRouteFactory (**niter, version);
1429 error << _("Session: cannot create Route from XML description.") << endmsg;
1433 BootMessage (string_compose (_("Loaded track/bus %1"), route->name()));
1435 new_routes.push_back (route);
1438 add_routes (new_routes, false, false, false);
1443 boost::shared_ptr<Route>
1444 Session::XMLRouteFactory (const XMLNode& node, int version)
1446 boost::shared_ptr<Route> ret;
1448 if (node.name() != "Route") {
1452 XMLNode* ds_child = find_named_node (node, X_("Diskstream"));
1454 DataType type = DataType::AUDIO;
1455 const XMLProperty* prop = node.property("default-type");
1458 type = DataType (prop->value());
1461 assert (type != DataType::NIL);
1465 boost::shared_ptr<Track> track;
1467 if (type == DataType::AUDIO) {
1468 track.reset (new AudioTrack (*this, X_("toBeResetFroXML")));
1470 track.reset (new MidiTrack (*this, X_("toBeResetFroXML")));
1473 if (track->init()) {
1477 if (track->set_state (node, version)) {
1481 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
1482 // boost_debug_shared_ptr_mark_interesting (track.get(), "Track");
1487 boost::shared_ptr<Route> r (new Route (*this, X_("toBeResetFroXML")));
1489 if (r->init () == 0 && r->set_state (node, version) == 0) {
1490 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
1491 // boost_debug_shared_ptr_mark_interesting (r.get(), "Route");
1500 boost::shared_ptr<Route>
1501 Session::XMLRouteFactory_2X (const XMLNode& node, int version)
1503 boost::shared_ptr<Route> ret;
1505 if (node.name() != "Route") {
1509 XMLProperty const * ds_prop = node.property (X_("diskstream-id"));
1511 ds_prop = node.property (X_("diskstream"));
1514 DataType type = DataType::AUDIO;
1515 const XMLProperty* prop = node.property("default-type");
1518 type = DataType (prop->value());
1521 assert (type != DataType::NIL);
1525 list<boost::shared_ptr<Diskstream> >::iterator i = _diskstreams_2X.begin ();
1526 while (i != _diskstreams_2X.end() && (*i)->id() != ds_prop->value()) {
1530 if (i == _diskstreams_2X.end()) {
1531 error << _("Could not find diskstream for route") << endmsg;
1532 return boost::shared_ptr<Route> ();
1535 boost::shared_ptr<Track> track;
1537 if (type == DataType::AUDIO) {
1538 track.reset (new AudioTrack (*this, X_("toBeResetFroXML")));
1540 track.reset (new MidiTrack (*this, X_("toBeResetFroXML")));
1543 if (track->init()) {
1547 if (track->set_state (node, version)) {
1551 track->set_diskstream (*i);
1553 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
1554 // boost_debug_shared_ptr_mark_interesting (track.get(), "Track");
1559 boost::shared_ptr<Route> r (new Route (*this, X_("toBeResetFroXML")));
1561 if (r->init () == 0 && r->set_state (node, version) == 0) {
1562 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
1563 // boost_debug_shared_ptr_mark_interesting (r.get(), "Route");
1573 Session::load_regions (const XMLNode& node)
1576 XMLNodeConstIterator niter;
1577 boost::shared_ptr<Region> region;
1579 nlist = node.children();
1583 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1584 if ((region = XMLRegionFactory (**niter, false)) == 0) {
1585 error << _("Session: cannot create Region from XML description.");
1586 const XMLProperty *name = (**niter).property("name");
1589 error << " " << string_compose (_("Can not load state for region '%1'"), name->value());
1600 Session::load_compounds (const XMLNode& node)
1602 XMLNodeList calist = node.children();
1603 XMLNodeConstIterator caiter;
1604 XMLProperty *caprop;
1606 for (caiter = calist.begin(); caiter != calist.end(); ++caiter) {
1607 XMLNode* ca = *caiter;
1611 if ((caprop = ca->property (X_("original"))) == 0) {
1614 orig_id = caprop->value();
1616 if ((caprop = ca->property (X_("copy"))) == 0) {
1619 copy_id = caprop->value();
1621 boost::shared_ptr<Region> orig = RegionFactory::region_by_id (orig_id);
1622 boost::shared_ptr<Region> copy = RegionFactory::region_by_id (copy_id);
1624 if (!orig || !copy) {
1625 warning << string_compose (_("Regions in compound description not found (ID's %1 and %2): ignored"),
1631 RegionFactory::add_compound_association (orig, copy);
1638 Session::load_nested_sources (const XMLNode& node)
1641 XMLNodeConstIterator niter;
1643 nlist = node.children();
1645 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1646 if ((*niter)->name() == "Source") {
1648 /* it may already exist, so don't recreate it unnecessarily
1651 XMLProperty* prop = (*niter)->property (X_("id"));
1653 error << _("Nested source has no ID info in session state file! (ignored)") << endmsg;
1657 ID source_id (prop->value());
1659 if (!source_by_id (source_id)) {
1662 SourceFactory::create (*this, **niter, true);
1664 catch (failed_constructor& err) {
1665 error << string_compose (_("Cannot reconstruct nested source for region %1"), name()) << endmsg;
1672 boost::shared_ptr<Region>
1673 Session::XMLRegionFactory (const XMLNode& node, bool full)
1675 const XMLProperty* type = node.property("type");
1679 const XMLNodeList& nlist = node.children();
1681 for (XMLNodeConstIterator niter = nlist.begin(); niter != nlist.end(); ++niter) {
1682 XMLNode *child = (*niter);
1683 if (child->name() == "NestedSource") {
1684 load_nested_sources (*child);
1688 if (!type || type->value() == "audio") {
1689 return boost::shared_ptr<Region>(XMLAudioRegionFactory (node, full));
1690 } else if (type->value() == "midi") {
1691 return boost::shared_ptr<Region>(XMLMidiRegionFactory (node, full));
1694 } catch (failed_constructor& err) {
1695 return boost::shared_ptr<Region> ();
1698 return boost::shared_ptr<Region> ();
1701 boost::shared_ptr<AudioRegion>
1702 Session::XMLAudioRegionFactory (const XMLNode& node, bool /*full*/)
1704 const XMLProperty* prop;
1705 boost::shared_ptr<Source> source;
1706 boost::shared_ptr<AudioSource> as;
1708 SourceList master_sources;
1709 uint32_t nchans = 1;
1712 if (node.name() != X_("Region")) {
1713 return boost::shared_ptr<AudioRegion>();
1716 if ((prop = node.property (X_("channels"))) != 0) {
1717 nchans = atoi (prop->value().c_str());
1720 if ((prop = node.property ("name")) == 0) {
1721 cerr << "no name for this region\n";
1725 if ((prop = node.property (X_("source-0"))) == 0) {
1726 if ((prop = node.property ("source")) == 0) {
1727 error << _("Session: XMLNode describing a AudioRegion is incomplete (no source)") << endmsg;
1728 return boost::shared_ptr<AudioRegion>();
1732 PBD::ID s_id (prop->value());
1734 if ((source = source_by_id (s_id)) == 0) {
1735 error << string_compose(_("Session: XMLNode describing a AudioRegion references an unknown source id =%1"), s_id) << endmsg;
1736 return boost::shared_ptr<AudioRegion>();
1739 as = boost::dynamic_pointer_cast<AudioSource>(source);
1741 error << string_compose(_("Session: XMLNode describing a AudioRegion references a non-audio source id =%1"), s_id) << endmsg;
1742 return boost::shared_ptr<AudioRegion>();
1745 sources.push_back (as);
1747 /* pickup other channels */
1749 for (uint32_t n=1; n < nchans; ++n) {
1750 snprintf (buf, sizeof(buf), X_("source-%d"), n);
1751 if ((prop = node.property (buf)) != 0) {
1753 PBD::ID id2 (prop->value());
1755 if ((source = source_by_id (id2)) == 0) {
1756 error << string_compose(_("Session: XMLNode describing a AudioRegion references an unknown source id =%1"), id2) << endmsg;
1757 return boost::shared_ptr<AudioRegion>();
1760 as = boost::dynamic_pointer_cast<AudioSource>(source);
1762 error << string_compose(_("Session: XMLNode describing a AudioRegion references a non-audio source id =%1"), id2) << endmsg;
1763 return boost::shared_ptr<AudioRegion>();
1765 sources.push_back (as);
1769 for (uint32_t n = 0; n < nchans; ++n) {
1770 snprintf (buf, sizeof(buf), X_("master-source-%d"), n);
1771 if ((prop = node.property (buf)) != 0) {
1773 PBD::ID id2 (prop->value());
1775 if ((source = source_by_id (id2)) == 0) {
1776 error << string_compose(_("Session: XMLNode describing a AudioRegion references an unknown source id =%1"), id2) << endmsg;
1777 return boost::shared_ptr<AudioRegion>();
1780 as = boost::dynamic_pointer_cast<AudioSource>(source);
1782 error << string_compose(_("Session: XMLNode describing a AudioRegion references a non-audio source id =%1"), id2) << endmsg;
1783 return boost::shared_ptr<AudioRegion>();
1785 master_sources.push_back (as);
1790 boost::shared_ptr<AudioRegion> region (boost::dynamic_pointer_cast<AudioRegion> (RegionFactory::create (sources, node)));
1792 /* a final detail: this is the one and only place that we know how long missing files are */
1794 if (region->whole_file()) {
1795 for (SourceList::iterator sx = sources.begin(); sx != sources.end(); ++sx) {
1796 boost::shared_ptr<SilentFileSource> sfp = boost::dynamic_pointer_cast<SilentFileSource> (*sx);
1798 sfp->set_length (region->length());
1803 if (!master_sources.empty()) {
1804 if (master_sources.size() != nchans) {
1805 error << _("Session: XMLNode describing an AudioRegion is missing some master sources; ignored") << endmsg;
1807 region->set_master_sources (master_sources);
1815 catch (failed_constructor& err) {
1816 return boost::shared_ptr<AudioRegion>();
1820 boost::shared_ptr<MidiRegion>
1821 Session::XMLMidiRegionFactory (const XMLNode& node, bool /*full*/)
1823 const XMLProperty* prop;
1824 boost::shared_ptr<Source> source;
1825 boost::shared_ptr<MidiSource> ms;
1828 if (node.name() != X_("Region")) {
1829 return boost::shared_ptr<MidiRegion>();
1832 if ((prop = node.property ("name")) == 0) {
1833 cerr << "no name for this region\n";
1837 if ((prop = node.property (X_("source-0"))) == 0) {
1838 if ((prop = node.property ("source")) == 0) {
1839 error << _("Session: XMLNode describing a MidiRegion is incomplete (no source)") << endmsg;
1840 return boost::shared_ptr<MidiRegion>();
1844 PBD::ID s_id (prop->value());
1846 if ((source = source_by_id (s_id)) == 0) {
1847 error << string_compose(_("Session: XMLNode describing a MidiRegion references an unknown source id =%1"), s_id) << endmsg;
1848 return boost::shared_ptr<MidiRegion>();
1851 ms = boost::dynamic_pointer_cast<MidiSource>(source);
1853 error << string_compose(_("Session: XMLNode describing a MidiRegion references a non-midi source id =%1"), s_id) << endmsg;
1854 return boost::shared_ptr<MidiRegion>();
1857 sources.push_back (ms);
1860 boost::shared_ptr<MidiRegion> region (boost::dynamic_pointer_cast<MidiRegion> (RegionFactory::create (sources, node)));
1861 /* a final detail: this is the one and only place that we know how long missing files are */
1863 if (region->whole_file()) {
1864 for (SourceList::iterator sx = sources.begin(); sx != sources.end(); ++sx) {
1865 boost::shared_ptr<SilentFileSource> sfp = boost::dynamic_pointer_cast<SilentFileSource> (*sx);
1867 sfp->set_length (region->length());
1875 catch (failed_constructor& err) {
1876 return boost::shared_ptr<MidiRegion>();
1881 Session::get_sources_as_xml ()
1884 XMLNode* node = new XMLNode (X_("Sources"));
1885 Glib::Threads::Mutex::Lock lm (source_lock);
1887 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ++i) {
1888 node->add_child_nocopy (i->second->get_state());
1895 Session::path_from_region_name (DataType type, string name, string identifier)
1897 char buf[PATH_MAX+1];
1899 SessionDirectory sdir(get_best_session_directory_for_new_source());
1900 std::string source_dir = ((type == DataType::AUDIO)
1901 ? sdir.sound_path() : sdir.midi_path());
1903 string ext = native_header_format_extension (config.get_native_file_header_format(), type);
1905 for (n = 0; n < 999999; ++n) {
1906 if (identifier.length()) {
1907 snprintf (buf, sizeof(buf), "%s%s%" PRIu32 "%s", name.c_str(),
1908 identifier.c_str(), n, ext.c_str());
1910 snprintf (buf, sizeof(buf), "%s-%" PRIu32 "%s", name.c_str(),
1914 std::string source_path = Glib::build_filename (source_dir, buf);
1916 if (!Glib::file_test (source_path, Glib::FILE_TEST_EXISTS)) {
1921 error << string_compose (_("cannot create new file from region name \"%1\" with ident = \"%2\": too many existing files with similar names"),
1930 Session::load_sources (const XMLNode& node)
1933 XMLNodeConstIterator niter;
1934 boost::shared_ptr<Source> source;
1936 nlist = node.children();
1940 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1943 if ((source = XMLSourceFactory (**niter)) == 0) {
1944 error << _("Session: cannot create Source from XML description.") << endmsg;
1947 } catch (MissingSource& err) {
1951 if (!no_questions_about_missing_files) {
1952 user_choice = MissingFile (this, err.path, err.type).get_value_or (-1);
1957 switch (user_choice) {
1959 /* user added a new search location, so try again */
1964 /* user asked to quit the entire session load
1969 no_questions_about_missing_files = true;
1973 no_questions_about_missing_files = true;
1978 warning << _("A sound file is missing. It will be replaced by silence.") << endmsg;
1979 source = SourceFactory::createSilent (*this, **niter, max_framecnt, _current_frame_rate);
1988 boost::shared_ptr<Source>
1989 Session::XMLSourceFactory (const XMLNode& node)
1991 if (node.name() != "Source") {
1992 return boost::shared_ptr<Source>();
1996 /* note: do peak building in another thread when loading session state */
1997 return SourceFactory::create (*this, node, true);
2000 catch (failed_constructor& err) {
2001 error << string_compose (_("Found a sound file that cannot be used by %1. Talk to the progammers."), PROGRAM_NAME) << endmsg;
2002 return boost::shared_ptr<Source>();
2007 Session::save_template (string template_name)
2011 if (_state_of_the_state & CannotSave) {
2015 std::string user_template_dir(user_template_directory());
2017 if (g_mkdir_with_parents (user_template_dir.c_str(), 0755) != 0) {
2018 error << string_compose(_("Could not create templates directory \"%1\" (%2)"),
2019 user_template_dir, g_strerror (errno)) << endmsg;
2023 tree.set_root (&get_template());
2025 std::string template_dir_path(user_template_dir);
2027 /* directory to put the template in */
2028 template_dir_path = Glib::build_filename (template_dir_path, template_name);
2030 if (Glib::file_test (template_dir_path, Glib::FILE_TEST_EXISTS)) {
2031 warning << string_compose(_("Template \"%1\" already exists - new version not created"),
2032 template_dir_path) << endmsg;
2036 if (g_mkdir_with_parents (template_dir_path.c_str(), 0755) != 0) {
2037 error << string_compose(_("Could not create directory for Session template\"%1\" (%2)"),
2038 template_dir_path, g_strerror (errno)) << endmsg;
2043 std::string template_file_path(template_dir_path);
2044 template_file_path = Glib::build_filename (template_file_path, template_name + template_suffix);
2046 if (!tree.write (template_file_path)) {
2047 error << _("template not saved") << endmsg;
2051 /* copy plugin state directory */
2053 std::string template_plugin_state_path(template_dir_path);
2054 template_plugin_state_path = Glib::build_filename (template_plugin_state_path, X_("plugins"));
2056 if (g_mkdir_with_parents (template_plugin_state_path.c_str(), 0755) != 0) {
2057 error << string_compose(_("Could not create directory for Session template plugin state\"%1\" (%2)"),
2058 template_plugin_state_path, g_strerror (errno)) << endmsg;
2062 copy_files (plugins_dir(), template_plugin_state_path);
2068 Session::refresh_disk_space ()
2070 #if HAVE_SYS_VFS_H && HAVE_SYS_STATVFS_H
2072 Glib::Threads::Mutex::Lock lm (space_lock);
2074 /* get freespace on every FS that is part of the session path */
2076 _total_free_4k_blocks = 0;
2077 _total_free_4k_blocks_uncertain = false;
2079 for (vector<space_and_path>::iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
2081 struct statfs statfsbuf;
2082 statfs (i->path.c_str(), &statfsbuf);
2084 double const scale = statfsbuf.f_bsize / 4096.0;
2086 /* See if this filesystem is read-only */
2087 struct statvfs statvfsbuf;
2088 statvfs (i->path.c_str(), &statvfsbuf);
2090 /* f_bavail can be 0 if it is undefined for whatever
2091 filesystem we are looking at; Samba shares mounted
2092 via GVFS are an example of this.
2094 if (statfsbuf.f_bavail == 0) {
2095 /* block count unknown */
2097 i->blocks_unknown = true;
2098 } else if (statvfsbuf.f_flag & ST_RDONLY) {
2099 /* read-only filesystem */
2101 i->blocks_unknown = false;
2103 /* read/write filesystem with known space */
2104 i->blocks = (uint32_t) floor (statfsbuf.f_bavail * scale);
2105 i->blocks_unknown = false;
2108 _total_free_4k_blocks += i->blocks;
2109 if (i->blocks_unknown) {
2110 _total_free_4k_blocks_uncertain = true;
2117 Session::get_best_session_directory_for_new_source ()
2119 vector<space_and_path>::iterator i;
2120 string result = _session_dir->root_path();
2122 /* handle common case without system calls */
2124 if (session_dirs.size() == 1) {
2128 /* OK, here's the algorithm we're following here:
2130 We want to select which directory to use for
2131 the next file source to be created. Ideally,
2132 we'd like to use a round-robin process so as to
2133 get maximum performance benefits from splitting
2134 the files across multiple disks.
2136 However, in situations without much diskspace, an
2137 RR approach may end up filling up a filesystem
2138 with new files while others still have space.
2139 Its therefore important to pay some attention to
2140 the freespace in the filesystem holding each
2141 directory as well. However, if we did that by
2142 itself, we'd keep creating new files in the file
2143 system with the most space until it was as full
2144 as all others, thus negating any performance
2145 benefits of this RAID-1 like approach.
2147 So, we use a user-configurable space threshold. If
2148 there are at least 2 filesystems with more than this
2149 much space available, we use RR selection between them.
2150 If not, then we pick the filesystem with the most space.
2152 This gets a good balance between the two
2156 refresh_disk_space ();
2158 int free_enough = 0;
2160 for (i = session_dirs.begin(); i != session_dirs.end(); ++i) {
2161 if ((*i).blocks * 4096 >= Config->get_disk_choice_space_threshold()) {
2166 if (free_enough >= 2) {
2167 /* use RR selection process, ensuring that the one
2171 i = last_rr_session_dir;
2174 if (++i == session_dirs.end()) {
2175 i = session_dirs.begin();
2178 if ((*i).blocks * 4096 >= Config->get_disk_choice_space_threshold()) {
2179 SessionDirectory sdir(i->path);
2180 if (sdir.create ()) {
2182 last_rr_session_dir = i;
2187 } while (i != last_rr_session_dir);
2191 /* pick FS with the most freespace (and that
2192 seems to actually work ...)
2195 vector<space_and_path> sorted;
2196 space_and_path_ascending_cmp cmp;
2198 sorted = session_dirs;
2199 sort (sorted.begin(), sorted.end(), cmp);
2201 for (i = sorted.begin(); i != sorted.end(); ++i) {
2202 SessionDirectory sdir(i->path);
2203 if (sdir.create ()) {
2205 last_rr_session_dir = i;
2215 Session::automation_dir () const
2217 return Glib::build_filename (_path, "automation");
2221 Session::analysis_dir () const
2223 return Glib::build_filename (_path, "analysis");
2227 Session::plugins_dir () const
2229 return Glib::build_filename (_path, "plugins");
2233 Session::externals_dir () const
2235 return Glib::build_filename (_path, "externals");
2239 Session::load_bundles (XMLNode const & node)
2241 XMLNodeList nlist = node.children();
2242 XMLNodeConstIterator niter;
2246 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2247 if ((*niter)->name() == "InputBundle") {
2248 add_bundle (boost::shared_ptr<UserBundle> (new UserBundle (**niter, true)));
2249 } else if ((*niter)->name() == "OutputBundle") {
2250 add_bundle (boost::shared_ptr<UserBundle> (new UserBundle (**niter, false)));
2252 error << string_compose(_("Unknown node \"%1\" found in Bundles list from state file"), (*niter)->name()) << endmsg;
2261 Session::load_route_groups (const XMLNode& node, int version)
2263 XMLNodeList nlist = node.children();
2264 XMLNodeConstIterator niter;
2268 if (version >= 3000) {
2270 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2271 if ((*niter)->name() == "RouteGroup") {
2272 RouteGroup* rg = new RouteGroup (*this, "");
2273 add_route_group (rg);
2274 rg->set_state (**niter, version);
2278 } else if (version < 3000) {
2280 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2281 if ((*niter)->name() == "EditGroup" || (*niter)->name() == "MixGroup") {
2282 RouteGroup* rg = new RouteGroup (*this, "");
2283 add_route_group (rg);
2284 rg->set_state (**niter, version);
2293 Session::auto_save()
2295 save_state (_current_snapshot_name);
2299 state_file_filter (const string &str, void */*arg*/)
2301 return (str.length() > strlen(statefile_suffix) &&
2302 str.find (statefile_suffix) == (str.length() - strlen (statefile_suffix)));
2306 bool operator()(const string* a, const string* b) {
2312 remove_end(string* state)
2314 string statename(*state);
2316 string::size_type start,end;
2317 if ((start = statename.find_last_of (G_DIR_SEPARATOR)) != string::npos) {
2318 statename = statename.substr (start+1);
2321 if ((end = statename.rfind(".ardour")) == string::npos) {
2322 end = statename.length();
2325 return new string(statename.substr (0, end));
2329 Session::possible_states (string path)
2331 PathScanner scanner;
2332 vector<string*>* states = scanner (path, state_file_filter, 0, false, false);
2334 transform(states->begin(), states->end(), states->begin(), remove_end);
2337 sort (states->begin(), states->end(), cmp);
2343 Session::possible_states () const
2345 return possible_states(_path);
2349 Session::add_route_group (RouteGroup* g)
2351 _route_groups.push_back (g);
2352 route_group_added (g); /* EMIT SIGNAL */
2354 g->RouteAdded.connect_same_thread (*this, boost::bind (&Session::route_added_to_route_group, this, _1, _2));
2355 g->RouteRemoved.connect_same_thread (*this, boost::bind (&Session::route_removed_from_route_group, this, _1, _2));
2356 g->PropertyChanged.connect_same_thread (*this, boost::bind (&Session::route_group_property_changed, this, g));
2362 Session::remove_route_group (RouteGroup& rg)
2364 list<RouteGroup*>::iterator i;
2366 if ((i = find (_route_groups.begin(), _route_groups.end(), &rg)) != _route_groups.end()) {
2367 _route_groups.erase (i);
2370 route_group_removed (); /* EMIT SIGNAL */
2374 /** Set a new order for our route groups, without adding or removing any.
2375 * @param groups Route group list in the new order.
2378 Session::reorder_route_groups (list<RouteGroup*> groups)
2380 _route_groups = groups;
2382 route_groups_reordered (); /* EMIT SIGNAL */
2388 Session::route_group_by_name (string name)
2390 list<RouteGroup *>::iterator i;
2392 for (i = _route_groups.begin(); i != _route_groups.end(); ++i) {
2393 if ((*i)->name() == name) {
2401 Session::all_route_group() const
2403 return *_all_route_group;
2407 Session::add_commands (vector<Command*> const & cmds)
2409 for (vector<Command*>::const_iterator i = cmds.begin(); i != cmds.end(); ++i) {
2415 Session::begin_reversible_command (const string& name)
2417 begin_reversible_command (g_quark_from_string (name.c_str ()));
2420 /** Begin a reversible command using a GQuark to identify it.
2421 * begin_reversible_command() and commit_reversible_command() calls may be nested,
2422 * but there must be as many begin...()s as there are commit...()s.
2425 Session::begin_reversible_command (GQuark q)
2427 /* If nested begin/commit pairs are used, we create just one UndoTransaction
2428 to hold all the commands that are committed. This keeps the order of
2429 commands correct in the history.
2432 if (_current_trans == 0) {
2433 /* start a new transaction */
2434 assert (_current_trans_quarks.empty ());
2435 _current_trans = new UndoTransaction();
2436 _current_trans->set_name (g_quark_to_string (q));
2439 _current_trans_quarks.push_front (q);
2443 Session::commit_reversible_command (Command *cmd)
2445 assert (_current_trans);
2446 assert (!_current_trans_quarks.empty ());
2451 _current_trans->add_command (cmd);
2454 _current_trans_quarks.pop_front ();
2456 if (!_current_trans_quarks.empty ()) {
2457 /* the transaction we're committing is not the top-level one */
2461 if (_current_trans->empty()) {
2462 /* no commands were added to the transaction, so just get rid of it */
2463 delete _current_trans;
2468 gettimeofday (&now, 0);
2469 _current_trans->set_timestamp (now);
2471 _history.add (_current_trans);
2476 accept_all_audio_files (const string& path, void */*arg*/)
2478 if (!Glib::file_test (path, Glib::FILE_TEST_IS_REGULAR)) {
2482 if (!AudioFileSource::safe_audio_file_extension (path)) {
2490 accept_all_midi_files (const string& path, void */*arg*/)
2492 if (!Glib::file_test (path, Glib::FILE_TEST_IS_REGULAR)) {
2496 return ((path.length() > 4 && path.find (".mid") != (path.length() - 4)) ||
2497 (path.length() > 4 && path.find (".smf") != (path.length() - 4)) ||
2498 (path.length() > 5 && path.find (".midi") != (path.length() - 5)));
2502 accept_all_state_files (const string& path, void */*arg*/)
2504 if (!Glib::file_test (path, Glib::FILE_TEST_IS_REGULAR)) {
2508 return (path.length() > 7 && path.find (".ardour") == (path.length() - 7));
2512 Session::find_all_sources (string path, set<string>& result)
2517 if (!tree.read (path)) {
2521 if ((node = find_named_node (*tree.root(), "Sources")) == 0) {
2526 XMLNodeConstIterator niter;
2528 nlist = node->children();
2532 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2536 if ((prop = (*niter)->property (X_("type"))) == 0) {
2540 DataType type (prop->value());
2542 if ((prop = (*niter)->property (X_("name"))) == 0) {
2546 if (Glib::path_is_absolute (prop->value())) {
2547 /* external file, ignore */
2555 if (FileSource::find (*this, type, prop->value(), true, is_new, chan, found_path)) {
2556 result.insert (found_path);
2564 Session::find_all_sources_across_snapshots (set<string>& result, bool exclude_this_snapshot)
2566 PathScanner scanner;
2567 vector<string*>* state_files;
2569 string this_snapshot_path;
2575 if (ripped[ripped.length()-1] == G_DIR_SEPARATOR) {
2576 ripped = ripped.substr (0, ripped.length() - 1);
2579 state_files = scanner (ripped, accept_all_state_files, (void *) 0, false, true);
2581 if (state_files == 0) {
2586 this_snapshot_path = _path;
2587 this_snapshot_path += legalize_for_path (_current_snapshot_name);
2588 this_snapshot_path += statefile_suffix;
2590 for (vector<string*>::iterator i = state_files->begin(); i != state_files->end(); ++i) {
2592 if (exclude_this_snapshot && **i == this_snapshot_path) {
2596 if (find_all_sources (**i, result) < 0) {
2604 struct RegionCounter {
2605 typedef std::map<PBD::ID,boost::shared_ptr<AudioSource> > AudioSourceList;
2606 AudioSourceList::iterator iter;
2607 boost::shared_ptr<Region> region;
2610 RegionCounter() : count (0) {}
2614 Session::ask_about_playlist_deletion (boost::shared_ptr<Playlist> p)
2616 boost::optional<int> r = AskAboutPlaylistDeletion (p);
2617 return r.get_value_or (1);
2621 Session::cleanup_regions ()
2623 const RegionFactory::RegionMap& regions (RegionFactory::regions());
2625 for (RegionFactory::RegionMap::const_iterator i = regions.begin(); i != regions.end(); ++i) {
2627 uint32_t used = playlists->region_use_count (i->second);
2629 if (used == 0 && !i->second->automatic ()) {
2630 RegionFactory::map_remove (i->second);
2634 /* dump the history list */
2641 Session::cleanup_sources (CleanupReport& rep)
2643 // FIXME: needs adaptation to midi
2645 vector<boost::shared_ptr<Source> > dead_sources;
2646 PathScanner scanner;
2649 vector<space_and_path>::iterator i;
2650 vector<space_and_path>::iterator nexti;
2651 vector<string*>* candidates;
2652 vector<string*>* candidates2;
2653 vector<string> unused;
2654 set<string> all_sources;
2659 _state_of_the_state = (StateOfTheState) (_state_of_the_state | InCleanup);
2661 /* consider deleting all unused playlists */
2663 if (playlists->maybe_delete_unused (boost::bind (Session::ask_about_playlist_deletion, _1))) {
2668 /* sync the "all regions" property of each playlist with its current state
2671 playlists->sync_all_regions_with_regions ();
2673 /* find all un-used sources */
2678 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ) {
2680 SourceMap::iterator tmp;
2685 /* do not bother with files that are zero size, otherwise we remove the current "nascent"
2689 if (!i->second->used() && (i->second->length(i->second->timeline_position() > 0))) {
2690 dead_sources.push_back (i->second);
2691 i->second->drop_references ();
2697 /* build a list of all the possible audio directories for the session */
2699 for (i = session_dirs.begin(); i != session_dirs.end(); ) {
2704 SessionDirectory sdir ((*i).path);
2705 audio_path += sdir.sound_path();
2707 if (nexti != session_dirs.end()) {
2715 /* build a list of all the possible midi directories for the session */
2717 for (i = session_dirs.begin(); i != session_dirs.end(); ) {
2722 SessionDirectory sdir ((*i).path);
2723 midi_path += sdir.midi_path();
2725 if (nexti != session_dirs.end()) {
2732 candidates = scanner (audio_path, accept_all_audio_files, (void *) 0, true, true);
2733 candidates2 = scanner (midi_path, accept_all_midi_files, (void *) 0, true, true);
2739 for (vector<string*>::iterator i = candidates2->begin(); i != candidates2->end(); ++i) {
2740 candidates->push_back (*i);
2745 candidates = candidates2; // might still be null
2748 /* find all sources, but don't use this snapshot because the
2749 state file on disk still references sources we may have already
2753 find_all_sources_across_snapshots (all_sources, true);
2755 /* add our current source list
2758 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ) {
2759 boost::shared_ptr<FileSource> fs;
2760 SourceMap::iterator tmp = i;
2763 if ((fs = boost::dynamic_pointer_cast<FileSource> (i->second)) != 0) {
2764 if (playlists->source_use_count (fs) != 0) {
2765 all_sources.insert (fs->path());
2768 /* we might not remove this source from disk, because it may be used
2769 by other snapshots, but its not being used in this version
2770 so lets get rid of it now, along with any representative regions
2774 RegionFactory::remove_regions_using_source (i->second);
2782 char tmppath1[PATH_MAX+1];
2783 char tmppath2[PATH_MAX+1];
2786 for (vector<string*>::iterator x = candidates->begin(); x != candidates->end(); ++x) {
2791 for (set<string>::iterator i = all_sources.begin(); i != all_sources.end(); ++i) {
2793 if (realpath(spath.c_str(), tmppath1) == 0) {
2794 error << string_compose (_("Cannot expand path %1 (%2)"),
2795 spath, strerror (errno)) << endmsg;
2799 if (realpath((*i).c_str(), tmppath2) == 0) {
2800 error << string_compose (_("Cannot expand path %1 (%2)"),
2801 (*i), strerror (errno)) << endmsg;
2805 if (strcmp(tmppath1, tmppath2) == 0) {
2812 unused.push_back (spath);
2821 /* now try to move all unused files into the "dead" directory(ies) */
2823 for (vector<string>::iterator x = unused.begin(); x != unused.end(); ++x) {
2824 struct stat statbuf;
2828 /* don't move the file across filesystems, just
2829 stick it in the `dead_dir_name' directory
2830 on whichever filesystem it was already on.
2833 if ((*x).find ("/sounds/") != string::npos) {
2835 /* old school, go up 1 level */
2837 newpath = Glib::path_get_dirname (*x); // "sounds"
2838 newpath = Glib::path_get_dirname (newpath); // "session-name"
2842 /* new school, go up 4 levels */
2844 newpath = Glib::path_get_dirname (*x); // "audiofiles" or "midifiles"
2845 newpath = Glib::path_get_dirname (newpath); // "session-name"
2846 newpath = Glib::path_get_dirname (newpath); // "interchange"
2847 newpath = Glib::path_get_dirname (newpath); // "session-dir"
2850 newpath = Glib::build_filename (newpath, dead_dir_name);
2852 if (g_mkdir_with_parents (newpath.c_str(), 0755) < 0) {
2853 error << string_compose(_("Session: cannot create dead file folder \"%1\" (%2)"), newpath, strerror (errno)) << endmsg;
2857 newpath = Glib::build_filename (newpath, Glib::path_get_basename ((*x)));
2859 if (Glib::file_test (newpath, Glib::FILE_TEST_EXISTS)) {
2861 /* the new path already exists, try versioning */
2863 char buf[PATH_MAX+1];
2867 snprintf (buf, sizeof (buf), "%s.%d", newpath.c_str(), version);
2870 while (Glib::file_test (newpath_v.c_str(), Glib::FILE_TEST_EXISTS) && version < 999) {
2871 snprintf (buf, sizeof (buf), "%s.%d", newpath.c_str(), ++version);
2875 if (version == 999) {
2876 error << string_compose (_("there are already 1000 files with names like %1; versioning discontinued"),
2880 newpath = newpath_v;
2885 /* it doesn't exist, or we can't read it or something */
2889 stat ((*x).c_str(), &statbuf);
2891 if (::rename ((*x).c_str(), newpath.c_str()) != 0) {
2892 error << string_compose (_("cannot rename unused file source from %1 to %2 (%3)"),
2893 (*x), newpath, strerror (errno))
2898 /* see if there an easy to find peakfile for this file, and remove it.
2901 string base = basename_nosuffix (*x);
2902 base += "%A"; /* this is what we add for the channel suffix of all native files,
2903 or for the first channel of embedded files. it will miss
2904 some peakfiles for other channels
2906 string peakpath = peak_path (base);
2908 if (Glib::file_test (peakpath.c_str(), Glib::FILE_TEST_EXISTS)) {
2909 if (::unlink (peakpath.c_str()) != 0) {
2910 error << string_compose (_("cannot remove peakfile %1 for %2 (%3)"),
2911 peakpath, _path, strerror (errno))
2913 /* try to back out */
2914 ::rename (newpath.c_str(), _path.c_str());
2919 rep.paths.push_back (*x);
2920 rep.space += statbuf.st_size;
2923 /* dump the history list */
2927 /* save state so we don't end up a session file
2928 referring to non-existent sources.
2935 _state_of_the_state = (StateOfTheState) (_state_of_the_state & ~InCleanup);
2941 Session::cleanup_trash_sources (CleanupReport& rep)
2943 // FIXME: needs adaptation for MIDI
2945 vector<space_and_path>::iterator i;
2951 for (i = session_dirs.begin(); i != session_dirs.end(); ++i) {
2953 dead_dir = Glib::build_filename ((*i).path, dead_dir_name);
2955 clear_directory (dead_dir, &rep.space, &rep.paths);
2962 Session::set_dirty ()
2964 bool was_dirty = dirty();
2966 _state_of_the_state = StateOfTheState (_state_of_the_state | Dirty);
2970 DirtyChanged(); /* EMIT SIGNAL */
2976 Session::set_clean ()
2978 bool was_dirty = dirty();
2980 _state_of_the_state = Clean;
2984 DirtyChanged(); /* EMIT SIGNAL */
2989 Session::set_deletion_in_progress ()
2991 _state_of_the_state = StateOfTheState (_state_of_the_state | Deletion);
2995 Session::clear_deletion_in_progress ()
2997 _state_of_the_state = StateOfTheState (_state_of_the_state & (~Deletion));
3001 Session::add_controllable (boost::shared_ptr<Controllable> c)
3003 /* this adds a controllable to the list managed by the Session.
3004 this is a subset of those managed by the Controllable class
3005 itself, and represents the only ones whose state will be saved
3006 as part of the session.
3009 Glib::Threads::Mutex::Lock lm (controllables_lock);
3010 controllables.insert (c);
3013 struct null_deleter { void operator()(void const *) const {} };
3016 Session::remove_controllable (Controllable* c)
3018 if (_state_of_the_state & Deletion) {
3022 Glib::Threads::Mutex::Lock lm (controllables_lock);
3024 Controllables::iterator x = controllables.find (boost::shared_ptr<Controllable>(c, null_deleter()));
3026 if (x != controllables.end()) {
3027 controllables.erase (x);
3031 boost::shared_ptr<Controllable>
3032 Session::controllable_by_id (const PBD::ID& id)
3034 Glib::Threads::Mutex::Lock lm (controllables_lock);
3036 for (Controllables::iterator i = controllables.begin(); i != controllables.end(); ++i) {
3037 if ((*i)->id() == id) {
3042 return boost::shared_ptr<Controllable>();
3045 boost::shared_ptr<Controllable>
3046 Session::controllable_by_descriptor (const ControllableDescriptor& desc)
3048 boost::shared_ptr<Controllable> c;
3049 boost::shared_ptr<Route> r;
3051 switch (desc.top_level_type()) {
3052 case ControllableDescriptor::NamedRoute:
3054 std::string str = desc.top_level_name();
3055 if (str == "master") {
3057 } else if (str == "control" || str == "listen") {
3060 r = route_by_name (desc.top_level_name());
3065 case ControllableDescriptor::RemoteControlID:
3066 r = route_by_remote_id (desc.rid());
3074 switch (desc.subtype()) {
3075 case ControllableDescriptor::Gain:
3076 c = r->gain_control ();
3079 case ControllableDescriptor::Solo:
3080 c = r->solo_control();
3083 case ControllableDescriptor::Mute:
3084 c = r->mute_control();
3087 case ControllableDescriptor::Recenable:
3089 boost::shared_ptr<Track> t = boost::dynamic_pointer_cast<Track>(r);
3092 c = t->rec_enable_control ();
3097 case ControllableDescriptor::PanDirection:
3099 c = r->pannable()->pan_azimuth_control;
3103 case ControllableDescriptor::PanWidth:
3105 c = r->pannable()->pan_width_control;
3109 case ControllableDescriptor::PanElevation:
3111 c = r->pannable()->pan_elevation_control;
3115 case ControllableDescriptor::Balance:
3116 /* XXX simple pan control */
3119 case ControllableDescriptor::PluginParameter:
3121 uint32_t plugin = desc.target (0);
3122 uint32_t parameter_index = desc.target (1);
3124 /* revert to zero based counting */
3130 if (parameter_index > 0) {
3134 boost::shared_ptr<Processor> p = r->nth_plugin (plugin);
3137 c = boost::dynamic_pointer_cast<ARDOUR::AutomationControl>(
3138 p->control(Evoral::Parameter(PluginAutomation, 0, parameter_index)));
3143 case ControllableDescriptor::SendGain:
3145 uint32_t send = desc.target (0);
3147 /* revert to zero-based counting */
3153 boost::shared_ptr<Processor> p = r->nth_send (send);
3156 boost::shared_ptr<Send> s = boost::dynamic_pointer_cast<Send>(p);
3157 boost::shared_ptr<Amp> a = s->amp();
3160 c = s->amp()->gain_control();
3167 /* relax and return a null pointer */
3175 Session::add_instant_xml (XMLNode& node, bool write_to_config)
3178 Stateful::add_instant_xml (node, _path);
3181 if (write_to_config) {
3182 Config->add_instant_xml (node);
3187 Session::instant_xml (const string& node_name)
3189 return Stateful::instant_xml (node_name, _path);
3193 Session::save_history (string snapshot_name)
3201 if (snapshot_name.empty()) {
3202 snapshot_name = _current_snapshot_name;
3205 const string history_filename = legalize_for_path (snapshot_name) + history_suffix;
3206 const string backup_filename = history_filename + backup_suffix;
3207 const std::string xml_path(Glib::build_filename (_session_dir->root_path(), history_filename));
3208 const std::string backup_path(Glib::build_filename (_session_dir->root_path(), backup_filename));
3210 if (Glib::file_test (xml_path, Glib::FILE_TEST_EXISTS)) {
3211 if (::g_rename (xml_path.c_str(), backup_path.c_str()) != 0) {
3212 error << _("could not backup old history file, current history not saved") << endmsg;
3217 if (!Config->get_save_history() || Config->get_saved_history_depth() < 0) {
3221 tree.set_root (&_history.get_state (Config->get_saved_history_depth()));
3223 if (!tree.write (xml_path))
3225 error << string_compose (_("history could not be saved to %1"), xml_path) << endmsg;
3227 if (g_remove (xml_path.c_str()) != 0) {
3228 error << string_compose(_("Could not remove history file at path \"%1\" (%2)"),
3229 xml_path, g_strerror (errno)) << endmsg;
3231 if (::g_rename (backup_path.c_str(), xml_path.c_str()) != 0) {
3232 error << string_compose (_("could not restore history file from backup %1 (%2)"),
3233 backup_path, g_strerror (errno)) << endmsg;
3243 Session::restore_history (string snapshot_name)
3247 if (snapshot_name.empty()) {
3248 snapshot_name = _current_snapshot_name;
3251 const std::string xml_filename = legalize_for_path (snapshot_name) + history_suffix;
3252 const std::string xml_path(Glib::build_filename (_session_dir->root_path(), xml_filename));
3254 info << "Loading history from " << xml_path << endmsg;
3256 if (!Glib::file_test (xml_path, Glib::FILE_TEST_EXISTS)) {
3257 info << string_compose (_("%1: no history file \"%2\" for this session."),
3258 _name, xml_path) << endmsg;
3262 if (!tree.read (xml_path)) {
3263 error << string_compose (_("Could not understand session history file \"%1\""),
3264 xml_path) << endmsg;
3271 for (XMLNodeConstIterator it = tree.root()->children().begin(); it != tree.root()->children().end(); it++) {
3274 UndoTransaction* ut = new UndoTransaction ();
3277 ut->set_name(t->property("name")->value());
3278 stringstream ss(t->property("tv-sec")->value());
3280 ss.str(t->property("tv-usec")->value());
3282 ut->set_timestamp(tv);
3284 for (XMLNodeConstIterator child_it = t->children().begin();
3285 child_it != t->children().end(); child_it++)
3287 XMLNode *n = *child_it;
3290 if (n->name() == "MementoCommand" ||
3291 n->name() == "MementoUndoCommand" ||
3292 n->name() == "MementoRedoCommand") {
3294 if ((c = memento_command_factory(n))) {
3298 } else if (n->name() == "NoteDiffCommand") {
3299 PBD::ID id (n->property("midi-source")->value());
3300 boost::shared_ptr<MidiSource> midi_source =
3301 boost::dynamic_pointer_cast<MidiSource, Source>(source_by_id(id));
3303 ut->add_command (new MidiModel::NoteDiffCommand(midi_source->model(), *n));
3305 error << _("Failed to downcast MidiSource for NoteDiffCommand") << endmsg;
3308 } else if (n->name() == "SysExDiffCommand") {
3310 PBD::ID id (n->property("midi-source")->value());
3311 boost::shared_ptr<MidiSource> midi_source =
3312 boost::dynamic_pointer_cast<MidiSource, Source>(source_by_id(id));
3314 ut->add_command (new MidiModel::SysExDiffCommand (midi_source->model(), *n));
3316 error << _("Failed to downcast MidiSource for SysExDiffCommand") << endmsg;
3319 } else if (n->name() == "PatchChangeDiffCommand") {
3321 PBD::ID id (n->property("midi-source")->value());
3322 boost::shared_ptr<MidiSource> midi_source =
3323 boost::dynamic_pointer_cast<MidiSource, Source>(source_by_id(id));
3325 ut->add_command (new MidiModel::PatchChangeDiffCommand (midi_source->model(), *n));
3327 error << _("Failed to downcast MidiSource for PatchChangeDiffCommand") << endmsg;
3330 } else if (n->name() == "StatefulDiffCommand") {
3331 if ((c = stateful_diff_command_factory (n))) {
3332 ut->add_command (c);
3335 error << string_compose(_("Couldn't figure out how to make a Command out of a %1 XMLNode."), n->name()) << endmsg;
3346 Session::config_changed (std::string p, bool ours)
3352 if (p == "seamless-loop") {
3354 } else if (p == "rf-speed") {
3356 } else if (p == "auto-loop") {
3358 } else if (p == "auto-input") {
3360 if (Config->get_monitoring_model() == HardwareMonitoring && transport_rolling()) {
3361 /* auto-input only makes a difference if we're rolling */
3362 set_track_monitor_input_status (!config.get_auto_input());
3365 } else if (p == "punch-in") {
3369 if ((location = _locations->auto_punch_location()) != 0) {
3371 if (config.get_punch_in ()) {
3372 replace_event (SessionEvent::PunchIn, location->start());
3374 remove_event (location->start(), SessionEvent::PunchIn);
3378 } else if (p == "punch-out") {
3382 if ((location = _locations->auto_punch_location()) != 0) {
3384 if (config.get_punch_out()) {
3385 replace_event (SessionEvent::PunchOut, location->end());
3387 clear_events (SessionEvent::PunchOut);
3391 } else if (p == "edit-mode") {
3393 Glib::Threads::Mutex::Lock lm (playlists->lock);
3395 for (SessionPlaylists::List::iterator i = playlists->playlists.begin(); i != playlists->playlists.end(); ++i) {
3396 (*i)->set_edit_mode (Config->get_edit_mode ());
3399 } else if (p == "use-video-sync") {
3401 waiting_for_sync_offset = config.get_use_video_sync();
3403 } else if (p == "mmc-control") {
3405 //poke_midi_thread ();
3407 } else if (p == "mmc-device-id" || p == "mmc-receive-id" || p == "mmc-receive-device-id") {
3409 MIDI::Manager::instance()->mmc()->set_receive_device_id (Config->get_mmc_receive_device_id());
3411 } else if (p == "mmc-send-id" || p == "mmc-send-device-id") {
3413 MIDI::Manager::instance()->mmc()->set_send_device_id (Config->get_mmc_send_device_id());
3415 } else if (p == "midi-control") {
3417 //poke_midi_thread ();
3419 } else if (p == "raid-path") {
3421 setup_raid_path (config.get_raid_path());
3423 } else if (p == "timecode-format") {
3427 } else if (p == "video-pullup") {
3431 } else if (p == "seamless-loop") {
3433 if (play_loop && transport_rolling()) {
3434 // to reset diskstreams etc
3435 request_play_loop (true);
3438 } else if (p == "rf-speed") {
3440 cumulative_rf_motion = 0;
3443 } else if (p == "click-sound") {
3445 setup_click_sounds (1);
3447 } else if (p == "click-emphasis-sound") {
3449 setup_click_sounds (-1);
3451 } else if (p == "clicking") {
3453 if (Config->get_clicking()) {
3454 if (_click_io && click_data) { // don't require emphasis data
3461 } else if (p == "click-gain") {
3464 _click_gain->set_gain (Config->get_click_gain(), this);
3467 } else if (p == "send-mtc") {
3469 if (Config->get_send_mtc ()) {
3470 /* mark us ready to send */
3471 next_quarter_frame_to_send = 0;
3474 } else if (p == "send-mmc") {
3476 MIDI::Manager::instance()->mmc()->enable_send (Config->get_send_mmc ());
3478 } else if (p == "midi-feedback") {
3480 session_midi_feedback = Config->get_midi_feedback();
3482 } else if (p == "jack-time-master") {
3484 engine().reset_timebase ();
3486 } else if (p == "native-file-header-format") {
3488 if (!first_file_header_format_reset) {
3489 reset_native_file_format ();
3492 first_file_header_format_reset = false;
3494 } else if (p == "native-file-data-format") {
3496 if (!first_file_data_format_reset) {
3497 reset_native_file_format ();
3500 first_file_data_format_reset = false;
3502 } else if (p == "external-sync") {
3503 if (!config.get_external_sync()) {
3504 drop_sync_source ();
3506 switch_to_sync_source (Config->get_sync_source());
3508 } else if (p == "denormal-model") {
3510 } else if (p == "history-depth") {
3511 set_history_depth (Config->get_history_depth());
3512 } else if (p == "remote-model") {
3513 /* XXX DO SOMETHING HERE TO TELL THE GUI THAT WE NEED
3516 } else if (p == "sync-all-route-ordering") {
3518 /* sync to editor order unless mixer is used for remote IDs
3521 switch (Config->get_remote_model()) {
3523 sync_order_keys (EditorSort);
3526 sync_order_keys (EditorSort);
3529 sync_order_keys (MixerSort);
3532 } else if (p == "initial-program-change") {
3534 if (MIDI::Manager::instance()->mmc()->output_port() && Config->get_initial_program_change() >= 0) {
3537 buf[0] = MIDI::program; // channel zero by default
3538 buf[1] = (Config->get_initial_program_change() & 0x7f);
3540 MIDI::Manager::instance()->mmc()->output_port()->midimsg (buf, sizeof (buf), 0);
3542 } else if (p == "solo-mute-override") {
3543 // catch_up_on_solo_mute_override ();
3544 } else if (p == "listen-position" || p == "pfl-position") {
3545 listen_position_changed ();
3546 } else if (p == "solo-control-is-listen-control") {
3547 solo_control_mode_changed ();
3548 } else if (p == "timecode-offset" || p == "timecode-offset-negative") {
3549 last_timecode_valid = false;
3550 } else if (p == "playback-buffer-seconds") {
3551 AudioSource::allocate_working_buffers (frame_rate());
3552 } else if (p == "automation-thinning-factor") {
3553 Evoral::ControlList::set_thinning_factor (Config->get_automation_thinning_factor());
3560 Session::set_history_depth (uint32_t d)
3562 _history.set_depth (d);
3566 Session::load_diskstreams_2X (XMLNode const & node, int)
3569 XMLNodeConstIterator citer;
3571 clist = node.children();
3573 for (citer = clist.begin(); citer != clist.end(); ++citer) {
3576 /* diskstreams added automatically by DiskstreamCreated handler */
3577 if ((*citer)->name() == "AudioDiskstream" || (*citer)->name() == "DiskStream") {
3578 boost::shared_ptr<AudioDiskstream> dsp (new AudioDiskstream (*this, **citer));
3579 _diskstreams_2X.push_back (dsp);
3581 error << _("Session: unknown diskstream type in XML") << endmsg;
3585 catch (failed_constructor& err) {
3586 error << _("Session: could not load diskstream via XML state") << endmsg;
3594 /** Connect things to the MMC object */
3596 Session::setup_midi_machine_control ()
3598 MIDI::MachineControl* mmc = MIDI::Manager::instance()->mmc ();
3600 mmc->Play.connect_same_thread (*this, boost::bind (&Session::mmc_deferred_play, this, _1));
3601 mmc->DeferredPlay.connect_same_thread (*this, boost::bind (&Session::mmc_deferred_play, this, _1));
3602 mmc->Stop.connect_same_thread (*this, boost::bind (&Session::mmc_stop, this, _1));
3603 mmc->FastForward.connect_same_thread (*this, boost::bind (&Session::mmc_fast_forward, this, _1));
3604 mmc->Rewind.connect_same_thread (*this, boost::bind (&Session::mmc_rewind, this, _1));
3605 mmc->Pause.connect_same_thread (*this, boost::bind (&Session::mmc_pause, this, _1));
3606 mmc->RecordPause.connect_same_thread (*this, boost::bind (&Session::mmc_record_pause, this, _1));
3607 mmc->RecordStrobe.connect_same_thread (*this, boost::bind (&Session::mmc_record_strobe, this, _1));
3608 mmc->RecordExit.connect_same_thread (*this, boost::bind (&Session::mmc_record_exit, this, _1));
3609 mmc->Locate.connect_same_thread (*this, boost::bind (&Session::mmc_locate, this, _1, _2));
3610 mmc->Step.connect_same_thread (*this, boost::bind (&Session::mmc_step, this, _1, _2));
3611 mmc->Shuttle.connect_same_thread (*this, boost::bind (&Session::mmc_shuttle, this, _1, _2, _3));
3612 mmc->TrackRecordStatusChange.connect_same_thread (*this, boost::bind (&Session::mmc_record_enable, this, _1, _2, _3));
3614 /* also handle MIDI SPP because its so common */
3616 mmc->SPPStart.connect_same_thread (*this, boost::bind (&Session::spp_start, this));
3617 mmc->SPPContinue.connect_same_thread (*this, boost::bind (&Session::spp_continue, this));
3618 mmc->SPPStop.connect_same_thread (*this, boost::bind (&Session::spp_stop, this));
3621 boost::shared_ptr<Controllable>
3622 Session::solo_cut_control() const
3624 /* the solo cut control is a bit of an anomaly, at least as of Febrary 2011. There are no other
3625 controls in Ardour that currently get presented to the user in the GUI that require
3626 access as a Controllable and are also NOT owned by some SessionObject (e.g. Route, or MonitorProcessor).
3628 its actually an RCConfiguration parameter, so we use a ProxyControllable to wrap
3629 it up as a Controllable. Changes to the Controllable will just map back to the RCConfiguration
3633 return _solo_cut_control;
3637 Session::rename (const std::string& new_name)
3639 string legal_name = legalize_for_path (new_name);
3645 string const old_sources_root = _session_dir->sources_root();
3647 #define RENAME ::rename
3652 * interchange subdirectory
3656 * Backup files are left unchanged and not renamed.
3659 /* pass one: not 100% safe check that the new directory names don't
3663 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
3668 /* this is a stupid hack because Glib::path_get_dirname() is
3669 * lexical-only, and so passing it /a/b/c/ gives a different
3670 * result than passing it /a/b/c ...
3673 if (oldstr[oldstr.length()-1] == G_DIR_SEPARATOR) {
3674 oldstr = oldstr.substr (0, oldstr.length() - 1);
3677 string base = Glib::path_get_dirname (oldstr);
3678 string p = Glib::path_get_basename (oldstr);
3680 newstr = Glib::build_filename (base, legal_name);
3682 if (Glib::file_test (newstr, Glib::FILE_TEST_EXISTS)) {
3689 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
3694 /* this is a stupid hack because Glib::path_get_dirname() is
3695 * lexical-only, and so passing it /a/b/c/ gives a different
3696 * result than passing it /a/b/c ...
3699 if (oldstr[oldstr.length()-1] == G_DIR_SEPARATOR) {
3700 oldstr = oldstr.substr (0, oldstr.length() - 1);
3703 string base = Glib::path_get_dirname (oldstr);
3704 string p = Glib::path_get_basename (oldstr);
3706 newstr = Glib::build_filename (base, legal_name);
3708 cerr << "Rename " << oldstr << " => " << newstr << endl;
3710 if (RENAME (oldstr.c_str(), newstr.c_str()) != 0) {
3715 (*_session_dir) = newstr;
3720 /* directory below interchange */
3722 v.push_back (newstr);
3723 v.push_back (interchange_dir_name);
3726 oldstr = Glib::build_filename (v);
3729 v.push_back (newstr);
3730 v.push_back (interchange_dir_name);
3731 v.push_back (legal_name);
3733 newstr = Glib::build_filename (v);
3735 cerr << "Rename " << oldstr << " => " << newstr << endl;
3737 if (RENAME (oldstr.c_str(), newstr.c_str()) != 0) {
3744 oldstr = Glib::build_filename (newpath, _current_snapshot_name) + statefile_suffix;
3745 newstr= Glib::build_filename (newpath, legal_name) + statefile_suffix;
3747 cerr << "Rename " << oldstr << " => " << newstr << endl;
3749 if (RENAME (oldstr.c_str(), newstr.c_str()) != 0) {
3756 oldstr = Glib::build_filename (newpath, _current_snapshot_name) + history_suffix;
3758 if (Glib::file_test (oldstr, Glib::FILE_TEST_EXISTS)) {
3759 newstr = Glib::build_filename (newpath, legal_name) + history_suffix;
3761 cerr << "Rename " << oldstr << " => " << newstr << endl;
3763 if (RENAME (oldstr.c_str(), newstr.c_str()) != 0) {
3768 /* update file source paths */
3770 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ++i) {
3771 boost::shared_ptr<FileSource> fs = boost::dynamic_pointer_cast<FileSource> (i->second);
3773 string p = fs->path ();
3774 boost::replace_all (p, old_sources_root, _session_dir->sources_root());
3779 /* remove old name from recent sessions */
3781 remove_recent_sessions (_path);
3784 _current_snapshot_name = new_name;
3789 /* save state again to get everything just right */
3791 save_state (_current_snapshot_name);
3794 /* add to recent sessions */
3796 store_recent_sessions (new_name, _path);