2 Copyright (C) 1999-2002 Paul Davis
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 #include "libardour-config.h"
25 #define __STDC_FORMAT_MACROS 1
34 #include <cstdio> /* snprintf(3) ... grrr */
49 #include <sys/param.h>
50 #include <sys/mount.h>
54 #include <glibmm/thread.h>
56 #include "midi++/mmc.h"
57 #include "midi++/port.h"
59 #include "pbd/boost_debug.h"
60 #include "pbd/controllable_descriptor.h"
61 #include "pbd/enumwriter.h"
62 #include "pbd/error.h"
63 #include "pbd/pathscanner.h"
64 #include "pbd/pthread_utils.h"
65 #include "pbd/search_path.h"
66 #include "pbd/stacktrace.h"
67 #include "pbd/convert.h"
69 #include "ardour/amp.h"
70 #include "ardour/audio_diskstream.h"
71 #include "ardour/audio_track.h"
72 #include "ardour/audioengine.h"
73 #include "ardour/audiofilesource.h"
74 #include "ardour/audioplaylist.h"
75 #include "ardour/audioregion.h"
76 #include "ardour/auditioner.h"
77 #include "ardour/buffer.h"
78 #include "ardour/butler.h"
79 #include "ardour/configuration.h"
80 #include "ardour/control_protocol_manager.h"
81 #include "ardour/crossfade.h"
82 #include "ardour/cycle_timer.h"
83 #include "ardour/directory_names.h"
84 #include "ardour/filename_extensions.h"
85 #include "ardour/io_processor.h"
86 #include "ardour/location.h"
87 #include "ardour/midi_diskstream.h"
88 #include "ardour/midi_patch_manager.h"
89 #include "ardour/midi_playlist.h"
90 #include "ardour/midi_region.h"
91 #include "ardour/midi_source.h"
92 #include "ardour/midi_track.h"
93 #include "ardour/named_selection.h"
94 #include "ardour/processor.h"
95 #include "ardour/port.h"
96 #include "ardour/region_factory.h"
97 #include "ardour/route_group.h"
98 #include "ardour/send.h"
99 #include "ardour/session.h"
100 #include "ardour/session_directory.h"
101 #include "ardour/session_metadata.h"
102 #include "ardour/session_state_utils.h"
103 #include "ardour/session_playlists.h"
104 #include "ardour/session_utils.h"
105 #include "ardour/silentfilesource.h"
106 #include "ardour/slave.h"
107 #include "ardour/smf_source.h"
108 #include "ardour/sndfile_helpers.h"
109 #include "ardour/sndfilesource.h"
110 #include "ardour/source_factory.h"
111 #include "ardour/template_utils.h"
112 #include "ardour/tempo.h"
113 #include "ardour/ticker.h"
114 #include "ardour/user_bundle.h"
115 #include "ardour/utils.h"
116 #include "ardour/utils.h"
117 #include "ardour/version.h"
118 #include "ardour/playlist_factory.h"
120 #include "control_protocol/control_protocol.h"
126 using namespace ARDOUR;
130 Session::first_stage_init (string fullpath, string snapshot_name)
132 if (fullpath.length() == 0) {
134 throw failed_constructor();
137 char buf[PATH_MAX+1];
138 if (!realpath (fullpath.c_str(), buf) && (errno != ENOENT)) {
139 error << string_compose(_("Could not use path %1 (%s)"), buf, strerror(errno)) << endmsg;
141 throw failed_constructor();
146 if (_path[_path.length()-1] != '/') {
150 if (Glib::file_test (_path, Glib::FILE_TEST_EXISTS) && ::access (_path.c_str(), W_OK)) {
156 /* these two are just provisional settings. set_state()
157 will likely override them.
160 _name = _current_snapshot_name = snapshot_name;
162 set_history_depth (Config->get_history_depth());
164 _current_frame_rate = _engine.frame_rate ();
165 _nominal_frame_rate = _current_frame_rate;
166 _base_frame_rate = _current_frame_rate;
168 _tempo_map = new TempoMap (_current_frame_rate);
169 _tempo_map->PropertyChanged.connect_same_thread (*this, boost::bind (&Session::tempo_map_changed, this, _1));
172 _non_soloed_outs_muted = false;
174 _solo_isolated_cnt = 0;
175 g_atomic_int_set (&processing_prohibited, 0);
176 _transport_speed = 0;
177 _last_transport_speed = 0;
178 _target_transport_speed = 0;
179 auto_play_legal = false;
180 transport_sub_state = 0;
181 _transport_frame = 0;
182 _requested_return_frame = -1;
183 _session_range_location = 0;
184 g_atomic_int_set (&_record_status, Disabled);
185 loop_changing = false;
188 _last_roll_location = 0;
189 _last_roll_or_reversal_location = 0;
190 _last_record_location = 0;
191 pending_locate_frame = 0;
192 pending_locate_roll = false;
193 pending_locate_flush = false;
194 state_was_pending = false;
196 outbound_mtc_timecode_frame = 0;
197 next_quarter_frame_to_send = -1;
198 current_block_size = 0;
199 solo_update_disabled = false;
200 _have_captured = false;
201 _worst_output_latency = 0;
202 _worst_input_latency = 0;
203 _worst_track_latency = 0;
204 _state_of_the_state = StateOfTheState(CannotSave|InitialConnecting|Loading);
205 _was_seamless = Config->get_seamless_loop ();
207 session_send_mtc = false;
208 g_atomic_int_set (&_playback_load, 100);
209 g_atomic_int_set (&_capture_load, 100);
212 pending_abort = false;
213 destructive_index = 0;
214 first_file_data_format_reset = true;
215 first_file_header_format_reset = true;
216 post_export_sync = false;
219 AudioDiskstream::allocate_working_buffers();
221 /* default short fade = 15ms */
223 Crossfade::set_short_xfade_length ((nframes_t) floor (config.get_short_xfade_seconds() * frame_rate()));
224 SndFileSource::setup_standard_crossfades (*this, frame_rate());
226 last_mmc_step.tv_sec = 0;
227 last_mmc_step.tv_usec = 0;
230 /* click sounds are unset by default, which causes us to internal
231 waveforms for clicks.
235 click_emphasis_length = 0;
238 process_function = &Session::process_with_events;
240 if (config.get_use_video_sync()) {
241 waiting_for_sync_offset = true;
243 waiting_for_sync_offset = false;
246 last_timecode_when = 0;
247 _timecode_offset = 0;
248 _timecode_offset_negative = true;
249 last_timecode_valid = false;
253 last_rr_session_dir = session_dirs.begin();
254 refresh_disk_space ();
256 // set_default_fade (0.2, 5.0); /* steepness, millisecs */
260 average_slave_delta = 1800; // !!! why 1800 ????
261 have_first_delta_accumulator = false;
262 delta_accumulator_cnt = 0;
263 _slave_state = Stopped;
265 _engine.GraphReordered.connect_same_thread (*this, boost::bind (&Session::graph_reordered, this));
267 /* These are all static "per-class" signals */
269 SourceFactory::SourceCreated.connect_same_thread (*this, boost::bind (&Session::add_source, this, _1));
270 PlaylistFactory::PlaylistCreated.connect_same_thread (*this, boost::bind (&Session::add_playlist, this, _1, _2));
271 AutomationList::AutomationListCreated.connect_same_thread (*this, boost::bind (&Session::add_automation_list, this, _1));
272 Controllable::Destroyed.connect_same_thread (*this, boost::bind (&Session::remove_controllable, this, _1));
273 IO::PortCountChanged.connect_same_thread (*this, boost::bind (&Session::ensure_buffers, this, _1));
275 /* stop IO objects from doing stuff until we're ready for them */
277 Delivery::disable_panners ();
278 IO::disable_connecting ();
282 Session::second_stage_init ()
284 AudioFileSource::set_peak_dir (_session_dir->peak_path().to_string());
287 if (load_state (_current_snapshot_name)) {
290 remove_empty_sounds ();
293 if (_butler->start_thread()) {
297 if (start_midi_thread ()) {
301 setup_midi_machine_control ();
303 // set_state() will call setup_raid_path(), but if it's a new session we need
304 // to call setup_raid_path() here.
307 if (set_state (*state_tree->root(), Stateful::loading_state_version)) {
311 setup_raid_path(_path);
314 /* we can't save till after ::when_engine_running() is called,
315 because otherwise we save state with no connections made.
316 therefore, we reset _state_of_the_state because ::set_state()
317 will have cleared it.
319 we also have to include Loading so that any events that get
320 generated between here and the end of ::when_engine_running()
321 will be processed directly rather than queued.
324 _state_of_the_state = StateOfTheState (_state_of_the_state|CannotSave|Loading);
326 _locations.changed.connect_same_thread (*this, boost::bind (&Session::locations_changed, this));
327 _locations.added.connect_same_thread (*this, boost::bind (&Session::locations_added, this, _1));
328 setup_click_sounds (0);
329 setup_midi_control ();
331 /* Pay attention ... */
333 _engine.Halted.connect_same_thread (*this, boost::bind (&Session::engine_halted, this));
334 _engine.Xrun.connect_same_thread (*this, boost::bind (&Session::xrun_recovery, this));
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 _mmc->send (MIDI::MachineControlCommand (MIDI::MachineControl::cmdMmcReset));
356 _mmc->send (MIDI::MachineControlCommand (Timecode::Time ()));
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 _state_of_the_state = Clean;
369 Port::set_connecting_blocked (false);
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::path_is_within_session (const std::string& path)
434 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
435 if (path.find ((*i).path) == 0) {
443 Session::ensure_subdirs ()
447 dir = session_directory().peak_path().to_string();
449 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
450 error << string_compose(_("Session: cannot create session peakfile folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
454 dir = session_directory().sound_path().to_string();
456 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
457 error << string_compose(_("Session: cannot create session sounds dir \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
461 dir = session_directory().midi_path().to_string();
463 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
464 error << string_compose(_("Session: cannot create session midi dir \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
468 dir = session_directory().dead_sound_path().to_string();
470 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
471 error << string_compose(_("Session: cannot create session dead sounds folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
475 dir = session_directory().export_path().to_string();
477 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
478 error << string_compose(_("Session: cannot create session export folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
482 dir = analysis_dir ();
484 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
485 error << string_compose(_("Session: cannot create session analysis folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
493 Session::create (const string& mix_template, BusProfile* bus_profile)
496 if (g_mkdir_with_parents (_path.c_str(), 0755) < 0) {
497 error << string_compose(_("Session: cannot create session folder \"%1\" (%2)"), _path, strerror (errno)) << endmsg;
501 if (ensure_subdirs ()) {
505 if (!mix_template.empty()) {
506 std::string in_path = mix_template;
508 ifstream in(in_path.c_str());
511 string out_path = _path;
513 out_path += statefile_suffix;
515 ofstream out(out_path.c_str());
523 error << string_compose (_("Could not open %1 for writing mix template"), out_path)
529 error << string_compose (_("Could not open mix template %1 for reading"), in_path)
536 /* Instantiate metadata */
538 _metadata = new SessionMetadata ();
540 /* set initial start + end point */
542 _state_of_the_state = Clean;
544 /* set up Master Out and Control Out if necessary */
550 ChanCount count(DataType::AUDIO, bus_profile->master_out_channels);
552 if (bus_profile->master_out_channels) {
553 Route* rt = new Route (*this, _("master"), Route::MasterOut, DataType::AUDIO);
558 boost_debug_shared_ptr_mark_interesting (rt, "Route");
559 boost::shared_ptr<Route> r (rt);
560 r->input()->ensure_io (count, false, this);
561 r->output()->ensure_io (count, false, this);
562 r->set_remote_control_id (control_id++);
566 if (Config->get_use_monitor_bus()) {
567 Route* rt = new Route (*this, _("monitor"), Route::MonitorOut, DataType::AUDIO);
572 boost_debug_shared_ptr_mark_interesting (rt, "Route");
573 boost::shared_ptr<Route> r (rt);
574 r->input()->ensure_io (count, false, this);
575 r->output()->ensure_io (count, false, this);
576 r->set_remote_control_id (control_id);
582 /* prohibit auto-connect to master, because there isn't one */
583 bus_profile->output_ac = AutoConnectOption (bus_profile->output_ac & ~AutoConnectMaster);
587 add_routes (rl, false);
590 /* this allows the user to override settings with an environment variable.
593 if (no_auto_connect()) {
594 bus_profile->input_ac = AutoConnectOption (0);
595 bus_profile->output_ac = AutoConnectOption (0);
598 Config->set_input_auto_connect (bus_profile->input_ac);
599 Config->set_output_auto_connect (bus_profile->output_ac);
608 Session::maybe_write_autosave()
610 if (dirty() && record_status() != Recording) {
611 save_state("", true);
616 Session::remove_pending_capture_state ()
618 sys::path pending_state_file_path(_session_dir->root_path());
620 pending_state_file_path /= legalize_for_path (_current_snapshot_name) + pending_suffix;
624 sys::remove (pending_state_file_path);
626 catch(sys::filesystem_error& ex)
628 error << string_compose(_("Could remove pending capture state at path \"%1\" (%2)"),
629 pending_state_file_path.to_string(), ex.what()) << endmsg;
633 /** Rename a state file.
634 * @param snapshot_name Snapshot name.
637 Session::rename_state (string old_name, string new_name)
639 if (old_name == _current_snapshot_name || old_name == _name) {
640 /* refuse to rename the current snapshot or the "main" one */
644 const string old_xml_filename = legalize_for_path (old_name) + statefile_suffix;
645 const string new_xml_filename = legalize_for_path (new_name) + statefile_suffix;
647 const sys::path old_xml_path = _session_dir->root_path() / old_xml_filename;
648 const sys::path new_xml_path = _session_dir->root_path() / new_xml_filename;
652 sys::rename (old_xml_path, new_xml_path);
654 catch (const sys::filesystem_error& err)
656 error << string_compose(_("could not rename snapshot %1 to %2 (%3)"),
657 old_name, new_name, err.what()) << endmsg;
661 /** Remove a state file.
662 * @param snapshot_name Snapshot name.
665 Session::remove_state (string snapshot_name)
667 if (snapshot_name == _current_snapshot_name || snapshot_name == _name) {
668 // refuse to remove the current snapshot or the "main" one
672 sys::path xml_path(_session_dir->root_path());
674 xml_path /= legalize_for_path (snapshot_name) + statefile_suffix;
676 if (!create_backup_file (xml_path)) {
677 // don't remove it if a backup can't be made
678 // create_backup_file will log the error.
683 sys::remove (xml_path);
686 #ifdef HAVE_JACK_SESSION
688 Session::jack_session_event (jack_session_event_t * event)
692 struct tm local_time;
695 localtime_r (&n, &local_time);
696 strftime (timebuf, sizeof(timebuf), "JS_%FT%T", &local_time);
698 if (event->type == JackSessionSaveTemplate)
700 if (save_template( timebuf )) {
701 event->flags = JackSessionSaveError;
703 string cmd ("ardour3 -P -U ");
704 cmd += event->client_uuid;
708 event->command_line = strdup (cmd.c_str());
713 if (save_state (timebuf)) {
714 event->flags = JackSessionSaveError;
716 sys::path xml_path (_session_dir->root_path());
717 xml_path /= legalize_for_path (timebuf) + statefile_suffix;
719 string cmd ("ardour3 -P -U ");
720 cmd += event->client_uuid;
722 cmd += xml_path.to_string();
725 event->command_line = strdup (cmd.c_str());
729 jack_session_reply (_engine.jack(), event);
731 if (event->type == JackSessionSaveAndQuit) {
732 // TODO: make ardour quit.
735 jack_session_event_free( event );
740 Session::save_state (string snapshot_name, bool pending, bool switch_to_snapshot)
743 sys::path xml_path(_session_dir->root_path());
745 if (!_writable || (_state_of_the_state & CannotSave)) {
749 if (!_engine.connected ()) {
750 error << string_compose (_("the %1 audio engine is not connected and state saving would lose all I/O connections. Session not saved"),
756 /* tell sources we're saving first, in case they write out to a new file
757 * which should be saved with the state rather than the old one */
758 for (SourceMap::const_iterator i = sources.begin(); i != sources.end(); ++i) {
759 i->second->session_saved();
762 tree.set_root (&get_state());
764 if (snapshot_name.empty()) {
765 snapshot_name = _current_snapshot_name;
766 } else if (switch_to_snapshot) {
767 _current_snapshot_name = snapshot_name;
772 /* proper save: use statefile_suffix (.ardour in English) */
774 xml_path /= legalize_for_path (snapshot_name) + statefile_suffix;
776 /* make a backup copy of the old file */
778 if (sys::exists(xml_path) && !create_backup_file (xml_path)) {
779 // create_backup_file will log the error
785 /* pending save: use pending_suffix (.pending in English) */
786 xml_path /= legalize_for_path (snapshot_name) + pending_suffix;
789 sys::path tmp_path(_session_dir->root_path());
791 tmp_path /= legalize_for_path (snapshot_name) + temp_suffix;
793 // cerr << "actually writing state to " << xml_path.to_string() << endl;
795 if (!tree.write (tmp_path.to_string())) {
796 error << string_compose (_("state could not be saved to %1"), tmp_path.to_string()) << endmsg;
797 sys::remove (tmp_path);
802 if (rename (tmp_path.to_string().c_str(), xml_path.to_string().c_str()) != 0) {
803 error << string_compose (_("could not rename temporary session file %1 to %2"),
804 tmp_path.to_string(), xml_path.to_string()) << endmsg;
805 sys::remove (tmp_path);
812 save_history (snapshot_name);
814 bool was_dirty = dirty();
816 _state_of_the_state = StateOfTheState (_state_of_the_state & ~Dirty);
819 DirtyChanged (); /* EMIT SIGNAL */
822 StateSaved (snapshot_name); /* EMIT SIGNAL */
829 Session::restore_state (string snapshot_name)
831 if (load_state (snapshot_name) == 0) {
832 set_state (*state_tree->root(), Stateful::loading_state_version);
839 Session::load_state (string snapshot_name)
844 state_was_pending = false;
846 /* check for leftover pending state from a crashed capture attempt */
848 sys::path xmlpath(_session_dir->root_path());
849 xmlpath /= legalize_for_path (snapshot_name) + pending_suffix;
851 if (sys::exists (xmlpath)) {
853 /* there is pending state from a crashed capture attempt */
855 boost::optional<int> r = AskAboutPendingState();
856 if (r.get_value_or (1)) {
857 state_was_pending = true;
861 if (!state_was_pending) {
862 xmlpath = _session_dir->root_path();
863 xmlpath /= snapshot_name;
866 if (!sys::exists (xmlpath)) {
867 xmlpath = _session_dir->root_path();
868 xmlpath /= legalize_for_path (snapshot_name) + statefile_suffix;
869 if (!sys::exists (xmlpath)) {
870 error << string_compose(_("%1: session state information file \"%2\" doesn't exist!"), _name, xmlpath.to_string()) << endmsg;
875 state_tree = new XMLTree;
879 /* writable() really reflects the whole folder, but if for any
880 reason the session state file can't be written to, still
884 if (::access (xmlpath.to_string().c_str(), W_OK) != 0) {
888 if (!state_tree->read (xmlpath.to_string())) {
889 error << string_compose(_("Could not understand ardour file %1"), xmlpath.to_string()) << endmsg;
895 XMLNode& root (*state_tree->root());
897 if (root.name() != X_("Session")) {
898 error << string_compose (_("Session file %1 is not a session"), xmlpath.to_string()) << endmsg;
904 const XMLProperty* prop;
906 if ((prop = root.property ("version")) == 0) {
907 /* no version implies very old version of Ardour */
908 Stateful::loading_state_version = 1000;
914 sscanf (prop->value().c_str(), "%d.%d.%d", &major, &minor, µ);
915 Stateful::loading_state_version = (major * 1000) + minor;
918 if (Stateful::loading_state_version < CURRENT_SESSION_FILE_VERSION) {
920 sys::path backup_path(_session_dir->root_path());
922 backup_path /= legalize_for_path (snapshot_name) + "-1" + statefile_suffix;
924 // only create a backup once
925 if (sys::exists (backup_path)) {
929 info << string_compose (_("Copying old session file %1 to %2\nUse %2 with %3 versions before 2.0 from now on"),
930 xmlpath.to_string(), backup_path.to_string(), PROGRAM_NAME)
935 sys::copy_file (xmlpath, backup_path);
937 catch(sys::filesystem_error& ex)
939 error << string_compose (_("Unable to make backup of state file %1 (%2)"),
940 xmlpath.to_string(), ex.what())
950 Session::load_options (const XMLNode& node)
952 LocaleGuard lg (X_("POSIX"));
953 config.set_variables (node);
964 Session::get_template()
966 /* if we don't disable rec-enable, diskstreams
967 will believe they need to store their capture
968 sources in their state node.
971 disable_record (false);
977 Session::state(bool full_state)
979 XMLNode* node = new XMLNode("Session");
982 // store libardour version, just in case
984 snprintf(buf, sizeof(buf), "%d.%d.%d", libardour3_major_version, libardour3_minor_version, libardour3_micro_version);
985 node->add_property("version", string(buf));
987 /* store configuration settings */
991 node->add_property ("name", _name);
992 snprintf (buf, sizeof (buf), "%" PRId32, _nominal_frame_rate);
993 node->add_property ("sample-rate", buf);
995 if (session_dirs.size() > 1) {
999 vector<space_and_path>::iterator i = session_dirs.begin();
1000 vector<space_and_path>::iterator next;
1002 ++i; /* skip the first one */
1006 while (i != session_dirs.end()) {
1010 if (next != session_dirs.end()) {
1020 child = node->add_child ("Path");
1021 child->add_content (p);
1025 /* save the ID counter */
1027 snprintf (buf, sizeof (buf), "%" PRIu64, ID::counter());
1028 node->add_property ("id-counter", buf);
1030 /* various options */
1032 node->add_child_nocopy (config.get_variables ());
1034 node->add_child_nocopy (_metadata->get_state());
1036 child = node->add_child ("Sources");
1039 Glib::Mutex::Lock sl (source_lock);
1041 for (SourceMap::iterator siter = sources.begin(); siter != sources.end(); ++siter) {
1043 /* Don't save information about non-destructive file sources that are empty
1044 and unused by any regions.
1047 boost::shared_ptr<FileSource> fs;
1048 if ((fs = boost::dynamic_pointer_cast<FileSource> (siter->second)) != 0) {
1049 if (!fs->destructive()) {
1050 if (fs->empty() && !fs->used()) {
1056 child->add_child_nocopy (siter->second->get_state());
1060 child = node->add_child ("Regions");
1063 Glib::Mutex::Lock rl (region_lock);
1064 const RegionFactory::RegionMap& region_map (RegionFactory::all_regions());
1065 for (RegionFactory::RegionMap::const_iterator i = region_map.begin(); i != region_map.end(); ++i) {
1066 boost::shared_ptr<Region> r = i->second;
1067 /* only store regions not attached to playlists */
1068 if (r->playlist() == 0) {
1069 child->add_child_nocopy (r->state (true));
1075 node->add_child_nocopy (_locations.get_state());
1077 // for a template, just create a new Locations, populate it
1078 // with the default start and end, and get the state for that.
1080 Location* range = new Location (0, 0, _("session"), Location::IsSessionRange);
1081 range->set (max_frames, 0);
1083 node->add_child_nocopy (loc.get_state());
1086 child = node->add_child ("Bundles");
1088 boost::shared_ptr<BundleList> bundles = _bundles.reader ();
1089 for (BundleList::iterator i = bundles->begin(); i != bundles->end(); ++i) {
1090 boost::shared_ptr<UserBundle> b = boost::dynamic_pointer_cast<UserBundle> (*i);
1092 child->add_child_nocopy (b->get_state());
1097 child = node->add_child ("Routes");
1099 boost::shared_ptr<RouteList> r = routes.reader ();
1101 RoutePublicOrderSorter cmp;
1102 RouteList public_order (*r);
1103 public_order.sort (cmp);
1105 /* the sort should have put control outs first */
1108 assert (_monitor_out == public_order.front());
1111 for (RouteList::iterator i = public_order.begin(); i != public_order.end(); ++i) {
1112 if (!(*i)->is_hidden()) {
1114 child->add_child_nocopy ((*i)->get_state());
1116 child->add_child_nocopy ((*i)->get_template());
1122 playlists->add_state (node, full_state);
1124 child = node->add_child ("RouteGroups");
1125 for (list<RouteGroup *>::iterator i = _route_groups.begin(); i != _route_groups.end(); ++i) {
1126 child->add_child_nocopy ((*i)->get_state());
1130 child = node->add_child ("Click");
1131 child->add_child_nocopy (_click_io->state (full_state));
1135 child = node->add_child ("NamedSelections");
1136 for (NamedSelectionList::iterator i = named_selections.begin(); i != named_selections.end(); ++i) {
1138 child->add_child_nocopy ((*i)->get_state());
1143 node->add_child_nocopy (_tempo_map->get_state());
1145 node->add_child_nocopy (get_control_protocol_state());
1148 node->add_child_copy (*_extra_xml);
1155 Session::get_control_protocol_state ()
1157 ControlProtocolManager& cpm (ControlProtocolManager::instance());
1158 return cpm.get_state();
1162 Session::set_state (const XMLNode& node, int version)
1166 const XMLProperty* prop;
1169 _state_of_the_state = StateOfTheState (_state_of_the_state|CannotSave);
1171 if (node.name() != X_("Session")){
1172 fatal << _("programming error: Session: incorrect XML node sent to set_state()") << endmsg;
1176 if ((prop = node.property ("version")) != 0) {
1177 version = atoi (prop->value ()) * 1000;
1180 if ((prop = node.property ("name")) != 0) {
1181 _name = prop->value ();
1184 if ((prop = node.property (X_("sample-rate"))) != 0) {
1186 _nominal_frame_rate = atoi (prop->value());
1188 if (_nominal_frame_rate != _current_frame_rate) {
1189 boost::optional<int> r = AskAboutSampleRateMismatch (_nominal_frame_rate, _current_frame_rate);
1190 if (r.get_value_or (0)) {
1196 setup_raid_path(_session_dir->root_path().to_string());
1198 if ((prop = node.property (X_("id-counter"))) != 0) {
1200 sscanf (prop->value().c_str(), "%" PRIu64, &x);
1201 ID::init_counter (x);
1203 /* old sessions used a timebased counter, so fake
1204 the startup ID counter based on a standard
1209 ID::init_counter (now);
1213 IO::disable_connecting ();
1215 /* Object loading order:
1220 MIDI Control // relies on data from Options/Config
1233 if ((child = find_named_node (node, "Extra")) != 0) {
1234 _extra_xml = new XMLNode (*child);
1237 if (((child = find_named_node (node, "Options")) != 0)) { /* old style */
1238 load_options (*child);
1239 } else if ((child = find_named_node (node, "Config")) != 0) { /* new style */
1240 load_options (*child);
1242 error << _("Session: XML state has no options section") << endmsg;
1245 setup_midi_machine_control ();
1247 if (use_config_midi_ports ()) {
1250 if (version >= 3000) {
1251 if ((child = find_named_node (node, "Metadata")) == 0) {
1252 warning << _("Session: XML state has no metadata section") << endmsg;
1253 } else if (_metadata->set_state (*child, version)) {
1258 if ((child = find_named_node (node, "Locations")) == 0) {
1259 error << _("Session: XML state has no locations section") << endmsg;
1261 } else if (_locations.set_state (*child, version)) {
1267 if ((location = _locations.auto_loop_location()) != 0) {
1268 set_auto_loop_location (location);
1271 if ((location = _locations.auto_punch_location()) != 0) {
1272 set_auto_punch_location (location);
1275 if ((location = _locations.session_range_location()) != 0) {
1276 delete _session_range_location;
1277 _session_range_location = location;
1280 if (_session_range_location) {
1281 AudioFileSource::set_header_position_offset (_session_range_location->start());
1284 if ((child = find_named_node (node, "Sources")) == 0) {
1285 error << _("Session: XML state has no sources section") << endmsg;
1287 } else if (load_sources (*child)) {
1291 if ((child = find_named_node (node, "Regions")) == 0) {
1292 error << _("Session: XML state has no Regions section") << endmsg;
1294 } else if (load_regions (*child)) {
1298 if ((child = find_named_node (node, "Playlists")) == 0) {
1299 error << _("Session: XML state has no playlists section") << endmsg;
1301 } else if (playlists->load (*this, *child)) {
1305 if ((child = find_named_node (node, "UnusedPlaylists")) == 0) {
1307 } else if (playlists->load_unused (*this, *child)) {
1311 if ((child = find_named_node (node, "NamedSelections")) != 0) {
1312 if (load_named_selections (*child)) {
1317 if (version >= 3000) {
1318 if ((child = find_named_node (node, "Bundles")) == 0) {
1319 warning << _("Session: XML state has no bundles section") << endmsg;
1322 /* We can't load Bundles yet as they need to be able
1323 to convert from port names to Port objects, which can't happen until
1325 _bundle_xml_node = new XMLNode (*child);
1329 if ((child = find_named_node (node, "TempoMap")) == 0) {
1330 error << _("Session: XML state has no Tempo Map section") << endmsg;
1332 } else if (_tempo_map->set_state (*child, version)) {
1336 if (version < 3000) {
1337 if ((child = find_named_node (node, X_("DiskStreams"))) == 0) {
1338 error << _("Session: XML state has no diskstreams section") << endmsg;
1340 } else if (load_diskstreams_2X (*child, version)) {
1345 if ((child = find_named_node (node, "Routes")) == 0) {
1346 error << _("Session: XML state has no routes section") << endmsg;
1348 } else if (load_routes (*child, version)) {
1352 /* our diskstreams list is no longer needed as they are now all owned by their Route */
1353 _diskstreams_2X.clear ();
1355 if (version >= 3000) {
1357 if ((child = find_named_node (node, "RouteGroups")) == 0) {
1358 error << _("Session: XML state has no route groups section") << endmsg;
1360 } else if (load_route_groups (*child, version)) {
1364 } else if (version < 3000) {
1366 if ((child = find_named_node (node, "EditGroups")) == 0) {
1367 error << _("Session: XML state has no edit groups section") << endmsg;
1369 } else if (load_route_groups (*child, version)) {
1373 if ((child = find_named_node (node, "MixGroups")) == 0) {
1374 error << _("Session: XML state has no mix groups section") << endmsg;
1376 } else if (load_route_groups (*child, version)) {
1381 if ((child = find_named_node (node, "Click")) == 0) {
1382 warning << _("Session: XML state has no click section") << endmsg;
1383 } else if (_click_io) {
1384 _click_io->set_state (*child, version);
1387 if ((child = find_named_node (node, "ControlProtocols")) != 0) {
1388 ControlProtocolManager::instance().set_protocol_states (*child);
1391 /* here beginneth the second phase ... */
1393 StateReady (); /* EMIT SIGNAL */
1402 Session::load_routes (const XMLNode& node, int version)
1405 XMLNodeConstIterator niter;
1406 RouteList new_routes;
1408 nlist = node.children();
1412 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1414 boost::shared_ptr<Route> route;
1415 if (version < 3000) {
1416 route = XMLRouteFactory_2X (**niter, version);
1418 route = XMLRouteFactory (**niter, version);
1422 error << _("Session: cannot create Route from XML description.") << endmsg;
1426 BootMessage (string_compose (_("Loaded track/bus %1"), route->name()));
1428 new_routes.push_back (route);
1431 add_routes (new_routes, false);
1436 boost::shared_ptr<Route>
1437 Session::XMLRouteFactory (const XMLNode& node, int version)
1439 boost::shared_ptr<Route> ret;
1441 if (node.name() != "Route") {
1445 XMLNode* ds_child = find_named_node (node, X_("Diskstream"));
1447 DataType type = DataType::AUDIO;
1448 const XMLProperty* prop = node.property("default-type");
1451 type = DataType (prop->value());
1454 assert (type != DataType::NIL);
1460 if (type == DataType::AUDIO) {
1461 track = new AudioTrack (*this, X_("toBeResetFroXML"));
1464 track = new MidiTrack (*this, X_("toBeResetFroXML"));
1467 if (track->init()) {
1472 if (track->set_state (node, version)) {
1477 boost_debug_shared_ptr_mark_interesting (track, "Track");
1481 Route* rt = new Route (*this, X_("toBeResetFroXML"));
1483 if (rt->init () == 0 && rt->set_state (node, version) == 0) {
1484 boost_debug_shared_ptr_mark_interesting (rt, "Route");
1494 boost::shared_ptr<Route>
1495 Session::XMLRouteFactory_2X (const XMLNode& node, int version)
1497 boost::shared_ptr<Route> ret;
1499 if (node.name() != "Route") {
1503 XMLProperty const * ds_prop = node.property (X_("diskstream-id"));
1505 ds_prop = node.property (X_("diskstream"));
1508 DataType type = DataType::AUDIO;
1509 const XMLProperty* prop = node.property("default-type");
1512 type = DataType (prop->value());
1515 assert (type != DataType::NIL);
1519 list<boost::shared_ptr<Diskstream> >::iterator i = _diskstreams_2X.begin ();
1520 while (i != _diskstreams_2X.end() && (*i)->id() != ds_prop->value()) {
1524 if (i == _diskstreams_2X.end()) {
1525 error << _("Could not find diskstream for route") << endmsg;
1526 return boost::shared_ptr<Route> ();
1531 if (type == DataType::AUDIO) {
1532 track = new AudioTrack (*this, X_("toBeResetFroXML"));
1535 track = new MidiTrack (*this, X_("toBeResetFroXML"));
1538 if (track->init()) {
1543 if (track->set_state (node, version)) {
1548 track->set_diskstream (*i);
1550 boost_debug_shared_ptr_mark_interesting (track, "Track");
1554 Route* rt = new Route (*this, X_("toBeResetFroXML"));
1556 if (rt->init () == 0 && rt->set_state (node, version) == 0) {
1557 boost_debug_shared_ptr_mark_interesting (rt, "Route");
1568 Session::load_regions (const XMLNode& node)
1571 XMLNodeConstIterator niter;
1572 boost::shared_ptr<Region> region;
1574 nlist = node.children();
1578 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1579 if ((region = XMLRegionFactory (**niter, false)) == 0) {
1580 error << _("Session: cannot create Region from XML description.");
1581 const XMLProperty *name = (**niter).property("name");
1584 error << " " << string_compose (_("Can not load state for region '%1'"), name->value());
1594 boost::shared_ptr<Region>
1595 Session::XMLRegionFactory (const XMLNode& node, bool full)
1597 const XMLProperty* type = node.property("type");
1601 if ( !type || type->value() == "audio" ) {
1603 return boost::shared_ptr<Region>(XMLAudioRegionFactory (node, full));
1605 } else if (type->value() == "midi") {
1607 return boost::shared_ptr<Region>(XMLMidiRegionFactory (node, full));
1611 } catch (failed_constructor& err) {
1612 return boost::shared_ptr<Region> ();
1615 return boost::shared_ptr<Region> ();
1618 boost::shared_ptr<AudioRegion>
1619 Session::XMLAudioRegionFactory (const XMLNode& node, bool /*full*/)
1621 const XMLProperty* prop;
1622 boost::shared_ptr<Source> source;
1623 boost::shared_ptr<AudioSource> as;
1625 SourceList master_sources;
1626 uint32_t nchans = 1;
1629 if (node.name() != X_("Region")) {
1630 return boost::shared_ptr<AudioRegion>();
1633 if ((prop = node.property (X_("channels"))) != 0) {
1634 nchans = atoi (prop->value().c_str());
1637 if ((prop = node.property ("name")) == 0) {
1638 cerr << "no name for this region\n";
1642 if ((prop = node.property (X_("source-0"))) == 0) {
1643 if ((prop = node.property ("source")) == 0) {
1644 error << _("Session: XMLNode describing a AudioRegion is incomplete (no source)") << endmsg;
1645 return boost::shared_ptr<AudioRegion>();
1649 PBD::ID s_id (prop->value());
1651 if ((source = source_by_id (s_id)) == 0) {
1652 error << string_compose(_("Session: XMLNode describing a AudioRegion references an unknown source id =%1"), s_id) << endmsg;
1653 return boost::shared_ptr<AudioRegion>();
1656 as = boost::dynamic_pointer_cast<AudioSource>(source);
1658 error << string_compose(_("Session: XMLNode describing a AudioRegion references a non-audio source id =%1"), s_id) << endmsg;
1659 return boost::shared_ptr<AudioRegion>();
1662 sources.push_back (as);
1664 /* pickup other channels */
1666 for (uint32_t n=1; n < nchans; ++n) {
1667 snprintf (buf, sizeof(buf), X_("source-%d"), n);
1668 if ((prop = node.property (buf)) != 0) {
1670 PBD::ID id2 (prop->value());
1672 if ((source = source_by_id (id2)) == 0) {
1673 error << string_compose(_("Session: XMLNode describing a AudioRegion references an unknown source id =%1"), id2) << endmsg;
1674 return boost::shared_ptr<AudioRegion>();
1677 as = boost::dynamic_pointer_cast<AudioSource>(source);
1679 error << string_compose(_("Session: XMLNode describing a AudioRegion references a non-audio source id =%1"), id2) << endmsg;
1680 return boost::shared_ptr<AudioRegion>();
1682 sources.push_back (as);
1686 for (uint32_t n = 0; n < nchans; ++n) {
1687 snprintf (buf, sizeof(buf), X_("master-source-%d"), n);
1688 if ((prop = node.property (buf)) != 0) {
1690 PBD::ID id2 (prop->value());
1692 if ((source = source_by_id (id2)) == 0) {
1693 error << string_compose(_("Session: XMLNode describing a AudioRegion references an unknown source id =%1"), id2) << endmsg;
1694 return boost::shared_ptr<AudioRegion>();
1697 as = boost::dynamic_pointer_cast<AudioSource>(source);
1699 error << string_compose(_("Session: XMLNode describing a AudioRegion references a non-audio source id =%1"), id2) << endmsg;
1700 return boost::shared_ptr<AudioRegion>();
1702 master_sources.push_back (as);
1707 boost::shared_ptr<AudioRegion> region (boost::dynamic_pointer_cast<AudioRegion> (RegionFactory::create (sources, node)));
1709 /* a final detail: this is the one and only place that we know how long missing files are */
1711 if (region->whole_file()) {
1712 for (SourceList::iterator sx = sources.begin(); sx != sources.end(); ++sx) {
1713 boost::shared_ptr<SilentFileSource> sfp = boost::dynamic_pointer_cast<SilentFileSource> (*sx);
1715 sfp->set_length (region->length());
1720 if (!master_sources.empty()) {
1721 if (master_sources.size() != nchans) {
1722 error << _("Session: XMLNode describing an AudioRegion is missing some master sources; ignored") << endmsg;
1724 region->set_master_sources (master_sources);
1732 catch (failed_constructor& err) {
1733 return boost::shared_ptr<AudioRegion>();
1737 boost::shared_ptr<MidiRegion>
1738 Session::XMLMidiRegionFactory (const XMLNode& node, bool /*full*/)
1740 const XMLProperty* prop;
1741 boost::shared_ptr<Source> source;
1742 boost::shared_ptr<MidiSource> ms;
1744 uint32_t nchans = 1;
1746 if (node.name() != X_("Region")) {
1747 return boost::shared_ptr<MidiRegion>();
1750 if ((prop = node.property (X_("channels"))) != 0) {
1751 nchans = atoi (prop->value().c_str());
1754 if ((prop = node.property ("name")) == 0) {
1755 cerr << "no name for this region\n";
1759 // Multiple midi channels? that's just crazy talk
1760 assert(nchans == 1);
1762 if ((prop = node.property (X_("source-0"))) == 0) {
1763 if ((prop = node.property ("source")) == 0) {
1764 error << _("Session: XMLNode describing a MidiRegion is incomplete (no source)") << endmsg;
1765 return boost::shared_ptr<MidiRegion>();
1769 PBD::ID s_id (prop->value());
1771 if ((source = source_by_id (s_id)) == 0) {
1772 error << string_compose(_("Session: XMLNode describing a MidiRegion references an unknown source id =%1"), s_id) << endmsg;
1773 return boost::shared_ptr<MidiRegion>();
1776 ms = boost::dynamic_pointer_cast<MidiSource>(source);
1778 error << string_compose(_("Session: XMLNode describing a MidiRegion references a non-midi source id =%1"), s_id) << endmsg;
1779 return boost::shared_ptr<MidiRegion>();
1782 sources.push_back (ms);
1785 boost::shared_ptr<MidiRegion> region (boost::dynamic_pointer_cast<MidiRegion> (RegionFactory::create (sources, node)));
1786 /* a final detail: this is the one and only place that we know how long missing files are */
1788 if (region->whole_file()) {
1789 for (SourceList::iterator sx = sources.begin(); sx != sources.end(); ++sx) {
1790 boost::shared_ptr<SilentFileSource> sfp = boost::dynamic_pointer_cast<SilentFileSource> (*sx);
1792 sfp->set_length (region->length());
1800 catch (failed_constructor& err) {
1801 return boost::shared_ptr<MidiRegion>();
1806 Session::get_sources_as_xml ()
1809 XMLNode* node = new XMLNode (X_("Sources"));
1810 Glib::Mutex::Lock lm (source_lock);
1812 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ++i) {
1813 node->add_child_nocopy (i->second->get_state());
1820 Session::path_from_region_name (DataType type, string name, string identifier)
1822 char buf[PATH_MAX+1];
1824 SessionDirectory sdir(get_best_session_directory_for_new_source());
1825 sys::path source_dir = ((type == DataType::AUDIO)
1826 ? sdir.sound_path() : sdir.midi_path());
1828 string ext = ((type == DataType::AUDIO) ? ".wav" : ".mid");
1830 for (n = 0; n < 999999; ++n) {
1831 if (identifier.length()) {
1832 snprintf (buf, sizeof(buf), "%s%s%" PRIu32 "%s", name.c_str(),
1833 identifier.c_str(), n, ext.c_str());
1835 snprintf (buf, sizeof(buf), "%s-%" PRIu32 "%s", name.c_str(),
1839 sys::path source_path = source_dir / buf;
1841 if (!sys::exists (source_path)) {
1842 return source_path.to_string();
1846 error << string_compose (_("cannot create new file from region name \"%1\" with ident = \"%2\": too many existing files with similar names"),
1855 Session::load_sources (const XMLNode& node)
1858 XMLNodeConstIterator niter;
1859 boost::shared_ptr<Source> source;
1861 nlist = node.children();
1865 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1867 if ((source = XMLSourceFactory (**niter)) == 0) {
1868 error << _("Session: cannot create Source from XML description.") << endmsg;
1870 } catch (MissingSource& err) {
1871 warning << _("A sound file is missing. It will be replaced by silence.") << endmsg;
1872 source = SourceFactory::createSilent (*this, **niter, max_frames, _current_frame_rate);
1879 boost::shared_ptr<Source>
1880 Session::XMLSourceFactory (const XMLNode& node)
1882 if (node.name() != "Source") {
1883 return boost::shared_ptr<Source>();
1887 /* note: do peak building in another thread when loading session state */
1888 return SourceFactory::create (*this, node, true);
1891 catch (failed_constructor& err) {
1892 error << string_compose (_("Found a sound file that cannot be used by %1. Talk to the progammers."), PROGRAM_NAME) << endmsg;
1893 return boost::shared_ptr<Source>();
1898 Session::save_template (string template_name)
1902 if (_state_of_the_state & CannotSave) {
1906 sys::path user_template_dir(user_template_directory());
1910 sys::create_directories (user_template_dir);
1912 catch(sys::filesystem_error& ex)
1914 error << string_compose(_("Could not create mix templates directory \"%1\" (%2)"),
1915 user_template_dir.to_string(), ex.what()) << endmsg;
1919 tree.set_root (&get_template());
1921 sys::path template_file_path(user_template_dir);
1922 template_file_path /= template_name + template_suffix;
1924 if (sys::exists (template_file_path))
1926 warning << string_compose(_("Template \"%1\" already exists - new version not created"),
1927 template_file_path.to_string()) << endmsg;
1931 if (!tree.write (template_file_path.to_string())) {
1932 error << _("mix template not saved") << endmsg;
1940 Session::rename_template (string old_name, string new_name)
1942 sys::path old_path (user_template_directory());
1943 old_path /= old_name + template_suffix;
1945 sys::path new_path(user_template_directory());
1946 new_path /= new_name + template_suffix;
1948 if (sys::exists (new_path)) {
1949 warning << string_compose(_("Template \"%1\" already exists - template not renamed"),
1950 new_path.to_string()) << endmsg;
1955 sys::rename (old_path, new_path);
1963 Session::delete_template (string name)
1965 sys::path path = user_template_directory();
1966 path /= name + template_suffix;
1977 Session::refresh_disk_space ()
1980 struct statfs statfsbuf;
1981 vector<space_and_path>::iterator i;
1982 Glib::Mutex::Lock lm (space_lock);
1985 /* get freespace on every FS that is part of the session path */
1987 _total_free_4k_blocks = 0;
1989 for (i = session_dirs.begin(); i != session_dirs.end(); ++i) {
1990 statfs ((*i).path.c_str(), &statfsbuf);
1992 scale = statfsbuf.f_bsize/4096.0;
1994 (*i).blocks = (uint32_t) floor (statfsbuf.f_bavail * scale);
1995 _total_free_4k_blocks += (*i).blocks;
2001 Session::get_best_session_directory_for_new_source ()
2003 vector<space_and_path>::iterator i;
2004 string result = _session_dir->root_path().to_string();
2006 /* handle common case without system calls */
2008 if (session_dirs.size() == 1) {
2012 /* OK, here's the algorithm we're following here:
2014 We want to select which directory to use for
2015 the next file source to be created. Ideally,
2016 we'd like to use a round-robin process so as to
2017 get maximum performance benefits from splitting
2018 the files across multiple disks.
2020 However, in situations without much diskspace, an
2021 RR approach may end up filling up a filesystem
2022 with new files while others still have space.
2023 Its therefore important to pay some attention to
2024 the freespace in the filesystem holding each
2025 directory as well. However, if we did that by
2026 itself, we'd keep creating new files in the file
2027 system with the most space until it was as full
2028 as all others, thus negating any performance
2029 benefits of this RAID-1 like approach.
2031 So, we use a user-configurable space threshold. If
2032 there are at least 2 filesystems with more than this
2033 much space available, we use RR selection between them.
2034 If not, then we pick the filesystem with the most space.
2036 This gets a good balance between the two
2040 refresh_disk_space ();
2042 int free_enough = 0;
2044 for (i = session_dirs.begin(); i != session_dirs.end(); ++i) {
2045 if ((*i).blocks * 4096 >= Config->get_disk_choice_space_threshold()) {
2050 if (free_enough >= 2) {
2051 /* use RR selection process, ensuring that the one
2055 i = last_rr_session_dir;
2058 if (++i == session_dirs.end()) {
2059 i = session_dirs.begin();
2062 if ((*i).blocks * 4096 >= Config->get_disk_choice_space_threshold()) {
2063 if (create_session_directory ((*i).path)) {
2065 last_rr_session_dir = i;
2070 } while (i != last_rr_session_dir);
2074 /* pick FS with the most freespace (and that
2075 seems to actually work ...)
2078 vector<space_and_path> sorted;
2079 space_and_path_ascending_cmp cmp;
2081 sorted = session_dirs;
2082 sort (sorted.begin(), sorted.end(), cmp);
2084 for (i = sorted.begin(); i != sorted.end(); ++i) {
2085 if (create_session_directory ((*i).path)) {
2087 last_rr_session_dir = i;
2097 Session::load_named_selections (const XMLNode& node)
2100 XMLNodeConstIterator niter;
2103 nlist = node.children();
2107 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2109 if ((ns = XMLNamedSelectionFactory (**niter)) == 0) {
2110 error << _("Session: cannot create Named Selection from XML description.") << endmsg;
2118 Session::XMLNamedSelectionFactory (const XMLNode& node)
2121 return new NamedSelection (*this, node);
2124 catch (failed_constructor& err) {
2130 Session::automation_dir () const
2132 return Glib::build_filename (_path, "automation");
2136 Session::analysis_dir () const
2138 return Glib::build_filename (_path, "analysis");
2142 Session::load_bundles (XMLNode const & node)
2144 XMLNodeList nlist = node.children();
2145 XMLNodeConstIterator niter;
2149 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2150 if ((*niter)->name() == "InputBundle") {
2151 add_bundle (boost::shared_ptr<UserBundle> (new UserBundle (**niter, true)));
2152 } else if ((*niter)->name() == "OutputBundle") {
2153 add_bundle (boost::shared_ptr<UserBundle> (new UserBundle (**niter, false)));
2155 error << string_compose(_("Unknown node \"%1\" found in Bundles list from state file"), (*niter)->name()) << endmsg;
2164 Session::load_route_groups (const XMLNode& node, int version)
2166 XMLNodeList nlist = node.children();
2167 XMLNodeConstIterator niter;
2171 if (version >= 3000) {
2173 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2174 if ((*niter)->name() == "RouteGroup") {
2175 RouteGroup* rg = new RouteGroup (*this, "");
2176 add_route_group (rg);
2177 rg->set_state (**niter, version);
2181 } else if (version < 3000) {
2183 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2184 if ((*niter)->name() == "EditGroup" || (*niter)->name() == "MixGroup") {
2185 RouteGroup* rg = new RouteGroup (*this, "");
2186 add_route_group (rg);
2187 rg->set_state (**niter, version);
2196 Session::auto_save()
2198 save_state (_current_snapshot_name);
2202 state_file_filter (const string &str, void */*arg*/)
2204 return (str.length() > strlen(statefile_suffix) &&
2205 str.find (statefile_suffix) == (str.length() - strlen (statefile_suffix)));
2209 bool operator()(const string* a, const string* b) {
2215 remove_end(string* state)
2217 string statename(*state);
2219 string::size_type start,end;
2220 if ((start = statename.find_last_of ('/')) != string::npos) {
2221 statename = statename.substr (start+1);
2224 if ((end = statename.rfind(".ardour")) == string::npos) {
2225 end = statename.length();
2228 return new string(statename.substr (0, end));
2232 Session::possible_states (string path)
2234 PathScanner scanner;
2235 vector<string*>* states = scanner (path, state_file_filter, 0, false, false);
2237 transform(states->begin(), states->end(), states->begin(), remove_end);
2240 sort (states->begin(), states->end(), cmp);
2246 Session::possible_states () const
2248 return possible_states(_path);
2252 Session::add_route_group (RouteGroup* g)
2254 _route_groups.push_back (g);
2255 route_group_added (g); /* EMIT SIGNAL */
2260 Session::remove_route_group (RouteGroup& rg)
2262 list<RouteGroup*>::iterator i;
2264 if ((i = find (_route_groups.begin(), _route_groups.end(), &rg)) != _route_groups.end()) {
2265 _route_groups.erase (i);
2268 route_group_removed (); /* EMIT SIGNAL */
2274 Session::route_group_by_name (string name)
2276 list<RouteGroup *>::iterator i;
2278 for (i = _route_groups.begin(); i != _route_groups.end(); ++i) {
2279 if ((*i)->name() == name) {
2287 Session::start_reversible_command (const string& name)
2289 UndoTransaction* trans = new UndoTransaction();
2290 trans->set_name(name);
2295 Session::finish_reversible_command (UndoTransaction& ut)
2298 gettimeofday(&now, 0);
2299 ut.set_timestamp(now);
2304 Session::begin_reversible_command(const string& name)
2306 UndoTransaction* trans = new UndoTransaction();
2307 trans->set_name(name);
2309 if (!_current_trans.empty()) {
2310 _current_trans.top()->add_command (trans);
2312 _current_trans.push(trans);
2317 Session::commit_reversible_command(Command *cmd)
2319 assert(!_current_trans.empty());
2323 _current_trans.top()->add_command(cmd);
2326 if (_current_trans.top()->empty()) {
2327 _current_trans.pop();
2331 gettimeofday(&now, 0);
2332 _current_trans.top()->set_timestamp(now);
2334 _history.add(_current_trans.top());
2335 _current_trans.pop();
2339 accept_all_non_peak_files (const string& path, void */*arg*/)
2341 return (path.length() > 5 && path.find (peakfile_suffix) != (path.length() - 5));
2345 accept_all_state_files (const string& path, void */*arg*/)
2347 return (path.length() > 7 && path.find (".ardour") == (path.length() - 7));
2351 Session::find_all_sources (string path, set<string>& result)
2356 if (!tree.read (path)) {
2360 if ((node = find_named_node (*tree.root(), "Sources")) == 0) {
2365 XMLNodeConstIterator niter;
2367 nlist = node->children();
2371 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2375 if ((prop = (*niter)->property (X_("type"))) == 0) {
2379 DataType type (prop->value());
2381 if ((prop = (*niter)->property (X_("name"))) == 0) {
2385 if (prop->value()[0] == '/') {
2386 /* external file, ignore */
2390 Glib::ustring found_path;
2394 if (FileSource::find (type, prop->value(), true, is_new, chan, found_path)) {
2395 result.insert (found_path);
2403 Session::find_all_sources_across_snapshots (set<string>& result, bool exclude_this_snapshot)
2405 PathScanner scanner;
2406 vector<string*>* state_files;
2408 string this_snapshot_path;
2414 if (ripped[ripped.length()-1] == '/') {
2415 ripped = ripped.substr (0, ripped.length() - 1);
2418 state_files = scanner (ripped, accept_all_state_files, (void *) 0, false, true);
2420 if (state_files == 0) {
2425 this_snapshot_path = _path;
2426 this_snapshot_path += legalize_for_path (_current_snapshot_name);
2427 this_snapshot_path += statefile_suffix;
2429 for (vector<string*>::iterator i = state_files->begin(); i != state_files->end(); ++i) {
2431 if (exclude_this_snapshot && **i == this_snapshot_path) {
2435 if (find_all_sources (**i, result) < 0) {
2443 struct RegionCounter {
2444 typedef std::map<PBD::ID,boost::shared_ptr<AudioSource> > AudioSourceList;
2445 AudioSourceList::iterator iter;
2446 boost::shared_ptr<Region> region;
2449 RegionCounter() : count (0) {}
2453 Session::ask_about_playlist_deletion (boost::shared_ptr<Playlist> p)
2455 boost::optional<int> r = AskAboutPlaylistDeletion (p);
2456 return r.get_value_or (1);
2460 Session::cleanup_sources (CleanupReport& rep)
2462 // FIXME: needs adaptation to midi
2464 vector<boost::shared_ptr<Source> > dead_sources;
2465 PathScanner scanner;
2467 vector<space_and_path>::iterator i;
2468 vector<space_and_path>::iterator nexti;
2469 vector<string*>* soundfiles;
2470 vector<string> unused;
2471 set<string> all_sources;
2476 _state_of_the_state = (StateOfTheState) (_state_of_the_state | InCleanup);
2478 /* step 1: consider deleting all unused playlists */
2480 if (playlists->maybe_delete_unused (boost::bind (Session::ask_about_playlist_deletion, _1))) {
2485 /* step 2: find all un-used sources */
2490 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ) {
2492 SourceMap::iterator tmp;
2497 /* do not bother with files that are zero size, otherwise we remove the current "nascent"
2501 if (!i->second->used() && (i->second->length(i->second->timeline_position() > 0))) {
2502 dead_sources.push_back (i->second);
2503 i->second->drop_references ();
2509 /* build a list of all the possible sound directories for the session */
2511 for (i = session_dirs.begin(); i != session_dirs.end(); ) {
2516 SessionDirectory sdir ((*i).path);
2517 sound_path += sdir.sound_path().to_string();
2519 if (nexti != session_dirs.end()) {
2526 /* now do the same thing for the files that ended up in the sounds dir(s)
2527 but are not referenced as sources in any snapshot.
2530 soundfiles = scanner (sound_path, accept_all_non_peak_files, (void *) 0, false, true);
2532 if (soundfiles == 0) {
2536 /* find all sources, but don't use this snapshot because the
2537 state file on disk still references sources we may have already
2541 find_all_sources_across_snapshots (all_sources, true);
2543 /* add our current source list
2546 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ++i) {
2547 boost::shared_ptr<FileSource> fs;
2549 if ((fs = boost::dynamic_pointer_cast<FileSource> (i->second)) != 0) {
2550 all_sources.insert (fs->path());
2554 char tmppath1[PATH_MAX+1];
2555 char tmppath2[PATH_MAX+1];
2557 for (vector<string*>::iterator x = soundfiles->begin(); x != soundfiles->end(); ++x) {
2562 for (set<string>::iterator i = all_sources.begin(); i != all_sources.end(); ++i) {
2564 if (realpath(spath.c_str(), tmppath1) == 0) {
2565 error << string_compose (_("Cannot expand path %1 (%2)"),
2566 spath, strerror (errno)) << endmsg;
2570 if (realpath((*i).c_str(), tmppath2) == 0) {
2571 error << string_compose (_("Cannot expand path %1 (%2)"),
2572 (*i), strerror (errno)) << endmsg;
2576 if (strcmp(tmppath1, tmppath2) == 0) {
2583 unused.push_back (spath);
2587 /* now try to move all unused files into the "dead_sounds" directory(ies) */
2589 for (vector<string>::iterator x = unused.begin(); x != unused.end(); ++x) {
2590 struct stat statbuf;
2592 rep.paths.push_back (*x);
2593 if (stat ((*x).c_str(), &statbuf) == 0) {
2594 rep.space += statbuf.st_size;
2599 /* don't move the file across filesystems, just
2600 stick it in the `dead_sound_dir_name' directory
2601 on whichever filesystem it was already on.
2604 if ((*x).find ("/sounds/") != string::npos) {
2606 /* old school, go up 1 level */
2608 newpath = Glib::path_get_dirname (*x); // "sounds"
2609 newpath = Glib::path_get_dirname (newpath); // "session-name"
2613 /* new school, go up 4 levels */
2615 newpath = Glib::path_get_dirname (*x); // "audiofiles"
2616 newpath = Glib::path_get_dirname (newpath); // "session-name"
2617 newpath = Glib::path_get_dirname (newpath); // "interchange"
2618 newpath = Glib::path_get_dirname (newpath); // "session-dir"
2622 newpath += dead_sound_dir_name;
2624 if (g_mkdir_with_parents (newpath.c_str(), 0755) < 0) {
2625 error << string_compose(_("Session: cannot create session peakfile folder \"%1\" (%2)"), newpath, strerror (errno)) << endmsg;
2630 newpath += Glib::path_get_basename ((*x));
2632 if (access (newpath.c_str(), F_OK) == 0) {
2634 /* the new path already exists, try versioning */
2636 char buf[PATH_MAX+1];
2640 snprintf (buf, sizeof (buf), "%s.%d", newpath.c_str(), version);
2643 while (access (newpath_v.c_str(), F_OK) == 0 && version < 999) {
2644 snprintf (buf, sizeof (buf), "%s.%d", newpath.c_str(), ++version);
2648 if (version == 999) {
2649 error << string_compose (_("there are already 1000 files with names like %1; versioning discontinued"),
2653 newpath = newpath_v;
2658 /* it doesn't exist, or we can't read it or something */
2662 if (::rename ((*x).c_str(), newpath.c_str()) != 0) {
2663 error << string_compose (_("cannot rename audio file source from %1 to %2 (%3)"),
2664 (*x), newpath, strerror (errno))
2669 /* see if there an easy to find peakfile for this file, and remove it.
2672 string peakpath = (*x).substr (0, (*x).find_last_of ('.'));
2673 peakpath += peakfile_suffix;
2675 if (access (peakpath.c_str(), W_OK) == 0) {
2676 if (::unlink (peakpath.c_str()) != 0) {
2677 error << string_compose (_("cannot remove peakfile %1 for %2 (%3)"),
2678 peakpath, _path, strerror (errno))
2680 /* try to back out */
2681 rename (newpath.c_str(), _path.c_str());
2689 /* dump the history list */
2693 /* save state so we don't end up a session file
2694 referring to non-existent sources.
2700 _state_of_the_state = (StateOfTheState) (_state_of_the_state & ~InCleanup);
2706 Session::cleanup_trash_sources (CleanupReport& rep)
2708 // FIXME: needs adaptation for MIDI
2710 vector<space_and_path>::iterator i;
2711 string dead_sound_dir;
2712 struct dirent* dentry;
2713 struct stat statbuf;
2719 for (i = session_dirs.begin(); i != session_dirs.end(); ++i) {
2721 dead_sound_dir = (*i).path;
2722 dead_sound_dir += dead_sound_dir_name;
2724 if ((dead = opendir (dead_sound_dir.c_str())) == 0) {
2728 while ((dentry = readdir (dead)) != 0) {
2730 /* avoid '.' and '..' */
2732 if ((dentry->d_name[0] == '.' && dentry->d_name[1] == '\0') ||
2733 (dentry->d_name[2] == '\0' && dentry->d_name[0] == '.' && dentry->d_name[1] == '.')) {
2739 fullpath = dead_sound_dir;
2741 fullpath += dentry->d_name;
2743 if (stat (fullpath.c_str(), &statbuf)) {
2747 if (!S_ISREG (statbuf.st_mode)) {
2751 if (unlink (fullpath.c_str())) {
2752 error << string_compose (_("cannot remove dead sound file %1 (%2)"),
2753 fullpath, strerror (errno))
2757 rep.paths.push_back (dentry->d_name);
2758 rep.space += statbuf.st_size;
2769 Session::set_dirty ()
2771 bool was_dirty = dirty();
2773 _state_of_the_state = StateOfTheState (_state_of_the_state | Dirty);
2777 DirtyChanged(); /* EMIT SIGNAL */
2783 Session::set_clean ()
2785 bool was_dirty = dirty();
2787 _state_of_the_state = Clean;
2791 DirtyChanged(); /* EMIT SIGNAL */
2796 Session::set_deletion_in_progress ()
2798 _state_of_the_state = StateOfTheState (_state_of_the_state | Deletion);
2802 Session::clear_deletion_in_progress ()
2804 _state_of_the_state = StateOfTheState (_state_of_the_state & (~Deletion));
2808 Session::add_controllable (boost::shared_ptr<Controllable> c)
2810 /* this adds a controllable to the list managed by the Session.
2811 this is a subset of those managed by the Controllable class
2812 itself, and represents the only ones whose state will be saved
2813 as part of the session.
2816 Glib::Mutex::Lock lm (controllables_lock);
2817 controllables.insert (c);
2820 struct null_deleter { void operator()(void const *) const {} };
2823 Session::remove_controllable (Controllable* c)
2825 if (_state_of_the_state | Deletion) {
2829 Glib::Mutex::Lock lm (controllables_lock);
2831 Controllables::iterator x = controllables.find (boost::shared_ptr<Controllable>(c, null_deleter()));
2833 if (x != controllables.end()) {
2834 controllables.erase (x);
2838 boost::shared_ptr<Controllable>
2839 Session::controllable_by_id (const PBD::ID& id)
2841 Glib::Mutex::Lock lm (controllables_lock);
2843 for (Controllables::iterator i = controllables.begin(); i != controllables.end(); ++i) {
2844 if ((*i)->id() == id) {
2849 return boost::shared_ptr<Controllable>();
2852 boost::shared_ptr<Controllable>
2853 Session::controllable_by_descriptor (const ControllableDescriptor& desc)
2855 boost::shared_ptr<Controllable> c;
2856 boost::shared_ptr<Route> r;
2858 switch (desc.top_level_type()) {
2859 case ControllableDescriptor::NamedRoute:
2861 std::string str = desc.top_level_name();
2862 if (str == "master") {
2864 } else if (str == "control" || str == "listen") {
2867 r = route_by_name (desc.top_level_name());
2872 case ControllableDescriptor::RemoteControlID:
2873 r = route_by_remote_id (desc.rid());
2881 switch (desc.subtype()) {
2882 case ControllableDescriptor::Gain:
2883 c = r->gain_control ();
2886 case ControllableDescriptor::Solo:
2887 c = r->solo_control();
2890 case ControllableDescriptor::Mute:
2891 c = r->mute_control();
2894 case ControllableDescriptor::Recenable:
2896 boost::shared_ptr<Track> t = boost::dynamic_pointer_cast<Track>(r);
2899 c = t->rec_enable_control ();
2904 case ControllableDescriptor::Pan:
2905 /* XXX pan control */
2908 case ControllableDescriptor::Balance:
2909 /* XXX simple pan control */
2912 case ControllableDescriptor::PluginParameter:
2914 uint32_t plugin = desc.target (0);
2915 uint32_t parameter_index = desc.target (1);
2917 /* revert to zero based counting */
2923 if (parameter_index > 0) {
2927 boost::shared_ptr<Processor> p = r->nth_plugin (plugin);
2930 c = boost::dynamic_pointer_cast<ARDOUR::AutomationControl>(
2931 p->control(Evoral::Parameter(PluginAutomation, 0, parameter_index)));
2936 case ControllableDescriptor::SendGain:
2938 uint32_t send = desc.target (0);
2940 /* revert to zero-based counting */
2946 boost::shared_ptr<Processor> p = r->nth_send (send);
2949 boost::shared_ptr<Send> s = boost::dynamic_pointer_cast<Send>(p);
2950 boost::shared_ptr<Amp> a = s->amp();
2953 c = s->amp()->gain_control();
2960 /* relax and return a null pointer */
2968 Session::add_instant_xml (XMLNode& node, bool write_to_config)
2971 Stateful::add_instant_xml (node, _path);
2974 if (write_to_config) {
2975 Config->add_instant_xml (node);
2980 Session::instant_xml (const string& node_name)
2982 return Stateful::instant_xml (node_name, _path);
2986 Session::save_history (string snapshot_name)
2994 if (snapshot_name.empty()) {
2995 snapshot_name = _current_snapshot_name;
2998 const string history_filename = legalize_for_path (snapshot_name) + history_suffix;
2999 const string backup_filename = history_filename + backup_suffix;
3000 const sys::path xml_path = _session_dir->root_path() / history_filename;
3001 const sys::path backup_path = _session_dir->root_path() / backup_filename;
3003 if (sys::exists (xml_path)) {
3006 sys::rename (xml_path, backup_path);
3008 catch (const sys::filesystem_error& err)
3010 error << _("could not backup old history file, current history not saved") << endmsg;
3015 if (!Config->get_save_history() || Config->get_saved_history_depth() < 0) {
3019 tree.set_root (&_history.get_state (Config->get_saved_history_depth()));
3021 if (!tree.write (xml_path.to_string()))
3023 error << string_compose (_("history could not be saved to %1"), xml_path.to_string()) << endmsg;
3027 sys::remove (xml_path);
3028 sys::rename (backup_path, xml_path);
3030 catch (const sys::filesystem_error& err)
3032 error << string_compose (_("could not restore history file from backup %1 (%2)"),
3033 backup_path.to_string(), err.what()) << endmsg;
3043 Session::restore_history (string snapshot_name)
3047 if (snapshot_name.empty()) {
3048 snapshot_name = _current_snapshot_name;
3051 const string xml_filename = legalize_for_path (snapshot_name) + history_suffix;
3052 const sys::path xml_path = _session_dir->root_path() / xml_filename;
3054 info << "Loading history from " << xml_path.to_string() << endmsg;
3056 if (!sys::exists (xml_path)) {
3057 info << string_compose (_("%1: no history file \"%2\" for this session."),
3058 _name, xml_path.to_string()) << endmsg;
3062 if (!tree.read (xml_path.to_string())) {
3063 error << string_compose (_("Could not understand session history file \"%1\""),
3064 xml_path.to_string()) << endmsg;
3071 for (XMLNodeConstIterator it = tree.root()->children().begin(); it != tree.root()->children().end(); it++) {
3074 UndoTransaction* ut = new UndoTransaction ();
3077 ut->set_name(t->property("name")->value());
3078 stringstream ss(t->property("tv-sec")->value());
3080 ss.str(t->property("tv-usec")->value());
3082 ut->set_timestamp(tv);
3084 for (XMLNodeConstIterator child_it = t->children().begin();
3085 child_it != t->children().end(); child_it++)
3087 XMLNode *n = *child_it;
3090 if (n->name() == "MementoCommand" ||
3091 n->name() == "MementoUndoCommand" ||
3092 n->name() == "MementoRedoCommand") {
3094 if ((c = memento_command_factory(n))) {
3098 } else if (n->name() == "DiffCommand") {
3099 PBD::ID id(n->property("midi-source")->value());
3100 boost::shared_ptr<MidiSource> midi_source =
3101 boost::dynamic_pointer_cast<MidiSource, Source>(source_by_id(id));
3103 ut->add_command(new MidiModel::DiffCommand(midi_source->model(), *n));
3105 error << _("Failed to downcast MidiSource for DiffCommand") << endmsg;
3108 } else if (n->name() == "StatefulDiffCommand") {
3109 if ((c = stateful_diff_command_factory (n))) {
3110 ut->add_command (c);
3113 error << string_compose(_("Couldn't figure out how to make a Command out of a %1 XMLNode."), n->name()) << endmsg;
3124 Session::config_changed (std::string p, bool ours)
3130 if (p == "seamless-loop") {
3132 } else if (p == "rf-speed") {
3134 } else if (p == "auto-loop") {
3136 } else if (p == "auto-input") {
3138 if (Config->get_monitoring_model() == HardwareMonitoring && transport_rolling()) {
3139 /* auto-input only makes a difference if we're rolling */
3141 boost::shared_ptr<RouteList> rl = routes.reader ();
3142 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
3143 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
3144 if (tr && tr->record_enabled ()) {
3145 tr->monitor_input (!config.get_auto_input());
3150 } else if (p == "punch-in") {
3154 if ((location = _locations.auto_punch_location()) != 0) {
3156 if (config.get_punch_in ()) {
3157 replace_event (SessionEvent::PunchIn, location->start());
3159 remove_event (location->start(), SessionEvent::PunchIn);
3163 } else if (p == "punch-out") {
3167 if ((location = _locations.auto_punch_location()) != 0) {
3169 if (config.get_punch_out()) {
3170 replace_event (SessionEvent::PunchOut, location->end());
3172 clear_events (SessionEvent::PunchOut);
3176 } else if (p == "edit-mode") {
3178 Glib::Mutex::Lock lm (playlists->lock);
3180 for (SessionPlaylists::List::iterator i = playlists->playlists.begin(); i != playlists->playlists.end(); ++i) {
3181 (*i)->set_edit_mode (Config->get_edit_mode ());
3184 } else if (p == "use-video-sync") {
3186 waiting_for_sync_offset = config.get_use_video_sync();
3188 } else if (p == "mmc-control") {
3190 //poke_midi_thread ();
3192 } else if (p == "mmc-device-id" || p == "mmc-receive-id") {
3194 _mmc->set_receive_device_id (Config->get_mmc_receive_device_id());
3196 } else if (p == "mmc-send-id") {
3198 _mmc->set_send_device_id (Config->get_mmc_send_device_id());
3200 } else if (p == "midi-control") {
3202 //poke_midi_thread ();
3204 } else if (p == "raid-path") {
3206 setup_raid_path (config.get_raid_path());
3208 } else if (p == "timecode-format") {
3212 } else if (p == "video-pullup") {
3216 } else if (p == "seamless-loop") {
3218 if (play_loop && transport_rolling()) {
3219 // to reset diskstreams etc
3220 request_play_loop (true);
3223 } else if (p == "rf-speed") {
3225 cumulative_rf_motion = 0;
3228 } else if (p == "click-sound") {
3230 setup_click_sounds (1);
3232 } else if (p == "click-emphasis-sound") {
3234 setup_click_sounds (-1);
3236 } else if (p == "clicking") {
3238 if (Config->get_clicking()) {
3239 if (_click_io && click_data) { // don't require emphasis data
3246 } else if (p == "send-mtc") {
3248 /* only set the internal flag if we have
3252 if (_mtc_port != 0) {
3253 session_send_mtc = Config->get_send_mtc();
3254 if (session_send_mtc) {
3255 /* mark us ready to send */
3256 next_quarter_frame_to_send = 0;
3259 session_send_mtc = false;
3262 } else if (p == "send-mmc") {
3264 _mmc->enable_send (Config->get_send_mmc ());
3266 } else if (p == "midi-feedback") {
3268 /* only set the internal flag if we have
3272 if (_mtc_port != 0) {
3273 session_midi_feedback = Config->get_midi_feedback();
3276 } else if (p == "jack-time-master") {
3278 engine().reset_timebase ();
3280 } else if (p == "native-file-header-format") {
3282 if (!first_file_header_format_reset) {
3283 reset_native_file_format ();
3286 first_file_header_format_reset = false;
3288 } else if (p == "native-file-data-format") {
3290 if (!first_file_data_format_reset) {
3291 reset_native_file_format ();
3294 first_file_data_format_reset = false;
3296 } else if (p == "external-sync") {
3297 if (!config.get_external_sync()) {
3298 drop_sync_source ();
3300 switch_to_sync_source (config.get_sync_source());
3302 } else if (p == "remote-model") {
3303 set_remote_control_ids ();
3304 } else if (p == "denormal-model") {
3306 } else if (p == "history-depth") {
3307 set_history_depth (Config->get_history_depth());
3308 } else if (p == "sync-all-route-ordering") {
3309 sync_order_keys ("session");
3310 } else if (p == "initial-program-change") {
3312 if (_mmc->port() && Config->get_initial_program_change() >= 0) {
3315 buf[0] = MIDI::program; // channel zero by default
3316 buf[1] = (Config->get_initial_program_change() & 0x7f);
3318 _mmc->port()->midimsg (buf, sizeof (buf), 0);
3320 } else if (p == "initial-program-change") {
3322 if (_mmc->port() && Config->get_initial_program_change() >= 0) {
3323 MIDI::byte* buf = new MIDI::byte[2];
3325 buf[0] = MIDI::program; // channel zero by default
3326 buf[1] = (Config->get_initial_program_change() & 0x7f);
3327 // deliver_midi (_mmc_port, buf, 2);
3329 } else if (p == "solo-mute-override") {
3330 // catch_up_on_solo_mute_override ();
3331 } else if (p == "listen-position") {
3332 listen_position_changed ();
3333 } else if (p == "solo-control-is-listen-control") {
3334 solo_control_mode_changed ();
3342 Session::set_history_depth (uint32_t d)
3344 _history.set_depth (d);
3348 Session::load_diskstreams_2X (XMLNode const & node, int)
3351 XMLNodeConstIterator citer;
3353 clist = node.children();
3355 for (citer = clist.begin(); citer != clist.end(); ++citer) {
3358 /* diskstreams added automatically by DiskstreamCreated handler */
3359 if ((*citer)->name() == "AudioDiskstream" || (*citer)->name() == "DiskStream") {
3360 boost::shared_ptr<AudioDiskstream> dsp (new AudioDiskstream (*this, **citer));
3361 _diskstreams_2X.push_back (dsp);
3363 error << _("Session: unknown diskstream type in XML") << endmsg;
3367 catch (failed_constructor& err) {
3368 error << _("Session: could not load diskstream via XML state") << endmsg;
3376 /** Create our MachineControl object and connect things to it */
3378 Session::setup_midi_machine_control ()
3380 _mmc = new MIDI::MachineControl;
3381 _mmc->set_port (default_mmc_port);
3383 _mmc->Play.connect_same_thread (*this, boost::bind (&Session::mmc_deferred_play, this, _1));
3384 _mmc->DeferredPlay.connect_same_thread (*this, boost::bind (&Session::mmc_deferred_play, this, _1));
3385 _mmc->Stop.connect_same_thread (*this, boost::bind (&Session::mmc_stop, this, _1));
3386 _mmc->FastForward.connect_same_thread (*this, boost::bind (&Session::mmc_fast_forward, this, _1));
3387 _mmc->Rewind.connect_same_thread (*this, boost::bind (&Session::mmc_rewind, this, _1));
3388 _mmc->Pause.connect_same_thread (*this, boost::bind (&Session::mmc_pause, this, _1));
3389 _mmc->RecordPause.connect_same_thread (*this, boost::bind (&Session::mmc_record_pause, this, _1));
3390 _mmc->RecordStrobe.connect_same_thread (*this, boost::bind (&Session::mmc_record_strobe, this, _1));
3391 _mmc->RecordExit.connect_same_thread (*this, boost::bind (&Session::mmc_record_exit, this, _1));
3392 _mmc->Locate.connect_same_thread (*this, boost::bind (&Session::mmc_locate, this, _1, _2));
3393 _mmc->Step.connect_same_thread (*this, boost::bind (&Session::mmc_step, this, _1, _2));
3394 _mmc->Shuttle.connect_same_thread (*this, boost::bind (&Session::mmc_shuttle, this, _1, _2, _3));
3395 _mmc->TrackRecordStatusChange.connect_same_thread (*this, boost::bind (&Session::mmc_record_enable, this, _1, _2, _3));
3397 /* also handle MIDI SPP because its so common */
3399 _mmc->port()->input()->start.connect_same_thread (*this, boost::bind (&Session::spp_start, this, _1, _2));
3400 _mmc->port()->input()->contineu.connect_same_thread (*this, boost::bind (&Session::spp_continue, this, _1, _2));
3401 _mmc->port()->input()->stop.connect_same_thread (*this, boost::bind (&Session::spp_stop, this, _1, _2));