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);
356 _mmc->send (MIDI::MachineControlCommand (MIDI::MachineControl::cmdMmcReset));
357 _mmc->send (MIDI::MachineControlCommand (Timecode::Time ()));
359 MidiClockTicker::instance().set_session (this);
360 MIDI::Name::MidiPatchManager::instance().set_session (this);
362 /* initial program change will be delivered later; see ::config_changed() */
364 BootMessage (_("Reset Control Protocols"));
366 ControlProtocolManager::instance().set_session (this);
368 _state_of_the_state = Clean;
370 Port::set_connecting_blocked (false);
372 DirtyChanged (); /* EMIT SIGNAL */
374 if (state_was_pending) {
375 save_state (_current_snapshot_name);
376 remove_pending_capture_state ();
377 state_was_pending = false;
380 BootMessage (_("Session loading complete"));
386 Session::raid_path () const
388 SearchPath raid_search_path;
390 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
391 raid_search_path += sys::path((*i).path);
394 return raid_search_path.to_string ();
398 Session::setup_raid_path (string path)
407 session_dirs.clear ();
409 SearchPath search_path(path);
410 SearchPath sound_search_path;
411 SearchPath midi_search_path;
413 for (SearchPath::const_iterator i = search_path.begin(); i != search_path.end(); ++i) {
414 sp.path = (*i).to_string ();
415 sp.blocks = 0; // not needed
416 session_dirs.push_back (sp);
418 SessionDirectory sdir(sp.path);
420 sound_search_path += sdir.sound_path ();
421 midi_search_path += sdir.midi_path ();
424 // set the search path for each data type
425 FileSource::set_search_path (DataType::AUDIO, sound_search_path.to_string ());
426 SMFSource::set_search_path (DataType::MIDI, midi_search_path.to_string ());
428 // reset the round-robin soundfile path thingie
429 last_rr_session_dir = session_dirs.begin();
433 Session::path_is_within_session (const std::string& path)
435 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
436 if (path.find ((*i).path) == 0) {
444 Session::ensure_subdirs ()
448 dir = session_directory().peak_path().to_string();
450 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
451 error << string_compose(_("Session: cannot create session peakfile folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
455 dir = session_directory().sound_path().to_string();
457 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
458 error << string_compose(_("Session: cannot create session sounds dir \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
462 dir = session_directory().midi_path().to_string();
464 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
465 error << string_compose(_("Session: cannot create session midi dir \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
469 dir = session_directory().dead_sound_path().to_string();
471 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
472 error << string_compose(_("Session: cannot create session dead sounds folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
476 dir = session_directory().export_path().to_string();
478 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
479 error << string_compose(_("Session: cannot create session export folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
483 dir = analysis_dir ();
485 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
486 error << string_compose(_("Session: cannot create session analysis folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
494 Session::create (const string& mix_template, BusProfile* bus_profile)
497 if (g_mkdir_with_parents (_path.c_str(), 0755) < 0) {
498 error << string_compose(_("Session: cannot create session folder \"%1\" (%2)"), _path, strerror (errno)) << endmsg;
502 if (ensure_subdirs ()) {
506 if (!mix_template.empty()) {
507 std::string in_path = mix_template;
509 ifstream in(in_path.c_str());
512 string out_path = _path;
514 out_path += statefile_suffix;
516 ofstream out(out_path.c_str());
524 error << string_compose (_("Could not open %1 for writing mix template"), out_path)
530 error << string_compose (_("Could not open mix template %1 for reading"), in_path)
537 /* Instantiate metadata */
539 _metadata = new SessionMetadata ();
541 /* set initial start + end point */
543 _state_of_the_state = Clean;
545 /* set up Master Out and Control Out if necessary */
551 ChanCount count(DataType::AUDIO, bus_profile->master_out_channels);
553 if (bus_profile->master_out_channels) {
554 Route* rt = new Route (*this, _("master"), Route::MasterOut, DataType::AUDIO);
559 boost_debug_shared_ptr_mark_interesting (rt, "Route");
560 boost::shared_ptr<Route> r (rt);
561 r->input()->ensure_io (count, false, this);
562 r->output()->ensure_io (count, false, this);
563 r->set_remote_control_id (control_id++);
567 if (Config->get_use_monitor_bus()) {
568 Route* rt = new Route (*this, _("monitor"), Route::MonitorOut, DataType::AUDIO);
573 boost_debug_shared_ptr_mark_interesting (rt, "Route");
574 boost::shared_ptr<Route> r (rt);
575 r->input()->ensure_io (count, false, this);
576 r->output()->ensure_io (count, false, this);
577 r->set_remote_control_id (control_id);
583 /* prohibit auto-connect to master, because there isn't one */
584 bus_profile->output_ac = AutoConnectOption (bus_profile->output_ac & ~AutoConnectMaster);
588 add_routes (rl, false);
591 /* this allows the user to override settings with an environment variable.
594 if (no_auto_connect()) {
595 bus_profile->input_ac = AutoConnectOption (0);
596 bus_profile->output_ac = AutoConnectOption (0);
599 Config->set_input_auto_connect (bus_profile->input_ac);
600 Config->set_output_auto_connect (bus_profile->output_ac);
609 Session::maybe_write_autosave()
611 if (dirty() && record_status() != Recording) {
612 save_state("", true);
617 Session::remove_pending_capture_state ()
619 sys::path pending_state_file_path(_session_dir->root_path());
621 pending_state_file_path /= legalize_for_path (_current_snapshot_name) + pending_suffix;
625 sys::remove (pending_state_file_path);
627 catch(sys::filesystem_error& ex)
629 error << string_compose(_("Could remove pending capture state at path \"%1\" (%2)"),
630 pending_state_file_path.to_string(), ex.what()) << endmsg;
634 /** Rename a state file.
635 * @param snapshot_name Snapshot name.
638 Session::rename_state (string old_name, string new_name)
640 if (old_name == _current_snapshot_name || old_name == _name) {
641 /* refuse to rename the current snapshot or the "main" one */
645 const string old_xml_filename = legalize_for_path (old_name) + statefile_suffix;
646 const string new_xml_filename = legalize_for_path (new_name) + statefile_suffix;
648 const sys::path old_xml_path = _session_dir->root_path() / old_xml_filename;
649 const sys::path new_xml_path = _session_dir->root_path() / new_xml_filename;
653 sys::rename (old_xml_path, new_xml_path);
655 catch (const sys::filesystem_error& err)
657 error << string_compose(_("could not rename snapshot %1 to %2 (%3)"),
658 old_name, new_name, err.what()) << endmsg;
662 /** Remove a state file.
663 * @param snapshot_name Snapshot name.
666 Session::remove_state (string snapshot_name)
668 if (snapshot_name == _current_snapshot_name || snapshot_name == _name) {
669 // refuse to remove the current snapshot or the "main" one
673 sys::path xml_path(_session_dir->root_path());
675 xml_path /= legalize_for_path (snapshot_name) + statefile_suffix;
677 if (!create_backup_file (xml_path)) {
678 // don't remove it if a backup can't be made
679 // create_backup_file will log the error.
684 sys::remove (xml_path);
687 #ifdef HAVE_JACK_SESSION
689 Session::jack_session_event (jack_session_event_t * event)
693 struct tm local_time;
696 localtime_r (&n, &local_time);
697 strftime (timebuf, sizeof(timebuf), "JS_%FT%T", &local_time);
699 if (event->type == JackSessionSaveTemplate)
701 if (save_template( timebuf )) {
702 event->flags = JackSessionSaveError;
704 string cmd ("ardour3 -P -U ");
705 cmd += event->client_uuid;
709 event->command_line = strdup (cmd.c_str());
714 if (save_state (timebuf)) {
715 event->flags = JackSessionSaveError;
717 sys::path xml_path (_session_dir->root_path());
718 xml_path /= legalize_for_path (timebuf) + statefile_suffix;
720 string cmd ("ardour3 -P -U ");
721 cmd += event->client_uuid;
723 cmd += xml_path.to_string();
726 event->command_line = strdup (cmd.c_str());
730 jack_session_reply (_engine.jack(), event);
732 if (event->type == JackSessionSaveAndQuit) {
733 // TODO: make ardour quit.
736 jack_session_event_free( event );
741 Session::save_state (string snapshot_name, bool pending, bool switch_to_snapshot)
744 sys::path xml_path(_session_dir->root_path());
746 if (!_writable || (_state_of_the_state & CannotSave)) {
750 if (!_engine.connected ()) {
751 error << string_compose (_("the %1 audio engine is not connected and state saving would lose all I/O connections. Session not saved"),
757 /* tell sources we're saving first, in case they write out to a new file
758 * which should be saved with the state rather than the old one */
759 for (SourceMap::const_iterator i = sources.begin(); i != sources.end(); ++i) {
760 i->second->session_saved();
763 tree.set_root (&get_state());
765 if (snapshot_name.empty()) {
766 snapshot_name = _current_snapshot_name;
767 } else if (switch_to_snapshot) {
768 _current_snapshot_name = snapshot_name;
773 /* proper save: use statefile_suffix (.ardour in English) */
775 xml_path /= legalize_for_path (snapshot_name) + statefile_suffix;
777 /* make a backup copy of the old file */
779 if (sys::exists(xml_path) && !create_backup_file (xml_path)) {
780 // create_backup_file will log the error
786 /* pending save: use pending_suffix (.pending in English) */
787 xml_path /= legalize_for_path (snapshot_name) + pending_suffix;
790 sys::path tmp_path(_session_dir->root_path());
792 tmp_path /= legalize_for_path (snapshot_name) + temp_suffix;
794 // cerr << "actually writing state to " << xml_path.to_string() << endl;
796 if (!tree.write (tmp_path.to_string())) {
797 error << string_compose (_("state could not be saved to %1"), tmp_path.to_string()) << endmsg;
798 sys::remove (tmp_path);
803 if (rename (tmp_path.to_string().c_str(), xml_path.to_string().c_str()) != 0) {
804 error << string_compose (_("could not rename temporary session file %1 to %2"),
805 tmp_path.to_string(), xml_path.to_string()) << endmsg;
806 sys::remove (tmp_path);
813 save_history (snapshot_name);
815 bool was_dirty = dirty();
817 _state_of_the_state = StateOfTheState (_state_of_the_state & ~Dirty);
820 DirtyChanged (); /* EMIT SIGNAL */
823 StateSaved (snapshot_name); /* EMIT SIGNAL */
830 Session::restore_state (string snapshot_name)
832 if (load_state (snapshot_name) == 0) {
833 set_state (*state_tree->root(), Stateful::loading_state_version);
840 Session::load_state (string snapshot_name)
845 state_was_pending = false;
847 /* check for leftover pending state from a crashed capture attempt */
849 sys::path xmlpath(_session_dir->root_path());
850 xmlpath /= legalize_for_path (snapshot_name) + pending_suffix;
852 if (sys::exists (xmlpath)) {
854 /* there is pending state from a crashed capture attempt */
856 boost::optional<int> r = AskAboutPendingState();
857 if (r.get_value_or (1)) {
858 state_was_pending = true;
862 if (!state_was_pending) {
863 xmlpath = _session_dir->root_path();
864 xmlpath /= snapshot_name;
867 if (!sys::exists (xmlpath)) {
868 xmlpath = _session_dir->root_path();
869 xmlpath /= legalize_for_path (snapshot_name) + statefile_suffix;
870 if (!sys::exists (xmlpath)) {
871 error << string_compose(_("%1: session state information file \"%2\" doesn't exist!"), _name, xmlpath.to_string()) << endmsg;
876 state_tree = new XMLTree;
880 /* writable() really reflects the whole folder, but if for any
881 reason the session state file can't be written to, still
885 if (::access (xmlpath.to_string().c_str(), W_OK) != 0) {
889 if (!state_tree->read (xmlpath.to_string())) {
890 error << string_compose(_("Could not understand ardour file %1"), xmlpath.to_string()) << endmsg;
896 XMLNode& root (*state_tree->root());
898 if (root.name() != X_("Session")) {
899 error << string_compose (_("Session file %1 is not a session"), xmlpath.to_string()) << endmsg;
905 const XMLProperty* prop;
907 if ((prop = root.property ("version")) == 0) {
908 /* no version implies very old version of Ardour */
909 Stateful::loading_state_version = 1000;
915 sscanf (prop->value().c_str(), "%d.%d.%d", &major, &minor, µ);
916 Stateful::loading_state_version = (major * 1000) + minor;
919 if (Stateful::loading_state_version < CURRENT_SESSION_FILE_VERSION) {
921 sys::path backup_path(_session_dir->root_path());
923 backup_path /= legalize_for_path (snapshot_name) + "-1" + statefile_suffix;
925 // only create a backup once
926 if (sys::exists (backup_path)) {
930 info << string_compose (_("Copying old session file %1 to %2\nUse %2 with %3 versions before 2.0 from now on"),
931 xmlpath.to_string(), backup_path.to_string(), PROGRAM_NAME)
936 sys::copy_file (xmlpath, backup_path);
938 catch(sys::filesystem_error& ex)
940 error << string_compose (_("Unable to make backup of state file %1 (%2)"),
941 xmlpath.to_string(), ex.what())
951 Session::load_options (const XMLNode& node)
953 LocaleGuard lg (X_("POSIX"));
954 config.set_variables (node);
965 Session::get_template()
967 /* if we don't disable rec-enable, diskstreams
968 will believe they need to store their capture
969 sources in their state node.
972 disable_record (false);
978 Session::state(bool full_state)
980 XMLNode* node = new XMLNode("Session");
983 // store libardour version, just in case
985 snprintf(buf, sizeof(buf), "%d.%d.%d", libardour3_major_version, libardour3_minor_version, libardour3_micro_version);
986 node->add_property("version", string(buf));
988 /* store configuration settings */
992 node->add_property ("name", _name);
993 snprintf (buf, sizeof (buf), "%" PRId32, _nominal_frame_rate);
994 node->add_property ("sample-rate", buf);
996 if (session_dirs.size() > 1) {
1000 vector<space_and_path>::iterator i = session_dirs.begin();
1001 vector<space_and_path>::iterator next;
1003 ++i; /* skip the first one */
1007 while (i != session_dirs.end()) {
1011 if (next != session_dirs.end()) {
1021 child = node->add_child ("Path");
1022 child->add_content (p);
1026 /* save the ID counter */
1028 snprintf (buf, sizeof (buf), "%" PRIu64, ID::counter());
1029 node->add_property ("id-counter", buf);
1031 /* various options */
1033 node->add_child_nocopy (config.get_variables ());
1035 node->add_child_nocopy (_metadata->get_state());
1037 child = node->add_child ("Sources");
1040 Glib::Mutex::Lock sl (source_lock);
1042 for (SourceMap::iterator siter = sources.begin(); siter != sources.end(); ++siter) {
1044 /* Don't save information about non-destructive file sources that are empty
1045 and unused by any regions.
1048 boost::shared_ptr<FileSource> fs;
1049 if ((fs = boost::dynamic_pointer_cast<FileSource> (siter->second)) != 0) {
1050 if (!fs->destructive()) {
1051 if (fs->empty() && !fs->used()) {
1057 child->add_child_nocopy (siter->second->get_state());
1061 child = node->add_child ("Regions");
1064 Glib::Mutex::Lock rl (region_lock);
1065 const RegionFactory::RegionMap& region_map (RegionFactory::all_regions());
1066 for (RegionFactory::RegionMap::const_iterator i = region_map.begin(); i != region_map.end(); ++i) {
1067 boost::shared_ptr<Region> r = i->second;
1068 /* only store regions not attached to playlists */
1069 if (r->playlist() == 0) {
1070 child->add_child_nocopy (r->state (true));
1076 node->add_child_nocopy (_locations.get_state());
1078 // for a template, just create a new Locations, populate it
1079 // with the default start and end, and get the state for that.
1081 Location* range = new Location (0, 0, _("session"), Location::IsSessionRange);
1082 range->set (max_frames, 0);
1084 node->add_child_nocopy (loc.get_state());
1087 child = node->add_child ("Bundles");
1089 boost::shared_ptr<BundleList> bundles = _bundles.reader ();
1090 for (BundleList::iterator i = bundles->begin(); i != bundles->end(); ++i) {
1091 boost::shared_ptr<UserBundle> b = boost::dynamic_pointer_cast<UserBundle> (*i);
1093 child->add_child_nocopy (b->get_state());
1098 child = node->add_child ("Routes");
1100 boost::shared_ptr<RouteList> r = routes.reader ();
1102 RoutePublicOrderSorter cmp;
1103 RouteList public_order (*r);
1104 public_order.sort (cmp);
1106 /* the sort should have put control outs first */
1109 assert (_monitor_out == public_order.front());
1112 for (RouteList::iterator i = public_order.begin(); i != public_order.end(); ++i) {
1113 if (!(*i)->is_hidden()) {
1115 child->add_child_nocopy ((*i)->get_state());
1117 child->add_child_nocopy ((*i)->get_template());
1123 playlists->add_state (node, full_state);
1125 child = node->add_child ("RouteGroups");
1126 for (list<RouteGroup *>::iterator i = _route_groups.begin(); i != _route_groups.end(); ++i) {
1127 child->add_child_nocopy ((*i)->get_state());
1131 child = node->add_child ("Click");
1132 child->add_child_nocopy (_click_io->state (full_state));
1136 child = node->add_child ("NamedSelections");
1137 for (NamedSelectionList::iterator i = named_selections.begin(); i != named_selections.end(); ++i) {
1139 child->add_child_nocopy ((*i)->get_state());
1144 node->add_child_nocopy (_tempo_map->get_state());
1146 node->add_child_nocopy (get_control_protocol_state());
1149 node->add_child_copy (*_extra_xml);
1156 Session::get_control_protocol_state ()
1158 ControlProtocolManager& cpm (ControlProtocolManager::instance());
1159 return cpm.get_state();
1163 Session::set_state (const XMLNode& node, int version)
1167 const XMLProperty* prop;
1170 _state_of_the_state = StateOfTheState (_state_of_the_state|CannotSave);
1172 if (node.name() != X_("Session")){
1173 fatal << _("programming error: Session: incorrect XML node sent to set_state()") << endmsg;
1177 if ((prop = node.property ("version")) != 0) {
1178 version = atoi (prop->value ()) * 1000;
1181 if ((prop = node.property ("name")) != 0) {
1182 _name = prop->value ();
1185 if ((prop = node.property (X_("sample-rate"))) != 0) {
1187 _nominal_frame_rate = atoi (prop->value());
1189 if (_nominal_frame_rate != _current_frame_rate) {
1190 boost::optional<int> r = AskAboutSampleRateMismatch (_nominal_frame_rate, _current_frame_rate);
1191 if (r.get_value_or (0)) {
1197 setup_raid_path(_session_dir->root_path().to_string());
1199 if ((prop = node.property (X_("id-counter"))) != 0) {
1201 sscanf (prop->value().c_str(), "%" PRIu64, &x);
1202 ID::init_counter (x);
1204 /* old sessions used a timebased counter, so fake
1205 the startup ID counter based on a standard
1210 ID::init_counter (now);
1214 IO::disable_connecting ();
1216 /* Object loading order:
1221 MIDI Control // relies on data from Options/Config
1234 if ((child = find_named_node (node, "Extra")) != 0) {
1235 _extra_xml = new XMLNode (*child);
1238 if (((child = find_named_node (node, "Options")) != 0)) { /* old style */
1239 load_options (*child);
1240 } else if ((child = find_named_node (node, "Config")) != 0) { /* new style */
1241 load_options (*child);
1243 error << _("Session: XML state has no options section") << endmsg;
1246 use_config_midi_ports ();
1248 if (version >= 3000) {
1249 if ((child = find_named_node (node, "Metadata")) == 0) {
1250 warning << _("Session: XML state has no metadata section") << endmsg;
1251 } else if (_metadata->set_state (*child, version)) {
1256 if ((child = find_named_node (node, "Locations")) == 0) {
1257 error << _("Session: XML state has no locations section") << endmsg;
1259 } else if (_locations.set_state (*child, version)) {
1265 if ((location = _locations.auto_loop_location()) != 0) {
1266 set_auto_loop_location (location);
1269 if ((location = _locations.auto_punch_location()) != 0) {
1270 set_auto_punch_location (location);
1273 if ((location = _locations.session_range_location()) != 0) {
1274 delete _session_range_location;
1275 _session_range_location = location;
1278 if (_session_range_location) {
1279 AudioFileSource::set_header_position_offset (_session_range_location->start());
1282 if ((child = find_named_node (node, "Sources")) == 0) {
1283 error << _("Session: XML state has no sources section") << endmsg;
1285 } else if (load_sources (*child)) {
1289 if ((child = find_named_node (node, "Regions")) == 0) {
1290 error << _("Session: XML state has no Regions section") << endmsg;
1292 } else if (load_regions (*child)) {
1296 if ((child = find_named_node (node, "Playlists")) == 0) {
1297 error << _("Session: XML state has no playlists section") << endmsg;
1299 } else if (playlists->load (*this, *child)) {
1303 if ((child = find_named_node (node, "UnusedPlaylists")) == 0) {
1305 } else if (playlists->load_unused (*this, *child)) {
1309 if ((child = find_named_node (node, "NamedSelections")) != 0) {
1310 if (load_named_selections (*child)) {
1315 if (version >= 3000) {
1316 if ((child = find_named_node (node, "Bundles")) == 0) {
1317 warning << _("Session: XML state has no bundles section") << endmsg;
1320 /* We can't load Bundles yet as they need to be able
1321 to convert from port names to Port objects, which can't happen until
1323 _bundle_xml_node = new XMLNode (*child);
1327 if ((child = find_named_node (node, "TempoMap")) == 0) {
1328 error << _("Session: XML state has no Tempo Map section") << endmsg;
1330 } else if (_tempo_map->set_state (*child, version)) {
1334 if (version < 3000) {
1335 if ((child = find_named_node (node, X_("DiskStreams"))) == 0) {
1336 error << _("Session: XML state has no diskstreams section") << endmsg;
1338 } else if (load_diskstreams_2X (*child, version)) {
1343 if ((child = find_named_node (node, "Routes")) == 0) {
1344 error << _("Session: XML state has no routes section") << endmsg;
1346 } else if (load_routes (*child, version)) {
1350 /* our diskstreams list is no longer needed as they are now all owned by their Route */
1351 _diskstreams_2X.clear ();
1353 if (version >= 3000) {
1355 if ((child = find_named_node (node, "RouteGroups")) == 0) {
1356 error << _("Session: XML state has no route groups section") << endmsg;
1358 } else if (load_route_groups (*child, version)) {
1362 } else if (version < 3000) {
1364 if ((child = find_named_node (node, "EditGroups")) == 0) {
1365 error << _("Session: XML state has no edit groups section") << endmsg;
1367 } else if (load_route_groups (*child, version)) {
1371 if ((child = find_named_node (node, "MixGroups")) == 0) {
1372 error << _("Session: XML state has no mix groups section") << endmsg;
1374 } else if (load_route_groups (*child, version)) {
1379 if ((child = find_named_node (node, "Click")) == 0) {
1380 warning << _("Session: XML state has no click section") << endmsg;
1381 } else if (_click_io) {
1382 _click_io->set_state (*child, version);
1385 if ((child = find_named_node (node, "ControlProtocols")) != 0) {
1386 ControlProtocolManager::instance().set_protocol_states (*child);
1389 /* here beginneth the second phase ... */
1391 StateReady (); /* EMIT SIGNAL */
1400 Session::load_routes (const XMLNode& node, int version)
1403 XMLNodeConstIterator niter;
1404 RouteList new_routes;
1406 nlist = node.children();
1410 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1412 boost::shared_ptr<Route> route;
1413 if (version < 3000) {
1414 route = XMLRouteFactory_2X (**niter, version);
1416 route = XMLRouteFactory (**niter, version);
1420 error << _("Session: cannot create Route from XML description.") << endmsg;
1424 BootMessage (string_compose (_("Loaded track/bus %1"), route->name()));
1426 new_routes.push_back (route);
1429 add_routes (new_routes, false);
1434 boost::shared_ptr<Route>
1435 Session::XMLRouteFactory (const XMLNode& node, int version)
1437 boost::shared_ptr<Route> ret;
1439 if (node.name() != "Route") {
1443 XMLNode* ds_child = find_named_node (node, X_("Diskstream"));
1445 DataType type = DataType::AUDIO;
1446 const XMLProperty* prop = node.property("default-type");
1449 type = DataType (prop->value());
1452 assert (type != DataType::NIL);
1458 if (type == DataType::AUDIO) {
1459 track = new AudioTrack (*this, X_("toBeResetFroXML"));
1462 track = new MidiTrack (*this, X_("toBeResetFroXML"));
1465 if (track->init()) {
1470 if (track->set_state (node, version)) {
1475 boost_debug_shared_ptr_mark_interesting (track, "Track");
1479 Route* rt = new Route (*this, X_("toBeResetFroXML"));
1481 if (rt->init () == 0 && rt->set_state (node, version) == 0) {
1482 boost_debug_shared_ptr_mark_interesting (rt, "Route");
1492 boost::shared_ptr<Route>
1493 Session::XMLRouteFactory_2X (const XMLNode& node, int version)
1495 boost::shared_ptr<Route> ret;
1497 if (node.name() != "Route") {
1501 XMLProperty const * ds_prop = node.property (X_("diskstream-id"));
1503 ds_prop = node.property (X_("diskstream"));
1506 DataType type = DataType::AUDIO;
1507 const XMLProperty* prop = node.property("default-type");
1510 type = DataType (prop->value());
1513 assert (type != DataType::NIL);
1517 list<boost::shared_ptr<Diskstream> >::iterator i = _diskstreams_2X.begin ();
1518 while (i != _diskstreams_2X.end() && (*i)->id() != ds_prop->value()) {
1522 if (i == _diskstreams_2X.end()) {
1523 error << _("Could not find diskstream for route") << endmsg;
1524 return boost::shared_ptr<Route> ();
1529 if (type == DataType::AUDIO) {
1530 track = new AudioTrack (*this, X_("toBeResetFroXML"));
1533 track = new MidiTrack (*this, X_("toBeResetFroXML"));
1536 if (track->init()) {
1541 if (track->set_state (node, version)) {
1546 track->set_diskstream (*i);
1548 boost_debug_shared_ptr_mark_interesting (track, "Track");
1552 Route* rt = new Route (*this, X_("toBeResetFroXML"));
1554 if (rt->init () == 0 && rt->set_state (node, version) == 0) {
1555 boost_debug_shared_ptr_mark_interesting (rt, "Route");
1566 Session::load_regions (const XMLNode& node)
1569 XMLNodeConstIterator niter;
1570 boost::shared_ptr<Region> region;
1572 nlist = node.children();
1576 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1577 if ((region = XMLRegionFactory (**niter, false)) == 0) {
1578 error << _("Session: cannot create Region from XML description.");
1579 const XMLProperty *name = (**niter).property("name");
1582 error << " " << string_compose (_("Can not load state for region '%1'"), name->value());
1592 boost::shared_ptr<Region>
1593 Session::XMLRegionFactory (const XMLNode& node, bool full)
1595 const XMLProperty* type = node.property("type");
1599 if ( !type || type->value() == "audio" ) {
1601 return boost::shared_ptr<Region>(XMLAudioRegionFactory (node, full));
1603 } else if (type->value() == "midi") {
1605 return boost::shared_ptr<Region>(XMLMidiRegionFactory (node, full));
1609 } catch (failed_constructor& err) {
1610 return boost::shared_ptr<Region> ();
1613 return boost::shared_ptr<Region> ();
1616 boost::shared_ptr<AudioRegion>
1617 Session::XMLAudioRegionFactory (const XMLNode& node, bool /*full*/)
1619 const XMLProperty* prop;
1620 boost::shared_ptr<Source> source;
1621 boost::shared_ptr<AudioSource> as;
1623 SourceList master_sources;
1624 uint32_t nchans = 1;
1627 if (node.name() != X_("Region")) {
1628 return boost::shared_ptr<AudioRegion>();
1631 if ((prop = node.property (X_("channels"))) != 0) {
1632 nchans = atoi (prop->value().c_str());
1635 if ((prop = node.property ("name")) == 0) {
1636 cerr << "no name for this region\n";
1640 if ((prop = node.property (X_("source-0"))) == 0) {
1641 if ((prop = node.property ("source")) == 0) {
1642 error << _("Session: XMLNode describing a AudioRegion is incomplete (no source)") << endmsg;
1643 return boost::shared_ptr<AudioRegion>();
1647 PBD::ID s_id (prop->value());
1649 if ((source = source_by_id (s_id)) == 0) {
1650 error << string_compose(_("Session: XMLNode describing a AudioRegion references an unknown source id =%1"), s_id) << endmsg;
1651 return boost::shared_ptr<AudioRegion>();
1654 as = boost::dynamic_pointer_cast<AudioSource>(source);
1656 error << string_compose(_("Session: XMLNode describing a AudioRegion references a non-audio source id =%1"), s_id) << endmsg;
1657 return boost::shared_ptr<AudioRegion>();
1660 sources.push_back (as);
1662 /* pickup other channels */
1664 for (uint32_t n=1; n < nchans; ++n) {
1665 snprintf (buf, sizeof(buf), X_("source-%d"), n);
1666 if ((prop = node.property (buf)) != 0) {
1668 PBD::ID id2 (prop->value());
1670 if ((source = source_by_id (id2)) == 0) {
1671 error << string_compose(_("Session: XMLNode describing a AudioRegion references an unknown source id =%1"), id2) << endmsg;
1672 return boost::shared_ptr<AudioRegion>();
1675 as = boost::dynamic_pointer_cast<AudioSource>(source);
1677 error << string_compose(_("Session: XMLNode describing a AudioRegion references a non-audio source id =%1"), id2) << endmsg;
1678 return boost::shared_ptr<AudioRegion>();
1680 sources.push_back (as);
1684 for (uint32_t n = 0; n < nchans; ++n) {
1685 snprintf (buf, sizeof(buf), X_("master-source-%d"), n);
1686 if ((prop = node.property (buf)) != 0) {
1688 PBD::ID id2 (prop->value());
1690 if ((source = source_by_id (id2)) == 0) {
1691 error << string_compose(_("Session: XMLNode describing a AudioRegion references an unknown source id =%1"), id2) << endmsg;
1692 return boost::shared_ptr<AudioRegion>();
1695 as = boost::dynamic_pointer_cast<AudioSource>(source);
1697 error << string_compose(_("Session: XMLNode describing a AudioRegion references a non-audio source id =%1"), id2) << endmsg;
1698 return boost::shared_ptr<AudioRegion>();
1700 master_sources.push_back (as);
1705 boost::shared_ptr<AudioRegion> region (boost::dynamic_pointer_cast<AudioRegion> (RegionFactory::create (sources, node)));
1707 /* a final detail: this is the one and only place that we know how long missing files are */
1709 if (region->whole_file()) {
1710 for (SourceList::iterator sx = sources.begin(); sx != sources.end(); ++sx) {
1711 boost::shared_ptr<SilentFileSource> sfp = boost::dynamic_pointer_cast<SilentFileSource> (*sx);
1713 sfp->set_length (region->length());
1718 if (!master_sources.empty()) {
1719 if (master_sources.size() != nchans) {
1720 error << _("Session: XMLNode describing an AudioRegion is missing some master sources; ignored") << endmsg;
1722 region->set_master_sources (master_sources);
1730 catch (failed_constructor& err) {
1731 return boost::shared_ptr<AudioRegion>();
1735 boost::shared_ptr<MidiRegion>
1736 Session::XMLMidiRegionFactory (const XMLNode& node, bool /*full*/)
1738 const XMLProperty* prop;
1739 boost::shared_ptr<Source> source;
1740 boost::shared_ptr<MidiSource> ms;
1742 uint32_t nchans = 1;
1744 if (node.name() != X_("Region")) {
1745 return boost::shared_ptr<MidiRegion>();
1748 if ((prop = node.property (X_("channels"))) != 0) {
1749 nchans = atoi (prop->value().c_str());
1752 if ((prop = node.property ("name")) == 0) {
1753 cerr << "no name for this region\n";
1757 // Multiple midi channels? that's just crazy talk
1758 assert(nchans == 1);
1760 if ((prop = node.property (X_("source-0"))) == 0) {
1761 if ((prop = node.property ("source")) == 0) {
1762 error << _("Session: XMLNode describing a MidiRegion is incomplete (no source)") << endmsg;
1763 return boost::shared_ptr<MidiRegion>();
1767 PBD::ID s_id (prop->value());
1769 if ((source = source_by_id (s_id)) == 0) {
1770 error << string_compose(_("Session: XMLNode describing a MidiRegion references an unknown source id =%1"), s_id) << endmsg;
1771 return boost::shared_ptr<MidiRegion>();
1774 ms = boost::dynamic_pointer_cast<MidiSource>(source);
1776 error << string_compose(_("Session: XMLNode describing a MidiRegion references a non-midi source id =%1"), s_id) << endmsg;
1777 return boost::shared_ptr<MidiRegion>();
1780 sources.push_back (ms);
1783 boost::shared_ptr<MidiRegion> region (boost::dynamic_pointer_cast<MidiRegion> (RegionFactory::create (sources, node)));
1784 /* a final detail: this is the one and only place that we know how long missing files are */
1786 if (region->whole_file()) {
1787 for (SourceList::iterator sx = sources.begin(); sx != sources.end(); ++sx) {
1788 boost::shared_ptr<SilentFileSource> sfp = boost::dynamic_pointer_cast<SilentFileSource> (*sx);
1790 sfp->set_length (region->length());
1798 catch (failed_constructor& err) {
1799 return boost::shared_ptr<MidiRegion>();
1804 Session::get_sources_as_xml ()
1807 XMLNode* node = new XMLNode (X_("Sources"));
1808 Glib::Mutex::Lock lm (source_lock);
1810 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ++i) {
1811 node->add_child_nocopy (i->second->get_state());
1818 Session::path_from_region_name (DataType type, string name, string identifier)
1820 char buf[PATH_MAX+1];
1822 SessionDirectory sdir(get_best_session_directory_for_new_source());
1823 sys::path source_dir = ((type == DataType::AUDIO)
1824 ? sdir.sound_path() : sdir.midi_path());
1826 string ext = ((type == DataType::AUDIO) ? ".wav" : ".mid");
1828 for (n = 0; n < 999999; ++n) {
1829 if (identifier.length()) {
1830 snprintf (buf, sizeof(buf), "%s%s%" PRIu32 "%s", name.c_str(),
1831 identifier.c_str(), n, ext.c_str());
1833 snprintf (buf, sizeof(buf), "%s-%" PRIu32 "%s", name.c_str(),
1837 sys::path source_path = source_dir / buf;
1839 if (!sys::exists (source_path)) {
1840 return source_path.to_string();
1844 error << string_compose (_("cannot create new file from region name \"%1\" with ident = \"%2\": too many existing files with similar names"),
1853 Session::load_sources (const XMLNode& node)
1856 XMLNodeConstIterator niter;
1857 boost::shared_ptr<Source> source;
1859 nlist = node.children();
1863 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1865 if ((source = XMLSourceFactory (**niter)) == 0) {
1866 error << _("Session: cannot create Source from XML description.") << endmsg;
1868 } catch (MissingSource& err) {
1869 warning << _("A sound file is missing. It will be replaced by silence.") << endmsg;
1870 source = SourceFactory::createSilent (*this, **niter, max_frames, _current_frame_rate);
1877 boost::shared_ptr<Source>
1878 Session::XMLSourceFactory (const XMLNode& node)
1880 if (node.name() != "Source") {
1881 return boost::shared_ptr<Source>();
1885 /* note: do peak building in another thread when loading session state */
1886 return SourceFactory::create (*this, node, true);
1889 catch (failed_constructor& err) {
1890 error << string_compose (_("Found a sound file that cannot be used by %1. Talk to the progammers."), PROGRAM_NAME) << endmsg;
1891 return boost::shared_ptr<Source>();
1896 Session::save_template (string template_name)
1900 if (_state_of_the_state & CannotSave) {
1904 sys::path user_template_dir(user_template_directory());
1908 sys::create_directories (user_template_dir);
1910 catch(sys::filesystem_error& ex)
1912 error << string_compose(_("Could not create mix templates directory \"%1\" (%2)"),
1913 user_template_dir.to_string(), ex.what()) << endmsg;
1917 tree.set_root (&get_template());
1919 sys::path template_file_path(user_template_dir);
1920 template_file_path /= template_name + template_suffix;
1922 if (sys::exists (template_file_path))
1924 warning << string_compose(_("Template \"%1\" already exists - new version not created"),
1925 template_file_path.to_string()) << endmsg;
1929 if (!tree.write (template_file_path.to_string())) {
1930 error << _("mix template not saved") << endmsg;
1938 Session::rename_template (string old_name, string new_name)
1940 sys::path old_path (user_template_directory());
1941 old_path /= old_name + template_suffix;
1943 sys::path new_path(user_template_directory());
1944 new_path /= new_name + template_suffix;
1946 if (sys::exists (new_path)) {
1947 warning << string_compose(_("Template \"%1\" already exists - template not renamed"),
1948 new_path.to_string()) << endmsg;
1953 sys::rename (old_path, new_path);
1961 Session::delete_template (string name)
1963 sys::path path = user_template_directory();
1964 path /= name + template_suffix;
1975 Session::refresh_disk_space ()
1978 struct statfs statfsbuf;
1979 vector<space_and_path>::iterator i;
1980 Glib::Mutex::Lock lm (space_lock);
1983 /* get freespace on every FS that is part of the session path */
1985 _total_free_4k_blocks = 0;
1987 for (i = session_dirs.begin(); i != session_dirs.end(); ++i) {
1988 statfs ((*i).path.c_str(), &statfsbuf);
1990 scale = statfsbuf.f_bsize/4096.0;
1992 (*i).blocks = (uint32_t) floor (statfsbuf.f_bavail * scale);
1993 _total_free_4k_blocks += (*i).blocks;
1999 Session::get_best_session_directory_for_new_source ()
2001 vector<space_and_path>::iterator i;
2002 string result = _session_dir->root_path().to_string();
2004 /* handle common case without system calls */
2006 if (session_dirs.size() == 1) {
2010 /* OK, here's the algorithm we're following here:
2012 We want to select which directory to use for
2013 the next file source to be created. Ideally,
2014 we'd like to use a round-robin process so as to
2015 get maximum performance benefits from splitting
2016 the files across multiple disks.
2018 However, in situations without much diskspace, an
2019 RR approach may end up filling up a filesystem
2020 with new files while others still have space.
2021 Its therefore important to pay some attention to
2022 the freespace in the filesystem holding each
2023 directory as well. However, if we did that by
2024 itself, we'd keep creating new files in the file
2025 system with the most space until it was as full
2026 as all others, thus negating any performance
2027 benefits of this RAID-1 like approach.
2029 So, we use a user-configurable space threshold. If
2030 there are at least 2 filesystems with more than this
2031 much space available, we use RR selection between them.
2032 If not, then we pick the filesystem with the most space.
2034 This gets a good balance between the two
2038 refresh_disk_space ();
2040 int free_enough = 0;
2042 for (i = session_dirs.begin(); i != session_dirs.end(); ++i) {
2043 if ((*i).blocks * 4096 >= Config->get_disk_choice_space_threshold()) {
2048 if (free_enough >= 2) {
2049 /* use RR selection process, ensuring that the one
2053 i = last_rr_session_dir;
2056 if (++i == session_dirs.end()) {
2057 i = session_dirs.begin();
2060 if ((*i).blocks * 4096 >= Config->get_disk_choice_space_threshold()) {
2061 if (create_session_directory ((*i).path)) {
2063 last_rr_session_dir = i;
2068 } while (i != last_rr_session_dir);
2072 /* pick FS with the most freespace (and that
2073 seems to actually work ...)
2076 vector<space_and_path> sorted;
2077 space_and_path_ascending_cmp cmp;
2079 sorted = session_dirs;
2080 sort (sorted.begin(), sorted.end(), cmp);
2082 for (i = sorted.begin(); i != sorted.end(); ++i) {
2083 if (create_session_directory ((*i).path)) {
2085 last_rr_session_dir = i;
2095 Session::load_named_selections (const XMLNode& node)
2098 XMLNodeConstIterator niter;
2101 nlist = node.children();
2105 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2107 if ((ns = XMLNamedSelectionFactory (**niter)) == 0) {
2108 error << _("Session: cannot create Named Selection from XML description.") << endmsg;
2116 Session::XMLNamedSelectionFactory (const XMLNode& node)
2119 return new NamedSelection (*this, node);
2122 catch (failed_constructor& err) {
2128 Session::automation_dir () const
2130 return Glib::build_filename (_path, "automation");
2134 Session::analysis_dir () const
2136 return Glib::build_filename (_path, "analysis");
2140 Session::load_bundles (XMLNode const & node)
2142 XMLNodeList nlist = node.children();
2143 XMLNodeConstIterator niter;
2147 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2148 if ((*niter)->name() == "InputBundle") {
2149 add_bundle (boost::shared_ptr<UserBundle> (new UserBundle (**niter, true)));
2150 } else if ((*niter)->name() == "OutputBundle") {
2151 add_bundle (boost::shared_ptr<UserBundle> (new UserBundle (**niter, false)));
2153 error << string_compose(_("Unknown node \"%1\" found in Bundles list from state file"), (*niter)->name()) << endmsg;
2162 Session::load_route_groups (const XMLNode& node, int version)
2164 XMLNodeList nlist = node.children();
2165 XMLNodeConstIterator niter;
2169 if (version >= 3000) {
2171 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2172 if ((*niter)->name() == "RouteGroup") {
2173 RouteGroup* rg = new RouteGroup (*this, "");
2174 add_route_group (rg);
2175 rg->set_state (**niter, version);
2179 } else if (version < 3000) {
2181 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2182 if ((*niter)->name() == "EditGroup" || (*niter)->name() == "MixGroup") {
2183 RouteGroup* rg = new RouteGroup (*this, "");
2184 add_route_group (rg);
2185 rg->set_state (**niter, version);
2194 Session::auto_save()
2196 save_state (_current_snapshot_name);
2200 state_file_filter (const string &str, void */*arg*/)
2202 return (str.length() > strlen(statefile_suffix) &&
2203 str.find (statefile_suffix) == (str.length() - strlen (statefile_suffix)));
2207 bool operator()(const string* a, const string* b) {
2213 remove_end(string* state)
2215 string statename(*state);
2217 string::size_type start,end;
2218 if ((start = statename.find_last_of ('/')) != string::npos) {
2219 statename = statename.substr (start+1);
2222 if ((end = statename.rfind(".ardour")) == string::npos) {
2223 end = statename.length();
2226 return new string(statename.substr (0, end));
2230 Session::possible_states (string path)
2232 PathScanner scanner;
2233 vector<string*>* states = scanner (path, state_file_filter, 0, false, false);
2235 transform(states->begin(), states->end(), states->begin(), remove_end);
2238 sort (states->begin(), states->end(), cmp);
2244 Session::possible_states () const
2246 return possible_states(_path);
2250 Session::add_route_group (RouteGroup* g)
2252 _route_groups.push_back (g);
2253 route_group_added (g); /* EMIT SIGNAL */
2255 g->MembershipChanged.connect_same_thread (*this, boost::bind (&Session::route_group_changed, this));
2256 g->PropertyChanged.connect_same_thread (*this, boost::bind (&Session::route_group_changed, this));
2262 Session::remove_route_group (RouteGroup& rg)
2264 list<RouteGroup*>::iterator i;
2266 if ((i = find (_route_groups.begin(), _route_groups.end(), &rg)) != _route_groups.end()) {
2267 _route_groups.erase (i);
2270 route_group_removed (); /* EMIT SIGNAL */
2276 Session::route_group_by_name (string name)
2278 list<RouteGroup *>::iterator i;
2280 for (i = _route_groups.begin(); i != _route_groups.end(); ++i) {
2281 if ((*i)->name() == name) {
2289 Session::start_reversible_command (const string& name)
2291 UndoTransaction* trans = new UndoTransaction();
2292 trans->set_name(name);
2297 Session::finish_reversible_command (UndoTransaction& ut)
2300 gettimeofday(&now, 0);
2301 ut.set_timestamp(now);
2306 Session::begin_reversible_command(const string& name)
2308 UndoTransaction* trans = new UndoTransaction();
2309 trans->set_name(name);
2311 if (!_current_trans.empty()) {
2312 _current_trans.top()->add_command (trans);
2314 _current_trans.push(trans);
2319 Session::commit_reversible_command(Command *cmd)
2321 assert(!_current_trans.empty());
2325 _current_trans.top()->add_command(cmd);
2328 if (_current_trans.top()->empty()) {
2329 _current_trans.pop();
2333 gettimeofday(&now, 0);
2334 _current_trans.top()->set_timestamp(now);
2336 _history.add(_current_trans.top());
2337 _current_trans.pop();
2341 accept_all_non_peak_files (const string& path, void */*arg*/)
2343 return (path.length() > 5 && path.find (peakfile_suffix) != (path.length() - 5));
2347 accept_all_state_files (const string& path, void */*arg*/)
2349 return (path.length() > 7 && path.find (".ardour") == (path.length() - 7));
2353 Session::find_all_sources (string path, set<string>& result)
2358 if (!tree.read (path)) {
2362 if ((node = find_named_node (*tree.root(), "Sources")) == 0) {
2367 XMLNodeConstIterator niter;
2369 nlist = node->children();
2373 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2377 if ((prop = (*niter)->property (X_("type"))) == 0) {
2381 DataType type (prop->value());
2383 if ((prop = (*niter)->property (X_("name"))) == 0) {
2387 if (prop->value()[0] == '/') {
2388 /* external file, ignore */
2392 Glib::ustring found_path;
2396 if (FileSource::find (type, prop->value(), true, is_new, chan, found_path)) {
2397 result.insert (found_path);
2405 Session::find_all_sources_across_snapshots (set<string>& result, bool exclude_this_snapshot)
2407 PathScanner scanner;
2408 vector<string*>* state_files;
2410 string this_snapshot_path;
2416 if (ripped[ripped.length()-1] == '/') {
2417 ripped = ripped.substr (0, ripped.length() - 1);
2420 state_files = scanner (ripped, accept_all_state_files, (void *) 0, false, true);
2422 if (state_files == 0) {
2427 this_snapshot_path = _path;
2428 this_snapshot_path += legalize_for_path (_current_snapshot_name);
2429 this_snapshot_path += statefile_suffix;
2431 for (vector<string*>::iterator i = state_files->begin(); i != state_files->end(); ++i) {
2433 if (exclude_this_snapshot && **i == this_snapshot_path) {
2437 if (find_all_sources (**i, result) < 0) {
2445 struct RegionCounter {
2446 typedef std::map<PBD::ID,boost::shared_ptr<AudioSource> > AudioSourceList;
2447 AudioSourceList::iterator iter;
2448 boost::shared_ptr<Region> region;
2451 RegionCounter() : count (0) {}
2455 Session::ask_about_playlist_deletion (boost::shared_ptr<Playlist> p)
2457 boost::optional<int> r = AskAboutPlaylistDeletion (p);
2458 return r.get_value_or (1);
2462 Session::cleanup_sources (CleanupReport& rep)
2464 // FIXME: needs adaptation to midi
2466 vector<boost::shared_ptr<Source> > dead_sources;
2467 PathScanner scanner;
2469 vector<space_and_path>::iterator i;
2470 vector<space_and_path>::iterator nexti;
2471 vector<string*>* soundfiles;
2472 vector<string> unused;
2473 set<string> all_sources;
2478 _state_of_the_state = (StateOfTheState) (_state_of_the_state | InCleanup);
2480 /* step 1: consider deleting all unused playlists */
2482 if (playlists->maybe_delete_unused (boost::bind (Session::ask_about_playlist_deletion, _1))) {
2487 /* step 2: find all un-used sources */
2492 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ) {
2494 SourceMap::iterator tmp;
2499 /* do not bother with files that are zero size, otherwise we remove the current "nascent"
2503 if (!i->second->used() && (i->second->length(i->second->timeline_position() > 0))) {
2504 dead_sources.push_back (i->second);
2505 i->second->drop_references ();
2511 /* build a list of all the possible sound directories for the session */
2513 for (i = session_dirs.begin(); i != session_dirs.end(); ) {
2518 SessionDirectory sdir ((*i).path);
2519 sound_path += sdir.sound_path().to_string();
2521 if (nexti != session_dirs.end()) {
2528 /* now do the same thing for the files that ended up in the sounds dir(s)
2529 but are not referenced as sources in any snapshot.
2532 soundfiles = scanner (sound_path, accept_all_non_peak_files, (void *) 0, false, true);
2534 if (soundfiles == 0) {
2538 /* find all sources, but don't use this snapshot because the
2539 state file on disk still references sources we may have already
2543 find_all_sources_across_snapshots (all_sources, true);
2545 /* add our current source list
2548 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ++i) {
2549 boost::shared_ptr<FileSource> fs;
2551 if ((fs = boost::dynamic_pointer_cast<FileSource> (i->second)) != 0) {
2552 all_sources.insert (fs->path());
2556 char tmppath1[PATH_MAX+1];
2557 char tmppath2[PATH_MAX+1];
2559 for (vector<string*>::iterator x = soundfiles->begin(); x != soundfiles->end(); ++x) {
2564 for (set<string>::iterator i = all_sources.begin(); i != all_sources.end(); ++i) {
2566 if (realpath(spath.c_str(), tmppath1) == 0) {
2567 error << string_compose (_("Cannot expand path %1 (%2)"),
2568 spath, strerror (errno)) << endmsg;
2572 if (realpath((*i).c_str(), tmppath2) == 0) {
2573 error << string_compose (_("Cannot expand path %1 (%2)"),
2574 (*i), strerror (errno)) << endmsg;
2578 if (strcmp(tmppath1, tmppath2) == 0) {
2585 unused.push_back (spath);
2589 /* now try to move all unused files into the "dead_sounds" directory(ies) */
2591 for (vector<string>::iterator x = unused.begin(); x != unused.end(); ++x) {
2592 struct stat statbuf;
2594 rep.paths.push_back (*x);
2595 if (stat ((*x).c_str(), &statbuf) == 0) {
2596 rep.space += statbuf.st_size;
2601 /* don't move the file across filesystems, just
2602 stick it in the `dead_sound_dir_name' directory
2603 on whichever filesystem it was already on.
2606 if ((*x).find ("/sounds/") != string::npos) {
2608 /* old school, go up 1 level */
2610 newpath = Glib::path_get_dirname (*x); // "sounds"
2611 newpath = Glib::path_get_dirname (newpath); // "session-name"
2615 /* new school, go up 4 levels */
2617 newpath = Glib::path_get_dirname (*x); // "audiofiles"
2618 newpath = Glib::path_get_dirname (newpath); // "session-name"
2619 newpath = Glib::path_get_dirname (newpath); // "interchange"
2620 newpath = Glib::path_get_dirname (newpath); // "session-dir"
2624 newpath += dead_sound_dir_name;
2626 if (g_mkdir_with_parents (newpath.c_str(), 0755) < 0) {
2627 error << string_compose(_("Session: cannot create session peakfile folder \"%1\" (%2)"), newpath, strerror (errno)) << endmsg;
2632 newpath += Glib::path_get_basename ((*x));
2634 if (access (newpath.c_str(), F_OK) == 0) {
2636 /* the new path already exists, try versioning */
2638 char buf[PATH_MAX+1];
2642 snprintf (buf, sizeof (buf), "%s.%d", newpath.c_str(), version);
2645 while (access (newpath_v.c_str(), F_OK) == 0 && version < 999) {
2646 snprintf (buf, sizeof (buf), "%s.%d", newpath.c_str(), ++version);
2650 if (version == 999) {
2651 error << string_compose (_("there are already 1000 files with names like %1; versioning discontinued"),
2655 newpath = newpath_v;
2660 /* it doesn't exist, or we can't read it or something */
2664 if (::rename ((*x).c_str(), newpath.c_str()) != 0) {
2665 error << string_compose (_("cannot rename audio file source from %1 to %2 (%3)"),
2666 (*x), newpath, strerror (errno))
2671 /* see if there an easy to find peakfile for this file, and remove it.
2674 string peakpath = (*x).substr (0, (*x).find_last_of ('.'));
2675 peakpath += peakfile_suffix;
2677 if (access (peakpath.c_str(), W_OK) == 0) {
2678 if (::unlink (peakpath.c_str()) != 0) {
2679 error << string_compose (_("cannot remove peakfile %1 for %2 (%3)"),
2680 peakpath, _path, strerror (errno))
2682 /* try to back out */
2683 rename (newpath.c_str(), _path.c_str());
2691 /* dump the history list */
2695 /* save state so we don't end up a session file
2696 referring to non-existent sources.
2702 _state_of_the_state = (StateOfTheState) (_state_of_the_state & ~InCleanup);
2708 Session::cleanup_trash_sources (CleanupReport& rep)
2710 // FIXME: needs adaptation for MIDI
2712 vector<space_and_path>::iterator i;
2713 string dead_sound_dir;
2714 struct dirent* dentry;
2715 struct stat statbuf;
2721 for (i = session_dirs.begin(); i != session_dirs.end(); ++i) {
2723 dead_sound_dir = (*i).path;
2724 dead_sound_dir += dead_sound_dir_name;
2726 if ((dead = opendir (dead_sound_dir.c_str())) == 0) {
2730 while ((dentry = readdir (dead)) != 0) {
2732 /* avoid '.' and '..' */
2734 if ((dentry->d_name[0] == '.' && dentry->d_name[1] == '\0') ||
2735 (dentry->d_name[2] == '\0' && dentry->d_name[0] == '.' && dentry->d_name[1] == '.')) {
2741 fullpath = dead_sound_dir;
2743 fullpath += dentry->d_name;
2745 if (stat (fullpath.c_str(), &statbuf)) {
2749 if (!S_ISREG (statbuf.st_mode)) {
2753 if (unlink (fullpath.c_str())) {
2754 error << string_compose (_("cannot remove dead sound file %1 (%2)"),
2755 fullpath, strerror (errno))
2759 rep.paths.push_back (dentry->d_name);
2760 rep.space += statbuf.st_size;
2771 Session::set_dirty ()
2773 bool was_dirty = dirty();
2775 _state_of_the_state = StateOfTheState (_state_of_the_state | Dirty);
2779 DirtyChanged(); /* EMIT SIGNAL */
2785 Session::set_clean ()
2787 bool was_dirty = dirty();
2789 _state_of_the_state = Clean;
2793 DirtyChanged(); /* EMIT SIGNAL */
2798 Session::set_deletion_in_progress ()
2800 _state_of_the_state = StateOfTheState (_state_of_the_state | Deletion);
2804 Session::clear_deletion_in_progress ()
2806 _state_of_the_state = StateOfTheState (_state_of_the_state & (~Deletion));
2810 Session::add_controllable (boost::shared_ptr<Controllable> c)
2812 /* this adds a controllable to the list managed by the Session.
2813 this is a subset of those managed by the Controllable class
2814 itself, and represents the only ones whose state will be saved
2815 as part of the session.
2818 Glib::Mutex::Lock lm (controllables_lock);
2819 controllables.insert (c);
2822 struct null_deleter { void operator()(void const *) const {} };
2825 Session::remove_controllable (Controllable* c)
2827 if (_state_of_the_state | Deletion) {
2831 Glib::Mutex::Lock lm (controllables_lock);
2833 Controllables::iterator x = controllables.find (boost::shared_ptr<Controllable>(c, null_deleter()));
2835 if (x != controllables.end()) {
2836 controllables.erase (x);
2840 boost::shared_ptr<Controllable>
2841 Session::controllable_by_id (const PBD::ID& id)
2843 Glib::Mutex::Lock lm (controllables_lock);
2845 for (Controllables::iterator i = controllables.begin(); i != controllables.end(); ++i) {
2846 if ((*i)->id() == id) {
2851 return boost::shared_ptr<Controllable>();
2854 boost::shared_ptr<Controllable>
2855 Session::controllable_by_descriptor (const ControllableDescriptor& desc)
2857 boost::shared_ptr<Controllable> c;
2858 boost::shared_ptr<Route> r;
2860 switch (desc.top_level_type()) {
2861 case ControllableDescriptor::NamedRoute:
2863 std::string str = desc.top_level_name();
2864 if (str == "master") {
2866 } else if (str == "control" || str == "listen") {
2869 r = route_by_name (desc.top_level_name());
2874 case ControllableDescriptor::RemoteControlID:
2875 r = route_by_remote_id (desc.rid());
2883 switch (desc.subtype()) {
2884 case ControllableDescriptor::Gain:
2885 c = r->gain_control ();
2888 case ControllableDescriptor::Solo:
2889 c = r->solo_control();
2892 case ControllableDescriptor::Mute:
2893 c = r->mute_control();
2896 case ControllableDescriptor::Recenable:
2898 boost::shared_ptr<Track> t = boost::dynamic_pointer_cast<Track>(r);
2901 c = t->rec_enable_control ();
2906 case ControllableDescriptor::Pan:
2907 /* XXX pan control */
2910 case ControllableDescriptor::Balance:
2911 /* XXX simple pan control */
2914 case ControllableDescriptor::PluginParameter:
2916 uint32_t plugin = desc.target (0);
2917 uint32_t parameter_index = desc.target (1);
2919 /* revert to zero based counting */
2925 if (parameter_index > 0) {
2929 boost::shared_ptr<Processor> p = r->nth_plugin (plugin);
2932 c = boost::dynamic_pointer_cast<ARDOUR::AutomationControl>(
2933 p->control(Evoral::Parameter(PluginAutomation, 0, parameter_index)));
2938 case ControllableDescriptor::SendGain:
2940 uint32_t send = desc.target (0);
2942 /* revert to zero-based counting */
2948 boost::shared_ptr<Processor> p = r->nth_send (send);
2951 boost::shared_ptr<Send> s = boost::dynamic_pointer_cast<Send>(p);
2952 boost::shared_ptr<Amp> a = s->amp();
2955 c = s->amp()->gain_control();
2962 /* relax and return a null pointer */
2970 Session::add_instant_xml (XMLNode& node, bool write_to_config)
2973 Stateful::add_instant_xml (node, _path);
2976 if (write_to_config) {
2977 Config->add_instant_xml (node);
2982 Session::instant_xml (const string& node_name)
2984 return Stateful::instant_xml (node_name, _path);
2988 Session::save_history (string snapshot_name)
2996 if (snapshot_name.empty()) {
2997 snapshot_name = _current_snapshot_name;
3000 const string history_filename = legalize_for_path (snapshot_name) + history_suffix;
3001 const string backup_filename = history_filename + backup_suffix;
3002 const sys::path xml_path = _session_dir->root_path() / history_filename;
3003 const sys::path backup_path = _session_dir->root_path() / backup_filename;
3005 if (sys::exists (xml_path)) {
3008 sys::rename (xml_path, backup_path);
3010 catch (const sys::filesystem_error& err)
3012 error << _("could not backup old history file, current history not saved") << endmsg;
3017 if (!Config->get_save_history() || Config->get_saved_history_depth() < 0) {
3021 tree.set_root (&_history.get_state (Config->get_saved_history_depth()));
3023 if (!tree.write (xml_path.to_string()))
3025 error << string_compose (_("history could not be saved to %1"), xml_path.to_string()) << endmsg;
3029 sys::remove (xml_path);
3030 sys::rename (backup_path, xml_path);
3032 catch (const sys::filesystem_error& err)
3034 error << string_compose (_("could not restore history file from backup %1 (%2)"),
3035 backup_path.to_string(), err.what()) << endmsg;
3045 Session::restore_history (string snapshot_name)
3049 if (snapshot_name.empty()) {
3050 snapshot_name = _current_snapshot_name;
3053 const string xml_filename = legalize_for_path (snapshot_name) + history_suffix;
3054 const sys::path xml_path = _session_dir->root_path() / xml_filename;
3056 info << "Loading history from " << xml_path.to_string() << endmsg;
3058 if (!sys::exists (xml_path)) {
3059 info << string_compose (_("%1: no history file \"%2\" for this session."),
3060 _name, xml_path.to_string()) << endmsg;
3064 if (!tree.read (xml_path.to_string())) {
3065 error << string_compose (_("Could not understand session history file \"%1\""),
3066 xml_path.to_string()) << endmsg;
3073 for (XMLNodeConstIterator it = tree.root()->children().begin(); it != tree.root()->children().end(); it++) {
3076 UndoTransaction* ut = new UndoTransaction ();
3079 ut->set_name(t->property("name")->value());
3080 stringstream ss(t->property("tv-sec")->value());
3082 ss.str(t->property("tv-usec")->value());
3084 ut->set_timestamp(tv);
3086 for (XMLNodeConstIterator child_it = t->children().begin();
3087 child_it != t->children().end(); child_it++)
3089 XMLNode *n = *child_it;
3092 if (n->name() == "MementoCommand" ||
3093 n->name() == "MementoUndoCommand" ||
3094 n->name() == "MementoRedoCommand") {
3096 if ((c = memento_command_factory(n))) {
3100 } else if (n->name() == "DiffCommand") {
3101 PBD::ID id(n->property("midi-source")->value());
3102 boost::shared_ptr<MidiSource> midi_source =
3103 boost::dynamic_pointer_cast<MidiSource, Source>(source_by_id(id));
3105 ut->add_command(new MidiModel::DiffCommand(midi_source->model(), *n));
3107 error << _("Failed to downcast MidiSource for DiffCommand") << endmsg;
3110 } else if (n->name() == "StatefulDiffCommand") {
3111 if ((c = stateful_diff_command_factory (n))) {
3112 ut->add_command (c);
3115 error << string_compose(_("Couldn't figure out how to make a Command out of a %1 XMLNode."), n->name()) << endmsg;
3126 Session::config_changed (std::string p, bool ours)
3132 if (p == "seamless-loop") {
3134 } else if (p == "rf-speed") {
3136 } else if (p == "auto-loop") {
3138 } else if (p == "auto-input") {
3140 if (Config->get_monitoring_model() == HardwareMonitoring && transport_rolling()) {
3141 /* auto-input only makes a difference if we're rolling */
3143 boost::shared_ptr<RouteList> rl = routes.reader ();
3144 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
3145 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
3146 if (tr && tr->record_enabled ()) {
3147 tr->monitor_input (!config.get_auto_input());
3152 } else if (p == "punch-in") {
3156 if ((location = _locations.auto_punch_location()) != 0) {
3158 if (config.get_punch_in ()) {
3159 replace_event (SessionEvent::PunchIn, location->start());
3161 remove_event (location->start(), SessionEvent::PunchIn);
3165 } else if (p == "punch-out") {
3169 if ((location = _locations.auto_punch_location()) != 0) {
3171 if (config.get_punch_out()) {
3172 replace_event (SessionEvent::PunchOut, location->end());
3174 clear_events (SessionEvent::PunchOut);
3178 } else if (p == "edit-mode") {
3180 Glib::Mutex::Lock lm (playlists->lock);
3182 for (SessionPlaylists::List::iterator i = playlists->playlists.begin(); i != playlists->playlists.end(); ++i) {
3183 (*i)->set_edit_mode (Config->get_edit_mode ());
3186 } else if (p == "use-video-sync") {
3188 waiting_for_sync_offset = config.get_use_video_sync();
3190 } else if (p == "mmc-control") {
3192 //poke_midi_thread ();
3194 } else if (p == "mmc-device-id" || p == "mmc-receive-id") {
3196 _mmc->set_receive_device_id (Config->get_mmc_receive_device_id());
3198 } else if (p == "mmc-send-id") {
3200 _mmc->set_send_device_id (Config->get_mmc_send_device_id());
3202 } else if (p == "midi-control") {
3204 //poke_midi_thread ();
3206 } else if (p == "raid-path") {
3208 setup_raid_path (config.get_raid_path());
3210 } else if (p == "timecode-format") {
3214 } else if (p == "video-pullup") {
3218 } else if (p == "seamless-loop") {
3220 if (play_loop && transport_rolling()) {
3221 // to reset diskstreams etc
3222 request_play_loop (true);
3225 } else if (p == "rf-speed") {
3227 cumulative_rf_motion = 0;
3230 } else if (p == "click-sound") {
3232 setup_click_sounds (1);
3234 } else if (p == "click-emphasis-sound") {
3236 setup_click_sounds (-1);
3238 } else if (p == "clicking") {
3240 if (Config->get_clicking()) {
3241 if (_click_io && click_data) { // don't require emphasis data
3248 } else if (p == "send-mtc") {
3250 /* only set the internal flag if we have
3254 if (_mtc_port != 0) {
3255 session_send_mtc = Config->get_send_mtc();
3256 if (session_send_mtc) {
3257 /* mark us ready to send */
3258 next_quarter_frame_to_send = 0;
3261 session_send_mtc = false;
3264 } else if (p == "send-mmc") {
3266 _mmc->enable_send (Config->get_send_mmc ());
3268 } else if (p == "midi-feedback") {
3270 /* only set the internal flag if we have
3274 if (_mtc_port != 0) {
3275 session_midi_feedback = Config->get_midi_feedback();
3278 } else if (p == "jack-time-master") {
3280 engine().reset_timebase ();
3282 } else if (p == "native-file-header-format") {
3284 if (!first_file_header_format_reset) {
3285 reset_native_file_format ();
3288 first_file_header_format_reset = false;
3290 } else if (p == "native-file-data-format") {
3292 if (!first_file_data_format_reset) {
3293 reset_native_file_format ();
3296 first_file_data_format_reset = false;
3298 } else if (p == "external-sync") {
3299 if (!config.get_external_sync()) {
3300 drop_sync_source ();
3302 switch_to_sync_source (config.get_sync_source());
3304 } else if (p == "remote-model") {
3305 set_remote_control_ids ();
3306 } else if (p == "denormal-model") {
3308 } else if (p == "history-depth") {
3309 set_history_depth (Config->get_history_depth());
3310 } else if (p == "sync-all-route-ordering") {
3311 sync_order_keys ("session");
3312 } else if (p == "initial-program-change") {
3314 if (_mmc->port() && Config->get_initial_program_change() >= 0) {
3317 buf[0] = MIDI::program; // channel zero by default
3318 buf[1] = (Config->get_initial_program_change() & 0x7f);
3320 _mmc->port()->midimsg (buf, sizeof (buf), 0);
3322 } else if (p == "initial-program-change") {
3324 if (_mmc->port() && Config->get_initial_program_change() >= 0) {
3325 MIDI::byte* buf = new MIDI::byte[2];
3327 buf[0] = MIDI::program; // channel zero by default
3328 buf[1] = (Config->get_initial_program_change() & 0x7f);
3329 // deliver_midi (_mmc_port, buf, 2);
3331 } else if (p == "solo-mute-override") {
3332 // catch_up_on_solo_mute_override ();
3333 } else if (p == "listen-position") {
3334 listen_position_changed ();
3335 } else if (p == "solo-control-is-listen-control") {
3336 solo_control_mode_changed ();
3344 Session::set_history_depth (uint32_t d)
3346 _history.set_depth (d);
3350 Session::load_diskstreams_2X (XMLNode const & node, int)
3353 XMLNodeConstIterator citer;
3355 clist = node.children();
3357 for (citer = clist.begin(); citer != clist.end(); ++citer) {
3360 /* diskstreams added automatically by DiskstreamCreated handler */
3361 if ((*citer)->name() == "AudioDiskstream" || (*citer)->name() == "DiskStream") {
3362 boost::shared_ptr<AudioDiskstream> dsp (new AudioDiskstream (*this, **citer));
3363 _diskstreams_2X.push_back (dsp);
3365 error << _("Session: unknown diskstream type in XML") << endmsg;
3369 catch (failed_constructor& err) {
3370 error << _("Session: could not load diskstream via XML state") << endmsg;
3378 /** Create our MachineControl object and connect things to it */
3380 Session::setup_midi_machine_control ()
3382 _mmc = new MIDI::MachineControl;
3384 _mmc->Play.connect_same_thread (*this, boost::bind (&Session::mmc_deferred_play, this, _1));
3385 _mmc->DeferredPlay.connect_same_thread (*this, boost::bind (&Session::mmc_deferred_play, this, _1));
3386 _mmc->Stop.connect_same_thread (*this, boost::bind (&Session::mmc_stop, this, _1));
3387 _mmc->FastForward.connect_same_thread (*this, boost::bind (&Session::mmc_fast_forward, this, _1));
3388 _mmc->Rewind.connect_same_thread (*this, boost::bind (&Session::mmc_rewind, this, _1));
3389 _mmc->Pause.connect_same_thread (*this, boost::bind (&Session::mmc_pause, this, _1));
3390 _mmc->RecordPause.connect_same_thread (*this, boost::bind (&Session::mmc_record_pause, this, _1));
3391 _mmc->RecordStrobe.connect_same_thread (*this, boost::bind (&Session::mmc_record_strobe, this, _1));
3392 _mmc->RecordExit.connect_same_thread (*this, boost::bind (&Session::mmc_record_exit, this, _1));
3393 _mmc->Locate.connect_same_thread (*this, boost::bind (&Session::mmc_locate, this, _1, _2));
3394 _mmc->Step.connect_same_thread (*this, boost::bind (&Session::mmc_step, this, _1, _2));
3395 _mmc->Shuttle.connect_same_thread (*this, boost::bind (&Session::mmc_shuttle, this, _1, _2, _3));
3396 _mmc->TrackRecordStatusChange.connect_same_thread (*this, boost::bind (&Session::mmc_record_enable, this, _1, _2, _3));
3398 /* also handle MIDI SPP because its so common */
3400 _mmc->SPPStart.connect_same_thread (*this, boost::bind (&Session::spp_start, this, _1, _2));
3401 _mmc->SPPContinue.connect_same_thread (*this, boost::bind (&Session::spp_continue, this, _1, _2));
3402 _mmc->SPPStop.connect_same_thread (*this, boost::bind (&Session::spp_stop, this, _1, _2));