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"
25 #define __STDC_FORMAT_MACROS 1
34 #include <cstdio> /* snprintf(3) ... grrr */
48 #include <sys/param.h>
49 #include <sys/mount.h>
53 #include <glibmm/thread.h>
55 #include "midi++/mmc.h"
56 #include "midi++/port.h"
57 #include "midi++/manager.h"
59 #include "pbd/boost_debug.h"
60 #include "pbd/controllable_descriptor.h"
61 #include "pbd/enumwriter.h"
62 #include "pbd/error.h"
63 #include "pbd/pathscanner.h"
64 #include "pbd/pthread_utils.h"
65 #include "pbd/search_path.h"
66 #include "pbd/stacktrace.h"
67 #include "pbd/convert.h"
68 #include "pbd/clear_dir.h"
70 #include "ardour/amp.h"
71 #include "ardour/audio_diskstream.h"
72 #include "ardour/audio_track.h"
73 #include "ardour/audioengine.h"
74 #include "ardour/audiofilesource.h"
75 #include "ardour/audioplaylist.h"
76 #include "ardour/audioregion.h"
77 #include "ardour/auditioner.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/processor.h"
96 #include "ardour/port.h"
97 #include "ardour/region_factory.h"
98 #include "ardour/route_group.h"
99 #include "ardour/send.h"
100 #include "ardour/session.h"
101 #include "ardour/session_directory.h"
102 #include "ardour/session_metadata.h"
103 #include "ardour/session_state_utils.h"
104 #include "ardour/session_playlists.h"
105 #include "ardour/session_utils.h"
106 #include "ardour/silentfilesource.h"
107 #include "ardour/slave.h"
108 #include "ardour/smf_source.h"
109 #include "ardour/sndfile_helpers.h"
110 #include "ardour/sndfilesource.h"
111 #include "ardour/source_factory.h"
112 #include "ardour/template_utils.h"
113 #include "ardour/tempo.h"
114 #include "ardour/ticker.h"
115 #include "ardour/user_bundle.h"
116 #include "ardour/utils.h"
117 #include "ardour/utils.h"
118 #include "ardour/version.h"
119 #include "ardour/playlist_factory.h"
121 #include "control_protocol/control_protocol.h"
127 using namespace ARDOUR;
131 Session::first_stage_init (string fullpath, string snapshot_name)
133 if (fullpath.length() == 0) {
135 throw failed_constructor();
138 char buf[PATH_MAX+1];
139 if (!realpath (fullpath.c_str(), buf) && (errno != ENOENT)) {
140 error << string_compose(_("Could not use path %1 (%s)"), buf, strerror(errno)) << endmsg;
142 throw failed_constructor();
147 if (_path[_path.length()-1] != '/') {
148 _path += G_DIR_SEPARATOR;
151 if (Glib::file_test (_path, Glib::FILE_TEST_EXISTS) && ::access (_path.c_str(), W_OK)) {
157 /* these two are just provisional settings. set_state()
158 will likely override them.
161 _name = _current_snapshot_name = snapshot_name;
163 set_history_depth (Config->get_history_depth());
165 _current_frame_rate = _engine.frame_rate ();
166 _nominal_frame_rate = _current_frame_rate;
167 _base_frame_rate = _current_frame_rate;
169 _tempo_map = new TempoMap (_current_frame_rate);
170 _tempo_map->PropertyChanged.connect_same_thread (*this, boost::bind (&Session::tempo_map_changed, this, _1));
173 _non_soloed_outs_muted = false;
175 _solo_isolated_cnt = 0;
176 g_atomic_int_set (&processing_prohibited, 0);
177 _transport_speed = 0;
178 _last_transport_speed = 0;
179 _target_transport_speed = 0;
180 auto_play_legal = false;
181 transport_sub_state = 0;
182 _transport_frame = 0;
183 _requested_return_frame = -1;
184 _session_range_location = 0;
185 g_atomic_int_set (&_record_status, Disabled);
186 loop_changing = false;
189 _last_roll_location = 0;
190 _last_roll_or_reversal_location = 0;
191 _last_record_location = 0;
192 pending_locate_frame = 0;
193 pending_locate_roll = false;
194 pending_locate_flush = false;
195 state_was_pending = false;
197 outbound_mtc_timecode_frame = 0;
198 next_quarter_frame_to_send = -1;
199 current_block_size = 0;
200 solo_update_disabled = false;
201 _have_captured = false;
202 _worst_output_latency = 0;
203 _worst_input_latency = 0;
204 _worst_track_latency = 0;
205 _state_of_the_state = StateOfTheState(CannotSave|InitialConnecting|Loading);
206 _was_seamless = Config->get_seamless_loop ();
208 session_send_mtc = false;
209 g_atomic_int_set (&_playback_load, 100);
210 g_atomic_int_set (&_capture_load, 100);
213 pending_abort = false;
214 destructive_index = 0;
215 first_file_data_format_reset = true;
216 first_file_header_format_reset = true;
217 post_export_sync = false;
220 no_questions_about_missing_files = false;
222 AudioDiskstream::allocate_working_buffers();
224 /* default short fade = 15ms */
226 Crossfade::set_short_xfade_length ((nframes_t) floor (config.get_short_xfade_seconds() * frame_rate()));
227 SndFileSource::setup_standard_crossfades (*this, frame_rate());
229 last_mmc_step.tv_sec = 0;
230 last_mmc_step.tv_usec = 0;
233 /* click sounds are unset by default, which causes us to internal
234 waveforms for clicks.
238 click_emphasis_length = 0;
241 process_function = &Session::process_with_events;
243 if (config.get_use_video_sync()) {
244 waiting_for_sync_offset = true;
246 waiting_for_sync_offset = false;
249 last_timecode_when = 0;
250 _timecode_offset = 0;
251 _timecode_offset_negative = true;
252 last_timecode_valid = false;
256 last_rr_session_dir = session_dirs.begin();
257 refresh_disk_space ();
259 // set_default_fade (0.2, 5.0); /* steepness, millisecs */
263 average_slave_delta = 1800; // !!! why 1800 ????
264 have_first_delta_accumulator = false;
265 delta_accumulator_cnt = 0;
266 _slave_state = Stopped;
268 _engine.GraphReordered.connect_same_thread (*this, boost::bind (&Session::graph_reordered, this));
270 /* These are all static "per-class" signals */
272 SourceFactory::SourceCreated.connect_same_thread (*this, boost::bind (&Session::add_source, this, _1));
273 PlaylistFactory::PlaylistCreated.connect_same_thread (*this, boost::bind (&Session::add_playlist, this, _1, _2));
274 AutomationList::AutomationListCreated.connect_same_thread (*this, boost::bind (&Session::add_automation_list, this, _1));
275 Controllable::Destroyed.connect_same_thread (*this, boost::bind (&Session::remove_controllable, this, _1));
276 IO::PortCountChanged.connect_same_thread (*this, boost::bind (&Session::ensure_buffers, this, _1));
278 /* stop IO objects from doing stuff until we're ready for them */
280 Delivery::disable_panners ();
281 IO::disable_connecting ();
285 Session::second_stage_init ()
287 AudioFileSource::set_peak_dir (_session_dir->peak_path().to_string());
290 if (load_state (_current_snapshot_name)) {
293 cleanup_stubfiles ();
296 if (_butler->start_thread()) {
300 if (start_midi_thread ()) {
304 setup_midi_machine_control ();
306 // set_state() will call setup_raid_path(), but if it's a new session we need
307 // to call setup_raid_path() here.
310 if (set_state (*state_tree->root(), Stateful::loading_state_version)) {
314 setup_raid_path(_path);
317 /* we can't save till after ::when_engine_running() is called,
318 because otherwise we save state with no connections made.
319 therefore, we reset _state_of_the_state because ::set_state()
320 will have cleared it.
322 we also have to include Loading so that any events that get
323 generated between here and the end of ::when_engine_running()
324 will be processed directly rather than queued.
327 _state_of_the_state = StateOfTheState (_state_of_the_state|CannotSave|Loading);
329 _locations->changed.connect_same_thread (*this, boost::bind (&Session::locations_changed, this));
330 _locations->added.connect_same_thread (*this, boost::bind (&Session::locations_added, this, _1));
331 setup_click_sounds (0);
332 setup_midi_control ();
334 /* Pay attention ... */
336 _engine.Halted.connect_same_thread (*this, boost::bind (&Session::engine_halted, this));
337 _engine.Xrun.connect_same_thread (*this, boost::bind (&Session::xrun_recovery, this));
340 when_engine_running ();
343 /* handle this one in a different way than all others, so that its clear what happened */
345 catch (AudioEngine::PortRegistrationFailure& err) {
346 error << err.what() << endmsg;
354 BootMessage (_("Reset Remote Controls"));
356 send_full_time_code (0);
357 _engine.transport_locate (0);
359 MIDI::Manager::instance()->mmc()->send (MIDI::MachineControlCommand (MIDI::MachineControl::cmdMmcReset));
360 MIDI::Manager::instance()->mmc()->send (MIDI::MachineControlCommand (Timecode::Time ()));
362 MidiClockTicker::instance().set_session (this);
363 MIDI::Name::MidiPatchManager::instance().set_session (this);
365 /* initial program change will be delivered later; see ::config_changed() */
367 BootMessage (_("Reset Control Protocols"));
369 ControlProtocolManager::instance().set_session (this);
371 _state_of_the_state = Clean;
373 Port::set_connecting_blocked (false);
375 DirtyChanged (); /* EMIT SIGNAL */
377 if (state_was_pending) {
378 save_state (_current_snapshot_name);
379 remove_pending_capture_state ();
380 state_was_pending = false;
383 BootMessage (_("Session loading complete"));
389 Session::raid_path () const
391 SearchPath raid_search_path;
393 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
394 raid_search_path += sys::path((*i).path);
397 return raid_search_path.to_string ();
401 Session::setup_raid_path (string path)
410 session_dirs.clear ();
412 SearchPath search_path(path);
413 SearchPath sound_search_path;
414 SearchPath midi_search_path;
416 for (SearchPath::const_iterator i = search_path.begin(); i != search_path.end(); ++i) {
417 sp.path = (*i).to_string ();
418 sp.blocks = 0; // not needed
419 session_dirs.push_back (sp);
421 SessionDirectory sdir(sp.path);
423 sound_search_path += sdir.sound_path ();
424 midi_search_path += sdir.midi_path ();
427 // reset the round-robin soundfile path thingie
428 last_rr_session_dir = session_dirs.begin();
432 Session::path_is_within_session (const std::string& path)
434 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
435 if (path.find ((*i).path) == 0) {
443 Session::ensure_subdirs ()
447 dir = session_directory().peak_path().to_string();
449 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
450 error << string_compose(_("Session: cannot create session peakfile folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
454 dir = session_directory().sound_path().to_string();
456 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
457 error << string_compose(_("Session: cannot create session sounds dir \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
461 dir = session_directory().sound_stub_path().to_string();
463 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
464 error << string_compose(_("Session: cannot create session stub sounds dir \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
468 dir = session_directory().midi_path().to_string();
470 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
471 error << string_compose(_("Session: cannot create session midi dir \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
475 dir = session_directory().midi_stub_path().to_string();
477 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
478 error << string_compose(_("Session: cannot create session stub midi dir \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
482 dir = session_directory().dead_sound_path().to_string();
484 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
485 error << string_compose(_("Session: cannot create session dead sounds folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
489 dir = session_directory().export_path().to_string();
491 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
492 error << string_compose(_("Session: cannot create session export folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
496 dir = analysis_dir ();
498 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
499 error << string_compose(_("Session: cannot create session analysis folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
507 Session::create (const string& mix_template, BusProfile* bus_profile)
510 if (g_mkdir_with_parents (_path.c_str(), 0755) < 0) {
511 error << string_compose(_("Session: cannot create session folder \"%1\" (%2)"), _path, strerror (errno)) << endmsg;
515 if (ensure_subdirs ()) {
519 if (!mix_template.empty()) {
520 std::string in_path = mix_template;
522 ifstream in(in_path.c_str());
525 string out_path = _path;
527 out_path += statefile_suffix;
529 ofstream out(out_path.c_str());
537 error << string_compose (_("Could not open %1 for writing mix template"), out_path)
543 error << string_compose (_("Could not open mix template %1 for reading"), in_path)
550 /* Instantiate metadata */
552 _metadata = new SessionMetadata ();
554 /* set initial start + end point */
556 _state_of_the_state = Clean;
558 /* set up Master Out and Control Out if necessary */
564 ChanCount count(DataType::AUDIO, bus_profile->master_out_channels);
566 if (bus_profile->master_out_channels) {
567 Route* rt = new Route (*this, _("master"), Route::MasterOut, DataType::AUDIO);
572 boost_debug_shared_ptr_mark_interesting (rt, "Route");
573 boost::shared_ptr<Route> r (rt);
574 r->input()->ensure_io (count, false, this);
575 r->output()->ensure_io (count, false, this);
576 r->set_remote_control_id (control_id++);
580 if (Config->get_use_monitor_bus()) {
581 Route* rt = new Route (*this, _("monitor"), Route::MonitorOut, DataType::AUDIO);
586 boost_debug_shared_ptr_mark_interesting (rt, "Route");
587 boost::shared_ptr<Route> r (rt);
588 r->input()->ensure_io (count, false, this);
589 r->output()->ensure_io (count, false, this);
590 r->set_remote_control_id (control_id);
596 /* prohibit auto-connect to master, because there isn't one */
597 bus_profile->output_ac = AutoConnectOption (bus_profile->output_ac & ~AutoConnectMaster);
601 add_routes (rl, false);
604 /* this allows the user to override settings with an environment variable.
607 if (no_auto_connect()) {
608 bus_profile->input_ac = AutoConnectOption (0);
609 bus_profile->output_ac = AutoConnectOption (0);
612 Config->set_input_auto_connect (bus_profile->input_ac);
613 Config->set_output_auto_connect (bus_profile->output_ac);
622 Session::maybe_write_autosave()
624 if (dirty() && record_status() != Recording) {
625 save_state("", true);
630 Session::remove_pending_capture_state ()
632 sys::path pending_state_file_path(_session_dir->root_path());
634 pending_state_file_path /= legalize_for_path (_current_snapshot_name) + pending_suffix;
638 sys::remove (pending_state_file_path);
640 catch(sys::filesystem_error& ex)
642 error << string_compose(_("Could remove pending capture state at path \"%1\" (%2)"),
643 pending_state_file_path.to_string(), ex.what()) << endmsg;
647 /** Rename a state file.
648 * @param snapshot_name Snapshot name.
651 Session::rename_state (string old_name, string new_name)
653 if (old_name == _current_snapshot_name || old_name == _name) {
654 /* refuse to rename the current snapshot or the "main" one */
658 const string old_xml_filename = legalize_for_path (old_name) + statefile_suffix;
659 const string new_xml_filename = legalize_for_path (new_name) + statefile_suffix;
661 const sys::path old_xml_path = _session_dir->root_path() / old_xml_filename;
662 const sys::path new_xml_path = _session_dir->root_path() / new_xml_filename;
666 sys::rename (old_xml_path, new_xml_path);
668 catch (const sys::filesystem_error& err)
670 error << string_compose(_("could not rename snapshot %1 to %2 (%3)"),
671 old_name, new_name, err.what()) << endmsg;
675 /** Remove a state file.
676 * @param snapshot_name Snapshot name.
679 Session::remove_state (string snapshot_name)
681 if (snapshot_name == _current_snapshot_name || snapshot_name == _name) {
682 // refuse to remove the current snapshot or the "main" one
686 sys::path xml_path(_session_dir->root_path());
688 xml_path /= legalize_for_path (snapshot_name) + statefile_suffix;
690 if (!create_backup_file (xml_path)) {
691 // don't remove it if a backup can't be made
692 // create_backup_file will log the error.
697 sys::remove (xml_path);
700 #ifdef HAVE_JACK_SESSION
702 Session::jack_session_event (jack_session_event_t * event)
706 struct tm local_time;
709 localtime_r (&n, &local_time);
710 strftime (timebuf, sizeof(timebuf), "JS_%FT%T", &local_time);
712 if (event->type == JackSessionSaveTemplate)
714 if (save_template( timebuf )) {
715 event->flags = JackSessionSaveError;
717 string cmd ("ardour3 -P -U ");
718 cmd += event->client_uuid;
722 event->command_line = strdup (cmd.c_str());
727 if (save_state (timebuf)) {
728 event->flags = JackSessionSaveError;
730 sys::path xml_path (_session_dir->root_path());
731 xml_path /= legalize_for_path (timebuf) + statefile_suffix;
733 string cmd ("ardour3 -P -U ");
734 cmd += event->client_uuid;
736 cmd += xml_path.to_string();
739 event->command_line = strdup (cmd.c_str());
743 jack_session_reply (_engine.jack(), event);
745 if (event->type == JackSessionSaveAndQuit) {
746 Quit (); /* EMIT SIGNAL */
749 jack_session_event_free( event );
754 Session::save_state (string snapshot_name, bool pending, bool switch_to_snapshot)
757 sys::path xml_path(_session_dir->root_path());
759 if (!_writable || (_state_of_the_state & CannotSave)) {
763 if (!_engine.connected ()) {
764 error << string_compose (_("the %1 audio engine is not connected and state saving would lose all I/O connections. Session not saved"),
770 /* tell sources we're saving first, in case they write out to a new file
771 * which should be saved with the state rather than the old one */
772 for (SourceMap::const_iterator i = sources.begin(); i != sources.end(); ++i) {
773 i->second->session_saved();
776 tree.set_root (&get_state());
778 if (snapshot_name.empty()) {
779 snapshot_name = _current_snapshot_name;
780 } else if (switch_to_snapshot) {
781 _current_snapshot_name = snapshot_name;
786 /* proper save: use statefile_suffix (.ardour in English) */
788 xml_path /= legalize_for_path (snapshot_name) + statefile_suffix;
790 /* make a backup copy of the old file */
792 if (sys::exists(xml_path) && !create_backup_file (xml_path)) {
793 // create_backup_file will log the error
799 /* pending save: use pending_suffix (.pending in English) */
800 xml_path /= legalize_for_path (snapshot_name) + pending_suffix;
803 sys::path tmp_path(_session_dir->root_path());
805 tmp_path /= legalize_for_path (snapshot_name) + temp_suffix;
807 // cerr << "actually writing state to " << xml_path.to_string() << endl;
809 if (!tree.write (tmp_path.to_string())) {
810 error << string_compose (_("state could not be saved to %1"), tmp_path.to_string()) << endmsg;
811 sys::remove (tmp_path);
816 if (rename (tmp_path.to_string().c_str(), xml_path.to_string().c_str()) != 0) {
817 error << string_compose (_("could not rename temporary session file %1 to %2"),
818 tmp_path.to_string(), xml_path.to_string()) << endmsg;
819 sys::remove (tmp_path);
826 save_history (snapshot_name);
828 bool was_dirty = dirty();
830 _state_of_the_state = StateOfTheState (_state_of_the_state & ~Dirty);
833 DirtyChanged (); /* EMIT SIGNAL */
836 StateSaved (snapshot_name); /* EMIT SIGNAL */
843 Session::restore_state (string snapshot_name)
845 if (load_state (snapshot_name) == 0) {
846 set_state (*state_tree->root(), Stateful::loading_state_version);
853 Session::load_state (string snapshot_name)
858 state_was_pending = false;
860 /* check for leftover pending state from a crashed capture attempt */
862 sys::path xmlpath(_session_dir->root_path());
863 xmlpath /= legalize_for_path (snapshot_name) + pending_suffix;
865 if (sys::exists (xmlpath)) {
867 /* there is pending state from a crashed capture attempt */
869 boost::optional<int> r = AskAboutPendingState();
870 if (r.get_value_or (1)) {
871 state_was_pending = true;
875 if (!state_was_pending) {
876 xmlpath = _session_dir->root_path();
877 xmlpath /= snapshot_name;
880 if (!sys::exists (xmlpath)) {
881 xmlpath = _session_dir->root_path();
882 xmlpath /= legalize_for_path (snapshot_name) + statefile_suffix;
883 if (!sys::exists (xmlpath)) {
884 error << string_compose(_("%1: session state information file \"%2\" doesn't exist!"), _name, xmlpath.to_string()) << endmsg;
889 state_tree = new XMLTree;
893 /* writable() really reflects the whole folder, but if for any
894 reason the session state file can't be written to, still
898 if (::access (xmlpath.to_string().c_str(), W_OK) != 0) {
902 if (!state_tree->read (xmlpath.to_string())) {
903 error << string_compose(_("Could not understand ardour file %1"), xmlpath.to_string()) << endmsg;
909 XMLNode& root (*state_tree->root());
911 if (root.name() != X_("Session")) {
912 error << string_compose (_("Session file %1 is not a session"), xmlpath.to_string()) << endmsg;
918 const XMLProperty* prop;
920 if ((prop = root.property ("version")) == 0) {
921 /* no version implies very old version of Ardour */
922 Stateful::loading_state_version = 1000;
928 sscanf (prop->value().c_str(), "%d.%d.%d", &major, &minor, µ);
929 Stateful::loading_state_version = (major * 1000) + minor;
932 if (Stateful::loading_state_version < CURRENT_SESSION_FILE_VERSION) {
934 sys::path backup_path(_session_dir->root_path());
936 backup_path /= legalize_for_path (snapshot_name) + "-1" + statefile_suffix;
938 // only create a backup once
939 if (sys::exists (backup_path)) {
943 info << string_compose (_("Copying old session file %1 to %2\nUse %2 with %3 versions before 2.0 from now on"),
944 xmlpath.to_string(), backup_path.to_string(), PROGRAM_NAME)
949 sys::copy_file (xmlpath, backup_path);
951 catch(sys::filesystem_error& ex)
953 error << string_compose (_("Unable to make backup of state file %1 (%2)"),
954 xmlpath.to_string(), ex.what())
964 Session::load_options (const XMLNode& node)
966 LocaleGuard lg (X_("POSIX"));
967 config.set_variables (node);
978 Session::get_template()
980 /* if we don't disable rec-enable, diskstreams
981 will believe they need to store their capture
982 sources in their state node.
985 disable_record (false);
991 Session::state(bool full_state)
993 XMLNode* node = new XMLNode("Session");
996 // store libardour version, just in case
998 snprintf(buf, sizeof(buf), "%d.%d.%d", libardour3_major_version, libardour3_minor_version, libardour3_micro_version);
999 node->add_property("version", string(buf));
1001 /* store configuration settings */
1005 node->add_property ("name", _name);
1006 snprintf (buf, sizeof (buf), "%" PRId32, _nominal_frame_rate);
1007 node->add_property ("sample-rate", buf);
1009 if (session_dirs.size() > 1) {
1013 vector<space_and_path>::iterator i = session_dirs.begin();
1014 vector<space_and_path>::iterator next;
1016 ++i; /* skip the first one */
1020 while (i != session_dirs.end()) {
1024 if (next != session_dirs.end()) {
1034 child = node->add_child ("Path");
1035 child->add_content (p);
1039 /* save the ID counter */
1041 snprintf (buf, sizeof (buf), "%" PRIu64, ID::counter());
1042 node->add_property ("id-counter", buf);
1044 /* save the event ID counter */
1046 snprintf (buf, sizeof (buf), "%d", Evoral::event_id_counter());
1047 node->add_property ("event-counter", buf);
1049 /* various options */
1051 node->add_child_nocopy (config.get_variables ());
1053 node->add_child_nocopy (_metadata->get_state());
1055 child = node->add_child ("Sources");
1058 Glib::Mutex::Lock sl (source_lock);
1060 for (SourceMap::iterator siter = sources.begin(); siter != sources.end(); ++siter) {
1062 /* Don't save information about non-destructive file sources that are empty
1063 and unused by any regions.
1066 boost::shared_ptr<FileSource> fs;
1067 if ((fs = boost::dynamic_pointer_cast<FileSource> (siter->second)) != 0) {
1068 if (!fs->destructive()) {
1069 if (fs->empty() && !fs->used()) {
1075 child->add_child_nocopy (siter->second->get_state());
1079 child = node->add_child ("Regions");
1082 Glib::Mutex::Lock rl (region_lock);
1083 const RegionFactory::RegionMap& region_map (RegionFactory::all_regions());
1084 for (RegionFactory::RegionMap::const_iterator i = region_map.begin(); i != region_map.end(); ++i) {
1085 boost::shared_ptr<Region> r = i->second;
1086 /* only store regions not attached to playlists */
1087 if (r->playlist() == 0) {
1088 child->add_child_nocopy (r->state ());
1094 node->add_child_nocopy (_locations->get_state());
1096 // for a template, just create a new Locations, populate it
1097 // with the default start and end, and get the state for that.
1098 Locations loc (*this);
1099 Location* range = new Location (*this, 0, 0, _("session"), Location::IsSessionRange);
1100 range->set (max_framepos, 0);
1102 node->add_child_nocopy (loc.get_state());
1105 child = node->add_child ("Bundles");
1107 boost::shared_ptr<BundleList> bundles = _bundles.reader ();
1108 for (BundleList::iterator i = bundles->begin(); i != bundles->end(); ++i) {
1109 boost::shared_ptr<UserBundle> b = boost::dynamic_pointer_cast<UserBundle> (*i);
1111 child->add_child_nocopy (b->get_state());
1116 child = node->add_child ("Routes");
1118 boost::shared_ptr<RouteList> r = routes.reader ();
1120 RoutePublicOrderSorter cmp;
1121 RouteList public_order (*r);
1122 public_order.sort (cmp);
1124 /* the sort should have put control outs first */
1127 assert (_monitor_out == public_order.front());
1130 for (RouteList::iterator i = public_order.begin(); i != public_order.end(); ++i) {
1131 if (!(*i)->is_hidden()) {
1133 child->add_child_nocopy ((*i)->get_state());
1135 child->add_child_nocopy ((*i)->get_template());
1141 playlists->add_state (node, full_state);
1143 child = node->add_child ("RouteGroups");
1144 for (list<RouteGroup *>::iterator i = _route_groups.begin(); i != _route_groups.end(); ++i) {
1145 child->add_child_nocopy ((*i)->get_state());
1149 child = node->add_child ("Click");
1150 child->add_child_nocopy (_click_io->state (full_state));
1154 child = node->add_child ("NamedSelections");
1155 for (NamedSelectionList::iterator i = named_selections.begin(); i != named_selections.end(); ++i) {
1157 child->add_child_nocopy ((*i)->get_state());
1162 node->add_child_nocopy (_tempo_map->get_state());
1164 node->add_child_nocopy (get_control_protocol_state());
1167 node->add_child_copy (*_extra_xml);
1174 Session::get_control_protocol_state ()
1176 ControlProtocolManager& cpm (ControlProtocolManager::instance());
1177 return cpm.get_state();
1181 Session::set_state (const XMLNode& node, int version)
1185 const XMLProperty* prop;
1188 _state_of_the_state = StateOfTheState (_state_of_the_state|CannotSave);
1190 if (node.name() != X_("Session")){
1191 fatal << _("programming error: Session: incorrect XML node sent to set_state()") << endmsg;
1195 if ((prop = node.property ("version")) != 0) {
1196 version = atoi (prop->value ()) * 1000;
1199 if ((prop = node.property ("name")) != 0) {
1200 _name = prop->value ();
1203 if ((prop = node.property (X_("sample-rate"))) != 0) {
1205 _nominal_frame_rate = atoi (prop->value());
1207 if (_nominal_frame_rate != _current_frame_rate) {
1208 boost::optional<int> r = AskAboutSampleRateMismatch (_nominal_frame_rate, _current_frame_rate);
1209 if (r.get_value_or (0)) {
1215 setup_raid_path(_session_dir->root_path().to_string());
1217 if ((prop = node.property (X_("id-counter"))) != 0) {
1219 sscanf (prop->value().c_str(), "%" PRIu64, &x);
1220 ID::init_counter (x);
1222 /* old sessions used a timebased counter, so fake
1223 the startup ID counter based on a standard
1228 ID::init_counter (now);
1231 if ((prop = node.property (X_("event-counter"))) != 0) {
1232 Evoral::init_event_id_counter (atoi (prop->value()));
1235 IO::disable_connecting ();
1237 /* Object loading order:
1242 MIDI Control // relies on data from Options/Config
1255 if ((child = find_named_node (node, "Extra")) != 0) {
1256 _extra_xml = new XMLNode (*child);
1259 if (((child = find_named_node (node, "Options")) != 0)) { /* old style */
1260 load_options (*child);
1261 } else if ((child = find_named_node (node, "Config")) != 0) { /* new style */
1262 load_options (*child);
1264 error << _("Session: XML state has no options section") << endmsg;
1267 if (version >= 3000) {
1268 if ((child = find_named_node (node, "Metadata")) == 0) {
1269 warning << _("Session: XML state has no metadata section") << endmsg;
1270 } else if (_metadata->set_state (*child, version)) {
1275 if ((child = find_named_node (node, "Locations")) == 0) {
1276 error << _("Session: XML state has no locations section") << endmsg;
1278 } else if (_locations->set_state (*child, version)) {
1284 if ((location = _locations->auto_loop_location()) != 0) {
1285 set_auto_loop_location (location);
1288 if ((location = _locations->auto_punch_location()) != 0) {
1289 set_auto_punch_location (location);
1292 if ((location = _locations->session_range_location()) != 0) {
1293 delete _session_range_location;
1294 _session_range_location = location;
1297 if (_session_range_location) {
1298 AudioFileSource::set_header_position_offset (_session_range_location->start());
1301 if ((child = find_named_node (node, "Sources")) == 0) {
1302 error << _("Session: XML state has no sources section") << endmsg;
1304 } else if (load_sources (*child)) {
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, "NamedSelections")) != 0) {
1329 if (load_named_selections (*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 ((child = find_named_node (node, "TempoMap")) == 0) {
1347 error << _("Session: XML state has no Tempo Map section") << endmsg;
1349 } else if (_tempo_map->set_state (*child, version)) {
1353 if (version < 3000) {
1354 if ((child = find_named_node (node, X_("DiskStreams"))) == 0) {
1355 error << _("Session: XML state has no diskstreams section") << endmsg;
1357 } else if (load_diskstreams_2X (*child, version)) {
1362 if ((child = find_named_node (node, "Routes")) == 0) {
1363 error << _("Session: XML state has no routes section") << endmsg;
1365 } else if (load_routes (*child, version)) {
1369 /* our diskstreams list is no longer needed as they are now all owned by their Route */
1370 _diskstreams_2X.clear ();
1372 if (version >= 3000) {
1374 if ((child = find_named_node (node, "RouteGroups")) == 0) {
1375 error << _("Session: XML state has no route groups section") << endmsg;
1377 } else if (load_route_groups (*child, version)) {
1381 } else if (version < 3000) {
1383 if ((child = find_named_node (node, "EditGroups")) == 0) {
1384 error << _("Session: XML state has no edit groups section") << endmsg;
1386 } else if (load_route_groups (*child, version)) {
1390 if ((child = find_named_node (node, "MixGroups")) == 0) {
1391 error << _("Session: XML state has no mix groups section") << endmsg;
1393 } else if (load_route_groups (*child, version)) {
1398 if ((child = find_named_node (node, "Click")) == 0) {
1399 warning << _("Session: XML state has no click section") << endmsg;
1400 } else if (_click_io) {
1401 _click_io->set_state (*child, version);
1404 if ((child = find_named_node (node, "ControlProtocols")) != 0) {
1405 ControlProtocolManager::instance().set_protocol_states (*child);
1408 /* here beginneth the second phase ... */
1410 StateReady (); /* EMIT SIGNAL */
1419 Session::load_routes (const XMLNode& node, int version)
1422 XMLNodeConstIterator niter;
1423 RouteList new_routes;
1425 nlist = node.children();
1429 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1431 boost::shared_ptr<Route> route;
1432 if (version < 3000) {
1433 route = XMLRouteFactory_2X (**niter, version);
1435 route = XMLRouteFactory (**niter, version);
1439 error << _("Session: cannot create Route from XML description.") << endmsg;
1443 BootMessage (string_compose (_("Loaded track/bus %1"), route->name()));
1445 new_routes.push_back (route);
1448 add_routes (new_routes, false);
1453 boost::shared_ptr<Route>
1454 Session::XMLRouteFactory (const XMLNode& node, int version)
1456 boost::shared_ptr<Route> ret;
1458 if (node.name() != "Route") {
1462 XMLNode* ds_child = find_named_node (node, X_("Diskstream"));
1464 DataType type = DataType::AUDIO;
1465 const XMLProperty* prop = node.property("default-type");
1468 type = DataType (prop->value());
1471 assert (type != DataType::NIL);
1477 if (type == DataType::AUDIO) {
1478 track = new AudioTrack (*this, X_("toBeResetFroXML"));
1481 track = new MidiTrack (*this, X_("toBeResetFroXML"));
1484 if (track->init()) {
1489 if (track->set_state (node, version)) {
1494 boost_debug_shared_ptr_mark_interesting (track, "Track");
1498 Route* rt = new Route (*this, X_("toBeResetFroXML"));
1500 if (rt->init () == 0 && rt->set_state (node, version) == 0) {
1501 boost_debug_shared_ptr_mark_interesting (rt, "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> ();
1548 if (type == DataType::AUDIO) {
1549 track = new AudioTrack (*this, X_("toBeResetFroXML"));
1552 track = new MidiTrack (*this, X_("toBeResetFroXML"));
1555 if (track->init()) {
1560 if (track->set_state (node, version)) {
1565 track->set_diskstream (*i);
1567 boost_debug_shared_ptr_mark_interesting (track, "Track");
1571 Route* rt = new Route (*this, X_("toBeResetFroXML"));
1573 if (rt->init () == 0 && rt->set_state (node, version) == 0) {
1574 boost_debug_shared_ptr_mark_interesting (rt, "Route");
1585 Session::load_regions (const XMLNode& node)
1588 XMLNodeConstIterator niter;
1589 boost::shared_ptr<Region> region;
1591 nlist = node.children();
1595 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1596 if ((region = XMLRegionFactory (**niter, false)) == 0) {
1597 error << _("Session: cannot create Region from XML description.");
1598 const XMLProperty *name = (**niter).property("name");
1601 error << " " << string_compose (_("Can not load state for region '%1'"), name->value());
1611 boost::shared_ptr<Region>
1612 Session::XMLRegionFactory (const XMLNode& node, bool full)
1614 const XMLProperty* type = node.property("type");
1618 if (!type || type->value() == "audio") {
1619 return boost::shared_ptr<Region>(XMLAudioRegionFactory (node, full));
1620 } else if (type->value() == "midi") {
1621 return boost::shared_ptr<Region>(XMLMidiRegionFactory (node, full));
1624 } catch (failed_constructor& err) {
1625 return boost::shared_ptr<Region> ();
1628 return boost::shared_ptr<Region> ();
1631 boost::shared_ptr<AudioRegion>
1632 Session::XMLAudioRegionFactory (const XMLNode& node, bool /*full*/)
1634 const XMLProperty* prop;
1635 boost::shared_ptr<Source> source;
1636 boost::shared_ptr<AudioSource> as;
1638 SourceList master_sources;
1639 uint32_t nchans = 1;
1642 if (node.name() != X_("Region")) {
1643 return boost::shared_ptr<AudioRegion>();
1646 if ((prop = node.property (X_("channels"))) != 0) {
1647 nchans = atoi (prop->value().c_str());
1650 if ((prop = node.property ("name")) == 0) {
1651 cerr << "no name for this region\n";
1655 if ((prop = node.property (X_("source-0"))) == 0) {
1656 if ((prop = node.property ("source")) == 0) {
1657 error << _("Session: XMLNode describing a AudioRegion is incomplete (no source)") << endmsg;
1658 return boost::shared_ptr<AudioRegion>();
1662 PBD::ID s_id (prop->value());
1664 if ((source = source_by_id (s_id)) == 0) {
1665 error << string_compose(_("Session: XMLNode describing a AudioRegion references an unknown source id =%1"), s_id) << endmsg;
1666 return boost::shared_ptr<AudioRegion>();
1669 as = boost::dynamic_pointer_cast<AudioSource>(source);
1671 error << string_compose(_("Session: XMLNode describing a AudioRegion references a non-audio source id =%1"), s_id) << endmsg;
1672 return boost::shared_ptr<AudioRegion>();
1675 sources.push_back (as);
1677 /* pickup other channels */
1679 for (uint32_t n=1; n < nchans; ++n) {
1680 snprintf (buf, sizeof(buf), X_("source-%d"), n);
1681 if ((prop = node.property (buf)) != 0) {
1683 PBD::ID id2 (prop->value());
1685 if ((source = source_by_id (id2)) == 0) {
1686 error << string_compose(_("Session: XMLNode describing a AudioRegion references an unknown source id =%1"), id2) << endmsg;
1687 return boost::shared_ptr<AudioRegion>();
1690 as = boost::dynamic_pointer_cast<AudioSource>(source);
1692 error << string_compose(_("Session: XMLNode describing a AudioRegion references a non-audio source id =%1"), id2) << endmsg;
1693 return boost::shared_ptr<AudioRegion>();
1695 sources.push_back (as);
1699 for (uint32_t n = 0; n < nchans; ++n) {
1700 snprintf (buf, sizeof(buf), X_("master-source-%d"), n);
1701 if ((prop = node.property (buf)) != 0) {
1703 PBD::ID id2 (prop->value());
1705 if ((source = source_by_id (id2)) == 0) {
1706 error << string_compose(_("Session: XMLNode describing a AudioRegion references an unknown source id =%1"), id2) << endmsg;
1707 return boost::shared_ptr<AudioRegion>();
1710 as = boost::dynamic_pointer_cast<AudioSource>(source);
1712 error << string_compose(_("Session: XMLNode describing a AudioRegion references a non-audio source id =%1"), id2) << endmsg;
1713 return boost::shared_ptr<AudioRegion>();
1715 master_sources.push_back (as);
1720 boost::shared_ptr<AudioRegion> region (boost::dynamic_pointer_cast<AudioRegion> (RegionFactory::create (sources, node)));
1722 /* a final detail: this is the one and only place that we know how long missing files are */
1724 if (region->whole_file()) {
1725 for (SourceList::iterator sx = sources.begin(); sx != sources.end(); ++sx) {
1726 boost::shared_ptr<SilentFileSource> sfp = boost::dynamic_pointer_cast<SilentFileSource> (*sx);
1728 sfp->set_length (region->length());
1733 if (!master_sources.empty()) {
1734 if (master_sources.size() != nchans) {
1735 error << _("Session: XMLNode describing an AudioRegion is missing some master sources; ignored") << endmsg;
1737 region->set_master_sources (master_sources);
1745 catch (failed_constructor& err) {
1746 return boost::shared_ptr<AudioRegion>();
1750 boost::shared_ptr<MidiRegion>
1751 Session::XMLMidiRegionFactory (const XMLNode& node, bool /*full*/)
1753 const XMLProperty* prop;
1754 boost::shared_ptr<Source> source;
1755 boost::shared_ptr<MidiSource> ms;
1758 if (node.name() != X_("Region")) {
1759 return boost::shared_ptr<MidiRegion>();
1762 if ((prop = node.property ("name")) == 0) {
1763 cerr << "no name for this region\n";
1767 if ((prop = node.property (X_("source-0"))) == 0) {
1768 if ((prop = node.property ("source")) == 0) {
1769 error << _("Session: XMLNode describing a MidiRegion is incomplete (no source)") << endmsg;
1770 return boost::shared_ptr<MidiRegion>();
1774 PBD::ID s_id (prop->value());
1776 if ((source = source_by_id (s_id)) == 0) {
1777 error << string_compose(_("Session: XMLNode describing a MidiRegion references an unknown source id =%1"), s_id) << endmsg;
1778 return boost::shared_ptr<MidiRegion>();
1781 ms = boost::dynamic_pointer_cast<MidiSource>(source);
1783 error << string_compose(_("Session: XMLNode describing a MidiRegion references a non-midi source id =%1"), s_id) << endmsg;
1784 return boost::shared_ptr<MidiRegion>();
1787 sources.push_back (ms);
1790 boost::shared_ptr<MidiRegion> region (boost::dynamic_pointer_cast<MidiRegion> (RegionFactory::create (sources, node)));
1791 /* a final detail: this is the one and only place that we know how long missing files are */
1793 if (region->whole_file()) {
1794 for (SourceList::iterator sx = sources.begin(); sx != sources.end(); ++sx) {
1795 boost::shared_ptr<SilentFileSource> sfp = boost::dynamic_pointer_cast<SilentFileSource> (*sx);
1797 sfp->set_length (region->length());
1805 catch (failed_constructor& err) {
1806 return boost::shared_ptr<MidiRegion>();
1811 Session::get_sources_as_xml ()
1814 XMLNode* node = new XMLNode (X_("Sources"));
1815 Glib::Mutex::Lock lm (source_lock);
1817 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ++i) {
1818 node->add_child_nocopy (i->second->get_state());
1825 Session::path_from_region_name (DataType type, string name, string identifier)
1827 char buf[PATH_MAX+1];
1829 SessionDirectory sdir(get_best_session_directory_for_new_source());
1830 sys::path source_dir = ((type == DataType::AUDIO)
1831 ? sdir.sound_path() : sdir.midi_path());
1833 string ext = native_header_format_extension (config.get_native_file_header_format(), type);
1835 for (n = 0; n < 999999; ++n) {
1836 if (identifier.length()) {
1837 snprintf (buf, sizeof(buf), "%s%s%" PRIu32 "%s", name.c_str(),
1838 identifier.c_str(), n, ext.c_str());
1840 snprintf (buf, sizeof(buf), "%s-%" PRIu32 "%s", name.c_str(),
1844 sys::path source_path = source_dir / buf;
1846 if (!sys::exists (source_path)) {
1847 return source_path.to_string();
1851 error << string_compose (_("cannot create new file from region name \"%1\" with ident = \"%2\": too many existing files with similar names"),
1860 Session::load_sources (const XMLNode& node)
1863 XMLNodeConstIterator niter;
1864 boost::shared_ptr<Source> source;
1866 nlist = node.children();
1870 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1873 if ((source = XMLSourceFactory (**niter)) == 0) {
1874 error << _("Session: cannot create Source from XML description.") << endmsg;
1877 } catch (MissingSource& err) {
1881 if (!no_questions_about_missing_files) {
1882 user_choice = MissingFile (this, err.path, err.type).get_value_or (-1);
1887 switch (user_choice) {
1889 /* user added a new search location, so try again */
1894 /* user asked to quit the entire session load
1899 no_questions_about_missing_files = true;
1903 no_questions_about_missing_files = true;
1908 warning << _("A sound file is missing. It will be replaced by silence.") << endmsg;
1909 source = SourceFactory::createSilent (*this, **niter, max_framecnt, _current_frame_rate);
1918 boost::shared_ptr<Source>
1919 Session::XMLSourceFactory (const XMLNode& node)
1921 if (node.name() != "Source") {
1922 return boost::shared_ptr<Source>();
1926 /* note: do peak building in another thread when loading session state */
1927 return SourceFactory::create (*this, node, true);
1930 catch (failed_constructor& err) {
1931 error << string_compose (_("Found a sound file that cannot be used by %1. Talk to the progammers."), PROGRAM_NAME) << endmsg;
1932 return boost::shared_ptr<Source>();
1937 Session::save_template (string template_name)
1941 if (_state_of_the_state & CannotSave) {
1945 sys::path user_template_dir(user_template_directory());
1949 sys::create_directories (user_template_dir);
1951 catch(sys::filesystem_error& ex)
1953 error << string_compose(_("Could not create mix templates directory \"%1\" (%2)"),
1954 user_template_dir.to_string(), ex.what()) << endmsg;
1958 tree.set_root (&get_template());
1960 sys::path template_file_path(user_template_dir);
1961 template_file_path /= template_name + template_suffix;
1963 if (sys::exists (template_file_path))
1965 warning << string_compose(_("Template \"%1\" already exists - new version not created"),
1966 template_file_path.to_string()) << endmsg;
1970 if (!tree.write (template_file_path.to_string())) {
1971 error << _("mix template not saved") << endmsg;
1979 Session::rename_template (string old_name, string new_name)
1981 sys::path old_path (user_template_directory());
1982 old_path /= old_name + template_suffix;
1984 sys::path new_path(user_template_directory());
1985 new_path /= new_name + template_suffix;
1987 if (sys::exists (new_path)) {
1988 warning << string_compose(_("Template \"%1\" already exists - template not renamed"),
1989 new_path.to_string()) << endmsg;
1994 sys::rename (old_path, new_path);
2002 Session::delete_template (string name)
2004 sys::path path = user_template_directory();
2005 path /= name + template_suffix;
2016 Session::refresh_disk_space ()
2019 struct statfs statfsbuf;
2020 vector<space_and_path>::iterator i;
2021 Glib::Mutex::Lock lm (space_lock);
2024 /* get freespace on every FS that is part of the session path */
2026 _total_free_4k_blocks = 0;
2028 for (i = session_dirs.begin(); i != session_dirs.end(); ++i) {
2029 statfs ((*i).path.c_str(), &statfsbuf);
2031 scale = statfsbuf.f_bsize/4096.0;
2033 (*i).blocks = (uint32_t) floor (statfsbuf.f_bavail * scale);
2034 _total_free_4k_blocks += (*i).blocks;
2040 Session::get_best_session_directory_for_new_source ()
2042 vector<space_and_path>::iterator i;
2043 string result = _session_dir->root_path().to_string();
2045 /* handle common case without system calls */
2047 if (session_dirs.size() == 1) {
2051 /* OK, here's the algorithm we're following here:
2053 We want to select which directory to use for
2054 the next file source to be created. Ideally,
2055 we'd like to use a round-robin process so as to
2056 get maximum performance benefits from splitting
2057 the files across multiple disks.
2059 However, in situations without much diskspace, an
2060 RR approach may end up filling up a filesystem
2061 with new files while others still have space.
2062 Its therefore important to pay some attention to
2063 the freespace in the filesystem holding each
2064 directory as well. However, if we did that by
2065 itself, we'd keep creating new files in the file
2066 system with the most space until it was as full
2067 as all others, thus negating any performance
2068 benefits of this RAID-1 like approach.
2070 So, we use a user-configurable space threshold. If
2071 there are at least 2 filesystems with more than this
2072 much space available, we use RR selection between them.
2073 If not, then we pick the filesystem with the most space.
2075 This gets a good balance between the two
2079 refresh_disk_space ();
2081 int free_enough = 0;
2083 for (i = session_dirs.begin(); i != session_dirs.end(); ++i) {
2084 if ((*i).blocks * 4096 >= Config->get_disk_choice_space_threshold()) {
2089 if (free_enough >= 2) {
2090 /* use RR selection process, ensuring that the one
2094 i = last_rr_session_dir;
2097 if (++i == session_dirs.end()) {
2098 i = session_dirs.begin();
2101 if ((*i).blocks * 4096 >= Config->get_disk_choice_space_threshold()) {
2102 if (create_session_directory ((*i).path)) {
2104 last_rr_session_dir = i;
2109 } while (i != last_rr_session_dir);
2113 /* pick FS with the most freespace (and that
2114 seems to actually work ...)
2117 vector<space_and_path> sorted;
2118 space_and_path_ascending_cmp cmp;
2120 sorted = session_dirs;
2121 sort (sorted.begin(), sorted.end(), cmp);
2123 for (i = sorted.begin(); i != sorted.end(); ++i) {
2124 if (create_session_directory ((*i).path)) {
2126 last_rr_session_dir = i;
2136 Session::load_named_selections (const XMLNode& node)
2139 XMLNodeConstIterator niter;
2142 nlist = node.children();
2146 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2148 if ((ns = XMLNamedSelectionFactory (**niter)) == 0) {
2149 error << _("Session: cannot create Named Selection from XML description.") << endmsg;
2157 Session::XMLNamedSelectionFactory (const XMLNode& node)
2160 return new NamedSelection (*this, node);
2163 catch (failed_constructor& err) {
2169 Session::automation_dir () const
2171 return Glib::build_filename (_path, "automation");
2175 Session::analysis_dir () const
2177 return Glib::build_filename (_path, "analysis");
2181 Session::load_bundles (XMLNode const & node)
2183 XMLNodeList nlist = node.children();
2184 XMLNodeConstIterator niter;
2188 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2189 if ((*niter)->name() == "InputBundle") {
2190 add_bundle (boost::shared_ptr<UserBundle> (new UserBundle (**niter, true)));
2191 } else if ((*niter)->name() == "OutputBundle") {
2192 add_bundle (boost::shared_ptr<UserBundle> (new UserBundle (**niter, false)));
2194 error << string_compose(_("Unknown node \"%1\" found in Bundles list from state file"), (*niter)->name()) << endmsg;
2203 Session::load_route_groups (const XMLNode& node, int version)
2205 XMLNodeList nlist = node.children();
2206 XMLNodeConstIterator niter;
2210 if (version >= 3000) {
2212 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2213 if ((*niter)->name() == "RouteGroup") {
2214 RouteGroup* rg = new RouteGroup (*this, "");
2215 add_route_group (rg);
2216 rg->set_state (**niter, version);
2220 } else if (version < 3000) {
2222 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2223 if ((*niter)->name() == "EditGroup" || (*niter)->name() == "MixGroup") {
2224 RouteGroup* rg = new RouteGroup (*this, "");
2225 add_route_group (rg);
2226 rg->set_state (**niter, version);
2235 Session::auto_save()
2237 save_state (_current_snapshot_name);
2241 state_file_filter (const string &str, void */*arg*/)
2243 return (str.length() > strlen(statefile_suffix) &&
2244 str.find (statefile_suffix) == (str.length() - strlen (statefile_suffix)));
2248 bool operator()(const string* a, const string* b) {
2254 remove_end(string* state)
2256 string statename(*state);
2258 string::size_type start,end;
2259 if ((start = statename.find_last_of (G_DIR_SEPARATOR)) != string::npos) {
2260 statename = statename.substr (start+1);
2263 if ((end = statename.rfind(".ardour")) == string::npos) {
2264 end = statename.length();
2267 return new string(statename.substr (0, end));
2271 Session::possible_states (string path)
2273 PathScanner scanner;
2274 vector<string*>* states = scanner (path, state_file_filter, 0, false, false);
2276 transform(states->begin(), states->end(), states->begin(), remove_end);
2279 sort (states->begin(), states->end(), cmp);
2285 Session::possible_states () const
2287 return possible_states(_path);
2291 Session::add_route_group (RouteGroup* g)
2293 _route_groups.push_back (g);
2294 route_group_added (g); /* EMIT SIGNAL */
2296 g->MembershipChanged.connect_same_thread (*this, boost::bind (&Session::route_group_changed, this));
2297 g->PropertyChanged.connect_same_thread (*this, boost::bind (&Session::route_group_changed, this));
2303 Session::remove_route_group (RouteGroup& rg)
2305 list<RouteGroup*>::iterator i;
2307 if ((i = find (_route_groups.begin(), _route_groups.end(), &rg)) != _route_groups.end()) {
2308 _route_groups.erase (i);
2311 route_group_removed (); /* EMIT SIGNAL */
2317 Session::route_group_by_name (string name)
2319 list<RouteGroup *>::iterator i;
2321 for (i = _route_groups.begin(); i != _route_groups.end(); ++i) {
2322 if ((*i)->name() == name) {
2330 Session::all_route_group() const
2332 return *_all_route_group;
2336 Session::start_reversible_command (const string& name)
2338 UndoTransaction* trans = new UndoTransaction();
2339 trans->set_name(name);
2344 Session::finish_reversible_command (UndoTransaction& ut)
2347 gettimeofday(&now, 0);
2348 ut.set_timestamp(now);
2353 Session::add_commands (vector<Command*> const & cmds)
2355 for (vector<Command*>::const_iterator i = cmds.begin(); i != cmds.end(); ++i) {
2361 Session::begin_reversible_command(const string& name)
2363 UndoTransaction* trans = new UndoTransaction();
2364 trans->set_name(name);
2366 if (!_current_trans.empty()) {
2367 _current_trans.top()->add_command (trans);
2369 _current_trans.push(trans);
2374 Session::commit_reversible_command(Command *cmd)
2376 assert(!_current_trans.empty());
2380 _current_trans.top()->add_command(cmd);
2383 if (_current_trans.top()->empty()) {
2384 _current_trans.pop();
2388 gettimeofday(&now, 0);
2389 _current_trans.top()->set_timestamp(now);
2391 _history.add(_current_trans.top());
2392 _current_trans.pop();
2396 accept_all_non_peak_files (const string& path, void */*arg*/)
2398 if (!Glib::file_test (path, Glib::FILE_TEST_IS_REGULAR)) {
2402 return (path.length() > 5 && path.find (peakfile_suffix) != (path.length() - 5));
2406 accept_all_state_files (const string& path, void */*arg*/)
2408 return (path.length() > 7 && path.find (".ardour") == (path.length() - 7));
2412 Session::find_all_sources (string path, set<string>& result)
2417 if (!tree.read (path)) {
2421 if ((node = find_named_node (*tree.root(), "Sources")) == 0) {
2426 XMLNodeConstIterator niter;
2428 nlist = node->children();
2432 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2436 if ((prop = (*niter)->property (X_("type"))) == 0) {
2440 DataType type (prop->value());
2442 if ((prop = (*niter)->property (X_("name"))) == 0) {
2446 if (Glib::path_is_absolute (prop->value())) {
2447 /* external file, ignore */
2455 if (FileSource::find (*this, type, prop->value(), true, is_new, chan, found_path)) {
2456 result.insert (found_path);
2464 Session::find_all_sources_across_snapshots (set<string>& result, bool exclude_this_snapshot)
2466 PathScanner scanner;
2467 vector<string*>* state_files;
2469 string this_snapshot_path;
2475 if (ripped[ripped.length()-1] == G_DIR_SEPARATOR) {
2476 ripped = ripped.substr (0, ripped.length() - 1);
2479 state_files = scanner (ripped, accept_all_state_files, (void *) 0, false, true);
2481 if (state_files == 0) {
2486 this_snapshot_path = _path;
2487 this_snapshot_path += legalize_for_path (_current_snapshot_name);
2488 this_snapshot_path += statefile_suffix;
2490 for (vector<string*>::iterator i = state_files->begin(); i != state_files->end(); ++i) {
2492 if (exclude_this_snapshot && **i == this_snapshot_path) {
2496 if (find_all_sources (**i, result) < 0) {
2504 struct RegionCounter {
2505 typedef std::map<PBD::ID,boost::shared_ptr<AudioSource> > AudioSourceList;
2506 AudioSourceList::iterator iter;
2507 boost::shared_ptr<Region> region;
2510 RegionCounter() : count (0) {}
2514 Session::ask_about_playlist_deletion (boost::shared_ptr<Playlist> p)
2516 boost::optional<int> r = AskAboutPlaylistDeletion (p);
2517 return r.get_value_or (1);
2521 Session::cleanup_sources (CleanupReport& rep)
2523 // FIXME: needs adaptation to midi
2525 vector<boost::shared_ptr<Source> > dead_sources;
2526 PathScanner scanner;
2528 vector<space_and_path>::iterator i;
2529 vector<space_and_path>::iterator nexti;
2530 vector<string*>* soundfiles;
2531 vector<string> unused;
2532 set<string> all_sources;
2537 _state_of_the_state = (StateOfTheState) (_state_of_the_state | InCleanup);
2539 /* step 1: consider deleting all unused playlists */
2541 if (playlists->maybe_delete_unused (boost::bind (Session::ask_about_playlist_deletion, _1))) {
2546 /* step 2: find all un-used sources */
2551 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ) {
2553 SourceMap::iterator tmp;
2558 /* do not bother with files that are zero size, otherwise we remove the current "nascent"
2562 if (!i->second->used() && (i->second->length(i->second->timeline_position() > 0))) {
2563 dead_sources.push_back (i->second);
2564 i->second->drop_references ();
2570 /* build a list of all the possible sound directories for the session */
2572 for (i = session_dirs.begin(); i != session_dirs.end(); ) {
2577 SessionDirectory sdir ((*i).path);
2578 sound_path += sdir.sound_path().to_string();
2580 if (nexti != session_dirs.end()) {
2587 /* now do the same thing for the files that ended up in the sounds dir(s)
2588 but are not referenced as sources in any snapshot.
2591 soundfiles = scanner (sound_path, accept_all_non_peak_files, (void *) 0, false, true);
2593 if (soundfiles == 0) {
2597 /* find all sources, but don't use this snapshot because the
2598 state file on disk still references sources we may have already
2602 find_all_sources_across_snapshots (all_sources, true);
2604 /* add our current source list
2607 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ++i) {
2608 boost::shared_ptr<FileSource> fs;
2610 if ((fs = boost::dynamic_pointer_cast<FileSource> (i->second)) != 0) {
2611 all_sources.insert (fs->path());
2615 char tmppath1[PATH_MAX+1];
2616 char tmppath2[PATH_MAX+1];
2618 for (vector<string*>::iterator x = soundfiles->begin(); x != soundfiles->end(); ++x) {
2623 for (set<string>::iterator i = all_sources.begin(); i != all_sources.end(); ++i) {
2625 if (realpath(spath.c_str(), tmppath1) == 0) {
2626 error << string_compose (_("Cannot expand path %1 (%2)"),
2627 spath, strerror (errno)) << endmsg;
2631 if (realpath((*i).c_str(), tmppath2) == 0) {
2632 error << string_compose (_("Cannot expand path %1 (%2)"),
2633 (*i), strerror (errno)) << endmsg;
2637 if (strcmp(tmppath1, tmppath2) == 0) {
2644 unused.push_back (spath);
2648 /* now try to move all unused files into the "dead_sounds" directory(ies) */
2650 for (vector<string>::iterator x = unused.begin(); x != unused.end(); ++x) {
2651 struct stat statbuf;
2653 rep.paths.push_back (*x);
2654 if (stat ((*x).c_str(), &statbuf) == 0) {
2655 rep.space += statbuf.st_size;
2660 /* don't move the file across filesystems, just
2661 stick it in the `dead_sound_dir_name' directory
2662 on whichever filesystem it was already on.
2665 if ((*x).find ("/sounds/") != string::npos) {
2667 /* old school, go up 1 level */
2669 newpath = Glib::path_get_dirname (*x); // "sounds"
2670 newpath = Glib::path_get_dirname (newpath); // "session-name"
2674 /* new school, go up 4 levels */
2676 newpath = Glib::path_get_dirname (*x); // "audiofiles"
2677 newpath = Glib::path_get_dirname (newpath); // "session-name"
2678 newpath = Glib::path_get_dirname (newpath); // "interchange"
2679 newpath = Glib::path_get_dirname (newpath); // "session-dir"
2682 newpath = Glib::build_filename (newpath, dead_sound_dir_name);
2684 if (g_mkdir_with_parents (newpath.c_str(), 0755) < 0) {
2685 error << string_compose(_("Session: cannot create session peakfile folder \"%1\" (%2)"), newpath, strerror (errno)) << endmsg;
2689 newpath = Glib::build_filename (newpath, Glib::path_get_basename ((*x)));
2691 if (Glib::file_test (newpath, Glib::FILE_TEST_EXISTS)) {
2693 /* the new path already exists, try versioning */
2695 char buf[PATH_MAX+1];
2699 snprintf (buf, sizeof (buf), "%s.%d", newpath.c_str(), version);
2702 while (access (newpath_v.c_str(), F_OK) == 0 && version < 999) {
2703 snprintf (buf, sizeof (buf), "%s.%d", newpath.c_str(), ++version);
2707 if (version == 999) {
2708 error << string_compose (_("there are already 1000 files with names like %1; versioning discontinued"),
2712 newpath = newpath_v;
2717 /* it doesn't exist, or we can't read it or something */
2721 if (::rename ((*x).c_str(), newpath.c_str()) != 0) {
2722 error << string_compose (_("cannot rename audio file source from %1 to %2 (%3)"),
2723 (*x), newpath, strerror (errno))
2728 /* see if there an easy to find peakfile for this file, and remove it.
2731 string peakpath = (*x).substr (0, (*x).find_last_of ('.'));
2732 peakpath += peakfile_suffix;
2734 if (access (peakpath.c_str(), W_OK) == 0) {
2735 if (::unlink (peakpath.c_str()) != 0) {
2736 error << string_compose (_("cannot remove peakfile %1 for %2 (%3)"),
2737 peakpath, _path, strerror (errno))
2739 /* try to back out */
2740 rename (newpath.c_str(), _path.c_str());
2748 /* dump the history list */
2752 /* save state so we don't end up a session file
2753 referring to non-existent sources.
2759 _state_of_the_state = (StateOfTheState) (_state_of_the_state & ~InCleanup);
2765 Session::cleanup_trash_sources (CleanupReport& rep)
2767 // FIXME: needs adaptation for MIDI
2769 vector<space_and_path>::iterator i;
2770 string dead_sound_dir;
2775 for (i = session_dirs.begin(); i != session_dirs.end(); ++i) {
2777 dead_sound_dir = (*i).path;
2778 dead_sound_dir += dead_sound_dir_name;
2780 clear_directory (dead_sound_dir, &rep.space, &rep.paths);
2787 Session::cleanup_stubfiles ()
2789 vector<space_and_path>::iterator i;
2791 for (i = session_dirs.begin(); i != session_dirs.end(); ++i) {
2794 string lname = legalize_for_path (_name);
2798 /* XXX this is a hack caused by semantic conflicts
2799 between space_and_path and the SessionDirectory concept.
2802 v.push_back ((*i).path);
2803 v.push_back ("interchange");
2804 v.push_back (lname);
2805 v.push_back ("audiofiles");
2806 v.push_back (stub_dir_name);
2808 dir = Glib::build_filename (v);
2810 clear_directory (dir);
2813 v.push_back ((*i).path);
2814 v.push_back ("interchange");
2815 v.push_back (lname);
2816 v.push_back ("midifiles");
2817 v.push_back (stub_dir_name);
2819 dir = Glib::build_filename (v);
2821 clear_directory (dir);
2826 Session::set_dirty ()
2828 bool was_dirty = dirty();
2830 _state_of_the_state = StateOfTheState (_state_of_the_state | Dirty);
2834 DirtyChanged(); /* EMIT SIGNAL */
2840 Session::set_clean ()
2842 bool was_dirty = dirty();
2844 _state_of_the_state = Clean;
2848 DirtyChanged(); /* EMIT SIGNAL */
2853 Session::set_deletion_in_progress ()
2855 _state_of_the_state = StateOfTheState (_state_of_the_state | Deletion);
2859 Session::clear_deletion_in_progress ()
2861 _state_of_the_state = StateOfTheState (_state_of_the_state & (~Deletion));
2865 Session::add_controllable (boost::shared_ptr<Controllable> c)
2867 /* this adds a controllable to the list managed by the Session.
2868 this is a subset of those managed by the Controllable class
2869 itself, and represents the only ones whose state will be saved
2870 as part of the session.
2873 Glib::Mutex::Lock lm (controllables_lock);
2874 controllables.insert (c);
2877 struct null_deleter { void operator()(void const *) const {} };
2880 Session::remove_controllable (Controllable* c)
2882 if (_state_of_the_state | Deletion) {
2886 Glib::Mutex::Lock lm (controllables_lock);
2888 Controllables::iterator x = controllables.find (boost::shared_ptr<Controllable>(c, null_deleter()));
2890 if (x != controllables.end()) {
2891 controllables.erase (x);
2895 boost::shared_ptr<Controllable>
2896 Session::controllable_by_id (const PBD::ID& id)
2898 Glib::Mutex::Lock lm (controllables_lock);
2900 for (Controllables::iterator i = controllables.begin(); i != controllables.end(); ++i) {
2901 if ((*i)->id() == id) {
2906 return boost::shared_ptr<Controllable>();
2909 boost::shared_ptr<Controllable>
2910 Session::controllable_by_descriptor (const ControllableDescriptor& desc)
2912 boost::shared_ptr<Controllable> c;
2913 boost::shared_ptr<Route> r;
2915 switch (desc.top_level_type()) {
2916 case ControllableDescriptor::NamedRoute:
2918 std::string str = desc.top_level_name();
2919 if (str == "master") {
2921 } else if (str == "control" || str == "listen") {
2924 r = route_by_name (desc.top_level_name());
2929 case ControllableDescriptor::RemoteControlID:
2930 r = route_by_remote_id (desc.rid());
2938 switch (desc.subtype()) {
2939 case ControllableDescriptor::Gain:
2940 c = r->gain_control ();
2943 case ControllableDescriptor::Solo:
2944 c = r->solo_control();
2947 case ControllableDescriptor::Mute:
2948 c = r->mute_control();
2951 case ControllableDescriptor::Recenable:
2953 boost::shared_ptr<Track> t = boost::dynamic_pointer_cast<Track>(r);
2956 c = t->rec_enable_control ();
2961 case ControllableDescriptor::Pan:
2962 /* XXX pan control */
2965 case ControllableDescriptor::Balance:
2966 /* XXX simple pan control */
2969 case ControllableDescriptor::PluginParameter:
2971 uint32_t plugin = desc.target (0);
2972 uint32_t parameter_index = desc.target (1);
2974 /* revert to zero based counting */
2980 if (parameter_index > 0) {
2984 boost::shared_ptr<Processor> p = r->nth_plugin (plugin);
2987 c = boost::dynamic_pointer_cast<ARDOUR::AutomationControl>(
2988 p->control(Evoral::Parameter(PluginAutomation, 0, parameter_index)));
2993 case ControllableDescriptor::SendGain:
2995 uint32_t send = desc.target (0);
2997 /* revert to zero-based counting */
3003 boost::shared_ptr<Processor> p = r->nth_send (send);
3006 boost::shared_ptr<Send> s = boost::dynamic_pointer_cast<Send>(p);
3007 boost::shared_ptr<Amp> a = s->amp();
3010 c = s->amp()->gain_control();
3017 /* relax and return a null pointer */
3025 Session::add_instant_xml (XMLNode& node, bool write_to_config)
3028 Stateful::add_instant_xml (node, _path);
3031 if (write_to_config) {
3032 Config->add_instant_xml (node);
3037 Session::instant_xml (const string& node_name)
3039 return Stateful::instant_xml (node_name, _path);
3043 Session::save_history (string snapshot_name)
3051 if (snapshot_name.empty()) {
3052 snapshot_name = _current_snapshot_name;
3055 const string history_filename = legalize_for_path (snapshot_name) + history_suffix;
3056 const string backup_filename = history_filename + backup_suffix;
3057 const sys::path xml_path = _session_dir->root_path() / history_filename;
3058 const sys::path backup_path = _session_dir->root_path() / backup_filename;
3060 if (sys::exists (xml_path)) {
3063 sys::rename (xml_path, backup_path);
3065 catch (const sys::filesystem_error& err)
3067 error << _("could not backup old history file, current history not saved") << endmsg;
3072 if (!Config->get_save_history() || Config->get_saved_history_depth() < 0) {
3076 tree.set_root (&_history.get_state (Config->get_saved_history_depth()));
3078 if (!tree.write (xml_path.to_string()))
3080 error << string_compose (_("history could not be saved to %1"), xml_path.to_string()) << endmsg;
3084 sys::remove (xml_path);
3085 sys::rename (backup_path, xml_path);
3087 catch (const sys::filesystem_error& err)
3089 error << string_compose (_("could not restore history file from backup %1 (%2)"),
3090 backup_path.to_string(), err.what()) << endmsg;
3100 Session::restore_history (string snapshot_name)
3104 if (snapshot_name.empty()) {
3105 snapshot_name = _current_snapshot_name;
3108 const string xml_filename = legalize_for_path (snapshot_name) + history_suffix;
3109 const sys::path xml_path = _session_dir->root_path() / xml_filename;
3111 info << "Loading history from " << xml_path.to_string() << endmsg;
3113 if (!sys::exists (xml_path)) {
3114 info << string_compose (_("%1: no history file \"%2\" for this session."),
3115 _name, xml_path.to_string()) << endmsg;
3119 if (!tree.read (xml_path.to_string())) {
3120 error << string_compose (_("Could not understand session history file \"%1\""),
3121 xml_path.to_string()) << endmsg;
3128 for (XMLNodeConstIterator it = tree.root()->children().begin(); it != tree.root()->children().end(); it++) {
3131 UndoTransaction* ut = new UndoTransaction ();
3134 ut->set_name(t->property("name")->value());
3135 stringstream ss(t->property("tv-sec")->value());
3137 ss.str(t->property("tv-usec")->value());
3139 ut->set_timestamp(tv);
3141 for (XMLNodeConstIterator child_it = t->children().begin();
3142 child_it != t->children().end(); child_it++)
3144 XMLNode *n = *child_it;
3147 if (n->name() == "MementoCommand" ||
3148 n->name() == "MementoUndoCommand" ||
3149 n->name() == "MementoRedoCommand") {
3151 if ((c = memento_command_factory(n))) {
3155 } else if (n->name() == "DiffCommand") {
3156 PBD::ID id(n->property("midi-source")->value());
3157 boost::shared_ptr<MidiSource> midi_source =
3158 boost::dynamic_pointer_cast<MidiSource, Source>(source_by_id(id));
3160 ut->add_command(new MidiModel::DiffCommand(midi_source->model(), *n));
3162 error << _("Failed to downcast MidiSource for DiffCommand") << endmsg;
3165 } else if (n->name() == "StatefulDiffCommand") {
3166 if ((c = stateful_diff_command_factory (n))) {
3167 ut->add_command (c);
3170 error << string_compose(_("Couldn't figure out how to make a Command out of a %1 XMLNode."), n->name()) << endmsg;
3181 Session::config_changed (std::string p, bool ours)
3187 if (p == "seamless-loop") {
3189 } else if (p == "rf-speed") {
3191 } else if (p == "auto-loop") {
3193 } else if (p == "auto-input") {
3195 if (Config->get_monitoring_model() == HardwareMonitoring && transport_rolling()) {
3196 /* auto-input only makes a difference if we're rolling */
3198 boost::shared_ptr<RouteList> rl = routes.reader ();
3199 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
3200 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
3201 if (tr && tr->record_enabled ()) {
3202 tr->monitor_input (!config.get_auto_input());
3207 } else if (p == "punch-in") {
3211 if ((location = _locations->auto_punch_location()) != 0) {
3213 if (config.get_punch_in ()) {
3214 replace_event (SessionEvent::PunchIn, location->start());
3216 remove_event (location->start(), SessionEvent::PunchIn);
3220 } else if (p == "punch-out") {
3224 if ((location = _locations->auto_punch_location()) != 0) {
3226 if (config.get_punch_out()) {
3227 replace_event (SessionEvent::PunchOut, location->end());
3229 clear_events (SessionEvent::PunchOut);
3233 } else if (p == "edit-mode") {
3235 Glib::Mutex::Lock lm (playlists->lock);
3237 for (SessionPlaylists::List::iterator i = playlists->playlists.begin(); i != playlists->playlists.end(); ++i) {
3238 (*i)->set_edit_mode (Config->get_edit_mode ());
3241 } else if (p == "use-video-sync") {
3243 waiting_for_sync_offset = config.get_use_video_sync();
3245 } else if (p == "mmc-control") {
3247 //poke_midi_thread ();
3249 } else if (p == "mmc-device-id" || p == "mmc-receive-id") {
3251 MIDI::Manager::instance()->mmc()->set_receive_device_id (Config->get_mmc_receive_device_id());
3253 } else if (p == "mmc-send-id") {
3255 MIDI::Manager::instance()->mmc()->set_send_device_id (Config->get_mmc_send_device_id());
3257 } else if (p == "midi-control") {
3259 //poke_midi_thread ();
3261 } else if (p == "raid-path") {
3263 setup_raid_path (config.get_raid_path());
3265 } else if (p == "timecode-format") {
3269 } else if (p == "video-pullup") {
3273 } else if (p == "seamless-loop") {
3275 if (play_loop && transport_rolling()) {
3276 // to reset diskstreams etc
3277 request_play_loop (true);
3280 } else if (p == "rf-speed") {
3282 cumulative_rf_motion = 0;
3285 } else if (p == "click-sound") {
3287 setup_click_sounds (1);
3289 } else if (p == "click-emphasis-sound") {
3291 setup_click_sounds (-1);
3293 } else if (p == "clicking") {
3295 if (Config->get_clicking()) {
3296 if (_click_io && click_data) { // don't require emphasis data
3303 } else if (p == "send-mtc") {
3305 session_send_mtc = Config->get_send_mtc();
3306 if (session_send_mtc) {
3307 /* mark us ready to send */
3308 next_quarter_frame_to_send = 0;
3311 } else if (p == "send-mmc") {
3313 MIDI::Manager::instance()->mmc()->enable_send (Config->get_send_mmc ());
3315 } else if (p == "midi-feedback") {
3317 session_midi_feedback = Config->get_midi_feedback();
3319 } else if (p == "jack-time-master") {
3321 engine().reset_timebase ();
3323 } else if (p == "native-file-header-format") {
3325 if (!first_file_header_format_reset) {
3326 reset_native_file_format ();
3329 first_file_header_format_reset = false;
3331 } else if (p == "native-file-data-format") {
3333 if (!first_file_data_format_reset) {
3334 reset_native_file_format ();
3337 first_file_data_format_reset = false;
3339 } else if (p == "external-sync") {
3340 if (!config.get_external_sync()) {
3341 drop_sync_source ();
3343 switch_to_sync_source (config.get_sync_source());
3345 } else if (p == "remote-model") {
3346 set_remote_control_ids ();
3347 } else if (p == "denormal-model") {
3349 } else if (p == "history-depth") {
3350 set_history_depth (Config->get_history_depth());
3351 } else if (p == "sync-all-route-ordering") {
3352 sync_order_keys ("session");
3353 } else if (p == "initial-program-change") {
3355 if (MIDI::Manager::instance()->mmc()->output_port() && Config->get_initial_program_change() >= 0) {
3358 buf[0] = MIDI::program; // channel zero by default
3359 buf[1] = (Config->get_initial_program_change() & 0x7f);
3361 MIDI::Manager::instance()->mmc()->output_port()->midimsg (buf, sizeof (buf), 0);
3363 } else if (p == "solo-mute-override") {
3364 // catch_up_on_solo_mute_override ();
3365 } else if (p == "listen-position") {
3366 listen_position_changed ();
3367 } else if (p == "solo-control-is-listen-control") {
3368 solo_control_mode_changed ();
3376 Session::set_history_depth (uint32_t d)
3378 _history.set_depth (d);
3382 Session::load_diskstreams_2X (XMLNode const & node, int)
3385 XMLNodeConstIterator citer;
3387 clist = node.children();
3389 for (citer = clist.begin(); citer != clist.end(); ++citer) {
3392 /* diskstreams added automatically by DiskstreamCreated handler */
3393 if ((*citer)->name() == "AudioDiskstream" || (*citer)->name() == "DiskStream") {
3394 boost::shared_ptr<AudioDiskstream> dsp (new AudioDiskstream (*this, **citer));
3395 _diskstreams_2X.push_back (dsp);
3397 error << _("Session: unknown diskstream type in XML") << endmsg;
3401 catch (failed_constructor& err) {
3402 error << _("Session: could not load diskstream via XML state") << endmsg;
3410 /** Connect things to the MMC object */
3412 Session::setup_midi_machine_control ()
3414 MIDI::MachineControl* mmc = MIDI::Manager::instance()->mmc ();
3416 mmc->Play.connect_same_thread (*this, boost::bind (&Session::mmc_deferred_play, this, _1));
3417 mmc->DeferredPlay.connect_same_thread (*this, boost::bind (&Session::mmc_deferred_play, this, _1));
3418 mmc->Stop.connect_same_thread (*this, boost::bind (&Session::mmc_stop, this, _1));
3419 mmc->FastForward.connect_same_thread (*this, boost::bind (&Session::mmc_fast_forward, this, _1));
3420 mmc->Rewind.connect_same_thread (*this, boost::bind (&Session::mmc_rewind, this, _1));
3421 mmc->Pause.connect_same_thread (*this, boost::bind (&Session::mmc_pause, this, _1));
3422 mmc->RecordPause.connect_same_thread (*this, boost::bind (&Session::mmc_record_pause, this, _1));
3423 mmc->RecordStrobe.connect_same_thread (*this, boost::bind (&Session::mmc_record_strobe, this, _1));
3424 mmc->RecordExit.connect_same_thread (*this, boost::bind (&Session::mmc_record_exit, this, _1));
3425 mmc->Locate.connect_same_thread (*this, boost::bind (&Session::mmc_locate, this, _1, _2));
3426 mmc->Step.connect_same_thread (*this, boost::bind (&Session::mmc_step, this, _1, _2));
3427 mmc->Shuttle.connect_same_thread (*this, boost::bind (&Session::mmc_shuttle, this, _1, _2, _3));
3428 mmc->TrackRecordStatusChange.connect_same_thread (*this, boost::bind (&Session::mmc_record_enable, this, _1, _2, _3));
3430 /* also handle MIDI SPP because its so common */
3432 mmc->SPPStart.connect_same_thread (*this, boost::bind (&Session::spp_start, this, _1, _2));
3433 mmc->SPPContinue.connect_same_thread (*this, boost::bind (&Session::spp_continue, this, _1, _2));
3434 mmc->SPPStop.connect_same_thread (*this, boost::bind (&Session::spp_stop, this, _1, _2));