2 Copyright (C) 1999-2002 Paul Davis
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 #include "libardour-config.h"
31 #include <cstdio> /* snprintf(3) ... grrr */
45 #include <sys/param.h>
46 #include <sys/mount.h>
49 #ifdef HAVE_SYS_STATVFS_H
50 #include <sys/statvfs.h>
54 #include <glib/gstdio.h>
57 #include <glibmm/threads.h>
59 #include <boost/algorithm/string.hpp>
61 #include "midi++/mmc.h"
62 #include "midi++/port.h"
63 #include "midi++/manager.h"
65 #include "evoral/SMF.hpp"
67 #include "pbd/boost_debug.h"
68 #include "pbd/basename.h"
69 #include "pbd/controllable_descriptor.h"
70 #include "pbd/enumwriter.h"
71 #include "pbd/error.h"
72 #include "pbd/file_utils.h"
73 #include "pbd/pathscanner.h"
74 #include "pbd/pthread_utils.h"
75 #include "pbd/stacktrace.h"
76 #include "pbd/convert.h"
77 #include "pbd/clear_dir.h"
79 #include "ardour/amp.h"
80 #include "ardour/audio_diskstream.h"
81 #include "ardour/audio_track.h"
82 #include "ardour/audioengine.h"
83 #include "ardour/audiofilesource.h"
84 #include "ardour/audioregion.h"
85 #include "ardour/automation_control.h"
86 #include "ardour/butler.h"
87 #include "ardour/control_protocol_manager.h"
88 #include "ardour/directory_names.h"
89 #include "ardour/filename_extensions.h"
90 #include "ardour/location.h"
91 #include "ardour/midi_model.h"
92 #include "ardour/midi_patch_manager.h"
93 #include "ardour/midi_region.h"
94 #include "ardour/midi_source.h"
95 #include "ardour/midi_track.h"
96 #include "ardour/pannable.h"
97 #include "ardour/playlist_factory.h"
98 #include "ardour/port.h"
99 #include "ardour/processor.h"
100 #include "ardour/proxy_controllable.h"
101 #include "ardour/recent_sessions.h"
102 #include "ardour/region_factory.h"
103 #include "ardour/route_group.h"
104 #include "ardour/send.h"
105 #include "ardour/session.h"
106 #include "ardour/session_directory.h"
107 #include "ardour/session_metadata.h"
108 #include "ardour/session_playlists.h"
109 #include "ardour/session_state_utils.h"
110 #include "ardour/silentfilesource.h"
111 #include "ardour/sndfilesource.h"
112 #include "ardour/source_factory.h"
113 #include "ardour/speakers.h"
114 #include "ardour/template_utils.h"
115 #include "ardour/tempo.h"
116 #include "ardour/ticker.h"
117 #include "ardour/user_bundle.h"
119 #include "control_protocol/control_protocol.h"
125 using namespace ARDOUR;
128 /** @param snapshot_name Snapshot name, without the .ardour prefix */
130 Session::first_stage_init (string fullpath, string snapshot_name)
132 if (fullpath.length() == 0) {
134 throw failed_constructor();
137 char buf[PATH_MAX+1];
138 if (!realpath (fullpath.c_str(), buf) && (errno != ENOENT)) {
139 error << string_compose(_("Could not use path %1 (%s)"), buf, strerror(errno)) << endmsg;
141 throw failed_constructor();
146 if (_path[_path.length()-1] != G_DIR_SEPARATOR) {
147 _path += G_DIR_SEPARATOR;
150 /* these two are just provisional settings. set_state()
151 will likely override them.
154 _name = _current_snapshot_name = snapshot_name;
156 set_history_depth (Config->get_history_depth());
158 _current_frame_rate = _engine.frame_rate ();
159 _nominal_frame_rate = _current_frame_rate;
160 _base_frame_rate = _current_frame_rate;
162 _tempo_map = new TempoMap (_current_frame_rate);
163 _tempo_map->PropertyChanged.connect_same_thread (*this, boost::bind (&Session::tempo_map_changed, this, _1));
166 _non_soloed_outs_muted = false;
168 _solo_isolated_cnt = 0;
169 g_atomic_int_set (&processing_prohibited, 0);
170 _transport_speed = 0;
171 _default_transport_speed = 1.0;
172 _last_transport_speed = 0;
173 _target_transport_speed = 0;
174 auto_play_legal = false;
175 transport_sub_state = 0;
176 _transport_frame = 0;
177 _requested_return_frame = -1;
178 _session_range_location = 0;
179 g_atomic_int_set (&_record_status, Disabled);
180 loop_changing = false;
183 _last_roll_location = 0;
184 _last_roll_or_reversal_location = 0;
185 _last_record_location = 0;
186 pending_locate_frame = 0;
187 pending_locate_roll = false;
188 pending_locate_flush = false;
189 state_was_pending = false;
191 outbound_mtc_timecode_frame = 0;
192 next_quarter_frame_to_send = -1;
193 current_block_size = 0;
194 solo_update_disabled = false;
195 _have_captured = false;
196 _worst_output_latency = 0;
197 _worst_input_latency = 0;
198 _worst_track_latency = 0;
199 _state_of_the_state = StateOfTheState(CannotSave|InitialConnecting|Loading);
200 _was_seamless = Config->get_seamless_loop ();
202 _send_qf_mtc = false;
203 _pframes_since_last_mtc = 0;
204 g_atomic_int_set (&_playback_load, 100);
205 g_atomic_int_set (&_capture_load, 100);
208 pending_abort = false;
209 _adding_routes_in_progress = false;
210 destructive_index = 0;
211 first_file_data_format_reset = true;
212 first_file_header_format_reset = true;
213 post_export_sync = false;
216 no_questions_about_missing_files = false;
217 _speakers.reset (new Speakers);
219 ignore_route_processor_changes = false;
220 _pre_export_mmc_enabled = false;
222 AudioDiskstream::allocate_working_buffers();
224 /* default short fade = 15ms */
226 SndFileSource::setup_standard_crossfades (*this, frame_rate());
228 last_mmc_step.tv_sec = 0;
229 last_mmc_step.tv_usec = 0;
232 /* click sounds are unset by default, which causes us to internal
233 waveforms for clicks.
237 click_emphasis_length = 0;
240 process_function = &Session::process_with_events;
242 if (config.get_use_video_sync()) {
243 waiting_for_sync_offset = true;
245 waiting_for_sync_offset = false;
248 last_timecode_when = 0;
249 last_timecode_valid = false;
253 last_rr_session_dir = session_dirs.begin();
254 refresh_disk_space ();
256 /* default: assume simple stereo speaker configuration */
258 _speakers->setup_default_speakers (2);
262 average_slave_delta = 1800; // !!! why 1800 ????
263 have_first_delta_accumulator = false;
264 delta_accumulator_cnt = 0;
265 _slave_state = Stopped;
267 _solo_cut_control.reset (new ProxyControllable (_("solo cut control (dB)"), PBD::Controllable::GainLike,
268 boost::bind (&RCConfiguration::set_solo_mute_gain, Config, _1),
269 boost::bind (&RCConfiguration::get_solo_mute_gain, Config)));
270 add_controllable (_solo_cut_control);
272 _engine.GraphReordered.connect_same_thread (*this, boost::bind (&Session::graph_reordered, this));
274 /* These are all static "per-class" signals */
276 SourceFactory::SourceCreated.connect_same_thread (*this, boost::bind (&Session::add_source, this, _1));
277 PlaylistFactory::PlaylistCreated.connect_same_thread (*this, boost::bind (&Session::add_playlist, this, _1, _2));
278 AutomationList::AutomationListCreated.connect_same_thread (*this, boost::bind (&Session::add_automation_list, this, _1));
279 Controllable::Destroyed.connect_same_thread (*this, boost::bind (&Session::remove_controllable, this, _1));
280 IO::PortCountChanged.connect_same_thread (*this, boost::bind (&Session::ensure_buffers, this, _1));
282 /* stop IO objects from doing stuff until we're ready for them */
284 Delivery::disable_panners ();
285 IO::disable_connecting ();
289 Session::second_stage_init ()
291 AudioFileSource::set_peak_dir (_session_dir->peak_path());
294 if (load_state (_current_snapshot_name)) {
299 if (_butler->start_thread()) {
303 if (start_midi_thread ()) {
307 setup_midi_machine_control ();
309 // set_state() will call setup_raid_path(), but if it's a new session we need
310 // to call setup_raid_path() here.
313 if (set_state (*state_tree->root(), Stateful::loading_state_version)) {
317 setup_raid_path(_path);
320 /* we can't save till after ::when_engine_running() is called,
321 because otherwise we save state with no connections made.
322 therefore, we reset _state_of_the_state because ::set_state()
323 will have cleared it.
325 we also have to include Loading so that any events that get
326 generated between here and the end of ::when_engine_running()
327 will be processed directly rather than queued.
330 _state_of_the_state = StateOfTheState (_state_of_the_state|CannotSave|Loading);
332 _locations->changed.connect_same_thread (*this, boost::bind (&Session::locations_changed, this));
333 _locations->added.connect_same_thread (*this, boost::bind (&Session::locations_added, this, _1));
334 setup_click_sounds (0);
335 setup_midi_control ();
337 /* Pay attention ... */
339 _engine.Halted.connect_same_thread (*this, boost::bind (&Session::engine_halted, this));
340 _engine.Xrun.connect_same_thread (*this, boost::bind (&Session::xrun_recovery, this));
342 midi_clock = new MidiClockTicker ();
343 midi_clock->set_session (this);
346 when_engine_running ();
349 /* handle this one in a different way than all others, so that its clear what happened */
351 catch (AudioEngine::PortRegistrationFailure& err) {
352 error << err.what() << endmsg;
360 BootMessage (_("Reset Remote Controls"));
362 send_full_time_code (0);
363 _engine.transport_locate (0);
365 MIDI::Manager::instance()->mmc()->send (MIDI::MachineControlCommand (MIDI::MachineControl::cmdMmcReset));
366 MIDI::Manager::instance()->mmc()->send (MIDI::MachineControlCommand (Timecode::Time ()));
368 MIDI::Name::MidiPatchManager::instance().set_session (this);
373 /* initial program change will be delivered later; see ::config_changed() */
375 _state_of_the_state = Clean;
377 Port::set_connecting_blocked (false);
379 DirtyChanged (); /* EMIT SIGNAL */
381 if (state_was_pending) {
382 save_state (_current_snapshot_name);
383 remove_pending_capture_state ();
384 state_was_pending = false;
387 BootMessage (_("Session loading complete"));
393 Session::raid_path () const
395 SearchPath raid_search_path;
397 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
398 raid_search_path += (*i).path;
401 return raid_search_path.to_string ();
405 Session::setup_raid_path (string path)
414 session_dirs.clear ();
416 SearchPath search_path(path);
417 SearchPath sound_search_path;
418 SearchPath midi_search_path;
420 for (SearchPath::const_iterator i = search_path.begin(); i != search_path.end(); ++i) {
422 sp.blocks = 0; // not needed
423 session_dirs.push_back (sp);
425 SessionDirectory sdir(sp.path);
427 sound_search_path += sdir.sound_path ();
428 midi_search_path += sdir.midi_path ();
431 // reset the round-robin soundfile path thingie
432 last_rr_session_dir = session_dirs.begin();
436 Session::path_is_within_session (const std::string& path)
438 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
439 if (PBD::path_is_within (i->path, path)) {
447 Session::ensure_subdirs ()
451 dir = session_directory().peak_path();
453 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
454 error << string_compose(_("Session: cannot create session peakfile folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
458 dir = session_directory().sound_path();
460 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
461 error << string_compose(_("Session: cannot create session sounds dir \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
465 dir = session_directory().midi_path();
467 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
468 error << string_compose(_("Session: cannot create session midi dir \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
472 dir = session_directory().dead_path();
474 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
475 error << string_compose(_("Session: cannot create session dead sounds folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
479 dir = session_directory().export_path();
481 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
482 error << string_compose(_("Session: cannot create session export folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
486 dir = analysis_dir ();
488 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
489 error << string_compose(_("Session: cannot create session analysis folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
493 dir = plugins_dir ();
495 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
496 error << string_compose(_("Session: cannot create session plugins folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
500 dir = externals_dir ();
502 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
503 error << string_compose(_("Session: cannot create session externals folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
510 /** @param session_template directory containing session template, or empty.
511 * Caller must not hold process lock.
514 Session::create (const string& session_template, BusProfile* bus_profile)
516 if (g_mkdir_with_parents (_path.c_str(), 0755) < 0) {
517 error << string_compose(_("Session: cannot create session folder \"%1\" (%2)"), _path, strerror (errno)) << endmsg;
521 if (ensure_subdirs ()) {
525 _writable = exists_and_writable (_path);
527 if (!session_template.empty()) {
528 std::string in_path = session_template_dir_to_file (session_template);
530 ifstream in(in_path.c_str());
533 string out_path = _path;
535 out_path += statefile_suffix;
537 ofstream out(out_path.c_str());
543 /* Copy plugin state files from template to new session */
544 std::string template_plugins = Glib::build_filename (session_template, X_("plugins"));
545 copy_files (template_plugins, plugins_dir ());
550 error << string_compose (_("Could not open %1 for writing session template"), out_path)
556 error << string_compose (_("Could not open session template %1 for reading"), in_path)
563 /* set initial start + end point */
565 _state_of_the_state = Clean;
567 /* set up Master Out and Control Out if necessary */
572 ChanCount count(DataType::AUDIO, bus_profile->master_out_channels);
574 if (bus_profile->master_out_channels) {
575 boost::shared_ptr<Route> r (new Route (*this, _("master"), Route::MasterOut, DataType::AUDIO));
579 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
580 // boost_debug_shared_ptr_mark_interesting (r.get(), "Route");
583 Glib::Threads::Mutex::Lock lm (AudioEngine::instance()->process_lock ());
584 r->input()->ensure_io (count, false, this);
585 r->output()->ensure_io (count, false, this);
591 /* prohibit auto-connect to master, because there isn't one */
592 bus_profile->output_ac = AutoConnectOption (bus_profile->output_ac & ~AutoConnectMaster);
596 add_routes (rl, false, false, false);
599 /* this allows the user to override settings with an environment variable.
602 if (no_auto_connect()) {
603 bus_profile->input_ac = AutoConnectOption (0);
604 bus_profile->output_ac = AutoConnectOption (0);
607 Config->set_input_auto_connect (bus_profile->input_ac);
608 Config->set_output_auto_connect (bus_profile->output_ac);
611 if (Config->get_use_monitor_bus() && bus_profile) {
612 add_monitor_section ();
621 Session::maybe_write_autosave()
623 if (dirty() && record_status() != Recording) {
624 save_state("", true);
629 Session::remove_pending_capture_state ()
631 std::string pending_state_file_path(_session_dir->root_path());
633 pending_state_file_path = Glib::build_filename (pending_state_file_path, legalize_for_path (_current_snapshot_name) + pending_suffix);
635 if (!Glib::file_test (pending_state_file_path, Glib::FILE_TEST_EXISTS)) return;
637 if (g_remove (pending_state_file_path.c_str()) != 0) {
638 error << string_compose(_("Could not remove pending capture state at path \"%1\" (%2)"),
639 pending_state_file_path, g_strerror (errno)) << endmsg;
643 /** Rename a state file.
644 * @param old_name Old snapshot name.
645 * @param new_name New snapshot name.
648 Session::rename_state (string old_name, string new_name)
650 if (old_name == _current_snapshot_name || old_name == _name) {
651 /* refuse to rename the current snapshot or the "main" one */
655 const string old_xml_filename = legalize_for_path (old_name) + statefile_suffix;
656 const string new_xml_filename = legalize_for_path (new_name) + statefile_suffix;
658 const std::string old_xml_path(Glib::build_filename (_session_dir->root_path(), old_xml_filename));
659 const std::string new_xml_path(Glib::build_filename (_session_dir->root_path(), new_xml_filename));
661 if (::g_rename (old_xml_path.c_str(), new_xml_path.c_str()) != 0) {
662 error << string_compose(_("could not rename snapshot %1 to %2 (%3)"),
663 old_name, new_name, g_strerror(errno)) << endmsg;
667 /** Remove a state file.
668 * @param snapshot_name Snapshot name.
671 Session::remove_state (string snapshot_name)
673 if (!_writable || snapshot_name == _current_snapshot_name || snapshot_name == _name) {
674 // refuse to remove the current snapshot or the "main" one
678 std::string xml_path(_session_dir->root_path());
680 xml_path = Glib::build_filename (xml_path, legalize_for_path (snapshot_name) + statefile_suffix);
682 if (!create_backup_file (xml_path)) {
683 // don't remove it if a backup can't be made
684 // create_backup_file will log the error.
689 if (g_remove (xml_path.c_str()) != 0) {
690 error << string_compose(_("Could not remove state file at path \"%1\" (%2)"),
691 xml_path, g_strerror (errno)) << endmsg;
695 #ifdef HAVE_JACK_SESSION
697 Session::jack_session_event (jack_session_event_t * event)
701 struct tm local_time;
704 localtime_r (&n, &local_time);
705 strftime (timebuf, sizeof(timebuf), "JS_%FT%T", &local_time);
707 if (event->type == JackSessionSaveTemplate)
709 if (save_template( timebuf )) {
710 event->flags = JackSessionSaveError;
712 string cmd ("ardour3 -P -U ");
713 cmd += event->client_uuid;
717 event->command_line = strdup (cmd.c_str());
722 if (save_state (timebuf)) {
723 event->flags = JackSessionSaveError;
725 std::string xml_path (_session_dir->root_path());
726 std::string legalized_filename = legalize_for_path (timebuf) + statefile_suffix;
727 xml_path = Glib::build_filename (xml_path, legalized_filename);
729 string cmd ("ardour3 -P -U ");
730 cmd += event->client_uuid;
735 event->command_line = strdup (cmd.c_str());
739 jack_session_reply (_engine.jack(), event);
741 if (event->type == JackSessionSaveAndQuit) {
742 Quit (); /* EMIT SIGNAL */
745 jack_session_event_free( event );
749 /** @param snapshot_name Name to save under, without .ardour / .pending prefix */
751 Session::save_state (string snapshot_name, bool pending, bool switch_to_snapshot)
754 std::string xml_path(_session_dir->root_path());
756 if (!_writable || (_state_of_the_state & CannotSave)) {
760 if (!_engine.connected ()) {
761 error << string_compose (_("the %1 audio engine is not connected and state saving would lose all I/O connections. Session not saved"),
767 /* tell sources we're saving first, in case they write out to a new file
768 * which should be saved with the state rather than the old one */
769 for (SourceMap::const_iterator i = sources.begin(); i != sources.end(); ++i) {
771 i->second->session_saved();
772 } catch (Evoral::SMF::FileError& e) {
773 error << string_compose ("Could not write to MIDI file %1; MIDI data not saved.", e.file_name ()) << endmsg;
777 tree.set_root (&get_state());
779 if (snapshot_name.empty()) {
780 snapshot_name = _current_snapshot_name;
781 } else if (switch_to_snapshot) {
782 _current_snapshot_name = snapshot_name;
787 /* proper save: use statefile_suffix (.ardour in English) */
789 xml_path = Glib::build_filename (xml_path, legalize_for_path (snapshot_name) + statefile_suffix);
791 /* make a backup copy of the old file */
793 if (Glib::file_test (xml_path, Glib::FILE_TEST_EXISTS) && !create_backup_file (xml_path)) {
794 // create_backup_file will log the error
800 /* pending save: use pending_suffix (.pending in English) */
801 xml_path = Glib::build_filename (xml_path, legalize_for_path (snapshot_name) + pending_suffix);
804 std::string tmp_path(_session_dir->root_path());
805 tmp_path = Glib::build_filename (tmp_path, legalize_for_path (snapshot_name) + temp_suffix);
807 // cerr << "actually writing state to " << xml_path << endl;
809 if (!tree.write (tmp_path)) {
810 error << string_compose (_("state could not be saved to %1"), tmp_path) << endmsg;
811 if (g_remove (tmp_path.c_str()) != 0) {
812 error << string_compose(_("Could not remove temporary state file at path \"%1\" (%2)"),
813 tmp_path, g_strerror (errno)) << endmsg;
819 if (::rename (tmp_path.c_str(), xml_path.c_str()) != 0) {
820 error << string_compose (_("could not rename temporary session file %1 to %2"),
821 tmp_path, xml_path) << endmsg;
822 if (g_remove (tmp_path.c_str()) != 0) {
823 error << string_compose(_("Could not remove temporary state file at path \"%1\" (%2)"),
824 tmp_path, g_strerror (errno)) << endmsg;
832 save_history (snapshot_name);
834 bool was_dirty = dirty();
836 _state_of_the_state = StateOfTheState (_state_of_the_state & ~Dirty);
839 DirtyChanged (); /* EMIT SIGNAL */
842 StateSaved (snapshot_name); /* EMIT SIGNAL */
849 Session::restore_state (string snapshot_name)
851 if (load_state (snapshot_name) == 0) {
852 set_state (*state_tree->root(), Stateful::loading_state_version);
859 Session::load_state (string snapshot_name)
864 state_was_pending = false;
866 /* check for leftover pending state from a crashed capture attempt */
868 std::string xmlpath(_session_dir->root_path());
869 xmlpath = Glib::build_filename (xmlpath, legalize_for_path (snapshot_name) + pending_suffix);
871 if (Glib::file_test (xmlpath, Glib::FILE_TEST_EXISTS)) {
873 /* there is pending state from a crashed capture attempt */
875 boost::optional<int> r = AskAboutPendingState();
876 if (r.get_value_or (1)) {
877 state_was_pending = true;
881 if (!state_was_pending) {
882 xmlpath = Glib::build_filename (_session_dir->root_path(), snapshot_name);
885 if (!Glib::file_test (xmlpath, Glib::FILE_TEST_EXISTS)) {
886 xmlpath = Glib::build_filename (_session_dir->root_path(), legalize_for_path (snapshot_name) + statefile_suffix);
887 if (!Glib::file_test (xmlpath, Glib::FILE_TEST_EXISTS)) {
888 error << string_compose(_("%1: session state information file \"%2\" doesn't exist!"), _name, xmlpath) << endmsg;
893 state_tree = new XMLTree;
897 _writable = exists_and_writable (xmlpath);
899 if (!state_tree->read (xmlpath)) {
900 error << string_compose(_("Could not understand ardour file %1"), xmlpath) << endmsg;
906 XMLNode& root (*state_tree->root());
908 if (root.name() != X_("Session")) {
909 error << string_compose (_("Session file %1 is not a session"), xmlpath) << endmsg;
915 const XMLProperty* prop;
917 if ((prop = root.property ("version")) == 0) {
918 /* no version implies very old version of Ardour */
919 Stateful::loading_state_version = 1000;
921 if (prop->value().find ('.') != string::npos) {
922 /* old school version format */
923 if (prop->value()[0] == '2') {
924 Stateful::loading_state_version = 2000;
926 Stateful::loading_state_version = 3000;
929 Stateful::loading_state_version = atoi (prop->value());
933 if (Stateful::loading_state_version < CURRENT_SESSION_FILE_VERSION && _writable) {
935 std::string backup_path(_session_dir->root_path());
936 std::string backup_filename = string_compose ("%1-%2%3", legalize_for_path (snapshot_name), Stateful::loading_state_version, statefile_suffix);
937 backup_path = Glib::build_filename (backup_path, backup_filename);
939 // only create a backup for a given statefile version once
941 if (!Glib::file_test (backup_path, Glib::FILE_TEST_EXISTS)) {
943 info << string_compose (_("Copying old session file %1 to %2\nUse %2 with %3 versions before 2.0 from now on"),
944 xmlpath, backup_path, PROGRAM_NAME)
947 if (!copy_file (xmlpath, backup_path)) {;
957 Session::load_options (const XMLNode& node)
959 LocaleGuard lg (X_("POSIX"));
960 config.set_variables (node);
971 Session::get_template()
973 /* if we don't disable rec-enable, diskstreams
974 will believe they need to store their capture
975 sources in their state node.
978 disable_record (false);
984 Session::state (bool full_state)
986 XMLNode* node = new XMLNode("Session");
990 snprintf(buf, sizeof(buf), "%d", CURRENT_SESSION_FILE_VERSION);
991 node->add_property("version", buf);
993 /* store configuration settings */
997 node->add_property ("name", _name);
998 snprintf (buf, sizeof (buf), "%" PRId64, _nominal_frame_rate);
999 node->add_property ("sample-rate", buf);
1001 if (session_dirs.size() > 1) {
1005 vector<space_and_path>::iterator i = session_dirs.begin();
1006 vector<space_and_path>::iterator next;
1008 ++i; /* skip the first one */
1012 while (i != session_dirs.end()) {
1016 if (next != session_dirs.end()) {
1026 child = node->add_child ("Path");
1027 child->add_content (p);
1031 /* save the ID counter */
1033 snprintf (buf, sizeof (buf), "%" PRIu64, ID::counter());
1034 node->add_property ("id-counter", buf);
1036 /* save the event ID counter */
1038 snprintf (buf, sizeof (buf), "%d", Evoral::event_id_counter());
1039 node->add_property ("event-counter", buf);
1041 /* various options */
1043 node->add_child_nocopy (config.get_variables ());
1045 node->add_child_nocopy (ARDOUR::SessionMetadata::Metadata()->get_state());
1047 child = node->add_child ("Sources");
1050 Glib::Threads::Mutex::Lock sl (source_lock);
1052 for (SourceMap::iterator siter = sources.begin(); siter != sources.end(); ++siter) {
1054 /* Don't save information about non-file Sources, or
1055 * about non-destructive file sources that are empty
1056 * and unused by any regions.
1059 boost::shared_ptr<FileSource> fs;
1061 if ((fs = boost::dynamic_pointer_cast<FileSource> (siter->second)) != 0) {
1063 if (!fs->destructive()) {
1064 if (fs->empty() && !fs->used()) {
1069 child->add_child_nocopy (siter->second->get_state());
1074 child = node->add_child ("Regions");
1077 Glib::Threads::Mutex::Lock rl (region_lock);
1078 const RegionFactory::RegionMap& region_map (RegionFactory::all_regions());
1079 for (RegionFactory::RegionMap::const_iterator i = region_map.begin(); i != region_map.end(); ++i) {
1080 boost::shared_ptr<Region> r = i->second;
1081 /* only store regions not attached to playlists */
1082 if (r->playlist() == 0) {
1083 child->add_child_nocopy (r->state ());
1087 RegionFactory::CompoundAssociations& cassocs (RegionFactory::compound_associations());
1089 if (!cassocs.empty()) {
1090 XMLNode* ca = node->add_child (X_("CompoundAssociations"));
1092 for (RegionFactory::CompoundAssociations::iterator i = cassocs.begin(); i != cassocs.end(); ++i) {
1094 XMLNode* can = new XMLNode (X_("CompoundAssociation"));
1095 i->first->id().print (buf, sizeof (buf));
1096 can->add_property (X_("copy"), buf);
1097 i->second->id().print (buf, sizeof (buf));
1098 can->add_property (X_("original"), buf);
1099 ca->add_child_nocopy (*can);
1105 node->add_child_nocopy (_locations->get_state());
1107 // for a template, just create a new Locations, populate it
1108 // with the default start and end, and get the state for that.
1109 Locations loc (*this);
1110 Location* range = new Location (*this, 0, 0, _("session"), Location::IsSessionRange);
1111 range->set (max_framepos, 0);
1113 node->add_child_nocopy (loc.get_state());
1116 child = node->add_child ("Bundles");
1118 boost::shared_ptr<BundleList> bundles = _bundles.reader ();
1119 for (BundleList::iterator i = bundles->begin(); i != bundles->end(); ++i) {
1120 boost::shared_ptr<UserBundle> b = boost::dynamic_pointer_cast<UserBundle> (*i);
1122 child->add_child_nocopy (b->get_state());
1127 child = node->add_child ("Routes");
1129 boost::shared_ptr<RouteList> r = routes.reader ();
1131 RoutePublicOrderSorter cmp;
1132 RouteList public_order (*r);
1133 public_order.sort (cmp);
1135 /* the sort should have put control outs first */
1138 assert (_monitor_out == public_order.front());
1141 for (RouteList::iterator i = public_order.begin(); i != public_order.end(); ++i) {
1142 if (!(*i)->is_hidden()) {
1144 child->add_child_nocopy ((*i)->get_state());
1146 child->add_child_nocopy ((*i)->get_template());
1152 playlists->add_state (node, full_state);
1154 child = node->add_child ("RouteGroups");
1155 for (list<RouteGroup *>::iterator i = _route_groups.begin(); i != _route_groups.end(); ++i) {
1156 child->add_child_nocopy ((*i)->get_state());
1160 XMLNode* gain_child = node->add_child ("Click");
1161 gain_child->add_child_nocopy (_click_io->state (full_state));
1162 gain_child->add_child_nocopy (_click_gain->state (full_state));
1166 XMLNode* ltc_input_child = node->add_child ("LTC-In");
1167 ltc_input_child->add_child_nocopy (_ltc_input->state (full_state));
1171 XMLNode* ltc_output_child = node->add_child ("LTC-Out");
1172 ltc_output_child->add_child_nocopy (_ltc_output->state (full_state));
1175 node->add_child_nocopy (_speakers->get_state());
1176 node->add_child_nocopy (_tempo_map->get_state());
1177 node->add_child_nocopy (get_control_protocol_state());
1180 node->add_child_copy (*_extra_xml);
1187 Session::get_control_protocol_state ()
1189 ControlProtocolManager& cpm (ControlProtocolManager::instance());
1190 return cpm.get_state();
1194 Session::set_state (const XMLNode& node, int version)
1198 const XMLProperty* prop;
1201 _state_of_the_state = StateOfTheState (_state_of_the_state|CannotSave);
1203 if (node.name() != X_("Session")) {
1204 fatal << _("programming error: Session: incorrect XML node sent to set_state()") << endmsg;
1208 if ((prop = node.property ("name")) != 0) {
1209 _name = prop->value ();
1212 if ((prop = node.property (X_("sample-rate"))) != 0) {
1214 _nominal_frame_rate = atoi (prop->value());
1216 if (_nominal_frame_rate != _current_frame_rate) {
1217 boost::optional<int> r = AskAboutSampleRateMismatch (_nominal_frame_rate, _current_frame_rate);
1218 if (r.get_value_or (0)) {
1224 setup_raid_path(_session_dir->root_path());
1226 if ((prop = node.property (X_("id-counter"))) != 0) {
1228 sscanf (prop->value().c_str(), "%" PRIu64, &x);
1229 ID::init_counter (x);
1231 /* old sessions used a timebased counter, so fake
1232 the startup ID counter based on a standard
1237 ID::init_counter (now);
1240 if ((prop = node.property (X_("event-counter"))) != 0) {
1241 Evoral::init_event_id_counter (atoi (prop->value()));
1244 IO::disable_connecting ();
1246 Stateful::save_extra_xml (node);
1248 if (((child = find_named_node (node, "Options")) != 0)) { /* old style */
1249 load_options (*child);
1250 } else if ((child = find_named_node (node, "Config")) != 0) { /* new style */
1251 load_options (*child);
1253 error << _("Session: XML state has no options section") << endmsg;
1256 if (version >= 3000) {
1257 if ((child = find_named_node (node, "Metadata")) == 0) {
1258 warning << _("Session: XML state has no metadata section") << endmsg;
1259 } else if ( ARDOUR::SessionMetadata::Metadata()->set_state (*child, version) ) {
1264 if ((child = find_named_node (node, X_("Speakers"))) != 0) {
1265 _speakers->set_state (*child, version);
1268 if ((child = find_named_node (node, "Sources")) == 0) {
1269 error << _("Session: XML state has no sources section") << endmsg;
1271 } else if (load_sources (*child)) {
1275 if ((child = find_named_node (node, "TempoMap")) == 0) {
1276 error << _("Session: XML state has no Tempo Map section") << endmsg;
1278 } else if (_tempo_map->set_state (*child, version)) {
1282 if ((child = find_named_node (node, "Locations")) == 0) {
1283 error << _("Session: XML state has no locations section") << endmsg;
1285 } else if (_locations->set_state (*child, version)) {
1291 if ((location = _locations->auto_loop_location()) != 0) {
1292 set_auto_loop_location (location);
1295 if ((location = _locations->auto_punch_location()) != 0) {
1296 set_auto_punch_location (location);
1299 if ((location = _locations->session_range_location()) != 0) {
1300 delete _session_range_location;
1301 _session_range_location = location;
1304 if (_session_range_location) {
1305 AudioFileSource::set_header_position_offset (_session_range_location->start());
1308 if ((child = find_named_node (node, "Regions")) == 0) {
1309 error << _("Session: XML state has no Regions section") << endmsg;
1311 } else if (load_regions (*child)) {
1315 if ((child = find_named_node (node, "Playlists")) == 0) {
1316 error << _("Session: XML state has no playlists section") << endmsg;
1318 } else if (playlists->load (*this, *child)) {
1322 if ((child = find_named_node (node, "UnusedPlaylists")) == 0) {
1324 } else if (playlists->load_unused (*this, *child)) {
1328 if ((child = find_named_node (node, "CompoundAssociations")) != 0) {
1329 if (load_compounds (*child)) {
1334 if (version >= 3000) {
1335 if ((child = find_named_node (node, "Bundles")) == 0) {
1336 warning << _("Session: XML state has no bundles section") << endmsg;
1339 /* We can't load Bundles yet as they need to be able
1340 to convert from port names to Port objects, which can't happen until
1342 _bundle_xml_node = new XMLNode (*child);
1346 if (version < 3000) {
1347 if ((child = find_named_node (node, X_("DiskStreams"))) == 0) {
1348 error << _("Session: XML state has no diskstreams section") << endmsg;
1350 } else if (load_diskstreams_2X (*child, version)) {
1355 if ((child = find_named_node (node, "Routes")) == 0) {
1356 error << _("Session: XML state has no routes section") << endmsg;
1358 } else if (load_routes (*child, version)) {
1362 /* our diskstreams list is no longer needed as they are now all owned by their Route */
1363 _diskstreams_2X.clear ();
1365 if (version >= 3000) {
1367 if ((child = find_named_node (node, "RouteGroups")) == 0) {
1368 error << _("Session: XML state has no route groups section") << endmsg;
1370 } else if (load_route_groups (*child, version)) {
1374 } else if (version < 3000) {
1376 if ((child = find_named_node (node, "EditGroups")) == 0) {
1377 error << _("Session: XML state has no edit groups section") << endmsg;
1379 } else if (load_route_groups (*child, version)) {
1383 if ((child = find_named_node (node, "MixGroups")) == 0) {
1384 error << _("Session: XML state has no mix groups section") << endmsg;
1386 } else if (load_route_groups (*child, version)) {
1391 if ((child = find_named_node (node, "Click")) == 0) {
1392 warning << _("Session: XML state has no click section") << endmsg;
1393 } else if (_click_io) {
1394 const XMLNodeList& children (child->children());
1395 XMLNodeList::const_iterator i = children.begin();
1396 _click_io->set_state (**i, version);
1398 if (i != children.end()) {
1399 _click_gain->set_state (**i, version);
1403 if ((child = find_named_node (node, ControlProtocolManager::state_node_name)) != 0) {
1404 ControlProtocolManager::instance().set_state (*child, version);
1407 update_have_rec_enabled_track ();
1409 /* here beginneth the second phase ... */
1411 StateReady (); /* EMIT SIGNAL */
1420 Session::load_routes (const XMLNode& node, int version)
1423 XMLNodeConstIterator niter;
1424 RouteList new_routes;
1426 nlist = node.children();
1430 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1432 boost::shared_ptr<Route> route;
1433 if (version < 3000) {
1434 route = XMLRouteFactory_2X (**niter, version);
1436 route = XMLRouteFactory (**niter, version);
1440 error << _("Session: cannot create Route from XML description.") << endmsg;
1444 BootMessage (string_compose (_("Loaded track/bus %1"), route->name()));
1446 new_routes.push_back (route);
1449 add_routes (new_routes, false, false, false);
1454 boost::shared_ptr<Route>
1455 Session::XMLRouteFactory (const XMLNode& node, int version)
1457 boost::shared_ptr<Route> ret;
1459 if (node.name() != "Route") {
1463 XMLNode* ds_child = find_named_node (node, X_("Diskstream"));
1465 DataType type = DataType::AUDIO;
1466 const XMLProperty* prop = node.property("default-type");
1469 type = DataType (prop->value());
1472 assert (type != DataType::NIL);
1476 boost::shared_ptr<Track> track;
1478 if (type == DataType::AUDIO) {
1479 track.reset (new AudioTrack (*this, X_("toBeResetFroXML")));
1481 track.reset (new MidiTrack (*this, X_("toBeResetFroXML")));
1484 if (track->init()) {
1488 if (track->set_state (node, version)) {
1492 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
1493 // boost_debug_shared_ptr_mark_interesting (track.get(), "Track");
1498 boost::shared_ptr<Route> r (new Route (*this, X_("toBeResetFroXML")));
1500 if (r->init () == 0 && r->set_state (node, version) == 0) {
1501 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
1502 // boost_debug_shared_ptr_mark_interesting (r.get(), "Route");
1511 boost::shared_ptr<Route>
1512 Session::XMLRouteFactory_2X (const XMLNode& node, int version)
1514 boost::shared_ptr<Route> ret;
1516 if (node.name() != "Route") {
1520 XMLProperty const * ds_prop = node.property (X_("diskstream-id"));
1522 ds_prop = node.property (X_("diskstream"));
1525 DataType type = DataType::AUDIO;
1526 const XMLProperty* prop = node.property("default-type");
1529 type = DataType (prop->value());
1532 assert (type != DataType::NIL);
1536 list<boost::shared_ptr<Diskstream> >::iterator i = _diskstreams_2X.begin ();
1537 while (i != _diskstreams_2X.end() && (*i)->id() != ds_prop->value()) {
1541 if (i == _diskstreams_2X.end()) {
1542 error << _("Could not find diskstream for route") << endmsg;
1543 return boost::shared_ptr<Route> ();
1546 boost::shared_ptr<Track> track;
1548 if (type == DataType::AUDIO) {
1549 track.reset (new AudioTrack (*this, X_("toBeResetFroXML")));
1551 track.reset (new MidiTrack (*this, X_("toBeResetFroXML")));
1554 if (track->init()) {
1558 if (track->set_state (node, version)) {
1562 track->set_diskstream (*i);
1564 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
1565 // boost_debug_shared_ptr_mark_interesting (track.get(), "Track");
1570 boost::shared_ptr<Route> r (new Route (*this, X_("toBeResetFroXML")));
1572 if (r->init () == 0 && r->set_state (node, version) == 0) {
1573 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
1574 // boost_debug_shared_ptr_mark_interesting (r.get(), "Route");
1584 Session::load_regions (const XMLNode& node)
1587 XMLNodeConstIterator niter;
1588 boost::shared_ptr<Region> region;
1590 nlist = node.children();
1594 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1595 if ((region = XMLRegionFactory (**niter, false)) == 0) {
1596 error << _("Session: cannot create Region from XML description.");
1597 const XMLProperty *name = (**niter).property("name");
1600 error << " " << string_compose (_("Can not load state for region '%1'"), name->value());
1611 Session::load_compounds (const XMLNode& node)
1613 XMLNodeList calist = node.children();
1614 XMLNodeConstIterator caiter;
1615 XMLProperty *caprop;
1617 for (caiter = calist.begin(); caiter != calist.end(); ++caiter) {
1618 XMLNode* ca = *caiter;
1622 if ((caprop = ca->property (X_("original"))) == 0) {
1625 orig_id = caprop->value();
1627 if ((caprop = ca->property (X_("copy"))) == 0) {
1630 copy_id = caprop->value();
1632 boost::shared_ptr<Region> orig = RegionFactory::region_by_id (orig_id);
1633 boost::shared_ptr<Region> copy = RegionFactory::region_by_id (copy_id);
1635 if (!orig || !copy) {
1636 warning << string_compose (_("Regions in compound description not found (ID's %1 and %2): ignored"),
1642 RegionFactory::add_compound_association (orig, copy);
1649 Session::load_nested_sources (const XMLNode& node)
1652 XMLNodeConstIterator niter;
1654 nlist = node.children();
1656 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1657 if ((*niter)->name() == "Source") {
1659 /* it may already exist, so don't recreate it unnecessarily
1662 XMLProperty* prop = (*niter)->property (X_("id"));
1664 error << _("Nested source has no ID info in session state file! (ignored)") << endmsg;
1668 ID source_id (prop->value());
1670 if (!source_by_id (source_id)) {
1673 SourceFactory::create (*this, **niter, true);
1675 catch (failed_constructor& err) {
1676 error << string_compose (_("Cannot reconstruct nested source for region %1"), name()) << endmsg;
1683 boost::shared_ptr<Region>
1684 Session::XMLRegionFactory (const XMLNode& node, bool full)
1686 const XMLProperty* type = node.property("type");
1690 const XMLNodeList& nlist = node.children();
1692 for (XMLNodeConstIterator niter = nlist.begin(); niter != nlist.end(); ++niter) {
1693 XMLNode *child = (*niter);
1694 if (child->name() == "NestedSource") {
1695 load_nested_sources (*child);
1699 if (!type || type->value() == "audio") {
1700 return boost::shared_ptr<Region>(XMLAudioRegionFactory (node, full));
1701 } else if (type->value() == "midi") {
1702 return boost::shared_ptr<Region>(XMLMidiRegionFactory (node, full));
1705 } catch (failed_constructor& err) {
1706 return boost::shared_ptr<Region> ();
1709 return boost::shared_ptr<Region> ();
1712 boost::shared_ptr<AudioRegion>
1713 Session::XMLAudioRegionFactory (const XMLNode& node, bool /*full*/)
1715 const XMLProperty* prop;
1716 boost::shared_ptr<Source> source;
1717 boost::shared_ptr<AudioSource> as;
1719 SourceList master_sources;
1720 uint32_t nchans = 1;
1723 if (node.name() != X_("Region")) {
1724 return boost::shared_ptr<AudioRegion>();
1727 if ((prop = node.property (X_("channels"))) != 0) {
1728 nchans = atoi (prop->value().c_str());
1731 if ((prop = node.property ("name")) == 0) {
1732 cerr << "no name for this region\n";
1736 if ((prop = node.property (X_("source-0"))) == 0) {
1737 if ((prop = node.property ("source")) == 0) {
1738 error << _("Session: XMLNode describing a AudioRegion is incomplete (no source)") << endmsg;
1739 return boost::shared_ptr<AudioRegion>();
1743 PBD::ID s_id (prop->value());
1745 if ((source = source_by_id (s_id)) == 0) {
1746 error << string_compose(_("Session: XMLNode describing a AudioRegion references an unknown source id =%1"), s_id) << endmsg;
1747 return boost::shared_ptr<AudioRegion>();
1750 as = boost::dynamic_pointer_cast<AudioSource>(source);
1752 error << string_compose(_("Session: XMLNode describing a AudioRegion references a non-audio source id =%1"), s_id) << endmsg;
1753 return boost::shared_ptr<AudioRegion>();
1756 sources.push_back (as);
1758 /* pickup other channels */
1760 for (uint32_t n=1; n < nchans; ++n) {
1761 snprintf (buf, sizeof(buf), X_("source-%d"), n);
1762 if ((prop = node.property (buf)) != 0) {
1764 PBD::ID id2 (prop->value());
1766 if ((source = source_by_id (id2)) == 0) {
1767 error << string_compose(_("Session: XMLNode describing a AudioRegion references an unknown source id =%1"), id2) << endmsg;
1768 return boost::shared_ptr<AudioRegion>();
1771 as = boost::dynamic_pointer_cast<AudioSource>(source);
1773 error << string_compose(_("Session: XMLNode describing a AudioRegion references a non-audio source id =%1"), id2) << endmsg;
1774 return boost::shared_ptr<AudioRegion>();
1776 sources.push_back (as);
1780 for (uint32_t n = 0; n < nchans; ++n) {
1781 snprintf (buf, sizeof(buf), X_("master-source-%d"), n);
1782 if ((prop = node.property (buf)) != 0) {
1784 PBD::ID id2 (prop->value());
1786 if ((source = source_by_id (id2)) == 0) {
1787 error << string_compose(_("Session: XMLNode describing a AudioRegion references an unknown source id =%1"), id2) << endmsg;
1788 return boost::shared_ptr<AudioRegion>();
1791 as = boost::dynamic_pointer_cast<AudioSource>(source);
1793 error << string_compose(_("Session: XMLNode describing a AudioRegion references a non-audio source id =%1"), id2) << endmsg;
1794 return boost::shared_ptr<AudioRegion>();
1796 master_sources.push_back (as);
1801 boost::shared_ptr<AudioRegion> region (boost::dynamic_pointer_cast<AudioRegion> (RegionFactory::create (sources, node)));
1803 /* a final detail: this is the one and only place that we know how long missing files are */
1805 if (region->whole_file()) {
1806 for (SourceList::iterator sx = sources.begin(); sx != sources.end(); ++sx) {
1807 boost::shared_ptr<SilentFileSource> sfp = boost::dynamic_pointer_cast<SilentFileSource> (*sx);
1809 sfp->set_length (region->length());
1814 if (!master_sources.empty()) {
1815 if (master_sources.size() != nchans) {
1816 error << _("Session: XMLNode describing an AudioRegion is missing some master sources; ignored") << endmsg;
1818 region->set_master_sources (master_sources);
1826 catch (failed_constructor& err) {
1827 return boost::shared_ptr<AudioRegion>();
1831 boost::shared_ptr<MidiRegion>
1832 Session::XMLMidiRegionFactory (const XMLNode& node, bool /*full*/)
1834 const XMLProperty* prop;
1835 boost::shared_ptr<Source> source;
1836 boost::shared_ptr<MidiSource> ms;
1839 if (node.name() != X_("Region")) {
1840 return boost::shared_ptr<MidiRegion>();
1843 if ((prop = node.property ("name")) == 0) {
1844 cerr << "no name for this region\n";
1848 if ((prop = node.property (X_("source-0"))) == 0) {
1849 if ((prop = node.property ("source")) == 0) {
1850 error << _("Session: XMLNode describing a MidiRegion is incomplete (no source)") << endmsg;
1851 return boost::shared_ptr<MidiRegion>();
1855 PBD::ID s_id (prop->value());
1857 if ((source = source_by_id (s_id)) == 0) {
1858 error << string_compose(_("Session: XMLNode describing a MidiRegion references an unknown source id =%1"), s_id) << endmsg;
1859 return boost::shared_ptr<MidiRegion>();
1862 ms = boost::dynamic_pointer_cast<MidiSource>(source);
1864 error << string_compose(_("Session: XMLNode describing a MidiRegion references a non-midi source id =%1"), s_id) << endmsg;
1865 return boost::shared_ptr<MidiRegion>();
1868 sources.push_back (ms);
1871 boost::shared_ptr<MidiRegion> region (boost::dynamic_pointer_cast<MidiRegion> (RegionFactory::create (sources, node)));
1872 /* a final detail: this is the one and only place that we know how long missing files are */
1874 if (region->whole_file()) {
1875 for (SourceList::iterator sx = sources.begin(); sx != sources.end(); ++sx) {
1876 boost::shared_ptr<SilentFileSource> sfp = boost::dynamic_pointer_cast<SilentFileSource> (*sx);
1878 sfp->set_length (region->length());
1886 catch (failed_constructor& err) {
1887 return boost::shared_ptr<MidiRegion>();
1892 Session::get_sources_as_xml ()
1895 XMLNode* node = new XMLNode (X_("Sources"));
1896 Glib::Threads::Mutex::Lock lm (source_lock);
1898 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ++i) {
1899 node->add_child_nocopy (i->second->get_state());
1906 Session::path_from_region_name (DataType type, string name, string identifier)
1908 char buf[PATH_MAX+1];
1910 SessionDirectory sdir(get_best_session_directory_for_new_source());
1911 std::string source_dir = ((type == DataType::AUDIO)
1912 ? sdir.sound_path() : sdir.midi_path());
1914 string ext = native_header_format_extension (config.get_native_file_header_format(), type);
1916 for (n = 0; n < 999999; ++n) {
1917 if (identifier.length()) {
1918 snprintf (buf, sizeof(buf), "%s%s%" PRIu32 "%s", name.c_str(),
1919 identifier.c_str(), n, ext.c_str());
1921 snprintf (buf, sizeof(buf), "%s-%" PRIu32 "%s", name.c_str(),
1925 std::string source_path = Glib::build_filename (source_dir, buf);
1927 if (!Glib::file_test (source_path, Glib::FILE_TEST_EXISTS)) {
1932 error << string_compose (_("cannot create new file from region name \"%1\" with ident = \"%2\": too many existing files with similar names"),
1941 Session::load_sources (const XMLNode& node)
1944 XMLNodeConstIterator niter;
1945 boost::shared_ptr<Source> source;
1947 nlist = node.children();
1951 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1954 if ((source = XMLSourceFactory (**niter)) == 0) {
1955 error << _("Session: cannot create Source from XML description.") << endmsg;
1958 } catch (MissingSource& err) {
1962 if (!no_questions_about_missing_files) {
1963 user_choice = MissingFile (this, err.path, err.type).get_value_or (-1);
1968 switch (user_choice) {
1970 /* user added a new search location, so try again */
1975 /* user asked to quit the entire session load
1980 no_questions_about_missing_files = true;
1984 no_questions_about_missing_files = true;
1989 warning << _("A sound file is missing. It will be replaced by silence.") << endmsg;
1990 source = SourceFactory::createSilent (*this, **niter, max_framecnt, _current_frame_rate);
1999 boost::shared_ptr<Source>
2000 Session::XMLSourceFactory (const XMLNode& node)
2002 if (node.name() != "Source") {
2003 return boost::shared_ptr<Source>();
2007 /* note: do peak building in another thread when loading session state */
2008 return SourceFactory::create (*this, node, true);
2011 catch (failed_constructor& err) {
2012 error << string_compose (_("Found a sound file that cannot be used by %1. Talk to the progammers."), PROGRAM_NAME) << endmsg;
2013 return boost::shared_ptr<Source>();
2018 Session::save_template (string template_name)
2022 if (_state_of_the_state & CannotSave) {
2026 std::string user_template_dir(user_template_directory());
2028 if (g_mkdir_with_parents (user_template_dir.c_str(), 0755) != 0) {
2029 error << string_compose(_("Could not create templates directory \"%1\" (%2)"),
2030 user_template_dir, g_strerror (errno)) << endmsg;
2034 tree.set_root (&get_template());
2036 std::string template_dir_path(user_template_dir);
2038 /* directory to put the template in */
2039 template_dir_path = Glib::build_filename (template_dir_path, template_name);
2041 if (Glib::file_test (template_dir_path, Glib::FILE_TEST_EXISTS)) {
2042 warning << string_compose(_("Template \"%1\" already exists - new version not created"),
2043 template_dir_path) << endmsg;
2047 if (g_mkdir_with_parents (template_dir_path.c_str(), 0755) != 0) {
2048 error << string_compose(_("Could not create directory for Session template\"%1\" (%2)"),
2049 template_dir_path, g_strerror (errno)) << endmsg;
2054 std::string template_file_path(template_dir_path);
2055 template_file_path = Glib::build_filename (template_file_path, template_name + template_suffix);
2057 if (!tree.write (template_file_path)) {
2058 error << _("template not saved") << endmsg;
2062 /* copy plugin state directory */
2064 std::string template_plugin_state_path(template_dir_path);
2065 template_plugin_state_path = Glib::build_filename (template_plugin_state_path, X_("plugins"));
2067 if (g_mkdir_with_parents (template_plugin_state_path.c_str(), 0755) != 0) {
2068 error << string_compose(_("Could not create directory for Session template plugin state\"%1\" (%2)"),
2069 template_plugin_state_path, g_strerror (errno)) << endmsg;
2073 copy_files (plugins_dir(), template_plugin_state_path);
2079 Session::refresh_disk_space ()
2081 #if HAVE_SYS_VFS_H && HAVE_SYS_STATVFS_H
2083 Glib::Threads::Mutex::Lock lm (space_lock);
2085 /* get freespace on every FS that is part of the session path */
2087 _total_free_4k_blocks = 0;
2088 _total_free_4k_blocks_uncertain = false;
2090 for (vector<space_and_path>::iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
2092 struct statfs statfsbuf;
2093 statfs (i->path.c_str(), &statfsbuf);
2095 double const scale = statfsbuf.f_bsize / 4096.0;
2097 /* See if this filesystem is read-only */
2098 struct statvfs statvfsbuf;
2099 statvfs (i->path.c_str(), &statvfsbuf);
2101 /* f_bavail can be 0 if it is undefined for whatever
2102 filesystem we are looking at; Samba shares mounted
2103 via GVFS are an example of this.
2105 if (statfsbuf.f_bavail == 0) {
2106 /* block count unknown */
2108 i->blocks_unknown = true;
2109 } else if (statvfsbuf.f_flag & ST_RDONLY) {
2110 /* read-only filesystem */
2112 i->blocks_unknown = false;
2114 /* read/write filesystem with known space */
2115 i->blocks = (uint32_t) floor (statfsbuf.f_bavail * scale);
2116 i->blocks_unknown = false;
2119 _total_free_4k_blocks += i->blocks;
2120 if (i->blocks_unknown) {
2121 _total_free_4k_blocks_uncertain = true;
2128 Session::get_best_session_directory_for_new_source ()
2130 vector<space_and_path>::iterator i;
2131 string result = _session_dir->root_path();
2133 /* handle common case without system calls */
2135 if (session_dirs.size() == 1) {
2139 /* OK, here's the algorithm we're following here:
2141 We want to select which directory to use for
2142 the next file source to be created. Ideally,
2143 we'd like to use a round-robin process so as to
2144 get maximum performance benefits from splitting
2145 the files across multiple disks.
2147 However, in situations without much diskspace, an
2148 RR approach may end up filling up a filesystem
2149 with new files while others still have space.
2150 Its therefore important to pay some attention to
2151 the freespace in the filesystem holding each
2152 directory as well. However, if we did that by
2153 itself, we'd keep creating new files in the file
2154 system with the most space until it was as full
2155 as all others, thus negating any performance
2156 benefits of this RAID-1 like approach.
2158 So, we use a user-configurable space threshold. If
2159 there are at least 2 filesystems with more than this
2160 much space available, we use RR selection between them.
2161 If not, then we pick the filesystem with the most space.
2163 This gets a good balance between the two
2167 refresh_disk_space ();
2169 int free_enough = 0;
2171 for (i = session_dirs.begin(); i != session_dirs.end(); ++i) {
2172 if ((*i).blocks * 4096 >= Config->get_disk_choice_space_threshold()) {
2177 if (free_enough >= 2) {
2178 /* use RR selection process, ensuring that the one
2182 i = last_rr_session_dir;
2185 if (++i == session_dirs.end()) {
2186 i = session_dirs.begin();
2189 if ((*i).blocks * 4096 >= Config->get_disk_choice_space_threshold()) {
2190 SessionDirectory sdir(i->path);
2191 if (sdir.create ()) {
2193 last_rr_session_dir = i;
2198 } while (i != last_rr_session_dir);
2202 /* pick FS with the most freespace (and that
2203 seems to actually work ...)
2206 vector<space_and_path> sorted;
2207 space_and_path_ascending_cmp cmp;
2209 sorted = session_dirs;
2210 sort (sorted.begin(), sorted.end(), cmp);
2212 for (i = sorted.begin(); i != sorted.end(); ++i) {
2213 SessionDirectory sdir(i->path);
2214 if (sdir.create ()) {
2216 last_rr_session_dir = i;
2226 Session::automation_dir () const
2228 return Glib::build_filename (_path, "automation");
2232 Session::analysis_dir () const
2234 return Glib::build_filename (_path, "analysis");
2238 Session::plugins_dir () const
2240 return Glib::build_filename (_path, "plugins");
2244 Session::externals_dir () const
2246 return Glib::build_filename (_path, "externals");
2250 Session::load_bundles (XMLNode const & node)
2252 XMLNodeList nlist = node.children();
2253 XMLNodeConstIterator niter;
2257 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2258 if ((*niter)->name() == "InputBundle") {
2259 add_bundle (boost::shared_ptr<UserBundle> (new UserBundle (**niter, true)));
2260 } else if ((*niter)->name() == "OutputBundle") {
2261 add_bundle (boost::shared_ptr<UserBundle> (new UserBundle (**niter, false)));
2263 error << string_compose(_("Unknown node \"%1\" found in Bundles list from state file"), (*niter)->name()) << endmsg;
2272 Session::load_route_groups (const XMLNode& node, int version)
2274 XMLNodeList nlist = node.children();
2275 XMLNodeConstIterator niter;
2279 if (version >= 3000) {
2281 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2282 if ((*niter)->name() == "RouteGroup") {
2283 RouteGroup* rg = new RouteGroup (*this, "");
2284 add_route_group (rg);
2285 rg->set_state (**niter, version);
2289 } else if (version < 3000) {
2291 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2292 if ((*niter)->name() == "EditGroup" || (*niter)->name() == "MixGroup") {
2293 RouteGroup* rg = new RouteGroup (*this, "");
2294 add_route_group (rg);
2295 rg->set_state (**niter, version);
2304 Session::auto_save()
2306 save_state (_current_snapshot_name);
2310 state_file_filter (const string &str, void */*arg*/)
2312 return (str.length() > strlen(statefile_suffix) &&
2313 str.find (statefile_suffix) == (str.length() - strlen (statefile_suffix)));
2317 bool operator()(const string* a, const string* b) {
2323 remove_end(string* state)
2325 string statename(*state);
2327 string::size_type start,end;
2328 if ((start = statename.find_last_of (G_DIR_SEPARATOR)) != string::npos) {
2329 statename = statename.substr (start+1);
2332 if ((end = statename.rfind(".ardour")) == string::npos) {
2333 end = statename.length();
2336 return new string(statename.substr (0, end));
2340 Session::possible_states (string path)
2342 PathScanner scanner;
2343 vector<string*>* states = scanner (path, state_file_filter, 0, false, false);
2345 transform(states->begin(), states->end(), states->begin(), remove_end);
2348 sort (states->begin(), states->end(), cmp);
2354 Session::possible_states () const
2356 return possible_states(_path);
2360 Session::add_route_group (RouteGroup* g)
2362 _route_groups.push_back (g);
2363 route_group_added (g); /* EMIT SIGNAL */
2365 g->RouteAdded.connect_same_thread (*this, boost::bind (&Session::route_added_to_route_group, this, _1, _2));
2366 g->RouteRemoved.connect_same_thread (*this, boost::bind (&Session::route_removed_from_route_group, this, _1, _2));
2367 g->PropertyChanged.connect_same_thread (*this, boost::bind (&Session::route_group_property_changed, this, g));
2373 Session::remove_route_group (RouteGroup& rg)
2375 list<RouteGroup*>::iterator i;
2377 if ((i = find (_route_groups.begin(), _route_groups.end(), &rg)) != _route_groups.end()) {
2378 _route_groups.erase (i);
2381 route_group_removed (); /* EMIT SIGNAL */
2385 /** Set a new order for our route groups, without adding or removing any.
2386 * @param groups Route group list in the new order.
2389 Session::reorder_route_groups (list<RouteGroup*> groups)
2391 _route_groups = groups;
2393 route_groups_reordered (); /* EMIT SIGNAL */
2399 Session::route_group_by_name (string name)
2401 list<RouteGroup *>::iterator i;
2403 for (i = _route_groups.begin(); i != _route_groups.end(); ++i) {
2404 if ((*i)->name() == name) {
2412 Session::all_route_group() const
2414 return *_all_route_group;
2418 Session::add_commands (vector<Command*> const & cmds)
2420 for (vector<Command*>::const_iterator i = cmds.begin(); i != cmds.end(); ++i) {
2426 Session::begin_reversible_command (const string& name)
2428 begin_reversible_command (g_quark_from_string (name.c_str ()));
2431 /** Begin a reversible command using a GQuark to identify it.
2432 * begin_reversible_command() and commit_reversible_command() calls may be nested,
2433 * but there must be as many begin...()s as there are commit...()s.
2436 Session::begin_reversible_command (GQuark q)
2438 /* If nested begin/commit pairs are used, we create just one UndoTransaction
2439 to hold all the commands that are committed. This keeps the order of
2440 commands correct in the history.
2443 if (_current_trans == 0) {
2444 /* start a new transaction */
2445 assert (_current_trans_quarks.empty ());
2446 _current_trans = new UndoTransaction();
2447 _current_trans->set_name (g_quark_to_string (q));
2450 _current_trans_quarks.push_front (q);
2454 Session::commit_reversible_command (Command *cmd)
2456 assert (_current_trans);
2457 assert (!_current_trans_quarks.empty ());
2462 _current_trans->add_command (cmd);
2465 _current_trans_quarks.pop_front ();
2467 if (!_current_trans_quarks.empty ()) {
2468 /* the transaction we're committing is not the top-level one */
2472 if (_current_trans->empty()) {
2473 /* no commands were added to the transaction, so just get rid of it */
2474 delete _current_trans;
2479 gettimeofday (&now, 0);
2480 _current_trans->set_timestamp (now);
2482 _history.add (_current_trans);
2487 accept_all_audio_files (const string& path, void */*arg*/)
2489 if (!Glib::file_test (path, Glib::FILE_TEST_IS_REGULAR)) {
2493 if (!AudioFileSource::safe_audio_file_extension (path)) {
2501 accept_all_midi_files (const string& path, void */*arg*/)
2503 if (!Glib::file_test (path, Glib::FILE_TEST_IS_REGULAR)) {
2507 return ((path.length() > 4 && path.find (".mid") != (path.length() - 4)) ||
2508 (path.length() > 4 && path.find (".smf") != (path.length() - 4)) ||
2509 (path.length() > 5 && path.find (".midi") != (path.length() - 5)));
2513 accept_all_state_files (const string& path, void */*arg*/)
2515 if (!Glib::file_test (path, Glib::FILE_TEST_IS_REGULAR)) {
2519 return (path.length() > 7 && path.find (".ardour") == (path.length() - 7));
2523 Session::find_all_sources (string path, set<string>& result)
2528 if (!tree.read (path)) {
2532 if ((node = find_named_node (*tree.root(), "Sources")) == 0) {
2537 XMLNodeConstIterator niter;
2539 nlist = node->children();
2543 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2547 if ((prop = (*niter)->property (X_("type"))) == 0) {
2551 DataType type (prop->value());
2553 if ((prop = (*niter)->property (X_("name"))) == 0) {
2557 if (Glib::path_is_absolute (prop->value())) {
2558 /* external file, ignore */
2566 if (FileSource::find (*this, type, prop->value(), true, is_new, chan, found_path)) {
2567 result.insert (found_path);
2575 Session::find_all_sources_across_snapshots (set<string>& result, bool exclude_this_snapshot)
2577 PathScanner scanner;
2578 vector<string*>* state_files;
2580 string this_snapshot_path;
2586 if (ripped[ripped.length()-1] == G_DIR_SEPARATOR) {
2587 ripped = ripped.substr (0, ripped.length() - 1);
2590 state_files = scanner (ripped, accept_all_state_files, (void *) 0, true, true);
2592 if (state_files == 0) {
2597 this_snapshot_path = _path;
2598 this_snapshot_path += legalize_for_path (_current_snapshot_name);
2599 this_snapshot_path += statefile_suffix;
2601 for (vector<string*>::iterator i = state_files->begin(); i != state_files->end(); ++i) {
2603 if (exclude_this_snapshot && **i == this_snapshot_path) {
2607 if (find_all_sources (**i, result) < 0) {
2615 struct RegionCounter {
2616 typedef std::map<PBD::ID,boost::shared_ptr<AudioSource> > AudioSourceList;
2617 AudioSourceList::iterator iter;
2618 boost::shared_ptr<Region> region;
2621 RegionCounter() : count (0) {}
2625 Session::ask_about_playlist_deletion (boost::shared_ptr<Playlist> p)
2627 boost::optional<int> r = AskAboutPlaylistDeletion (p);
2628 return r.get_value_or (1);
2632 Session::cleanup_regions ()
2634 const RegionFactory::RegionMap& regions (RegionFactory::regions());
2636 for (RegionFactory::RegionMap::const_iterator i = regions.begin(); i != regions.end(); ++i) {
2638 uint32_t used = playlists->region_use_count (i->second);
2640 if (used == 0 && !i->second->automatic ()) {
2641 RegionFactory::map_remove (i->second);
2645 /* dump the history list */
2652 Session::cleanup_sources (CleanupReport& rep)
2654 // FIXME: needs adaptation to midi
2656 vector<boost::shared_ptr<Source> > dead_sources;
2657 PathScanner scanner;
2660 vector<space_and_path>::iterator i;
2661 vector<space_and_path>::iterator nexti;
2662 vector<string*>* candidates;
2663 vector<string*>* candidates2;
2664 vector<string> unused;
2665 set<string> all_sources;
2670 _state_of_the_state = (StateOfTheState) (_state_of_the_state | InCleanup);
2672 /* consider deleting all unused playlists */
2674 if (playlists->maybe_delete_unused (boost::bind (Session::ask_about_playlist_deletion, _1))) {
2679 /* sync the "all regions" property of each playlist with its current state
2682 playlists->sync_all_regions_with_regions ();
2684 /* find all un-used sources */
2689 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ) {
2691 SourceMap::iterator tmp;
2696 /* do not bother with files that are zero size, otherwise we remove the current "nascent"
2700 if (!i->second->used() && (i->second->length(i->second->timeline_position() > 0))) {
2701 dead_sources.push_back (i->second);
2702 i->second->drop_references ();
2708 /* build a list of all the possible audio directories for the session */
2710 for (i = session_dirs.begin(); i != session_dirs.end(); ) {
2715 SessionDirectory sdir ((*i).path);
2716 audio_path += sdir.sound_path();
2718 if (nexti != session_dirs.end()) {
2726 /* build a list of all the possible midi directories for the session */
2728 for (i = session_dirs.begin(); i != session_dirs.end(); ) {
2733 SessionDirectory sdir ((*i).path);
2734 midi_path += sdir.midi_path();
2736 if (nexti != session_dirs.end()) {
2743 candidates = scanner (audio_path, accept_all_audio_files, (void *) 0, true, true);
2744 candidates2 = scanner (midi_path, accept_all_midi_files, (void *) 0, true, true);
2750 for (vector<string*>::iterator i = candidates2->begin(); i != candidates2->end(); ++i) {
2751 candidates->push_back (*i);
2756 candidates = candidates2; // might still be null
2759 /* find all sources, but don't use this snapshot because the
2760 state file on disk still references sources we may have already
2764 find_all_sources_across_snapshots (all_sources, true);
2766 /* add our current source list
2769 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ) {
2770 boost::shared_ptr<FileSource> fs;
2771 SourceMap::iterator tmp = i;
2774 if ((fs = boost::dynamic_pointer_cast<FileSource> (i->second)) != 0) {
2775 if (playlists->source_use_count (fs) != 0) {
2776 all_sources.insert (fs->path());
2779 /* we might not remove this source from disk, because it may be used
2780 by other snapshots, but its not being used in this version
2781 so lets get rid of it now, along with any representative regions
2785 RegionFactory::remove_regions_using_source (i->second);
2793 char tmppath1[PATH_MAX+1];
2794 char tmppath2[PATH_MAX+1];
2797 for (vector<string*>::iterator x = candidates->begin(); x != candidates->end(); ++x) {
2802 for (set<string>::iterator i = all_sources.begin(); i != all_sources.end(); ++i) {
2804 if (realpath(spath.c_str(), tmppath1) == 0) {
2805 error << string_compose (_("Cannot expand path %1 (%2)"),
2806 spath, strerror (errno)) << endmsg;
2810 if (realpath((*i).c_str(), tmppath2) == 0) {
2811 error << string_compose (_("Cannot expand path %1 (%2)"),
2812 (*i), strerror (errno)) << endmsg;
2816 if (strcmp(tmppath1, tmppath2) == 0) {
2823 unused.push_back (spath);
2832 /* now try to move all unused files into the "dead" directory(ies) */
2834 for (vector<string>::iterator x = unused.begin(); x != unused.end(); ++x) {
2835 struct stat statbuf;
2839 /* don't move the file across filesystems, just
2840 stick it in the `dead_dir_name' directory
2841 on whichever filesystem it was already on.
2844 if ((*x).find ("/sounds/") != string::npos) {
2846 /* old school, go up 1 level */
2848 newpath = Glib::path_get_dirname (*x); // "sounds"
2849 newpath = Glib::path_get_dirname (newpath); // "session-name"
2853 /* new school, go up 4 levels */
2855 newpath = Glib::path_get_dirname (*x); // "audiofiles" or "midifiles"
2856 newpath = Glib::path_get_dirname (newpath); // "session-name"
2857 newpath = Glib::path_get_dirname (newpath); // "interchange"
2858 newpath = Glib::path_get_dirname (newpath); // "session-dir"
2861 newpath = Glib::build_filename (newpath, dead_dir_name);
2863 if (g_mkdir_with_parents (newpath.c_str(), 0755) < 0) {
2864 error << string_compose(_("Session: cannot create dead file folder \"%1\" (%2)"), newpath, strerror (errno)) << endmsg;
2868 newpath = Glib::build_filename (newpath, Glib::path_get_basename ((*x)));
2870 if (Glib::file_test (newpath, Glib::FILE_TEST_EXISTS)) {
2872 /* the new path already exists, try versioning */
2874 char buf[PATH_MAX+1];
2878 snprintf (buf, sizeof (buf), "%s.%d", newpath.c_str(), version);
2881 while (Glib::file_test (newpath_v.c_str(), Glib::FILE_TEST_EXISTS) && version < 999) {
2882 snprintf (buf, sizeof (buf), "%s.%d", newpath.c_str(), ++version);
2886 if (version == 999) {
2887 error << string_compose (_("there are already 1000 files with names like %1; versioning discontinued"),
2891 newpath = newpath_v;
2896 /* it doesn't exist, or we can't read it or something */
2900 stat ((*x).c_str(), &statbuf);
2902 if (::rename ((*x).c_str(), newpath.c_str()) != 0) {
2903 error << string_compose (_("cannot rename unused file source from %1 to %2 (%3)"),
2904 (*x), newpath, strerror (errno))
2909 /* see if there an easy to find peakfile for this file, and remove it.
2912 string base = basename_nosuffix (*x);
2913 base += "%A"; /* this is what we add for the channel suffix of all native files,
2914 or for the first channel of embedded files. it will miss
2915 some peakfiles for other channels
2917 string peakpath = peak_path (base);
2919 if (Glib::file_test (peakpath.c_str(), Glib::FILE_TEST_EXISTS)) {
2920 if (::unlink (peakpath.c_str()) != 0) {
2921 error << string_compose (_("cannot remove peakfile %1 for %2 (%3)"),
2922 peakpath, _path, strerror (errno))
2924 /* try to back out */
2925 ::rename (newpath.c_str(), _path.c_str());
2930 rep.paths.push_back (*x);
2931 rep.space += statbuf.st_size;
2934 /* dump the history list */
2938 /* save state so we don't end up a session file
2939 referring to non-existent sources.
2946 _state_of_the_state = (StateOfTheState) (_state_of_the_state & ~InCleanup);
2952 Session::cleanup_trash_sources (CleanupReport& rep)
2954 // FIXME: needs adaptation for MIDI
2956 vector<space_and_path>::iterator i;
2962 for (i = session_dirs.begin(); i != session_dirs.end(); ++i) {
2964 dead_dir = Glib::build_filename ((*i).path, dead_dir_name);
2966 clear_directory (dead_dir, &rep.space, &rep.paths);
2973 Session::set_dirty ()
2975 bool was_dirty = dirty();
2977 _state_of_the_state = StateOfTheState (_state_of_the_state | Dirty);
2981 DirtyChanged(); /* EMIT SIGNAL */
2987 Session::set_clean ()
2989 bool was_dirty = dirty();
2991 _state_of_the_state = Clean;
2995 DirtyChanged(); /* EMIT SIGNAL */
3000 Session::set_deletion_in_progress ()
3002 _state_of_the_state = StateOfTheState (_state_of_the_state | Deletion);
3006 Session::clear_deletion_in_progress ()
3008 _state_of_the_state = StateOfTheState (_state_of_the_state & (~Deletion));
3012 Session::add_controllable (boost::shared_ptr<Controllable> c)
3014 /* this adds a controllable to the list managed by the Session.
3015 this is a subset of those managed by the Controllable class
3016 itself, and represents the only ones whose state will be saved
3017 as part of the session.
3020 Glib::Threads::Mutex::Lock lm (controllables_lock);
3021 controllables.insert (c);
3024 struct null_deleter { void operator()(void const *) const {} };
3027 Session::remove_controllable (Controllable* c)
3029 if (_state_of_the_state & Deletion) {
3033 Glib::Threads::Mutex::Lock lm (controllables_lock);
3035 Controllables::iterator x = controllables.find (boost::shared_ptr<Controllable>(c, null_deleter()));
3037 if (x != controllables.end()) {
3038 controllables.erase (x);
3042 boost::shared_ptr<Controllable>
3043 Session::controllable_by_id (const PBD::ID& id)
3045 Glib::Threads::Mutex::Lock lm (controllables_lock);
3047 for (Controllables::iterator i = controllables.begin(); i != controllables.end(); ++i) {
3048 if ((*i)->id() == id) {
3053 return boost::shared_ptr<Controllable>();
3056 boost::shared_ptr<Controllable>
3057 Session::controllable_by_descriptor (const ControllableDescriptor& desc)
3059 boost::shared_ptr<Controllable> c;
3060 boost::shared_ptr<Route> r;
3062 switch (desc.top_level_type()) {
3063 case ControllableDescriptor::NamedRoute:
3065 std::string str = desc.top_level_name();
3066 if (str == "master") {
3068 } else if (str == "control" || str == "listen") {
3071 r = route_by_name (desc.top_level_name());
3076 case ControllableDescriptor::RemoteControlID:
3077 r = route_by_remote_id (desc.rid());
3085 switch (desc.subtype()) {
3086 case ControllableDescriptor::Gain:
3087 c = r->gain_control ();
3090 case ControllableDescriptor::Solo:
3091 c = r->solo_control();
3094 case ControllableDescriptor::Mute:
3095 c = r->mute_control();
3098 case ControllableDescriptor::Recenable:
3100 boost::shared_ptr<Track> t = boost::dynamic_pointer_cast<Track>(r);
3103 c = t->rec_enable_control ();
3108 case ControllableDescriptor::PanDirection:
3110 c = r->pannable()->pan_azimuth_control;
3114 case ControllableDescriptor::PanWidth:
3116 c = r->pannable()->pan_width_control;
3120 case ControllableDescriptor::PanElevation:
3122 c = r->pannable()->pan_elevation_control;
3126 case ControllableDescriptor::Balance:
3127 /* XXX simple pan control */
3130 case ControllableDescriptor::PluginParameter:
3132 uint32_t plugin = desc.target (0);
3133 uint32_t parameter_index = desc.target (1);
3135 /* revert to zero based counting */
3141 if (parameter_index > 0) {
3145 boost::shared_ptr<Processor> p = r->nth_plugin (plugin);
3148 c = boost::dynamic_pointer_cast<ARDOUR::AutomationControl>(
3149 p->control(Evoral::Parameter(PluginAutomation, 0, parameter_index)));
3154 case ControllableDescriptor::SendGain:
3156 uint32_t send = desc.target (0);
3158 /* revert to zero-based counting */
3164 boost::shared_ptr<Processor> p = r->nth_send (send);
3167 boost::shared_ptr<Send> s = boost::dynamic_pointer_cast<Send>(p);
3168 boost::shared_ptr<Amp> a = s->amp();
3171 c = s->amp()->gain_control();
3178 /* relax and return a null pointer */
3186 Session::add_instant_xml (XMLNode& node, bool write_to_config)
3189 Stateful::add_instant_xml (node, _path);
3192 if (write_to_config) {
3193 Config->add_instant_xml (node);
3198 Session::instant_xml (const string& node_name)
3200 return Stateful::instant_xml (node_name, _path);
3204 Session::save_history (string snapshot_name)
3212 if (snapshot_name.empty()) {
3213 snapshot_name = _current_snapshot_name;
3216 const string history_filename = legalize_for_path (snapshot_name) + history_suffix;
3217 const string backup_filename = history_filename + backup_suffix;
3218 const std::string xml_path(Glib::build_filename (_session_dir->root_path(), history_filename));
3219 const std::string backup_path(Glib::build_filename (_session_dir->root_path(), backup_filename));
3221 if (Glib::file_test (xml_path, Glib::FILE_TEST_EXISTS)) {
3222 if (::g_rename (xml_path.c_str(), backup_path.c_str()) != 0) {
3223 error << _("could not backup old history file, current history not saved") << endmsg;
3228 if (!Config->get_save_history() || Config->get_saved_history_depth() < 0) {
3232 tree.set_root (&_history.get_state (Config->get_saved_history_depth()));
3234 if (!tree.write (xml_path))
3236 error << string_compose (_("history could not be saved to %1"), xml_path) << endmsg;
3238 if (g_remove (xml_path.c_str()) != 0) {
3239 error << string_compose(_("Could not remove history file at path \"%1\" (%2)"),
3240 xml_path, g_strerror (errno)) << endmsg;
3242 if (::g_rename (backup_path.c_str(), xml_path.c_str()) != 0) {
3243 error << string_compose (_("could not restore history file from backup %1 (%2)"),
3244 backup_path, g_strerror (errno)) << endmsg;
3254 Session::restore_history (string snapshot_name)
3258 if (snapshot_name.empty()) {
3259 snapshot_name = _current_snapshot_name;
3262 const std::string xml_filename = legalize_for_path (snapshot_name) + history_suffix;
3263 const std::string xml_path(Glib::build_filename (_session_dir->root_path(), xml_filename));
3265 info << "Loading history from " << xml_path << endmsg;
3267 if (!Glib::file_test (xml_path, Glib::FILE_TEST_EXISTS)) {
3268 info << string_compose (_("%1: no history file \"%2\" for this session."),
3269 _name, xml_path) << endmsg;
3273 if (!tree.read (xml_path)) {
3274 error << string_compose (_("Could not understand session history file \"%1\""),
3275 xml_path) << endmsg;
3282 for (XMLNodeConstIterator it = tree.root()->children().begin(); it != tree.root()->children().end(); it++) {
3285 UndoTransaction* ut = new UndoTransaction ();
3288 ut->set_name(t->property("name")->value());
3289 stringstream ss(t->property("tv-sec")->value());
3291 ss.str(t->property("tv-usec")->value());
3293 ut->set_timestamp(tv);
3295 for (XMLNodeConstIterator child_it = t->children().begin();
3296 child_it != t->children().end(); child_it++)
3298 XMLNode *n = *child_it;
3301 if (n->name() == "MementoCommand" ||
3302 n->name() == "MementoUndoCommand" ||
3303 n->name() == "MementoRedoCommand") {
3305 if ((c = memento_command_factory(n))) {
3309 } else if (n->name() == "NoteDiffCommand") {
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::NoteDiffCommand(midi_source->model(), *n));
3316 error << _("Failed to downcast MidiSource for NoteDiffCommand") << endmsg;
3319 } else if (n->name() == "SysExDiffCommand") {
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::SysExDiffCommand (midi_source->model(), *n));
3327 error << _("Failed to downcast MidiSource for SysExDiffCommand") << endmsg;
3330 } else if (n->name() == "PatchChangeDiffCommand") {
3332 PBD::ID id (n->property("midi-source")->value());
3333 boost::shared_ptr<MidiSource> midi_source =
3334 boost::dynamic_pointer_cast<MidiSource, Source>(source_by_id(id));
3336 ut->add_command (new MidiModel::PatchChangeDiffCommand (midi_source->model(), *n));
3338 error << _("Failed to downcast MidiSource for PatchChangeDiffCommand") << endmsg;
3341 } else if (n->name() == "StatefulDiffCommand") {
3342 if ((c = stateful_diff_command_factory (n))) {
3343 ut->add_command (c);
3346 error << string_compose(_("Couldn't figure out how to make a Command out of a %1 XMLNode."), n->name()) << endmsg;
3357 Session::config_changed (std::string p, bool ours)
3363 if (p == "seamless-loop") {
3365 } else if (p == "rf-speed") {
3367 } else if (p == "auto-loop") {
3369 } else if (p == "auto-input") {
3371 if (Config->get_monitoring_model() == HardwareMonitoring && transport_rolling()) {
3372 /* auto-input only makes a difference if we're rolling */
3373 set_track_monitor_input_status (!config.get_auto_input());
3376 } else if (p == "punch-in") {
3380 if ((location = _locations->auto_punch_location()) != 0) {
3382 if (config.get_punch_in ()) {
3383 replace_event (SessionEvent::PunchIn, location->start());
3385 remove_event (location->start(), SessionEvent::PunchIn);
3389 } else if (p == "punch-out") {
3393 if ((location = _locations->auto_punch_location()) != 0) {
3395 if (config.get_punch_out()) {
3396 replace_event (SessionEvent::PunchOut, location->end());
3398 clear_events (SessionEvent::PunchOut);
3402 } else if (p == "edit-mode") {
3404 Glib::Threads::Mutex::Lock lm (playlists->lock);
3406 for (SessionPlaylists::List::iterator i = playlists->playlists.begin(); i != playlists->playlists.end(); ++i) {
3407 (*i)->set_edit_mode (Config->get_edit_mode ());
3410 } else if (p == "use-video-sync") {
3412 waiting_for_sync_offset = config.get_use_video_sync();
3414 } else if (p == "mmc-control") {
3416 //poke_midi_thread ();
3418 } else if (p == "mmc-device-id" || p == "mmc-receive-id" || p == "mmc-receive-device-id") {
3420 MIDI::Manager::instance()->mmc()->set_receive_device_id (Config->get_mmc_receive_device_id());
3422 } else if (p == "mmc-send-id" || p == "mmc-send-device-id") {
3424 MIDI::Manager::instance()->mmc()->set_send_device_id (Config->get_mmc_send_device_id());
3426 } else if (p == "midi-control") {
3428 //poke_midi_thread ();
3430 } else if (p == "raid-path") {
3432 setup_raid_path (config.get_raid_path());
3434 } else if (p == "timecode-format") {
3438 } else if (p == "video-pullup") {
3442 } else if (p == "seamless-loop") {
3444 if (play_loop && transport_rolling()) {
3445 // to reset diskstreams etc
3446 request_play_loop (true);
3449 } else if (p == "rf-speed") {
3451 cumulative_rf_motion = 0;
3454 } else if (p == "click-sound") {
3456 setup_click_sounds (1);
3458 } else if (p == "click-emphasis-sound") {
3460 setup_click_sounds (-1);
3462 } else if (p == "clicking") {
3464 if (Config->get_clicking()) {
3465 if (_click_io && click_data) { // don't require emphasis data
3472 } else if (p == "click-gain") {
3475 _click_gain->set_gain (Config->get_click_gain(), this);
3478 } else if (p == "send-mtc") {
3480 if (Config->get_send_mtc ()) {
3481 /* mark us ready to send */
3482 next_quarter_frame_to_send = 0;
3485 } else if (p == "send-mmc") {
3487 MIDI::Manager::instance()->mmc()->enable_send (Config->get_send_mmc ());
3489 } else if (p == "midi-feedback") {
3491 session_midi_feedback = Config->get_midi_feedback();
3493 } else if (p == "jack-time-master") {
3495 engine().reset_timebase ();
3497 } else if (p == "native-file-header-format") {
3499 if (!first_file_header_format_reset) {
3500 reset_native_file_format ();
3503 first_file_header_format_reset = false;
3505 } else if (p == "native-file-data-format") {
3507 if (!first_file_data_format_reset) {
3508 reset_native_file_format ();
3511 first_file_data_format_reset = false;
3513 } else if (p == "external-sync") {
3514 if (!config.get_external_sync()) {
3515 drop_sync_source ();
3517 switch_to_sync_source (Config->get_sync_source());
3519 } else if (p == "denormal-model") {
3521 } else if (p == "history-depth") {
3522 set_history_depth (Config->get_history_depth());
3523 } else if (p == "remote-model") {
3524 /* XXX DO SOMETHING HERE TO TELL THE GUI THAT WE NEED
3527 } else if (p == "sync-all-route-ordering") {
3529 /* sync to editor order unless mixer is used for remote IDs
3532 switch (Config->get_remote_model()) {
3534 sync_order_keys (EditorSort);
3537 sync_order_keys (EditorSort);
3540 sync_order_keys (MixerSort);
3543 } else if (p == "initial-program-change") {
3545 if (MIDI::Manager::instance()->mmc()->output_port() && Config->get_initial_program_change() >= 0) {
3548 buf[0] = MIDI::program; // channel zero by default
3549 buf[1] = (Config->get_initial_program_change() & 0x7f);
3551 MIDI::Manager::instance()->mmc()->output_port()->midimsg (buf, sizeof (buf), 0);
3553 } else if (p == "solo-mute-override") {
3554 // catch_up_on_solo_mute_override ();
3555 } else if (p == "listen-position" || p == "pfl-position") {
3556 listen_position_changed ();
3557 } else if (p == "solo-control-is-listen-control") {
3558 solo_control_mode_changed ();
3559 } else if (p == "timecode-offset" || p == "timecode-offset-negative") {
3560 last_timecode_valid = false;
3561 } else if (p == "playback-buffer-seconds") {
3562 AudioSource::allocate_working_buffers (frame_rate());
3563 } else if (p == "automation-thinning-factor") {
3564 Evoral::ControlList::set_thinning_factor (Config->get_automation_thinning_factor());
3565 } else if (p == "ltc-source-port") {
3566 reconnect_ltc_input ();
3567 } else if (p == "ltc-sink-port") {
3568 reconnect_ltc_output ();
3570 } else if (p == "timecode-generator-offset") {
3571 ltc_tx_parse_offset();
3579 Session::set_history_depth (uint32_t d)
3581 _history.set_depth (d);
3585 Session::load_diskstreams_2X (XMLNode const & node, int)
3588 XMLNodeConstIterator citer;
3590 clist = node.children();
3592 for (citer = clist.begin(); citer != clist.end(); ++citer) {
3595 /* diskstreams added automatically by DiskstreamCreated handler */
3596 if ((*citer)->name() == "AudioDiskstream" || (*citer)->name() == "DiskStream") {
3597 boost::shared_ptr<AudioDiskstream> dsp (new AudioDiskstream (*this, **citer));
3598 _diskstreams_2X.push_back (dsp);
3600 error << _("Session: unknown diskstream type in XML") << endmsg;
3604 catch (failed_constructor& err) {
3605 error << _("Session: could not load diskstream via XML state") << endmsg;
3613 /** Connect things to the MMC object */
3615 Session::setup_midi_machine_control ()
3617 MIDI::MachineControl* mmc = MIDI::Manager::instance()->mmc ();
3619 mmc->Play.connect_same_thread (*this, boost::bind (&Session::mmc_deferred_play, this, _1));
3620 mmc->DeferredPlay.connect_same_thread (*this, boost::bind (&Session::mmc_deferred_play, this, _1));
3621 mmc->Stop.connect_same_thread (*this, boost::bind (&Session::mmc_stop, this, _1));
3622 mmc->FastForward.connect_same_thread (*this, boost::bind (&Session::mmc_fast_forward, this, _1));
3623 mmc->Rewind.connect_same_thread (*this, boost::bind (&Session::mmc_rewind, this, _1));
3624 mmc->Pause.connect_same_thread (*this, boost::bind (&Session::mmc_pause, this, _1));
3625 mmc->RecordPause.connect_same_thread (*this, boost::bind (&Session::mmc_record_pause, this, _1));
3626 mmc->RecordStrobe.connect_same_thread (*this, boost::bind (&Session::mmc_record_strobe, this, _1));
3627 mmc->RecordExit.connect_same_thread (*this, boost::bind (&Session::mmc_record_exit, this, _1));
3628 mmc->Locate.connect_same_thread (*this, boost::bind (&Session::mmc_locate, this, _1, _2));
3629 mmc->Step.connect_same_thread (*this, boost::bind (&Session::mmc_step, this, _1, _2));
3630 mmc->Shuttle.connect_same_thread (*this, boost::bind (&Session::mmc_shuttle, this, _1, _2, _3));
3631 mmc->TrackRecordStatusChange.connect_same_thread (*this, boost::bind (&Session::mmc_record_enable, this, _1, _2, _3));
3633 /* also handle MIDI SPP because its so common */
3635 mmc->SPPStart.connect_same_thread (*this, boost::bind (&Session::spp_start, this));
3636 mmc->SPPContinue.connect_same_thread (*this, boost::bind (&Session::spp_continue, this));
3637 mmc->SPPStop.connect_same_thread (*this, boost::bind (&Session::spp_stop, this));
3640 boost::shared_ptr<Controllable>
3641 Session::solo_cut_control() const
3643 /* the solo cut control is a bit of an anomaly, at least as of Febrary 2011. There are no other
3644 controls in Ardour that currently get presented to the user in the GUI that require
3645 access as a Controllable and are also NOT owned by some SessionObject (e.g. Route, or MonitorProcessor).
3647 its actually an RCConfiguration parameter, so we use a ProxyControllable to wrap
3648 it up as a Controllable. Changes to the Controllable will just map back to the RCConfiguration
3652 return _solo_cut_control;
3656 Session::rename (const std::string& new_name)
3658 string legal_name = legalize_for_path (new_name);
3664 string const old_sources_root = _session_dir->sources_root();
3666 #define RENAME ::rename
3671 * interchange subdirectory
3675 * Backup files are left unchanged and not renamed.
3678 /* pass one: not 100% safe check that the new directory names don't
3682 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
3687 /* this is a stupid hack because Glib::path_get_dirname() is
3688 * lexical-only, and so passing it /a/b/c/ gives a different
3689 * result than passing it /a/b/c ...
3692 if (oldstr[oldstr.length()-1] == G_DIR_SEPARATOR) {
3693 oldstr = oldstr.substr (0, oldstr.length() - 1);
3696 string base = Glib::path_get_dirname (oldstr);
3697 string p = Glib::path_get_basename (oldstr);
3699 newstr = Glib::build_filename (base, legal_name);
3701 if (Glib::file_test (newstr, Glib::FILE_TEST_EXISTS)) {
3708 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
3713 /* this is a stupid hack because Glib::path_get_dirname() is
3714 * lexical-only, and so passing it /a/b/c/ gives a different
3715 * result than passing it /a/b/c ...
3718 if (oldstr[oldstr.length()-1] == G_DIR_SEPARATOR) {
3719 oldstr = oldstr.substr (0, oldstr.length() - 1);
3722 string base = Glib::path_get_dirname (oldstr);
3723 string p = Glib::path_get_basename (oldstr);
3725 newstr = Glib::build_filename (base, legal_name);
3727 cerr << "Rename " << oldstr << " => " << newstr << endl;
3729 if (RENAME (oldstr.c_str(), newstr.c_str()) != 0) {
3734 (*_session_dir) = newstr;
3739 /* directory below interchange */
3741 v.push_back (newstr);
3742 v.push_back (interchange_dir_name);
3745 oldstr = Glib::build_filename (v);
3748 v.push_back (newstr);
3749 v.push_back (interchange_dir_name);
3750 v.push_back (legal_name);
3752 newstr = Glib::build_filename (v);
3754 cerr << "Rename " << oldstr << " => " << newstr << endl;
3756 if (RENAME (oldstr.c_str(), newstr.c_str()) != 0) {
3763 oldstr = Glib::build_filename (newpath, _current_snapshot_name) + statefile_suffix;
3764 newstr= Glib::build_filename (newpath, legal_name) + statefile_suffix;
3766 cerr << "Rename " << oldstr << " => " << newstr << endl;
3768 if (RENAME (oldstr.c_str(), newstr.c_str()) != 0) {
3775 oldstr = Glib::build_filename (newpath, _current_snapshot_name) + history_suffix;
3777 if (Glib::file_test (oldstr, Glib::FILE_TEST_EXISTS)) {
3778 newstr = Glib::build_filename (newpath, legal_name) + history_suffix;
3780 cerr << "Rename " << oldstr << " => " << newstr << endl;
3782 if (RENAME (oldstr.c_str(), newstr.c_str()) != 0) {
3787 /* update file source paths */
3789 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ++i) {
3790 boost::shared_ptr<FileSource> fs = boost::dynamic_pointer_cast<FileSource> (i->second);
3792 string p = fs->path ();
3793 boost::replace_all (p, old_sources_root, _session_dir->sources_root());
3798 /* remove old name from recent sessions */
3800 remove_recent_sessions (_path);
3803 _current_snapshot_name = new_name;
3808 /* save state again to get everything just right */
3810 save_state (_current_snapshot_name);
3813 /* add to recent sessions */
3815 store_recent_sessions (new_name, _path);