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);
2155 if (!_current_trans.empty()) {
2156 _current_trans.top()->add_command (trans);
2158 _current_trans.push(trans);
2163 Session::commit_reversible_command(Command *cmd)
2165 assert(!_current_trans.empty());
2169 _current_trans.top()->add_command(cmd);
2172 if (_current_trans.top()->empty()) {
2173 _current_trans.pop();
2177 gettimeofday(&now, 0);
2178 _current_trans.top()->set_timestamp(now);
2180 _history.add(_current_trans.top());
2181 _current_trans.pop();
2184 Session::GlobalRouteBooleanState
2185 Session::get_global_route_boolean (bool (Route::*method)(void) const)
2187 GlobalRouteBooleanState s;
2188 boost::shared_ptr<RouteList> r = routes.reader ();
2190 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
2191 if (!(*i)->is_hidden()) {
2192 RouteBooleanState v;
2195 Route* r = (*i).get();
2196 v.second = (r->*method)();
2205 Session::GlobalRouteMeterState
2206 Session::get_global_route_metering ()
2208 GlobalRouteMeterState s;
2209 boost::shared_ptr<RouteList> r = routes.reader ();
2211 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
2212 if (!(*i)->is_hidden()) {
2216 v.second = (*i)->meter_point();
2226 Session::set_global_route_metering (GlobalRouteMeterState s, void* arg)
2228 for (GlobalRouteMeterState::iterator i = s.begin(); i != s.end(); ++i) {
2230 boost::shared_ptr<Route> r = (i->first.lock());
2233 r->set_meter_point (i->second, arg);
2239 Session::set_global_route_boolean (GlobalRouteBooleanState s, void (Route::*method)(bool, void*), void* arg)
2241 for (GlobalRouteBooleanState::iterator i = s.begin(); i != s.end(); ++i) {
2243 boost::shared_ptr<Route> r = (i->first.lock());
2246 Route* rp = r.get();
2247 (rp->*method) (i->second, arg);
2253 Session::set_global_mute (GlobalRouteBooleanState s, void* src)
2255 set_global_route_boolean (s, &Route::set_mute, src);
2259 Session::set_global_solo (GlobalRouteBooleanState s, void* src)
2261 set_global_route_boolean (s, &Route::set_solo, src);
2265 Session::set_global_record_enable (GlobalRouteBooleanState s, void* src)
2267 set_global_route_boolean (s, &Route::set_record_enable, src);
2271 accept_all_non_peak_files (const string& path, void */*arg*/)
2273 return (path.length() > 5 && path.find (peakfile_suffix) != (path.length() - 5));
2277 accept_all_state_files (const string& path, void */*arg*/)
2279 return (path.length() > 7 && path.find (".ardour") == (path.length() - 7));
2283 Session::find_all_sources (string path, set<string>& result)
2288 if (!tree.read (path)) {
2292 if ((node = find_named_node (*tree.root(), "Sources")) == 0) {
2297 XMLNodeConstIterator niter;
2299 nlist = node->children();
2303 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2307 if ((prop = (*niter)->property (X_("type"))) == 0) {
2311 DataType type (prop->value());
2313 if ((prop = (*niter)->property (X_("name"))) == 0) {
2317 if (prop->value()[0] == '/') {
2318 /* external file, ignore */
2322 Glib::ustring found_path;
2326 if (FileSource::find (type, prop->value(), true, is_new, chan, found_path)) {
2327 result.insert (found_path);
2335 Session::find_all_sources_across_snapshots (set<string>& result, bool exclude_this_snapshot)
2337 PathScanner scanner;
2338 vector<string*>* state_files;
2340 string this_snapshot_path;
2346 if (ripped[ripped.length()-1] == '/') {
2347 ripped = ripped.substr (0, ripped.length() - 1);
2350 state_files = scanner (ripped, accept_all_state_files, (void *) 0, false, true);
2352 if (state_files == 0) {
2357 this_snapshot_path = _path;
2358 this_snapshot_path += legalize_for_path (_current_snapshot_name);
2359 this_snapshot_path += statefile_suffix;
2361 for (vector<string*>::iterator i = state_files->begin(); i != state_files->end(); ++i) {
2363 if (exclude_this_snapshot && **i == this_snapshot_path) {
2367 if (find_all_sources (**i, result) < 0) {
2375 struct RegionCounter {
2376 typedef std::map<PBD::ID,boost::shared_ptr<AudioSource> > AudioSourceList;
2377 AudioSourceList::iterator iter;
2378 boost::shared_ptr<Region> region;
2381 RegionCounter() : count (0) {}
2385 Session::cleanup_sources (Session::cleanup_report& rep)
2387 // FIXME: needs adaptation to midi
2389 vector<boost::shared_ptr<Source> > dead_sources;
2390 vector<boost::shared_ptr<Playlist> > playlists_tbd;
2391 PathScanner scanner;
2393 vector<space_and_path>::iterator i;
2394 vector<space_and_path>::iterator nexti;
2395 vector<string*>* soundfiles;
2396 vector<string> unused;
2397 set<string> all_sources;
2402 _state_of_the_state = (StateOfTheState) (_state_of_the_state | InCleanup);
2405 /* step 1: consider deleting all unused playlists */
2407 for (PlaylistList::iterator x = unused_playlists.begin(); x != unused_playlists.end(); ++x) {
2410 status = AskAboutPlaylistDeletion (*x);
2419 playlists_tbd.push_back (*x);
2423 /* leave it alone */
2428 /* now delete any that were marked for deletion */
2430 for (vector<boost::shared_ptr<Playlist> >::iterator x = playlists_tbd.begin(); x != playlists_tbd.end(); ++x) {
2431 (*x)->drop_references ();
2434 playlists_tbd.clear ();
2436 /* step 2: find all un-used sources */
2441 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ) {
2443 SourceMap::iterator tmp;
2448 /* do not bother with files that are zero size, otherwise we remove the current "nascent"
2452 if (!i->second->used() && i->second->length(i->second->timeline_position()) > 0) {
2453 dead_sources.push_back (i->second);
2454 i->second->GoingAway();
2460 /* build a list of all the possible sound directories for the session */
2462 for (i = session_dirs.begin(); i != session_dirs.end(); ) {
2467 SessionDirectory sdir ((*i).path);
2468 sound_path += sdir.sound_path().to_string();
2470 if (nexti != session_dirs.end()) {
2477 /* now do the same thing for the files that ended up in the sounds dir(s)
2478 but are not referenced as sources in any snapshot.
2481 soundfiles = scanner (sound_path, accept_all_non_peak_files, (void *) 0, false, true);
2483 if (soundfiles == 0) {
2487 /* find all sources, but don't use this snapshot because the
2488 state file on disk still references sources we may have already
2492 find_all_sources_across_snapshots (all_sources, true);
2494 /* add our current source list
2497 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ++i) {
2498 boost::shared_ptr<FileSource> fs;
2500 if ((fs = boost::dynamic_pointer_cast<FileSource> (i->second)) != 0) {
2501 all_sources.insert (fs->path());
2505 char tmppath1[PATH_MAX+1];
2506 char tmppath2[PATH_MAX+1];
2508 for (vector<string*>::iterator x = soundfiles->begin(); x != soundfiles->end(); ++x) {
2513 for (set<string>::iterator i = all_sources.begin(); i != all_sources.end(); ++i) {
2515 realpath(spath.c_str(), tmppath1);
2516 realpath((*i).c_str(), tmppath2);
2518 if (strcmp(tmppath1, tmppath2) == 0) {
2525 unused.push_back (spath);
2529 /* now try to move all unused files into the "dead_sounds" directory(ies) */
2531 for (vector<string>::iterator x = unused.begin(); x != unused.end(); ++x) {
2532 struct stat statbuf;
2534 rep.paths.push_back (*x);
2535 if (stat ((*x).c_str(), &statbuf) == 0) {
2536 rep.space += statbuf.st_size;
2541 /* don't move the file across filesystems, just
2542 stick it in the `dead_sound_dir_name' directory
2543 on whichever filesystem it was already on.
2546 if ((*x).find ("/sounds/") != string::npos) {
2548 /* old school, go up 1 level */
2550 newpath = Glib::path_get_dirname (*x); // "sounds"
2551 newpath = Glib::path_get_dirname (newpath); // "session-name"
2555 /* new school, go up 4 levels */
2557 newpath = Glib::path_get_dirname (*x); // "audiofiles"
2558 newpath = Glib::path_get_dirname (newpath); // "session-name"
2559 newpath = Glib::path_get_dirname (newpath); // "interchange"
2560 newpath = Glib::path_get_dirname (newpath); // "session-dir"
2564 newpath += dead_sound_dir_name;
2566 if (g_mkdir_with_parents (newpath.c_str(), 0755) < 0) {
2567 error << string_compose(_("Session: cannot create session peakfile folder \"%1\" (%2)"), newpath, strerror (errno)) << endmsg;
2572 newpath += Glib::path_get_basename ((*x));
2574 if (access (newpath.c_str(), F_OK) == 0) {
2576 /* the new path already exists, try versioning */
2578 char buf[PATH_MAX+1];
2582 snprintf (buf, sizeof (buf), "%s.%d", newpath.c_str(), version);
2585 while (access (newpath_v.c_str(), F_OK) == 0 && version < 999) {
2586 snprintf (buf, sizeof (buf), "%s.%d", newpath.c_str(), ++version);
2590 if (version == 999) {
2591 error << string_compose (_("there are already 1000 files with names like %1; versioning discontinued"),
2595 newpath = newpath_v;
2600 /* it doesn't exist, or we can't read it or something */
2604 if (::rename ((*x).c_str(), newpath.c_str()) != 0) {
2605 error << string_compose (_("cannot rename audio file source from %1 to %2 (%3)"),
2606 (*x), newpath, strerror (errno))
2611 /* see if there an easy to find peakfile for this file, and remove it.
2614 string peakpath = (*x).substr (0, (*x).find_last_of ('.'));
2615 peakpath += peakfile_suffix;
2617 if (access (peakpath.c_str(), W_OK) == 0) {
2618 if (::unlink (peakpath.c_str()) != 0) {
2619 error << string_compose (_("cannot remove peakfile %1 for %2 (%3)"),
2620 peakpath, _path, strerror (errno))
2622 /* try to back out */
2623 rename (newpath.c_str(), _path.c_str());
2631 /* dump the history list */
2635 /* save state so we don't end up a session file
2636 referring to non-existent sources.
2642 _state_of_the_state = (StateOfTheState) (_state_of_the_state & ~InCleanup);
2648 Session::cleanup_trash_sources (Session::cleanup_report& rep)
2650 // FIXME: needs adaptation for MIDI
2652 vector<space_and_path>::iterator i;
2653 string dead_sound_dir;
2654 struct dirent* dentry;
2655 struct stat statbuf;
2661 for (i = session_dirs.begin(); i != session_dirs.end(); ++i) {
2663 dead_sound_dir = (*i).path;
2664 dead_sound_dir += dead_sound_dir_name;
2666 if ((dead = opendir (dead_sound_dir.c_str())) == 0) {
2670 while ((dentry = readdir (dead)) != 0) {
2672 /* avoid '.' and '..' */
2674 if ((dentry->d_name[0] == '.' && dentry->d_name[1] == '\0') ||
2675 (dentry->d_name[2] == '\0' && dentry->d_name[0] == '.' && dentry->d_name[1] == '.')) {
2681 fullpath = dead_sound_dir;
2683 fullpath += dentry->d_name;
2685 if (stat (fullpath.c_str(), &statbuf)) {
2689 if (!S_ISREG (statbuf.st_mode)) {
2693 if (unlink (fullpath.c_str())) {
2694 error << string_compose (_("cannot remove dead sound file %1 (%2)"),
2695 fullpath, strerror (errno))
2699 rep.paths.push_back (dentry->d_name);
2700 rep.space += statbuf.st_size;
2711 Session::set_dirty ()
2713 bool was_dirty = dirty();
2715 _state_of_the_state = StateOfTheState (_state_of_the_state | Dirty);
2719 DirtyChanged(); /* EMIT SIGNAL */
2725 Session::set_clean ()
2727 bool was_dirty = dirty();
2729 _state_of_the_state = Clean;
2733 DirtyChanged(); /* EMIT SIGNAL */
2738 Session::set_deletion_in_progress ()
2740 _state_of_the_state = StateOfTheState (_state_of_the_state | Deletion);
2744 Session::clear_deletion_in_progress ()
2746 _state_of_the_state = StateOfTheState (_state_of_the_state & (~Deletion));
2750 Session::add_controllable (boost::shared_ptr<Controllable> c)
2752 /* this adds a controllable to the list managed by the Session.
2753 this is a subset of those managed by the Controllable class
2754 itself, and represents the only ones whose state will be saved
2755 as part of the session.
2758 Glib::Mutex::Lock lm (controllables_lock);
2759 controllables.insert (c);
2762 struct null_deleter { void operator()(void const *) const {} };
2765 Session::remove_controllable (Controllable* c)
2767 if (_state_of_the_state | Deletion) {
2771 Glib::Mutex::Lock lm (controllables_lock);
2773 Controllables::iterator x = controllables.find(
2774 boost::shared_ptr<Controllable>(c, null_deleter()));
2776 if (x != controllables.end()) {
2777 controllables.erase (x);
2781 boost::shared_ptr<Controllable>
2782 Session::controllable_by_id (const PBD::ID& id)
2784 Glib::Mutex::Lock lm (controllables_lock);
2786 for (Controllables::iterator i = controllables.begin(); i != controllables.end(); ++i) {
2787 if ((*i)->id() == id) {
2792 return boost::shared_ptr<Controllable>();
2796 Session::add_instant_xml (XMLNode& node, bool write_to_config)
2798 Stateful::add_instant_xml (node, _path);
2799 if (write_to_config) {
2800 Config->add_instant_xml (node);
2805 Session::instant_xml (const string& node_name)
2807 return Stateful::instant_xml (node_name, _path);
2811 Session::save_history (string snapshot_name)
2815 if (snapshot_name.empty()) {
2816 snapshot_name = _current_snapshot_name;
2819 const string history_filename = legalize_for_path (snapshot_name) + history_suffix;
2820 const string backup_filename = history_filename + backup_suffix;
2821 const sys::path xml_path = _session_dir->root_path() / history_filename;
2822 const sys::path backup_path = _session_dir->root_path() / backup_filename;
2824 if (sys::exists (xml_path)) {
2827 sys::rename (xml_path, backup_path);
2829 catch (const sys::filesystem_error& err)
2831 error << _("could not backup old history file, current history not saved") << endmsg;
2837 if (!Config->get_save_history() || Config->get_saved_history_depth() < 0) {
2841 tree.set_root (&_history.get_state (Config->get_saved_history_depth()));
2843 if (!tree.write (xml_path.to_string()))
2845 error << string_compose (_("history could not be saved to %1"), xml_path.to_string()) << endmsg;
2849 sys::remove (xml_path);
2850 sys::rename (backup_path, xml_path);
2852 catch (const sys::filesystem_error& err)
2854 error << string_compose (_("could not restore history file from backup %1 (%2)"),
2855 backup_path.to_string(), err.what()) << endmsg;
2865 Session::restore_history (string snapshot_name)
2869 if (snapshot_name.empty()) {
2870 snapshot_name = _current_snapshot_name;
2873 const string xml_filename = legalize_for_path (snapshot_name) + history_suffix;
2874 const sys::path xml_path = _session_dir->root_path() / xml_filename;
2876 cerr << "Loading history from " << xml_path.to_string() << endmsg;
2878 if (!sys::exists (xml_path)) {
2879 info << string_compose (_("%1: no history file \"%2\" for this session."),
2880 _name, xml_path.to_string()) << endmsg;
2884 if (!tree.read (xml_path.to_string())) {
2885 error << string_compose (_("Could not understand session history file \"%1\""),
2886 xml_path.to_string()) << endmsg;
2893 for (XMLNodeConstIterator it = tree.root()->children().begin(); it != tree.root()->children().end(); it++) {
2896 UndoTransaction* ut = new UndoTransaction ();
2899 ut->set_name(t->property("name")->value());
2900 stringstream ss(t->property("tv-sec")->value());
2902 ss.str(t->property("tv-usec")->value());
2904 ut->set_timestamp(tv);
2906 for (XMLNodeConstIterator child_it = t->children().begin();
2907 child_it != t->children().end(); child_it++)
2909 XMLNode *n = *child_it;
2912 if (n->name() == "MementoCommand" ||
2913 n->name() == "MementoUndoCommand" ||
2914 n->name() == "MementoRedoCommand") {
2916 if ((c = memento_command_factory(n))) {
2920 } else if (n->name() == X_("GlobalRouteStateCommand")) {
2922 if ((c = global_state_command_factory (*n))) {
2923 ut->add_command (c);
2926 } else if (n->name() == "DeltaCommand") {
2927 PBD::ID id(n->property("midi-source")->value());
2928 boost::shared_ptr<MidiSource> midi_source =
2929 boost::dynamic_pointer_cast<MidiSource, Source>(source_by_id(id));
2931 ut->add_command(new MidiModel::DeltaCommand(midi_source->model(), *n));
2933 error << "FIXME: Failed to downcast MidiSource for DeltaCommand" << endmsg;
2935 } else if (n->name() == "DiffCommand") {
2936 PBD::ID id(n->property("midi-source")->value());
2937 boost::shared_ptr<MidiSource> midi_source =
2938 boost::dynamic_pointer_cast<MidiSource, Source>(source_by_id(id));
2940 ut->add_command(new MidiModel::DiffCommand(midi_source->model(), *n));
2942 error << "FIXME: Failed to downcast MidiSource for DeltaCommand" << endmsg;
2946 error << string_compose(_("Couldn't figure out how to make a Command out of a %1 XMLNode."), n->name()) << endmsg;
2957 Session::config_changed (std::string p, bool ours)
2963 if (p == "seamless-loop") {
2965 } else if (p == "rf-speed") {
2967 } else if (p == "auto-loop") {
2969 } else if (p == "auto-input") {
2971 if (Config->get_monitoring_model() == HardwareMonitoring && transport_rolling()) {
2972 /* auto-input only makes a difference if we're rolling */
2974 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
2976 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
2977 if ((*i)->record_enabled ()) {
2978 (*i)->monitor_input (!config.get_auto_input());
2983 } else if (p == "punch-in") {
2987 if ((location = _locations.auto_punch_location()) != 0) {
2989 if (config.get_punch_in ()) {
2990 replace_event (Event::PunchIn, location->start());
2992 remove_event (location->start(), Event::PunchIn);
2996 } else if (p == "punch-out") {
3000 if ((location = _locations.auto_punch_location()) != 0) {
3002 if (config.get_punch_out()) {
3003 replace_event (Event::PunchOut, location->end());
3005 clear_events (Event::PunchOut);
3009 } else if (p == "edit-mode") {
3011 Glib::Mutex::Lock lm (playlist_lock);
3013 for (PlaylistList::iterator i = playlists.begin(); i != playlists.end(); ++i) {
3014 (*i)->set_edit_mode (Config->get_edit_mode ());
3017 } else if (p == "use-video-sync") {
3019 waiting_for_sync_offset = config.get_use_video_sync();
3021 } else if (p == "mmc-control") {
3023 //poke_midi_thread ();
3025 } else if (p == "mmc-device-id" || p == "mmc-receive-id") {
3028 mmc->set_receive_device_id (Config->get_mmc_receive_device_id());
3031 } else if (p == "mmc-send-id") {
3034 mmc->set_send_device_id (Config->get_mmc_send_device_id());
3037 } else if (p == "midi-control") {
3039 //poke_midi_thread ();
3041 } else if (p == "raid-path") {
3043 setup_raid_path (config.get_raid_path());
3045 } else if (p == "smpte-format") {
3049 } else if (p == "video-pullup") {
3053 } else if (p == "seamless-loop") {
3055 if (play_loop && transport_rolling()) {
3056 // to reset diskstreams etc
3057 request_play_loop (true);
3060 } else if (p == "rf-speed") {
3062 cumulative_rf_motion = 0;
3065 } else if (p == "click-sound") {
3067 setup_click_sounds (1);
3069 } else if (p == "click-emphasis-sound") {
3071 setup_click_sounds (-1);
3073 } else if (p == "clicking") {
3075 if (Config->get_clicking()) {
3076 if (_click_io && click_data) { // don't require emphasis data
3083 } else if (p == "send-mtc") {
3085 /* only set the internal flag if we have
3089 if (_mtc_port != 0) {
3090 session_send_mtc = Config->get_send_mtc();
3091 if (session_send_mtc) {
3092 /* mark us ready to send */
3093 next_quarter_frame_to_send = 0;
3096 session_send_mtc = false;
3099 } else if (p == "send-mmc") {
3101 /* only set the internal flag if we have
3105 if (_mmc_port != 0) {
3106 session_send_mmc = Config->get_send_mmc();
3109 session_send_mmc = false;
3112 } else if (p == "midi-feedback") {
3114 /* only set the internal flag if we have
3118 if (_mtc_port != 0) {
3119 session_midi_feedback = Config->get_midi_feedback();
3122 } else if (p == "jack-time-master") {
3124 engine().reset_timebase ();
3126 } else if (p == "native-file-header-format") {
3128 if (!first_file_header_format_reset) {
3129 reset_native_file_format ();
3132 first_file_header_format_reset = false;
3134 } else if (p == "native-file-data-format") {
3136 if (!first_file_data_format_reset) {
3137 reset_native_file_format ();
3140 first_file_data_format_reset = false;
3142 } else if (p == "slave-source") {
3143 set_slave_source (Config->get_slave_source());
3144 } else if (p == "remote-model") {
3145 set_remote_control_ids ();
3146 } else if (p == "denormal-model") {
3148 } else if (p == "history-depth") {
3149 set_history_depth (Config->get_history_depth());
3150 } else if (p == "sync-all-route-ordering") {
3151 sync_order_keys ("session");
3152 } else if (p == "initial-program-change") {
3154 if (_mmc_port && Config->get_initial_program_change() >= 0) {
3157 buf[0] = MIDI::program; // channel zero by default
3158 buf[1] = (Config->get_initial_program_change() & 0x7f);
3160 _mmc_port->midimsg (buf, sizeof (buf), 0);
3162 } else if (p == "initial-program-change") {
3164 if (_mmc_port && Config->get_initial_program_change() >= 0) {
3165 MIDI::byte* buf = new MIDI::byte[2];
3167 buf[0] = MIDI::program; // channel zero by default
3168 buf[1] = (Config->get_initial_program_change() & 0x7f);
3169 // deliver_midi (_mmc_port, buf, 2);
3171 } else if (p == "solo-mute-override") {
3172 // catch_up_on_solo_mute_override ();
3173 } else if (p == "listen-position") {
3174 listen_position_changed ();
3175 } else if (p == "solo-control-is-listen-control") {
3176 solo_control_mode_changed ();
3184 Session::set_history_depth (uint32_t d)
3186 _history.set_depth (d);