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 */
49 #include <sys/param.h>
50 #include <sys/mount.h>
54 #include <glibmm/thread.h>
56 #include "midi++/mmc.h"
57 #include "midi++/port.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"
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/buffer.h"
78 #include "ardour/butler.h"
79 #include "ardour/configuration.h"
80 #include "ardour/control_protocol_manager.h"
81 #include "ardour/crossfade.h"
82 #include "ardour/cycle_timer.h"
83 #include "ardour/directory_names.h"
84 #include "ardour/filename_extensions.h"
85 #include "ardour/io_processor.h"
86 #include "ardour/location.h"
87 #include "ardour/midi_diskstream.h"
88 #include "ardour/midi_patch_manager.h"
89 #include "ardour/midi_playlist.h"
90 #include "ardour/midi_region.h"
91 #include "ardour/midi_source.h"
92 #include "ardour/midi_track.h"
93 #include "ardour/named_selection.h"
94 #include "ardour/processor.h"
95 #include "ardour/region_factory.h"
96 #include "ardour/route_group.h"
97 #include "ardour/send.h"
98 #include "ardour/session.h"
99 #include "ardour/session_directory.h"
100 #include "ardour/session_metadata.h"
101 #include "ardour/session_state_utils.h"
102 #include "ardour/session_playlists.h"
103 #include "ardour/session_utils.h"
104 #include "ardour/silentfilesource.h"
105 #include "ardour/slave.h"
106 #include "ardour/smf_source.h"
107 #include "ardour/sndfile_helpers.h"
108 #include "ardour/sndfilesource.h"
109 #include "ardour/source_factory.h"
110 #include "ardour/template_utils.h"
111 #include "ardour/tempo.h"
112 #include "ardour/ticker.h"
113 #include "ardour/user_bundle.h"
114 #include "ardour/utils.h"
115 #include "ardour/utils.h"
116 #include "ardour/version.h"
117 #include "ardour/playlist_factory.h"
119 #include "control_protocol/control_protocol.h"
125 using namespace ARDOUR;
129 Session::first_stage_init (string fullpath, string snapshot_name)
131 if (fullpath.length() == 0) {
133 throw failed_constructor();
136 char buf[PATH_MAX+1];
137 if (!realpath (fullpath.c_str(), buf) && (errno != ENOENT)) {
138 error << string_compose(_("Could not use path %1 (%s)"), buf, strerror(errno)) << endmsg;
140 throw failed_constructor();
145 if (_path[_path.length()-1] != '/') {
149 if (Glib::file_test (_path, Glib::FILE_TEST_EXISTS) && ::access (_path.c_str(), W_OK)) {
155 /* these two are just provisional settings. set_state()
156 will likely override them.
159 _name = _current_snapshot_name = snapshot_name;
161 set_history_depth (Config->get_history_depth());
163 _current_frame_rate = _engine.frame_rate ();
164 _nominal_frame_rate = _current_frame_rate;
165 _base_frame_rate = _current_frame_rate;
167 _tempo_map = new TempoMap (_current_frame_rate);
168 _tempo_map->PropertyChanged.connect_same_thread (*this, boost::bind (&Session::tempo_map_changed, this, _1));
171 _non_soloed_outs_muted = false;
173 g_atomic_int_set (&processing_prohibited, 0);
174 _transport_speed = 0;
175 _last_transport_speed = 0;
176 _target_transport_speed = 0;
177 auto_play_legal = false;
178 transport_sub_state = 0;
179 _transport_frame = 0;
180 _requested_return_frame = -1;
181 end_location = new Location (0, 0, _("end"), Location::Flags ((Location::IsMark|Location::IsEnd)));
182 start_location = new Location (0, 0, _("start"), Location::Flags ((Location::IsMark|Location::IsStart)));
183 g_atomic_int_set (&_record_status, Disabled);
184 loop_changing = false;
187 _last_roll_location = 0;
188 _last_record_location = 0;
189 pending_locate_frame = 0;
190 pending_locate_roll = false;
191 pending_locate_flush = false;
192 state_was_pending = false;
194 outbound_mtc_timecode_frame = 0;
195 next_quarter_frame_to_send = -1;
196 current_block_size = 0;
197 solo_update_disabled = false;
198 _have_captured = false;
199 _worst_output_latency = 0;
200 _worst_input_latency = 0;
201 _worst_track_latency = 0;
202 _state_of_the_state = StateOfTheState(CannotSave|InitialConnecting|Loading);
203 _was_seamless = Config->get_seamless_loop ();
205 session_send_mmc = false;
206 session_send_mtc = false;
207 g_atomic_int_set (&_playback_load, 100);
208 g_atomic_int_set (&_capture_load, 100);
209 g_atomic_int_set (&_playback_load_min, 100);
210 g_atomic_int_set (&_capture_load_min, 100);
213 _gain_automation_buffer = 0;
214 _pan_automation_buffer = 0;
216 pending_abort = false;
217 destructive_index = 0;
218 first_file_data_format_reset = true;
219 first_file_header_format_reset = true;
220 post_export_sync = false;
223 AudioDiskstream::allocate_working_buffers();
225 /* default short fade = 15ms */
227 Crossfade::set_short_xfade_length ((nframes_t) floor (config.get_short_xfade_seconds() * frame_rate()));
228 SndFileSource::setup_standard_crossfades (*this, frame_rate());
230 last_mmc_step.tv_sec = 0;
231 last_mmc_step.tv_usec = 0;
234 /* click sounds are unset by default, which causes us to internal
235 waveforms for clicks.
239 click_emphasis_length = 0;
242 process_function = &Session::process_with_events;
244 if (config.get_use_video_sync()) {
245 waiting_for_sync_offset = true;
247 waiting_for_sync_offset = false;
250 last_timecode_when = 0;
251 _timecode_offset = 0;
252 _timecode_offset_negative = true;
253 last_timecode_valid = false;
257 last_rr_session_dir = session_dirs.begin();
258 refresh_disk_space ();
260 // set_default_fade (0.2, 5.0); /* steepness, millisecs */
264 average_slave_delta = 1800; // !!! why 1800 ????
265 have_first_delta_accumulator = false;
266 delta_accumulator_cnt = 0;
267 _slave_state = Stopped;
269 _engine.GraphReordered.connect_same_thread (*this, boost::bind (&Session::graph_reordered, this));
271 /* These are all static "per-class" signals */
273 SourceFactory::SourceCreated.connect_same_thread (*this, boost::bind (&Session::add_source, this, _1));
274 PlaylistFactory::PlaylistCreated.connect_same_thread (*this, boost::bind (&Session::add_playlist, this, _1, _2));
275 AutomationList::AutomationListCreated.connect_same_thread (*this, boost::bind (&Session::add_automation_list, this, _1));
276 Controllable::Destroyed.connect_same_thread (*this, boost::bind (&Session::remove_controllable, this, _1));
277 IO::PortCountChanged.connect_same_thread (*this, boost::bind (&Session::ensure_buffers, this, _1));
279 /* stop IO objects from doing stuff until we're ready for them */
281 Delivery::disable_panners ();
282 IO::disable_connecting ();
286 Session::second_stage_init ()
288 AudioFileSource::set_peak_dir (_session_dir->peak_path().to_string());
291 if (load_state (_current_snapshot_name)) {
294 remove_empty_sounds ();
297 if (_butler->start_thread()) {
301 if (start_midi_thread ()) {
305 // set_state() will call setup_raid_path(), but if it's a new session we need
306 // to call setup_raid_path() here.
309 if (set_state (*state_tree->root(), Stateful::loading_state_version)) {
313 setup_raid_path(_path);
316 /* we can't save till after ::when_engine_running() is called,
317 because otherwise we save state with no connections made.
318 therefore, we reset _state_of_the_state because ::set_state()
319 will have cleared it.
321 we also have to include Loading so that any events that get
322 generated between here and the end of ::when_engine_running()
323 will be processed directly rather than queued.
326 _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);
358 deliver_mmc (MIDI::MachineControl::cmdMmcReset, 0);
359 deliver_mmc (MIDI::MachineControl::cmdLocate, 0);
361 MidiClockTicker::instance().set_session (this);
362 MIDI::Name::MidiPatchManager::instance().set_session (this);
364 /* initial program change will be delivered later; see ::config_changed() */
366 BootMessage (_("Reset Control Protocols"));
368 ControlProtocolManager::instance().set_session (this);
370 config.set_end_marker_is_free (_is_new);
372 _state_of_the_state = Clean;
374 DirtyChanged (); /* EMIT SIGNAL */
376 if (state_was_pending) {
377 save_state (_current_snapshot_name);
378 remove_pending_capture_state ();
379 state_was_pending = false;
382 BootMessage (_("Session loading complete"));
388 Session::raid_path () const
390 SearchPath raid_search_path;
392 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
393 raid_search_path += sys::path((*i).path);
396 return raid_search_path.to_string ();
400 Session::setup_raid_path (string path)
409 session_dirs.clear ();
411 SearchPath search_path(path);
412 SearchPath sound_search_path;
413 SearchPath midi_search_path;
415 for (SearchPath::const_iterator i = search_path.begin(); i != search_path.end(); ++i) {
416 sp.path = (*i).to_string ();
417 sp.blocks = 0; // not needed
418 session_dirs.push_back (sp);
420 SessionDirectory sdir(sp.path);
422 sound_search_path += sdir.sound_path ();
423 midi_search_path += sdir.midi_path ();
426 // set the search path for each data type
427 FileSource::set_search_path (DataType::AUDIO, sound_search_path.to_string ());
428 SMFSource::set_search_path (DataType::MIDI, midi_search_path.to_string ());
430 // reset the round-robin soundfile path thingie
431 last_rr_session_dir = session_dirs.begin();
435 Session::path_is_within_session (const std::string& path)
437 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
438 if (path.find ((*i).path) == 0) {
446 Session::ensure_subdirs ()
450 dir = session_directory().peak_path().to_string();
452 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
453 error << string_compose(_("Session: cannot create session peakfile folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
457 dir = session_directory().sound_path().to_string();
459 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
460 error << string_compose(_("Session: cannot create session sounds dir \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
464 dir = session_directory().midi_path().to_string();
466 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
467 error << string_compose(_("Session: cannot create session midi dir \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
471 dir = session_directory().dead_sound_path().to_string();
473 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
474 error << string_compose(_("Session: cannot create session dead sounds folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
478 dir = session_directory().export_path().to_string();
480 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
481 error << string_compose(_("Session: cannot create session export folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
485 dir = analysis_dir ();
487 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
488 error << string_compose(_("Session: cannot create session analysis folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
496 Session::create (const string& mix_template, nframes_t initial_length, BusProfile* bus_profile)
499 if (g_mkdir_with_parents (_path.c_str(), 0755) < 0) {
500 error << string_compose(_("Session: cannot create session folder \"%1\" (%2)"), _path, strerror (errno)) << endmsg;
504 if (ensure_subdirs ()) {
508 if (!mix_template.empty()) {
509 std::string in_path = mix_template;
511 ifstream in(in_path.c_str());
514 string out_path = _path;
516 out_path += statefile_suffix;
518 ofstream out(out_path.c_str());
525 error << string_compose (_("Could not open %1 for writing mix template"), out_path)
531 error << string_compose (_("Could not open mix template %1 for reading"), in_path)
538 /* Instantiate metadata */
540 _metadata = new SessionMetadata ();
542 /* set initial start + end point */
544 start_location->set_end (0);
545 _locations.add (start_location);
547 end_location->set_end (initial_length);
548 _locations.add (end_location);
550 _state_of_the_state = Clean;
552 /* set up Master Out and Control Out if necessary */
558 ChanCount count(DataType::AUDIO, bus_profile->master_out_channels);
560 if (bus_profile->master_out_channels) {
561 Route* rt = new Route (*this, _("master"), Route::MasterOut, DataType::AUDIO);
566 boost_debug_shared_ptr_mark_interesting (rt, "Route");
567 boost::shared_ptr<Route> r (rt);
568 r->input()->ensure_io (count, false, this);
569 r->output()->ensure_io (count, false, this);
570 r->set_remote_control_id (control_id++);
574 if (Config->get_use_monitor_bus()) {
575 Route* rt = new Route (*this, _("monitor"), Route::MonitorOut, DataType::AUDIO);
580 boost_debug_shared_ptr_mark_interesting (rt, "Route");
581 boost::shared_ptr<Route> r (rt);
582 r->input()->ensure_io (count, false, this);
583 r->output()->ensure_io (count, false, this);
584 r->set_remote_control_id (control_id);
590 /* prohibit auto-connect to master, because there isn't one */
591 bus_profile->output_ac = AutoConnectOption (bus_profile->output_ac & ~AutoConnectMaster);
595 add_routes (rl, false);
598 /* this allows the user to override settings with an environment variable.
601 if (no_auto_connect()) {
602 bus_profile->input_ac = AutoConnectOption (0);
603 bus_profile->output_ac = AutoConnectOption (0);
606 Config->set_input_auto_connect (bus_profile->input_ac);
607 Config->set_output_auto_connect (bus_profile->output_ac);
617 Session::load_diskstreams (const XMLNode& node)
620 XMLNodeConstIterator citer;
622 clist = node.children();
624 for (citer = clist.begin(); citer != clist.end(); ++citer) {
627 /* diskstreams added automatically by DiskstreamCreated handler */
628 if ((*citer)->name() == "AudioDiskstream" || (*citer)->name() == "DiskStream") {
629 AudioDiskstream* dsp (new AudioDiskstream (*this, **citer));
630 boost::shared_ptr<AudioDiskstream> dstream (dsp);
631 add_diskstream (dstream);
632 } else if ((*citer)->name() == "MidiDiskstream") {
633 boost::shared_ptr<MidiDiskstream> dstream (new MidiDiskstream (*this, **citer));
634 add_diskstream (dstream);
636 error << _("Session: unknown diskstream type in XML") << endmsg;
640 catch (failed_constructor& err) {
641 error << _("Session: could not load diskstream via XML state") << endmsg;
650 Session::maybe_write_autosave()
652 if (dirty() && record_status() != Recording) {
653 save_state("", true);
658 Session::remove_pending_capture_state ()
660 sys::path pending_state_file_path(_session_dir->root_path());
662 pending_state_file_path /= legalize_for_path (_current_snapshot_name) + pending_suffix;
666 sys::remove (pending_state_file_path);
668 catch(sys::filesystem_error& ex)
670 error << string_compose(_("Could remove pending capture state at path \"%1\" (%2)"),
671 pending_state_file_path.to_string(), ex.what()) << endmsg;
675 /** Rename a state file.
676 * @param snapshot_name Snapshot name.
679 Session::rename_state (string old_name, string new_name)
681 if (old_name == _current_snapshot_name || old_name == _name) {
682 /* refuse to rename the current snapshot or the "main" one */
686 const string old_xml_filename = legalize_for_path (old_name) + statefile_suffix;
687 const string new_xml_filename = legalize_for_path (new_name) + statefile_suffix;
689 const sys::path old_xml_path = _session_dir->root_path() / old_xml_filename;
690 const sys::path new_xml_path = _session_dir->root_path() / new_xml_filename;
694 sys::rename (old_xml_path, new_xml_path);
696 catch (const sys::filesystem_error& err)
698 error << string_compose(_("could not rename snapshot %1 to %2 (%3)"),
699 old_name, new_name, err.what()) << endmsg;
703 /** Remove a state file.
704 * @param snapshot_name Snapshot name.
707 Session::remove_state (string snapshot_name)
709 if (snapshot_name == _current_snapshot_name || snapshot_name == _name) {
710 // refuse to remove the current snapshot or the "main" one
714 sys::path xml_path(_session_dir->root_path());
716 xml_path /= legalize_for_path (snapshot_name) + statefile_suffix;
718 if (!create_backup_file (xml_path)) {
719 // don't remove it if a backup can't be made
720 // create_backup_file will log the error.
725 sys::remove (xml_path);
729 Session::save_state (string snapshot_name, bool pending)
732 sys::path xml_path(_session_dir->root_path());
734 if (!_writable || (_state_of_the_state & CannotSave)) {
738 if (!_engine.connected ()) {
739 error << string_compose (_("the %1 audio engine is not connected and state saving would lose all I/O connections. Session not saved"),
745 /* tell sources we're saving first, in case they write out to a new file
746 * which should be saved with the state rather than the old one */
747 for (SourceMap::const_iterator i = sources.begin(); i != sources.end(); ++i)
748 i->second->session_saved();
750 tree.set_root (&get_state());
752 if (snapshot_name.empty()) {
753 snapshot_name = _current_snapshot_name;
758 /* proper save: use statefile_suffix (.ardour in English) */
760 xml_path /= legalize_for_path (snapshot_name) + statefile_suffix;
762 /* make a backup copy of the old file */
764 if (sys::exists(xml_path) && !create_backup_file (xml_path)) {
765 // create_backup_file will log the error
771 /* pending save: use pending_suffix (.pending in English) */
772 xml_path /= legalize_for_path (snapshot_name) + pending_suffix;
775 sys::path tmp_path(_session_dir->root_path());
777 tmp_path /= legalize_for_path (snapshot_name) + temp_suffix;
779 // cerr << "actually writing state to " << xml_path.to_string() << endl;
781 if (!tree.write (tmp_path.to_string())) {
782 error << string_compose (_("state could not be saved to %1"), tmp_path.to_string()) << endmsg;
783 sys::remove (tmp_path);
788 if (rename (tmp_path.to_string().c_str(), xml_path.to_string().c_str()) != 0) {
789 error << string_compose (_("could not rename temporary session file %1 to %2"),
790 tmp_path.to_string(), xml_path.to_string()) << endmsg;
791 sys::remove (tmp_path);
798 save_history (snapshot_name);
800 bool was_dirty = dirty();
802 _state_of_the_state = StateOfTheState (_state_of_the_state & ~Dirty);
805 DirtyChanged (); /* EMIT SIGNAL */
808 StateSaved (snapshot_name); /* EMIT SIGNAL */
815 Session::restore_state (string snapshot_name)
817 if (load_state (snapshot_name) == 0) {
818 set_state (*state_tree->root(), Stateful::loading_state_version);
825 Session::load_state (string snapshot_name)
830 state_was_pending = false;
832 /* check for leftover pending state from a crashed capture attempt */
834 sys::path xmlpath(_session_dir->root_path());
835 xmlpath /= legalize_for_path (snapshot_name) + pending_suffix;
837 if (sys::exists (xmlpath)) {
839 /* there is pending state from a crashed capture attempt */
841 if (*AskAboutPendingState()) {
842 state_was_pending = true;
846 if (!state_was_pending) {
847 xmlpath = _session_dir->root_path();
848 xmlpath /= legalize_for_path (snapshot_name) + statefile_suffix;
851 if (!sys::exists (xmlpath)) {
852 error << string_compose(_("%1: session state information file \"%2\" doesn't exist!"), _name, xmlpath.to_string()) << endmsg;
856 state_tree = new XMLTree;
860 /* writable() really reflects the whole folder, but if for any
861 reason the session state file can't be written to, still
865 if (::access (xmlpath.to_string().c_str(), W_OK) != 0) {
869 if (!state_tree->read (xmlpath.to_string())) {
870 error << string_compose(_("Could not understand ardour file %1"), xmlpath.to_string()) << endmsg;
876 XMLNode& root (*state_tree->root());
878 if (root.name() != X_("Session")) {
879 error << string_compose (_("Session file %1 is not a session"), xmlpath.to_string()) << endmsg;
885 const XMLProperty* prop;
887 if ((prop = root.property ("version")) == 0) {
888 /* no version implies very old version of Ardour */
889 Stateful::loading_state_version = 1000;
895 sscanf (prop->value().c_str(), "%d.%d.%d", &major, &minor, µ);
896 Stateful::loading_state_version = (major * 1000) + minor;
899 if (Stateful::loading_state_version < CURRENT_SESSION_FILE_VERSION) {
901 sys::path backup_path(_session_dir->root_path());
903 backup_path /= legalize_for_path (snapshot_name) + "-1" + statefile_suffix;
905 // only create a backup once
906 if (sys::exists (backup_path)) {
910 info << string_compose (_("Copying old session file %1 to %2\nUse %2 with %3 versions before 2.0 from now on"),
911 xmlpath.to_string(), backup_path.to_string(), PROGRAM_NAME)
916 sys::copy_file (xmlpath, backup_path);
918 catch(sys::filesystem_error& ex)
920 error << string_compose (_("Unable to make backup of state file %1 (%2)"),
921 xmlpath.to_string(), ex.what())
931 Session::load_options (const XMLNode& node)
933 LocaleGuard lg (X_("POSIX"));
934 config.set_variables (node);
945 Session::get_template()
947 /* if we don't disable rec-enable, diskstreams
948 will believe they need to store their capture
949 sources in their state node.
952 disable_record (false);
958 Session::state(bool full_state)
960 XMLNode* node = new XMLNode("Session");
963 // store libardour version, just in case
965 snprintf(buf, sizeof(buf), "%d.%d.%d", libardour3_major_version, libardour3_minor_version, libardour3_micro_version);
966 node->add_property("version", string(buf));
968 /* store configuration settings */
972 node->add_property ("name", _name);
973 snprintf (buf, sizeof (buf), "%" PRId32, _nominal_frame_rate);
974 node->add_property ("sample-rate", buf);
976 if (session_dirs.size() > 1) {
980 vector<space_and_path>::iterator i = session_dirs.begin();
981 vector<space_and_path>::iterator next;
983 ++i; /* skip the first one */
987 while (i != session_dirs.end()) {
991 if (next != session_dirs.end()) {
1001 child = node->add_child ("Path");
1002 child->add_content (p);
1006 /* save the ID counter */
1008 snprintf (buf, sizeof (buf), "%" PRIu64, ID::counter());
1009 node->add_property ("id-counter", buf);
1011 /* various options */
1013 node->add_child_nocopy (config.get_variables ());
1015 node->add_child_nocopy (_metadata->get_state());
1017 child = node->add_child ("Sources");
1020 Glib::Mutex::Lock sl (source_lock);
1022 for (SourceMap::iterator siter = sources.begin(); siter != sources.end(); ++siter) {
1024 /* Don't save information about non-destructive file sources that are empty */
1025 /* FIXME: MIDI breaks if this is made FileSource like it should be... */
1027 boost::shared_ptr<AudioFileSource> fs;
1028 if ((fs = boost::dynamic_pointer_cast<AudioFileSource> (siter->second)) != 0) {
1029 if (!fs->destructive()) {
1030 if (fs->length(fs->timeline_position()) == 0) {
1036 child->add_child_nocopy (siter->second->get_state());
1040 child = node->add_child ("Regions");
1043 Glib::Mutex::Lock rl (region_lock);
1044 const RegionFactory::RegionMap& region_map (RegionFactory::all_regions());
1045 for (RegionFactory::RegionMap::const_iterator i = region_map.begin(); i != region_map.end(); ++i) {
1046 boost::shared_ptr<Region> r = i->second;
1047 /* only store regions not attached to playlists */
1048 if (r->playlist() == 0) {
1049 child->add_child_nocopy (r->state (true));
1054 child = node->add_child ("DiskStreams");
1057 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
1058 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
1059 if (!(*i)->hidden()) {
1060 child->add_child_nocopy ((*i)->get_state());
1066 node->add_child_nocopy (_locations.get_state());
1068 // for a template, just create a new Locations, populate it
1069 // with the default start and end, and get the state for that.
1071 Location* start = new Location(0, 0, _("start"), Location::Flags ((Location::IsMark|Location::IsStart)));
1072 Location* end = new Location(0, 0, _("end"), Location::Flags ((Location::IsMark|Location::IsEnd)));
1075 end->set_end(compute_initial_length());
1077 node->add_child_nocopy (loc.get_state());
1080 child = node->add_child ("Bundles");
1082 boost::shared_ptr<BundleList> bundles = _bundles.reader ();
1083 for (BundleList::iterator i = bundles->begin(); i != bundles->end(); ++i) {
1084 boost::shared_ptr<UserBundle> b = boost::dynamic_pointer_cast<UserBundle> (*i);
1086 child->add_child_nocopy (b->get_state());
1091 child = node->add_child ("Routes");
1093 boost::shared_ptr<RouteList> r = routes.reader ();
1095 RoutePublicOrderSorter cmp;
1096 RouteList public_order (*r);
1097 public_order.sort (cmp);
1099 /* the sort should have put control outs first */
1102 assert (_monitor_out == public_order.front());
1105 for (RouteList::iterator i = public_order.begin(); i != public_order.end(); ++i) {
1106 if (!(*i)->is_hidden()) {
1108 child->add_child_nocopy ((*i)->get_state());
1110 child->add_child_nocopy ((*i)->get_template());
1116 playlists->add_state (node, full_state);
1118 child = node->add_child ("RouteGroups");
1119 for (list<RouteGroup *>::iterator i = _route_groups.begin(); i != _route_groups.end(); ++i) {
1120 child->add_child_nocopy ((*i)->get_state());
1124 child = node->add_child ("Click");
1125 child->add_child_nocopy (_click_io->state (full_state));
1129 child = node->add_child ("NamedSelections");
1130 for (NamedSelectionList::iterator i = named_selections.begin(); i != named_selections.end(); ++i) {
1132 child->add_child_nocopy ((*i)->get_state());
1137 node->add_child_nocopy (_tempo_map->get_state());
1139 node->add_child_nocopy (get_control_protocol_state());
1142 node->add_child_copy (*_extra_xml);
1149 Session::get_control_protocol_state ()
1151 ControlProtocolManager& cpm (ControlProtocolManager::instance());
1152 return cpm.get_state();
1156 Session::set_state (const XMLNode& node, int version)
1160 const XMLProperty* prop;
1163 _state_of_the_state = StateOfTheState (_state_of_the_state|CannotSave);
1165 if (node.name() != X_("Session")){
1166 fatal << _("programming error: Session: incorrect XML node sent to set_state()") << endmsg;
1170 if ((prop = node.property ("version")) != 0) {
1171 version = atoi (prop->value ()) * 1000;
1174 if ((prop = node.property ("name")) != 0) {
1175 _name = prop->value ();
1178 if ((prop = node.property (X_("sample-rate"))) != 0) {
1180 _nominal_frame_rate = atoi (prop->value());
1182 if (_nominal_frame_rate != _current_frame_rate) {
1183 if (*AskAboutSampleRateMismatch (_nominal_frame_rate, _current_frame_rate)) {
1189 setup_raid_path(_session_dir->root_path().to_string());
1191 if ((prop = node.property (X_("id-counter"))) != 0) {
1193 sscanf (prop->value().c_str(), "%" PRIu64, &x);
1194 ID::init_counter (x);
1196 /* old sessions used a timebased counter, so fake
1197 the startup ID counter based on a standard
1202 ID::init_counter (now);
1206 IO::disable_connecting ();
1208 /* Object loading order:
1213 MIDI Control // relies on data from Options/Config
1227 if ((child = find_named_node (node, "Extra")) != 0) {
1228 _extra_xml = new XMLNode (*child);
1231 if (((child = find_named_node (node, "Options")) != 0)) { /* old style */
1232 load_options (*child);
1233 } else if ((child = find_named_node (node, "Config")) != 0) { /* new style */
1234 load_options (*child);
1236 error << _("Session: XML state has no options section") << endmsg;
1239 if (use_config_midi_ports ()) {
1242 if (version >= 3000) {
1243 if ((child = find_named_node (node, "Metadata")) == 0) {
1244 warning << _("Session: XML state has no metadata section") << endmsg;
1245 } else if (_metadata->set_state (*child, version)) {
1250 if ((child = find_named_node (node, "Locations")) == 0) {
1251 error << _("Session: XML state has no locations section") << endmsg;
1253 } else if (_locations.set_state (*child, version)) {
1259 if ((location = _locations.auto_loop_location()) != 0) {
1260 set_auto_loop_location (location);
1263 if ((location = _locations.auto_punch_location()) != 0) {
1264 set_auto_punch_location (location);
1267 if ((location = _locations.end_location()) == 0) {
1268 _locations.add (end_location);
1270 delete end_location;
1271 end_location = location;
1274 if ((location = _locations.start_location()) == 0) {
1275 _locations.add (start_location);
1277 delete start_location;
1278 start_location = location;
1281 AudioFileSource::set_header_position_offset (start_location->start());
1283 if ((child = find_named_node (node, "Sources")) == 0) {
1284 error << _("Session: XML state has no sources section") << endmsg;
1286 } else if (load_sources (*child)) {
1290 if ((child = find_named_node (node, "Regions")) == 0) {
1291 error << _("Session: XML state has no Regions section") << endmsg;
1293 } else if (load_regions (*child)) {
1297 if ((child = find_named_node (node, "Playlists")) == 0) {
1298 error << _("Session: XML state has no playlists section") << endmsg;
1300 } else if (playlists->load (*this, *child)) {
1304 if ((child = find_named_node (node, "UnusedPlaylists")) == 0) {
1306 } else if (playlists->load_unused (*this, *child)) {
1310 if ((child = find_named_node (node, "NamedSelections")) != 0) {
1311 if (load_named_selections (*child)) {
1316 if ((child = find_named_node (node, "DiskStreams")) == 0) {
1317 error << _("Session: XML state has no diskstreams section") << endmsg;
1319 } else if (load_diskstreams (*child)) {
1323 if (version >= 3000) {
1324 if ((child = find_named_node (node, "Bundles")) == 0) {
1325 warning << _("Session: XML state has no bundles section") << endmsg;
1328 /* We can't load Bundles yet as they need to be able
1329 to convert from port names to Port objects, which can't happen until
1331 _bundle_xml_node = new XMLNode (*child);
1335 if ((child = find_named_node (node, "TempoMap")) == 0) {
1336 error << _("Session: XML state has no Tempo Map section") << endmsg;
1338 } else if (_tempo_map->set_state (*child, version)) {
1342 if ((child = find_named_node (node, "Routes")) == 0) {
1343 error << _("Session: XML state has no routes section") << endmsg;
1345 } else if (load_routes (*child, version)) {
1349 if (version >= 3000) {
1351 if ((child = find_named_node (node, "RouteGroups")) == 0) {
1352 error << _("Session: XML state has no route groups section") << endmsg;
1354 } else if (load_route_groups (*child, version)) {
1358 } else if (version < 3000) {
1360 if ((child = find_named_node (node, "EditGroups")) == 0) {
1361 error << _("Session: XML state has no edit groups section") << endmsg;
1363 } else if (load_route_groups (*child, version)) {
1367 if ((child = find_named_node (node, "MixGroups")) == 0) {
1368 error << _("Session: XML state has no mix groups section") << endmsg;
1370 } else if (load_route_groups (*child, version)) {
1375 if ((child = find_named_node (node, "Click")) == 0) {
1376 warning << _("Session: XML state has no click section") << endmsg;
1377 } else if (_click_io) {
1378 _click_io->set_state (*child, version);
1381 if ((child = find_named_node (node, "ControlProtocols")) != 0) {
1382 ControlProtocolManager::instance().set_protocol_states (*child);
1385 /* here beginneth the second phase ... */
1387 StateReady (); /* EMIT SIGNAL */
1396 Session::load_routes (const XMLNode& node, int version)
1399 XMLNodeConstIterator niter;
1400 RouteList new_routes;
1402 nlist = node.children();
1406 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1408 boost::shared_ptr<Route> route (XMLRouteFactory (**niter, version));
1411 error << _("Session: cannot create Route from XML description.") << endmsg;
1415 BootMessage (string_compose (_("Loaded track/bus %1"), route->name()));
1417 new_routes.push_back (route);
1420 add_routes (new_routes, false);
1425 boost::shared_ptr<Route>
1426 Session::XMLRouteFactory (const XMLNode& node, int version)
1428 boost::shared_ptr<Route> ret;
1430 if (node.name() != "Route") {
1434 const XMLProperty* dsprop;
1436 if ((dsprop = node.property (X_("diskstream-id"))) == 0) {
1437 dsprop = node.property (X_("diskstream"));
1440 DataType type = DataType::AUDIO;
1441 const XMLProperty* prop = node.property("default-type");
1444 type = DataType (prop->value());
1447 assert (type != DataType::NIL);
1451 boost::shared_ptr<Diskstream> ds;
1452 PBD::ID diskstream_id (dsprop->value());
1455 /* this wierd hack is used when creating
1456 tracks from a template. We have a special
1457 ID for the diskstream that means "you
1458 should create a new diskstream here, not
1459 look for an old one."
1462 if (diskstream_id != zero) {
1464 ds = diskstream_by_id (diskstream_id);
1467 error << string_compose (_("cannot find diskstream ID %1"), diskstream_id.to_s()) << endmsg;
1474 if (type == DataType::AUDIO) {
1475 track = new AudioTrack (*this, X_("toBeResetFroXML"));
1478 track = new MidiTrack (*this, X_("toBeResetFroXML"));
1481 if (track->init()) {
1487 track->set_diskstream (ds);
1489 track->use_new_diskstream ();
1492 if (track->set_state (node, version)) {
1497 boost_debug_shared_ptr_mark_interesting (track, "Track");
1501 Route* rt = new Route (*this, X_("toBeResetFroXML"));
1503 if (rt->init () == 0 && rt->set_state (node, version) == 0) {
1504 boost_debug_shared_ptr_mark_interesting (rt, "Route");
1515 Session::load_regions (const XMLNode& node)
1518 XMLNodeConstIterator niter;
1519 boost::shared_ptr<Region> region;
1521 nlist = node.children();
1525 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1526 if ((region = XMLRegionFactory (**niter, false)) == 0) {
1527 error << _("Session: cannot create Region from XML description.");
1528 const XMLProperty *name = (**niter).property("name");
1531 error << " " << string_compose (_("Can not load state for region '%1'"), name->value());
1541 boost::shared_ptr<Region>
1542 Session::XMLRegionFactory (const XMLNode& node, bool full)
1544 const XMLProperty* type = node.property("type");
1548 if ( !type || type->value() == "audio" ) {
1550 return boost::shared_ptr<Region>(XMLAudioRegionFactory (node, full));
1552 } else if (type->value() == "midi") {
1554 return boost::shared_ptr<Region>(XMLMidiRegionFactory (node, full));
1558 } catch (failed_constructor& err) {
1559 return boost::shared_ptr<Region> ();
1562 return boost::shared_ptr<Region> ();
1565 boost::shared_ptr<AudioRegion>
1566 Session::XMLAudioRegionFactory (const XMLNode& node, bool /*full*/)
1568 const XMLProperty* prop;
1569 boost::shared_ptr<Source> source;
1570 boost::shared_ptr<AudioSource> as;
1572 SourceList master_sources;
1573 uint32_t nchans = 1;
1576 if (node.name() != X_("Region")) {
1577 return boost::shared_ptr<AudioRegion>();
1580 if ((prop = node.property (X_("channels"))) != 0) {
1581 nchans = atoi (prop->value().c_str());
1584 if ((prop = node.property ("name")) == 0) {
1585 cerr << "no name for this region\n";
1589 if ((prop = node.property (X_("source-0"))) == 0) {
1590 if ((prop = node.property ("source")) == 0) {
1591 error << _("Session: XMLNode describing a AudioRegion is incomplete (no source)") << endmsg;
1592 return boost::shared_ptr<AudioRegion>();
1596 PBD::ID s_id (prop->value());
1598 if ((source = source_by_id (s_id)) == 0) {
1599 error << string_compose(_("Session: XMLNode describing a AudioRegion references an unknown source id =%1"), s_id) << endmsg;
1600 return boost::shared_ptr<AudioRegion>();
1603 as = boost::dynamic_pointer_cast<AudioSource>(source);
1605 error << string_compose(_("Session: XMLNode describing a AudioRegion references a non-audio source id =%1"), s_id) << endmsg;
1606 return boost::shared_ptr<AudioRegion>();
1609 sources.push_back (as);
1611 /* pickup other channels */
1613 for (uint32_t n=1; n < nchans; ++n) {
1614 snprintf (buf, sizeof(buf), X_("source-%d"), n);
1615 if ((prop = node.property (buf)) != 0) {
1617 PBD::ID id2 (prop->value());
1619 if ((source = source_by_id (id2)) == 0) {
1620 error << string_compose(_("Session: XMLNode describing a AudioRegion references an unknown source id =%1"), id2) << endmsg;
1621 return boost::shared_ptr<AudioRegion>();
1624 as = boost::dynamic_pointer_cast<AudioSource>(source);
1626 error << string_compose(_("Session: XMLNode describing a AudioRegion references a non-audio source id =%1"), id2) << endmsg;
1627 return boost::shared_ptr<AudioRegion>();
1629 sources.push_back (as);
1633 for (uint32_t n = 0; n < nchans; ++n) {
1634 snprintf (buf, sizeof(buf), X_("master-source-%d"), n);
1635 if ((prop = node.property (buf)) != 0) {
1637 PBD::ID id2 (prop->value());
1639 if ((source = source_by_id (id2)) == 0) {
1640 error << string_compose(_("Session: XMLNode describing a AudioRegion references an unknown source id =%1"), id2) << endmsg;
1641 return boost::shared_ptr<AudioRegion>();
1644 as = boost::dynamic_pointer_cast<AudioSource>(source);
1646 error << string_compose(_("Session: XMLNode describing a AudioRegion references a non-audio source id =%1"), id2) << endmsg;
1647 return boost::shared_ptr<AudioRegion>();
1649 master_sources.push_back (as);
1654 boost::shared_ptr<AudioRegion> region (boost::dynamic_pointer_cast<AudioRegion> (RegionFactory::create (sources, node)));
1656 /* a final detail: this is the one and only place that we know how long missing files are */
1658 if (region->whole_file()) {
1659 for (SourceList::iterator sx = sources.begin(); sx != sources.end(); ++sx) {
1660 boost::shared_ptr<SilentFileSource> sfp = boost::dynamic_pointer_cast<SilentFileSource> (*sx);
1662 sfp->set_length (region->length());
1667 if (!master_sources.empty()) {
1668 if (master_sources.size() != nchans) {
1669 error << _("Session: XMLNode describing an AudioRegion is missing some master sources; ignored") << endmsg;
1671 region->set_master_sources (master_sources);
1679 catch (failed_constructor& err) {
1680 return boost::shared_ptr<AudioRegion>();
1684 boost::shared_ptr<MidiRegion>
1685 Session::XMLMidiRegionFactory (const XMLNode& node, bool /*full*/)
1687 const XMLProperty* prop;
1688 boost::shared_ptr<Source> source;
1689 boost::shared_ptr<MidiSource> ms;
1691 uint32_t nchans = 1;
1693 if (node.name() != X_("Region")) {
1694 return boost::shared_ptr<MidiRegion>();
1697 if ((prop = node.property (X_("channels"))) != 0) {
1698 nchans = atoi (prop->value().c_str());
1701 if ((prop = node.property ("name")) == 0) {
1702 cerr << "no name for this region\n";
1706 // Multiple midi channels? that's just crazy talk
1707 assert(nchans == 1);
1709 if ((prop = node.property (X_("source-0"))) == 0) {
1710 if ((prop = node.property ("source")) == 0) {
1711 error << _("Session: XMLNode describing a MidiRegion is incomplete (no source)") << endmsg;
1712 return boost::shared_ptr<MidiRegion>();
1716 PBD::ID s_id (prop->value());
1718 if ((source = source_by_id (s_id)) == 0) {
1719 error << string_compose(_("Session: XMLNode describing a MidiRegion references an unknown source id =%1"), s_id) << endmsg;
1720 return boost::shared_ptr<MidiRegion>();
1723 ms = boost::dynamic_pointer_cast<MidiSource>(source);
1725 error << string_compose(_("Session: XMLNode describing a MidiRegion references a non-midi source id =%1"), s_id) << endmsg;
1726 return boost::shared_ptr<MidiRegion>();
1729 sources.push_back (ms);
1732 boost::shared_ptr<MidiRegion> region (boost::dynamic_pointer_cast<MidiRegion> (RegionFactory::create (sources, node)));
1733 /* a final detail: this is the one and only place that we know how long missing files are */
1735 if (region->whole_file()) {
1736 for (SourceList::iterator sx = sources.begin(); sx != sources.end(); ++sx) {
1737 boost::shared_ptr<SilentFileSource> sfp = boost::dynamic_pointer_cast<SilentFileSource> (*sx);
1739 sfp->set_length (region->length());
1747 catch (failed_constructor& err) {
1748 return boost::shared_ptr<MidiRegion>();
1753 Session::get_sources_as_xml ()
1756 XMLNode* node = new XMLNode (X_("Sources"));
1757 Glib::Mutex::Lock lm (source_lock);
1759 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ++i) {
1760 node->add_child_nocopy (i->second->get_state());
1767 Session::path_from_region_name (DataType type, string name, string identifier)
1769 char buf[PATH_MAX+1];
1771 SessionDirectory sdir(get_best_session_directory_for_new_source());
1772 sys::path source_dir = ((type == DataType::AUDIO)
1773 ? sdir.sound_path() : sdir.midi_path());
1775 string ext = ((type == DataType::AUDIO) ? ".wav" : ".mid");
1777 for (n = 0; n < 999999; ++n) {
1778 if (identifier.length()) {
1779 snprintf (buf, sizeof(buf), "%s%s%" PRIu32 "%s", name.c_str(),
1780 identifier.c_str(), n, ext.c_str());
1782 snprintf (buf, sizeof(buf), "%s-%" PRIu32 "%s", name.c_str(),
1786 sys::path source_path = source_dir / buf;
1788 if (!sys::exists (source_path)) {
1789 return source_path.to_string();
1793 error << string_compose (_("cannot create new file from region name \"%1\" with ident = \"%2\": too many existing files with similar names"),
1802 Session::load_sources (const XMLNode& node)
1805 XMLNodeConstIterator niter;
1806 boost::shared_ptr<Source> source;
1808 nlist = node.children();
1812 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1814 if ((source = XMLSourceFactory (**niter)) == 0) {
1815 error << _("Session: cannot create Source from XML description.") << endmsg;
1817 } catch (MissingSource& err) {
1818 warning << _("A sound file is missing. It will be replaced by silence.") << endmsg;
1819 source = SourceFactory::createSilent (*this, **niter, max_frames, _current_frame_rate);
1826 boost::shared_ptr<Source>
1827 Session::XMLSourceFactory (const XMLNode& node)
1829 if (node.name() != "Source") {
1830 return boost::shared_ptr<Source>();
1834 /* note: do peak building in another thread when loading session state */
1835 return SourceFactory::create (*this, node, true);
1838 catch (failed_constructor& err) {
1839 error << string_compose (_("Found a sound file that cannot be used by %1. Talk to the progammers."), PROGRAM_NAME) << endmsg;
1840 return boost::shared_ptr<Source>();
1845 Session::save_template (string template_name)
1849 if (_state_of_the_state & CannotSave) {
1853 sys::path user_template_dir(user_template_directory());
1857 sys::create_directories (user_template_dir);
1859 catch(sys::filesystem_error& ex)
1861 error << string_compose(_("Could not create mix templates directory \"%1\" (%2)"),
1862 user_template_dir.to_string(), ex.what()) << endmsg;
1866 tree.set_root (&get_template());
1868 sys::path template_file_path(user_template_dir);
1869 template_file_path /= template_name + template_suffix;
1871 if (sys::exists (template_file_path))
1873 warning << string_compose(_("Template \"%1\" already exists - new version not created"),
1874 template_file_path.to_string()) << endmsg;
1878 if (!tree.write (template_file_path.to_string())) {
1879 error << _("mix template not saved") << endmsg;
1887 Session::rename_template (string old_name, string new_name)
1889 sys::path old_path (user_template_directory());
1890 old_path /= old_name + template_suffix;
1892 sys::path new_path(user_template_directory());
1893 new_path /= new_name + template_suffix;
1895 if (sys::exists (new_path)) {
1896 warning << string_compose(_("Template \"%1\" already exists - template not renamed"),
1897 new_path.to_string()) << endmsg;
1902 sys::rename (old_path, new_path);
1910 Session::delete_template (string name)
1912 sys::path path = user_template_directory();
1913 path /= name + template_suffix;
1924 Session::refresh_disk_space ()
1927 struct statfs statfsbuf;
1928 vector<space_and_path>::iterator i;
1929 Glib::Mutex::Lock lm (space_lock);
1932 /* get freespace on every FS that is part of the session path */
1934 _total_free_4k_blocks = 0;
1936 for (i = session_dirs.begin(); i != session_dirs.end(); ++i) {
1937 statfs ((*i).path.c_str(), &statfsbuf);
1939 scale = statfsbuf.f_bsize/4096.0;
1941 (*i).blocks = (uint32_t) floor (statfsbuf.f_bavail * scale);
1942 _total_free_4k_blocks += (*i).blocks;
1948 Session::get_best_session_directory_for_new_source ()
1950 vector<space_and_path>::iterator i;
1951 string result = _session_dir->root_path().to_string();
1953 /* handle common case without system calls */
1955 if (session_dirs.size() == 1) {
1959 /* OK, here's the algorithm we're following here:
1961 We want to select which directory to use for
1962 the next file source to be created. Ideally,
1963 we'd like to use a round-robin process so as to
1964 get maximum performance benefits from splitting
1965 the files across multiple disks.
1967 However, in situations without much diskspace, an
1968 RR approach may end up filling up a filesystem
1969 with new files while others still have space.
1970 Its therefore important to pay some attention to
1971 the freespace in the filesystem holding each
1972 directory as well. However, if we did that by
1973 itself, we'd keep creating new files in the file
1974 system with the most space until it was as full
1975 as all others, thus negating any performance
1976 benefits of this RAID-1 like approach.
1978 So, we use a user-configurable space threshold. If
1979 there are at least 2 filesystems with more than this
1980 much space available, we use RR selection between them.
1981 If not, then we pick the filesystem with the most space.
1983 This gets a good balance between the two
1987 refresh_disk_space ();
1989 int free_enough = 0;
1991 for (i = session_dirs.begin(); i != session_dirs.end(); ++i) {
1992 if ((*i).blocks * 4096 >= Config->get_disk_choice_space_threshold()) {
1997 if (free_enough >= 2) {
1998 /* use RR selection process, ensuring that the one
2002 i = last_rr_session_dir;
2005 if (++i == session_dirs.end()) {
2006 i = session_dirs.begin();
2009 if ((*i).blocks * 4096 >= Config->get_disk_choice_space_threshold()) {
2010 if (create_session_directory ((*i).path)) {
2012 last_rr_session_dir = i;
2017 } while (i != last_rr_session_dir);
2021 /* pick FS with the most freespace (and that
2022 seems to actually work ...)
2025 vector<space_and_path> sorted;
2026 space_and_path_ascending_cmp cmp;
2028 sorted = session_dirs;
2029 sort (sorted.begin(), sorted.end(), cmp);
2031 for (i = sorted.begin(); i != sorted.end(); ++i) {
2032 if (create_session_directory ((*i).path)) {
2034 last_rr_session_dir = i;
2044 Session::load_named_selections (const XMLNode& node)
2047 XMLNodeConstIterator niter;
2050 nlist = node.children();
2054 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2056 if ((ns = XMLNamedSelectionFactory (**niter)) == 0) {
2057 error << _("Session: cannot create Named Selection from XML description.") << endmsg;
2065 Session::XMLNamedSelectionFactory (const XMLNode& node)
2068 return new NamedSelection (*this, node);
2071 catch (failed_constructor& err) {
2077 Session::automation_dir () const
2079 return Glib::build_filename (_path, "automation");
2083 Session::analysis_dir () const
2085 return Glib::build_filename (_path, "analysis");
2089 Session::load_bundles (XMLNode const & node)
2091 XMLNodeList nlist = node.children();
2092 XMLNodeConstIterator niter;
2096 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2097 if ((*niter)->name() == "InputBundle") {
2098 add_bundle (boost::shared_ptr<UserBundle> (new UserBundle (**niter, true)));
2099 } else if ((*niter)->name() == "OutputBundle") {
2100 add_bundle (boost::shared_ptr<UserBundle> (new UserBundle (**niter, false)));
2102 error << string_compose(_("Unknown node \"%1\" found in Bundles list from state file"), (*niter)->name()) << endmsg;
2111 Session::load_route_groups (const XMLNode& node, int version)
2113 XMLNodeList nlist = node.children();
2114 XMLNodeConstIterator niter;
2118 if (version >= 3000) {
2120 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2121 if ((*niter)->name() == "RouteGroup") {
2122 RouteGroup* rg = new RouteGroup (*this, "");
2123 add_route_group (rg);
2124 rg->set_state (**niter, version);
2128 } else if (version < 3000) {
2130 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2131 if ((*niter)->name() == "EditGroup" || (*niter)->name() == "MixGroup") {
2132 RouteGroup* rg = new RouteGroup (*this, "");
2133 add_route_group (rg);
2134 rg->set_state (**niter, version);
2143 Session::auto_save()
2145 save_state (_current_snapshot_name);
2149 state_file_filter (const string &str, void */*arg*/)
2151 return (str.length() > strlen(statefile_suffix) &&
2152 str.find (statefile_suffix) == (str.length() - strlen (statefile_suffix)));
2156 bool operator()(const string* a, const string* b) {
2162 remove_end(string* state)
2164 string statename(*state);
2166 string::size_type start,end;
2167 if ((start = statename.find_last_of ('/')) != string::npos) {
2168 statename = statename.substr (start+1);
2171 if ((end = statename.rfind(".ardour")) == string::npos) {
2172 end = statename.length();
2175 return new string(statename.substr (0, end));
2179 Session::possible_states (string path)
2181 PathScanner scanner;
2182 vector<string*>* states = scanner (path, state_file_filter, 0, false, false);
2184 transform(states->begin(), states->end(), states->begin(), remove_end);
2187 sort (states->begin(), states->end(), cmp);
2193 Session::possible_states () const
2195 return possible_states(_path);
2199 Session::add_route_group (RouteGroup* g)
2201 _route_groups.push_back (g);
2202 route_group_added (g); /* EMIT SIGNAL */
2207 Session::remove_route_group (RouteGroup& rg)
2209 list<RouteGroup*>::iterator i;
2211 if ((i = find (_route_groups.begin(), _route_groups.end(), &rg)) != _route_groups.end()) {
2212 _route_groups.erase (i);
2215 route_group_removed (); /* EMIT SIGNAL */
2221 Session::route_group_by_name (string name)
2223 list<RouteGroup *>::iterator i;
2225 for (i = _route_groups.begin(); i != _route_groups.end(); ++i) {
2226 if ((*i)->name() == name) {
2234 Session::start_reversible_command (const string& name)
2236 UndoTransaction* trans = new UndoTransaction();
2237 trans->set_name(name);
2242 Session::finish_reversible_command (UndoTransaction& ut)
2245 gettimeofday(&now, 0);
2246 ut.set_timestamp(now);
2251 Session::begin_reversible_command(const string& name)
2253 UndoTransaction* trans = new UndoTransaction();
2254 trans->set_name(name);
2256 if (!_current_trans.empty()) {
2257 _current_trans.top()->add_command (trans);
2259 _current_trans.push(trans);
2264 Session::commit_reversible_command(Command *cmd)
2266 assert(!_current_trans.empty());
2270 _current_trans.top()->add_command(cmd);
2273 if (_current_trans.top()->empty()) {
2274 _current_trans.pop();
2278 gettimeofday(&now, 0);
2279 _current_trans.top()->set_timestamp(now);
2281 _history.add(_current_trans.top());
2282 _current_trans.pop();
2286 accept_all_non_peak_files (const string& path, void */*arg*/)
2288 return (path.length() > 5 && path.find (peakfile_suffix) != (path.length() - 5));
2292 accept_all_state_files (const string& path, void */*arg*/)
2294 return (path.length() > 7 && path.find (".ardour") == (path.length() - 7));
2298 Session::find_all_sources (string path, set<string>& result)
2303 if (!tree.read (path)) {
2307 if ((node = find_named_node (*tree.root(), "Sources")) == 0) {
2312 XMLNodeConstIterator niter;
2314 nlist = node->children();
2318 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2322 if ((prop = (*niter)->property (X_("type"))) == 0) {
2326 DataType type (prop->value());
2328 if ((prop = (*niter)->property (X_("name"))) == 0) {
2332 if (prop->value()[0] == '/') {
2333 /* external file, ignore */
2337 Glib::ustring found_path;
2341 if (FileSource::find (type, prop->value(), true, is_new, chan, found_path)) {
2342 result.insert (found_path);
2350 Session::find_all_sources_across_snapshots (set<string>& result, bool exclude_this_snapshot)
2352 PathScanner scanner;
2353 vector<string*>* state_files;
2355 string this_snapshot_path;
2361 if (ripped[ripped.length()-1] == '/') {
2362 ripped = ripped.substr (0, ripped.length() - 1);
2365 state_files = scanner (ripped, accept_all_state_files, (void *) 0, false, true);
2367 if (state_files == 0) {
2372 this_snapshot_path = _path;
2373 this_snapshot_path += legalize_for_path (_current_snapshot_name);
2374 this_snapshot_path += statefile_suffix;
2376 for (vector<string*>::iterator i = state_files->begin(); i != state_files->end(); ++i) {
2378 if (exclude_this_snapshot && **i == this_snapshot_path) {
2382 if (find_all_sources (**i, result) < 0) {
2390 struct RegionCounter {
2391 typedef std::map<PBD::ID,boost::shared_ptr<AudioSource> > AudioSourceList;
2392 AudioSourceList::iterator iter;
2393 boost::shared_ptr<Region> region;
2396 RegionCounter() : count (0) {}
2400 Session::ask_about_playlist_deletion (boost::shared_ptr<Playlist> p)
2402 return *AskAboutPlaylistDeletion (p);
2406 Session::cleanup_sources (CleanupReport& rep)
2408 // FIXME: needs adaptation to midi
2410 vector<boost::shared_ptr<Source> > dead_sources;
2411 PathScanner scanner;
2413 vector<space_and_path>::iterator i;
2414 vector<space_and_path>::iterator nexti;
2415 vector<string*>* soundfiles;
2416 vector<string> unused;
2417 set<string> all_sources;
2422 _state_of_the_state = (StateOfTheState) (_state_of_the_state | InCleanup);
2424 /* step 1: consider deleting all unused playlists */
2426 if (playlists->maybe_delete_unused (boost::bind (Session::ask_about_playlist_deletion, _1))) {
2431 /* step 2: find all un-used sources */
2436 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ) {
2438 SourceMap::iterator tmp;
2443 /* do not bother with files that are zero size, otherwise we remove the current "nascent"
2447 if (!playlists->source_use_count(i->second) && i->second->length(i->second->timeline_position()) > 0) {
2448 dead_sources.push_back (i->second);
2449 i->second->drop_references ();
2455 /* build a list of all the possible sound directories for the session */
2457 for (i = session_dirs.begin(); i != session_dirs.end(); ) {
2462 SessionDirectory sdir ((*i).path);
2463 sound_path += sdir.sound_path().to_string();
2465 if (nexti != session_dirs.end()) {
2472 /* now do the same thing for the files that ended up in the sounds dir(s)
2473 but are not referenced as sources in any snapshot.
2476 soundfiles = scanner (sound_path, accept_all_non_peak_files, (void *) 0, false, true);
2478 if (soundfiles == 0) {
2482 /* find all sources, but don't use this snapshot because the
2483 state file on disk still references sources we may have already
2487 find_all_sources_across_snapshots (all_sources, true);
2489 /* add our current source list
2492 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ++i) {
2493 boost::shared_ptr<FileSource> fs;
2495 if ((fs = boost::dynamic_pointer_cast<FileSource> (i->second)) != 0) {
2496 all_sources.insert (fs->path());
2500 char tmppath1[PATH_MAX+1];
2501 char tmppath2[PATH_MAX+1];
2503 for (vector<string*>::iterator x = soundfiles->begin(); x != soundfiles->end(); ++x) {
2508 for (set<string>::iterator i = all_sources.begin(); i != all_sources.end(); ++i) {
2510 realpath(spath.c_str(), tmppath1);
2511 realpath((*i).c_str(), tmppath2);
2513 if (strcmp(tmppath1, tmppath2) == 0) {
2520 unused.push_back (spath);
2524 /* now try to move all unused files into the "dead_sounds" directory(ies) */
2526 for (vector<string>::iterator x = unused.begin(); x != unused.end(); ++x) {
2527 struct stat statbuf;
2529 rep.paths.push_back (*x);
2530 if (stat ((*x).c_str(), &statbuf) == 0) {
2531 rep.space += statbuf.st_size;
2536 /* don't move the file across filesystems, just
2537 stick it in the `dead_sound_dir_name' directory
2538 on whichever filesystem it was already on.
2541 if ((*x).find ("/sounds/") != string::npos) {
2543 /* old school, go up 1 level */
2545 newpath = Glib::path_get_dirname (*x); // "sounds"
2546 newpath = Glib::path_get_dirname (newpath); // "session-name"
2550 /* new school, go up 4 levels */
2552 newpath = Glib::path_get_dirname (*x); // "audiofiles"
2553 newpath = Glib::path_get_dirname (newpath); // "session-name"
2554 newpath = Glib::path_get_dirname (newpath); // "interchange"
2555 newpath = Glib::path_get_dirname (newpath); // "session-dir"
2559 newpath += dead_sound_dir_name;
2561 if (g_mkdir_with_parents (newpath.c_str(), 0755) < 0) {
2562 error << string_compose(_("Session: cannot create session peakfile folder \"%1\" (%2)"), newpath, strerror (errno)) << endmsg;
2567 newpath += Glib::path_get_basename ((*x));
2569 if (access (newpath.c_str(), F_OK) == 0) {
2571 /* the new path already exists, try versioning */
2573 char buf[PATH_MAX+1];
2577 snprintf (buf, sizeof (buf), "%s.%d", newpath.c_str(), version);
2580 while (access (newpath_v.c_str(), F_OK) == 0 && version < 999) {
2581 snprintf (buf, sizeof (buf), "%s.%d", newpath.c_str(), ++version);
2585 if (version == 999) {
2586 error << string_compose (_("there are already 1000 files with names like %1; versioning discontinued"),
2590 newpath = newpath_v;
2595 /* it doesn't exist, or we can't read it or something */
2599 if (::rename ((*x).c_str(), newpath.c_str()) != 0) {
2600 error << string_compose (_("cannot rename audio file source from %1 to %2 (%3)"),
2601 (*x), newpath, strerror (errno))
2606 /* see if there an easy to find peakfile for this file, and remove it.
2609 string peakpath = (*x).substr (0, (*x).find_last_of ('.'));
2610 peakpath += peakfile_suffix;
2612 if (access (peakpath.c_str(), W_OK) == 0) {
2613 if (::unlink (peakpath.c_str()) != 0) {
2614 error << string_compose (_("cannot remove peakfile %1 for %2 (%3)"),
2615 peakpath, _path, strerror (errno))
2617 /* try to back out */
2618 rename (newpath.c_str(), _path.c_str());
2626 /* dump the history list */
2630 /* save state so we don't end up a session file
2631 referring to non-existent sources.
2637 _state_of_the_state = (StateOfTheState) (_state_of_the_state & ~InCleanup);
2643 Session::cleanup_trash_sources (CleanupReport& rep)
2645 // FIXME: needs adaptation for MIDI
2647 vector<space_and_path>::iterator i;
2648 string dead_sound_dir;
2649 struct dirent* dentry;
2650 struct stat statbuf;
2656 for (i = session_dirs.begin(); i != session_dirs.end(); ++i) {
2658 dead_sound_dir = (*i).path;
2659 dead_sound_dir += dead_sound_dir_name;
2661 if ((dead = opendir (dead_sound_dir.c_str())) == 0) {
2665 while ((dentry = readdir (dead)) != 0) {
2667 /* avoid '.' and '..' */
2669 if ((dentry->d_name[0] == '.' && dentry->d_name[1] == '\0') ||
2670 (dentry->d_name[2] == '\0' && dentry->d_name[0] == '.' && dentry->d_name[1] == '.')) {
2676 fullpath = dead_sound_dir;
2678 fullpath += dentry->d_name;
2680 if (stat (fullpath.c_str(), &statbuf)) {
2684 if (!S_ISREG (statbuf.st_mode)) {
2688 if (unlink (fullpath.c_str())) {
2689 error << string_compose (_("cannot remove dead sound file %1 (%2)"),
2690 fullpath, strerror (errno))
2694 rep.paths.push_back (dentry->d_name);
2695 rep.space += statbuf.st_size;
2706 Session::set_dirty ()
2708 bool was_dirty = dirty();
2710 _state_of_the_state = StateOfTheState (_state_of_the_state | Dirty);
2714 DirtyChanged(); /* EMIT SIGNAL */
2720 Session::set_clean ()
2722 bool was_dirty = dirty();
2724 _state_of_the_state = Clean;
2728 DirtyChanged(); /* EMIT SIGNAL */
2733 Session::set_deletion_in_progress ()
2735 _state_of_the_state = StateOfTheState (_state_of_the_state | Deletion);
2739 Session::clear_deletion_in_progress ()
2741 _state_of_the_state = StateOfTheState (_state_of_the_state & (~Deletion));
2745 Session::add_controllable (boost::shared_ptr<Controllable> c)
2747 /* this adds a controllable to the list managed by the Session.
2748 this is a subset of those managed by the Controllable class
2749 itself, and represents the only ones whose state will be saved
2750 as part of the session.
2753 Glib::Mutex::Lock lm (controllables_lock);
2754 controllables.insert (c);
2757 struct null_deleter { void operator()(void const *) const {} };
2760 Session::remove_controllable (Controllable* c)
2762 if (_state_of_the_state | Deletion) {
2766 Glib::Mutex::Lock lm (controllables_lock);
2768 Controllables::iterator x = controllables.find (boost::shared_ptr<Controllable>(c, null_deleter()));
2770 if (x != controllables.end()) {
2771 controllables.erase (x);
2775 boost::shared_ptr<Controllable>
2776 Session::controllable_by_id (const PBD::ID& id)
2778 Glib::Mutex::Lock lm (controllables_lock);
2780 for (Controllables::iterator i = controllables.begin(); i != controllables.end(); ++i) {
2781 if ((*i)->id() == id) {
2786 return boost::shared_ptr<Controllable>();
2789 boost::shared_ptr<Controllable>
2790 Session::controllable_by_descriptor (const ControllableDescriptor& desc)
2792 boost::shared_ptr<Controllable> c;
2793 boost::shared_ptr<Route> r;
2795 switch (desc.top_level_type()) {
2796 case ControllableDescriptor::NamedRoute:
2798 std::string str = desc.top_level_name();
2799 if (str == "master") {
2801 } else if (str == "control" || str == "listen") {
2804 r = route_by_name (desc.top_level_name());
2809 case ControllableDescriptor::RemoteControlID:
2810 r = route_by_remote_id (desc.rid());
2818 switch (desc.subtype()) {
2819 case ControllableDescriptor::Gain:
2820 c = r->gain_control ();
2823 case ControllableDescriptor::Solo:
2824 c = r->solo_control();
2827 case ControllableDescriptor::Mute:
2828 c = r->mute_control();
2831 case ControllableDescriptor::Recenable:
2833 boost::shared_ptr<Track> t = boost::dynamic_pointer_cast<Track>(r);
2836 c = t->rec_enable_control ();
2841 case ControllableDescriptor::Pan:
2842 /* XXX pan control */
2845 case ControllableDescriptor::Balance:
2846 /* XXX simple pan control */
2849 case ControllableDescriptor::PluginParameter:
2851 uint32_t plugin = desc.target (0);
2852 uint32_t parameter_index = desc.target (1);
2854 /* revert to zero based counting */
2860 if (parameter_index > 0) {
2864 boost::shared_ptr<Processor> p = r->nth_plugin (plugin);
2867 c = boost::dynamic_pointer_cast<ARDOUR::AutomationControl>(
2868 p->control(Evoral::Parameter(PluginAutomation, 0, parameter_index)));
2873 case ControllableDescriptor::SendGain:
2875 uint32_t send = desc.target (0);
2877 /* revert to zero-based counting */
2883 boost::shared_ptr<Processor> p = r->nth_send (send);
2886 boost::shared_ptr<Send> s = boost::dynamic_pointer_cast<Send>(p);
2887 boost::shared_ptr<Amp> a = s->amp();
2890 c = s->amp()->gain_control();
2897 /* relax and return a null pointer */
2905 Session::add_instant_xml (XMLNode& node, bool write_to_config)
2908 Stateful::add_instant_xml (node, _path);
2911 if (write_to_config) {
2912 Config->add_instant_xml (node);
2917 Session::instant_xml (const string& node_name)
2919 return Stateful::instant_xml (node_name, _path);
2923 Session::save_history (string snapshot_name)
2931 if (snapshot_name.empty()) {
2932 snapshot_name = _current_snapshot_name;
2935 const string history_filename = legalize_for_path (snapshot_name) + history_suffix;
2936 const string backup_filename = history_filename + backup_suffix;
2937 const sys::path xml_path = _session_dir->root_path() / history_filename;
2938 const sys::path backup_path = _session_dir->root_path() / backup_filename;
2940 if (sys::exists (xml_path)) {
2943 sys::rename (xml_path, backup_path);
2945 catch (const sys::filesystem_error& err)
2947 error << _("could not backup old history file, current history not saved") << endmsg;
2952 if (!Config->get_save_history() || Config->get_saved_history_depth() < 0) {
2956 tree.set_root (&_history.get_state (Config->get_saved_history_depth()));
2958 if (!tree.write (xml_path.to_string()))
2960 error << string_compose (_("history could not be saved to %1"), xml_path.to_string()) << endmsg;
2964 sys::remove (xml_path);
2965 sys::rename (backup_path, xml_path);
2967 catch (const sys::filesystem_error& err)
2969 error << string_compose (_("could not restore history file from backup %1 (%2)"),
2970 backup_path.to_string(), err.what()) << endmsg;
2980 Session::restore_history (string snapshot_name)
2984 if (snapshot_name.empty()) {
2985 snapshot_name = _current_snapshot_name;
2988 const string xml_filename = legalize_for_path (snapshot_name) + history_suffix;
2989 const sys::path xml_path = _session_dir->root_path() / xml_filename;
2991 info << "Loading history from " << xml_path.to_string() << endmsg;
2993 if (!sys::exists (xml_path)) {
2994 info << string_compose (_("%1: no history file \"%2\" for this session."),
2995 _name, xml_path.to_string()) << endmsg;
2999 if (!tree.read (xml_path.to_string())) {
3000 error << string_compose (_("Could not understand session history file \"%1\""),
3001 xml_path.to_string()) << endmsg;
3008 for (XMLNodeConstIterator it = tree.root()->children().begin(); it != tree.root()->children().end(); it++) {
3011 UndoTransaction* ut = new UndoTransaction ();
3014 ut->set_name(t->property("name")->value());
3015 stringstream ss(t->property("tv-sec")->value());
3017 ss.str(t->property("tv-usec")->value());
3019 ut->set_timestamp(tv);
3021 for (XMLNodeConstIterator child_it = t->children().begin();
3022 child_it != t->children().end(); child_it++)
3024 XMLNode *n = *child_it;
3027 if (n->name() == "MementoCommand" ||
3028 n->name() == "MementoUndoCommand" ||
3029 n->name() == "MementoRedoCommand") {
3031 if ((c = memento_command_factory(n))) {
3035 } else if (n->name() == "DeltaCommand") {
3036 PBD::ID id(n->property("midi-source")->value());
3037 boost::shared_ptr<MidiSource> midi_source =
3038 boost::dynamic_pointer_cast<MidiSource, Source>(source_by_id(id));
3040 ut->add_command(new MidiModel::DeltaCommand(midi_source->model(), *n));
3042 error << _("Failed to downcast MidiSource for DeltaCommand") << endmsg;
3045 } else if (n->name() == "DiffCommand") {
3046 PBD::ID id(n->property("midi-source")->value());
3047 boost::shared_ptr<MidiSource> midi_source =
3048 boost::dynamic_pointer_cast<MidiSource, Source>(source_by_id(id));
3050 ut->add_command(new MidiModel::DiffCommand(midi_source->model(), *n));
3052 error << _("Failed to downcast MidiSource for DeltaCommand") << endmsg;
3055 } else if (n->name() == "StatefulDiffCommand") {
3056 if ((c = stateful_diff_command_factory (n))) {
3057 ut->add_command (c);
3060 error << string_compose(_("Couldn't figure out how to make a Command out of a %1 XMLNode."), n->name()) << endmsg;
3071 Session::config_changed (std::string p, bool ours)
3077 if (p == "seamless-loop") {
3079 } else if (p == "rf-speed") {
3081 } else if (p == "auto-loop") {
3083 } else if (p == "auto-input") {
3085 if (Config->get_monitoring_model() == HardwareMonitoring && transport_rolling()) {
3086 /* auto-input only makes a difference if we're rolling */
3088 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
3090 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
3091 if ((*i)->record_enabled ()) {
3092 (*i)->monitor_input (!config.get_auto_input());
3097 } else if (p == "punch-in") {
3101 if ((location = _locations.auto_punch_location()) != 0) {
3103 if (config.get_punch_in ()) {
3104 replace_event (SessionEvent::PunchIn, location->start());
3106 remove_event (location->start(), SessionEvent::PunchIn);
3110 } else if (p == "punch-out") {
3114 if ((location = _locations.auto_punch_location()) != 0) {
3116 if (config.get_punch_out()) {
3117 replace_event (SessionEvent::PunchOut, location->end());
3119 clear_events (SessionEvent::PunchOut);
3123 } else if (p == "edit-mode") {
3125 Glib::Mutex::Lock lm (playlists->lock);
3127 for (SessionPlaylists::List::iterator i = playlists->playlists.begin(); i != playlists->playlists.end(); ++i) {
3128 (*i)->set_edit_mode (Config->get_edit_mode ());
3131 } else if (p == "use-video-sync") {
3133 waiting_for_sync_offset = config.get_use_video_sync();
3135 } else if (p == "mmc-control") {
3137 //poke_midi_thread ();
3139 } else if (p == "mmc-device-id" || p == "mmc-receive-id") {
3142 mmc->set_receive_device_id (Config->get_mmc_receive_device_id());
3145 } else if (p == "mmc-send-id") {
3148 mmc->set_send_device_id (Config->get_mmc_send_device_id());
3151 } else if (p == "midi-control") {
3153 //poke_midi_thread ();
3155 } else if (p == "raid-path") {
3157 setup_raid_path (config.get_raid_path());
3159 } else if (p == "timecode-format") {
3163 } else if (p == "video-pullup") {
3167 } else if (p == "seamless-loop") {
3169 if (play_loop && transport_rolling()) {
3170 // to reset diskstreams etc
3171 request_play_loop (true);
3174 } else if (p == "rf-speed") {
3176 cumulative_rf_motion = 0;
3179 } else if (p == "click-sound") {
3181 setup_click_sounds (1);
3183 } else if (p == "click-emphasis-sound") {
3185 setup_click_sounds (-1);
3187 } else if (p == "clicking") {
3189 if (Config->get_clicking()) {
3190 if (_click_io && click_data) { // don't require emphasis data
3197 } else if (p == "send-mtc") {
3199 /* only set the internal flag if we have
3203 if (_mtc_port != 0) {
3204 session_send_mtc = Config->get_send_mtc();
3205 if (session_send_mtc) {
3206 /* mark us ready to send */
3207 next_quarter_frame_to_send = 0;
3210 session_send_mtc = false;
3213 } else if (p == "send-mmc") {
3215 /* only set the internal flag if we have
3219 if (_mmc_port != 0) {
3220 session_send_mmc = Config->get_send_mmc();
3223 session_send_mmc = false;
3226 } else if (p == "midi-feedback") {
3228 /* only set the internal flag if we have
3232 if (_mtc_port != 0) {
3233 session_midi_feedback = Config->get_midi_feedback();
3236 } else if (p == "jack-time-master") {
3238 engine().reset_timebase ();
3240 } else if (p == "native-file-header-format") {
3242 if (!first_file_header_format_reset) {
3243 reset_native_file_format ();
3246 first_file_header_format_reset = false;
3248 } else if (p == "native-file-data-format") {
3250 if (!first_file_data_format_reset) {
3251 reset_native_file_format ();
3254 first_file_data_format_reset = false;
3256 } else if (p == "external-sync") {
3257 if (!config.get_external_sync()) {
3258 drop_sync_source ();
3260 switch_to_sync_source (config.get_sync_source());
3262 } else if (p == "remote-model") {
3263 set_remote_control_ids ();
3264 } else if (p == "denormal-model") {
3266 } else if (p == "history-depth") {
3267 set_history_depth (Config->get_history_depth());
3268 } else if (p == "sync-all-route-ordering") {
3269 sync_order_keys ("session");
3270 } else if (p == "initial-program-change") {
3272 if (_mmc_port && Config->get_initial_program_change() >= 0) {
3275 buf[0] = MIDI::program; // channel zero by default
3276 buf[1] = (Config->get_initial_program_change() & 0x7f);
3278 _mmc_port->midimsg (buf, sizeof (buf), 0);
3280 } else if (p == "initial-program-change") {
3282 if (_mmc_port && Config->get_initial_program_change() >= 0) {
3283 MIDI::byte* buf = new MIDI::byte[2];
3285 buf[0] = MIDI::program; // channel zero by default
3286 buf[1] = (Config->get_initial_program_change() & 0x7f);
3287 // deliver_midi (_mmc_port, buf, 2);
3289 } else if (p == "solo-mute-override") {
3290 // catch_up_on_solo_mute_override ();
3291 } else if (p == "listen-position") {
3292 listen_position_changed ();
3293 } else if (p == "solo-control-is-listen-control") {
3294 solo_control_mode_changed ();
3302 Session::set_history_depth (uint32_t d)
3304 _history.set_depth (d);