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"
33 #include <cstdio> /* snprintf(3) ... grrr */
47 #include <sys/param.h>
48 #include <sys/mount.h>
52 #include <glibmm/thread.h>
54 #include "midi++/mmc.h"
55 #include "midi++/port.h"
56 #include "midi++/manager.h"
58 #include "pbd/boost_debug.h"
59 #include "pbd/controllable_descriptor.h"
60 #include "pbd/enumwriter.h"
61 #include "pbd/error.h"
62 #include "pbd/pathscanner.h"
63 #include "pbd/pthread_utils.h"
64 #include "pbd/search_path.h"
65 #include "pbd/stacktrace.h"
66 #include "pbd/convert.h"
67 #include "pbd/clear_dir.h"
69 #include "ardour/amp.h"
70 #include "ardour/audio_diskstream.h"
71 #include "ardour/audio_track.h"
72 #include "ardour/audioengine.h"
73 #include "ardour/audiofilesource.h"
74 #include "ardour/audioplaylist.h"
75 #include "ardour/audioregion.h"
76 #include "ardour/auditioner.h"
77 #include "ardour/automation_control.h"
78 #include "ardour/buffer.h"
79 #include "ardour/butler.h"
80 #include "ardour/configuration.h"
81 #include "ardour/control_protocol_manager.h"
82 #include "ardour/crossfade.h"
83 #include "ardour/cycle_timer.h"
84 #include "ardour/directory_names.h"
85 #include "ardour/filename_extensions.h"
86 #include "ardour/io_processor.h"
87 #include "ardour/location.h"
88 #include "ardour/midi_diskstream.h"
89 #include "ardour/midi_patch_manager.h"
90 #include "ardour/midi_playlist.h"
91 #include "ardour/midi_region.h"
92 #include "ardour/midi_source.h"
93 #include "ardour/midi_track.h"
94 #include "ardour/named_selection.h"
95 #include "ardour/panner.h"
96 #include "ardour/processor.h"
97 #include "ardour/port.h"
98 #include "ardour/region_factory.h"
99 #include "ardour/route_group.h"
100 #include "ardour/send.h"
101 #include "ardour/session.h"
102 #include "ardour/session_directory.h"
103 #include "ardour/session_metadata.h"
104 #include "ardour/session_state_utils.h"
105 #include "ardour/session_playlists.h"
106 #include "ardour/session_utils.h"
107 #include "ardour/silentfilesource.h"
108 #include "ardour/slave.h"
109 #include "ardour/smf_source.h"
110 #include "ardour/sndfile_helpers.h"
111 #include "ardour/sndfilesource.h"
112 #include "ardour/source_factory.h"
113 #include "ardour/template_utils.h"
114 #include "ardour/tempo.h"
115 #include "ardour/ticker.h"
116 #include "ardour/user_bundle.h"
117 #include "ardour/utils.h"
118 #include "ardour/utils.h"
119 #include "ardour/version.h"
120 #include "ardour/playlist_factory.h"
122 #include "control_protocol/control_protocol.h"
128 using namespace ARDOUR;
132 Session::first_stage_init (string fullpath, string snapshot_name)
134 if (fullpath.length() == 0) {
136 throw failed_constructor();
139 char buf[PATH_MAX+1];
140 if (!realpath (fullpath.c_str(), buf) && (errno != ENOENT)) {
141 error << string_compose(_("Could not use path %1 (%s)"), buf, strerror(errno)) << endmsg;
143 throw failed_constructor();
148 if (_path[_path.length()-1] != '/') {
149 _path += G_DIR_SEPARATOR;
152 if (Glib::file_test (_path, Glib::FILE_TEST_EXISTS) && ::access (_path.c_str(), W_OK)) {
158 /* these two are just provisional settings. set_state()
159 will likely override them.
162 _name = _current_snapshot_name = snapshot_name;
164 set_history_depth (Config->get_history_depth());
166 _current_frame_rate = _engine.frame_rate ();
167 _nominal_frame_rate = _current_frame_rate;
168 _base_frame_rate = _current_frame_rate;
170 _tempo_map = new TempoMap (_current_frame_rate);
171 _tempo_map->PropertyChanged.connect_same_thread (*this, boost::bind (&Session::tempo_map_changed, this, _1));
174 _non_soloed_outs_muted = false;
176 _solo_isolated_cnt = 0;
177 g_atomic_int_set (&processing_prohibited, 0);
178 _transport_speed = 0;
179 _last_transport_speed = 0;
180 _target_transport_speed = 0;
181 auto_play_legal = false;
182 transport_sub_state = 0;
183 _transport_frame = 0;
184 _requested_return_frame = -1;
185 _session_range_location = 0;
186 g_atomic_int_set (&_record_status, Disabled);
187 loop_changing = false;
190 _last_roll_location = 0;
191 _last_roll_or_reversal_location = 0;
192 _last_record_location = 0;
193 pending_locate_frame = 0;
194 pending_locate_roll = false;
195 pending_locate_flush = false;
196 state_was_pending = false;
198 outbound_mtc_timecode_frame = 0;
199 next_quarter_frame_to_send = -1;
200 current_block_size = 0;
201 solo_update_disabled = false;
202 _have_captured = false;
203 _worst_output_latency = 0;
204 _worst_input_latency = 0;
205 _worst_track_latency = 0;
206 _state_of_the_state = StateOfTheState(CannotSave|InitialConnecting|Loading);
207 _was_seamless = Config->get_seamless_loop ();
209 session_send_mtc = false;
210 g_atomic_int_set (&_playback_load, 100);
211 g_atomic_int_set (&_capture_load, 100);
214 pending_abort = false;
215 destructive_index = 0;
216 first_file_data_format_reset = true;
217 first_file_header_format_reset = true;
218 post_export_sync = false;
221 no_questions_about_missing_files = false;
224 AudioDiskstream::allocate_working_buffers();
226 /* default short fade = 15ms */
228 Crossfade::set_short_xfade_length ((nframes_t) floor (config.get_short_xfade_seconds() * frame_rate()));
229 SndFileSource::setup_standard_crossfades (*this, frame_rate());
231 last_mmc_step.tv_sec = 0;
232 last_mmc_step.tv_usec = 0;
235 /* click sounds are unset by default, which causes us to internal
236 waveforms for clicks.
240 click_emphasis_length = 0;
243 process_function = &Session::process_with_events;
245 if (config.get_use_video_sync()) {
246 waiting_for_sync_offset = true;
248 waiting_for_sync_offset = false;
251 last_timecode_when = 0;
252 _timecode_offset = 0;
253 _timecode_offset_negative = true;
254 last_timecode_valid = false;
258 last_rr_session_dir = session_dirs.begin();
259 refresh_disk_space ();
261 // set_default_fade (0.2, 5.0); /* steepness, millisecs */
265 average_slave_delta = 1800; // !!! why 1800 ????
266 have_first_delta_accumulator = false;
267 delta_accumulator_cnt = 0;
268 _slave_state = Stopped;
270 _engine.GraphReordered.connect_same_thread (*this, boost::bind (&Session::graph_reordered, this));
272 /* These are all static "per-class" signals */
274 SourceFactory::SourceCreated.connect_same_thread (*this, boost::bind (&Session::add_source, this, _1));
275 PlaylistFactory::PlaylistCreated.connect_same_thread (*this, boost::bind (&Session::add_playlist, this, _1, _2));
276 AutomationList::AutomationListCreated.connect_same_thread (*this, boost::bind (&Session::add_automation_list, this, _1));
277 Controllable::Destroyed.connect_same_thread (*this, boost::bind (&Session::remove_controllable, this, _1));
278 IO::PortCountChanged.connect_same_thread (*this, boost::bind (&Session::ensure_buffers, this, _1));
280 /* stop IO objects from doing stuff until we're ready for them */
282 Delivery::disable_panners ();
283 IO::disable_connecting ();
287 Session::second_stage_init ()
289 AudioFileSource::set_peak_dir (_session_dir->peak_path().to_string());
292 if (load_state (_current_snapshot_name)) {
295 cleanup_stubfiles ();
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));
342 when_engine_running ();
345 /* handle this one in a different way than all others, so that its clear what happened */
347 catch (AudioEngine::PortRegistrationFailure& err) {
348 error << err.what() << endmsg;
356 BootMessage (_("Reset Remote Controls"));
358 send_full_time_code (0);
359 _engine.transport_locate (0);
361 MIDI::Manager::instance()->mmc()->send (MIDI::MachineControlCommand (MIDI::MachineControl::cmdMmcReset));
362 MIDI::Manager::instance()->mmc()->send (MIDI::MachineControlCommand (Timecode::Time ()));
364 MidiClockTicker::instance().set_session (this);
365 MIDI::Name::MidiPatchManager::instance().set_session (this);
367 /* initial program change will be delivered later; see ::config_changed() */
369 BootMessage (_("Reset Control Protocols"));
371 ControlProtocolManager::instance().set_session (this);
373 _state_of_the_state = Clean;
375 Port::set_connecting_blocked (false);
377 DirtyChanged (); /* EMIT SIGNAL */
379 if (state_was_pending) {
380 save_state (_current_snapshot_name);
381 remove_pending_capture_state ();
382 state_was_pending = false;
385 BootMessage (_("Session loading complete"));
391 Session::raid_path () const
393 SearchPath raid_search_path;
395 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
396 raid_search_path += sys::path((*i).path);
399 return raid_search_path.to_string ();
403 Session::setup_raid_path (string path)
412 session_dirs.clear ();
414 SearchPath search_path(path);
415 SearchPath sound_search_path;
416 SearchPath midi_search_path;
418 for (SearchPath::const_iterator i = search_path.begin(); i != search_path.end(); ++i) {
419 sp.path = (*i).to_string ();
420 sp.blocks = 0; // not needed
421 session_dirs.push_back (sp);
423 SessionDirectory sdir(sp.path);
425 sound_search_path += sdir.sound_path ();
426 midi_search_path += sdir.midi_path ();
429 // reset the round-robin soundfile path thingie
430 last_rr_session_dir = session_dirs.begin();
434 Session::path_is_within_session (const std::string& path)
436 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
437 if (path.find ((*i).path) == 0) {
445 Session::ensure_subdirs ()
449 dir = session_directory().peak_path().to_string();
451 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
452 error << string_compose(_("Session: cannot create session peakfile folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
456 dir = session_directory().sound_path().to_string();
458 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
459 error << string_compose(_("Session: cannot create session sounds dir \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
463 dir = session_directory().sound_stub_path().to_string();
465 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
466 error << string_compose(_("Session: cannot create session stub sounds dir \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
470 dir = session_directory().midi_path().to_string();
472 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
473 error << string_compose(_("Session: cannot create session midi dir \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
477 dir = session_directory().midi_stub_path().to_string();
479 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
480 error << string_compose(_("Session: cannot create session stub midi dir \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
484 dir = session_directory().dead_sound_path().to_string();
486 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
487 error << string_compose(_("Session: cannot create session dead sounds folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
491 dir = session_directory().export_path().to_string();
493 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
494 error << string_compose(_("Session: cannot create session export folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
498 dir = analysis_dir ();
500 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
501 error << string_compose(_("Session: cannot create session analysis folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
505 dir = plugins_dir ();
507 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
508 error << string_compose(_("Session: cannot create session plugins folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
515 /** Caller must not hold process lock */
517 Session::create (const string& mix_template, BusProfile* bus_profile)
520 if (g_mkdir_with_parents (_path.c_str(), 0755) < 0) {
521 error << string_compose(_("Session: cannot create session folder \"%1\" (%2)"), _path, strerror (errno)) << endmsg;
525 if (ensure_subdirs ()) {
529 if (!mix_template.empty()) {
530 std::string in_path = mix_template;
532 ifstream in(in_path.c_str());
535 string out_path = _path;
537 out_path += statefile_suffix;
539 ofstream out(out_path.c_str());
547 error << string_compose (_("Could not open %1 for writing mix template"), out_path)
553 error << string_compose (_("Could not open mix template %1 for reading"), in_path)
560 /* Instantiate metadata */
562 _metadata = new SessionMetadata ();
564 /* set initial start + end point */
566 _state_of_the_state = Clean;
568 /* set up Master Out and Control Out if necessary */
574 ChanCount count(DataType::AUDIO, bus_profile->master_out_channels);
576 if (bus_profile->master_out_channels) {
577 Route* rt = new Route (*this, _("master"), Route::MasterOut, DataType::AUDIO);
582 boost_debug_shared_ptr_mark_interesting (rt, "Route");
583 boost::shared_ptr<Route> r (rt);
585 Glib::Mutex::Lock lm (AudioEngine::instance()->process_lock ());
586 r->input()->ensure_io (count, false, this);
587 r->output()->ensure_io (count, false, this);
589 r->set_remote_control_id (control_id++);
593 if (Config->get_use_monitor_bus()) {
594 Route* rt = new Route (*this, _("monitor"), Route::MonitorOut, DataType::AUDIO);
599 boost_debug_shared_ptr_mark_interesting (rt, "Route");
600 boost::shared_ptr<Route> r (rt);
602 Glib::Mutex::Lock lm (AudioEngine::instance()->process_lock ());
603 r->input()->ensure_io (count, false, this);
604 r->output()->ensure_io (count, false, this);
606 r->set_remote_control_id (control_id);
612 /* prohibit auto-connect to master, because there isn't one */
613 bus_profile->output_ac = AutoConnectOption (bus_profile->output_ac & ~AutoConnectMaster);
617 add_routes (rl, false);
620 /* this allows the user to override settings with an environment variable.
623 if (no_auto_connect()) {
624 bus_profile->input_ac = AutoConnectOption (0);
625 bus_profile->output_ac = AutoConnectOption (0);
628 Config->set_input_auto_connect (bus_profile->input_ac);
629 Config->set_output_auto_connect (bus_profile->output_ac);
638 Session::maybe_write_autosave()
640 if (dirty() && record_status() != Recording) {
641 save_state("", true);
646 Session::remove_pending_capture_state ()
648 sys::path pending_state_file_path(_session_dir->root_path());
650 pending_state_file_path /= legalize_for_path (_current_snapshot_name) + pending_suffix;
654 sys::remove (pending_state_file_path);
656 catch(sys::filesystem_error& ex)
658 error << string_compose(_("Could remove pending capture state at path \"%1\" (%2)"),
659 pending_state_file_path.to_string(), ex.what()) << endmsg;
663 /** Rename a state file.
664 * @param snapshot_name Snapshot name.
667 Session::rename_state (string old_name, string new_name)
669 if (old_name == _current_snapshot_name || old_name == _name) {
670 /* refuse to rename the current snapshot or the "main" one */
674 const string old_xml_filename = legalize_for_path (old_name) + statefile_suffix;
675 const string new_xml_filename = legalize_for_path (new_name) + statefile_suffix;
677 const sys::path old_xml_path = _session_dir->root_path() / old_xml_filename;
678 const sys::path new_xml_path = _session_dir->root_path() / new_xml_filename;
682 sys::rename (old_xml_path, new_xml_path);
684 catch (const sys::filesystem_error& err)
686 error << string_compose(_("could not rename snapshot %1 to %2 (%3)"),
687 old_name, new_name, err.what()) << endmsg;
691 /** Remove a state file.
692 * @param snapshot_name Snapshot name.
695 Session::remove_state (string snapshot_name)
697 if (snapshot_name == _current_snapshot_name || snapshot_name == _name) {
698 // refuse to remove the current snapshot or the "main" one
702 sys::path xml_path(_session_dir->root_path());
704 xml_path /= legalize_for_path (snapshot_name) + statefile_suffix;
706 if (!create_backup_file (xml_path)) {
707 // don't remove it if a backup can't be made
708 // create_backup_file will log the error.
713 sys::remove (xml_path);
716 #ifdef HAVE_JACK_SESSION
718 Session::jack_session_event (jack_session_event_t * event)
722 struct tm local_time;
725 localtime_r (&n, &local_time);
726 strftime (timebuf, sizeof(timebuf), "JS_%FT%T", &local_time);
728 if (event->type == JackSessionSaveTemplate)
730 if (save_template( timebuf )) {
731 event->flags = JackSessionSaveError;
733 string cmd ("ardour3 -P -U ");
734 cmd += event->client_uuid;
738 event->command_line = strdup (cmd.c_str());
743 if (save_state (timebuf)) {
744 event->flags = JackSessionSaveError;
746 sys::path xml_path (_session_dir->root_path());
747 xml_path /= legalize_for_path (timebuf) + statefile_suffix;
749 string cmd ("ardour3 -P -U ");
750 cmd += event->client_uuid;
752 cmd += xml_path.to_string();
755 event->command_line = strdup (cmd.c_str());
759 jack_session_reply (_engine.jack(), event);
761 if (event->type == JackSessionSaveAndQuit) {
762 Quit (); /* EMIT SIGNAL */
765 jack_session_event_free( event );
770 Session::save_state (string snapshot_name, bool pending, bool switch_to_snapshot)
773 sys::path xml_path(_session_dir->root_path());
775 if (!_writable || (_state_of_the_state & CannotSave)) {
779 if (!_engine.connected ()) {
780 error << string_compose (_("the %1 audio engine is not connected and state saving would lose all I/O connections. Session not saved"),
786 /* tell sources we're saving first, in case they write out to a new file
787 * which should be saved with the state rather than the old one */
788 for (SourceMap::const_iterator i = sources.begin(); i != sources.end(); ++i) {
789 i->second->session_saved();
792 tree.set_root (&get_state());
794 if (snapshot_name.empty()) {
795 snapshot_name = _current_snapshot_name;
796 } else if (switch_to_snapshot) {
797 _current_snapshot_name = snapshot_name;
802 /* proper save: use statefile_suffix (.ardour in English) */
804 xml_path /= legalize_for_path (snapshot_name) + statefile_suffix;
806 /* make a backup copy of the old file */
808 if (sys::exists(xml_path) && !create_backup_file (xml_path)) {
809 // create_backup_file will log the error
815 /* pending save: use pending_suffix (.pending in English) */
816 xml_path /= legalize_for_path (snapshot_name) + pending_suffix;
819 sys::path tmp_path(_session_dir->root_path());
821 tmp_path /= legalize_for_path (snapshot_name) + temp_suffix;
823 // cerr << "actually writing state to " << xml_path.to_string() << endl;
825 if (!tree.write (tmp_path.to_string())) {
826 error << string_compose (_("state could not be saved to %1"), tmp_path.to_string()) << endmsg;
827 sys::remove (tmp_path);
832 if (rename (tmp_path.to_string().c_str(), xml_path.to_string().c_str()) != 0) {
833 error << string_compose (_("could not rename temporary session file %1 to %2"),
834 tmp_path.to_string(), xml_path.to_string()) << endmsg;
835 sys::remove (tmp_path);
842 save_history (snapshot_name);
844 bool was_dirty = dirty();
846 _state_of_the_state = StateOfTheState (_state_of_the_state & ~Dirty);
849 DirtyChanged (); /* EMIT SIGNAL */
852 StateSaved (snapshot_name); /* EMIT SIGNAL */
859 Session::restore_state (string snapshot_name)
861 if (load_state (snapshot_name) == 0) {
862 set_state (*state_tree->root(), Stateful::loading_state_version);
869 Session::load_state (string snapshot_name)
874 state_was_pending = false;
876 /* check for leftover pending state from a crashed capture attempt */
878 sys::path xmlpath(_session_dir->root_path());
879 xmlpath /= legalize_for_path (snapshot_name) + pending_suffix;
881 if (sys::exists (xmlpath)) {
883 /* there is pending state from a crashed capture attempt */
885 boost::optional<int> r = AskAboutPendingState();
886 if (r.get_value_or (1)) {
887 state_was_pending = true;
891 if (!state_was_pending) {
892 xmlpath = _session_dir->root_path();
893 xmlpath /= snapshot_name;
896 if (!sys::exists (xmlpath)) {
897 xmlpath = _session_dir->root_path();
898 xmlpath /= legalize_for_path (snapshot_name) + statefile_suffix;
899 if (!sys::exists (xmlpath)) {
900 error << string_compose(_("%1: session state information file \"%2\" doesn't exist!"), _name, xmlpath.to_string()) << endmsg;
905 state_tree = new XMLTree;
909 /* writable() really reflects the whole folder, but if for any
910 reason the session state file can't be written to, still
914 if (::access (xmlpath.to_string().c_str(), W_OK) != 0) {
918 if (!state_tree->read (xmlpath.to_string())) {
919 error << string_compose(_("Could not understand ardour file %1"), xmlpath.to_string()) << endmsg;
925 XMLNode& root (*state_tree->root());
927 if (root.name() != X_("Session")) {
928 error << string_compose (_("Session file %1 is not a session"), xmlpath.to_string()) << endmsg;
934 const XMLProperty* prop;
936 if ((prop = root.property ("version")) == 0) {
937 /* no version implies very old version of Ardour */
938 Stateful::loading_state_version = 1000;
944 sscanf (prop->value().c_str(), "%d.%d.%d", &major, &minor, µ);
945 Stateful::loading_state_version = (major * 1000) + minor;
948 if (Stateful::loading_state_version < CURRENT_SESSION_FILE_VERSION) {
950 sys::path backup_path(_session_dir->root_path());
952 backup_path /= legalize_for_path (snapshot_name) + "-1" + statefile_suffix;
954 // only create a backup once
955 if (sys::exists (backup_path)) {
959 info << string_compose (_("Copying old session file %1 to %2\nUse %2 with %3 versions before 2.0 from now on"),
960 xmlpath.to_string(), backup_path.to_string(), PROGRAM_NAME)
965 sys::copy_file (xmlpath, backup_path);
967 catch(sys::filesystem_error& ex)
969 error << string_compose (_("Unable to make backup of state file %1 (%2)"),
970 xmlpath.to_string(), ex.what())
980 Session::load_options (const XMLNode& node)
982 LocaleGuard lg (X_("POSIX"));
983 config.set_variables (node);
994 Session::get_template()
996 /* if we don't disable rec-enable, diskstreams
997 will believe they need to store their capture
998 sources in their state node.
1001 disable_record (false);
1003 return state(false);
1007 Session::state(bool full_state)
1009 XMLNode* node = new XMLNode("Session");
1012 // store libardour version, just in case
1014 snprintf(buf, sizeof(buf), "%d.%d.%d", libardour3_major_version, libardour3_minor_version, libardour3_micro_version);
1015 node->add_property("version", string(buf));
1017 /* store configuration settings */
1021 node->add_property ("name", _name);
1022 snprintf (buf, sizeof (buf), "%" PRId32, _nominal_frame_rate);
1023 node->add_property ("sample-rate", buf);
1025 if (session_dirs.size() > 1) {
1029 vector<space_and_path>::iterator i = session_dirs.begin();
1030 vector<space_and_path>::iterator next;
1032 ++i; /* skip the first one */
1036 while (i != session_dirs.end()) {
1040 if (next != session_dirs.end()) {
1050 child = node->add_child ("Path");
1051 child->add_content (p);
1055 /* save the ID counter */
1057 snprintf (buf, sizeof (buf), "%" PRIu64, ID::counter());
1058 node->add_property ("id-counter", buf);
1060 /* save the event ID counter */
1062 snprintf (buf, sizeof (buf), "%d", Evoral::event_id_counter());
1063 node->add_property ("event-counter", buf);
1065 /* various options */
1067 node->add_child_nocopy (config.get_variables ());
1069 node->add_child_nocopy (_metadata->get_state());
1071 child = node->add_child ("Sources");
1074 Glib::Mutex::Lock sl (source_lock);
1076 for (SourceMap::iterator siter = sources.begin(); siter != sources.end(); ++siter) {
1078 /* Don't save information about non-destructive file sources that are empty
1079 and unused by any regions.
1082 boost::shared_ptr<FileSource> fs;
1083 if ((fs = boost::dynamic_pointer_cast<FileSource> (siter->second)) != 0) {
1084 if (!fs->destructive()) {
1085 if (fs->empty() && !fs->used()) {
1091 child->add_child_nocopy (siter->second->get_state());
1095 child = node->add_child ("Regions");
1098 Glib::Mutex::Lock rl (region_lock);
1099 const RegionFactory::RegionMap& region_map (RegionFactory::all_regions());
1100 for (RegionFactory::RegionMap::const_iterator i = region_map.begin(); i != region_map.end(); ++i) {
1101 boost::shared_ptr<Region> r = i->second;
1102 /* only store regions not attached to playlists */
1103 if (r->playlist() == 0) {
1104 child->add_child_nocopy (r->state ());
1110 node->add_child_nocopy (_locations->get_state());
1112 // for a template, just create a new Locations, populate it
1113 // with the default start and end, and get the state for that.
1114 Locations loc (*this);
1115 Location* range = new Location (*this, 0, 0, _("session"), Location::IsSessionRange);
1116 range->set (max_framepos, 0);
1118 node->add_child_nocopy (loc.get_state());
1121 child = node->add_child ("Bundles");
1123 boost::shared_ptr<BundleList> bundles = _bundles.reader ();
1124 for (BundleList::iterator i = bundles->begin(); i != bundles->end(); ++i) {
1125 boost::shared_ptr<UserBundle> b = boost::dynamic_pointer_cast<UserBundle> (*i);
1127 child->add_child_nocopy (b->get_state());
1132 child = node->add_child ("Routes");
1134 boost::shared_ptr<RouteList> r = routes.reader ();
1136 RoutePublicOrderSorter cmp;
1137 RouteList public_order (*r);
1138 public_order.sort (cmp);
1140 /* the sort should have put control outs first */
1143 assert (_monitor_out == public_order.front());
1146 for (RouteList::iterator i = public_order.begin(); i != public_order.end(); ++i) {
1147 if (!(*i)->is_hidden()) {
1149 child->add_child_nocopy ((*i)->get_state());
1151 child->add_child_nocopy ((*i)->get_template());
1157 playlists->add_state (node, full_state);
1159 child = node->add_child ("RouteGroups");
1160 for (list<RouteGroup *>::iterator i = _route_groups.begin(); i != _route_groups.end(); ++i) {
1161 child->add_child_nocopy ((*i)->get_state());
1165 child = node->add_child ("Click");
1166 child->add_child_nocopy (_click_io->state (full_state));
1170 child = node->add_child ("NamedSelections");
1171 for (NamedSelectionList::iterator i = named_selections.begin(); i != named_selections.end(); ++i) {
1173 child->add_child_nocopy ((*i)->get_state());
1178 node->add_child_nocopy (_tempo_map->get_state());
1180 node->add_child_nocopy (get_control_protocol_state());
1183 node->add_child_copy (*_extra_xml);
1190 Session::get_control_protocol_state ()
1192 ControlProtocolManager& cpm (ControlProtocolManager::instance());
1193 return cpm.get_state();
1197 Session::set_state (const XMLNode& node, int version)
1201 const XMLProperty* prop;
1204 _state_of_the_state = StateOfTheState (_state_of_the_state|CannotSave);
1206 if (node.name() != X_("Session")){
1207 fatal << _("programming error: Session: incorrect XML node sent to set_state()") << endmsg;
1211 if ((prop = node.property ("version")) != 0) {
1212 version = atoi (prop->value ()) * 1000;
1215 if ((prop = node.property ("name")) != 0) {
1216 _name = prop->value ();
1219 if ((prop = node.property (X_("sample-rate"))) != 0) {
1221 _nominal_frame_rate = atoi (prop->value());
1223 if (_nominal_frame_rate != _current_frame_rate) {
1224 boost::optional<int> r = AskAboutSampleRateMismatch (_nominal_frame_rate, _current_frame_rate);
1225 if (r.get_value_or (0)) {
1231 setup_raid_path(_session_dir->root_path().to_string());
1233 if ((prop = node.property (X_("id-counter"))) != 0) {
1235 sscanf (prop->value().c_str(), "%" PRIu64, &x);
1236 ID::init_counter (x);
1238 /* old sessions used a timebased counter, so fake
1239 the startup ID counter based on a standard
1244 ID::init_counter (now);
1247 if ((prop = node.property (X_("event-counter"))) != 0) {
1248 Evoral::init_event_id_counter (atoi (prop->value()));
1251 IO::disable_connecting ();
1253 /* Object loading order:
1258 MIDI Control // relies on data from Options/Config
1271 if ((child = find_named_node (node, "Extra")) != 0) {
1272 _extra_xml = new XMLNode (*child);
1275 if (((child = find_named_node (node, "Options")) != 0)) { /* old style */
1276 load_options (*child);
1277 } else if ((child = find_named_node (node, "Config")) != 0) { /* new style */
1278 load_options (*child);
1280 error << _("Session: XML state has no options section") << endmsg;
1283 if (version >= 3000) {
1284 if ((child = find_named_node (node, "Metadata")) == 0) {
1285 warning << _("Session: XML state has no metadata section") << endmsg;
1286 } else if (_metadata->set_state (*child, version)) {
1291 if ((child = find_named_node (node, "Locations")) == 0) {
1292 error << _("Session: XML state has no locations section") << endmsg;
1294 } else if (_locations->set_state (*child, version)) {
1300 if ((location = _locations->auto_loop_location()) != 0) {
1301 set_auto_loop_location (location);
1304 if ((location = _locations->auto_punch_location()) != 0) {
1305 set_auto_punch_location (location);
1308 if ((location = _locations->session_range_location()) != 0) {
1309 delete _session_range_location;
1310 _session_range_location = location;
1313 if (_session_range_location) {
1314 AudioFileSource::set_header_position_offset (_session_range_location->start());
1317 if ((child = find_named_node (node, "Sources")) == 0) {
1318 error << _("Session: XML state has no sources section") << endmsg;
1320 } else if (load_sources (*child)) {
1324 if ((child = find_named_node (node, "Regions")) == 0) {
1325 error << _("Session: XML state has no Regions section") << endmsg;
1327 } else if (load_regions (*child)) {
1331 if ((child = find_named_node (node, "Playlists")) == 0) {
1332 error << _("Session: XML state has no playlists section") << endmsg;
1334 } else if (playlists->load (*this, *child)) {
1338 if ((child = find_named_node (node, "UnusedPlaylists")) == 0) {
1340 } else if (playlists->load_unused (*this, *child)) {
1344 if ((child = find_named_node (node, "NamedSelections")) != 0) {
1345 if (load_named_selections (*child)) {
1350 if (version >= 3000) {
1351 if ((child = find_named_node (node, "Bundles")) == 0) {
1352 warning << _("Session: XML state has no bundles section") << endmsg;
1355 /* We can't load Bundles yet as they need to be able
1356 to convert from port names to Port objects, which can't happen until
1358 _bundle_xml_node = new XMLNode (*child);
1362 if ((child = find_named_node (node, "TempoMap")) == 0) {
1363 error << _("Session: XML state has no Tempo Map section") << endmsg;
1365 } else if (_tempo_map->set_state (*child, version)) {
1369 if (version < 3000) {
1370 if ((child = find_named_node (node, X_("DiskStreams"))) == 0) {
1371 error << _("Session: XML state has no diskstreams section") << endmsg;
1373 } else if (load_diskstreams_2X (*child, version)) {
1378 if ((child = find_named_node (node, "Routes")) == 0) {
1379 error << _("Session: XML state has no routes section") << endmsg;
1381 } else if (load_routes (*child, version)) {
1385 /* our diskstreams list is no longer needed as they are now all owned by their Route */
1386 _diskstreams_2X.clear ();
1388 if (version >= 3000) {
1390 if ((child = find_named_node (node, "RouteGroups")) == 0) {
1391 error << _("Session: XML state has no route groups section") << endmsg;
1393 } else if (load_route_groups (*child, version)) {
1397 } else if (version < 3000) {
1399 if ((child = find_named_node (node, "EditGroups")) == 0) {
1400 error << _("Session: XML state has no edit groups section") << endmsg;
1402 } else if (load_route_groups (*child, version)) {
1406 if ((child = find_named_node (node, "MixGroups")) == 0) {
1407 error << _("Session: XML state has no mix groups section") << endmsg;
1409 } else if (load_route_groups (*child, version)) {
1414 if ((child = find_named_node (node, "Click")) == 0) {
1415 warning << _("Session: XML state has no click section") << endmsg;
1416 } else if (_click_io) {
1417 _click_io->set_state (*child, version);
1420 if ((child = find_named_node (node, "ControlProtocols")) != 0) {
1421 ControlProtocolManager::instance().set_protocol_states (*child);
1424 /* here beginneth the second phase ... */
1426 StateReady (); /* EMIT SIGNAL */
1435 Session::load_routes (const XMLNode& node, int version)
1438 XMLNodeConstIterator niter;
1439 RouteList new_routes;
1441 nlist = node.children();
1445 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1447 boost::shared_ptr<Route> route;
1448 if (version < 3000) {
1449 route = XMLRouteFactory_2X (**niter, version);
1451 route = XMLRouteFactory (**niter, version);
1455 error << _("Session: cannot create Route from XML description.") << endmsg;
1459 BootMessage (string_compose (_("Loaded track/bus %1"), route->name()));
1461 new_routes.push_back (route);
1464 add_routes (new_routes, false);
1469 boost::shared_ptr<Route>
1470 Session::XMLRouteFactory (const XMLNode& node, int version)
1472 boost::shared_ptr<Route> ret;
1474 if (node.name() != "Route") {
1478 XMLNode* ds_child = find_named_node (node, X_("Diskstream"));
1480 DataType type = DataType::AUDIO;
1481 const XMLProperty* prop = node.property("default-type");
1484 type = DataType (prop->value());
1487 assert (type != DataType::NIL);
1493 if (type == DataType::AUDIO) {
1494 track = new AudioTrack (*this, X_("toBeResetFroXML"));
1497 track = new MidiTrack (*this, X_("toBeResetFroXML"));
1500 if (track->init()) {
1505 if (track->set_state (node, version)) {
1510 boost_debug_shared_ptr_mark_interesting (track, "Track");
1514 Route* rt = new Route (*this, X_("toBeResetFroXML"));
1516 if (rt->init () == 0 && rt->set_state (node, version) == 0) {
1517 boost_debug_shared_ptr_mark_interesting (rt, "Route");
1527 boost::shared_ptr<Route>
1528 Session::XMLRouteFactory_2X (const XMLNode& node, int version)
1530 boost::shared_ptr<Route> ret;
1532 if (node.name() != "Route") {
1536 XMLProperty const * ds_prop = node.property (X_("diskstream-id"));
1538 ds_prop = node.property (X_("diskstream"));
1541 DataType type = DataType::AUDIO;
1542 const XMLProperty* prop = node.property("default-type");
1545 type = DataType (prop->value());
1548 assert (type != DataType::NIL);
1552 list<boost::shared_ptr<Diskstream> >::iterator i = _diskstreams_2X.begin ();
1553 while (i != _diskstreams_2X.end() && (*i)->id() != ds_prop->value()) {
1557 if (i == _diskstreams_2X.end()) {
1558 error << _("Could not find diskstream for route") << endmsg;
1559 return boost::shared_ptr<Route> ();
1564 if (type == DataType::AUDIO) {
1565 track = new AudioTrack (*this, X_("toBeResetFroXML"));
1568 track = new MidiTrack (*this, X_("toBeResetFroXML"));
1571 if (track->init()) {
1576 if (track->set_state (node, version)) {
1581 track->set_diskstream (*i);
1583 boost_debug_shared_ptr_mark_interesting (track, "Track");
1587 Route* rt = new Route (*this, X_("toBeResetFroXML"));
1589 if (rt->init () == 0 && rt->set_state (node, version) == 0) {
1590 boost_debug_shared_ptr_mark_interesting (rt, "Route");
1601 Session::load_regions (const XMLNode& node)
1604 XMLNodeConstIterator niter;
1605 boost::shared_ptr<Region> region;
1607 nlist = node.children();
1611 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1612 if ((region = XMLRegionFactory (**niter, false)) == 0) {
1613 error << _("Session: cannot create Region from XML description.");
1614 const XMLProperty *name = (**niter).property("name");
1617 error << " " << string_compose (_("Can not load state for region '%1'"), name->value());
1627 boost::shared_ptr<Region>
1628 Session::XMLRegionFactory (const XMLNode& node, bool full)
1630 const XMLProperty* type = node.property("type");
1634 if (!type || type->value() == "audio") {
1635 return boost::shared_ptr<Region>(XMLAudioRegionFactory (node, full));
1636 } else if (type->value() == "midi") {
1637 return boost::shared_ptr<Region>(XMLMidiRegionFactory (node, full));
1640 } catch (failed_constructor& err) {
1641 return boost::shared_ptr<Region> ();
1644 return boost::shared_ptr<Region> ();
1647 boost::shared_ptr<AudioRegion>
1648 Session::XMLAudioRegionFactory (const XMLNode& node, bool /*full*/)
1650 const XMLProperty* prop;
1651 boost::shared_ptr<Source> source;
1652 boost::shared_ptr<AudioSource> as;
1654 SourceList master_sources;
1655 uint32_t nchans = 1;
1658 if (node.name() != X_("Region")) {
1659 return boost::shared_ptr<AudioRegion>();
1662 if ((prop = node.property (X_("channels"))) != 0) {
1663 nchans = atoi (prop->value().c_str());
1666 if ((prop = node.property ("name")) == 0) {
1667 cerr << "no name for this region\n";
1671 if ((prop = node.property (X_("source-0"))) == 0) {
1672 if ((prop = node.property ("source")) == 0) {
1673 error << _("Session: XMLNode describing a AudioRegion is incomplete (no source)") << endmsg;
1674 return boost::shared_ptr<AudioRegion>();
1678 PBD::ID s_id (prop->value());
1680 if ((source = source_by_id (s_id)) == 0) {
1681 error << string_compose(_("Session: XMLNode describing a AudioRegion references an unknown source id =%1"), s_id) << endmsg;
1682 return boost::shared_ptr<AudioRegion>();
1685 as = boost::dynamic_pointer_cast<AudioSource>(source);
1687 error << string_compose(_("Session: XMLNode describing a AudioRegion references a non-audio source id =%1"), s_id) << endmsg;
1688 return boost::shared_ptr<AudioRegion>();
1691 sources.push_back (as);
1693 /* pickup other channels */
1695 for (uint32_t n=1; n < nchans; ++n) {
1696 snprintf (buf, sizeof(buf), X_("source-%d"), n);
1697 if ((prop = node.property (buf)) != 0) {
1699 PBD::ID id2 (prop->value());
1701 if ((source = source_by_id (id2)) == 0) {
1702 error << string_compose(_("Session: XMLNode describing a AudioRegion references an unknown source id =%1"), id2) << endmsg;
1703 return boost::shared_ptr<AudioRegion>();
1706 as = boost::dynamic_pointer_cast<AudioSource>(source);
1708 error << string_compose(_("Session: XMLNode describing a AudioRegion references a non-audio source id =%1"), id2) << endmsg;
1709 return boost::shared_ptr<AudioRegion>();
1711 sources.push_back (as);
1715 for (uint32_t n = 0; n < nchans; ++n) {
1716 snprintf (buf, sizeof(buf), X_("master-source-%d"), n);
1717 if ((prop = node.property (buf)) != 0) {
1719 PBD::ID id2 (prop->value());
1721 if ((source = source_by_id (id2)) == 0) {
1722 error << string_compose(_("Session: XMLNode describing a AudioRegion references an unknown source id =%1"), id2) << endmsg;
1723 return boost::shared_ptr<AudioRegion>();
1726 as = boost::dynamic_pointer_cast<AudioSource>(source);
1728 error << string_compose(_("Session: XMLNode describing a AudioRegion references a non-audio source id =%1"), id2) << endmsg;
1729 return boost::shared_ptr<AudioRegion>();
1731 master_sources.push_back (as);
1736 boost::shared_ptr<AudioRegion> region (boost::dynamic_pointer_cast<AudioRegion> (RegionFactory::create (sources, node)));
1738 /* a final detail: this is the one and only place that we know how long missing files are */
1740 if (region->whole_file()) {
1741 for (SourceList::iterator sx = sources.begin(); sx != sources.end(); ++sx) {
1742 boost::shared_ptr<SilentFileSource> sfp = boost::dynamic_pointer_cast<SilentFileSource> (*sx);
1744 sfp->set_length (region->length());
1749 if (!master_sources.empty()) {
1750 if (master_sources.size() != nchans) {
1751 error << _("Session: XMLNode describing an AudioRegion is missing some master sources; ignored") << endmsg;
1753 region->set_master_sources (master_sources);
1761 catch (failed_constructor& err) {
1762 return boost::shared_ptr<AudioRegion>();
1766 boost::shared_ptr<MidiRegion>
1767 Session::XMLMidiRegionFactory (const XMLNode& node, bool /*full*/)
1769 const XMLProperty* prop;
1770 boost::shared_ptr<Source> source;
1771 boost::shared_ptr<MidiSource> ms;
1774 if (node.name() != X_("Region")) {
1775 return boost::shared_ptr<MidiRegion>();
1778 if ((prop = node.property ("name")) == 0) {
1779 cerr << "no name for this region\n";
1783 if ((prop = node.property (X_("source-0"))) == 0) {
1784 if ((prop = node.property ("source")) == 0) {
1785 error << _("Session: XMLNode describing a MidiRegion is incomplete (no source)") << endmsg;
1786 return boost::shared_ptr<MidiRegion>();
1790 PBD::ID s_id (prop->value());
1792 if ((source = source_by_id (s_id)) == 0) {
1793 error << string_compose(_("Session: XMLNode describing a MidiRegion references an unknown source id =%1"), s_id) << endmsg;
1794 return boost::shared_ptr<MidiRegion>();
1797 ms = boost::dynamic_pointer_cast<MidiSource>(source);
1799 error << string_compose(_("Session: XMLNode describing a MidiRegion references a non-midi source id =%1"), s_id) << endmsg;
1800 return boost::shared_ptr<MidiRegion>();
1803 sources.push_back (ms);
1806 boost::shared_ptr<MidiRegion> region (boost::dynamic_pointer_cast<MidiRegion> (RegionFactory::create (sources, node)));
1807 /* a final detail: this is the one and only place that we know how long missing files are */
1809 if (region->whole_file()) {
1810 for (SourceList::iterator sx = sources.begin(); sx != sources.end(); ++sx) {
1811 boost::shared_ptr<SilentFileSource> sfp = boost::dynamic_pointer_cast<SilentFileSource> (*sx);
1813 sfp->set_length (region->length());
1821 catch (failed_constructor& err) {
1822 return boost::shared_ptr<MidiRegion>();
1827 Session::get_sources_as_xml ()
1830 XMLNode* node = new XMLNode (X_("Sources"));
1831 Glib::Mutex::Lock lm (source_lock);
1833 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ++i) {
1834 node->add_child_nocopy (i->second->get_state());
1841 Session::path_from_region_name (DataType type, string name, string identifier)
1843 char buf[PATH_MAX+1];
1845 SessionDirectory sdir(get_best_session_directory_for_new_source());
1846 sys::path source_dir = ((type == DataType::AUDIO)
1847 ? sdir.sound_path() : sdir.midi_path());
1849 string ext = native_header_format_extension (config.get_native_file_header_format(), type);
1851 for (n = 0; n < 999999; ++n) {
1852 if (identifier.length()) {
1853 snprintf (buf, sizeof(buf), "%s%s%" PRIu32 "%s", name.c_str(),
1854 identifier.c_str(), n, ext.c_str());
1856 snprintf (buf, sizeof(buf), "%s-%" PRIu32 "%s", name.c_str(),
1860 sys::path source_path = source_dir / buf;
1862 if (!sys::exists (source_path)) {
1863 return source_path.to_string();
1867 error << string_compose (_("cannot create new file from region name \"%1\" with ident = \"%2\": too many existing files with similar names"),
1876 Session::load_sources (const XMLNode& node)
1879 XMLNodeConstIterator niter;
1880 boost::shared_ptr<Source> source;
1882 nlist = node.children();
1886 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1889 if ((source = XMLSourceFactory (**niter)) == 0) {
1890 error << _("Session: cannot create Source from XML description.") << endmsg;
1893 } catch (MissingSource& err) {
1897 if (!no_questions_about_missing_files) {
1898 user_choice = MissingFile (this, err.path, err.type).get_value_or (-1);
1903 switch (user_choice) {
1905 /* user added a new search location, so try again */
1910 /* user asked to quit the entire session load
1915 no_questions_about_missing_files = true;
1919 no_questions_about_missing_files = true;
1924 warning << _("A sound file is missing. It will be replaced by silence.") << endmsg;
1925 source = SourceFactory::createSilent (*this, **niter, max_framecnt, _current_frame_rate);
1934 boost::shared_ptr<Source>
1935 Session::XMLSourceFactory (const XMLNode& node)
1937 if (node.name() != "Source") {
1938 return boost::shared_ptr<Source>();
1942 /* note: do peak building in another thread when loading session state */
1943 return SourceFactory::create (*this, node, true);
1946 catch (failed_constructor& err) {
1947 error << string_compose (_("Found a sound file that cannot be used by %1. Talk to the progammers."), PROGRAM_NAME) << endmsg;
1948 return boost::shared_ptr<Source>();
1953 Session::save_template (string template_name)
1957 if (_state_of_the_state & CannotSave) {
1961 sys::path user_template_dir(user_template_directory());
1965 sys::create_directories (user_template_dir);
1967 catch(sys::filesystem_error& ex)
1969 error << string_compose(_("Could not create mix templates directory \"%1\" (%2)"),
1970 user_template_dir.to_string(), ex.what()) << endmsg;
1974 tree.set_root (&get_template());
1976 sys::path template_file_path(user_template_dir);
1977 template_file_path /= template_name + template_suffix;
1979 if (sys::exists (template_file_path))
1981 warning << string_compose(_("Template \"%1\" already exists - new version not created"),
1982 template_file_path.to_string()) << endmsg;
1986 if (!tree.write (template_file_path.to_string())) {
1987 error << _("mix template not saved") << endmsg;
1995 Session::rename_template (string old_name, string new_name)
1997 sys::path old_path (user_template_directory());
1998 old_path /= old_name + template_suffix;
2000 sys::path new_path(user_template_directory());
2001 new_path /= new_name + template_suffix;
2003 if (sys::exists (new_path)) {
2004 warning << string_compose(_("Template \"%1\" already exists - template not renamed"),
2005 new_path.to_string()) << endmsg;
2010 sys::rename (old_path, new_path);
2018 Session::delete_template (string name)
2020 sys::path path = user_template_directory();
2021 path /= name + template_suffix;
2032 Session::refresh_disk_space ()
2035 struct statfs statfsbuf;
2036 vector<space_and_path>::iterator i;
2037 Glib::Mutex::Lock lm (space_lock);
2040 /* get freespace on every FS that is part of the session path */
2042 _total_free_4k_blocks = 0;
2044 for (i = session_dirs.begin(); i != session_dirs.end(); ++i) {
2045 statfs ((*i).path.c_str(), &statfsbuf);
2047 scale = statfsbuf.f_bsize/4096.0;
2049 (*i).blocks = (uint32_t) floor (statfsbuf.f_bavail * scale);
2050 _total_free_4k_blocks += (*i).blocks;
2056 Session::get_best_session_directory_for_new_source ()
2058 vector<space_and_path>::iterator i;
2059 string result = _session_dir->root_path().to_string();
2061 /* handle common case without system calls */
2063 if (session_dirs.size() == 1) {
2067 /* OK, here's the algorithm we're following here:
2069 We want to select which directory to use for
2070 the next file source to be created. Ideally,
2071 we'd like to use a round-robin process so as to
2072 get maximum performance benefits from splitting
2073 the files across multiple disks.
2075 However, in situations without much diskspace, an
2076 RR approach may end up filling up a filesystem
2077 with new files while others still have space.
2078 Its therefore important to pay some attention to
2079 the freespace in the filesystem holding each
2080 directory as well. However, if we did that by
2081 itself, we'd keep creating new files in the file
2082 system with the most space until it was as full
2083 as all others, thus negating any performance
2084 benefits of this RAID-1 like approach.
2086 So, we use a user-configurable space threshold. If
2087 there are at least 2 filesystems with more than this
2088 much space available, we use RR selection between them.
2089 If not, then we pick the filesystem with the most space.
2091 This gets a good balance between the two
2095 refresh_disk_space ();
2097 int free_enough = 0;
2099 for (i = session_dirs.begin(); i != session_dirs.end(); ++i) {
2100 if ((*i).blocks * 4096 >= Config->get_disk_choice_space_threshold()) {
2105 if (free_enough >= 2) {
2106 /* use RR selection process, ensuring that the one
2110 i = last_rr_session_dir;
2113 if (++i == session_dirs.end()) {
2114 i = session_dirs.begin();
2117 if ((*i).blocks * 4096 >= Config->get_disk_choice_space_threshold()) {
2118 if (create_session_directory ((*i).path)) {
2120 last_rr_session_dir = i;
2125 } while (i != last_rr_session_dir);
2129 /* pick FS with the most freespace (and that
2130 seems to actually work ...)
2133 vector<space_and_path> sorted;
2134 space_and_path_ascending_cmp cmp;
2136 sorted = session_dirs;
2137 sort (sorted.begin(), sorted.end(), cmp);
2139 for (i = sorted.begin(); i != sorted.end(); ++i) {
2140 if (create_session_directory ((*i).path)) {
2142 last_rr_session_dir = i;
2152 Session::load_named_selections (const XMLNode& node)
2155 XMLNodeConstIterator niter;
2158 nlist = node.children();
2162 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2164 if ((ns = XMLNamedSelectionFactory (**niter)) == 0) {
2165 error << _("Session: cannot create Named Selection from XML description.") << endmsg;
2173 Session::XMLNamedSelectionFactory (const XMLNode& node)
2176 return new NamedSelection (*this, node);
2179 catch (failed_constructor& err) {
2185 Session::automation_dir () const
2187 return Glib::build_filename (_path, "automation");
2191 Session::analysis_dir () const
2193 return Glib::build_filename (_path, "analysis");
2197 Session::plugins_dir () const
2199 return Glib::build_filename (_path, "plugins");
2203 Session::load_bundles (XMLNode const & node)
2205 XMLNodeList nlist = node.children();
2206 XMLNodeConstIterator niter;
2210 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2211 if ((*niter)->name() == "InputBundle") {
2212 add_bundle (boost::shared_ptr<UserBundle> (new UserBundle (**niter, true)));
2213 } else if ((*niter)->name() == "OutputBundle") {
2214 add_bundle (boost::shared_ptr<UserBundle> (new UserBundle (**niter, false)));
2216 error << string_compose(_("Unknown node \"%1\" found in Bundles list from state file"), (*niter)->name()) << endmsg;
2225 Session::load_route_groups (const XMLNode& node, int version)
2227 XMLNodeList nlist = node.children();
2228 XMLNodeConstIterator niter;
2232 if (version >= 3000) {
2234 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2235 if ((*niter)->name() == "RouteGroup") {
2236 RouteGroup* rg = new RouteGroup (*this, "");
2237 add_route_group (rg);
2238 rg->set_state (**niter, version);
2242 } else if (version < 3000) {
2244 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2245 if ((*niter)->name() == "EditGroup" || (*niter)->name() == "MixGroup") {
2246 RouteGroup* rg = new RouteGroup (*this, "");
2247 add_route_group (rg);
2248 rg->set_state (**niter, version);
2257 Session::auto_save()
2259 save_state (_current_snapshot_name);
2263 state_file_filter (const string &str, void */*arg*/)
2265 return (str.length() > strlen(statefile_suffix) &&
2266 str.find (statefile_suffix) == (str.length() - strlen (statefile_suffix)));
2270 bool operator()(const string* a, const string* b) {
2276 remove_end(string* state)
2278 string statename(*state);
2280 string::size_type start,end;
2281 if ((start = statename.find_last_of (G_DIR_SEPARATOR)) != string::npos) {
2282 statename = statename.substr (start+1);
2285 if ((end = statename.rfind(".ardour")) == string::npos) {
2286 end = statename.length();
2289 return new string(statename.substr (0, end));
2293 Session::possible_states (string path)
2295 PathScanner scanner;
2296 vector<string*>* states = scanner (path, state_file_filter, 0, false, false);
2298 transform(states->begin(), states->end(), states->begin(), remove_end);
2301 sort (states->begin(), states->end(), cmp);
2307 Session::possible_states () const
2309 return possible_states(_path);
2313 Session::add_route_group (RouteGroup* g)
2315 _route_groups.push_back (g);
2316 route_group_added (g); /* EMIT SIGNAL */
2318 g->MembershipChanged.connect_same_thread (*this, boost::bind (&Session::route_group_changed, this));
2319 g->PropertyChanged.connect_same_thread (*this, boost::bind (&Session::route_group_changed, this));
2325 Session::remove_route_group (RouteGroup& rg)
2327 list<RouteGroup*>::iterator i;
2329 if ((i = find (_route_groups.begin(), _route_groups.end(), &rg)) != _route_groups.end()) {
2330 _route_groups.erase (i);
2333 route_group_removed (); /* EMIT SIGNAL */
2339 Session::route_group_by_name (string name)
2341 list<RouteGroup *>::iterator i;
2343 for (i = _route_groups.begin(); i != _route_groups.end(); ++i) {
2344 if ((*i)->name() == name) {
2352 Session::all_route_group() const
2354 return *_all_route_group;
2358 Session::start_reversible_command (const string& name)
2360 UndoTransaction* trans = new UndoTransaction();
2361 trans->set_name(name);
2366 Session::finish_reversible_command (UndoTransaction& ut)
2369 gettimeofday(&now, 0);
2370 ut.set_timestamp(now);
2375 Session::add_commands (vector<Command*> const & cmds)
2377 for (vector<Command*>::const_iterator i = cmds.begin(); i != cmds.end(); ++i) {
2383 Session::begin_reversible_command(const string& name)
2385 UndoTransaction* trans = new UndoTransaction();
2386 trans->set_name(name);
2388 if (!_current_trans.empty()) {
2389 _current_trans.top()->add_command (trans);
2391 _current_trans.push(trans);
2396 Session::commit_reversible_command(Command *cmd)
2398 assert(!_current_trans.empty());
2402 _current_trans.top()->add_command(cmd);
2405 if (_current_trans.top()->empty()) {
2406 _current_trans.pop();
2410 gettimeofday(&now, 0);
2411 _current_trans.top()->set_timestamp(now);
2413 _history.add(_current_trans.top());
2414 _current_trans.pop();
2418 accept_all_non_peak_files (const string& path, void */*arg*/)
2420 if (!Glib::file_test (path, Glib::FILE_TEST_IS_REGULAR)) {
2424 return (path.length() > 5 && path.find (peakfile_suffix) != (path.length() - 5));
2428 accept_all_state_files (const string& path, void */*arg*/)
2430 return (path.length() > 7 && path.find (".ardour") == (path.length() - 7));
2434 Session::find_all_sources (string path, set<string>& result)
2439 if (!tree.read (path)) {
2443 if ((node = find_named_node (*tree.root(), "Sources")) == 0) {
2448 XMLNodeConstIterator niter;
2450 nlist = node->children();
2454 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2458 if ((prop = (*niter)->property (X_("type"))) == 0) {
2462 DataType type (prop->value());
2464 if ((prop = (*niter)->property (X_("name"))) == 0) {
2468 if (Glib::path_is_absolute (prop->value())) {
2469 /* external file, ignore */
2477 if (FileSource::find (*this, type, prop->value(), true, is_new, chan, found_path)) {
2478 result.insert (found_path);
2486 Session::find_all_sources_across_snapshots (set<string>& result, bool exclude_this_snapshot)
2488 PathScanner scanner;
2489 vector<string*>* state_files;
2491 string this_snapshot_path;
2497 if (ripped[ripped.length()-1] == G_DIR_SEPARATOR) {
2498 ripped = ripped.substr (0, ripped.length() - 1);
2501 state_files = scanner (ripped, accept_all_state_files, (void *) 0, false, true);
2503 if (state_files == 0) {
2508 this_snapshot_path = _path;
2509 this_snapshot_path += legalize_for_path (_current_snapshot_name);
2510 this_snapshot_path += statefile_suffix;
2512 for (vector<string*>::iterator i = state_files->begin(); i != state_files->end(); ++i) {
2514 if (exclude_this_snapshot && **i == this_snapshot_path) {
2518 if (find_all_sources (**i, result) < 0) {
2526 struct RegionCounter {
2527 typedef std::map<PBD::ID,boost::shared_ptr<AudioSource> > AudioSourceList;
2528 AudioSourceList::iterator iter;
2529 boost::shared_ptr<Region> region;
2532 RegionCounter() : count (0) {}
2536 Session::ask_about_playlist_deletion (boost::shared_ptr<Playlist> p)
2538 boost::optional<int> r = AskAboutPlaylistDeletion (p);
2539 return r.get_value_or (1);
2543 Session::cleanup_sources (CleanupReport& rep)
2545 // FIXME: needs adaptation to midi
2547 vector<boost::shared_ptr<Source> > dead_sources;
2548 PathScanner scanner;
2550 vector<space_and_path>::iterator i;
2551 vector<space_and_path>::iterator nexti;
2552 vector<string*>* soundfiles;
2553 vector<string> unused;
2554 set<string> all_sources;
2559 _state_of_the_state = (StateOfTheState) (_state_of_the_state | InCleanup);
2561 /* step 1: consider deleting all unused playlists */
2563 if (playlists->maybe_delete_unused (boost::bind (Session::ask_about_playlist_deletion, _1))) {
2568 /* step 2: find all un-used sources */
2573 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ) {
2575 SourceMap::iterator tmp;
2580 /* do not bother with files that are zero size, otherwise we remove the current "nascent"
2584 if (!i->second->used() && (i->second->length(i->second->timeline_position() > 0))) {
2585 dead_sources.push_back (i->second);
2586 i->second->drop_references ();
2592 /* build a list of all the possible sound directories for the session */
2594 for (i = session_dirs.begin(); i != session_dirs.end(); ) {
2599 SessionDirectory sdir ((*i).path);
2600 sound_path += sdir.sound_path().to_string();
2602 if (nexti != session_dirs.end()) {
2609 /* now do the same thing for the files that ended up in the sounds dir(s)
2610 but are not referenced as sources in any snapshot.
2613 soundfiles = scanner (sound_path, accept_all_non_peak_files, (void *) 0, false, true);
2615 if (soundfiles == 0) {
2619 /* find all sources, but don't use this snapshot because the
2620 state file on disk still references sources we may have already
2624 find_all_sources_across_snapshots (all_sources, true);
2626 /* add our current source list
2629 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ++i) {
2630 boost::shared_ptr<FileSource> fs;
2632 if ((fs = boost::dynamic_pointer_cast<FileSource> (i->second)) != 0) {
2633 all_sources.insert (fs->path());
2637 char tmppath1[PATH_MAX+1];
2638 char tmppath2[PATH_MAX+1];
2640 for (vector<string*>::iterator x = soundfiles->begin(); x != soundfiles->end(); ++x) {
2645 for (set<string>::iterator i = all_sources.begin(); i != all_sources.end(); ++i) {
2647 if (realpath(spath.c_str(), tmppath1) == 0) {
2648 error << string_compose (_("Cannot expand path %1 (%2)"),
2649 spath, strerror (errno)) << endmsg;
2653 if (realpath((*i).c_str(), tmppath2) == 0) {
2654 error << string_compose (_("Cannot expand path %1 (%2)"),
2655 (*i), strerror (errno)) << endmsg;
2659 if (strcmp(tmppath1, tmppath2) == 0) {
2666 unused.push_back (spath);
2670 /* now try to move all unused files into the "dead_sounds" directory(ies) */
2672 for (vector<string>::iterator x = unused.begin(); x != unused.end(); ++x) {
2673 struct stat statbuf;
2675 rep.paths.push_back (*x);
2676 if (stat ((*x).c_str(), &statbuf) == 0) {
2677 rep.space += statbuf.st_size;
2682 /* don't move the file across filesystems, just
2683 stick it in the `dead_sound_dir_name' directory
2684 on whichever filesystem it was already on.
2687 if ((*x).find ("/sounds/") != string::npos) {
2689 /* old school, go up 1 level */
2691 newpath = Glib::path_get_dirname (*x); // "sounds"
2692 newpath = Glib::path_get_dirname (newpath); // "session-name"
2696 /* new school, go up 4 levels */
2698 newpath = Glib::path_get_dirname (*x); // "audiofiles"
2699 newpath = Glib::path_get_dirname (newpath); // "session-name"
2700 newpath = Glib::path_get_dirname (newpath); // "interchange"
2701 newpath = Glib::path_get_dirname (newpath); // "session-dir"
2704 newpath = Glib::build_filename (newpath, dead_sound_dir_name);
2706 if (g_mkdir_with_parents (newpath.c_str(), 0755) < 0) {
2707 error << string_compose(_("Session: cannot create session peakfile folder \"%1\" (%2)"), newpath, strerror (errno)) << endmsg;
2711 newpath = Glib::build_filename (newpath, Glib::path_get_basename ((*x)));
2713 if (Glib::file_test (newpath, Glib::FILE_TEST_EXISTS)) {
2715 /* the new path already exists, try versioning */
2717 char buf[PATH_MAX+1];
2721 snprintf (buf, sizeof (buf), "%s.%d", newpath.c_str(), version);
2724 while (access (newpath_v.c_str(), F_OK) == 0 && version < 999) {
2725 snprintf (buf, sizeof (buf), "%s.%d", newpath.c_str(), ++version);
2729 if (version == 999) {
2730 error << string_compose (_("there are already 1000 files with names like %1; versioning discontinued"),
2734 newpath = newpath_v;
2739 /* it doesn't exist, or we can't read it or something */
2743 if (::rename ((*x).c_str(), newpath.c_str()) != 0) {
2744 error << string_compose (_("cannot rename audio file source from %1 to %2 (%3)"),
2745 (*x), newpath, strerror (errno))
2750 /* see if there an easy to find peakfile for this file, and remove it.
2753 string peakpath = (*x).substr (0, (*x).find_last_of ('.'));
2754 peakpath += peakfile_suffix;
2756 if (access (peakpath.c_str(), W_OK) == 0) {
2757 if (::unlink (peakpath.c_str()) != 0) {
2758 error << string_compose (_("cannot remove peakfile %1 for %2 (%3)"),
2759 peakpath, _path, strerror (errno))
2761 /* try to back out */
2762 rename (newpath.c_str(), _path.c_str());
2770 /* dump the history list */
2774 /* save state so we don't end up a session file
2775 referring to non-existent sources.
2781 _state_of_the_state = (StateOfTheState) (_state_of_the_state & ~InCleanup);
2787 Session::cleanup_trash_sources (CleanupReport& rep)
2789 // FIXME: needs adaptation for MIDI
2791 vector<space_and_path>::iterator i;
2792 string dead_sound_dir;
2797 for (i = session_dirs.begin(); i != session_dirs.end(); ++i) {
2799 dead_sound_dir = (*i).path;
2800 dead_sound_dir += dead_sound_dir_name;
2802 clear_directory (dead_sound_dir, &rep.space, &rep.paths);
2809 Session::cleanup_stubfiles ()
2811 vector<space_and_path>::iterator i;
2813 for (i = session_dirs.begin(); i != session_dirs.end(); ++i) {
2816 string lname = legalize_for_path (_name);
2820 /* XXX this is a hack caused by semantic conflicts
2821 between space_and_path and the SessionDirectory concept.
2824 v.push_back ((*i).path);
2825 v.push_back ("interchange");
2826 v.push_back (lname);
2827 v.push_back ("audiofiles");
2828 v.push_back (stub_dir_name);
2830 dir = Glib::build_filename (v);
2832 clear_directory (dir);
2835 v.push_back ((*i).path);
2836 v.push_back ("interchange");
2837 v.push_back (lname);
2838 v.push_back ("midifiles");
2839 v.push_back (stub_dir_name);
2841 dir = Glib::build_filename (v);
2843 clear_directory (dir);
2848 Session::set_dirty ()
2850 bool was_dirty = dirty();
2852 _state_of_the_state = StateOfTheState (_state_of_the_state | Dirty);
2856 DirtyChanged(); /* EMIT SIGNAL */
2862 Session::set_clean ()
2864 bool was_dirty = dirty();
2866 _state_of_the_state = Clean;
2870 DirtyChanged(); /* EMIT SIGNAL */
2875 Session::set_deletion_in_progress ()
2877 _state_of_the_state = StateOfTheState (_state_of_the_state | Deletion);
2881 Session::clear_deletion_in_progress ()
2883 _state_of_the_state = StateOfTheState (_state_of_the_state & (~Deletion));
2887 Session::add_controllable (boost::shared_ptr<Controllable> c)
2889 /* this adds a controllable to the list managed by the Session.
2890 this is a subset of those managed by the Controllable class
2891 itself, and represents the only ones whose state will be saved
2892 as part of the session.
2895 Glib::Mutex::Lock lm (controllables_lock);
2896 controllables.insert (c);
2899 struct null_deleter { void operator()(void const *) const {} };
2902 Session::remove_controllable (Controllable* c)
2904 if (_state_of_the_state | Deletion) {
2908 Glib::Mutex::Lock lm (controllables_lock);
2910 Controllables::iterator x = controllables.find (boost::shared_ptr<Controllable>(c, null_deleter()));
2912 if (x != controllables.end()) {
2913 controllables.erase (x);
2917 boost::shared_ptr<Controllable>
2918 Session::controllable_by_id (const PBD::ID& id)
2920 Glib::Mutex::Lock lm (controllables_lock);
2922 for (Controllables::iterator i = controllables.begin(); i != controllables.end(); ++i) {
2923 if ((*i)->id() == id) {
2928 return boost::shared_ptr<Controllable>();
2931 boost::shared_ptr<Controllable>
2932 Session::controllable_by_descriptor (const ControllableDescriptor& desc)
2934 boost::shared_ptr<Controllable> c;
2935 boost::shared_ptr<Route> r;
2937 switch (desc.top_level_type()) {
2938 case ControllableDescriptor::NamedRoute:
2940 std::string str = desc.top_level_name();
2941 if (str == "master") {
2943 } else if (str == "control" || str == "listen") {
2946 r = route_by_name (desc.top_level_name());
2951 case ControllableDescriptor::RemoteControlID:
2952 r = route_by_remote_id (desc.rid());
2960 switch (desc.subtype()) {
2961 case ControllableDescriptor::Gain:
2962 c = r->gain_control ();
2965 case ControllableDescriptor::Solo:
2966 c = r->solo_control();
2969 case ControllableDescriptor::Mute:
2970 c = r->mute_control();
2973 case ControllableDescriptor::Recenable:
2975 boost::shared_ptr<Track> t = boost::dynamic_pointer_cast<Track>(r);
2978 c = t->rec_enable_control ();
2983 case ControllableDescriptor::PanDirection:
2985 boost::shared_ptr<Panner> p = r->panner();
2987 c = p->direction_control();
2992 case ControllableDescriptor::PanWidth:
2994 boost::shared_ptr<Panner> p = r->panner();
2996 c = p->width_control();
3001 case ControllableDescriptor::Balance:
3002 /* XXX simple pan control */
3005 case ControllableDescriptor::PluginParameter:
3007 uint32_t plugin = desc.target (0);
3008 uint32_t parameter_index = desc.target (1);
3010 /* revert to zero based counting */
3016 if (parameter_index > 0) {
3020 boost::shared_ptr<Processor> p = r->nth_plugin (plugin);
3023 c = boost::dynamic_pointer_cast<ARDOUR::AutomationControl>(
3024 p->control(Evoral::Parameter(PluginAutomation, 0, parameter_index)));
3029 case ControllableDescriptor::SendGain:
3031 uint32_t send = desc.target (0);
3033 /* revert to zero-based counting */
3039 boost::shared_ptr<Processor> p = r->nth_send (send);
3042 boost::shared_ptr<Send> s = boost::dynamic_pointer_cast<Send>(p);
3043 boost::shared_ptr<Amp> a = s->amp();
3046 c = s->amp()->gain_control();
3053 /* relax and return a null pointer */
3061 Session::add_instant_xml (XMLNode& node, bool write_to_config)
3064 Stateful::add_instant_xml (node, _path);
3067 if (write_to_config) {
3068 Config->add_instant_xml (node);
3073 Session::instant_xml (const string& node_name)
3075 return Stateful::instant_xml (node_name, _path);
3079 Session::save_history (string snapshot_name)
3087 if (snapshot_name.empty()) {
3088 snapshot_name = _current_snapshot_name;
3091 const string history_filename = legalize_for_path (snapshot_name) + history_suffix;
3092 const string backup_filename = history_filename + backup_suffix;
3093 const sys::path xml_path = _session_dir->root_path() / history_filename;
3094 const sys::path backup_path = _session_dir->root_path() / backup_filename;
3096 if (sys::exists (xml_path)) {
3099 sys::rename (xml_path, backup_path);
3101 catch (const sys::filesystem_error& err)
3103 error << _("could not backup old history file, current history not saved") << endmsg;
3108 if (!Config->get_save_history() || Config->get_saved_history_depth() < 0) {
3112 tree.set_root (&_history.get_state (Config->get_saved_history_depth()));
3114 if (!tree.write (xml_path.to_string()))
3116 error << string_compose (_("history could not be saved to %1"), xml_path.to_string()) << endmsg;
3120 sys::remove (xml_path);
3121 sys::rename (backup_path, xml_path);
3123 catch (const sys::filesystem_error& err)
3125 error << string_compose (_("could not restore history file from backup %1 (%2)"),
3126 backup_path.to_string(), err.what()) << endmsg;
3136 Session::restore_history (string snapshot_name)
3140 if (snapshot_name.empty()) {
3141 snapshot_name = _current_snapshot_name;
3144 const string xml_filename = legalize_for_path (snapshot_name) + history_suffix;
3145 const sys::path xml_path = _session_dir->root_path() / xml_filename;
3147 info << "Loading history from " << xml_path.to_string() << endmsg;
3149 if (!sys::exists (xml_path)) {
3150 info << string_compose (_("%1: no history file \"%2\" for this session."),
3151 _name, xml_path.to_string()) << endmsg;
3155 if (!tree.read (xml_path.to_string())) {
3156 error << string_compose (_("Could not understand session history file \"%1\""),
3157 xml_path.to_string()) << endmsg;
3164 for (XMLNodeConstIterator it = tree.root()->children().begin(); it != tree.root()->children().end(); it++) {
3167 UndoTransaction* ut = new UndoTransaction ();
3170 ut->set_name(t->property("name")->value());
3171 stringstream ss(t->property("tv-sec")->value());
3173 ss.str(t->property("tv-usec")->value());
3175 ut->set_timestamp(tv);
3177 for (XMLNodeConstIterator child_it = t->children().begin();
3178 child_it != t->children().end(); child_it++)
3180 XMLNode *n = *child_it;
3183 if (n->name() == "MementoCommand" ||
3184 n->name() == "MementoUndoCommand" ||
3185 n->name() == "MementoRedoCommand") {
3187 if ((c = memento_command_factory(n))) {
3191 } else if (n->name() == "DiffCommand") {
3192 PBD::ID id(n->property("midi-source")->value());
3193 boost::shared_ptr<MidiSource> midi_source =
3194 boost::dynamic_pointer_cast<MidiSource, Source>(source_by_id(id));
3196 ut->add_command(new MidiModel::DiffCommand(midi_source->model(), *n));
3198 error << _("Failed to downcast MidiSource for DiffCommand") << endmsg;
3201 } else if (n->name() == "StatefulDiffCommand") {
3202 if ((c = stateful_diff_command_factory (n))) {
3203 ut->add_command (c);
3206 error << string_compose(_("Couldn't figure out how to make a Command out of a %1 XMLNode."), n->name()) << endmsg;
3217 Session::config_changed (std::string p, bool ours)
3223 if (p == "seamless-loop") {
3225 } else if (p == "rf-speed") {
3227 } else if (p == "auto-loop") {
3229 } else if (p == "auto-input") {
3231 if (Config->get_monitoring_model() == HardwareMonitoring && transport_rolling()) {
3232 /* auto-input only makes a difference if we're rolling */
3234 boost::shared_ptr<RouteList> rl = routes.reader ();
3235 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
3236 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
3237 if (tr && tr->record_enabled ()) {
3238 tr->monitor_input (!config.get_auto_input());
3243 } else if (p == "punch-in") {
3247 if ((location = _locations->auto_punch_location()) != 0) {
3249 if (config.get_punch_in ()) {
3250 replace_event (SessionEvent::PunchIn, location->start());
3252 remove_event (location->start(), SessionEvent::PunchIn);
3256 } else if (p == "punch-out") {
3260 if ((location = _locations->auto_punch_location()) != 0) {
3262 if (config.get_punch_out()) {
3263 replace_event (SessionEvent::PunchOut, location->end());
3265 clear_events (SessionEvent::PunchOut);
3269 } else if (p == "edit-mode") {
3271 Glib::Mutex::Lock lm (playlists->lock);
3273 for (SessionPlaylists::List::iterator i = playlists->playlists.begin(); i != playlists->playlists.end(); ++i) {
3274 (*i)->set_edit_mode (Config->get_edit_mode ());
3277 } else if (p == "use-video-sync") {
3279 waiting_for_sync_offset = config.get_use_video_sync();
3281 } else if (p == "mmc-control") {
3283 //poke_midi_thread ();
3285 } else if (p == "mmc-device-id" || p == "mmc-receive-id") {
3287 MIDI::Manager::instance()->mmc()->set_receive_device_id (Config->get_mmc_receive_device_id());
3289 } else if (p == "mmc-send-id") {
3291 MIDI::Manager::instance()->mmc()->set_send_device_id (Config->get_mmc_send_device_id());
3293 } else if (p == "midi-control") {
3295 //poke_midi_thread ();
3297 } else if (p == "raid-path") {
3299 setup_raid_path (config.get_raid_path());
3301 } else if (p == "timecode-format") {
3305 } else if (p == "video-pullup") {
3309 } else if (p == "seamless-loop") {
3311 if (play_loop && transport_rolling()) {
3312 // to reset diskstreams etc
3313 request_play_loop (true);
3316 } else if (p == "rf-speed") {
3318 cumulative_rf_motion = 0;
3321 } else if (p == "click-sound") {
3323 setup_click_sounds (1);
3325 } else if (p == "click-emphasis-sound") {
3327 setup_click_sounds (-1);
3329 } else if (p == "clicking") {
3331 if (Config->get_clicking()) {
3332 if (_click_io && click_data) { // don't require emphasis data
3339 } else if (p == "send-mtc") {
3341 session_send_mtc = Config->get_send_mtc();
3342 if (session_send_mtc) {
3343 /* mark us ready to send */
3344 next_quarter_frame_to_send = 0;
3347 } else if (p == "send-mmc") {
3349 MIDI::Manager::instance()->mmc()->enable_send (Config->get_send_mmc ());
3351 } else if (p == "midi-feedback") {
3353 session_midi_feedback = Config->get_midi_feedback();
3355 } else if (p == "jack-time-master") {
3357 engine().reset_timebase ();
3359 } else if (p == "native-file-header-format") {
3361 if (!first_file_header_format_reset) {
3362 reset_native_file_format ();
3365 first_file_header_format_reset = false;
3367 } else if (p == "native-file-data-format") {
3369 if (!first_file_data_format_reset) {
3370 reset_native_file_format ();
3373 first_file_data_format_reset = false;
3375 } else if (p == "external-sync") {
3376 if (!config.get_external_sync()) {
3377 drop_sync_source ();
3379 switch_to_sync_source (config.get_sync_source());
3381 } else if (p == "remote-model") {
3382 set_remote_control_ids ();
3383 } else if (p == "denormal-model") {
3385 } else if (p == "history-depth") {
3386 set_history_depth (Config->get_history_depth());
3387 } else if (p == "sync-all-route-ordering") {
3388 sync_order_keys ("session");
3389 } else if (p == "initial-program-change") {
3391 if (MIDI::Manager::instance()->mmc()->output_port() && Config->get_initial_program_change() >= 0) {
3394 buf[0] = MIDI::program; // channel zero by default
3395 buf[1] = (Config->get_initial_program_change() & 0x7f);
3397 MIDI::Manager::instance()->mmc()->output_port()->midimsg (buf, sizeof (buf), 0);
3399 } else if (p == "solo-mute-override") {
3400 // catch_up_on_solo_mute_override ();
3401 } else if (p == "listen-position") {
3402 listen_position_changed ();
3403 } else if (p == "solo-control-is-listen-control") {
3404 solo_control_mode_changed ();
3412 Session::set_history_depth (uint32_t d)
3414 _history.set_depth (d);
3418 Session::load_diskstreams_2X (XMLNode const & node, int)
3421 XMLNodeConstIterator citer;
3423 clist = node.children();
3425 for (citer = clist.begin(); citer != clist.end(); ++citer) {
3428 /* diskstreams added automatically by DiskstreamCreated handler */
3429 if ((*citer)->name() == "AudioDiskstream" || (*citer)->name() == "DiskStream") {
3430 boost::shared_ptr<AudioDiskstream> dsp (new AudioDiskstream (*this, **citer));
3431 _diskstreams_2X.push_back (dsp);
3433 error << _("Session: unknown diskstream type in XML") << endmsg;
3437 catch (failed_constructor& err) {
3438 error << _("Session: could not load diskstream via XML state") << endmsg;
3446 /** Connect things to the MMC object */
3448 Session::setup_midi_machine_control ()
3450 MIDI::MachineControl* mmc = MIDI::Manager::instance()->mmc ();
3452 mmc->Play.connect_same_thread (*this, boost::bind (&Session::mmc_deferred_play, this, _1));
3453 mmc->DeferredPlay.connect_same_thread (*this, boost::bind (&Session::mmc_deferred_play, this, _1));
3454 mmc->Stop.connect_same_thread (*this, boost::bind (&Session::mmc_stop, this, _1));
3455 mmc->FastForward.connect_same_thread (*this, boost::bind (&Session::mmc_fast_forward, this, _1));
3456 mmc->Rewind.connect_same_thread (*this, boost::bind (&Session::mmc_rewind, this, _1));
3457 mmc->Pause.connect_same_thread (*this, boost::bind (&Session::mmc_pause, this, _1));
3458 mmc->RecordPause.connect_same_thread (*this, boost::bind (&Session::mmc_record_pause, this, _1));
3459 mmc->RecordStrobe.connect_same_thread (*this, boost::bind (&Session::mmc_record_strobe, this, _1));
3460 mmc->RecordExit.connect_same_thread (*this, boost::bind (&Session::mmc_record_exit, this, _1));
3461 mmc->Locate.connect_same_thread (*this, boost::bind (&Session::mmc_locate, this, _1, _2));
3462 mmc->Step.connect_same_thread (*this, boost::bind (&Session::mmc_step, this, _1, _2));
3463 mmc->Shuttle.connect_same_thread (*this, boost::bind (&Session::mmc_shuttle, this, _1, _2, _3));
3464 mmc->TrackRecordStatusChange.connect_same_thread (*this, boost::bind (&Session::mmc_record_enable, this, _1, _2, _3));
3466 /* also handle MIDI SPP because its so common */
3468 mmc->SPPStart.connect_same_thread (*this, boost::bind (&Session::spp_start, this, _1, _2));
3469 mmc->SPPContinue.connect_same_thread (*this, boost::bind (&Session::spp_continue, this, _1, _2));
3470 mmc->SPPStop.connect_same_thread (*this, boost::bind (&Session::spp_stop, this, _1, _2));