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
33 #include <sigc++/bind.h>
35 #include <cstdio> /* snprintf(3) ... grrr */
50 #include <sys/param.h>
51 #include <sys/mount.h>
55 #include <glibmm/thread.h>
57 #include "midi++/mmc.h"
58 #include "midi++/port.h"
60 #include "pbd/error.h"
61 #include "pbd/pathscanner.h"
62 #include "pbd/pthread_utils.h"
63 #include "pbd/search_path.h"
64 #include "pbd/stacktrace.h"
66 #include "ardour/audioengine.h"
67 #include "ardour/configuration.h"
68 #include "ardour/session.h"
69 #include "ardour/session_directory.h"
70 #include "ardour/session_utils.h"
71 #include "ardour/session_state_utils.h"
72 #include "ardour/session_metadata.h"
73 #include "ardour/buffer.h"
74 #include "ardour/audio_diskstream.h"
75 #include "ardour/midi_diskstream.h"
76 #include "ardour/utils.h"
77 #include "ardour/audioplaylist.h"
78 #include "ardour/midi_playlist.h"
79 #include "ardour/smf_source.h"
80 #include "ardour/audiofilesource.h"
81 #include "ardour/silentfilesource.h"
82 #include "ardour/sndfilesource.h"
83 #include "ardour/midi_source.h"
84 #include "ardour/sndfile_helpers.h"
85 #include "ardour/auditioner.h"
86 #include "ardour/io_processor.h"
87 #include "ardour/send.h"
88 #include "ardour/processor.h"
89 #include "ardour/user_bundle.h"
90 #include "ardour/slave.h"
91 #include "ardour/tempo.h"
92 #include "ardour/audio_track.h"
93 #include "ardour/midi_track.h"
94 #include "ardour/midi_patch_manager.h"
95 #include "ardour/cycle_timer.h"
96 #include "ardour/utils.h"
97 #include "ardour/named_selection.h"
98 #include "ardour/version.h"
99 #include "ardour/location.h"
100 #include "ardour/audioregion.h"
101 #include "ardour/midi_region.h"
102 #include "ardour/crossfade.h"
103 #include "ardour/control_protocol_manager.h"
104 #include "ardour/region_factory.h"
105 #include "ardour/source_factory.h"
106 #include "ardour/playlist_factory.h"
107 #include "ardour/filename_extensions.h"
108 #include "ardour/directory_names.h"
109 #include "ardour/template_utils.h"
110 #include "ardour/ticker.h"
111 #include "ardour/route_group.h"
113 #include "control_protocol/control_protocol.h"
119 using namespace ARDOUR;
123 Session::first_stage_init (string fullpath, string snapshot_name)
125 if (fullpath.length() == 0) {
127 throw failed_constructor();
130 char buf[PATH_MAX+1];
131 if (!realpath (fullpath.c_str(), buf) && (errno != ENOENT)) {
132 error << string_compose(_("Could not use path %1 (%s)"), buf, strerror(errno)) << endmsg;
134 throw failed_constructor();
139 if (_path[_path.length()-1] != '/') {
143 /* these two are just provisional settings. set_state()
144 will likely override them.
147 _name = _current_snapshot_name = snapshot_name;
149 set_history_depth (Config->get_history_depth());
151 _current_frame_rate = _engine.frame_rate ();
152 _nominal_frame_rate = _current_frame_rate;
153 _base_frame_rate = _current_frame_rate;
155 _tempo_map = new TempoMap (_current_frame_rate);
156 _tempo_map->StateChanged.connect (mem_fun (*this, &Session::tempo_map_changed));
159 _non_soloed_outs_muted = false;
161 g_atomic_int_set (&processing_prohibited, 0);
162 _transport_speed = 0;
163 _last_transport_speed = 0;
164 _target_transport_speed = 0;
165 auto_play_legal = false;
166 transport_sub_state = 0;
167 _transport_frame = 0;
168 end_location = new Location (0, 0, _("end"), Location::Flags ((Location::IsMark|Location::IsEnd)));
169 start_location = new Location (0, 0, _("start"), Location::Flags ((Location::IsMark|Location::IsStart)));
170 g_atomic_int_set (&_record_status, Disabled);
171 loop_changing = false;
174 _last_roll_location = 0;
175 _last_record_location = 0;
176 pending_locate_frame = 0;
177 pending_locate_roll = false;
178 pending_locate_flush = false;
179 audio_dstream_buffer_size = 0;
180 midi_dstream_buffer_size = 0;
181 state_was_pending = false;
183 outbound_mtc_smpte_frame = 0;
184 next_quarter_frame_to_send = -1;
185 current_block_size = 0;
186 solo_update_disabled = false;
187 _have_captured = false;
188 _worst_output_latency = 0;
189 _worst_input_latency = 0;
190 _worst_track_latency = 0;
191 _state_of_the_state = StateOfTheState(CannotSave|InitialConnecting|Loading);
194 session_send_mmc = false;
195 session_send_mtc = false;
196 post_transport_work = PostTransportWork (0);
197 g_atomic_int_set (&butler_should_do_transport_work, 0);
198 g_atomic_int_set (&_playback_load, 100);
199 g_atomic_int_set (&_capture_load, 100);
200 g_atomic_int_set (&_playback_load_min, 100);
201 g_atomic_int_set (&_capture_load_min, 100);
204 _exporting_realtime = false;
205 _gain_automation_buffer = 0;
206 _pan_automation_buffer = 0;
208 pending_abort = false;
209 destructive_index = 0;
210 first_file_data_format_reset = true;
211 first_file_header_format_reset = true;
212 butler_thread = (pthread_t) 0;
213 //midi_thread = (pthread_t) 0;
215 AudioDiskstream::allocate_working_buffers();
217 /* default short fade = 15ms */
219 Crossfade::set_short_xfade_length ((nframes_t) floor (config.get_short_xfade_seconds() * frame_rate()));
220 SndFileSource::setup_standard_crossfades (*this, frame_rate());
222 last_mmc_step.tv_sec = 0;
223 last_mmc_step.tv_usec = 0;
226 /* click sounds are unset by default, which causes us to internal
227 waveforms for clicks.
231 click_emphasis_length = 0;
234 process_function = &Session::process_with_events;
236 if (config.get_use_video_sync()) {
237 waiting_for_sync_offset = true;
239 waiting_for_sync_offset = false;
244 _smpte_offset_negative = true;
245 last_smpte_valid = false;
249 last_rr_session_dir = session_dirs.begin();
250 refresh_disk_space ();
252 // set_default_fade (0.2, 5.0); /* steepness, millisecs */
256 average_slave_delta = 1800; // !!! why 1800 ????
257 have_first_delta_accumulator = false;
258 delta_accumulator_cnt = 0;
259 slave_state = Stopped;
261 _engine.GraphReordered.connect (mem_fun (*this, &Session::graph_reordered));
263 /* These are all static "per-class" signals */
265 RegionFactory::CheckNewRegion.connect (mem_fun (*this, &Session::add_region));
266 SourceFactory::SourceCreated.connect (mem_fun (*this, &Session::add_source));
267 PlaylistFactory::PlaylistCreated.connect (mem_fun (*this, &Session::add_playlist));
268 Processor::ProcessorCreated.connect (mem_fun (*this, &Session::add_processor));
269 NamedSelection::NamedSelectionCreated.connect (mem_fun (*this, &Session::add_named_selection));
270 AutomationList::AutomationListCreated.connect (mem_fun (*this, &Session::add_automation_list));
272 Controllable::Destroyed.connect (mem_fun (*this, &Session::remove_controllable));
274 IO::PortCountChanged.connect (mem_fun (*this, &Session::ensure_buffers));
276 /* stop IO objects from doing stuff until we're ready for them */
278 Delivery::disable_panners ();
279 IO::disable_connecting ();
283 Session::second_stage_init (bool new_session)
285 AudioFileSource::set_peak_dir (_session_dir->peak_path().to_string());
288 if (load_state (_current_snapshot_name)) {
291 remove_empty_sounds ();
294 if (start_butler_thread()) {
298 if (start_midi_thread ()) {
302 // set_state() will call setup_raid_path(), but if it's a new session we need
303 // to call setup_raid_path() here.
306 if (set_state (*state_tree->root())) {
310 setup_raid_path(_path);
313 /* we can't save till after ::when_engine_running() is called,
314 because otherwise we save state with no connections made.
315 therefore, we reset _state_of_the_state because ::set_state()
316 will have cleared it.
318 we also have to include Loading so that any events that get
319 generated between here and the end of ::when_engine_running()
320 will be processed directly rather than queued.
323 _state_of_the_state = StateOfTheState (_state_of_the_state|CannotSave|Loading);
326 _locations.changed.connect (mem_fun (this, &Session::locations_changed));
327 _locations.added.connect (mem_fun (this, &Session::locations_added));
328 setup_click_sounds (0);
329 setup_midi_control ();
331 /* Pay attention ... */
333 _engine.Halted.connect (mem_fun (*this, &Session::engine_halted));
334 _engine.Xrun.connect (mem_fun (*this, &Session::xrun_recovery));
337 when_engine_running();
340 /* handle this one in a different way than all others, so that its clear what happened */
342 catch (AudioEngine::PortRegistrationFailure& err) {
343 error << err.what() << endmsg;
351 BootMessage (_("Reset Remote Controls"));
353 send_full_time_code (0);
354 _engine.transport_locate (0);
355 deliver_mmc (MIDI::MachineControl::cmdMmcReset, 0);
356 deliver_mmc (MIDI::MachineControl::cmdLocate, 0);
358 MidiClockTicker::instance().set_session(*this);
359 MIDI::Name::MidiPatchManager::instance().set_session(*this);
361 /* initial program change will be delivered later; see ::config_changed() */
363 BootMessage (_("Reset Control Protocols"));
365 ControlProtocolManager::instance().set_session (*this);
367 config.set_end_marker_is_free (new_session);
369 _state_of_the_state = Clean;
371 DirtyChanged (); /* EMIT SIGNAL */
373 if (state_was_pending) {
374 save_state (_current_snapshot_name);
375 remove_pending_capture_state ();
376 state_was_pending = false;
379 BootMessage (_("Session loading complete"));
385 Session::raid_path () const
387 SearchPath raid_search_path;
389 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
390 raid_search_path += sys::path((*i).path);
393 return raid_search_path.to_string ();
397 Session::setup_raid_path (string path)
406 session_dirs.clear ();
408 SearchPath search_path(path);
409 SearchPath sound_search_path;
410 SearchPath midi_search_path;
412 for (SearchPath::const_iterator i = search_path.begin(); i != search_path.end(); ++i) {
413 sp.path = (*i).to_string ();
414 sp.blocks = 0; // not needed
415 session_dirs.push_back (sp);
417 SessionDirectory sdir(sp.path);
419 sound_search_path += sdir.sound_path ();
420 midi_search_path += sdir.midi_path ();
423 // set the search path for each data type
424 FileSource::set_search_path (DataType::AUDIO, sound_search_path.to_string ());
425 SMFSource::set_search_path (DataType::MIDI, midi_search_path.to_string ());
427 // reset the round-robin soundfile path thingie
428 last_rr_session_dir = session_dirs.begin();
432 Session::ensure_subdirs ()
436 dir = session_directory().peak_path().to_string();
438 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
439 error << string_compose(_("Session: cannot create session peakfile folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
443 dir = session_directory().sound_path().to_string();
445 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
446 error << string_compose(_("Session: cannot create session sounds dir \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
450 dir = session_directory().midi_path().to_string();
452 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
453 error << string_compose(_("Session: cannot create session midi dir \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
457 dir = session_directory().dead_sound_path().to_string();
459 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
460 error << string_compose(_("Session: cannot create session dead sounds folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
464 dir = session_directory().export_path().to_string();
466 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
467 error << string_compose(_("Session: cannot create session export folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
471 dir = analysis_dir ();
473 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
474 error << string_compose(_("Session: cannot create session analysis folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
482 Session::create (bool& new_session, const string& mix_template, nframes_t initial_length)
485 if (g_mkdir_with_parents (_path.c_str(), 0755) < 0) {
486 error << string_compose(_("Session: cannot create session folder \"%1\" (%2)"), _path, strerror (errno)) << endmsg;
490 if (ensure_subdirs ()) {
494 /* check new_session so we don't overwrite an existing one */
496 if (!mix_template.empty()) {
497 std::string in_path = mix_template;
499 ifstream in(in_path.c_str());
502 string out_path = _path;
504 out_path += statefile_suffix;
506 ofstream out(out_path.c_str());
511 // okay, session is set up. Treat like normal saved
512 // session from now on.
518 error << string_compose (_("Could not open %1 for writing mix template"), out_path)
524 error << string_compose (_("Could not open mix template %1 for reading"), in_path)
531 /* Instantiate metadata */
533 _metadata = new SessionMetadata ();
535 /* set initial start + end point */
537 start_location->set_end (0);
538 _locations.add (start_location);
540 end_location->set_end (initial_length);
541 _locations.add (end_location);
543 _state_of_the_state = Clean;
552 Session::load_diskstreams (const XMLNode& node)
555 XMLNodeConstIterator citer;
557 clist = node.children();
559 for (citer = clist.begin(); citer != clist.end(); ++citer) {
562 /* diskstreams added automatically by DiskstreamCreated handler */
563 if ((*citer)->name() == "AudioDiskstream" || (*citer)->name() == "DiskStream") {
564 boost::shared_ptr<AudioDiskstream> dstream (new AudioDiskstream (*this, **citer));
565 add_diskstream (dstream);
566 } else if ((*citer)->name() == "MidiDiskstream") {
567 boost::shared_ptr<MidiDiskstream> dstream (new MidiDiskstream (*this, **citer));
568 add_diskstream (dstream);
570 error << _("Session: unknown diskstream type in XML") << endmsg;
574 catch (failed_constructor& err) {
575 error << _("Session: could not load diskstream via XML state") << endmsg;
584 Session::maybe_write_autosave()
586 if (dirty() && record_status() != Recording) {
587 save_state("", true);
592 Session::remove_pending_capture_state ()
594 sys::path pending_state_file_path(_session_dir->root_path());
596 pending_state_file_path /= legalize_for_path (_current_snapshot_name) + pending_suffix;
600 sys::remove (pending_state_file_path);
602 catch(sys::filesystem_error& ex)
604 error << string_compose(_("Could remove pending capture state at path \"%1\" (%2)"),
605 pending_state_file_path.to_string(), ex.what()) << endmsg;
609 /** Rename a state file.
610 * @param snapshot_name Snapshot name.
613 Session::rename_state (string old_name, string new_name)
615 if (old_name == _current_snapshot_name || old_name == _name) {
616 /* refuse to rename the current snapshot or the "main" one */
620 const string old_xml_filename = legalize_for_path (old_name) + statefile_suffix;
621 const string new_xml_filename = legalize_for_path (new_name) + statefile_suffix;
623 const sys::path old_xml_path = _session_dir->root_path() / old_xml_filename;
624 const sys::path new_xml_path = _session_dir->root_path() / new_xml_filename;
628 sys::rename (old_xml_path, new_xml_path);
630 catch (const sys::filesystem_error& err)
632 error << string_compose(_("could not rename snapshot %1 to %2 (%3)"),
633 old_name, new_name, err.what()) << endmsg;
637 /** Remove a state file.
638 * @param snapshot_name Snapshot name.
641 Session::remove_state (string snapshot_name)
643 if (snapshot_name == _current_snapshot_name || snapshot_name == _name) {
644 // refuse to remove the current snapshot or the "main" one
648 sys::path xml_path(_session_dir->root_path());
650 xml_path /= legalize_for_path (snapshot_name) + statefile_suffix;
652 if (!create_backup_file (xml_path)) {
653 // don't remove it if a backup can't be made
654 // create_backup_file will log the error.
659 sys::remove (xml_path);
663 Session::save_state (string snapshot_name, bool pending)
666 sys::path xml_path(_session_dir->root_path());
668 if (_state_of_the_state & CannotSave) {
672 if (!_engine.connected ()) {
673 error << _("Ardour's audio engine is not connected and state saving would lose all I/O connections. Session not saved")
678 /* tell sources we're saving first, in case they write out to a new file
679 * which should be saved with the state rather than the old one */
680 for (SourceMap::const_iterator i = sources.begin(); i != sources.end(); ++i)
681 i->second->session_saved();
683 tree.set_root (&get_state());
685 if (snapshot_name.empty()) {
686 snapshot_name = _current_snapshot_name;
691 /* proper save: use statefile_suffix (.ardour in English) */
693 xml_path /= legalize_for_path (snapshot_name) + statefile_suffix;
695 /* make a backup copy of the old file */
697 if (sys::exists(xml_path) && !create_backup_file (xml_path)) {
698 // create_backup_file will log the error
704 /* pending save: use pending_suffix (.pending in English) */
705 xml_path /= legalize_for_path (snapshot_name) + pending_suffix;
708 sys::path tmp_path(_session_dir->root_path());
710 tmp_path /= legalize_for_path (snapshot_name) + temp_suffix;
712 // cerr << "actually writing state to " << xml_path.to_string() << endl;
714 if (!tree.write (tmp_path.to_string())) {
715 error << string_compose (_("state could not be saved to %1"), tmp_path.to_string()) << endmsg;
716 sys::remove (tmp_path);
721 if (rename (tmp_path.to_string().c_str(), xml_path.to_string().c_str()) != 0) {
722 error << string_compose (_("could not rename temporary session file %1 to %2"),
723 tmp_path.to_string(), xml_path.to_string()) << endmsg;
724 sys::remove (tmp_path);
731 save_history (snapshot_name);
733 bool was_dirty = dirty();
735 _state_of_the_state = StateOfTheState (_state_of_the_state & ~Dirty);
738 DirtyChanged (); /* EMIT SIGNAL */
741 StateSaved (snapshot_name); /* EMIT SIGNAL */
748 Session::restore_state (string snapshot_name)
750 if (load_state (snapshot_name) == 0) {
751 set_state (*state_tree->root());
758 Session::load_state (string snapshot_name)
763 state_was_pending = false;
765 /* check for leftover pending state from a crashed capture attempt */
767 sys::path xmlpath(_session_dir->root_path());
768 xmlpath /= legalize_for_path (snapshot_name) + pending_suffix;
770 if (sys::exists (xmlpath)) {
772 /* there is pending state from a crashed capture attempt */
774 if (AskAboutPendingState()) {
775 state_was_pending = true;
779 if (!state_was_pending) {
780 xmlpath = _session_dir->root_path();
781 xmlpath /= legalize_for_path (snapshot_name) + statefile_suffix;
784 if (!sys::exists (xmlpath)) {
785 error << string_compose(_("%1: session state information file \"%2\" doesn't exist!"), _name, xmlpath.to_string()) << endmsg;
789 state_tree = new XMLTree;
793 if (!state_tree->read (xmlpath.to_string())) {
794 error << string_compose(_("Could not understand ardour file %1"), xmlpath.to_string()) << endmsg;
800 XMLNode& root (*state_tree->root());
802 if (root.name() != X_("Session")) {
803 error << string_compose (_("Session file %1 is not an Ardour session"), xmlpath.to_string()) << endmsg;
809 const XMLProperty* prop;
810 bool is_old = false; // session is _very_ old (pre-2.0)
812 if ((prop = root.property ("version")) == 0) {
813 /* no version implies very old version of Ardour */
817 major_version = atoi (prop->value().c_str()); // grab just the first number before the period
818 if (major_version < 2) {
825 sys::path backup_path(_session_dir->root_path());
827 backup_path /= legalize_for_path (snapshot_name) + "-1" + statefile_suffix;
829 // only create a backup once
830 if (sys::exists (backup_path)) {
834 info << string_compose (_("Copying old session file %1 to %2\nUse %2 with Ardour versions before 2.0 from now on"),
835 xmlpath.to_string(), backup_path.to_string())
840 sys::copy_file (xmlpath, backup_path);
842 catch(sys::filesystem_error& ex)
844 error << string_compose (_("Unable to make backup of state file %1 (%2)"),
845 xmlpath.to_string(), ex.what())
855 Session::load_options (const XMLNode& node)
857 LocaleGuard lg (X_("POSIX"));
859 config.set_variables (node);
861 /* now reset MIDI ports because the session can have its own
877 Session::get_template()
879 /* if we don't disable rec-enable, diskstreams
880 will believe they need to store their capture
881 sources in their state node.
884 disable_record (false);
890 Session::state(bool full_state)
892 XMLNode* node = new XMLNode("Session");
895 // store libardour version, just in case
897 snprintf(buf, sizeof(buf), "%d.%d.%d", libardour3_major_version, libardour3_minor_version, libardour3_micro_version);
898 node->add_property("version", string(buf));
900 /* store configuration settings */
904 node->add_property ("name", _name);
905 snprintf (buf, sizeof (buf), "%" PRId32, _nominal_frame_rate);
906 node->add_property ("sample-rate", buf);
908 if (session_dirs.size() > 1) {
912 vector<space_and_path>::iterator i = session_dirs.begin();
913 vector<space_and_path>::iterator next;
915 ++i; /* skip the first one */
919 while (i != session_dirs.end()) {
923 if (next != session_dirs.end()) {
933 child = node->add_child ("Path");
934 child->add_content (p);
938 /* save the ID counter */
940 snprintf (buf, sizeof (buf), "%" PRIu64, ID::counter());
941 node->add_property ("id-counter", buf);
943 /* various options */
945 node->add_child_nocopy (config.get_variables ());
947 node->add_child_nocopy (_metadata->get_state());
949 child = node->add_child ("Sources");
952 Glib::Mutex::Lock sl (source_lock);
954 for (SourceMap::iterator siter = sources.begin(); siter != sources.end(); ++siter) {
956 /* Don't save information about non-destructive file sources that are empty */
957 /* FIXME: MIDI breaks if this is made FileSource like it should be... */
959 boost::shared_ptr<AudioFileSource> fs;
960 if ((fs = boost::dynamic_pointer_cast<AudioFileSource> (siter->second)) != 0) {
961 if (!fs->destructive()) {
962 if (fs->length(fs->timeline_position()) == 0) {
968 child->add_child_nocopy (siter->second->get_state());
972 child = node->add_child ("Regions");
975 Glib::Mutex::Lock rl (region_lock);
977 for (RegionList::const_iterator i = regions.begin(); i != regions.end(); ++i) {
979 /* only store regions not attached to playlists */
981 if (i->second->playlist() == 0) {
982 child->add_child_nocopy (i->second->state (true));
987 child = node->add_child ("DiskStreams");
990 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
991 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
992 if (!(*i)->hidden()) {
993 child->add_child_nocopy ((*i)->get_state());
999 node->add_child_nocopy (_locations.get_state());
1001 // for a template, just create a new Locations, populate it
1002 // with the default start and end, and get the state for that.
1004 Location* start = new Location(0, 0, _("start"), Location::Flags ((Location::IsMark|Location::IsStart)));
1005 Location* end = new Location(0, 0, _("end"), Location::Flags ((Location::IsMark|Location::IsEnd)));
1008 end->set_end(compute_initial_length());
1010 node->add_child_nocopy (loc.get_state());
1013 child = node->add_child ("Bundles");
1015 boost::shared_ptr<BundleList> bundles = _bundles.reader ();
1016 for (BundleList::iterator i = bundles->begin(); i != bundles->end(); ++i) {
1017 boost::shared_ptr<UserBundle> b = boost::dynamic_pointer_cast<UserBundle> (*i);
1019 child->add_child_nocopy (b->get_state());
1024 child = node->add_child ("Routes");
1026 boost::shared_ptr<RouteList> r = routes.reader ();
1028 RoutePublicOrderSorter cmp;
1029 RouteList public_order (*r);
1030 public_order.sort (cmp);
1032 for (RouteList::iterator i = public_order.begin(); i != public_order.end(); ++i) {
1033 if (!(*i)->is_hidden()) {
1035 child->add_child_nocopy ((*i)->get_state());
1037 child->add_child_nocopy ((*i)->get_template());
1044 child = node->add_child ("RouteGroups");
1045 for (list<RouteGroup *>::iterator i = _route_groups.begin(); i != _route_groups.end(); ++i) {
1046 child->add_child_nocopy ((*i)->get_state());
1049 child = node->add_child ("Playlists");
1050 for (PlaylistList::iterator i = playlists.begin(); i != playlists.end(); ++i) {
1051 if (!(*i)->hidden()) {
1052 if (!(*i)->empty()) {
1054 child->add_child_nocopy ((*i)->get_state());
1056 child->add_child_nocopy ((*i)->get_template());
1062 child = node->add_child ("UnusedPlaylists");
1063 for (PlaylistList::iterator i = unused_playlists.begin(); i != unused_playlists.end(); ++i) {
1064 if (!(*i)->hidden()) {
1065 if (!(*i)->empty()) {
1067 child->add_child_nocopy ((*i)->get_state());
1069 child->add_child_nocopy ((*i)->get_template());
1077 child = node->add_child ("Click");
1078 child->add_child_nocopy (_click_io->state (full_state));
1082 child = node->add_child ("NamedSelections");
1083 for (NamedSelectionList::iterator i = named_selections.begin(); i != named_selections.end(); ++i) {
1085 child->add_child_nocopy ((*i)->get_state());
1090 node->add_child_nocopy (_tempo_map->get_state());
1092 node->add_child_nocopy (get_control_protocol_state());
1095 node->add_child_copy (*_extra_xml);
1102 Session::get_control_protocol_state ()
1104 ControlProtocolManager& cpm (ControlProtocolManager::instance());
1105 return cpm.get_state();
1109 Session::set_state (const XMLNode& node)
1113 const XMLProperty* prop;
1116 _state_of_the_state = StateOfTheState (_state_of_the_state|CannotSave);
1118 if (node.name() != X_("Session")){
1119 fatal << _("programming error: Session: incorrect XML node sent to set_state()") << endmsg;
1123 if ((prop = node.property ("name")) != 0) {
1124 _name = prop->value ();
1127 if ((prop = node.property (X_("sample-rate"))) != 0) {
1129 _nominal_frame_rate = atoi (prop->value());
1131 if (_nominal_frame_rate != _current_frame_rate) {
1132 if (AskAboutSampleRateMismatch (_nominal_frame_rate, _current_frame_rate)) {
1138 setup_raid_path(_session_dir->root_path().to_string());
1140 if ((prop = node.property (X_("id-counter"))) != 0) {
1142 sscanf (prop->value().c_str(), "%" PRIu64, &x);
1143 ID::init_counter (x);
1145 /* old sessions used a timebased counter, so fake
1146 the startup ID counter based on a standard
1151 ID::init_counter (now);
1155 IO::disable_connecting ();
1157 /* Object loading order:
1162 MIDI Control // relies on data from Options/Config
1176 if ((child = find_named_node (node, "Extra")) != 0) {
1177 _extra_xml = new XMLNode (*child);
1180 if (((child = find_named_node (node, "Options")) != 0)) { /* old style */
1181 load_options (*child);
1182 } else if ((child = find_named_node (node, "Config")) != 0) { /* new style */
1183 load_options (*child);
1185 error << _("Session: XML state has no options section") << endmsg;
1188 if (use_config_midi_ports ()) {
1191 if ((child = find_named_node (node, "Metadata")) == 0) {
1192 warning << _("Session: XML state has no metadata section (2.0 session?)") << endmsg;
1193 } else if (_metadata->set_state (*child)) {
1197 if ((child = find_named_node (node, "Locations")) == 0) {
1198 error << _("Session: XML state has no locations section") << endmsg;
1200 } else if (_locations.set_state (*child)) {
1206 if ((location = _locations.auto_loop_location()) != 0) {
1207 set_auto_loop_location (location);
1210 if ((location = _locations.auto_punch_location()) != 0) {
1211 set_auto_punch_location (location);
1214 if ((location = _locations.end_location()) == 0) {
1215 _locations.add (end_location);
1217 delete end_location;
1218 end_location = location;
1221 if ((location = _locations.start_location()) == 0) {
1222 _locations.add (start_location);
1224 delete start_location;
1225 start_location = location;
1228 AudioFileSource::set_header_position_offset (start_location->start());
1230 if ((child = find_named_node (node, "Sources")) == 0) {
1231 error << _("Session: XML state has no sources section") << endmsg;
1233 } else if (load_sources (*child)) {
1237 if ((child = find_named_node (node, "Regions")) == 0) {
1238 error << _("Session: XML state has no Regions section") << endmsg;
1240 } else if (load_regions (*child)) {
1244 if ((child = find_named_node (node, "Playlists")) == 0) {
1245 error << _("Session: XML state has no playlists section") << endmsg;
1247 } else if (load_playlists (*child)) {
1251 if ((child = find_named_node (node, "UnusedPlaylists")) == 0) {
1253 } else if (load_unused_playlists (*child)) {
1257 if ((child = find_named_node (node, "NamedSelections")) != 0) {
1258 if (load_named_selections (*child)) {
1263 if ((child = find_named_node (node, "DiskStreams")) == 0) {
1264 error << _("Session: XML state has no diskstreams section") << endmsg;
1266 } else if (load_diskstreams (*child)) {
1270 if ((child = find_named_node (node, "Bundles")) == 0) {
1271 warning << _("Session: XML state has no bundles section (2.0 session?)") << endmsg;
1274 /* We can't load Bundles yet as they need to be able
1275 to convert from port names to Port objects, which can't happen until
1277 _bundle_xml_node = new XMLNode (*child);
1280 if ((child = find_named_node (node, "RouteGroups")) == 0) {
1281 error << _("Session: XML state has no route groups section") << endmsg;
1283 } else if (load_route_groups (*child)) {
1287 if ((child = find_named_node (node, "TempoMap")) == 0) {
1288 error << _("Session: XML state has no Tempo Map section") << endmsg;
1290 } else if (_tempo_map->set_state (*child)) {
1294 if ((child = find_named_node (node, "Routes")) == 0) {
1295 error << _("Session: XML state has no routes section") << endmsg;
1297 } else if (load_routes (*child)) {
1301 if ((child = find_named_node (node, "Click")) == 0) {
1302 warning << _("Session: XML state has no click section") << endmsg;
1303 } else if (_click_io) {
1304 _click_io->set_state (*child);
1307 if ((child = find_named_node (node, "ControlProtocols")) != 0) {
1308 ControlProtocolManager::instance().set_protocol_states (*child);
1311 /* here beginneth the second phase ... */
1313 StateReady (); /* EMIT SIGNAL */
1322 Session::load_routes (const XMLNode& node)
1325 XMLNodeConstIterator niter;
1326 RouteList new_routes;
1328 nlist = node.children();
1332 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1334 boost::shared_ptr<Route> route (XMLRouteFactory (**niter));
1337 error << _("Session: cannot create Route from XML description.") << endmsg;
1341 BootMessage (string_compose (_("Loaded track/bus %1"), route->name()));
1343 new_routes.push_back (route);
1346 add_routes (new_routes, false);
1351 boost::shared_ptr<Route>
1352 Session::XMLRouteFactory (const XMLNode& node)
1354 if (node.name() != "Route") {
1355 return boost::shared_ptr<Route> ((Route*) 0);
1358 bool has_diskstream = (node.property ("diskstream") != 0 || node.property ("diskstream-id") != 0);
1360 DataType type = DataType::AUDIO;
1361 const XMLProperty* prop = node.property("default-type");
1364 type = DataType(prop->value());
1367 assert(type != DataType::NIL);
1369 if (has_diskstream) {
1370 if (type == DataType::AUDIO) {
1371 boost::shared_ptr<Route> ret (new AudioTrack (*this, node));
1374 boost::shared_ptr<Route> ret (new MidiTrack (*this, node));
1378 boost::shared_ptr<Route> ret (new Route (*this, node));
1384 Session::load_regions (const XMLNode& node)
1387 XMLNodeConstIterator niter;
1388 boost::shared_ptr<Region> region;
1390 nlist = node.children();
1394 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1395 if ((region = XMLRegionFactory (**niter, false)) == 0) {
1396 error << _("Session: cannot create Region from XML description.");
1397 const XMLProperty *name = (**niter).property("name");
1400 error << " " << string_compose (_("Can not load state for region '%1'"), name->value());
1410 boost::shared_ptr<Region>
1411 Session::XMLRegionFactory (const XMLNode& node, bool full)
1413 const XMLProperty* type = node.property("type");
1417 if ( !type || type->value() == "audio" ) {
1419 return boost::shared_ptr<Region>(XMLAudioRegionFactory (node, full));
1421 } else if (type->value() == "midi") {
1423 return boost::shared_ptr<Region>(XMLMidiRegionFactory (node, full));
1427 } catch (failed_constructor& err) {
1428 return boost::shared_ptr<Region> ();
1431 return boost::shared_ptr<Region> ();
1434 boost::shared_ptr<AudioRegion>
1435 Session::XMLAudioRegionFactory (const XMLNode& node, bool /*full*/)
1437 const XMLProperty* prop;
1438 boost::shared_ptr<Source> source;
1439 boost::shared_ptr<AudioSource> as;
1441 SourceList master_sources;
1442 uint32_t nchans = 1;
1445 if (node.name() != X_("Region")) {
1446 return boost::shared_ptr<AudioRegion>();
1449 if ((prop = node.property (X_("channels"))) != 0) {
1450 nchans = atoi (prop->value().c_str());
1453 if ((prop = node.property ("name")) == 0) {
1454 cerr << "no name for this region\n";
1458 if ((prop = node.property (X_("source-0"))) == 0) {
1459 if ((prop = node.property ("source")) == 0) {
1460 error << _("Session: XMLNode describing a AudioRegion is incomplete (no source)") << endmsg;
1461 return boost::shared_ptr<AudioRegion>();
1465 PBD::ID s_id (prop->value());
1467 if ((source = source_by_id (s_id)) == 0) {
1468 error << string_compose(_("Session: XMLNode describing a AudioRegion references an unknown source id =%1"), s_id) << endmsg;
1469 return boost::shared_ptr<AudioRegion>();
1472 as = boost::dynamic_pointer_cast<AudioSource>(source);
1474 error << string_compose(_("Session: XMLNode describing a AudioRegion references a non-audio source id =%1"), s_id) << endmsg;
1475 return boost::shared_ptr<AudioRegion>();
1478 sources.push_back (as);
1480 /* pickup other channels */
1482 for (uint32_t n=1; n < nchans; ++n) {
1483 snprintf (buf, sizeof(buf), X_("source-%d"), n);
1484 if ((prop = node.property (buf)) != 0) {
1486 PBD::ID id2 (prop->value());
1488 if ((source = source_by_id (id2)) == 0) {
1489 error << string_compose(_("Session: XMLNode describing a AudioRegion references an unknown source id =%1"), id2) << endmsg;
1490 return boost::shared_ptr<AudioRegion>();
1493 as = boost::dynamic_pointer_cast<AudioSource>(source);
1495 error << string_compose(_("Session: XMLNode describing a AudioRegion references a non-audio source id =%1"), id2) << endmsg;
1496 return boost::shared_ptr<AudioRegion>();
1498 sources.push_back (as);
1502 for (uint32_t n = 0; n < nchans; ++n) {
1503 snprintf (buf, sizeof(buf), X_("master-source-%d"), n);
1504 if ((prop = node.property (buf)) != 0) {
1506 PBD::ID id2 (prop->value());
1508 if ((source = source_by_id (id2)) == 0) {
1509 error << string_compose(_("Session: XMLNode describing a AudioRegion references an unknown source id =%1"), id2) << endmsg;
1510 return boost::shared_ptr<AudioRegion>();
1513 as = boost::dynamic_pointer_cast<AudioSource>(source);
1515 error << string_compose(_("Session: XMLNode describing a AudioRegion references a non-audio source id =%1"), id2) << endmsg;
1516 return boost::shared_ptr<AudioRegion>();
1518 master_sources.push_back (as);
1523 boost::shared_ptr<AudioRegion> region (boost::dynamic_pointer_cast<AudioRegion> (RegionFactory::create (sources, node)));
1525 /* a final detail: this is the one and only place that we know how long missing files are */
1527 if (region->whole_file()) {
1528 for (SourceList::iterator sx = sources.begin(); sx != sources.end(); ++sx) {
1529 boost::shared_ptr<SilentFileSource> sfp = boost::dynamic_pointer_cast<SilentFileSource> (*sx);
1531 sfp->set_length (region->length());
1536 if (!master_sources.empty()) {
1537 if (master_sources.size() != nchans) {
1538 error << _("Session: XMLNode describing an AudioRegion is missing some master sources; ignored") << endmsg;
1540 region->set_master_sources (master_sources);
1548 catch (failed_constructor& err) {
1549 return boost::shared_ptr<AudioRegion>();
1553 boost::shared_ptr<MidiRegion>
1554 Session::XMLMidiRegionFactory (const XMLNode& node, bool /*full*/)
1556 const XMLProperty* prop;
1557 boost::shared_ptr<Source> source;
1558 boost::shared_ptr<MidiSource> ms;
1560 uint32_t nchans = 1;
1562 if (node.name() != X_("Region")) {
1563 return boost::shared_ptr<MidiRegion>();
1566 if ((prop = node.property (X_("channels"))) != 0) {
1567 nchans = atoi (prop->value().c_str());
1570 if ((prop = node.property ("name")) == 0) {
1571 cerr << "no name for this region\n";
1575 // Multiple midi channels? that's just crazy talk
1576 assert(nchans == 1);
1578 if ((prop = node.property (X_("source-0"))) == 0) {
1579 if ((prop = node.property ("source")) == 0) {
1580 error << _("Session: XMLNode describing a MidiRegion is incomplete (no source)") << endmsg;
1581 return boost::shared_ptr<MidiRegion>();
1585 PBD::ID s_id (prop->value());
1587 if ((source = source_by_id (s_id)) == 0) {
1588 error << string_compose(_("Session: XMLNode describing a MidiRegion references an unknown source id =%1"), s_id) << endmsg;
1589 return boost::shared_ptr<MidiRegion>();
1592 ms = boost::dynamic_pointer_cast<MidiSource>(source);
1594 error << string_compose(_("Session: XMLNode describing a MidiRegion references a non-midi source id =%1"), s_id) << endmsg;
1595 return boost::shared_ptr<MidiRegion>();
1598 sources.push_back (ms);
1601 boost::shared_ptr<MidiRegion> region (boost::dynamic_pointer_cast<MidiRegion> (RegionFactory::create (sources, node)));
1602 /* a final detail: this is the one and only place that we know how long missing files are */
1604 if (region->whole_file()) {
1605 for (SourceList::iterator sx = sources.begin(); sx != sources.end(); ++sx) {
1606 boost::shared_ptr<SilentFileSource> sfp = boost::dynamic_pointer_cast<SilentFileSource> (*sx);
1608 sfp->set_length (region->length());
1616 catch (failed_constructor& err) {
1617 return boost::shared_ptr<MidiRegion>();
1622 Session::get_sources_as_xml ()
1625 XMLNode* node = new XMLNode (X_("Sources"));
1626 Glib::Mutex::Lock lm (source_lock);
1628 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ++i) {
1629 node->add_child_nocopy (i->second->get_state());
1636 Session::path_from_region_name (DataType type, string name, string identifier)
1638 char buf[PATH_MAX+1];
1640 SessionDirectory sdir(get_best_session_directory_for_new_source());
1641 sys::path source_dir = ((type == DataType::AUDIO)
1642 ? sdir.sound_path() : sdir.midi_path());
1644 string ext = ((type == DataType::AUDIO) ? ".wav" : ".mid");
1646 for (n = 0; n < 999999; ++n) {
1647 if (identifier.length()) {
1648 snprintf (buf, sizeof(buf), "%s%s%" PRIu32 "%s", name.c_str(),
1649 identifier.c_str(), n, ext.c_str());
1651 snprintf (buf, sizeof(buf), "%s-%" PRIu32 "%s", name.c_str(),
1655 sys::path source_path = source_dir / buf;
1657 if (!sys::exists (source_path)) {
1658 return source_path.to_string();
1662 error << string_compose (_("cannot create new file from region name \"%1\" with ident = \"%2\": too many existing files with similar names"),
1671 Session::load_sources (const XMLNode& node)
1674 XMLNodeConstIterator niter;
1675 boost::shared_ptr<Source> source;
1677 nlist = node.children();
1681 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1683 if ((source = XMLSourceFactory (**niter)) == 0) {
1684 error << _("Session: cannot create Source from XML description.") << endmsg;
1686 } catch (MissingSource& err) {
1687 warning << _("A sound file is missing. It will be replaced by silence.") << endmsg;
1688 source = SourceFactory::createSilent (*this, **niter, max_frames, _current_frame_rate);
1695 boost::shared_ptr<Source>
1696 Session::XMLSourceFactory (const XMLNode& node)
1698 if (node.name() != "Source") {
1699 return boost::shared_ptr<Source>();
1703 /* note: do peak building in another thread when loading session state */
1704 return SourceFactory::create (*this, node, true);
1707 catch (failed_constructor& err) {
1708 error << _("Found a sound file that cannot be used by Ardour. Talk to the progammers.") << endmsg;
1709 return boost::shared_ptr<Source>();
1714 Session::save_template (string template_name)
1718 if (_state_of_the_state & CannotSave) {
1722 sys::path user_template_dir(user_template_directory());
1726 sys::create_directories (user_template_dir);
1728 catch(sys::filesystem_error& ex)
1730 error << string_compose(_("Could not create mix templates directory \"%1\" (%2)"),
1731 user_template_dir.to_string(), ex.what()) << endmsg;
1735 tree.set_root (&get_template());
1737 sys::path template_file_path(user_template_dir);
1738 template_file_path /= template_name + template_suffix;
1740 if (sys::exists (template_file_path))
1742 warning << string_compose(_("Template \"%1\" already exists - new version not created"),
1743 template_file_path.to_string()) << endmsg;
1747 if (!tree.write (template_file_path.to_string())) {
1748 error << _("mix template not saved") << endmsg;
1756 Session::rename_template (string old_name, string new_name)
1758 sys::path old_path (user_template_directory());
1759 old_path /= old_name + template_suffix;
1761 sys::path new_path(user_template_directory());
1762 new_path /= new_name + template_suffix;
1764 if (sys::exists (new_path)) {
1765 warning << string_compose(_("Template \"%1\" already exists - template not renamed"),
1766 new_path.to_string()) << endmsg;
1771 sys::rename (old_path, new_path);
1779 Session::delete_template (string name)
1781 sys::path path = user_template_directory();
1782 path /= name + template_suffix;
1793 Session::refresh_disk_space ()
1796 struct statfs statfsbuf;
1797 vector<space_and_path>::iterator i;
1798 Glib::Mutex::Lock lm (space_lock);
1801 /* get freespace on every FS that is part of the session path */
1803 _total_free_4k_blocks = 0;
1805 for (i = session_dirs.begin(); i != session_dirs.end(); ++i) {
1806 statfs ((*i).path.c_str(), &statfsbuf);
1808 scale = statfsbuf.f_bsize/4096.0;
1810 (*i).blocks = (uint32_t) floor (statfsbuf.f_bavail * scale);
1811 _total_free_4k_blocks += (*i).blocks;
1817 Session::get_best_session_directory_for_new_source ()
1819 vector<space_and_path>::iterator i;
1820 string result = _session_dir->root_path().to_string();
1822 /* handle common case without system calls */
1824 if (session_dirs.size() == 1) {
1828 /* OK, here's the algorithm we're following here:
1830 We want to select which directory to use for
1831 the next file source to be created. Ideally,
1832 we'd like to use a round-robin process so as to
1833 get maximum performance benefits from splitting
1834 the files across multiple disks.
1836 However, in situations without much diskspace, an
1837 RR approach may end up filling up a filesystem
1838 with new files while others still have space.
1839 Its therefore important to pay some attention to
1840 the freespace in the filesystem holding each
1841 directory as well. However, if we did that by
1842 itself, we'd keep creating new files in the file
1843 system with the most space until it was as full
1844 as all others, thus negating any performance
1845 benefits of this RAID-1 like approach.
1847 So, we use a user-configurable space threshold. If
1848 there are at least 2 filesystems with more than this
1849 much space available, we use RR selection between them.
1850 If not, then we pick the filesystem with the most space.
1852 This gets a good balance between the two
1856 refresh_disk_space ();
1858 int free_enough = 0;
1860 for (i = session_dirs.begin(); i != session_dirs.end(); ++i) {
1861 if ((*i).blocks * 4096 >= Config->get_disk_choice_space_threshold()) {
1866 if (free_enough >= 2) {
1867 /* use RR selection process, ensuring that the one
1871 i = last_rr_session_dir;
1874 if (++i == session_dirs.end()) {
1875 i = session_dirs.begin();
1878 if ((*i).blocks * 4096 >= Config->get_disk_choice_space_threshold()) {
1879 if (create_session_directory ((*i).path)) {
1881 last_rr_session_dir = i;
1886 } while (i != last_rr_session_dir);
1890 /* pick FS with the most freespace (and that
1891 seems to actually work ...)
1894 vector<space_and_path> sorted;
1895 space_and_path_ascending_cmp cmp;
1897 sorted = session_dirs;
1898 sort (sorted.begin(), sorted.end(), cmp);
1900 for (i = sorted.begin(); i != sorted.end(); ++i) {
1901 if (create_session_directory ((*i).path)) {
1903 last_rr_session_dir = i;
1913 Session::load_playlists (const XMLNode& node)
1916 XMLNodeConstIterator niter;
1917 boost::shared_ptr<Playlist> playlist;
1919 nlist = node.children();
1923 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1925 if ((playlist = XMLPlaylistFactory (**niter)) == 0) {
1926 error << _("Session: cannot create Playlist from XML description.") << endmsg;
1934 Session::load_unused_playlists (const XMLNode& node)
1937 XMLNodeConstIterator niter;
1938 boost::shared_ptr<Playlist> playlist;
1940 nlist = node.children();
1944 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1946 if ((playlist = XMLPlaylistFactory (**niter)) == 0) {
1947 error << _("Session: cannot create Playlist from XML description.") << endmsg;
1951 // now manually untrack it
1953 track_playlist (false, boost::weak_ptr<Playlist> (playlist));
1959 boost::shared_ptr<Playlist>
1960 Session::XMLPlaylistFactory (const XMLNode& node)
1963 return PlaylistFactory::create (*this, node);
1966 catch (failed_constructor& err) {
1967 return boost::shared_ptr<Playlist>();
1972 Session::load_named_selections (const XMLNode& node)
1975 XMLNodeConstIterator niter;
1978 nlist = node.children();
1982 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1984 if ((ns = XMLNamedSelectionFactory (**niter)) == 0) {
1985 error << _("Session: cannot create Named Selection from XML description.") << endmsg;
1993 Session::XMLNamedSelectionFactory (const XMLNode& node)
1996 return new NamedSelection (*this, node);
1999 catch (failed_constructor& err) {
2005 Session::automation_dir () const
2007 return Glib::build_filename (_path, "automation");
2011 Session::analysis_dir () const
2013 return Glib::build_filename (_path, "analysis");
2017 Session::load_bundles (XMLNode const & node)
2019 XMLNodeList nlist = node.children();
2020 XMLNodeConstIterator niter;
2024 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2025 if ((*niter)->name() == "InputBundle") {
2026 add_bundle (boost::shared_ptr<UserBundle> (new UserBundle (**niter, true)));
2027 } else if ((*niter)->name() == "OutputBundle") {
2028 add_bundle (boost::shared_ptr<UserBundle> (new UserBundle (**niter, false)));
2030 error << string_compose(_("Unknown node \"%1\" found in Bundles list from state file"), (*niter)->name()) << endmsg;
2039 Session::load_route_groups (const XMLNode& node)
2041 XMLNodeList nlist = node.children();
2042 XMLNodeConstIterator niter;
2046 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2047 if ((*niter)->name() == "RouteGroup") {
2048 RouteGroup* rg = new RouteGroup (*this, "");
2049 add_route_group (rg);
2050 rg->set_state (**niter);
2058 Session::auto_save()
2060 save_state (_current_snapshot_name);
2064 state_file_filter (const string &str, void */*arg*/)
2066 return (str.length() > strlen(statefile_suffix) &&
2067 str.find (statefile_suffix) == (str.length() - strlen (statefile_suffix)));
2071 bool operator()(const string* a, const string* b) {
2077 remove_end(string* state)
2079 string statename(*state);
2081 string::size_type start,end;
2082 if ((start = statename.find_last_of ('/')) != string::npos) {
2083 statename = statename.substr (start+1);
2086 if ((end = statename.rfind(".ardour")) == string::npos) {
2087 end = statename.length();
2090 return new string(statename.substr (0, end));
2094 Session::possible_states (string path)
2096 PathScanner scanner;
2097 vector<string*>* states = scanner (path, state_file_filter, 0, false, false);
2099 transform(states->begin(), states->end(), states->begin(), remove_end);
2102 sort (states->begin(), states->end(), cmp);
2108 Session::possible_states () const
2110 return possible_states(_path);
2114 Session::add_route_group (RouteGroup* g)
2116 _route_groups.push_back (g);
2117 route_group_added (g); /* EMIT SIGNAL */
2122 Session::remove_route_group (RouteGroup& rg)
2124 list<RouteGroup*>::iterator i;
2126 if ((i = find (_route_groups.begin(), _route_groups.end(), &rg)) != _route_groups.end()) {
2127 (*i)->apply (&Route::drop_route_group, this);
2128 _route_groups.erase (i);
2129 route_group_removed (); /* EMIT SIGNAL */
2137 Session::route_group_by_name (string name)
2139 list<RouteGroup *>::iterator i;
2141 for (i = _route_groups.begin(); i != _route_groups.end(); ++i) {
2142 if ((*i)->name() == name) {
2150 Session::begin_reversible_command(const string& name)
2152 UndoTransaction* trans = new UndoTransaction();
2153 trans->set_name(name);
2154 if (!_current_trans.empty()) {
2155 _current_trans.top()->add_command(trans);
2157 _current_trans.push(trans);
2161 Session::commit_reversible_command(Command *cmd)
2163 assert(!_current_trans.empty());
2167 _current_trans.top()->add_command(cmd);
2170 if (_current_trans.top()->empty()) {
2171 _current_trans.pop();
2175 gettimeofday(&now, 0);
2176 _current_trans.top()->set_timestamp(now);
2178 _history.add(_current_trans.top());
2179 _current_trans.pop();
2182 Session::GlobalRouteBooleanState
2183 Session::get_global_route_boolean (bool (Route::*method)(void) const)
2185 GlobalRouteBooleanState s;
2186 boost::shared_ptr<RouteList> r = routes.reader ();
2188 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
2189 if (!(*i)->is_hidden()) {
2190 RouteBooleanState v;
2193 Route* r = (*i).get();
2194 v.second = (r->*method)();
2203 Session::GlobalRouteMeterState
2204 Session::get_global_route_metering ()
2206 GlobalRouteMeterState s;
2207 boost::shared_ptr<RouteList> r = routes.reader ();
2209 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
2210 if (!(*i)->is_hidden()) {
2214 v.second = (*i)->meter_point();
2224 Session::set_global_route_metering (GlobalRouteMeterState s, void* arg)
2226 for (GlobalRouteMeterState::iterator i = s.begin(); i != s.end(); ++i) {
2228 boost::shared_ptr<Route> r = (i->first.lock());
2231 r->set_meter_point (i->second, arg);
2237 Session::set_global_route_boolean (GlobalRouteBooleanState s, void (Route::*method)(bool, void*), void* arg)
2239 for (GlobalRouteBooleanState::iterator i = s.begin(); i != s.end(); ++i) {
2241 boost::shared_ptr<Route> r = (i->first.lock());
2244 Route* rp = r.get();
2245 (rp->*method) (i->second, arg);
2251 Session::set_global_mute (GlobalRouteBooleanState s, void* src)
2253 set_global_route_boolean (s, &Route::set_mute, src);
2257 Session::set_global_solo (GlobalRouteBooleanState s, void* src)
2259 set_global_route_boolean (s, &Route::set_solo, src);
2263 Session::set_global_record_enable (GlobalRouteBooleanState s, void* src)
2265 set_global_route_boolean (s, &Route::set_record_enable, src);
2269 accept_all_non_peak_files (const string& path, void */*arg*/)
2271 return (path.length() > 5 && path.find (peakfile_suffix) != (path.length() - 5));
2275 accept_all_state_files (const string& path, void */*arg*/)
2277 return (path.length() > 7 && path.find (".ardour") == (path.length() - 7));
2281 Session::find_all_sources (string path, set<string>& result)
2286 if (!tree.read (path)) {
2290 if ((node = find_named_node (*tree.root(), "Sources")) == 0) {
2295 XMLNodeConstIterator niter;
2297 nlist = node->children();
2301 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2305 if ((prop = (*niter)->property (X_("type"))) == 0) {
2309 DataType type (prop->value());
2311 if ((prop = (*niter)->property (X_("name"))) == 0) {
2315 if (prop->value()[0] == '/') {
2316 /* external file, ignore */
2320 Glib::ustring found_path;
2324 if (FileSource::find (type, prop->value(), true, is_new, chan, found_path)) {
2325 result.insert (found_path);
2333 Session::find_all_sources_across_snapshots (set<string>& result, bool exclude_this_snapshot)
2335 PathScanner scanner;
2336 vector<string*>* state_files;
2338 string this_snapshot_path;
2344 if (ripped[ripped.length()-1] == '/') {
2345 ripped = ripped.substr (0, ripped.length() - 1);
2348 state_files = scanner (ripped, accept_all_state_files, (void *) 0, false, true);
2350 if (state_files == 0) {
2355 this_snapshot_path = _path;
2356 this_snapshot_path += legalize_for_path (_current_snapshot_name);
2357 this_snapshot_path += statefile_suffix;
2359 for (vector<string*>::iterator i = state_files->begin(); i != state_files->end(); ++i) {
2361 if (exclude_this_snapshot && **i == this_snapshot_path) {
2365 if (find_all_sources (**i, result) < 0) {
2373 struct RegionCounter {
2374 typedef std::map<PBD::ID,boost::shared_ptr<AudioSource> > AudioSourceList;
2375 AudioSourceList::iterator iter;
2376 boost::shared_ptr<Region> region;
2379 RegionCounter() : count (0) {}
2383 Session::cleanup_sources (Session::cleanup_report& rep)
2385 // FIXME: needs adaptation to midi
2387 vector<boost::shared_ptr<Source> > dead_sources;
2388 vector<boost::shared_ptr<Playlist> > playlists_tbd;
2389 PathScanner scanner;
2391 vector<space_and_path>::iterator i;
2392 vector<space_and_path>::iterator nexti;
2393 vector<string*>* soundfiles;
2394 vector<string> unused;
2395 set<string> all_sources;
2400 _state_of_the_state = (StateOfTheState) (_state_of_the_state | InCleanup);
2403 /* step 1: consider deleting all unused playlists */
2405 for (PlaylistList::iterator x = unused_playlists.begin(); x != unused_playlists.end(); ++x) {
2408 status = AskAboutPlaylistDeletion (*x);
2417 playlists_tbd.push_back (*x);
2421 /* leave it alone */
2426 /* now delete any that were marked for deletion */
2428 for (vector<boost::shared_ptr<Playlist> >::iterator x = playlists_tbd.begin(); x != playlists_tbd.end(); ++x) {
2429 (*x)->drop_references ();
2432 playlists_tbd.clear ();
2434 /* step 2: find all un-used sources */
2439 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ) {
2441 SourceMap::iterator tmp;
2446 /* do not bother with files that are zero size, otherwise we remove the current "nascent"
2450 if (!i->second->used() && i->second->length(i->second->timeline_position()) > 0) {
2451 dead_sources.push_back (i->second);
2452 i->second->GoingAway();
2458 /* build a list of all the possible sound directories for the session */
2460 for (i = session_dirs.begin(); i != session_dirs.end(); ) {
2465 SessionDirectory sdir ((*i).path);
2466 sound_path += sdir.sound_path().to_string();
2468 if (nexti != session_dirs.end()) {
2475 /* now do the same thing for the files that ended up in the sounds dir(s)
2476 but are not referenced as sources in any snapshot.
2479 soundfiles = scanner (sound_path, accept_all_non_peak_files, (void *) 0, false, true);
2481 if (soundfiles == 0) {
2485 /* find all sources, but don't use this snapshot because the
2486 state file on disk still references sources we may have already
2490 find_all_sources_across_snapshots (all_sources, true);
2492 /* add our current source list
2495 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ++i) {
2496 boost::shared_ptr<FileSource> fs;
2498 if ((fs = boost::dynamic_pointer_cast<FileSource> (i->second)) != 0) {
2499 all_sources.insert (fs->path());
2503 char tmppath1[PATH_MAX+1];
2504 char tmppath2[PATH_MAX+1];
2506 for (vector<string*>::iterator x = soundfiles->begin(); x != soundfiles->end(); ++x) {
2511 for (set<string>::iterator i = all_sources.begin(); i != all_sources.end(); ++i) {
2513 realpath(spath.c_str(), tmppath1);
2514 realpath((*i).c_str(), tmppath2);
2516 if (strcmp(tmppath1, tmppath2) == 0) {
2523 unused.push_back (spath);
2527 /* now try to move all unused files into the "dead_sounds" directory(ies) */
2529 for (vector<string>::iterator x = unused.begin(); x != unused.end(); ++x) {
2530 struct stat statbuf;
2532 rep.paths.push_back (*x);
2533 if (stat ((*x).c_str(), &statbuf) == 0) {
2534 rep.space += statbuf.st_size;
2539 /* don't move the file across filesystems, just
2540 stick it in the `dead_sound_dir_name' directory
2541 on whichever filesystem it was already on.
2544 if ((*x).find ("/sounds/") != string::npos) {
2546 /* old school, go up 1 level */
2548 newpath = Glib::path_get_dirname (*x); // "sounds"
2549 newpath = Glib::path_get_dirname (newpath); // "session-name"
2553 /* new school, go up 4 levels */
2555 newpath = Glib::path_get_dirname (*x); // "audiofiles"
2556 newpath = Glib::path_get_dirname (newpath); // "session-name"
2557 newpath = Glib::path_get_dirname (newpath); // "interchange"
2558 newpath = Glib::path_get_dirname (newpath); // "session-dir"
2562 newpath += dead_sound_dir_name;
2564 if (g_mkdir_with_parents (newpath.c_str(), 0755) < 0) {
2565 error << string_compose(_("Session: cannot create session peakfile folder \"%1\" (%2)"), newpath, strerror (errno)) << endmsg;
2570 newpath += Glib::path_get_basename ((*x));
2572 if (access (newpath.c_str(), F_OK) == 0) {
2574 /* the new path already exists, try versioning */
2576 char buf[PATH_MAX+1];
2580 snprintf (buf, sizeof (buf), "%s.%d", newpath.c_str(), version);
2583 while (access (newpath_v.c_str(), F_OK) == 0 && version < 999) {
2584 snprintf (buf, sizeof (buf), "%s.%d", newpath.c_str(), ++version);
2588 if (version == 999) {
2589 error << string_compose (_("there are already 1000 files with names like %1; versioning discontinued"),
2593 newpath = newpath_v;
2598 /* it doesn't exist, or we can't read it or something */
2602 if (::rename ((*x).c_str(), newpath.c_str()) != 0) {
2603 error << string_compose (_("cannot rename audio file source from %1 to %2 (%3)"),
2604 (*x), newpath, strerror (errno))
2609 /* see if there an easy to find peakfile for this file, and remove it.
2612 string peakpath = (*x).substr (0, (*x).find_last_of ('.'));
2613 peakpath += peakfile_suffix;
2615 if (access (peakpath.c_str(), W_OK) == 0) {
2616 if (::unlink (peakpath.c_str()) != 0) {
2617 error << string_compose (_("cannot remove peakfile %1 for %2 (%3)"),
2618 peakpath, _path, strerror (errno))
2620 /* try to back out */
2621 rename (newpath.c_str(), _path.c_str());
2629 /* dump the history list */
2633 /* save state so we don't end up a session file
2634 referring to non-existent sources.
2640 _state_of_the_state = (StateOfTheState) (_state_of_the_state & ~InCleanup);
2646 Session::cleanup_trash_sources (Session::cleanup_report& rep)
2648 // FIXME: needs adaptation for MIDI
2650 vector<space_and_path>::iterator i;
2651 string dead_sound_dir;
2652 struct dirent* dentry;
2653 struct stat statbuf;
2659 for (i = session_dirs.begin(); i != session_dirs.end(); ++i) {
2661 dead_sound_dir = (*i).path;
2662 dead_sound_dir += dead_sound_dir_name;
2664 if ((dead = opendir (dead_sound_dir.c_str())) == 0) {
2668 while ((dentry = readdir (dead)) != 0) {
2670 /* avoid '.' and '..' */
2672 if ((dentry->d_name[0] == '.' && dentry->d_name[1] == '\0') ||
2673 (dentry->d_name[2] == '\0' && dentry->d_name[0] == '.' && dentry->d_name[1] == '.')) {
2679 fullpath = dead_sound_dir;
2681 fullpath += dentry->d_name;
2683 if (stat (fullpath.c_str(), &statbuf)) {
2687 if (!S_ISREG (statbuf.st_mode)) {
2691 if (unlink (fullpath.c_str())) {
2692 error << string_compose (_("cannot remove dead sound file %1 (%2)"),
2693 fullpath, strerror (errno))
2697 rep.paths.push_back (dentry->d_name);
2698 rep.space += statbuf.st_size;
2709 Session::set_dirty ()
2711 bool was_dirty = dirty();
2713 _state_of_the_state = StateOfTheState (_state_of_the_state | Dirty);
2717 DirtyChanged(); /* EMIT SIGNAL */
2723 Session::set_clean ()
2725 bool was_dirty = dirty();
2727 _state_of_the_state = Clean;
2731 DirtyChanged(); /* EMIT SIGNAL */
2736 Session::set_deletion_in_progress ()
2738 _state_of_the_state = StateOfTheState (_state_of_the_state | Deletion);
2742 Session::clear_deletion_in_progress ()
2744 _state_of_the_state = StateOfTheState (_state_of_the_state & (~Deletion));
2748 Session::add_controllable (boost::shared_ptr<Controllable> c)
2750 /* this adds a controllable to the list managed by the Session.
2751 this is a subset of those managed by the Controllable class
2752 itself, and represents the only ones whose state will be saved
2753 as part of the session.
2756 Glib::Mutex::Lock lm (controllables_lock);
2757 controllables.insert (c);
2760 struct null_deleter { void operator()(void const *) const {} };
2763 Session::remove_controllable (Controllable* c)
2765 if (_state_of_the_state | Deletion) {
2769 Glib::Mutex::Lock lm (controllables_lock);
2771 Controllables::iterator x = controllables.find(
2772 boost::shared_ptr<Controllable>(c, null_deleter()));
2774 if (x != controllables.end()) {
2775 controllables.erase (x);
2779 boost::shared_ptr<Controllable>
2780 Session::controllable_by_id (const PBD::ID& id)
2782 Glib::Mutex::Lock lm (controllables_lock);
2784 for (Controllables::iterator i = controllables.begin(); i != controllables.end(); ++i) {
2785 if ((*i)->id() == id) {
2790 return boost::shared_ptr<Controllable>();
2794 Session::add_instant_xml (XMLNode& node, bool write_to_config)
2796 Stateful::add_instant_xml (node, _path);
2797 if (write_to_config) {
2798 Config->add_instant_xml (node);
2803 Session::instant_xml (const string& node_name)
2805 return Stateful::instant_xml (node_name, _path);
2809 Session::save_history (string snapshot_name)
2813 if (snapshot_name.empty()) {
2814 snapshot_name = _current_snapshot_name;
2817 const string history_filename = legalize_for_path (snapshot_name) + history_suffix;
2818 const string backup_filename = history_filename + backup_suffix;
2819 const sys::path xml_path = _session_dir->root_path() / history_filename;
2820 const sys::path backup_path = _session_dir->root_path() / backup_filename;
2822 if (sys::exists (xml_path)) {
2825 sys::rename (xml_path, backup_path);
2827 catch (const sys::filesystem_error& err)
2829 error << _("could not backup old history file, current history not saved") << endmsg;
2835 if (!Config->get_save_history() || Config->get_saved_history_depth() < 0) {
2839 tree.set_root (&_history.get_state (Config->get_saved_history_depth()));
2841 if (!tree.write (xml_path.to_string()))
2843 error << string_compose (_("history could not be saved to %1"), xml_path.to_string()) << endmsg;
2847 sys::remove (xml_path);
2848 sys::rename (backup_path, xml_path);
2850 catch (const sys::filesystem_error& err)
2852 error << string_compose (_("could not restore history file from backup %1 (%2)"),
2853 backup_path.to_string(), err.what()) << endmsg;
2863 Session::restore_history (string snapshot_name)
2867 if (snapshot_name.empty()) {
2868 snapshot_name = _current_snapshot_name;
2871 const string xml_filename = legalize_for_path (snapshot_name) + history_suffix;
2872 const sys::path xml_path = _session_dir->root_path() / xml_filename;
2874 cerr << "Loading history from " << xml_path.to_string() << endmsg;
2876 if (!sys::exists (xml_path)) {
2877 info << string_compose (_("%1: no history file \"%2\" for this session."),
2878 _name, xml_path.to_string()) << endmsg;
2882 if (!tree.read (xml_path.to_string())) {
2883 error << string_compose (_("Could not understand session history file \"%1\""),
2884 xml_path.to_string()) << endmsg;
2891 for (XMLNodeConstIterator it = tree.root()->children().begin(); it != tree.root()->children().end(); it++) {
2894 UndoTransaction* ut = new UndoTransaction ();
2897 ut->set_name(t->property("name")->value());
2898 stringstream ss(t->property("tv-sec")->value());
2900 ss.str(t->property("tv-usec")->value());
2902 ut->set_timestamp(tv);
2904 for (XMLNodeConstIterator child_it = t->children().begin();
2905 child_it != t->children().end(); child_it++)
2907 XMLNode *n = *child_it;
2910 if (n->name() == "MementoCommand" ||
2911 n->name() == "MementoUndoCommand" ||
2912 n->name() == "MementoRedoCommand") {
2914 if ((c = memento_command_factory(n))) {
2918 } else if (n->name() == X_("GlobalRouteStateCommand")) {
2920 if ((c = global_state_command_factory (*n))) {
2921 ut->add_command (c);
2924 } else if (n->name() == "DeltaCommand") {
2925 PBD::ID id(n->property("midi-source")->value());
2926 boost::shared_ptr<MidiSource> midi_source =
2927 boost::dynamic_pointer_cast<MidiSource, Source>(source_by_id(id));
2929 ut->add_command(new MidiModel::DeltaCommand(midi_source->model(), *n));
2931 error << "FIXME: Failed to downcast MidiSource for DeltaCommand" << endmsg;
2934 error << string_compose(_("Couldn't figure out how to make a Command out of a %1 XMLNode."), n->name()) << endmsg;
2945 Session::config_changed (std::string p, bool ours)
2951 if (p == "seamless-loop") {
2953 } else if (p == "rf-speed") {
2955 } else if (p == "auto-loop") {
2957 } else if (p == "auto-input") {
2959 if (Config->get_monitoring_model() == HardwareMonitoring && transport_rolling()) {
2960 /* auto-input only makes a difference if we're rolling */
2962 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
2964 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
2965 if ((*i)->record_enabled ()) {
2966 (*i)->monitor_input (!config.get_auto_input());
2971 } else if (p == "punch-in") {
2975 if ((location = _locations.auto_punch_location()) != 0) {
2977 if (config.get_punch_in ()) {
2978 replace_event (Event::PunchIn, location->start());
2980 remove_event (location->start(), Event::PunchIn);
2984 } else if (p == "punch-out") {
2988 if ((location = _locations.auto_punch_location()) != 0) {
2990 if (config.get_punch_out()) {
2991 replace_event (Event::PunchOut, location->end());
2993 clear_events (Event::PunchOut);
2997 } else if (p == "edit-mode") {
2999 Glib::Mutex::Lock lm (playlist_lock);
3001 for (PlaylistList::iterator i = playlists.begin(); i != playlists.end(); ++i) {
3002 (*i)->set_edit_mode (Config->get_edit_mode ());
3005 } else if (p == "use-video-sync") {
3007 waiting_for_sync_offset = config.get_use_video_sync();
3009 } else if (p == "mmc-control") {
3011 //poke_midi_thread ();
3013 } else if (p == "mmc-device-id" || p == "mmc-receive-id") {
3016 mmc->set_receive_device_id (Config->get_mmc_receive_device_id());
3019 } else if (p == "mmc-send-id") {
3022 mmc->set_send_device_id (Config->get_mmc_send_device_id());
3025 } else if (p == "midi-control") {
3027 //poke_midi_thread ();
3029 } else if (p == "raid-path") {
3031 setup_raid_path (config.get_raid_path());
3033 } else if (p == "smpte-format") {
3037 } else if (p == "video-pullup") {
3041 } else if (p == "seamless-loop") {
3043 if (play_loop && transport_rolling()) {
3044 // to reset diskstreams etc
3045 request_play_loop (true);
3048 } else if (p == "rf-speed") {
3050 cumulative_rf_motion = 0;
3053 } else if (p == "click-sound") {
3055 setup_click_sounds (1);
3057 } else if (p == "click-emphasis-sound") {
3059 setup_click_sounds (-1);
3061 } else if (p == "clicking") {
3063 if (Config->get_clicking()) {
3064 if (_click_io && click_data) { // don't require emphasis data
3071 } else if (p == "send-mtc") {
3073 /* only set the internal flag if we have
3077 if (_mtc_port != 0) {
3078 session_send_mtc = Config->get_send_mtc();
3079 if (session_send_mtc) {
3080 /* mark us ready to send */
3081 next_quarter_frame_to_send = 0;
3084 session_send_mtc = false;
3087 } else if (p == "send-mmc") {
3089 /* only set the internal flag if we have
3093 if (_mmc_port != 0) {
3094 session_send_mmc = Config->get_send_mmc();
3097 session_send_mmc = false;
3100 } else if (p == "midi-feedback") {
3102 /* only set the internal flag if we have
3106 if (_mtc_port != 0) {
3107 session_midi_feedback = Config->get_midi_feedback();
3110 } else if (p == "jack-time-master") {
3112 engine().reset_timebase ();
3114 } else if (p == "native-file-header-format") {
3116 if (!first_file_header_format_reset) {
3117 reset_native_file_format ();
3120 first_file_header_format_reset = false;
3122 } else if (p == "native-file-data-format") {
3124 if (!first_file_data_format_reset) {
3125 reset_native_file_format ();
3128 first_file_data_format_reset = false;
3130 } else if (p == "slave-source") {
3131 set_slave_source (Config->get_slave_source());
3132 } else if (p == "remote-model") {
3133 set_remote_control_ids ();
3134 } else if (p == "denormal-model") {
3136 } else if (p == "history-depth") {
3137 set_history_depth (Config->get_history_depth());
3138 } else if (p == "sync-all-route-ordering") {
3139 sync_order_keys ("session");
3140 } else if (p == "initial-program-change") {
3142 if (_mmc_port && Config->get_initial_program_change() >= 0) {
3145 buf[0] = MIDI::program; // channel zero by default
3146 buf[1] = (Config->get_initial_program_change() & 0x7f);
3148 _mmc_port->midimsg (buf, sizeof (buf), 0);
3150 } else if (p == "initial-program-change") {
3152 if (_mmc_port && Config->get_initial_program_change() >= 0) {
3153 MIDI::byte* buf = new MIDI::byte[2];
3155 buf[0] = MIDI::program; // channel zero by default
3156 buf[1] = (Config->get_initial_program_change() & 0x7f);
3157 // deliver_midi (_mmc_port, buf, 2);
3159 } else if (p == "solo-mute-override") {
3160 // catch_up_on_solo_mute_override ();
3161 } else if (p == "listen-position") {
3162 listen_position_changed ();
3163 } else if (p == "solo-control-is-listen-control") {
3164 solo_control_mode_changed ();
3172 Session::set_history_depth (uint32_t d)
3174 _history.set_depth (d);