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);
728 #ifdef HAVE_JACK_SESSION
730 Session::jack_session_event( jack_session_event_t * event )
732 if (save_state ("jacksession_snap")) {
733 event->flags = JackSessionSaveError;
735 sys::path xml_path (_session_dir->root_path());
736 xml_path /= legalize_for_path ("jacksession_snap") + statefile_suffix;
738 string cmd ("PROG_NAME -U ");
739 cmd += event->client_uuid;
741 cmd += xml_path.to_string();
744 event->command_line = strdup (cmd.c_str());
747 jack_session_reply (_engine.jack(), event);
749 if (event->type == JackSessionSaveAndQuit) {
750 // TODO: make ardour quit.
753 jack_session_event_free( event );
758 Session::save_state (string snapshot_name, bool pending)
761 sys::path xml_path(_session_dir->root_path());
763 if (!_writable || (_state_of_the_state & CannotSave)) {
767 if (!_engine.connected ()) {
768 error << string_compose (_("the %1 audio engine is not connected and state saving would lose all I/O connections. Session not saved"),
774 /* tell sources we're saving first, in case they write out to a new file
775 * which should be saved with the state rather than the old one */
776 for (SourceMap::const_iterator i = sources.begin(); i != sources.end(); ++i)
777 i->second->session_saved();
779 tree.set_root (&get_state());
781 if (snapshot_name.empty()) {
782 snapshot_name = _current_snapshot_name;
787 /* proper save: use statefile_suffix (.ardour in English) */
789 xml_path /= legalize_for_path (snapshot_name) + statefile_suffix;
791 /* make a backup copy of the old file */
793 if (sys::exists(xml_path) && !create_backup_file (xml_path)) {
794 // create_backup_file will log the error
800 /* pending save: use pending_suffix (.pending in English) */
801 xml_path /= legalize_for_path (snapshot_name) + pending_suffix;
804 sys::path tmp_path(_session_dir->root_path());
806 tmp_path /= legalize_for_path (snapshot_name) + temp_suffix;
808 // cerr << "actually writing state to " << xml_path.to_string() << endl;
810 if (!tree.write (tmp_path.to_string())) {
811 error << string_compose (_("state could not be saved to %1"), tmp_path.to_string()) << endmsg;
812 sys::remove (tmp_path);
817 if (rename (tmp_path.to_string().c_str(), xml_path.to_string().c_str()) != 0) {
818 error << string_compose (_("could not rename temporary session file %1 to %2"),
819 tmp_path.to_string(), xml_path.to_string()) << endmsg;
820 sys::remove (tmp_path);
827 save_history (snapshot_name);
829 bool was_dirty = dirty();
831 _state_of_the_state = StateOfTheState (_state_of_the_state & ~Dirty);
834 DirtyChanged (); /* EMIT SIGNAL */
837 StateSaved (snapshot_name); /* EMIT SIGNAL */
844 Session::restore_state (string snapshot_name)
846 if (load_state (snapshot_name) == 0) {
847 set_state (*state_tree->root(), Stateful::loading_state_version);
854 Session::load_state (string snapshot_name)
859 state_was_pending = false;
861 /* check for leftover pending state from a crashed capture attempt */
863 sys::path xmlpath(_session_dir->root_path());
864 xmlpath /= legalize_for_path (snapshot_name) + pending_suffix;
866 if (sys::exists (xmlpath)) {
868 /* there is pending state from a crashed capture attempt */
870 if (*AskAboutPendingState()) {
871 state_was_pending = true;
875 if (!state_was_pending) {
876 xmlpath = _session_dir->root_path();
877 xmlpath /= legalize_for_path (snapshot_name) + statefile_suffix;
880 if (!sys::exists (xmlpath)) {
881 error << string_compose(_("%1: session state information file \"%2\" doesn't exist!"), _name, xmlpath.to_string()) << endmsg;
885 state_tree = new XMLTree;
889 /* writable() really reflects the whole folder, but if for any
890 reason the session state file can't be written to, still
894 if (::access (xmlpath.to_string().c_str(), W_OK) != 0) {
898 if (!state_tree->read (xmlpath.to_string())) {
899 error << string_compose(_("Could not understand ardour file %1"), xmlpath.to_string()) << endmsg;
905 XMLNode& root (*state_tree->root());
907 if (root.name() != X_("Session")) {
908 error << string_compose (_("Session file %1 is not a session"), xmlpath.to_string()) << endmsg;
914 const XMLProperty* prop;
916 if ((prop = root.property ("version")) == 0) {
917 /* no version implies very old version of Ardour */
918 Stateful::loading_state_version = 1000;
924 sscanf (prop->value().c_str(), "%d.%d.%d", &major, &minor, µ);
925 Stateful::loading_state_version = (major * 1000) + minor;
928 if (Stateful::loading_state_version < CURRENT_SESSION_FILE_VERSION) {
930 sys::path backup_path(_session_dir->root_path());
932 backup_path /= legalize_for_path (snapshot_name) + "-1" + statefile_suffix;
934 // only create a backup once
935 if (sys::exists (backup_path)) {
939 info << string_compose (_("Copying old session file %1 to %2\nUse %2 with %3 versions before 2.0 from now on"),
940 xmlpath.to_string(), backup_path.to_string(), PROGRAM_NAME)
945 sys::copy_file (xmlpath, backup_path);
947 catch(sys::filesystem_error& ex)
949 error << string_compose (_("Unable to make backup of state file %1 (%2)"),
950 xmlpath.to_string(), ex.what())
960 Session::load_options (const XMLNode& node)
962 LocaleGuard lg (X_("POSIX"));
963 config.set_variables (node);
974 Session::get_template()
976 /* if we don't disable rec-enable, diskstreams
977 will believe they need to store their capture
978 sources in their state node.
981 disable_record (false);
987 Session::state(bool full_state)
989 XMLNode* node = new XMLNode("Session");
992 // store libardour version, just in case
994 snprintf(buf, sizeof(buf), "%d.%d.%d", libardour3_major_version, libardour3_minor_version, libardour3_micro_version);
995 node->add_property("version", string(buf));
997 /* store configuration settings */
1001 node->add_property ("name", _name);
1002 snprintf (buf, sizeof (buf), "%" PRId32, _nominal_frame_rate);
1003 node->add_property ("sample-rate", buf);
1005 if (session_dirs.size() > 1) {
1009 vector<space_and_path>::iterator i = session_dirs.begin();
1010 vector<space_and_path>::iterator next;
1012 ++i; /* skip the first one */
1016 while (i != session_dirs.end()) {
1020 if (next != session_dirs.end()) {
1030 child = node->add_child ("Path");
1031 child->add_content (p);
1035 /* save the ID counter */
1037 snprintf (buf, sizeof (buf), "%" PRIu64, ID::counter());
1038 node->add_property ("id-counter", buf);
1040 /* various options */
1042 node->add_child_nocopy (config.get_variables ());
1044 node->add_child_nocopy (_metadata->get_state());
1046 child = node->add_child ("Sources");
1049 Glib::Mutex::Lock sl (source_lock);
1051 for (SourceMap::iterator siter = sources.begin(); siter != sources.end(); ++siter) {
1053 /* Don't save information about non-destructive file sources that are empty */
1054 /* FIXME: MIDI breaks if this is made FileSource like it should be... */
1056 boost::shared_ptr<AudioFileSource> fs;
1057 if ((fs = boost::dynamic_pointer_cast<AudioFileSource> (siter->second)) != 0) {
1058 if (!fs->destructive()) {
1059 if (fs->length(fs->timeline_position()) == 0) {
1065 child->add_child_nocopy (siter->second->get_state());
1069 child = node->add_child ("Regions");
1072 Glib::Mutex::Lock rl (region_lock);
1073 const RegionFactory::RegionMap& region_map (RegionFactory::all_regions());
1074 for (RegionFactory::RegionMap::const_iterator i = region_map.begin(); i != region_map.end(); ++i) {
1075 boost::shared_ptr<Region> r = i->second;
1076 /* only store regions not attached to playlists */
1077 if (r->playlist() == 0) {
1078 child->add_child_nocopy (r->state (true));
1083 child = node->add_child ("DiskStreams");
1086 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
1087 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
1088 if (!(*i)->hidden()) {
1089 child->add_child_nocopy ((*i)->get_state());
1095 node->add_child_nocopy (_locations.get_state());
1097 // for a template, just create a new Locations, populate it
1098 // with the default start and end, and get the state for that.
1100 Location* start = new Location(0, 0, _("start"), Location::Flags ((Location::IsMark|Location::IsStart)));
1101 Location* end = new Location(0, 0, _("end"), Location::Flags ((Location::IsMark|Location::IsEnd)));
1104 end->set_end(compute_initial_length());
1106 node->add_child_nocopy (loc.get_state());
1109 child = node->add_child ("Bundles");
1111 boost::shared_ptr<BundleList> bundles = _bundles.reader ();
1112 for (BundleList::iterator i = bundles->begin(); i != bundles->end(); ++i) {
1113 boost::shared_ptr<UserBundle> b = boost::dynamic_pointer_cast<UserBundle> (*i);
1115 child->add_child_nocopy (b->get_state());
1120 child = node->add_child ("Routes");
1122 boost::shared_ptr<RouteList> r = routes.reader ();
1124 RoutePublicOrderSorter cmp;
1125 RouteList public_order (*r);
1126 public_order.sort (cmp);
1128 /* the sort should have put control outs first */
1131 assert (_monitor_out == public_order.front());
1134 for (RouteList::iterator i = public_order.begin(); i != public_order.end(); ++i) {
1135 if (!(*i)->is_hidden()) {
1137 child->add_child_nocopy ((*i)->get_state());
1139 child->add_child_nocopy ((*i)->get_template());
1145 playlists->add_state (node, full_state);
1147 child = node->add_child ("RouteGroups");
1148 for (list<RouteGroup *>::iterator i = _route_groups.begin(); i != _route_groups.end(); ++i) {
1149 child->add_child_nocopy ((*i)->get_state());
1153 child = node->add_child ("Click");
1154 child->add_child_nocopy (_click_io->state (full_state));
1158 child = node->add_child ("NamedSelections");
1159 for (NamedSelectionList::iterator i = named_selections.begin(); i != named_selections.end(); ++i) {
1161 child->add_child_nocopy ((*i)->get_state());
1166 node->add_child_nocopy (_tempo_map->get_state());
1168 node->add_child_nocopy (get_control_protocol_state());
1171 node->add_child_copy (*_extra_xml);
1178 Session::get_control_protocol_state ()
1180 ControlProtocolManager& cpm (ControlProtocolManager::instance());
1181 return cpm.get_state();
1185 Session::set_state (const XMLNode& node, int version)
1189 const XMLProperty* prop;
1192 _state_of_the_state = StateOfTheState (_state_of_the_state|CannotSave);
1194 if (node.name() != X_("Session")){
1195 fatal << _("programming error: Session: incorrect XML node sent to set_state()") << endmsg;
1199 if ((prop = node.property ("version")) != 0) {
1200 version = atoi (prop->value ()) * 1000;
1203 if ((prop = node.property ("name")) != 0) {
1204 _name = prop->value ();
1207 if ((prop = node.property (X_("sample-rate"))) != 0) {
1209 _nominal_frame_rate = atoi (prop->value());
1211 if (_nominal_frame_rate != _current_frame_rate) {
1212 if (*AskAboutSampleRateMismatch (_nominal_frame_rate, _current_frame_rate)) {
1218 setup_raid_path(_session_dir->root_path().to_string());
1220 if ((prop = node.property (X_("id-counter"))) != 0) {
1222 sscanf (prop->value().c_str(), "%" PRIu64, &x);
1223 ID::init_counter (x);
1225 /* old sessions used a timebased counter, so fake
1226 the startup ID counter based on a standard
1231 ID::init_counter (now);
1235 IO::disable_connecting ();
1237 /* Object loading order:
1242 MIDI Control // relies on data from Options/Config
1256 if ((child = find_named_node (node, "Extra")) != 0) {
1257 _extra_xml = new XMLNode (*child);
1260 if (((child = find_named_node (node, "Options")) != 0)) { /* old style */
1261 load_options (*child);
1262 } else if ((child = find_named_node (node, "Config")) != 0) { /* new style */
1263 load_options (*child);
1265 error << _("Session: XML state has no options section") << endmsg;
1268 if (use_config_midi_ports ()) {
1271 if (version >= 3000) {
1272 if ((child = find_named_node (node, "Metadata")) == 0) {
1273 warning << _("Session: XML state has no metadata section") << endmsg;
1274 } else if (_metadata->set_state (*child, version)) {
1279 if ((child = find_named_node (node, "Locations")) == 0) {
1280 error << _("Session: XML state has no locations section") << endmsg;
1282 } else if (_locations.set_state (*child, version)) {
1288 if ((location = _locations.auto_loop_location()) != 0) {
1289 set_auto_loop_location (location);
1292 if ((location = _locations.auto_punch_location()) != 0) {
1293 set_auto_punch_location (location);
1296 if ((location = _locations.end_location()) == 0) {
1297 _locations.add (end_location);
1299 delete end_location;
1300 end_location = location;
1303 if ((location = _locations.start_location()) == 0) {
1304 _locations.add (start_location);
1306 delete start_location;
1307 start_location = location;
1310 AudioFileSource::set_header_position_offset (start_location->start());
1312 if ((child = find_named_node (node, "Sources")) == 0) {
1313 error << _("Session: XML state has no sources section") << endmsg;
1315 } else if (load_sources (*child)) {
1319 if ((child = find_named_node (node, "Regions")) == 0) {
1320 error << _("Session: XML state has no Regions section") << endmsg;
1322 } else if (load_regions (*child)) {
1326 if ((child = find_named_node (node, "Playlists")) == 0) {
1327 error << _("Session: XML state has no playlists section") << endmsg;
1329 } else if (playlists->load (*this, *child)) {
1333 if ((child = find_named_node (node, "UnusedPlaylists")) == 0) {
1335 } else if (playlists->load_unused (*this, *child)) {
1339 if ((child = find_named_node (node, "NamedSelections")) != 0) {
1340 if (load_named_selections (*child)) {
1345 if ((child = find_named_node (node, "DiskStreams")) == 0) {
1346 error << _("Session: XML state has no diskstreams section") << endmsg;
1348 } else if (load_diskstreams (*child)) {
1352 if (version >= 3000) {
1353 if ((child = find_named_node (node, "Bundles")) == 0) {
1354 warning << _("Session: XML state has no bundles section") << endmsg;
1357 /* We can't load Bundles yet as they need to be able
1358 to convert from port names to Port objects, which can't happen until
1360 _bundle_xml_node = new XMLNode (*child);
1364 if ((child = find_named_node (node, "TempoMap")) == 0) {
1365 error << _("Session: XML state has no Tempo Map section") << endmsg;
1367 } else if (_tempo_map->set_state (*child, version)) {
1371 if ((child = find_named_node (node, "Routes")) == 0) {
1372 error << _("Session: XML state has no routes section") << endmsg;
1374 } else if (load_routes (*child, version)) {
1378 if (version >= 3000) {
1380 if ((child = find_named_node (node, "RouteGroups")) == 0) {
1381 error << _("Session: XML state has no route groups section") << endmsg;
1383 } else if (load_route_groups (*child, version)) {
1387 } else if (version < 3000) {
1389 if ((child = find_named_node (node, "EditGroups")) == 0) {
1390 error << _("Session: XML state has no edit groups section") << endmsg;
1392 } else if (load_route_groups (*child, version)) {
1396 if ((child = find_named_node (node, "MixGroups")) == 0) {
1397 error << _("Session: XML state has no mix groups section") << endmsg;
1399 } else if (load_route_groups (*child, version)) {
1404 if ((child = find_named_node (node, "Click")) == 0) {
1405 warning << _("Session: XML state has no click section") << endmsg;
1406 } else if (_click_io) {
1407 _click_io->set_state (*child, version);
1410 if ((child = find_named_node (node, "ControlProtocols")) != 0) {
1411 ControlProtocolManager::instance().set_protocol_states (*child);
1414 /* here beginneth the second phase ... */
1416 StateReady (); /* EMIT SIGNAL */
1425 Session::load_routes (const XMLNode& node, int version)
1428 XMLNodeConstIterator niter;
1429 RouteList new_routes;
1431 nlist = node.children();
1435 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1437 boost::shared_ptr<Route> route (XMLRouteFactory (**niter, version));
1440 error << _("Session: cannot create Route from XML description.") << endmsg;
1444 BootMessage (string_compose (_("Loaded track/bus %1"), route->name()));
1446 new_routes.push_back (route);
1449 add_routes (new_routes, false);
1454 boost::shared_ptr<Route>
1455 Session::XMLRouteFactory (const XMLNode& node, int version)
1457 boost::shared_ptr<Route> ret;
1459 if (node.name() != "Route") {
1463 const XMLProperty* dsprop;
1465 if ((dsprop = node.property (X_("diskstream-id"))) == 0) {
1466 dsprop = node.property (X_("diskstream"));
1469 DataType type = DataType::AUDIO;
1470 const XMLProperty* prop = node.property("default-type");
1473 type = DataType (prop->value());
1476 assert (type != DataType::NIL);
1480 boost::shared_ptr<Diskstream> ds;
1481 PBD::ID diskstream_id (dsprop->value());
1484 /* this wierd hack is used when creating
1485 tracks from a template. We have a special
1486 ID for the diskstream that means "you
1487 should create a new diskstream here, not
1488 look for an old one."
1491 if (diskstream_id != zero) {
1493 ds = diskstream_by_id (diskstream_id);
1496 error << string_compose (_("cannot find diskstream ID %1"), diskstream_id.to_s()) << endmsg;
1503 if (type == DataType::AUDIO) {
1504 track = new AudioTrack (*this, X_("toBeResetFroXML"));
1507 track = new MidiTrack (*this, X_("toBeResetFroXML"));
1510 if (track->init()) {
1516 track->set_diskstream (ds);
1518 track->use_new_diskstream ();
1521 if (track->set_state (node, version)) {
1526 boost_debug_shared_ptr_mark_interesting (track, "Track");
1530 Route* rt = new Route (*this, X_("toBeResetFroXML"));
1532 if (rt->init () == 0 && rt->set_state (node, version) == 0) {
1533 boost_debug_shared_ptr_mark_interesting (rt, "Route");
1544 Session::load_regions (const XMLNode& node)
1547 XMLNodeConstIterator niter;
1548 boost::shared_ptr<Region> region;
1550 nlist = node.children();
1554 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1555 if ((region = XMLRegionFactory (**niter, false)) == 0) {
1556 error << _("Session: cannot create Region from XML description.");
1557 const XMLProperty *name = (**niter).property("name");
1560 error << " " << string_compose (_("Can not load state for region '%1'"), name->value());
1570 boost::shared_ptr<Region>
1571 Session::XMLRegionFactory (const XMLNode& node, bool full)
1573 const XMLProperty* type = node.property("type");
1577 if ( !type || type->value() == "audio" ) {
1579 return boost::shared_ptr<Region>(XMLAudioRegionFactory (node, full));
1581 } else if (type->value() == "midi") {
1583 return boost::shared_ptr<Region>(XMLMidiRegionFactory (node, full));
1587 } catch (failed_constructor& err) {
1588 return boost::shared_ptr<Region> ();
1591 return boost::shared_ptr<Region> ();
1594 boost::shared_ptr<AudioRegion>
1595 Session::XMLAudioRegionFactory (const XMLNode& node, bool /*full*/)
1597 const XMLProperty* prop;
1598 boost::shared_ptr<Source> source;
1599 boost::shared_ptr<AudioSource> as;
1601 SourceList master_sources;
1602 uint32_t nchans = 1;
1605 if (node.name() != X_("Region")) {
1606 return boost::shared_ptr<AudioRegion>();
1609 if ((prop = node.property (X_("channels"))) != 0) {
1610 nchans = atoi (prop->value().c_str());
1613 if ((prop = node.property ("name")) == 0) {
1614 cerr << "no name for this region\n";
1618 if ((prop = node.property (X_("source-0"))) == 0) {
1619 if ((prop = node.property ("source")) == 0) {
1620 error << _("Session: XMLNode describing a AudioRegion is incomplete (no source)") << endmsg;
1621 return boost::shared_ptr<AudioRegion>();
1625 PBD::ID s_id (prop->value());
1627 if ((source = source_by_id (s_id)) == 0) {
1628 error << string_compose(_("Session: XMLNode describing a AudioRegion references an unknown source id =%1"), s_id) << endmsg;
1629 return boost::shared_ptr<AudioRegion>();
1632 as = boost::dynamic_pointer_cast<AudioSource>(source);
1634 error << string_compose(_("Session: XMLNode describing a AudioRegion references a non-audio source id =%1"), s_id) << endmsg;
1635 return boost::shared_ptr<AudioRegion>();
1638 sources.push_back (as);
1640 /* pickup other channels */
1642 for (uint32_t n=1; n < nchans; ++n) {
1643 snprintf (buf, sizeof(buf), X_("source-%d"), n);
1644 if ((prop = node.property (buf)) != 0) {
1646 PBD::ID id2 (prop->value());
1648 if ((source = source_by_id (id2)) == 0) {
1649 error << string_compose(_("Session: XMLNode describing a AudioRegion references an unknown source id =%1"), id2) << endmsg;
1650 return boost::shared_ptr<AudioRegion>();
1653 as = boost::dynamic_pointer_cast<AudioSource>(source);
1655 error << string_compose(_("Session: XMLNode describing a AudioRegion references a non-audio source id =%1"), id2) << endmsg;
1656 return boost::shared_ptr<AudioRegion>();
1658 sources.push_back (as);
1662 for (uint32_t n = 0; n < nchans; ++n) {
1663 snprintf (buf, sizeof(buf), X_("master-source-%d"), n);
1664 if ((prop = node.property (buf)) != 0) {
1666 PBD::ID id2 (prop->value());
1668 if ((source = source_by_id (id2)) == 0) {
1669 error << string_compose(_("Session: XMLNode describing a AudioRegion references an unknown source id =%1"), id2) << endmsg;
1670 return boost::shared_ptr<AudioRegion>();
1673 as = boost::dynamic_pointer_cast<AudioSource>(source);
1675 error << string_compose(_("Session: XMLNode describing a AudioRegion references a non-audio source id =%1"), id2) << endmsg;
1676 return boost::shared_ptr<AudioRegion>();
1678 master_sources.push_back (as);
1683 boost::shared_ptr<AudioRegion> region (boost::dynamic_pointer_cast<AudioRegion> (RegionFactory::create (sources, node)));
1685 /* a final detail: this is the one and only place that we know how long missing files are */
1687 if (region->whole_file()) {
1688 for (SourceList::iterator sx = sources.begin(); sx != sources.end(); ++sx) {
1689 boost::shared_ptr<SilentFileSource> sfp = boost::dynamic_pointer_cast<SilentFileSource> (*sx);
1691 sfp->set_length (region->length());
1696 if (!master_sources.empty()) {
1697 if (master_sources.size() != nchans) {
1698 error << _("Session: XMLNode describing an AudioRegion is missing some master sources; ignored") << endmsg;
1700 region->set_master_sources (master_sources);
1708 catch (failed_constructor& err) {
1709 return boost::shared_ptr<AudioRegion>();
1713 boost::shared_ptr<MidiRegion>
1714 Session::XMLMidiRegionFactory (const XMLNode& node, bool /*full*/)
1716 const XMLProperty* prop;
1717 boost::shared_ptr<Source> source;
1718 boost::shared_ptr<MidiSource> ms;
1720 uint32_t nchans = 1;
1722 if (node.name() != X_("Region")) {
1723 return boost::shared_ptr<MidiRegion>();
1726 if ((prop = node.property (X_("channels"))) != 0) {
1727 nchans = atoi (prop->value().c_str());
1730 if ((prop = node.property ("name")) == 0) {
1731 cerr << "no name for this region\n";
1735 // Multiple midi channels? that's just crazy talk
1736 assert(nchans == 1);
1738 if ((prop = node.property (X_("source-0"))) == 0) {
1739 if ((prop = node.property ("source")) == 0) {
1740 error << _("Session: XMLNode describing a MidiRegion is incomplete (no source)") << endmsg;
1741 return boost::shared_ptr<MidiRegion>();
1745 PBD::ID s_id (prop->value());
1747 if ((source = source_by_id (s_id)) == 0) {
1748 error << string_compose(_("Session: XMLNode describing a MidiRegion references an unknown source id =%1"), s_id) << endmsg;
1749 return boost::shared_ptr<MidiRegion>();
1752 ms = boost::dynamic_pointer_cast<MidiSource>(source);
1754 error << string_compose(_("Session: XMLNode describing a MidiRegion references a non-midi source id =%1"), s_id) << endmsg;
1755 return boost::shared_ptr<MidiRegion>();
1758 sources.push_back (ms);
1761 boost::shared_ptr<MidiRegion> region (boost::dynamic_pointer_cast<MidiRegion> (RegionFactory::create (sources, node)));
1762 /* a final detail: this is the one and only place that we know how long missing files are */
1764 if (region->whole_file()) {
1765 for (SourceList::iterator sx = sources.begin(); sx != sources.end(); ++sx) {
1766 boost::shared_ptr<SilentFileSource> sfp = boost::dynamic_pointer_cast<SilentFileSource> (*sx);
1768 sfp->set_length (region->length());
1776 catch (failed_constructor& err) {
1777 return boost::shared_ptr<MidiRegion>();
1782 Session::get_sources_as_xml ()
1785 XMLNode* node = new XMLNode (X_("Sources"));
1786 Glib::Mutex::Lock lm (source_lock);
1788 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ++i) {
1789 node->add_child_nocopy (i->second->get_state());
1796 Session::path_from_region_name (DataType type, string name, string identifier)
1798 char buf[PATH_MAX+1];
1800 SessionDirectory sdir(get_best_session_directory_for_new_source());
1801 sys::path source_dir = ((type == DataType::AUDIO)
1802 ? sdir.sound_path() : sdir.midi_path());
1804 string ext = ((type == DataType::AUDIO) ? ".wav" : ".mid");
1806 for (n = 0; n < 999999; ++n) {
1807 if (identifier.length()) {
1808 snprintf (buf, sizeof(buf), "%s%s%" PRIu32 "%s", name.c_str(),
1809 identifier.c_str(), n, ext.c_str());
1811 snprintf (buf, sizeof(buf), "%s-%" PRIu32 "%s", name.c_str(),
1815 sys::path source_path = source_dir / buf;
1817 if (!sys::exists (source_path)) {
1818 return source_path.to_string();
1822 error << string_compose (_("cannot create new file from region name \"%1\" with ident = \"%2\": too many existing files with similar names"),
1831 Session::load_sources (const XMLNode& node)
1834 XMLNodeConstIterator niter;
1835 boost::shared_ptr<Source> source;
1837 nlist = node.children();
1841 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1843 if ((source = XMLSourceFactory (**niter)) == 0) {
1844 error << _("Session: cannot create Source from XML description.") << endmsg;
1846 } catch (MissingSource& err) {
1847 warning << _("A sound file is missing. It will be replaced by silence.") << endmsg;
1848 source = SourceFactory::createSilent (*this, **niter, max_frames, _current_frame_rate);
1855 boost::shared_ptr<Source>
1856 Session::XMLSourceFactory (const XMLNode& node)
1858 if (node.name() != "Source") {
1859 return boost::shared_ptr<Source>();
1863 /* note: do peak building in another thread when loading session state */
1864 return SourceFactory::create (*this, node, true);
1867 catch (failed_constructor& err) {
1868 error << string_compose (_("Found a sound file that cannot be used by %1. Talk to the progammers."), PROGRAM_NAME) << endmsg;
1869 return boost::shared_ptr<Source>();
1874 Session::save_template (string template_name)
1878 if (_state_of_the_state & CannotSave) {
1882 sys::path user_template_dir(user_template_directory());
1886 sys::create_directories (user_template_dir);
1888 catch(sys::filesystem_error& ex)
1890 error << string_compose(_("Could not create mix templates directory \"%1\" (%2)"),
1891 user_template_dir.to_string(), ex.what()) << endmsg;
1895 tree.set_root (&get_template());
1897 sys::path template_file_path(user_template_dir);
1898 template_file_path /= template_name + template_suffix;
1900 if (sys::exists (template_file_path))
1902 warning << string_compose(_("Template \"%1\" already exists - new version not created"),
1903 template_file_path.to_string()) << endmsg;
1907 if (!tree.write (template_file_path.to_string())) {
1908 error << _("mix template not saved") << endmsg;
1916 Session::rename_template (string old_name, string new_name)
1918 sys::path old_path (user_template_directory());
1919 old_path /= old_name + template_suffix;
1921 sys::path new_path(user_template_directory());
1922 new_path /= new_name + template_suffix;
1924 if (sys::exists (new_path)) {
1925 warning << string_compose(_("Template \"%1\" already exists - template not renamed"),
1926 new_path.to_string()) << endmsg;
1931 sys::rename (old_path, new_path);
1939 Session::delete_template (string name)
1941 sys::path path = user_template_directory();
1942 path /= name + template_suffix;
1953 Session::refresh_disk_space ()
1956 struct statfs statfsbuf;
1957 vector<space_and_path>::iterator i;
1958 Glib::Mutex::Lock lm (space_lock);
1961 /* get freespace on every FS that is part of the session path */
1963 _total_free_4k_blocks = 0;
1965 for (i = session_dirs.begin(); i != session_dirs.end(); ++i) {
1966 statfs ((*i).path.c_str(), &statfsbuf);
1968 scale = statfsbuf.f_bsize/4096.0;
1970 (*i).blocks = (uint32_t) floor (statfsbuf.f_bavail * scale);
1971 _total_free_4k_blocks += (*i).blocks;
1977 Session::get_best_session_directory_for_new_source ()
1979 vector<space_and_path>::iterator i;
1980 string result = _session_dir->root_path().to_string();
1982 /* handle common case without system calls */
1984 if (session_dirs.size() == 1) {
1988 /* OK, here's the algorithm we're following here:
1990 We want to select which directory to use for
1991 the next file source to be created. Ideally,
1992 we'd like to use a round-robin process so as to
1993 get maximum performance benefits from splitting
1994 the files across multiple disks.
1996 However, in situations without much diskspace, an
1997 RR approach may end up filling up a filesystem
1998 with new files while others still have space.
1999 Its therefore important to pay some attention to
2000 the freespace in the filesystem holding each
2001 directory as well. However, if we did that by
2002 itself, we'd keep creating new files in the file
2003 system with the most space until it was as full
2004 as all others, thus negating any performance
2005 benefits of this RAID-1 like approach.
2007 So, we use a user-configurable space threshold. If
2008 there are at least 2 filesystems with more than this
2009 much space available, we use RR selection between them.
2010 If not, then we pick the filesystem with the most space.
2012 This gets a good balance between the two
2016 refresh_disk_space ();
2018 int free_enough = 0;
2020 for (i = session_dirs.begin(); i != session_dirs.end(); ++i) {
2021 if ((*i).blocks * 4096 >= Config->get_disk_choice_space_threshold()) {
2026 if (free_enough >= 2) {
2027 /* use RR selection process, ensuring that the one
2031 i = last_rr_session_dir;
2034 if (++i == session_dirs.end()) {
2035 i = session_dirs.begin();
2038 if ((*i).blocks * 4096 >= Config->get_disk_choice_space_threshold()) {
2039 if (create_session_directory ((*i).path)) {
2041 last_rr_session_dir = i;
2046 } while (i != last_rr_session_dir);
2050 /* pick FS with the most freespace (and that
2051 seems to actually work ...)
2054 vector<space_and_path> sorted;
2055 space_and_path_ascending_cmp cmp;
2057 sorted = session_dirs;
2058 sort (sorted.begin(), sorted.end(), cmp);
2060 for (i = sorted.begin(); i != sorted.end(); ++i) {
2061 if (create_session_directory ((*i).path)) {
2063 last_rr_session_dir = i;
2073 Session::load_named_selections (const XMLNode& node)
2076 XMLNodeConstIterator niter;
2079 nlist = node.children();
2083 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2085 if ((ns = XMLNamedSelectionFactory (**niter)) == 0) {
2086 error << _("Session: cannot create Named Selection from XML description.") << endmsg;
2094 Session::XMLNamedSelectionFactory (const XMLNode& node)
2097 return new NamedSelection (*this, node);
2100 catch (failed_constructor& err) {
2106 Session::automation_dir () const
2108 return Glib::build_filename (_path, "automation");
2112 Session::analysis_dir () const
2114 return Glib::build_filename (_path, "analysis");
2118 Session::load_bundles (XMLNode const & node)
2120 XMLNodeList nlist = node.children();
2121 XMLNodeConstIterator niter;
2125 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2126 if ((*niter)->name() == "InputBundle") {
2127 add_bundle (boost::shared_ptr<UserBundle> (new UserBundle (**niter, true)));
2128 } else if ((*niter)->name() == "OutputBundle") {
2129 add_bundle (boost::shared_ptr<UserBundle> (new UserBundle (**niter, false)));
2131 error << string_compose(_("Unknown node \"%1\" found in Bundles list from state file"), (*niter)->name()) << endmsg;
2140 Session::load_route_groups (const XMLNode& node, int version)
2142 XMLNodeList nlist = node.children();
2143 XMLNodeConstIterator niter;
2147 if (version >= 3000) {
2149 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2150 if ((*niter)->name() == "RouteGroup") {
2151 RouteGroup* rg = new RouteGroup (*this, "");
2152 add_route_group (rg);
2153 rg->set_state (**niter, version);
2157 } else if (version < 3000) {
2159 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2160 if ((*niter)->name() == "EditGroup" || (*niter)->name() == "MixGroup") {
2161 RouteGroup* rg = new RouteGroup (*this, "");
2162 add_route_group (rg);
2163 rg->set_state (**niter, version);
2172 Session::auto_save()
2174 save_state (_current_snapshot_name);
2178 state_file_filter (const string &str, void */*arg*/)
2180 return (str.length() > strlen(statefile_suffix) &&
2181 str.find (statefile_suffix) == (str.length() - strlen (statefile_suffix)));
2185 bool operator()(const string* a, const string* b) {
2191 remove_end(string* state)
2193 string statename(*state);
2195 string::size_type start,end;
2196 if ((start = statename.find_last_of ('/')) != string::npos) {
2197 statename = statename.substr (start+1);
2200 if ((end = statename.rfind(".ardour")) == string::npos) {
2201 end = statename.length();
2204 return new string(statename.substr (0, end));
2208 Session::possible_states (string path)
2210 PathScanner scanner;
2211 vector<string*>* states = scanner (path, state_file_filter, 0, false, false);
2213 transform(states->begin(), states->end(), states->begin(), remove_end);
2216 sort (states->begin(), states->end(), cmp);
2222 Session::possible_states () const
2224 return possible_states(_path);
2228 Session::add_route_group (RouteGroup* g)
2230 _route_groups.push_back (g);
2231 route_group_added (g); /* EMIT SIGNAL */
2236 Session::remove_route_group (RouteGroup& rg)
2238 list<RouteGroup*>::iterator i;
2240 if ((i = find (_route_groups.begin(), _route_groups.end(), &rg)) != _route_groups.end()) {
2241 _route_groups.erase (i);
2244 route_group_removed (); /* EMIT SIGNAL */
2250 Session::route_group_by_name (string name)
2252 list<RouteGroup *>::iterator i;
2254 for (i = _route_groups.begin(); i != _route_groups.end(); ++i) {
2255 if ((*i)->name() == name) {
2263 Session::start_reversible_command (const string& name)
2265 UndoTransaction* trans = new UndoTransaction();
2266 trans->set_name(name);
2271 Session::finish_reversible_command (UndoTransaction& ut)
2274 gettimeofday(&now, 0);
2275 ut.set_timestamp(now);
2280 Session::begin_reversible_command(const string& name)
2282 UndoTransaction* trans = new UndoTransaction();
2283 trans->set_name(name);
2285 if (!_current_trans.empty()) {
2286 _current_trans.top()->add_command (trans);
2288 _current_trans.push(trans);
2293 Session::commit_reversible_command(Command *cmd)
2295 assert(!_current_trans.empty());
2299 _current_trans.top()->add_command(cmd);
2302 if (_current_trans.top()->empty()) {
2303 _current_trans.pop();
2307 gettimeofday(&now, 0);
2308 _current_trans.top()->set_timestamp(now);
2310 _history.add(_current_trans.top());
2311 _current_trans.pop();
2315 accept_all_non_peak_files (const string& path, void */*arg*/)
2317 return (path.length() > 5 && path.find (peakfile_suffix) != (path.length() - 5));
2321 accept_all_state_files (const string& path, void */*arg*/)
2323 return (path.length() > 7 && path.find (".ardour") == (path.length() - 7));
2327 Session::find_all_sources (string path, set<string>& result)
2332 if (!tree.read (path)) {
2336 if ((node = find_named_node (*tree.root(), "Sources")) == 0) {
2341 XMLNodeConstIterator niter;
2343 nlist = node->children();
2347 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2351 if ((prop = (*niter)->property (X_("type"))) == 0) {
2355 DataType type (prop->value());
2357 if ((prop = (*niter)->property (X_("name"))) == 0) {
2361 if (prop->value()[0] == '/') {
2362 /* external file, ignore */
2366 Glib::ustring found_path;
2370 if (FileSource::find (type, prop->value(), true, is_new, chan, found_path)) {
2371 result.insert (found_path);
2379 Session::find_all_sources_across_snapshots (set<string>& result, bool exclude_this_snapshot)
2381 PathScanner scanner;
2382 vector<string*>* state_files;
2384 string this_snapshot_path;
2390 if (ripped[ripped.length()-1] == '/') {
2391 ripped = ripped.substr (0, ripped.length() - 1);
2394 state_files = scanner (ripped, accept_all_state_files, (void *) 0, false, true);
2396 if (state_files == 0) {
2401 this_snapshot_path = _path;
2402 this_snapshot_path += legalize_for_path (_current_snapshot_name);
2403 this_snapshot_path += statefile_suffix;
2405 for (vector<string*>::iterator i = state_files->begin(); i != state_files->end(); ++i) {
2407 if (exclude_this_snapshot && **i == this_snapshot_path) {
2411 if (find_all_sources (**i, result) < 0) {
2419 struct RegionCounter {
2420 typedef std::map<PBD::ID,boost::shared_ptr<AudioSource> > AudioSourceList;
2421 AudioSourceList::iterator iter;
2422 boost::shared_ptr<Region> region;
2425 RegionCounter() : count (0) {}
2429 Session::ask_about_playlist_deletion (boost::shared_ptr<Playlist> p)
2431 return *AskAboutPlaylistDeletion (p);
2435 Session::cleanup_sources (CleanupReport& rep)
2437 // FIXME: needs adaptation to midi
2439 vector<boost::shared_ptr<Source> > dead_sources;
2440 PathScanner scanner;
2442 vector<space_and_path>::iterator i;
2443 vector<space_and_path>::iterator nexti;
2444 vector<string*>* soundfiles;
2445 vector<string> unused;
2446 set<string> all_sources;
2451 _state_of_the_state = (StateOfTheState) (_state_of_the_state | InCleanup);
2453 /* step 1: consider deleting all unused playlists */
2455 if (playlists->maybe_delete_unused (boost::bind (Session::ask_about_playlist_deletion, _1))) {
2460 /* step 2: find all un-used sources */
2465 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ) {
2467 SourceMap::iterator tmp;
2472 /* do not bother with files that are zero size, otherwise we remove the current "nascent"
2476 if (!playlists->source_use_count(i->second) && i->second->length(i->second->timeline_position()) > 0) {
2477 dead_sources.push_back (i->second);
2478 i->second->drop_references ();
2484 /* build a list of all the possible sound directories for the session */
2486 for (i = session_dirs.begin(); i != session_dirs.end(); ) {
2491 SessionDirectory sdir ((*i).path);
2492 sound_path += sdir.sound_path().to_string();
2494 if (nexti != session_dirs.end()) {
2501 /* now do the same thing for the files that ended up in the sounds dir(s)
2502 but are not referenced as sources in any snapshot.
2505 soundfiles = scanner (sound_path, accept_all_non_peak_files, (void *) 0, false, true);
2507 if (soundfiles == 0) {
2511 /* find all sources, but don't use this snapshot because the
2512 state file on disk still references sources we may have already
2516 find_all_sources_across_snapshots (all_sources, true);
2518 /* add our current source list
2521 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ++i) {
2522 boost::shared_ptr<FileSource> fs;
2524 if ((fs = boost::dynamic_pointer_cast<FileSource> (i->second)) != 0) {
2525 all_sources.insert (fs->path());
2529 char tmppath1[PATH_MAX+1];
2530 char tmppath2[PATH_MAX+1];
2532 for (vector<string*>::iterator x = soundfiles->begin(); x != soundfiles->end(); ++x) {
2537 for (set<string>::iterator i = all_sources.begin(); i != all_sources.end(); ++i) {
2539 realpath(spath.c_str(), tmppath1);
2540 realpath((*i).c_str(), tmppath2);
2542 if (strcmp(tmppath1, tmppath2) == 0) {
2549 unused.push_back (spath);
2553 /* now try to move all unused files into the "dead_sounds" directory(ies) */
2555 for (vector<string>::iterator x = unused.begin(); x != unused.end(); ++x) {
2556 struct stat statbuf;
2558 rep.paths.push_back (*x);
2559 if (stat ((*x).c_str(), &statbuf) == 0) {
2560 rep.space += statbuf.st_size;
2565 /* don't move the file across filesystems, just
2566 stick it in the `dead_sound_dir_name' directory
2567 on whichever filesystem it was already on.
2570 if ((*x).find ("/sounds/") != string::npos) {
2572 /* old school, go up 1 level */
2574 newpath = Glib::path_get_dirname (*x); // "sounds"
2575 newpath = Glib::path_get_dirname (newpath); // "session-name"
2579 /* new school, go up 4 levels */
2581 newpath = Glib::path_get_dirname (*x); // "audiofiles"
2582 newpath = Glib::path_get_dirname (newpath); // "session-name"
2583 newpath = Glib::path_get_dirname (newpath); // "interchange"
2584 newpath = Glib::path_get_dirname (newpath); // "session-dir"
2588 newpath += dead_sound_dir_name;
2590 if (g_mkdir_with_parents (newpath.c_str(), 0755) < 0) {
2591 error << string_compose(_("Session: cannot create session peakfile folder \"%1\" (%2)"), newpath, strerror (errno)) << endmsg;
2596 newpath += Glib::path_get_basename ((*x));
2598 if (access (newpath.c_str(), F_OK) == 0) {
2600 /* the new path already exists, try versioning */
2602 char buf[PATH_MAX+1];
2606 snprintf (buf, sizeof (buf), "%s.%d", newpath.c_str(), version);
2609 while (access (newpath_v.c_str(), F_OK) == 0 && version < 999) {
2610 snprintf (buf, sizeof (buf), "%s.%d", newpath.c_str(), ++version);
2614 if (version == 999) {
2615 error << string_compose (_("there are already 1000 files with names like %1; versioning discontinued"),
2619 newpath = newpath_v;
2624 /* it doesn't exist, or we can't read it or something */
2628 if (::rename ((*x).c_str(), newpath.c_str()) != 0) {
2629 error << string_compose (_("cannot rename audio file source from %1 to %2 (%3)"),
2630 (*x), newpath, strerror (errno))
2635 /* see if there an easy to find peakfile for this file, and remove it.
2638 string peakpath = (*x).substr (0, (*x).find_last_of ('.'));
2639 peakpath += peakfile_suffix;
2641 if (access (peakpath.c_str(), W_OK) == 0) {
2642 if (::unlink (peakpath.c_str()) != 0) {
2643 error << string_compose (_("cannot remove peakfile %1 for %2 (%3)"),
2644 peakpath, _path, strerror (errno))
2646 /* try to back out */
2647 rename (newpath.c_str(), _path.c_str());
2655 /* dump the history list */
2659 /* save state so we don't end up a session file
2660 referring to non-existent sources.
2666 _state_of_the_state = (StateOfTheState) (_state_of_the_state & ~InCleanup);
2672 Session::cleanup_trash_sources (CleanupReport& rep)
2674 // FIXME: needs adaptation for MIDI
2676 vector<space_and_path>::iterator i;
2677 string dead_sound_dir;
2678 struct dirent* dentry;
2679 struct stat statbuf;
2685 for (i = session_dirs.begin(); i != session_dirs.end(); ++i) {
2687 dead_sound_dir = (*i).path;
2688 dead_sound_dir += dead_sound_dir_name;
2690 if ((dead = opendir (dead_sound_dir.c_str())) == 0) {
2694 while ((dentry = readdir (dead)) != 0) {
2696 /* avoid '.' and '..' */
2698 if ((dentry->d_name[0] == '.' && dentry->d_name[1] == '\0') ||
2699 (dentry->d_name[2] == '\0' && dentry->d_name[0] == '.' && dentry->d_name[1] == '.')) {
2705 fullpath = dead_sound_dir;
2707 fullpath += dentry->d_name;
2709 if (stat (fullpath.c_str(), &statbuf)) {
2713 if (!S_ISREG (statbuf.st_mode)) {
2717 if (unlink (fullpath.c_str())) {
2718 error << string_compose (_("cannot remove dead sound file %1 (%2)"),
2719 fullpath, strerror (errno))
2723 rep.paths.push_back (dentry->d_name);
2724 rep.space += statbuf.st_size;
2735 Session::set_dirty ()
2737 bool was_dirty = dirty();
2739 _state_of_the_state = StateOfTheState (_state_of_the_state | Dirty);
2743 DirtyChanged(); /* EMIT SIGNAL */
2749 Session::set_clean ()
2751 bool was_dirty = dirty();
2753 _state_of_the_state = Clean;
2757 DirtyChanged(); /* EMIT SIGNAL */
2762 Session::set_deletion_in_progress ()
2764 _state_of_the_state = StateOfTheState (_state_of_the_state | Deletion);
2768 Session::clear_deletion_in_progress ()
2770 _state_of_the_state = StateOfTheState (_state_of_the_state & (~Deletion));
2774 Session::add_controllable (boost::shared_ptr<Controllable> c)
2776 /* this adds a controllable to the list managed by the Session.
2777 this is a subset of those managed by the Controllable class
2778 itself, and represents the only ones whose state will be saved
2779 as part of the session.
2782 Glib::Mutex::Lock lm (controllables_lock);
2783 controllables.insert (c);
2786 struct null_deleter { void operator()(void const *) const {} };
2789 Session::remove_controllable (Controllable* c)
2791 if (_state_of_the_state | Deletion) {
2795 Glib::Mutex::Lock lm (controllables_lock);
2797 Controllables::iterator x = controllables.find (boost::shared_ptr<Controllable>(c, null_deleter()));
2799 if (x != controllables.end()) {
2800 controllables.erase (x);
2804 boost::shared_ptr<Controllable>
2805 Session::controllable_by_id (const PBD::ID& id)
2807 Glib::Mutex::Lock lm (controllables_lock);
2809 for (Controllables::iterator i = controllables.begin(); i != controllables.end(); ++i) {
2810 if ((*i)->id() == id) {
2815 return boost::shared_ptr<Controllable>();
2818 boost::shared_ptr<Controllable>
2819 Session::controllable_by_descriptor (const ControllableDescriptor& desc)
2821 boost::shared_ptr<Controllable> c;
2822 boost::shared_ptr<Route> r;
2824 switch (desc.top_level_type()) {
2825 case ControllableDescriptor::NamedRoute:
2827 std::string str = desc.top_level_name();
2828 if (str == "master") {
2830 } else if (str == "control" || str == "listen") {
2833 r = route_by_name (desc.top_level_name());
2838 case ControllableDescriptor::RemoteControlID:
2839 r = route_by_remote_id (desc.rid());
2847 switch (desc.subtype()) {
2848 case ControllableDescriptor::Gain:
2849 c = r->gain_control ();
2852 case ControllableDescriptor::Solo:
2853 c = r->solo_control();
2856 case ControllableDescriptor::Mute:
2857 c = r->mute_control();
2860 case ControllableDescriptor::Recenable:
2862 boost::shared_ptr<Track> t = boost::dynamic_pointer_cast<Track>(r);
2865 c = t->rec_enable_control ();
2870 case ControllableDescriptor::Pan:
2871 /* XXX pan control */
2874 case ControllableDescriptor::Balance:
2875 /* XXX simple pan control */
2878 case ControllableDescriptor::PluginParameter:
2880 uint32_t plugin = desc.target (0);
2881 uint32_t parameter_index = desc.target (1);
2883 /* revert to zero based counting */
2889 if (parameter_index > 0) {
2893 boost::shared_ptr<Processor> p = r->nth_plugin (plugin);
2896 c = boost::dynamic_pointer_cast<ARDOUR::AutomationControl>(
2897 p->control(Evoral::Parameter(PluginAutomation, 0, parameter_index)));
2902 case ControllableDescriptor::SendGain:
2904 uint32_t send = desc.target (0);
2906 /* revert to zero-based counting */
2912 boost::shared_ptr<Processor> p = r->nth_send (send);
2915 boost::shared_ptr<Send> s = boost::dynamic_pointer_cast<Send>(p);
2916 boost::shared_ptr<Amp> a = s->amp();
2919 c = s->amp()->gain_control();
2926 /* relax and return a null pointer */
2934 Session::add_instant_xml (XMLNode& node, bool write_to_config)
2937 Stateful::add_instant_xml (node, _path);
2940 if (write_to_config) {
2941 Config->add_instant_xml (node);
2946 Session::instant_xml (const string& node_name)
2948 return Stateful::instant_xml (node_name, _path);
2952 Session::save_history (string snapshot_name)
2960 if (snapshot_name.empty()) {
2961 snapshot_name = _current_snapshot_name;
2964 const string history_filename = legalize_for_path (snapshot_name) + history_suffix;
2965 const string backup_filename = history_filename + backup_suffix;
2966 const sys::path xml_path = _session_dir->root_path() / history_filename;
2967 const sys::path backup_path = _session_dir->root_path() / backup_filename;
2969 if (sys::exists (xml_path)) {
2972 sys::rename (xml_path, backup_path);
2974 catch (const sys::filesystem_error& err)
2976 error << _("could not backup old history file, current history not saved") << endmsg;
2981 if (!Config->get_save_history() || Config->get_saved_history_depth() < 0) {
2985 tree.set_root (&_history.get_state (Config->get_saved_history_depth()));
2987 if (!tree.write (xml_path.to_string()))
2989 error << string_compose (_("history could not be saved to %1"), xml_path.to_string()) << endmsg;
2993 sys::remove (xml_path);
2994 sys::rename (backup_path, xml_path);
2996 catch (const sys::filesystem_error& err)
2998 error << string_compose (_("could not restore history file from backup %1 (%2)"),
2999 backup_path.to_string(), err.what()) << endmsg;
3009 Session::restore_history (string snapshot_name)
3013 if (snapshot_name.empty()) {
3014 snapshot_name = _current_snapshot_name;
3017 const string xml_filename = legalize_for_path (snapshot_name) + history_suffix;
3018 const sys::path xml_path = _session_dir->root_path() / xml_filename;
3020 info << "Loading history from " << xml_path.to_string() << endmsg;
3022 if (!sys::exists (xml_path)) {
3023 info << string_compose (_("%1: no history file \"%2\" for this session."),
3024 _name, xml_path.to_string()) << endmsg;
3028 if (!tree.read (xml_path.to_string())) {
3029 error << string_compose (_("Could not understand session history file \"%1\""),
3030 xml_path.to_string()) << endmsg;
3037 for (XMLNodeConstIterator it = tree.root()->children().begin(); it != tree.root()->children().end(); it++) {
3040 UndoTransaction* ut = new UndoTransaction ();
3043 ut->set_name(t->property("name")->value());
3044 stringstream ss(t->property("tv-sec")->value());
3046 ss.str(t->property("tv-usec")->value());
3048 ut->set_timestamp(tv);
3050 for (XMLNodeConstIterator child_it = t->children().begin();
3051 child_it != t->children().end(); child_it++)
3053 XMLNode *n = *child_it;
3056 if (n->name() == "MementoCommand" ||
3057 n->name() == "MementoUndoCommand" ||
3058 n->name() == "MementoRedoCommand") {
3060 if ((c = memento_command_factory(n))) {
3064 } else if (n->name() == "DeltaCommand") {
3065 PBD::ID id(n->property("midi-source")->value());
3066 boost::shared_ptr<MidiSource> midi_source =
3067 boost::dynamic_pointer_cast<MidiSource, Source>(source_by_id(id));
3069 ut->add_command(new MidiModel::DeltaCommand(midi_source->model(), *n));
3071 error << _("Failed to downcast MidiSource for DeltaCommand") << endmsg;
3074 } else if (n->name() == "DiffCommand") {
3075 PBD::ID id(n->property("midi-source")->value());
3076 boost::shared_ptr<MidiSource> midi_source =
3077 boost::dynamic_pointer_cast<MidiSource, Source>(source_by_id(id));
3079 ut->add_command(new MidiModel::DiffCommand(midi_source->model(), *n));
3081 error << _("Failed to downcast MidiSource for DeltaCommand") << endmsg;
3084 } else if (n->name() == "StatefulDiffCommand") {
3085 if ((c = stateful_diff_command_factory (n))) {
3086 ut->add_command (c);
3089 error << string_compose(_("Couldn't figure out how to make a Command out of a %1 XMLNode."), n->name()) << endmsg;
3100 Session::config_changed (std::string p, bool ours)
3106 if (p == "seamless-loop") {
3108 } else if (p == "rf-speed") {
3110 } else if (p == "auto-loop") {
3112 } else if (p == "auto-input") {
3114 if (Config->get_monitoring_model() == HardwareMonitoring && transport_rolling()) {
3115 /* auto-input only makes a difference if we're rolling */
3117 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
3119 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
3120 if ((*i)->record_enabled ()) {
3121 (*i)->monitor_input (!config.get_auto_input());
3126 } else if (p == "punch-in") {
3130 if ((location = _locations.auto_punch_location()) != 0) {
3132 if (config.get_punch_in ()) {
3133 replace_event (SessionEvent::PunchIn, location->start());
3135 remove_event (location->start(), SessionEvent::PunchIn);
3139 } else if (p == "punch-out") {
3143 if ((location = _locations.auto_punch_location()) != 0) {
3145 if (config.get_punch_out()) {
3146 replace_event (SessionEvent::PunchOut, location->end());
3148 clear_events (SessionEvent::PunchOut);
3152 } else if (p == "edit-mode") {
3154 Glib::Mutex::Lock lm (playlists->lock);
3156 for (SessionPlaylists::List::iterator i = playlists->playlists.begin(); i != playlists->playlists.end(); ++i) {
3157 (*i)->set_edit_mode (Config->get_edit_mode ());
3160 } else if (p == "use-video-sync") {
3162 waiting_for_sync_offset = config.get_use_video_sync();
3164 } else if (p == "mmc-control") {
3166 //poke_midi_thread ();
3168 } else if (p == "mmc-device-id" || p == "mmc-receive-id") {
3171 mmc->set_receive_device_id (Config->get_mmc_receive_device_id());
3174 } else if (p == "mmc-send-id") {
3177 mmc->set_send_device_id (Config->get_mmc_send_device_id());
3180 } else if (p == "midi-control") {
3182 //poke_midi_thread ();
3184 } else if (p == "raid-path") {
3186 setup_raid_path (config.get_raid_path());
3188 } else if (p == "timecode-format") {
3192 } else if (p == "video-pullup") {
3196 } else if (p == "seamless-loop") {
3198 if (play_loop && transport_rolling()) {
3199 // to reset diskstreams etc
3200 request_play_loop (true);
3203 } else if (p == "rf-speed") {
3205 cumulative_rf_motion = 0;
3208 } else if (p == "click-sound") {
3210 setup_click_sounds (1);
3212 } else if (p == "click-emphasis-sound") {
3214 setup_click_sounds (-1);
3216 } else if (p == "clicking") {
3218 if (Config->get_clicking()) {
3219 if (_click_io && click_data) { // don't require emphasis data
3226 } else if (p == "send-mtc") {
3228 /* only set the internal flag if we have
3232 if (_mtc_port != 0) {
3233 session_send_mtc = Config->get_send_mtc();
3234 if (session_send_mtc) {
3235 /* mark us ready to send */
3236 next_quarter_frame_to_send = 0;
3239 session_send_mtc = false;
3242 } else if (p == "send-mmc") {
3244 /* only set the internal flag if we have
3248 if (_mmc_port != 0) {
3249 session_send_mmc = Config->get_send_mmc();
3252 session_send_mmc = false;
3255 } else if (p == "midi-feedback") {
3257 /* only set the internal flag if we have
3261 if (_mtc_port != 0) {
3262 session_midi_feedback = Config->get_midi_feedback();
3265 } else if (p == "jack-time-master") {
3267 engine().reset_timebase ();
3269 } else if (p == "native-file-header-format") {
3271 if (!first_file_header_format_reset) {
3272 reset_native_file_format ();
3275 first_file_header_format_reset = false;
3277 } else if (p == "native-file-data-format") {
3279 if (!first_file_data_format_reset) {
3280 reset_native_file_format ();
3283 first_file_data_format_reset = false;
3285 } else if (p == "external-sync") {
3286 if (!config.get_external_sync()) {
3287 drop_sync_source ();
3289 switch_to_sync_source (config.get_sync_source());
3291 } else if (p == "remote-model") {
3292 set_remote_control_ids ();
3293 } else if (p == "denormal-model") {
3295 } else if (p == "history-depth") {
3296 set_history_depth (Config->get_history_depth());
3297 } else if (p == "sync-all-route-ordering") {
3298 sync_order_keys ("session");
3299 } else if (p == "initial-program-change") {
3301 if (_mmc_port && Config->get_initial_program_change() >= 0) {
3304 buf[0] = MIDI::program; // channel zero by default
3305 buf[1] = (Config->get_initial_program_change() & 0x7f);
3307 _mmc_port->midimsg (buf, sizeof (buf), 0);
3309 } else if (p == "initial-program-change") {
3311 if (_mmc_port && Config->get_initial_program_change() >= 0) {
3312 MIDI::byte* buf = new MIDI::byte[2];
3314 buf[0] = MIDI::program; // channel zero by default
3315 buf[1] = (Config->get_initial_program_change() & 0x7f);
3316 // deliver_midi (_mmc_port, buf, 2);
3318 } else if (p == "solo-mute-override") {
3319 // catch_up_on_solo_mute_override ();
3320 } else if (p == "listen-position") {
3321 listen_position_changed ();
3322 } else if (p == "solo-control-is-listen-control") {
3323 solo_control_mode_changed ();
3331 Session::set_history_depth (uint32_t d)
3333 _history.set_depth (d);