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 _session_range_location = new Location (0, 0, _("session"), Location::Flags (Location::IsSessionRange));
182 g_atomic_int_set (&_record_status, Disabled);
183 loop_changing = false;
186 _last_roll_location = 0;
187 _last_record_location = 0;
188 pending_locate_frame = 0;
189 pending_locate_roll = false;
190 pending_locate_flush = false;
191 state_was_pending = false;
193 outbound_mtc_timecode_frame = 0;
194 next_quarter_frame_to_send = -1;
195 current_block_size = 0;
196 solo_update_disabled = false;
197 _have_captured = false;
198 _worst_output_latency = 0;
199 _worst_input_latency = 0;
200 _worst_track_latency = 0;
201 _state_of_the_state = StateOfTheState(CannotSave|InitialConnecting|Loading);
202 _was_seamless = Config->get_seamless_loop ();
204 session_send_mmc = false;
205 session_send_mtc = false;
206 g_atomic_int_set (&_playback_load, 100);
207 g_atomic_int_set (&_capture_load, 100);
208 g_atomic_int_set (&_playback_load_min, 100);
209 g_atomic_int_set (&_capture_load_min, 100);
212 pending_abort = false;
213 destructive_index = 0;
214 first_file_data_format_reset = true;
215 first_file_header_format_reset = true;
216 post_export_sync = false;
219 AudioDiskstream::allocate_working_buffers();
221 /* default short fade = 15ms */
223 Crossfade::set_short_xfade_length ((nframes_t) floor (config.get_short_xfade_seconds() * frame_rate()));
224 SndFileSource::setup_standard_crossfades (*this, frame_rate());
226 last_mmc_step.tv_sec = 0;
227 last_mmc_step.tv_usec = 0;
230 /* click sounds are unset by default, which causes us to internal
231 waveforms for clicks.
235 click_emphasis_length = 0;
238 process_function = &Session::process_with_events;
240 if (config.get_use_video_sync()) {
241 waiting_for_sync_offset = true;
243 waiting_for_sync_offset = false;
246 last_timecode_when = 0;
247 _timecode_offset = 0;
248 _timecode_offset_negative = true;
249 last_timecode_valid = false;
253 last_rr_session_dir = session_dirs.begin();
254 refresh_disk_space ();
256 // set_default_fade (0.2, 5.0); /* steepness, millisecs */
260 average_slave_delta = 1800; // !!! why 1800 ????
261 have_first_delta_accumulator = false;
262 delta_accumulator_cnt = 0;
263 _slave_state = Stopped;
265 _engine.GraphReordered.connect_same_thread (*this, boost::bind (&Session::graph_reordered, this));
267 /* These are all static "per-class" signals */
269 SourceFactory::SourceCreated.connect_same_thread (*this, boost::bind (&Session::add_source, this, _1));
270 PlaylistFactory::PlaylistCreated.connect_same_thread (*this, boost::bind (&Session::add_playlist, this, _1, _2));
271 AutomationList::AutomationListCreated.connect_same_thread (*this, boost::bind (&Session::add_automation_list, this, _1));
272 Controllable::Destroyed.connect_same_thread (*this, boost::bind (&Session::remove_controllable, this, _1));
273 IO::PortCountChanged.connect_same_thread (*this, boost::bind (&Session::ensure_buffers, this, _1));
275 /* stop IO objects from doing stuff until we're ready for them */
277 Delivery::disable_panners ();
278 IO::disable_connecting ();
282 Session::second_stage_init ()
284 AudioFileSource::set_peak_dir (_session_dir->peak_path().to_string());
287 if (load_state (_current_snapshot_name)) {
290 remove_empty_sounds ();
293 if (_butler->start_thread()) {
297 if (start_midi_thread ()) {
301 // set_state() will call setup_raid_path(), but if it's a new session we need
302 // to call setup_raid_path() here.
305 if (set_state (*state_tree->root(), Stateful::loading_state_version)) {
309 setup_raid_path(_path);
312 /* we can't save till after ::when_engine_running() is called,
313 because otherwise we save state with no connections made.
314 therefore, we reset _state_of_the_state because ::set_state()
315 will have cleared it.
317 we also have to include Loading so that any events that get
318 generated between here and the end of ::when_engine_running()
319 will be processed directly rather than queued.
322 _state_of_the_state = StateOfTheState (_state_of_the_state|CannotSave|Loading);
325 _locations.changed.connect_same_thread (*this, boost::bind (&Session::locations_changed, this));
326 _locations.added.connect_same_thread (*this, boost::bind (&Session::locations_added, this, _1));
327 setup_click_sounds (0);
328 setup_midi_control ();
330 /* Pay attention ... */
332 _engine.Halted.connect_same_thread (*this, boost::bind (&Session::engine_halted, this));
333 _engine.Xrun.connect_same_thread (*this, boost::bind (&Session::xrun_recovery, this));
336 when_engine_running ();
339 /* handle this one in a different way than all others, so that its clear what happened */
341 catch (AudioEngine::PortRegistrationFailure& err) {
342 error << err.what() << endmsg;
350 BootMessage (_("Reset Remote Controls"));
352 send_full_time_code (0);
353 _engine.transport_locate (0);
354 deliver_mmc (MIDI::MachineControl::cmdMmcReset, 0);
355 deliver_mmc (MIDI::MachineControl::cmdLocate, 0);
357 MidiClockTicker::instance().set_session (this);
358 MIDI::Name::MidiPatchManager::instance().set_session (this);
360 /* initial program change will be delivered later; see ::config_changed() */
362 BootMessage (_("Reset Control Protocols"));
364 ControlProtocolManager::instance().set_session (this);
366 config.set_end_marker_is_free (_is_new);
368 _state_of_the_state = Clean;
370 DirtyChanged (); /* EMIT SIGNAL */
372 if (state_was_pending) {
373 save_state (_current_snapshot_name);
374 remove_pending_capture_state ();
375 state_was_pending = false;
378 BootMessage (_("Session loading complete"));
384 Session::raid_path () const
386 SearchPath raid_search_path;
388 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
389 raid_search_path += sys::path((*i).path);
392 return raid_search_path.to_string ();
396 Session::setup_raid_path (string path)
405 session_dirs.clear ();
407 SearchPath search_path(path);
408 SearchPath sound_search_path;
409 SearchPath midi_search_path;
411 for (SearchPath::const_iterator i = search_path.begin(); i != search_path.end(); ++i) {
412 sp.path = (*i).to_string ();
413 sp.blocks = 0; // not needed
414 session_dirs.push_back (sp);
416 SessionDirectory sdir(sp.path);
418 sound_search_path += sdir.sound_path ();
419 midi_search_path += sdir.midi_path ();
422 // set the search path for each data type
423 FileSource::set_search_path (DataType::AUDIO, sound_search_path.to_string ());
424 SMFSource::set_search_path (DataType::MIDI, midi_search_path.to_string ());
426 // reset the round-robin soundfile path thingie
427 last_rr_session_dir = session_dirs.begin();
431 Session::path_is_within_session (const std::string& path)
433 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
434 if (path.find ((*i).path) == 0) {
442 Session::ensure_subdirs ()
446 dir = session_directory().peak_path().to_string();
448 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
449 error << string_compose(_("Session: cannot create session peakfile folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
453 dir = session_directory().sound_path().to_string();
455 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
456 error << string_compose(_("Session: cannot create session sounds dir \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
460 dir = session_directory().midi_path().to_string();
462 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
463 error << string_compose(_("Session: cannot create session midi dir \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
467 dir = session_directory().dead_sound_path().to_string();
469 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
470 error << string_compose(_("Session: cannot create session dead sounds folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
474 dir = session_directory().export_path().to_string();
476 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
477 error << string_compose(_("Session: cannot create session export folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
481 dir = analysis_dir ();
483 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
484 error << string_compose(_("Session: cannot create session analysis folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
492 Session::create (const string& mix_template, nframes_t initial_length, BusProfile* bus_profile)
495 if (g_mkdir_with_parents (_path.c_str(), 0755) < 0) {
496 error << string_compose(_("Session: cannot create session folder \"%1\" (%2)"), _path, strerror (errno)) << endmsg;
500 if (ensure_subdirs ()) {
504 if (!mix_template.empty()) {
505 std::string in_path = mix_template;
507 ifstream in(in_path.c_str());
510 string out_path = _path;
512 out_path += statefile_suffix;
514 ofstream out(out_path.c_str());
521 error << string_compose (_("Could not open %1 for writing mix template"), out_path)
527 error << string_compose (_("Could not open mix template %1 for reading"), in_path)
534 /* Instantiate metadata */
536 _metadata = new SessionMetadata ();
538 /* set initial start + end point */
540 _session_range_location->set (0, initial_length);
541 _locations.add (_session_range_location);
543 _state_of_the_state = Clean;
545 /* set up Master Out and Control Out if necessary */
551 ChanCount count(DataType::AUDIO, bus_profile->master_out_channels);
553 if (bus_profile->master_out_channels) {
554 Route* rt = new Route (*this, _("master"), Route::MasterOut, DataType::AUDIO);
559 boost_debug_shared_ptr_mark_interesting (rt, "Route");
560 boost::shared_ptr<Route> r (rt);
561 r->input()->ensure_io (count, false, this);
562 r->output()->ensure_io (count, false, this);
563 r->set_remote_control_id (control_id++);
567 if (Config->get_use_monitor_bus()) {
568 Route* rt = new Route (*this, _("monitor"), Route::MonitorOut, DataType::AUDIO);
573 boost_debug_shared_ptr_mark_interesting (rt, "Route");
574 boost::shared_ptr<Route> r (rt);
575 r->input()->ensure_io (count, false, this);
576 r->output()->ensure_io (count, false, this);
577 r->set_remote_control_id (control_id);
583 /* prohibit auto-connect to master, because there isn't one */
584 bus_profile->output_ac = AutoConnectOption (bus_profile->output_ac & ~AutoConnectMaster);
588 add_routes (rl, false);
591 /* this allows the user to override settings with an environment variable.
594 if (no_auto_connect()) {
595 bus_profile->input_ac = AutoConnectOption (0);
596 bus_profile->output_ac = AutoConnectOption (0);
599 Config->set_input_auto_connect (bus_profile->input_ac);
600 Config->set_output_auto_connect (bus_profile->output_ac);
610 Session::load_diskstreams (const XMLNode& node)
613 XMLNodeConstIterator citer;
615 clist = node.children();
617 for (citer = clist.begin(); citer != clist.end(); ++citer) {
620 /* diskstreams added automatically by DiskstreamCreated handler */
621 if ((*citer)->name() == "AudioDiskstream" || (*citer)->name() == "DiskStream") {
622 AudioDiskstream* dsp (new AudioDiskstream (*this, **citer));
623 boost::shared_ptr<AudioDiskstream> dstream (dsp);
624 add_diskstream (dstream);
625 } else if ((*citer)->name() == "MidiDiskstream") {
626 boost::shared_ptr<MidiDiskstream> dstream (new MidiDiskstream (*this, **citer));
627 add_diskstream (dstream);
629 error << _("Session: unknown diskstream type in XML") << endmsg;
633 catch (failed_constructor& err) {
634 error << _("Session: could not load diskstream via XML state") << endmsg;
643 Session::maybe_write_autosave()
645 if (dirty() && record_status() != Recording) {
646 save_state("", true);
651 Session::remove_pending_capture_state ()
653 sys::path pending_state_file_path(_session_dir->root_path());
655 pending_state_file_path /= legalize_for_path (_current_snapshot_name) + pending_suffix;
659 sys::remove (pending_state_file_path);
661 catch(sys::filesystem_error& ex)
663 error << string_compose(_("Could remove pending capture state at path \"%1\" (%2)"),
664 pending_state_file_path.to_string(), ex.what()) << endmsg;
668 /** Rename a state file.
669 * @param snapshot_name Snapshot name.
672 Session::rename_state (string old_name, string new_name)
674 if (old_name == _current_snapshot_name || old_name == _name) {
675 /* refuse to rename the current snapshot or the "main" one */
679 const string old_xml_filename = legalize_for_path (old_name) + statefile_suffix;
680 const string new_xml_filename = legalize_for_path (new_name) + statefile_suffix;
682 const sys::path old_xml_path = _session_dir->root_path() / old_xml_filename;
683 const sys::path new_xml_path = _session_dir->root_path() / new_xml_filename;
687 sys::rename (old_xml_path, new_xml_path);
689 catch (const sys::filesystem_error& err)
691 error << string_compose(_("could not rename snapshot %1 to %2 (%3)"),
692 old_name, new_name, err.what()) << endmsg;
696 /** Remove a state file.
697 * @param snapshot_name Snapshot name.
700 Session::remove_state (string snapshot_name)
702 if (snapshot_name == _current_snapshot_name || snapshot_name == _name) {
703 // refuse to remove the current snapshot or the "main" one
707 sys::path xml_path(_session_dir->root_path());
709 xml_path /= legalize_for_path (snapshot_name) + statefile_suffix;
711 if (!create_backup_file (xml_path)) {
712 // don't remove it if a backup can't be made
713 // create_backup_file will log the error.
718 sys::remove (xml_path);
721 #ifdef HAVE_JACK_SESSION
723 Session::jack_session_event (jack_session_event_t * event)
725 if (save_state ("jacksession_snap")) {
726 event->flags = JackSessionSaveError;
728 sys::path xml_path (_session_dir->root_path());
729 xml_path /= legalize_for_path ("jacksession_snap") + statefile_suffix;
731 string cmd ("PROG_NAME -U ");
732 cmd += event->client_uuid;
734 cmd += xml_path.to_string();
737 event->command_line = strdup (cmd.c_str());
740 jack_session_reply (_engine.jack(), event);
742 if (event->type == JackSessionSaveAndQuit) {
743 // TODO: make ardour quit.
746 jack_session_event_free( event );
751 Session::save_state (string snapshot_name, bool pending)
754 sys::path xml_path(_session_dir->root_path());
756 if (!_writable || (_state_of_the_state & CannotSave)) {
760 if (!_engine.connected ()) {
761 error << string_compose (_("the %1 audio engine is not connected and state saving would lose all I/O connections. Session not saved"),
767 /* tell sources we're saving first, in case they write out to a new file
768 * which should be saved with the state rather than the old one */
769 for (SourceMap::const_iterator i = sources.begin(); i != sources.end(); ++i)
770 i->second->session_saved();
772 tree.set_root (&get_state());
774 if (snapshot_name.empty()) {
775 snapshot_name = _current_snapshot_name;
780 /* proper save: use statefile_suffix (.ardour in English) */
782 xml_path /= legalize_for_path (snapshot_name) + statefile_suffix;
784 /* make a backup copy of the old file */
786 if (sys::exists(xml_path) && !create_backup_file (xml_path)) {
787 // create_backup_file will log the error
793 /* pending save: use pending_suffix (.pending in English) */
794 xml_path /= legalize_for_path (snapshot_name) + pending_suffix;
797 sys::path tmp_path(_session_dir->root_path());
799 tmp_path /= legalize_for_path (snapshot_name) + temp_suffix;
801 // cerr << "actually writing state to " << xml_path.to_string() << endl;
803 if (!tree.write (tmp_path.to_string())) {
804 error << string_compose (_("state could not be saved to %1"), tmp_path.to_string()) << endmsg;
805 sys::remove (tmp_path);
810 if (rename (tmp_path.to_string().c_str(), xml_path.to_string().c_str()) != 0) {
811 error << string_compose (_("could not rename temporary session file %1 to %2"),
812 tmp_path.to_string(), xml_path.to_string()) << endmsg;
813 sys::remove (tmp_path);
820 save_history (snapshot_name);
822 bool was_dirty = dirty();
824 _state_of_the_state = StateOfTheState (_state_of_the_state & ~Dirty);
827 DirtyChanged (); /* EMIT SIGNAL */
830 StateSaved (snapshot_name); /* EMIT SIGNAL */
837 Session::restore_state (string snapshot_name)
839 if (load_state (snapshot_name) == 0) {
840 set_state (*state_tree->root(), Stateful::loading_state_version);
847 Session::load_state (string snapshot_name)
852 state_was_pending = false;
854 /* check for leftover pending state from a crashed capture attempt */
856 sys::path xmlpath(_session_dir->root_path());
857 xmlpath /= legalize_for_path (snapshot_name) + pending_suffix;
859 if (sys::exists (xmlpath)) {
861 /* there is pending state from a crashed capture attempt */
863 if (*AskAboutPendingState()) {
864 state_was_pending = true;
868 if (!state_was_pending) {
869 xmlpath = _session_dir->root_path();
870 xmlpath /= legalize_for_path (snapshot_name) + statefile_suffix;
873 if (!sys::exists (xmlpath)) {
874 error << string_compose(_("%1: session state information file \"%2\" doesn't exist!"), _name, xmlpath.to_string()) << endmsg;
878 state_tree = new XMLTree;
882 /* writable() really reflects the whole folder, but if for any
883 reason the session state file can't be written to, still
887 if (::access (xmlpath.to_string().c_str(), W_OK) != 0) {
891 if (!state_tree->read (xmlpath.to_string())) {
892 error << string_compose(_("Could not understand ardour file %1"), xmlpath.to_string()) << endmsg;
898 XMLNode& root (*state_tree->root());
900 if (root.name() != X_("Session")) {
901 error << string_compose (_("Session file %1 is not a session"), xmlpath.to_string()) << endmsg;
907 const XMLProperty* prop;
909 if ((prop = root.property ("version")) == 0) {
910 /* no version implies very old version of Ardour */
911 Stateful::loading_state_version = 1000;
917 sscanf (prop->value().c_str(), "%d.%d.%d", &major, &minor, µ);
918 Stateful::loading_state_version = (major * 1000) + minor;
921 if (Stateful::loading_state_version < CURRENT_SESSION_FILE_VERSION) {
923 sys::path backup_path(_session_dir->root_path());
925 backup_path /= legalize_for_path (snapshot_name) + "-1" + statefile_suffix;
927 // only create a backup once
928 if (sys::exists (backup_path)) {
932 info << string_compose (_("Copying old session file %1 to %2\nUse %2 with %3 versions before 2.0 from now on"),
933 xmlpath.to_string(), backup_path.to_string(), PROGRAM_NAME)
938 sys::copy_file (xmlpath, backup_path);
940 catch(sys::filesystem_error& ex)
942 error << string_compose (_("Unable to make backup of state file %1 (%2)"),
943 xmlpath.to_string(), ex.what())
953 Session::load_options (const XMLNode& node)
955 LocaleGuard lg (X_("POSIX"));
956 config.set_variables (node);
967 Session::get_template()
969 /* if we don't disable rec-enable, diskstreams
970 will believe they need to store their capture
971 sources in their state node.
974 disable_record (false);
980 Session::state(bool full_state)
982 XMLNode* node = new XMLNode("Session");
985 // store libardour version, just in case
987 snprintf(buf, sizeof(buf), "%d.%d.%d", libardour3_major_version, libardour3_minor_version, libardour3_micro_version);
988 node->add_property("version", string(buf));
990 /* store configuration settings */
994 node->add_property ("name", _name);
995 snprintf (buf, sizeof (buf), "%" PRId32, _nominal_frame_rate);
996 node->add_property ("sample-rate", buf);
998 if (session_dirs.size() > 1) {
1002 vector<space_and_path>::iterator i = session_dirs.begin();
1003 vector<space_and_path>::iterator next;
1005 ++i; /* skip the first one */
1009 while (i != session_dirs.end()) {
1013 if (next != session_dirs.end()) {
1023 child = node->add_child ("Path");
1024 child->add_content (p);
1028 /* save the ID counter */
1030 snprintf (buf, sizeof (buf), "%" PRIu64, ID::counter());
1031 node->add_property ("id-counter", buf);
1033 /* various options */
1035 node->add_child_nocopy (config.get_variables ());
1037 node->add_child_nocopy (_metadata->get_state());
1039 child = node->add_child ("Sources");
1042 Glib::Mutex::Lock sl (source_lock);
1044 for (SourceMap::iterator siter = sources.begin(); siter != sources.end(); ++siter) {
1046 /* Don't save information about non-destructive file sources that are empty */
1047 /* FIXME: MIDI breaks if this is made FileSource like it should be... */
1049 boost::shared_ptr<AudioFileSource> fs;
1050 if ((fs = boost::dynamic_pointer_cast<AudioFileSource> (siter->second)) != 0) {
1051 if (!fs->destructive()) {
1052 if (fs->length(fs->timeline_position()) == 0) {
1058 child->add_child_nocopy (siter->second->get_state());
1062 child = node->add_child ("Regions");
1065 Glib::Mutex::Lock rl (region_lock);
1066 const RegionFactory::RegionMap& region_map (RegionFactory::all_regions());
1067 for (RegionFactory::RegionMap::const_iterator i = region_map.begin(); i != region_map.end(); ++i) {
1068 boost::shared_ptr<Region> r = i->second;
1069 /* only store regions not attached to playlists */
1070 if (r->playlist() == 0) {
1071 child->add_child_nocopy (r->state (true));
1076 child = node->add_child ("DiskStreams");
1079 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
1080 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
1081 if (!(*i)->hidden()) {
1082 child->add_child_nocopy ((*i)->get_state());
1088 node->add_child_nocopy (_locations.get_state());
1090 // for a template, just create a new Locations, populate it
1091 // with the default start and end, and get the state for that.
1093 Location* range = new Location (0, 0, _("session"), Location::Flags (Location::IsSessionRange));
1094 range->set (0, compute_initial_length ());
1096 node->add_child_nocopy (loc.get_state());
1099 child = node->add_child ("Bundles");
1101 boost::shared_ptr<BundleList> bundles = _bundles.reader ();
1102 for (BundleList::iterator i = bundles->begin(); i != bundles->end(); ++i) {
1103 boost::shared_ptr<UserBundle> b = boost::dynamic_pointer_cast<UserBundle> (*i);
1105 child->add_child_nocopy (b->get_state());
1110 child = node->add_child ("Routes");
1112 boost::shared_ptr<RouteList> r = routes.reader ();
1114 RoutePublicOrderSorter cmp;
1115 RouteList public_order (*r);
1116 public_order.sort (cmp);
1118 /* the sort should have put control outs first */
1121 assert (_monitor_out == public_order.front());
1124 for (RouteList::iterator i = public_order.begin(); i != public_order.end(); ++i) {
1125 if (!(*i)->is_hidden()) {
1127 child->add_child_nocopy ((*i)->get_state());
1129 child->add_child_nocopy ((*i)->get_template());
1135 playlists->add_state (node, full_state);
1137 child = node->add_child ("RouteGroups");
1138 for (list<RouteGroup *>::iterator i = _route_groups.begin(); i != _route_groups.end(); ++i) {
1139 child->add_child_nocopy ((*i)->get_state());
1143 child = node->add_child ("Click");
1144 child->add_child_nocopy (_click_io->state (full_state));
1148 child = node->add_child ("NamedSelections");
1149 for (NamedSelectionList::iterator i = named_selections.begin(); i != named_selections.end(); ++i) {
1151 child->add_child_nocopy ((*i)->get_state());
1156 node->add_child_nocopy (_tempo_map->get_state());
1158 node->add_child_nocopy (get_control_protocol_state());
1161 node->add_child_copy (*_extra_xml);
1168 Session::get_control_protocol_state ()
1170 ControlProtocolManager& cpm (ControlProtocolManager::instance());
1171 return cpm.get_state();
1175 Session::set_state (const XMLNode& node, int version)
1179 const XMLProperty* prop;
1182 _state_of_the_state = StateOfTheState (_state_of_the_state|CannotSave);
1184 if (node.name() != X_("Session")){
1185 fatal << _("programming error: Session: incorrect XML node sent to set_state()") << endmsg;
1189 if ((prop = node.property ("version")) != 0) {
1190 version = atoi (prop->value ()) * 1000;
1193 if ((prop = node.property ("name")) != 0) {
1194 _name = prop->value ();
1197 if ((prop = node.property (X_("sample-rate"))) != 0) {
1199 _nominal_frame_rate = atoi (prop->value());
1201 if (_nominal_frame_rate != _current_frame_rate) {
1202 if (*AskAboutSampleRateMismatch (_nominal_frame_rate, _current_frame_rate)) {
1208 setup_raid_path(_session_dir->root_path().to_string());
1210 if ((prop = node.property (X_("id-counter"))) != 0) {
1212 sscanf (prop->value().c_str(), "%" PRIu64, &x);
1213 ID::init_counter (x);
1215 /* old sessions used a timebased counter, so fake
1216 the startup ID counter based on a standard
1221 ID::init_counter (now);
1225 IO::disable_connecting ();
1227 /* Object loading order:
1232 MIDI Control // relies on data from Options/Config
1246 if ((child = find_named_node (node, "Extra")) != 0) {
1247 _extra_xml = new XMLNode (*child);
1250 if (((child = find_named_node (node, "Options")) != 0)) { /* old style */
1251 load_options (*child);
1252 } else if ((child = find_named_node (node, "Config")) != 0) { /* new style */
1253 load_options (*child);
1255 error << _("Session: XML state has no options section") << endmsg;
1258 if (use_config_midi_ports ()) {
1261 if (version >= 3000) {
1262 if ((child = find_named_node (node, "Metadata")) == 0) {
1263 warning << _("Session: XML state has no metadata section") << endmsg;
1264 } else if (_metadata->set_state (*child, version)) {
1269 if ((child = find_named_node (node, "Locations")) == 0) {
1270 error << _("Session: XML state has no locations section") << endmsg;
1272 } else if (_locations.set_state (*child, version)) {
1278 if ((location = _locations.auto_loop_location()) != 0) {
1279 set_auto_loop_location (location);
1282 if ((location = _locations.auto_punch_location()) != 0) {
1283 set_auto_punch_location (location);
1286 if ((location = _locations.session_range_location()) == 0) {
1287 _locations.add (_session_range_location);
1289 delete _session_range_location;
1290 _session_range_location = location;
1293 AudioFileSource::set_header_position_offset (_session_range_location->start());
1295 if ((child = find_named_node (node, "Sources")) == 0) {
1296 error << _("Session: XML state has no sources section") << endmsg;
1298 } else if (load_sources (*child)) {
1302 if ((child = find_named_node (node, "Regions")) == 0) {
1303 error << _("Session: XML state has no Regions section") << endmsg;
1305 } else if (load_regions (*child)) {
1309 if ((child = find_named_node (node, "Playlists")) == 0) {
1310 error << _("Session: XML state has no playlists section") << endmsg;
1312 } else if (playlists->load (*this, *child)) {
1316 if ((child = find_named_node (node, "UnusedPlaylists")) == 0) {
1318 } else if (playlists->load_unused (*this, *child)) {
1322 if ((child = find_named_node (node, "NamedSelections")) != 0) {
1323 if (load_named_selections (*child)) {
1328 if ((child = find_named_node (node, "DiskStreams")) == 0) {
1329 error << _("Session: XML state has no diskstreams section") << endmsg;
1331 } else if (load_diskstreams (*child)) {
1335 if (version >= 3000) {
1336 if ((child = find_named_node (node, "Bundles")) == 0) {
1337 warning << _("Session: XML state has no bundles section") << endmsg;
1340 /* We can't load Bundles yet as they need to be able
1341 to convert from port names to Port objects, which can't happen until
1343 _bundle_xml_node = new XMLNode (*child);
1347 if ((child = find_named_node (node, "TempoMap")) == 0) {
1348 error << _("Session: XML state has no Tempo Map section") << endmsg;
1350 } else if (_tempo_map->set_state (*child, version)) {
1354 if ((child = find_named_node (node, "Routes")) == 0) {
1355 error << _("Session: XML state has no routes section") << endmsg;
1357 } else if (load_routes (*child, version)) {
1361 if (version >= 3000) {
1363 if ((child = find_named_node (node, "RouteGroups")) == 0) {
1364 error << _("Session: XML state has no route groups section") << endmsg;
1366 } else if (load_route_groups (*child, version)) {
1370 } else if (version < 3000) {
1372 if ((child = find_named_node (node, "EditGroups")) == 0) {
1373 error << _("Session: XML state has no edit groups section") << endmsg;
1375 } else if (load_route_groups (*child, version)) {
1379 if ((child = find_named_node (node, "MixGroups")) == 0) {
1380 error << _("Session: XML state has no mix groups section") << endmsg;
1382 } else if (load_route_groups (*child, version)) {
1387 if ((child = find_named_node (node, "Click")) == 0) {
1388 warning << _("Session: XML state has no click section") << endmsg;
1389 } else if (_click_io) {
1390 _click_io->set_state (*child, version);
1393 if ((child = find_named_node (node, "ControlProtocols")) != 0) {
1394 ControlProtocolManager::instance().set_protocol_states (*child);
1397 /* here beginneth the second phase ... */
1399 StateReady (); /* EMIT SIGNAL */
1408 Session::load_routes (const XMLNode& node, int version)
1411 XMLNodeConstIterator niter;
1412 RouteList new_routes;
1414 nlist = node.children();
1418 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1420 boost::shared_ptr<Route> route (XMLRouteFactory (**niter, version));
1423 error << _("Session: cannot create Route from XML description.") << endmsg;
1427 BootMessage (string_compose (_("Loaded track/bus %1"), route->name()));
1429 new_routes.push_back (route);
1432 add_routes (new_routes, false);
1437 boost::shared_ptr<Route>
1438 Session::XMLRouteFactory (const XMLNode& node, int version)
1440 boost::shared_ptr<Route> ret;
1442 if (node.name() != "Route") {
1446 const XMLProperty* dsprop;
1448 if ((dsprop = node.property (X_("diskstream-id"))) == 0) {
1449 dsprop = node.property (X_("diskstream"));
1452 DataType type = DataType::AUDIO;
1453 const XMLProperty* prop = node.property("default-type");
1456 type = DataType (prop->value());
1459 assert (type != DataType::NIL);
1463 boost::shared_ptr<Diskstream> ds;
1464 PBD::ID diskstream_id (dsprop->value());
1467 /* this wierd hack is used when creating
1468 tracks from a template. We have a special
1469 ID for the diskstream that means "you
1470 should create a new diskstream here, not
1471 look for an old one."
1474 if (diskstream_id != zero) {
1476 ds = diskstream_by_id (diskstream_id);
1479 error << string_compose (_("cannot find diskstream ID %1"), diskstream_id.to_s()) << endmsg;
1486 if (type == DataType::AUDIO) {
1487 track = new AudioTrack (*this, X_("toBeResetFroXML"));
1490 track = new MidiTrack (*this, X_("toBeResetFroXML"));
1493 if (track->init()) {
1499 track->set_diskstream (ds);
1501 track->use_new_diskstream ();
1504 if (track->set_state (node, version)) {
1509 boost_debug_shared_ptr_mark_interesting (track, "Track");
1513 Route* rt = new Route (*this, X_("toBeResetFroXML"));
1515 if (rt->init () == 0 && rt->set_state (node, version) == 0) {
1516 boost_debug_shared_ptr_mark_interesting (rt, "Route");
1527 Session::load_regions (const XMLNode& node)
1530 XMLNodeConstIterator niter;
1531 boost::shared_ptr<Region> region;
1533 nlist = node.children();
1537 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1538 if ((region = XMLRegionFactory (**niter, false)) == 0) {
1539 error << _("Session: cannot create Region from XML description.");
1540 const XMLProperty *name = (**niter).property("name");
1543 error << " " << string_compose (_("Can not load state for region '%1'"), name->value());
1553 boost::shared_ptr<Region>
1554 Session::XMLRegionFactory (const XMLNode& node, bool full)
1556 const XMLProperty* type = node.property("type");
1560 if ( !type || type->value() == "audio" ) {
1562 return boost::shared_ptr<Region>(XMLAudioRegionFactory (node, full));
1564 } else if (type->value() == "midi") {
1566 return boost::shared_ptr<Region>(XMLMidiRegionFactory (node, full));
1570 } catch (failed_constructor& err) {
1571 return boost::shared_ptr<Region> ();
1574 return boost::shared_ptr<Region> ();
1577 boost::shared_ptr<AudioRegion>
1578 Session::XMLAudioRegionFactory (const XMLNode& node, bool /*full*/)
1580 const XMLProperty* prop;
1581 boost::shared_ptr<Source> source;
1582 boost::shared_ptr<AudioSource> as;
1584 SourceList master_sources;
1585 uint32_t nchans = 1;
1588 if (node.name() != X_("Region")) {
1589 return boost::shared_ptr<AudioRegion>();
1592 if ((prop = node.property (X_("channels"))) != 0) {
1593 nchans = atoi (prop->value().c_str());
1596 if ((prop = node.property ("name")) == 0) {
1597 cerr << "no name for this region\n";
1601 if ((prop = node.property (X_("source-0"))) == 0) {
1602 if ((prop = node.property ("source")) == 0) {
1603 error << _("Session: XMLNode describing a AudioRegion is incomplete (no source)") << endmsg;
1604 return boost::shared_ptr<AudioRegion>();
1608 PBD::ID s_id (prop->value());
1610 if ((source = source_by_id (s_id)) == 0) {
1611 error << string_compose(_("Session: XMLNode describing a AudioRegion references an unknown source id =%1"), s_id) << endmsg;
1612 return boost::shared_ptr<AudioRegion>();
1615 as = boost::dynamic_pointer_cast<AudioSource>(source);
1617 error << string_compose(_("Session: XMLNode describing a AudioRegion references a non-audio source id =%1"), s_id) << endmsg;
1618 return boost::shared_ptr<AudioRegion>();
1621 sources.push_back (as);
1623 /* pickup other channels */
1625 for (uint32_t n=1; n < nchans; ++n) {
1626 snprintf (buf, sizeof(buf), X_("source-%d"), n);
1627 if ((prop = node.property (buf)) != 0) {
1629 PBD::ID id2 (prop->value());
1631 if ((source = source_by_id (id2)) == 0) {
1632 error << string_compose(_("Session: XMLNode describing a AudioRegion references an unknown source id =%1"), id2) << endmsg;
1633 return boost::shared_ptr<AudioRegion>();
1636 as = boost::dynamic_pointer_cast<AudioSource>(source);
1638 error << string_compose(_("Session: XMLNode describing a AudioRegion references a non-audio source id =%1"), id2) << endmsg;
1639 return boost::shared_ptr<AudioRegion>();
1641 sources.push_back (as);
1645 for (uint32_t n = 0; n < nchans; ++n) {
1646 snprintf (buf, sizeof(buf), X_("master-source-%d"), n);
1647 if ((prop = node.property (buf)) != 0) {
1649 PBD::ID id2 (prop->value());
1651 if ((source = source_by_id (id2)) == 0) {
1652 error << string_compose(_("Session: XMLNode describing a AudioRegion references an unknown source id =%1"), id2) << endmsg;
1653 return boost::shared_ptr<AudioRegion>();
1656 as = boost::dynamic_pointer_cast<AudioSource>(source);
1658 error << string_compose(_("Session: XMLNode describing a AudioRegion references a non-audio source id =%1"), id2) << endmsg;
1659 return boost::shared_ptr<AudioRegion>();
1661 master_sources.push_back (as);
1666 boost::shared_ptr<AudioRegion> region (boost::dynamic_pointer_cast<AudioRegion> (RegionFactory::create (sources, node)));
1668 /* a final detail: this is the one and only place that we know how long missing files are */
1670 if (region->whole_file()) {
1671 for (SourceList::iterator sx = sources.begin(); sx != sources.end(); ++sx) {
1672 boost::shared_ptr<SilentFileSource> sfp = boost::dynamic_pointer_cast<SilentFileSource> (*sx);
1674 sfp->set_length (region->length());
1679 if (!master_sources.empty()) {
1680 if (master_sources.size() != nchans) {
1681 error << _("Session: XMLNode describing an AudioRegion is missing some master sources; ignored") << endmsg;
1683 region->set_master_sources (master_sources);
1691 catch (failed_constructor& err) {
1692 return boost::shared_ptr<AudioRegion>();
1696 boost::shared_ptr<MidiRegion>
1697 Session::XMLMidiRegionFactory (const XMLNode& node, bool /*full*/)
1699 const XMLProperty* prop;
1700 boost::shared_ptr<Source> source;
1701 boost::shared_ptr<MidiSource> ms;
1703 uint32_t nchans = 1;
1705 if (node.name() != X_("Region")) {
1706 return boost::shared_ptr<MidiRegion>();
1709 if ((prop = node.property (X_("channels"))) != 0) {
1710 nchans = atoi (prop->value().c_str());
1713 if ((prop = node.property ("name")) == 0) {
1714 cerr << "no name for this region\n";
1718 // Multiple midi channels? that's just crazy talk
1719 assert(nchans == 1);
1721 if ((prop = node.property (X_("source-0"))) == 0) {
1722 if ((prop = node.property ("source")) == 0) {
1723 error << _("Session: XMLNode describing a MidiRegion is incomplete (no source)") << endmsg;
1724 return boost::shared_ptr<MidiRegion>();
1728 PBD::ID s_id (prop->value());
1730 if ((source = source_by_id (s_id)) == 0) {
1731 error << string_compose(_("Session: XMLNode describing a MidiRegion references an unknown source id =%1"), s_id) << endmsg;
1732 return boost::shared_ptr<MidiRegion>();
1735 ms = boost::dynamic_pointer_cast<MidiSource>(source);
1737 error << string_compose(_("Session: XMLNode describing a MidiRegion references a non-midi source id =%1"), s_id) << endmsg;
1738 return boost::shared_ptr<MidiRegion>();
1741 sources.push_back (ms);
1744 boost::shared_ptr<MidiRegion> region (boost::dynamic_pointer_cast<MidiRegion> (RegionFactory::create (sources, node)));
1745 /* a final detail: this is the one and only place that we know how long missing files are */
1747 if (region->whole_file()) {
1748 for (SourceList::iterator sx = sources.begin(); sx != sources.end(); ++sx) {
1749 boost::shared_ptr<SilentFileSource> sfp = boost::dynamic_pointer_cast<SilentFileSource> (*sx);
1751 sfp->set_length (region->length());
1759 catch (failed_constructor& err) {
1760 return boost::shared_ptr<MidiRegion>();
1765 Session::get_sources_as_xml ()
1768 XMLNode* node = new XMLNode (X_("Sources"));
1769 Glib::Mutex::Lock lm (source_lock);
1771 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ++i) {
1772 node->add_child_nocopy (i->second->get_state());
1779 Session::path_from_region_name (DataType type, string name, string identifier)
1781 char buf[PATH_MAX+1];
1783 SessionDirectory sdir(get_best_session_directory_for_new_source());
1784 sys::path source_dir = ((type == DataType::AUDIO)
1785 ? sdir.sound_path() : sdir.midi_path());
1787 string ext = ((type == DataType::AUDIO) ? ".wav" : ".mid");
1789 for (n = 0; n < 999999; ++n) {
1790 if (identifier.length()) {
1791 snprintf (buf, sizeof(buf), "%s%s%" PRIu32 "%s", name.c_str(),
1792 identifier.c_str(), n, ext.c_str());
1794 snprintf (buf, sizeof(buf), "%s-%" PRIu32 "%s", name.c_str(),
1798 sys::path source_path = source_dir / buf;
1800 if (!sys::exists (source_path)) {
1801 return source_path.to_string();
1805 error << string_compose (_("cannot create new file from region name \"%1\" with ident = \"%2\": too many existing files with similar names"),
1814 Session::load_sources (const XMLNode& node)
1817 XMLNodeConstIterator niter;
1818 boost::shared_ptr<Source> source;
1820 nlist = node.children();
1824 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1826 if ((source = XMLSourceFactory (**niter)) == 0) {
1827 error << _("Session: cannot create Source from XML description.") << endmsg;
1829 } catch (MissingSource& err) {
1830 warning << _("A sound file is missing. It will be replaced by silence.") << endmsg;
1831 source = SourceFactory::createSilent (*this, **niter, max_frames, _current_frame_rate);
1838 boost::shared_ptr<Source>
1839 Session::XMLSourceFactory (const XMLNode& node)
1841 if (node.name() != "Source") {
1842 return boost::shared_ptr<Source>();
1846 /* note: do peak building in another thread when loading session state */
1847 return SourceFactory::create (*this, node, true);
1850 catch (failed_constructor& err) {
1851 error << string_compose (_("Found a sound file that cannot be used by %1. Talk to the progammers."), PROGRAM_NAME) << endmsg;
1852 return boost::shared_ptr<Source>();
1857 Session::save_template (string template_name)
1861 if (_state_of_the_state & CannotSave) {
1865 sys::path user_template_dir(user_template_directory());
1869 sys::create_directories (user_template_dir);
1871 catch(sys::filesystem_error& ex)
1873 error << string_compose(_("Could not create mix templates directory \"%1\" (%2)"),
1874 user_template_dir.to_string(), ex.what()) << endmsg;
1878 tree.set_root (&get_template());
1880 sys::path template_file_path(user_template_dir);
1881 template_file_path /= template_name + template_suffix;
1883 if (sys::exists (template_file_path))
1885 warning << string_compose(_("Template \"%1\" already exists - new version not created"),
1886 template_file_path.to_string()) << endmsg;
1890 if (!tree.write (template_file_path.to_string())) {
1891 error << _("mix template not saved") << endmsg;
1899 Session::rename_template (string old_name, string new_name)
1901 sys::path old_path (user_template_directory());
1902 old_path /= old_name + template_suffix;
1904 sys::path new_path(user_template_directory());
1905 new_path /= new_name + template_suffix;
1907 if (sys::exists (new_path)) {
1908 warning << string_compose(_("Template \"%1\" already exists - template not renamed"),
1909 new_path.to_string()) << endmsg;
1914 sys::rename (old_path, new_path);
1922 Session::delete_template (string name)
1924 sys::path path = user_template_directory();
1925 path /= name + template_suffix;
1936 Session::refresh_disk_space ()
1939 struct statfs statfsbuf;
1940 vector<space_and_path>::iterator i;
1941 Glib::Mutex::Lock lm (space_lock);
1944 /* get freespace on every FS that is part of the session path */
1946 _total_free_4k_blocks = 0;
1948 for (i = session_dirs.begin(); i != session_dirs.end(); ++i) {
1949 statfs ((*i).path.c_str(), &statfsbuf);
1951 scale = statfsbuf.f_bsize/4096.0;
1953 (*i).blocks = (uint32_t) floor (statfsbuf.f_bavail * scale);
1954 _total_free_4k_blocks += (*i).blocks;
1960 Session::get_best_session_directory_for_new_source ()
1962 vector<space_and_path>::iterator i;
1963 string result = _session_dir->root_path().to_string();
1965 /* handle common case without system calls */
1967 if (session_dirs.size() == 1) {
1971 /* OK, here's the algorithm we're following here:
1973 We want to select which directory to use for
1974 the next file source to be created. Ideally,
1975 we'd like to use a round-robin process so as to
1976 get maximum performance benefits from splitting
1977 the files across multiple disks.
1979 However, in situations without much diskspace, an
1980 RR approach may end up filling up a filesystem
1981 with new files while others still have space.
1982 Its therefore important to pay some attention to
1983 the freespace in the filesystem holding each
1984 directory as well. However, if we did that by
1985 itself, we'd keep creating new files in the file
1986 system with the most space until it was as full
1987 as all others, thus negating any performance
1988 benefits of this RAID-1 like approach.
1990 So, we use a user-configurable space threshold. If
1991 there are at least 2 filesystems with more than this
1992 much space available, we use RR selection between them.
1993 If not, then we pick the filesystem with the most space.
1995 This gets a good balance between the two
1999 refresh_disk_space ();
2001 int free_enough = 0;
2003 for (i = session_dirs.begin(); i != session_dirs.end(); ++i) {
2004 if ((*i).blocks * 4096 >= Config->get_disk_choice_space_threshold()) {
2009 if (free_enough >= 2) {
2010 /* use RR selection process, ensuring that the one
2014 i = last_rr_session_dir;
2017 if (++i == session_dirs.end()) {
2018 i = session_dirs.begin();
2021 if ((*i).blocks * 4096 >= Config->get_disk_choice_space_threshold()) {
2022 if (create_session_directory ((*i).path)) {
2024 last_rr_session_dir = i;
2029 } while (i != last_rr_session_dir);
2033 /* pick FS with the most freespace (and that
2034 seems to actually work ...)
2037 vector<space_and_path> sorted;
2038 space_and_path_ascending_cmp cmp;
2040 sorted = session_dirs;
2041 sort (sorted.begin(), sorted.end(), cmp);
2043 for (i = sorted.begin(); i != sorted.end(); ++i) {
2044 if (create_session_directory ((*i).path)) {
2046 last_rr_session_dir = i;
2056 Session::load_named_selections (const XMLNode& node)
2059 XMLNodeConstIterator niter;
2062 nlist = node.children();
2066 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2068 if ((ns = XMLNamedSelectionFactory (**niter)) == 0) {
2069 error << _("Session: cannot create Named Selection from XML description.") << endmsg;
2077 Session::XMLNamedSelectionFactory (const XMLNode& node)
2080 return new NamedSelection (*this, node);
2083 catch (failed_constructor& err) {
2089 Session::automation_dir () const
2091 return Glib::build_filename (_path, "automation");
2095 Session::analysis_dir () const
2097 return Glib::build_filename (_path, "analysis");
2101 Session::load_bundles (XMLNode const & node)
2103 XMLNodeList nlist = node.children();
2104 XMLNodeConstIterator niter;
2108 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2109 if ((*niter)->name() == "InputBundle") {
2110 add_bundle (boost::shared_ptr<UserBundle> (new UserBundle (**niter, true)));
2111 } else if ((*niter)->name() == "OutputBundle") {
2112 add_bundle (boost::shared_ptr<UserBundle> (new UserBundle (**niter, false)));
2114 error << string_compose(_("Unknown node \"%1\" found in Bundles list from state file"), (*niter)->name()) << endmsg;
2123 Session::load_route_groups (const XMLNode& node, int version)
2125 XMLNodeList nlist = node.children();
2126 XMLNodeConstIterator niter;
2130 if (version >= 3000) {
2132 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2133 if ((*niter)->name() == "RouteGroup") {
2134 RouteGroup* rg = new RouteGroup (*this, "");
2135 add_route_group (rg);
2136 rg->set_state (**niter, version);
2140 } else if (version < 3000) {
2142 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2143 if ((*niter)->name() == "EditGroup" || (*niter)->name() == "MixGroup") {
2144 RouteGroup* rg = new RouteGroup (*this, "");
2145 add_route_group (rg);
2146 rg->set_state (**niter, version);
2155 Session::auto_save()
2157 save_state (_current_snapshot_name);
2161 state_file_filter (const string &str, void */*arg*/)
2163 return (str.length() > strlen(statefile_suffix) &&
2164 str.find (statefile_suffix) == (str.length() - strlen (statefile_suffix)));
2168 bool operator()(const string* a, const string* b) {
2174 remove_end(string* state)
2176 string statename(*state);
2178 string::size_type start,end;
2179 if ((start = statename.find_last_of ('/')) != string::npos) {
2180 statename = statename.substr (start+1);
2183 if ((end = statename.rfind(".ardour")) == string::npos) {
2184 end = statename.length();
2187 return new string(statename.substr (0, end));
2191 Session::possible_states (string path)
2193 PathScanner scanner;
2194 vector<string*>* states = scanner (path, state_file_filter, 0, false, false);
2196 transform(states->begin(), states->end(), states->begin(), remove_end);
2199 sort (states->begin(), states->end(), cmp);
2205 Session::possible_states () const
2207 return possible_states(_path);
2211 Session::add_route_group (RouteGroup* g)
2213 _route_groups.push_back (g);
2214 route_group_added (g); /* EMIT SIGNAL */
2219 Session::remove_route_group (RouteGroup& rg)
2221 list<RouteGroup*>::iterator i;
2223 if ((i = find (_route_groups.begin(), _route_groups.end(), &rg)) != _route_groups.end()) {
2224 _route_groups.erase (i);
2227 route_group_removed (); /* EMIT SIGNAL */
2233 Session::route_group_by_name (string name)
2235 list<RouteGroup *>::iterator i;
2237 for (i = _route_groups.begin(); i != _route_groups.end(); ++i) {
2238 if ((*i)->name() == name) {
2246 Session::start_reversible_command (const string& name)
2248 UndoTransaction* trans = new UndoTransaction();
2249 trans->set_name(name);
2254 Session::finish_reversible_command (UndoTransaction& ut)
2257 gettimeofday(&now, 0);
2258 ut.set_timestamp(now);
2263 Session::begin_reversible_command(const string& name)
2265 UndoTransaction* trans = new UndoTransaction();
2266 trans->set_name(name);
2268 if (!_current_trans.empty()) {
2269 _current_trans.top()->add_command (trans);
2271 _current_trans.push(trans);
2276 Session::commit_reversible_command(Command *cmd)
2278 assert(!_current_trans.empty());
2282 _current_trans.top()->add_command(cmd);
2285 if (_current_trans.top()->empty()) {
2286 _current_trans.pop();
2290 gettimeofday(&now, 0);
2291 _current_trans.top()->set_timestamp(now);
2293 _history.add(_current_trans.top());
2294 _current_trans.pop();
2298 accept_all_non_peak_files (const string& path, void */*arg*/)
2300 return (path.length() > 5 && path.find (peakfile_suffix) != (path.length() - 5));
2304 accept_all_state_files (const string& path, void */*arg*/)
2306 return (path.length() > 7 && path.find (".ardour") == (path.length() - 7));
2310 Session::find_all_sources (string path, set<string>& result)
2315 if (!tree.read (path)) {
2319 if ((node = find_named_node (*tree.root(), "Sources")) == 0) {
2324 XMLNodeConstIterator niter;
2326 nlist = node->children();
2330 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2334 if ((prop = (*niter)->property (X_("type"))) == 0) {
2338 DataType type (prop->value());
2340 if ((prop = (*niter)->property (X_("name"))) == 0) {
2344 if (prop->value()[0] == '/') {
2345 /* external file, ignore */
2349 Glib::ustring found_path;
2353 if (FileSource::find (type, prop->value(), true, is_new, chan, found_path)) {
2354 result.insert (found_path);
2362 Session::find_all_sources_across_snapshots (set<string>& result, bool exclude_this_snapshot)
2364 PathScanner scanner;
2365 vector<string*>* state_files;
2367 string this_snapshot_path;
2373 if (ripped[ripped.length()-1] == '/') {
2374 ripped = ripped.substr (0, ripped.length() - 1);
2377 state_files = scanner (ripped, accept_all_state_files, (void *) 0, false, true);
2379 if (state_files == 0) {
2384 this_snapshot_path = _path;
2385 this_snapshot_path += legalize_for_path (_current_snapshot_name);
2386 this_snapshot_path += statefile_suffix;
2388 for (vector<string*>::iterator i = state_files->begin(); i != state_files->end(); ++i) {
2390 if (exclude_this_snapshot && **i == this_snapshot_path) {
2394 if (find_all_sources (**i, result) < 0) {
2402 struct RegionCounter {
2403 typedef std::map<PBD::ID,boost::shared_ptr<AudioSource> > AudioSourceList;
2404 AudioSourceList::iterator iter;
2405 boost::shared_ptr<Region> region;
2408 RegionCounter() : count (0) {}
2412 Session::ask_about_playlist_deletion (boost::shared_ptr<Playlist> p)
2414 return *AskAboutPlaylistDeletion (p);
2418 Session::cleanup_sources (CleanupReport& rep)
2420 // FIXME: needs adaptation to midi
2422 vector<boost::shared_ptr<Source> > dead_sources;
2423 PathScanner scanner;
2425 vector<space_and_path>::iterator i;
2426 vector<space_and_path>::iterator nexti;
2427 vector<string*>* soundfiles;
2428 vector<string> unused;
2429 set<string> all_sources;
2434 _state_of_the_state = (StateOfTheState) (_state_of_the_state | InCleanup);
2436 /* step 1: consider deleting all unused playlists */
2438 if (playlists->maybe_delete_unused (boost::bind (Session::ask_about_playlist_deletion, _1))) {
2443 /* step 2: find all un-used sources */
2448 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ) {
2450 SourceMap::iterator tmp;
2455 /* do not bother with files that are zero size, otherwise we remove the current "nascent"
2459 if (!playlists->source_use_count(i->second) && i->second->length(i->second->timeline_position()) > 0) {
2460 dead_sources.push_back (i->second);
2461 i->second->drop_references ();
2467 /* build a list of all the possible sound directories for the session */
2469 for (i = session_dirs.begin(); i != session_dirs.end(); ) {
2474 SessionDirectory sdir ((*i).path);
2475 sound_path += sdir.sound_path().to_string();
2477 if (nexti != session_dirs.end()) {
2484 /* now do the same thing for the files that ended up in the sounds dir(s)
2485 but are not referenced as sources in any snapshot.
2488 soundfiles = scanner (sound_path, accept_all_non_peak_files, (void *) 0, false, true);
2490 if (soundfiles == 0) {
2494 /* find all sources, but don't use this snapshot because the
2495 state file on disk still references sources we may have already
2499 find_all_sources_across_snapshots (all_sources, true);
2501 /* add our current source list
2504 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ++i) {
2505 boost::shared_ptr<FileSource> fs;
2507 if ((fs = boost::dynamic_pointer_cast<FileSource> (i->second)) != 0) {
2508 all_sources.insert (fs->path());
2512 char tmppath1[PATH_MAX+1];
2513 char tmppath2[PATH_MAX+1];
2515 for (vector<string*>::iterator x = soundfiles->begin(); x != soundfiles->end(); ++x) {
2520 for (set<string>::iterator i = all_sources.begin(); i != all_sources.end(); ++i) {
2522 realpath(spath.c_str(), tmppath1);
2523 realpath((*i).c_str(), tmppath2);
2525 if (strcmp(tmppath1, tmppath2) == 0) {
2532 unused.push_back (spath);
2536 /* now try to move all unused files into the "dead_sounds" directory(ies) */
2538 for (vector<string>::iterator x = unused.begin(); x != unused.end(); ++x) {
2539 struct stat statbuf;
2541 rep.paths.push_back (*x);
2542 if (stat ((*x).c_str(), &statbuf) == 0) {
2543 rep.space += statbuf.st_size;
2548 /* don't move the file across filesystems, just
2549 stick it in the `dead_sound_dir_name' directory
2550 on whichever filesystem it was already on.
2553 if ((*x).find ("/sounds/") != string::npos) {
2555 /* old school, go up 1 level */
2557 newpath = Glib::path_get_dirname (*x); // "sounds"
2558 newpath = Glib::path_get_dirname (newpath); // "session-name"
2562 /* new school, go up 4 levels */
2564 newpath = Glib::path_get_dirname (*x); // "audiofiles"
2565 newpath = Glib::path_get_dirname (newpath); // "session-name"
2566 newpath = Glib::path_get_dirname (newpath); // "interchange"
2567 newpath = Glib::path_get_dirname (newpath); // "session-dir"
2571 newpath += dead_sound_dir_name;
2573 if (g_mkdir_with_parents (newpath.c_str(), 0755) < 0) {
2574 error << string_compose(_("Session: cannot create session peakfile folder \"%1\" (%2)"), newpath, strerror (errno)) << endmsg;
2579 newpath += Glib::path_get_basename ((*x));
2581 if (access (newpath.c_str(), F_OK) == 0) {
2583 /* the new path already exists, try versioning */
2585 char buf[PATH_MAX+1];
2589 snprintf (buf, sizeof (buf), "%s.%d", newpath.c_str(), version);
2592 while (access (newpath_v.c_str(), F_OK) == 0 && version < 999) {
2593 snprintf (buf, sizeof (buf), "%s.%d", newpath.c_str(), ++version);
2597 if (version == 999) {
2598 error << string_compose (_("there are already 1000 files with names like %1; versioning discontinued"),
2602 newpath = newpath_v;
2607 /* it doesn't exist, or we can't read it or something */
2611 if (::rename ((*x).c_str(), newpath.c_str()) != 0) {
2612 error << string_compose (_("cannot rename audio file source from %1 to %2 (%3)"),
2613 (*x), newpath, strerror (errno))
2618 /* see if there an easy to find peakfile for this file, and remove it.
2621 string peakpath = (*x).substr (0, (*x).find_last_of ('.'));
2622 peakpath += peakfile_suffix;
2624 if (access (peakpath.c_str(), W_OK) == 0) {
2625 if (::unlink (peakpath.c_str()) != 0) {
2626 error << string_compose (_("cannot remove peakfile %1 for %2 (%3)"),
2627 peakpath, _path, strerror (errno))
2629 /* try to back out */
2630 rename (newpath.c_str(), _path.c_str());
2638 /* dump the history list */
2642 /* save state so we don't end up a session file
2643 referring to non-existent sources.
2649 _state_of_the_state = (StateOfTheState) (_state_of_the_state & ~InCleanup);
2655 Session::cleanup_trash_sources (CleanupReport& rep)
2657 // FIXME: needs adaptation for MIDI
2659 vector<space_and_path>::iterator i;
2660 string dead_sound_dir;
2661 struct dirent* dentry;
2662 struct stat statbuf;
2668 for (i = session_dirs.begin(); i != session_dirs.end(); ++i) {
2670 dead_sound_dir = (*i).path;
2671 dead_sound_dir += dead_sound_dir_name;
2673 if ((dead = opendir (dead_sound_dir.c_str())) == 0) {
2677 while ((dentry = readdir (dead)) != 0) {
2679 /* avoid '.' and '..' */
2681 if ((dentry->d_name[0] == '.' && dentry->d_name[1] == '\0') ||
2682 (dentry->d_name[2] == '\0' && dentry->d_name[0] == '.' && dentry->d_name[1] == '.')) {
2688 fullpath = dead_sound_dir;
2690 fullpath += dentry->d_name;
2692 if (stat (fullpath.c_str(), &statbuf)) {
2696 if (!S_ISREG (statbuf.st_mode)) {
2700 if (unlink (fullpath.c_str())) {
2701 error << string_compose (_("cannot remove dead sound file %1 (%2)"),
2702 fullpath, strerror (errno))
2706 rep.paths.push_back (dentry->d_name);
2707 rep.space += statbuf.st_size;
2718 Session::set_dirty ()
2720 bool was_dirty = dirty();
2722 _state_of_the_state = StateOfTheState (_state_of_the_state | Dirty);
2726 DirtyChanged(); /* EMIT SIGNAL */
2732 Session::set_clean ()
2734 bool was_dirty = dirty();
2736 _state_of_the_state = Clean;
2740 DirtyChanged(); /* EMIT SIGNAL */
2745 Session::set_deletion_in_progress ()
2747 _state_of_the_state = StateOfTheState (_state_of_the_state | Deletion);
2751 Session::clear_deletion_in_progress ()
2753 _state_of_the_state = StateOfTheState (_state_of_the_state & (~Deletion));
2757 Session::add_controllable (boost::shared_ptr<Controllable> c)
2759 /* this adds a controllable to the list managed by the Session.
2760 this is a subset of those managed by the Controllable class
2761 itself, and represents the only ones whose state will be saved
2762 as part of the session.
2765 Glib::Mutex::Lock lm (controllables_lock);
2766 controllables.insert (c);
2769 struct null_deleter { void operator()(void const *) const {} };
2772 Session::remove_controllable (Controllable* c)
2774 if (_state_of_the_state | Deletion) {
2778 Glib::Mutex::Lock lm (controllables_lock);
2780 Controllables::iterator x = controllables.find (boost::shared_ptr<Controllable>(c, null_deleter()));
2782 if (x != controllables.end()) {
2783 controllables.erase (x);
2787 boost::shared_ptr<Controllable>
2788 Session::controllable_by_id (const PBD::ID& id)
2790 Glib::Mutex::Lock lm (controllables_lock);
2792 for (Controllables::iterator i = controllables.begin(); i != controllables.end(); ++i) {
2793 if ((*i)->id() == id) {
2798 return boost::shared_ptr<Controllable>();
2801 boost::shared_ptr<Controllable>
2802 Session::controllable_by_descriptor (const ControllableDescriptor& desc)
2804 boost::shared_ptr<Controllable> c;
2805 boost::shared_ptr<Route> r;
2807 switch (desc.top_level_type()) {
2808 case ControllableDescriptor::NamedRoute:
2810 std::string str = desc.top_level_name();
2811 if (str == "master") {
2813 } else if (str == "control" || str == "listen") {
2816 r = route_by_name (desc.top_level_name());
2821 case ControllableDescriptor::RemoteControlID:
2822 r = route_by_remote_id (desc.rid());
2830 switch (desc.subtype()) {
2831 case ControllableDescriptor::Gain:
2832 c = r->gain_control ();
2835 case ControllableDescriptor::Solo:
2836 c = r->solo_control();
2839 case ControllableDescriptor::Mute:
2840 c = r->mute_control();
2843 case ControllableDescriptor::Recenable:
2845 boost::shared_ptr<Track> t = boost::dynamic_pointer_cast<Track>(r);
2848 c = t->rec_enable_control ();
2853 case ControllableDescriptor::Pan:
2854 /* XXX pan control */
2857 case ControllableDescriptor::Balance:
2858 /* XXX simple pan control */
2861 case ControllableDescriptor::PluginParameter:
2863 uint32_t plugin = desc.target (0);
2864 uint32_t parameter_index = desc.target (1);
2866 /* revert to zero based counting */
2872 if (parameter_index > 0) {
2876 boost::shared_ptr<Processor> p = r->nth_plugin (plugin);
2879 c = boost::dynamic_pointer_cast<ARDOUR::AutomationControl>(
2880 p->control(Evoral::Parameter(PluginAutomation, 0, parameter_index)));
2885 case ControllableDescriptor::SendGain:
2887 uint32_t send = desc.target (0);
2889 /* revert to zero-based counting */
2895 boost::shared_ptr<Processor> p = r->nth_send (send);
2898 boost::shared_ptr<Send> s = boost::dynamic_pointer_cast<Send>(p);
2899 boost::shared_ptr<Amp> a = s->amp();
2902 c = s->amp()->gain_control();
2909 /* relax and return a null pointer */
2917 Session::add_instant_xml (XMLNode& node, bool write_to_config)
2920 Stateful::add_instant_xml (node, _path);
2923 if (write_to_config) {
2924 Config->add_instant_xml (node);
2929 Session::instant_xml (const string& node_name)
2931 return Stateful::instant_xml (node_name, _path);
2935 Session::save_history (string snapshot_name)
2943 if (snapshot_name.empty()) {
2944 snapshot_name = _current_snapshot_name;
2947 const string history_filename = legalize_for_path (snapshot_name) + history_suffix;
2948 const string backup_filename = history_filename + backup_suffix;
2949 const sys::path xml_path = _session_dir->root_path() / history_filename;
2950 const sys::path backup_path = _session_dir->root_path() / backup_filename;
2952 if (sys::exists (xml_path)) {
2955 sys::rename (xml_path, backup_path);
2957 catch (const sys::filesystem_error& err)
2959 error << _("could not backup old history file, current history not saved") << endmsg;
2964 if (!Config->get_save_history() || Config->get_saved_history_depth() < 0) {
2968 tree.set_root (&_history.get_state (Config->get_saved_history_depth()));
2970 if (!tree.write (xml_path.to_string()))
2972 error << string_compose (_("history could not be saved to %1"), xml_path.to_string()) << endmsg;
2976 sys::remove (xml_path);
2977 sys::rename (backup_path, xml_path);
2979 catch (const sys::filesystem_error& err)
2981 error << string_compose (_("could not restore history file from backup %1 (%2)"),
2982 backup_path.to_string(), err.what()) << endmsg;
2992 Session::restore_history (string snapshot_name)
2996 if (snapshot_name.empty()) {
2997 snapshot_name = _current_snapshot_name;
3000 const string xml_filename = legalize_for_path (snapshot_name) + history_suffix;
3001 const sys::path xml_path = _session_dir->root_path() / xml_filename;
3003 info << "Loading history from " << xml_path.to_string() << endmsg;
3005 if (!sys::exists (xml_path)) {
3006 info << string_compose (_("%1: no history file \"%2\" for this session."),
3007 _name, xml_path.to_string()) << endmsg;
3011 if (!tree.read (xml_path.to_string())) {
3012 error << string_compose (_("Could not understand session history file \"%1\""),
3013 xml_path.to_string()) << endmsg;
3020 for (XMLNodeConstIterator it = tree.root()->children().begin(); it != tree.root()->children().end(); it++) {
3023 UndoTransaction* ut = new UndoTransaction ();
3026 ut->set_name(t->property("name")->value());
3027 stringstream ss(t->property("tv-sec")->value());
3029 ss.str(t->property("tv-usec")->value());
3031 ut->set_timestamp(tv);
3033 for (XMLNodeConstIterator child_it = t->children().begin();
3034 child_it != t->children().end(); child_it++)
3036 XMLNode *n = *child_it;
3039 if (n->name() == "MementoCommand" ||
3040 n->name() == "MementoUndoCommand" ||
3041 n->name() == "MementoRedoCommand") {
3043 if ((c = memento_command_factory(n))) {
3047 } else if (n->name() == "DeltaCommand") {
3048 PBD::ID id(n->property("midi-source")->value());
3049 boost::shared_ptr<MidiSource> midi_source =
3050 boost::dynamic_pointer_cast<MidiSource, Source>(source_by_id(id));
3052 ut->add_command(new MidiModel::DeltaCommand(midi_source->model(), *n));
3054 error << _("Failed to downcast MidiSource for DeltaCommand") << endmsg;
3057 } else if (n->name() == "DiffCommand") {
3058 PBD::ID id(n->property("midi-source")->value());
3059 boost::shared_ptr<MidiSource> midi_source =
3060 boost::dynamic_pointer_cast<MidiSource, Source>(source_by_id(id));
3062 ut->add_command(new MidiModel::DiffCommand(midi_source->model(), *n));
3064 error << _("Failed to downcast MidiSource for DeltaCommand") << endmsg;
3067 } else if (n->name() == "StatefulDiffCommand") {
3068 if ((c = stateful_diff_command_factory (n))) {
3069 ut->add_command (c);
3072 error << string_compose(_("Couldn't figure out how to make a Command out of a %1 XMLNode."), n->name()) << endmsg;
3083 Session::config_changed (std::string p, bool ours)
3089 if (p == "seamless-loop") {
3091 } else if (p == "rf-speed") {
3093 } else if (p == "auto-loop") {
3095 } else if (p == "auto-input") {
3097 if (Config->get_monitoring_model() == HardwareMonitoring && transport_rolling()) {
3098 /* auto-input only makes a difference if we're rolling */
3100 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
3102 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
3103 if ((*i)->record_enabled ()) {
3104 (*i)->monitor_input (!config.get_auto_input());
3109 } else if (p == "punch-in") {
3113 if ((location = _locations.auto_punch_location()) != 0) {
3115 if (config.get_punch_in ()) {
3116 replace_event (SessionEvent::PunchIn, location->start());
3118 remove_event (location->start(), SessionEvent::PunchIn);
3122 } else if (p == "punch-out") {
3126 if ((location = _locations.auto_punch_location()) != 0) {
3128 if (config.get_punch_out()) {
3129 replace_event (SessionEvent::PunchOut, location->end());
3131 clear_events (SessionEvent::PunchOut);
3135 } else if (p == "edit-mode") {
3137 Glib::Mutex::Lock lm (playlists->lock);
3139 for (SessionPlaylists::List::iterator i = playlists->playlists.begin(); i != playlists->playlists.end(); ++i) {
3140 (*i)->set_edit_mode (Config->get_edit_mode ());
3143 } else if (p == "use-video-sync") {
3145 waiting_for_sync_offset = config.get_use_video_sync();
3147 } else if (p == "mmc-control") {
3149 //poke_midi_thread ();
3151 } else if (p == "mmc-device-id" || p == "mmc-receive-id") {
3154 mmc->set_receive_device_id (Config->get_mmc_receive_device_id());
3157 } else if (p == "mmc-send-id") {
3160 mmc->set_send_device_id (Config->get_mmc_send_device_id());
3163 } else if (p == "midi-control") {
3165 //poke_midi_thread ();
3167 } else if (p == "raid-path") {
3169 setup_raid_path (config.get_raid_path());
3171 } else if (p == "timecode-format") {
3175 } else if (p == "video-pullup") {
3179 } else if (p == "seamless-loop") {
3181 if (play_loop && transport_rolling()) {
3182 // to reset diskstreams etc
3183 request_play_loop (true);
3186 } else if (p == "rf-speed") {
3188 cumulative_rf_motion = 0;
3191 } else if (p == "click-sound") {
3193 setup_click_sounds (1);
3195 } else if (p == "click-emphasis-sound") {
3197 setup_click_sounds (-1);
3199 } else if (p == "clicking") {
3201 if (Config->get_clicking()) {
3202 if (_click_io && click_data) { // don't require emphasis data
3209 } else if (p == "send-mtc") {
3211 /* only set the internal flag if we have
3215 if (_mtc_port != 0) {
3216 session_send_mtc = Config->get_send_mtc();
3217 if (session_send_mtc) {
3218 /* mark us ready to send */
3219 next_quarter_frame_to_send = 0;
3222 session_send_mtc = false;
3225 } else if (p == "send-mmc") {
3227 /* only set the internal flag if we have
3231 if (_mmc_port != 0) {
3232 session_send_mmc = Config->get_send_mmc();
3235 session_send_mmc = false;
3238 } else if (p == "midi-feedback") {
3240 /* only set the internal flag if we have
3244 if (_mtc_port != 0) {
3245 session_midi_feedback = Config->get_midi_feedback();
3248 } else if (p == "jack-time-master") {
3250 engine().reset_timebase ();
3252 } else if (p == "native-file-header-format") {
3254 if (!first_file_header_format_reset) {
3255 reset_native_file_format ();
3258 first_file_header_format_reset = false;
3260 } else if (p == "native-file-data-format") {
3262 if (!first_file_data_format_reset) {
3263 reset_native_file_format ();
3266 first_file_data_format_reset = false;
3268 } else if (p == "external-sync") {
3269 if (!config.get_external_sync()) {
3270 drop_sync_source ();
3272 switch_to_sync_source (config.get_sync_source());
3274 } else if (p == "remote-model") {
3275 set_remote_control_ids ();
3276 } else if (p == "denormal-model") {
3278 } else if (p == "history-depth") {
3279 set_history_depth (Config->get_history_depth());
3280 } else if (p == "sync-all-route-ordering") {
3281 sync_order_keys ("session");
3282 } else if (p == "initial-program-change") {
3284 if (_mmc_port && Config->get_initial_program_change() >= 0) {
3287 buf[0] = MIDI::program; // channel zero by default
3288 buf[1] = (Config->get_initial_program_change() & 0x7f);
3290 _mmc_port->midimsg (buf, sizeof (buf), 0);
3292 } else if (p == "initial-program-change") {
3294 if (_mmc_port && Config->get_initial_program_change() >= 0) {
3295 MIDI::byte* buf = new MIDI::byte[2];
3297 buf[0] = MIDI::program; // channel zero by default
3298 buf[1] = (Config->get_initial_program_change() & 0x7f);
3299 // deliver_midi (_mmc_port, buf, 2);
3301 } else if (p == "solo-mute-override") {
3302 // catch_up_on_solo_mute_override ();
3303 } else if (p == "listen-position") {
3304 listen_position_changed ();
3305 } else if (p == "solo-control-is-listen-control") {
3306 solo_control_mode_changed ();
3314 Session::set_history_depth (uint32_t d)
3316 _history.set_depth (d);