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"
68 #include "ardour/amp.h"
69 #include "ardour/audio_diskstream.h"
70 #include "ardour/audio_track.h"
71 #include "ardour/audioengine.h"
72 #include "ardour/audiofilesource.h"
73 #include "ardour/audioplaylist.h"
74 #include "ardour/audioregion.h"
75 #include "ardour/auditioner.h"
76 #include "ardour/buffer.h"
77 #include "ardour/butler.h"
78 #include "ardour/configuration.h"
79 #include "ardour/control_protocol_manager.h"
80 #include "ardour/crossfade.h"
81 #include "ardour/cycle_timer.h"
82 #include "ardour/directory_names.h"
83 #include "ardour/filename_extensions.h"
84 #include "ardour/io_processor.h"
85 #include "ardour/location.h"
86 #include "ardour/midi_diskstream.h"
87 #include "ardour/midi_patch_manager.h"
88 #include "ardour/midi_playlist.h"
89 #include "ardour/midi_region.h"
90 #include "ardour/midi_source.h"
91 #include "ardour/midi_track.h"
92 #include "ardour/named_selection.h"
93 #include "ardour/processor.h"
94 #include "ardour/region_factory.h"
95 #include "ardour/route_group.h"
96 #include "ardour/send.h"
97 #include "ardour/session.h"
98 #include "ardour/session_directory.h"
99 #include "ardour/session_metadata.h"
100 #include "ardour/session_state_utils.h"
101 #include "ardour/session_playlists.h"
102 #include "ardour/session_utils.h"
103 #include "ardour/silentfilesource.h"
104 #include "ardour/slave.h"
105 #include "ardour/smf_source.h"
106 #include "ardour/sndfile_helpers.h"
107 #include "ardour/sndfilesource.h"
108 #include "ardour/source_factory.h"
109 #include "ardour/template_utils.h"
110 #include "ardour/tempo.h"
111 #include "ardour/ticker.h"
112 #include "ardour/user_bundle.h"
113 #include "ardour/utils.h"
114 #include "ardour/utils.h"
115 #include "ardour/version.h"
116 #include "ardour/playlist_factory.h"
118 #include "control_protocol/control_protocol.h"
124 using namespace ARDOUR
;
128 Session::first_stage_init (string fullpath
, string snapshot_name
)
130 if (fullpath
.length() == 0) {
132 throw failed_constructor();
135 char buf
[PATH_MAX
+1];
136 if (!realpath (fullpath
.c_str(), buf
) && (errno
!= ENOENT
)) {
137 error
<< string_compose(_("Could not use path %1 (%s)"), buf
, strerror(errno
)) << endmsg
;
139 throw failed_constructor();
144 if (_path
[_path
.length()-1] != '/') {
148 if (Glib::file_test (_path
, Glib::FILE_TEST_EXISTS
) && ::access (_path
.c_str(), W_OK
)) {
154 /* these two are just provisional settings. set_state()
155 will likely override them.
158 _name
= _current_snapshot_name
= snapshot_name
;
160 set_history_depth (Config
->get_history_depth());
162 _current_frame_rate
= _engine
.frame_rate ();
163 _nominal_frame_rate
= _current_frame_rate
;
164 _base_frame_rate
= _current_frame_rate
;
166 _tempo_map
= new TempoMap (_current_frame_rate
);
167 _tempo_map
->StateChanged
.connect_same_thread (*this, boost::bind (&Session::tempo_map_changed
, this, _1
));
170 _non_soloed_outs_muted
= false;
172 g_atomic_int_set (&processing_prohibited
, 0);
173 _transport_speed
= 0;
174 _last_transport_speed
= 0;
175 _target_transport_speed
= 0;
176 auto_play_legal
= false;
177 transport_sub_state
= 0;
178 _transport_frame
= 0;
179 _requested_return_frame
= -1;
180 end_location
= new Location (0, 0, _("end"), Location::Flags ((Location::IsMark
|Location::IsEnd
)));
181 start_location
= new Location (0, 0, _("start"), Location::Flags ((Location::IsMark
|Location::IsStart
)));
182 g_atomic_int_set (&_record_status
, Disabled
);
183 loop_changing
= false;
186 _last_roll_location
= 0;
187 _last_record_location
= 0;
188 pending_locate_frame
= 0;
189 pending_locate_roll
= false;
190 pending_locate_flush
= false;
191 state_was_pending
= false;
193 outbound_mtc_timecode_frame
= 0;
194 next_quarter_frame_to_send
= -1;
195 current_block_size
= 0;
196 solo_update_disabled
= false;
197 _have_captured
= false;
198 _worst_output_latency
= 0;
199 _worst_input_latency
= 0;
200 _worst_track_latency
= 0;
201 _state_of_the_state
= StateOfTheState(CannotSave
|InitialConnecting
|Loading
);
202 _was_seamless
= Config
->get_seamless_loop ();
204 session_send_mmc
= false;
205 session_send_mtc
= false;
206 g_atomic_int_set (&_playback_load
, 100);
207 g_atomic_int_set (&_capture_load
, 100);
208 g_atomic_int_set (&_playback_load_min
, 100);
209 g_atomic_int_set (&_capture_load_min
, 100);
212 _gain_automation_buffer
= 0;
213 _pan_automation_buffer
= 0;
215 pending_abort
= false;
216 destructive_index
= 0;
217 first_file_data_format_reset
= true;
218 first_file_header_format_reset
= true;
219 post_export_sync
= false;
222 AudioDiskstream::allocate_working_buffers();
224 /* default short fade = 15ms */
226 Crossfade::set_short_xfade_length ((nframes_t
) floor (config
.get_short_xfade_seconds() * frame_rate()));
227 SndFileSource::setup_standard_crossfades (*this, frame_rate());
229 last_mmc_step
.tv_sec
= 0;
230 last_mmc_step
.tv_usec
= 0;
233 /* click sounds are unset by default, which causes us to internal
234 waveforms for clicks.
238 click_emphasis_length
= 0;
241 process_function
= &Session::process_with_events
;
243 if (config
.get_use_video_sync()) {
244 waiting_for_sync_offset
= true;
246 waiting_for_sync_offset
= false;
249 last_timecode_when
= 0;
250 _timecode_offset
= 0;
251 _timecode_offset_negative
= true;
252 last_timecode_valid
= false;
256 last_rr_session_dir
= session_dirs
.begin();
257 refresh_disk_space ();
259 // set_default_fade (0.2, 5.0); /* steepness, millisecs */
263 average_slave_delta
= 1800; // !!! why 1800 ????
264 have_first_delta_accumulator
= false;
265 delta_accumulator_cnt
= 0;
266 _slave_state
= Stopped
;
268 _engine
.GraphReordered
.connect_same_thread (*this, boost::bind (&Session::graph_reordered
, this));
270 /* These are all static "per-class" signals */
272 RegionFactory::CheckNewRegion
.connect_same_thread (*this, boost::bind (&Session::add_region
, this, _1
));
273 SourceFactory::SourceCreated
.connect_same_thread (*this, boost::bind (&Session::add_source
, this, _1
));
274 PlaylistFactory::PlaylistCreated
.connect_same_thread (*this, boost::bind (&Session::add_playlist
, this, _1
, _2
));
275 Processor::ProcessorCreated
.connect_same_thread (*this, boost::bind (&Session::add_processor
, this, _1
));
276 AutomationList::AutomationListCreated
.connect_same_thread (*this, boost::bind (&Session::add_automation_list
, this, _1
));
277 Controllable::Destroyed
.connect_same_thread (*this, boost::bind (&Session::remove_controllable
, this, _1
));
278 IO::PortCountChanged
.connect_same_thread (*this, boost::bind (&Session::ensure_buffers
, this, _1
));
280 /* stop IO objects from doing stuff until we're ready for them */
282 Delivery::disable_panners ();
283 IO::disable_connecting ();
287 Session::second_stage_init (bool new_session
)
289 AudioFileSource::set_peak_dir (_session_dir
->peak_path().to_string());
292 if (load_state (_current_snapshot_name
)) {
295 remove_empty_sounds ();
298 if (_butler
->start_thread()) {
302 if (start_midi_thread ()) {
306 // set_state() will call setup_raid_path(), but if it's a new session we need
307 // to call setup_raid_path() here.
310 if (set_state (*state_tree
->root(), Stateful::loading_state_version
)) {
314 setup_raid_path(_path
);
317 /* we can't save till after ::when_engine_running() is called,
318 because otherwise we save state with no connections made.
319 therefore, we reset _state_of_the_state because ::set_state()
320 will have cleared it.
322 we also have to include Loading so that any events that get
323 generated between here and the end of ::when_engine_running()
324 will be processed directly rather than queued.
327 _state_of_the_state
= StateOfTheState (_state_of_the_state
|CannotSave
|Loading
);
330 _locations
.changed
.connect_same_thread (*this, boost::bind (&Session::locations_changed
, this));
331 _locations
.added
.connect_same_thread (*this, boost::bind (&Session::locations_added
, this, _1
));
332 setup_click_sounds (0);
333 setup_midi_control ();
335 /* Pay attention ... */
337 _engine
.Halted
.connect_same_thread (*this, boost::bind (&Session::engine_halted
, this));
338 _engine
.Xrun
.connect_same_thread (*this, boost::bind (&Session::xrun_recovery
, this));
341 when_engine_running();
344 /* handle this one in a different way than all others, so that its clear what happened */
346 catch (AudioEngine::PortRegistrationFailure
& err
) {
347 error
<< err
.what() << endmsg
;
355 BootMessage (_("Reset Remote Controls"));
357 send_full_time_code (0);
358 _engine
.transport_locate (0);
359 deliver_mmc (MIDI::MachineControl::cmdMmcReset
, 0);
360 deliver_mmc (MIDI::MachineControl::cmdLocate
, 0);
362 MidiClockTicker::instance().set_session (this);
363 MIDI::Name::MidiPatchManager::instance().set_session (this);
365 /* initial program change will be delivered later; see ::config_changed() */
367 BootMessage (_("Reset Control Protocols"));
369 ControlProtocolManager::instance().set_session (this);
371 config
.set_end_marker_is_free (new_session
);
373 _state_of_the_state
= Clean
;
375 DirtyChanged (); /* EMIT SIGNAL */
377 if (state_was_pending
) {
378 save_state (_current_snapshot_name
);
379 remove_pending_capture_state ();
380 state_was_pending
= false;
383 BootMessage (_("Session loading complete"));
389 Session::raid_path () const
391 SearchPath raid_search_path
;
393 for (vector
<space_and_path
>::const_iterator i
= session_dirs
.begin(); i
!= session_dirs
.end(); ++i
) {
394 raid_search_path
+= sys::path((*i
).path
);
397 return raid_search_path
.to_string ();
401 Session::setup_raid_path (string path
)
410 session_dirs
.clear ();
412 SearchPath
search_path(path
);
413 SearchPath sound_search_path
;
414 SearchPath midi_search_path
;
416 for (SearchPath::const_iterator i
= search_path
.begin(); i
!= search_path
.end(); ++i
) {
417 sp
.path
= (*i
).to_string ();
418 sp
.blocks
= 0; // not needed
419 session_dirs
.push_back (sp
);
421 SessionDirectory
sdir(sp
.path
);
423 sound_search_path
+= sdir
.sound_path ();
424 midi_search_path
+= sdir
.midi_path ();
427 // set the search path for each data type
428 FileSource::set_search_path (DataType::AUDIO
, sound_search_path
.to_string ());
429 SMFSource::set_search_path (DataType::MIDI
, midi_search_path
.to_string ());
431 // reset the round-robin soundfile path thingie
432 last_rr_session_dir
= session_dirs
.begin();
436 Session::path_is_within_session (const std::string
& path
)
438 for (vector
<space_and_path
>::const_iterator i
= session_dirs
.begin(); i
!= session_dirs
.end(); ++i
) {
439 if (path
.find ((*i
).path
) == 0) {
447 Session::ensure_subdirs ()
451 dir
= session_directory().peak_path().to_string();
453 if (g_mkdir_with_parents (dir
.c_str(), 0755) < 0) {
454 error
<< string_compose(_("Session: cannot create session peakfile folder \"%1\" (%2)"), dir
, strerror (errno
)) << endmsg
;
458 dir
= session_directory().sound_path().to_string();
460 if (g_mkdir_with_parents (dir
.c_str(), 0755) < 0) {
461 error
<< string_compose(_("Session: cannot create session sounds dir \"%1\" (%2)"), dir
, strerror (errno
)) << endmsg
;
465 dir
= session_directory().midi_path().to_string();
467 if (g_mkdir_with_parents (dir
.c_str(), 0755) < 0) {
468 error
<< string_compose(_("Session: cannot create session midi dir \"%1\" (%2)"), dir
, strerror (errno
)) << endmsg
;
472 dir
= session_directory().dead_sound_path().to_string();
474 if (g_mkdir_with_parents (dir
.c_str(), 0755) < 0) {
475 error
<< string_compose(_("Session: cannot create session dead sounds folder \"%1\" (%2)"), dir
, strerror (errno
)) << endmsg
;
479 dir
= session_directory().export_path().to_string();
481 if (g_mkdir_with_parents (dir
.c_str(), 0755) < 0) {
482 error
<< string_compose(_("Session: cannot create session export folder \"%1\" (%2)"), dir
, strerror (errno
)) << endmsg
;
486 dir
= analysis_dir ();
488 if (g_mkdir_with_parents (dir
.c_str(), 0755) < 0) {
489 error
<< string_compose(_("Session: cannot create session analysis folder \"%1\" (%2)"), dir
, strerror (errno
)) << endmsg
;
497 Session::create (bool& new_session
, const string
& mix_template
, nframes_t initial_length
)
500 if (g_mkdir_with_parents (_path
.c_str(), 0755) < 0) {
501 error
<< string_compose(_("Session: cannot create session folder \"%1\" (%2)"), _path
, strerror (errno
)) << endmsg
;
505 if (ensure_subdirs ()) {
509 /* check new_session so we don't overwrite an existing one */
511 if (!mix_template
.empty()) {
512 std::string in_path
= mix_template
;
514 ifstream
in(in_path
.c_str());
517 string out_path
= _path
;
519 out_path
+= statefile_suffix
;
521 ofstream
out(out_path
.c_str());
526 // okay, session is set up. Treat like normal saved
527 // session from now on.
533 error
<< string_compose (_("Could not open %1 for writing mix template"), out_path
)
539 error
<< string_compose (_("Could not open mix template %1 for reading"), in_path
)
546 /* Instantiate metadata */
548 _metadata
= new SessionMetadata ();
550 /* set initial start + end point */
552 start_location
->set_end (0);
553 _locations
.add (start_location
);
555 end_location
->set_end (initial_length
);
556 _locations
.add (end_location
);
558 _state_of_the_state
= Clean
;
567 Session::load_diskstreams (const XMLNode
& node
)
570 XMLNodeConstIterator citer
;
572 clist
= node
.children();
574 for (citer
= clist
.begin(); citer
!= clist
.end(); ++citer
) {
577 /* diskstreams added automatically by DiskstreamCreated handler */
578 if ((*citer
)->name() == "AudioDiskstream" || (*citer
)->name() == "DiskStream") {
579 AudioDiskstream
* dsp (new AudioDiskstream (*this, **citer
));
580 boost::shared_ptr
<AudioDiskstream
> dstream (dsp
);
581 add_diskstream (dstream
);
582 } else if ((*citer
)->name() == "MidiDiskstream") {
583 boost::shared_ptr
<MidiDiskstream
> dstream (new MidiDiskstream (*this, **citer
));
584 add_diskstream (dstream
);
586 error
<< _("Session: unknown diskstream type in XML") << endmsg
;
590 catch (failed_constructor
& err
) {
591 error
<< _("Session: could not load diskstream via XML state") << endmsg
;
600 Session::maybe_write_autosave()
602 if (dirty() && record_status() != Recording
) {
603 save_state("", true);
608 Session::remove_pending_capture_state ()
610 sys::path
pending_state_file_path(_session_dir
->root_path());
612 pending_state_file_path
/= legalize_for_path (_current_snapshot_name
) + pending_suffix
;
616 sys::remove (pending_state_file_path
);
618 catch(sys::filesystem_error
& ex
)
620 error
<< string_compose(_("Could remove pending capture state at path \"%1\" (%2)"),
621 pending_state_file_path
.to_string(), ex
.what()) << endmsg
;
625 /** Rename a state file.
626 * @param snapshot_name Snapshot name.
629 Session::rename_state (string old_name
, string new_name
)
631 if (old_name
== _current_snapshot_name
|| old_name
== _name
) {
632 /* refuse to rename the current snapshot or the "main" one */
636 const string old_xml_filename
= legalize_for_path (old_name
) + statefile_suffix
;
637 const string new_xml_filename
= legalize_for_path (new_name
) + statefile_suffix
;
639 const sys::path old_xml_path
= _session_dir
->root_path() / old_xml_filename
;
640 const sys::path new_xml_path
= _session_dir
->root_path() / new_xml_filename
;
644 sys::rename (old_xml_path
, new_xml_path
);
646 catch (const sys::filesystem_error
& err
)
648 error
<< string_compose(_("could not rename snapshot %1 to %2 (%3)"),
649 old_name
, new_name
, err
.what()) << endmsg
;
653 /** Remove a state file.
654 * @param snapshot_name Snapshot name.
657 Session::remove_state (string snapshot_name
)
659 if (snapshot_name
== _current_snapshot_name
|| snapshot_name
== _name
) {
660 // refuse to remove the current snapshot or the "main" one
664 sys::path
xml_path(_session_dir
->root_path());
666 xml_path
/= legalize_for_path (snapshot_name
) + statefile_suffix
;
668 if (!create_backup_file (xml_path
)) {
669 // don't remove it if a backup can't be made
670 // create_backup_file will log the error.
675 sys::remove (xml_path
);
679 Session::save_state (string snapshot_name
, bool pending
)
682 sys::path
xml_path(_session_dir
->root_path());
684 if (!_writable
|| (_state_of_the_state
& CannotSave
)) {
688 if (!_engine
.connected ()) {
689 error
<< _("Ardour's audio engine is not connected and state saving would lose all I/O connections. Session not saved")
694 /* tell sources we're saving first, in case they write out to a new file
695 * which should be saved with the state rather than the old one */
696 for (SourceMap::const_iterator i
= sources
.begin(); i
!= sources
.end(); ++i
)
697 i
->second
->session_saved();
699 tree
.set_root (&get_state());
701 if (snapshot_name
.empty()) {
702 snapshot_name
= _current_snapshot_name
;
707 /* proper save: use statefile_suffix (.ardour in English) */
709 xml_path
/= legalize_for_path (snapshot_name
) + statefile_suffix
;
711 /* make a backup copy of the old file */
713 if (sys::exists(xml_path
) && !create_backup_file (xml_path
)) {
714 // create_backup_file will log the error
720 /* pending save: use pending_suffix (.pending in English) */
721 xml_path
/= legalize_for_path (snapshot_name
) + pending_suffix
;
724 sys::path
tmp_path(_session_dir
->root_path());
726 tmp_path
/= legalize_for_path (snapshot_name
) + temp_suffix
;
728 // cerr << "actually writing state to " << xml_path.to_string() << endl;
730 if (!tree
.write (tmp_path
.to_string())) {
731 error
<< string_compose (_("state could not be saved to %1"), tmp_path
.to_string()) << endmsg
;
732 sys::remove (tmp_path
);
737 if (rename (tmp_path
.to_string().c_str(), xml_path
.to_string().c_str()) != 0) {
738 error
<< string_compose (_("could not rename temporary session file %1 to %2"),
739 tmp_path
.to_string(), xml_path
.to_string()) << endmsg
;
740 sys::remove (tmp_path
);
747 save_history (snapshot_name
);
749 bool was_dirty
= dirty();
751 _state_of_the_state
= StateOfTheState (_state_of_the_state
& ~Dirty
);
754 DirtyChanged (); /* EMIT SIGNAL */
757 StateSaved (snapshot_name
); /* EMIT SIGNAL */
764 Session::restore_state (string snapshot_name
)
766 if (load_state (snapshot_name
) == 0) {
767 set_state (*state_tree
->root(), Stateful::loading_state_version
);
774 Session::load_state (string snapshot_name
)
779 state_was_pending
= false;
781 /* check for leftover pending state from a crashed capture attempt */
783 sys::path
xmlpath(_session_dir
->root_path());
784 xmlpath
/= legalize_for_path (snapshot_name
) + pending_suffix
;
786 if (sys::exists (xmlpath
)) {
788 /* there is pending state from a crashed capture attempt */
790 if (*AskAboutPendingState()) {
791 state_was_pending
= true;
795 if (!state_was_pending
) {
796 xmlpath
= _session_dir
->root_path();
797 xmlpath
/= legalize_for_path (snapshot_name
) + statefile_suffix
;
800 if (!sys::exists (xmlpath
)) {
801 error
<< string_compose(_("%1: session state information file \"%2\" doesn't exist!"), _name
, xmlpath
.to_string()) << endmsg
;
805 state_tree
= new XMLTree
;
809 /* writable() really reflects the whole folder, but if for any
810 reason the session state file can't be written to, still
814 if (::access (xmlpath
.to_string().c_str(), W_OK
) != 0) {
818 if (!state_tree
->read (xmlpath
.to_string())) {
819 error
<< string_compose(_("Could not understand ardour file %1"), xmlpath
.to_string()) << endmsg
;
825 XMLNode
& root (*state_tree
->root());
827 if (root
.name() != X_("Session")) {
828 error
<< string_compose (_("Session file %1 is not an Ardour session"), xmlpath
.to_string()) << endmsg
;
834 const XMLProperty
* prop
;
836 if ((prop
= root
.property ("version")) == 0) {
837 /* no version implies very old version of Ardour */
838 Stateful::loading_state_version
= 1000;
844 sscanf (prop
->value().c_str(), "%d.%d.%d", &major
, &minor
, µ
);
845 Stateful::loading_state_version
= (major
* 1000) + minor
;
848 if (Stateful::loading_state_version
< CURRENT_SESSION_FILE_VERSION
) {
850 sys::path
backup_path(_session_dir
->root_path());
852 backup_path
/= legalize_for_path (snapshot_name
) + "-1" + statefile_suffix
;
854 // only create a backup once
855 if (sys::exists (backup_path
)) {
859 info
<< string_compose (_("Copying old session file %1 to %2\nUse %2 with Ardour versions before 2.0 from now on"),
860 xmlpath
.to_string(), backup_path
.to_string())
865 sys::copy_file (xmlpath
, backup_path
);
867 catch(sys::filesystem_error
& ex
)
869 error
<< string_compose (_("Unable to make backup of state file %1 (%2)"),
870 xmlpath
.to_string(), ex
.what())
880 Session::load_options (const XMLNode
& node
)
882 LocaleGuard
lg (X_("POSIX"));
883 config
.set_variables (node
);
894 Session::get_template()
896 /* if we don't disable rec-enable, diskstreams
897 will believe they need to store their capture
898 sources in their state node.
901 disable_record (false);
907 Session::state(bool full_state
)
909 XMLNode
* node
= new XMLNode("Session");
912 // store libardour version, just in case
914 snprintf(buf
, sizeof(buf
), "%d.%d.%d", libardour3_major_version
, libardour3_minor_version
, libardour3_micro_version
);
915 node
->add_property("version", string(buf
));
917 /* store configuration settings */
921 node
->add_property ("name", _name
);
922 snprintf (buf
, sizeof (buf
), "%" PRId32
, _nominal_frame_rate
);
923 node
->add_property ("sample-rate", buf
);
925 if (session_dirs
.size() > 1) {
929 vector
<space_and_path
>::iterator i
= session_dirs
.begin();
930 vector
<space_and_path
>::iterator next
;
932 ++i
; /* skip the first one */
936 while (i
!= session_dirs
.end()) {
940 if (next
!= session_dirs
.end()) {
950 child
= node
->add_child ("Path");
951 child
->add_content (p
);
955 /* save the ID counter */
957 snprintf (buf
, sizeof (buf
), "%" PRIu64
, ID::counter());
958 node
->add_property ("id-counter", buf
);
960 /* various options */
962 node
->add_child_nocopy (config
.get_variables ());
964 node
->add_child_nocopy (_metadata
->get_state());
966 child
= node
->add_child ("Sources");
969 Glib::Mutex::Lock
sl (source_lock
);
971 for (SourceMap::iterator siter
= sources
.begin(); siter
!= sources
.end(); ++siter
) {
973 /* Don't save information about non-destructive file sources that are empty */
974 /* FIXME: MIDI breaks if this is made FileSource like it should be... */
976 boost::shared_ptr
<AudioFileSource
> fs
;
977 if ((fs
= boost::dynamic_pointer_cast
<AudioFileSource
> (siter
->second
)) != 0) {
978 if (!fs
->destructive()) {
979 if (fs
->length(fs
->timeline_position()) == 0) {
985 child
->add_child_nocopy (siter
->second
->get_state());
989 child
= node
->add_child ("Regions");
992 Glib::Mutex::Lock
rl (region_lock
);
994 for (RegionList::const_iterator i
= regions
.begin(); i
!= regions
.end(); ++i
) {
996 /* only store regions not attached to playlists */
998 if (i
->second
->playlist() == 0) {
999 child
->add_child_nocopy (i
->second
->state (true));
1004 child
= node
->add_child ("DiskStreams");
1007 boost::shared_ptr
<DiskstreamList
> dsl
= diskstreams
.reader();
1008 for (DiskstreamList::iterator i
= dsl
->begin(); i
!= dsl
->end(); ++i
) {
1009 if (!(*i
)->hidden()) {
1010 child
->add_child_nocopy ((*i
)->get_state());
1016 node
->add_child_nocopy (_locations
.get_state());
1018 // for a template, just create a new Locations, populate it
1019 // with the default start and end, and get the state for that.
1021 Location
* start
= new Location(0, 0, _("start"), Location::Flags ((Location::IsMark
|Location::IsStart
)));
1022 Location
* end
= new Location(0, 0, _("end"), Location::Flags ((Location::IsMark
|Location::IsEnd
)));
1025 end
->set_end(compute_initial_length());
1027 node
->add_child_nocopy (loc
.get_state());
1030 child
= node
->add_child ("Bundles");
1032 boost::shared_ptr
<BundleList
> bundles
= _bundles
.reader ();
1033 for (BundleList::iterator i
= bundles
->begin(); i
!= bundles
->end(); ++i
) {
1034 boost::shared_ptr
<UserBundle
> b
= boost::dynamic_pointer_cast
<UserBundle
> (*i
);
1036 child
->add_child_nocopy (b
->get_state());
1041 child
= node
->add_child ("Routes");
1043 boost::shared_ptr
<RouteList
> r
= routes
.reader ();
1045 RoutePublicOrderSorter cmp
;
1046 RouteList
public_order (*r
);
1047 public_order
.sort (cmp
);
1049 for (RouteList::iterator i
= public_order
.begin(); i
!= public_order
.end(); ++i
) {
1050 if (!(*i
)->is_hidden()) {
1052 child
->add_child_nocopy ((*i
)->get_state());
1054 child
->add_child_nocopy ((*i
)->get_template());
1060 playlists
->add_state (node
, full_state
);
1062 child
= node
->add_child ("RouteGroups");
1063 for (list
<RouteGroup
*>::iterator i
= _route_groups
.begin(); i
!= _route_groups
.end(); ++i
) {
1064 child
->add_child_nocopy ((*i
)->get_state());
1068 child
= node
->add_child ("Click");
1069 child
->add_child_nocopy (_click_io
->state (full_state
));
1073 child
= node
->add_child ("NamedSelections");
1074 for (NamedSelectionList::iterator i
= named_selections
.begin(); i
!= named_selections
.end(); ++i
) {
1076 child
->add_child_nocopy ((*i
)->get_state());
1081 node
->add_child_nocopy (_tempo_map
->get_state());
1083 node
->add_child_nocopy (get_control_protocol_state());
1086 node
->add_child_copy (*_extra_xml
);
1093 Session::get_control_protocol_state ()
1095 ControlProtocolManager
& cpm (ControlProtocolManager::instance());
1096 return cpm
.get_state();
1100 Session::set_state (const XMLNode
& node
, int version
)
1104 const XMLProperty
* prop
;
1107 _state_of_the_state
= StateOfTheState (_state_of_the_state
|CannotSave
);
1109 if (node
.name() != X_("Session")){
1110 fatal
<< _("programming error: Session: incorrect XML node sent to set_state()") << endmsg
;
1114 if ((prop
= node
.property ("version")) != 0) {
1115 version
= atoi (prop
->value ()) * 1000;
1118 if ((prop
= node
.property ("name")) != 0) {
1119 _name
= prop
->value ();
1122 if ((prop
= node
.property (X_("sample-rate"))) != 0) {
1124 _nominal_frame_rate
= atoi (prop
->value());
1126 if (_nominal_frame_rate
!= _current_frame_rate
) {
1127 if (*AskAboutSampleRateMismatch (_nominal_frame_rate
, _current_frame_rate
)) {
1133 setup_raid_path(_session_dir
->root_path().to_string());
1135 if ((prop
= node
.property (X_("id-counter"))) != 0) {
1137 sscanf (prop
->value().c_str(), "%" PRIu64
, &x
);
1138 ID::init_counter (x
);
1140 /* old sessions used a timebased counter, so fake
1141 the startup ID counter based on a standard
1146 ID::init_counter (now
);
1150 IO::disable_connecting ();
1152 /* Object loading order:
1157 MIDI Control // relies on data from Options/Config
1171 if ((child
= find_named_node (node
, "Extra")) != 0) {
1172 _extra_xml
= new XMLNode (*child
);
1175 if (((child
= find_named_node (node
, "Options")) != 0)) { /* old style */
1176 load_options (*child
);
1177 } else if ((child
= find_named_node (node
, "Config")) != 0) { /* new style */
1178 load_options (*child
);
1180 error
<< _("Session: XML state has no options section") << endmsg
;
1183 if (use_config_midi_ports ()) {
1186 if (version
>= 3000) {
1187 if ((child
= find_named_node (node
, "Metadata")) == 0) {
1188 warning
<< _("Session: XML state has no metadata section") << endmsg
;
1189 } else if (_metadata
->set_state (*child
, version
)) {
1194 if ((child
= find_named_node (node
, "Locations")) == 0) {
1195 error
<< _("Session: XML state has no locations section") << endmsg
;
1197 } else if (_locations
.set_state (*child
, version
)) {
1203 if ((location
= _locations
.auto_loop_location()) != 0) {
1204 set_auto_loop_location (location
);
1207 if ((location
= _locations
.auto_punch_location()) != 0) {
1208 set_auto_punch_location (location
);
1211 if ((location
= _locations
.end_location()) == 0) {
1212 _locations
.add (end_location
);
1214 delete end_location
;
1215 end_location
= location
;
1218 if ((location
= _locations
.start_location()) == 0) {
1219 _locations
.add (start_location
);
1221 delete start_location
;
1222 start_location
= location
;
1225 AudioFileSource::set_header_position_offset (start_location
->start());
1227 if ((child
= find_named_node (node
, "Sources")) == 0) {
1228 error
<< _("Session: XML state has no sources section") << endmsg
;
1230 } else if (load_sources (*child
)) {
1234 if ((child
= find_named_node (node
, "Regions")) == 0) {
1235 error
<< _("Session: XML state has no Regions section") << endmsg
;
1237 } else if (load_regions (*child
)) {
1241 if ((child
= find_named_node (node
, "Playlists")) == 0) {
1242 error
<< _("Session: XML state has no playlists section") << endmsg
;
1244 } else if (playlists
->load (*this, *child
)) {
1248 if ((child
= find_named_node (node
, "UnusedPlaylists")) == 0) {
1250 } else if (playlists
->load_unused (*this, *child
)) {
1254 if ((child
= find_named_node (node
, "NamedSelections")) != 0) {
1255 if (load_named_selections (*child
)) {
1260 if ((child
= find_named_node (node
, "DiskStreams")) == 0) {
1261 error
<< _("Session: XML state has no diskstreams section") << endmsg
;
1263 } else if (load_diskstreams (*child
)) {
1267 if (version
>= 3000) {
1268 if ((child
= find_named_node (node
, "Bundles")) == 0) {
1269 warning
<< _("Session: XML state has no bundles section") << endmsg
;
1272 /* We can't load Bundles yet as they need to be able
1273 to convert from port names to Port objects, which can't happen until
1275 _bundle_xml_node
= new XMLNode (*child
);
1279 if ((child
= find_named_node (node
, "TempoMap")) == 0) {
1280 error
<< _("Session: XML state has no Tempo Map section") << endmsg
;
1282 } else if (_tempo_map
->set_state (*child
, version
)) {
1286 if ((child
= find_named_node (node
, "Routes")) == 0) {
1287 error
<< _("Session: XML state has no routes section") << endmsg
;
1289 } else if (load_routes (*child
, version
)) {
1293 if (version
>= 3000) {
1295 if ((child
= find_named_node (node
, "RouteGroups")) == 0) {
1296 error
<< _("Session: XML state has no route groups section") << endmsg
;
1298 } else if (load_route_groups (*child
, version
)) {
1302 } else if (version
< 3000) {
1304 if ((child
= find_named_node (node
, "EditGroups")) == 0) {
1305 error
<< _("Session: XML state has no edit groups section") << endmsg
;
1307 } else if (load_route_groups (*child
, version
)) {
1311 if ((child
= find_named_node (node
, "MixGroups")) == 0) {
1312 error
<< _("Session: XML state has no mix groups section") << endmsg
;
1314 } else if (load_route_groups (*child
, version
)) {
1319 if ((child
= find_named_node (node
, "Click")) == 0) {
1320 warning
<< _("Session: XML state has no click section") << endmsg
;
1321 } else if (_click_io
) {
1322 _click_io
->set_state (*child
, version
);
1325 if ((child
= find_named_node (node
, "ControlProtocols")) != 0) {
1326 ControlProtocolManager::instance().set_protocol_states (*child
);
1329 /* here beginneth the second phase ... */
1331 StateReady (); /* EMIT SIGNAL */
1340 Session::load_routes (const XMLNode
& node
, int version
)
1343 XMLNodeConstIterator niter
;
1344 RouteList new_routes
;
1346 nlist
= node
.children();
1350 for (niter
= nlist
.begin(); niter
!= nlist
.end(); ++niter
) {
1352 boost::shared_ptr
<Route
> route (XMLRouteFactory (**niter
, version
));
1355 error
<< _("Session: cannot create Route from XML description.") << endmsg
;
1359 BootMessage (string_compose (_("Loaded track/bus %1"), route
->name()));
1361 new_routes
.push_back (route
);
1364 add_routes (new_routes
, false);
1369 boost::shared_ptr
<Route
>
1370 Session::XMLRouteFactory (const XMLNode
& node
, int version
)
1372 if (node
.name() != "Route") {
1373 return boost::shared_ptr
<Route
> ((Route
*) 0);
1376 bool has_diskstream
= (node
.property ("diskstream") != 0 || node
.property ("diskstream-id") != 0);
1378 DataType type
= DataType::AUDIO
;
1379 const XMLProperty
* prop
= node
.property("default-type");
1380 boost::shared_ptr
<Route
> ret
;
1383 type
= DataType(prop
->value());
1386 assert(type
!= DataType::NIL
);
1388 if (has_diskstream
) {
1389 if (type
== DataType::AUDIO
) {
1390 AudioTrack
* at
= new AudioTrack (*this, node
, version
);
1391 boost_debug_shared_ptr_mark_interesting (at
, "Track");
1395 ret
.reset (new MidiTrack (*this, node
, version
));
1398 Route
* rt
= new Route (*this, node
);
1399 boost_debug_shared_ptr_mark_interesting (rt
, "Route");
1407 Session::load_regions (const XMLNode
& node
)
1410 XMLNodeConstIterator niter
;
1411 boost::shared_ptr
<Region
> region
;
1413 nlist
= node
.children();
1417 for (niter
= nlist
.begin(); niter
!= nlist
.end(); ++niter
) {
1418 if ((region
= XMLRegionFactory (**niter
, false)) == 0) {
1419 error
<< _("Session: cannot create Region from XML description.");
1420 const XMLProperty
*name
= (**niter
).property("name");
1423 error
<< " " << string_compose (_("Can not load state for region '%1'"), name
->value());
1433 boost::shared_ptr
<Region
>
1434 Session::XMLRegionFactory (const XMLNode
& node
, bool full
)
1436 const XMLProperty
* type
= node
.property("type");
1440 if ( !type
|| type
->value() == "audio" ) {
1442 return boost::shared_ptr
<Region
>(XMLAudioRegionFactory (node
, full
));
1444 } else if (type
->value() == "midi") {
1446 return boost::shared_ptr
<Region
>(XMLMidiRegionFactory (node
, full
));
1450 } catch (failed_constructor
& err
) {
1451 return boost::shared_ptr
<Region
> ();
1454 return boost::shared_ptr
<Region
> ();
1457 boost::shared_ptr
<AudioRegion
>
1458 Session::XMLAudioRegionFactory (const XMLNode
& node
, bool /*full*/)
1460 const XMLProperty
* prop
;
1461 boost::shared_ptr
<Source
> source
;
1462 boost::shared_ptr
<AudioSource
> as
;
1464 SourceList master_sources
;
1465 uint32_t nchans
= 1;
1468 if (node
.name() != X_("Region")) {
1469 return boost::shared_ptr
<AudioRegion
>();
1472 if ((prop
= node
.property (X_("channels"))) != 0) {
1473 nchans
= atoi (prop
->value().c_str());
1476 if ((prop
= node
.property ("name")) == 0) {
1477 cerr
<< "no name for this region\n";
1481 if ((prop
= node
.property (X_("source-0"))) == 0) {
1482 if ((prop
= node
.property ("source")) == 0) {
1483 error
<< _("Session: XMLNode describing a AudioRegion is incomplete (no source)") << endmsg
;
1484 return boost::shared_ptr
<AudioRegion
>();
1488 PBD::ID
s_id (prop
->value());
1490 if ((source
= source_by_id (s_id
)) == 0) {
1491 error
<< string_compose(_("Session: XMLNode describing a AudioRegion references an unknown source id =%1"), s_id
) << endmsg
;
1492 return boost::shared_ptr
<AudioRegion
>();
1495 as
= boost::dynamic_pointer_cast
<AudioSource
>(source
);
1497 error
<< string_compose(_("Session: XMLNode describing a AudioRegion references a non-audio source id =%1"), s_id
) << endmsg
;
1498 return boost::shared_ptr
<AudioRegion
>();
1501 sources
.push_back (as
);
1503 /* pickup other channels */
1505 for (uint32_t n
=1; n
< nchans
; ++n
) {
1506 snprintf (buf
, sizeof(buf
), X_("source-%d"), n
);
1507 if ((prop
= node
.property (buf
)) != 0) {
1509 PBD::ID
id2 (prop
->value());
1511 if ((source
= source_by_id (id2
)) == 0) {
1512 error
<< string_compose(_("Session: XMLNode describing a AudioRegion references an unknown source id =%1"), id2
) << endmsg
;
1513 return boost::shared_ptr
<AudioRegion
>();
1516 as
= boost::dynamic_pointer_cast
<AudioSource
>(source
);
1518 error
<< string_compose(_("Session: XMLNode describing a AudioRegion references a non-audio source id =%1"), id2
) << endmsg
;
1519 return boost::shared_ptr
<AudioRegion
>();
1521 sources
.push_back (as
);
1525 for (uint32_t n
= 0; n
< nchans
; ++n
) {
1526 snprintf (buf
, sizeof(buf
), X_("master-source-%d"), n
);
1527 if ((prop
= node
.property (buf
)) != 0) {
1529 PBD::ID
id2 (prop
->value());
1531 if ((source
= source_by_id (id2
)) == 0) {
1532 error
<< string_compose(_("Session: XMLNode describing a AudioRegion references an unknown source id =%1"), id2
) << endmsg
;
1533 return boost::shared_ptr
<AudioRegion
>();
1536 as
= boost::dynamic_pointer_cast
<AudioSource
>(source
);
1538 error
<< string_compose(_("Session: XMLNode describing a AudioRegion references a non-audio source id =%1"), id2
) << endmsg
;
1539 return boost::shared_ptr
<AudioRegion
>();
1541 master_sources
.push_back (as
);
1546 boost::shared_ptr
<AudioRegion
> region (boost::dynamic_pointer_cast
<AudioRegion
> (RegionFactory::create (sources
, node
)));
1548 /* a final detail: this is the one and only place that we know how long missing files are */
1550 if (region
->whole_file()) {
1551 for (SourceList::iterator sx
= sources
.begin(); sx
!= sources
.end(); ++sx
) {
1552 boost::shared_ptr
<SilentFileSource
> sfp
= boost::dynamic_pointer_cast
<SilentFileSource
> (*sx
);
1554 sfp
->set_length (region
->length());
1559 if (!master_sources
.empty()) {
1560 if (master_sources
.size() != nchans
) {
1561 error
<< _("Session: XMLNode describing an AudioRegion is missing some master sources; ignored") << endmsg
;
1563 region
->set_master_sources (master_sources
);
1571 catch (failed_constructor
& err
) {
1572 return boost::shared_ptr
<AudioRegion
>();
1576 boost::shared_ptr
<MidiRegion
>
1577 Session::XMLMidiRegionFactory (const XMLNode
& node
, bool /*full*/)
1579 const XMLProperty
* prop
;
1580 boost::shared_ptr
<Source
> source
;
1581 boost::shared_ptr
<MidiSource
> ms
;
1583 uint32_t nchans
= 1;
1585 if (node
.name() != X_("Region")) {
1586 return boost::shared_ptr
<MidiRegion
>();
1589 if ((prop
= node
.property (X_("channels"))) != 0) {
1590 nchans
= atoi (prop
->value().c_str());
1593 if ((prop
= node
.property ("name")) == 0) {
1594 cerr
<< "no name for this region\n";
1598 // Multiple midi channels? that's just crazy talk
1599 assert(nchans
== 1);
1601 if ((prop
= node
.property (X_("source-0"))) == 0) {
1602 if ((prop
= node
.property ("source")) == 0) {
1603 error
<< _("Session: XMLNode describing a MidiRegion is incomplete (no source)") << endmsg
;
1604 return boost::shared_ptr
<MidiRegion
>();
1608 PBD::ID
s_id (prop
->value());
1610 if ((source
= source_by_id (s_id
)) == 0) {
1611 error
<< string_compose(_("Session: XMLNode describing a MidiRegion references an unknown source id =%1"), s_id
) << endmsg
;
1612 return boost::shared_ptr
<MidiRegion
>();
1615 ms
= boost::dynamic_pointer_cast
<MidiSource
>(source
);
1617 error
<< string_compose(_("Session: XMLNode describing a MidiRegion references a non-midi source id =%1"), s_id
) << endmsg
;
1618 return boost::shared_ptr
<MidiRegion
>();
1621 sources
.push_back (ms
);
1624 boost::shared_ptr
<MidiRegion
> region (boost::dynamic_pointer_cast
<MidiRegion
> (RegionFactory::create (sources
, node
)));
1625 /* a final detail: this is the one and only place that we know how long missing files are */
1627 if (region
->whole_file()) {
1628 for (SourceList::iterator sx
= sources
.begin(); sx
!= sources
.end(); ++sx
) {
1629 boost::shared_ptr
<SilentFileSource
> sfp
= boost::dynamic_pointer_cast
<SilentFileSource
> (*sx
);
1631 sfp
->set_length (region
->length());
1639 catch (failed_constructor
& err
) {
1640 return boost::shared_ptr
<MidiRegion
>();
1645 Session::get_sources_as_xml ()
1648 XMLNode
* node
= new XMLNode (X_("Sources"));
1649 Glib::Mutex::Lock
lm (source_lock
);
1651 for (SourceMap::iterator i
= sources
.begin(); i
!= sources
.end(); ++i
) {
1652 node
->add_child_nocopy (i
->second
->get_state());
1659 Session::path_from_region_name (DataType type
, string name
, string identifier
)
1661 char buf
[PATH_MAX
+1];
1663 SessionDirectory
sdir(get_best_session_directory_for_new_source());
1664 sys::path source_dir
= ((type
== DataType::AUDIO
)
1665 ? sdir
.sound_path() : sdir
.midi_path());
1667 string ext
= ((type
== DataType::AUDIO
) ? ".wav" : ".mid");
1669 for (n
= 0; n
< 999999; ++n
) {
1670 if (identifier
.length()) {
1671 snprintf (buf
, sizeof(buf
), "%s%s%" PRIu32
"%s", name
.c_str(),
1672 identifier
.c_str(), n
, ext
.c_str());
1674 snprintf (buf
, sizeof(buf
), "%s-%" PRIu32
"%s", name
.c_str(),
1678 sys::path source_path
= source_dir
/ buf
;
1680 if (!sys::exists (source_path
)) {
1681 return source_path
.to_string();
1685 error
<< string_compose (_("cannot create new file from region name \"%1\" with ident = \"%2\": too many existing files with similar names"),
1694 Session::load_sources (const XMLNode
& node
)
1697 XMLNodeConstIterator niter
;
1698 boost::shared_ptr
<Source
> source
;
1700 nlist
= node
.children();
1704 for (niter
= nlist
.begin(); niter
!= nlist
.end(); ++niter
) {
1706 if ((source
= XMLSourceFactory (**niter
)) == 0) {
1707 error
<< _("Session: cannot create Source from XML description.") << endmsg
;
1709 } catch (MissingSource
& err
) {
1710 warning
<< _("A sound file is missing. It will be replaced by silence.") << endmsg
;
1711 source
= SourceFactory::createSilent (*this, **niter
, max_frames
, _current_frame_rate
);
1718 boost::shared_ptr
<Source
>
1719 Session::XMLSourceFactory (const XMLNode
& node
)
1721 if (node
.name() != "Source") {
1722 return boost::shared_ptr
<Source
>();
1726 /* note: do peak building in another thread when loading session state */
1727 return SourceFactory::create (*this, node
, true);
1730 catch (failed_constructor
& err
) {
1731 error
<< _("Found a sound file that cannot be used by Ardour. Talk to the progammers.") << endmsg
;
1732 return boost::shared_ptr
<Source
>();
1737 Session::save_template (string template_name
)
1741 if (_state_of_the_state
& CannotSave
) {
1745 sys::path
user_template_dir(user_template_directory());
1749 sys::create_directories (user_template_dir
);
1751 catch(sys::filesystem_error
& ex
)
1753 error
<< string_compose(_("Could not create mix templates directory \"%1\" (%2)"),
1754 user_template_dir
.to_string(), ex
.what()) << endmsg
;
1758 tree
.set_root (&get_template());
1760 sys::path
template_file_path(user_template_dir
);
1761 template_file_path
/= template_name
+ template_suffix
;
1763 if (sys::exists (template_file_path
))
1765 warning
<< string_compose(_("Template \"%1\" already exists - new version not created"),
1766 template_file_path
.to_string()) << endmsg
;
1770 if (!tree
.write (template_file_path
.to_string())) {
1771 error
<< _("mix template not saved") << endmsg
;
1779 Session::rename_template (string old_name
, string new_name
)
1781 sys::path
old_path (user_template_directory());
1782 old_path
/= old_name
+ template_suffix
;
1784 sys::path
new_path(user_template_directory());
1785 new_path
/= new_name
+ template_suffix
;
1787 if (sys::exists (new_path
)) {
1788 warning
<< string_compose(_("Template \"%1\" already exists - template not renamed"),
1789 new_path
.to_string()) << endmsg
;
1794 sys::rename (old_path
, new_path
);
1802 Session::delete_template (string name
)
1804 sys::path path
= user_template_directory();
1805 path
/= name
+ template_suffix
;
1816 Session::refresh_disk_space ()
1819 struct statfs statfsbuf
;
1820 vector
<space_and_path
>::iterator i
;
1821 Glib::Mutex::Lock
lm (space_lock
);
1824 /* get freespace on every FS that is part of the session path */
1826 _total_free_4k_blocks
= 0;
1828 for (i
= session_dirs
.begin(); i
!= session_dirs
.end(); ++i
) {
1829 statfs ((*i
).path
.c_str(), &statfsbuf
);
1831 scale
= statfsbuf
.f_bsize
/4096.0;
1833 (*i
).blocks
= (uint32_t) floor (statfsbuf
.f_bavail
* scale
);
1834 _total_free_4k_blocks
+= (*i
).blocks
;
1840 Session::get_best_session_directory_for_new_source ()
1842 vector
<space_and_path
>::iterator i
;
1843 string result
= _session_dir
->root_path().to_string();
1845 /* handle common case without system calls */
1847 if (session_dirs
.size() == 1) {
1851 /* OK, here's the algorithm we're following here:
1853 We want to select which directory to use for
1854 the next file source to be created. Ideally,
1855 we'd like to use a round-robin process so as to
1856 get maximum performance benefits from splitting
1857 the files across multiple disks.
1859 However, in situations without much diskspace, an
1860 RR approach may end up filling up a filesystem
1861 with new files while others still have space.
1862 Its therefore important to pay some attention to
1863 the freespace in the filesystem holding each
1864 directory as well. However, if we did that by
1865 itself, we'd keep creating new files in the file
1866 system with the most space until it was as full
1867 as all others, thus negating any performance
1868 benefits of this RAID-1 like approach.
1870 So, we use a user-configurable space threshold. If
1871 there are at least 2 filesystems with more than this
1872 much space available, we use RR selection between them.
1873 If not, then we pick the filesystem with the most space.
1875 This gets a good balance between the two
1879 refresh_disk_space ();
1881 int free_enough
= 0;
1883 for (i
= session_dirs
.begin(); i
!= session_dirs
.end(); ++i
) {
1884 if ((*i
).blocks
* 4096 >= Config
->get_disk_choice_space_threshold()) {
1889 if (free_enough
>= 2) {
1890 /* use RR selection process, ensuring that the one
1894 i
= last_rr_session_dir
;
1897 if (++i
== session_dirs
.end()) {
1898 i
= session_dirs
.begin();
1901 if ((*i
).blocks
* 4096 >= Config
->get_disk_choice_space_threshold()) {
1902 if (create_session_directory ((*i
).path
)) {
1904 last_rr_session_dir
= i
;
1909 } while (i
!= last_rr_session_dir
);
1913 /* pick FS with the most freespace (and that
1914 seems to actually work ...)
1917 vector
<space_and_path
> sorted
;
1918 space_and_path_ascending_cmp cmp
;
1920 sorted
= session_dirs
;
1921 sort (sorted
.begin(), sorted
.end(), cmp
);
1923 for (i
= sorted
.begin(); i
!= sorted
.end(); ++i
) {
1924 if (create_session_directory ((*i
).path
)) {
1926 last_rr_session_dir
= i
;
1936 Session::load_named_selections (const XMLNode
& node
)
1939 XMLNodeConstIterator niter
;
1942 nlist
= node
.children();
1946 for (niter
= nlist
.begin(); niter
!= nlist
.end(); ++niter
) {
1948 if ((ns
= XMLNamedSelectionFactory (**niter
)) == 0) {
1949 error
<< _("Session: cannot create Named Selection from XML description.") << endmsg
;
1957 Session::XMLNamedSelectionFactory (const XMLNode
& node
)
1960 return new NamedSelection (*this, node
);
1963 catch (failed_constructor
& err
) {
1969 Session::automation_dir () const
1971 return Glib::build_filename (_path
, "automation");
1975 Session::analysis_dir () const
1977 return Glib::build_filename (_path
, "analysis");
1981 Session::load_bundles (XMLNode
const & node
)
1983 XMLNodeList nlist
= node
.children();
1984 XMLNodeConstIterator niter
;
1988 for (niter
= nlist
.begin(); niter
!= nlist
.end(); ++niter
) {
1989 if ((*niter
)->name() == "InputBundle") {
1990 add_bundle (boost::shared_ptr
<UserBundle
> (new UserBundle (**niter
, true)));
1991 } else if ((*niter
)->name() == "OutputBundle") {
1992 add_bundle (boost::shared_ptr
<UserBundle
> (new UserBundle (**niter
, false)));
1994 error
<< string_compose(_("Unknown node \"%1\" found in Bundles list from state file"), (*niter
)->name()) << endmsg
;
2003 Session::load_route_groups (const XMLNode
& node
, int version
)
2005 XMLNodeList nlist
= node
.children();
2006 XMLNodeConstIterator niter
;
2010 if (version
>= 3000) {
2012 for (niter
= nlist
.begin(); niter
!= nlist
.end(); ++niter
) {
2013 if ((*niter
)->name() == "RouteGroup") {
2014 RouteGroup
* rg
= new RouteGroup (*this, "");
2015 add_route_group (rg
);
2016 rg
->set_state (**niter
, version
);
2020 } else if (version
< 3000) {
2022 for (niter
= nlist
.begin(); niter
!= nlist
.end(); ++niter
) {
2023 if ((*niter
)->name() == "EditGroup" || (*niter
)->name() == "MixGroup") {
2024 RouteGroup
* rg
= new RouteGroup (*this, "");
2025 add_route_group (rg
);
2026 rg
->set_state (**niter
, version
);
2035 Session::auto_save()
2037 save_state (_current_snapshot_name
);
2041 state_file_filter (const string
&str
, void */
*arg*/
)
2043 return (str
.length() > strlen(statefile_suffix
) &&
2044 str
.find (statefile_suffix
) == (str
.length() - strlen (statefile_suffix
)));
2048 bool operator()(const string
* a
, const string
* b
) {
2054 remove_end(string
* state
)
2056 string
statename(*state
);
2058 string::size_type start
,end
;
2059 if ((start
= statename
.find_last_of ('/')) != string::npos
) {
2060 statename
= statename
.substr (start
+1);
2063 if ((end
= statename
.rfind(".ardour")) == string::npos
) {
2064 end
= statename
.length();
2067 return new string(statename
.substr (0, end
));
2071 Session::possible_states (string path
)
2073 PathScanner scanner
;
2074 vector
<string
*>* states
= scanner (path
, state_file_filter
, 0, false, false);
2076 transform(states
->begin(), states
->end(), states
->begin(), remove_end
);
2079 sort (states
->begin(), states
->end(), cmp
);
2085 Session::possible_states () const
2087 return possible_states(_path
);
2091 Session::add_route_group (RouteGroup
* g
)
2093 _route_groups
.push_back (g
);
2094 route_group_added (g
); /* EMIT SIGNAL */
2099 Session::remove_route_group (RouteGroup
& rg
)
2101 list
<RouteGroup
*>::iterator i
;
2103 if ((i
= find (_route_groups
.begin(), _route_groups
.end(), &rg
)) != _route_groups
.end()) {
2104 _route_groups
.erase (i
);
2107 route_group_removed (); /* EMIT SIGNAL */
2113 Session::route_group_by_name (string name
)
2115 list
<RouteGroup
*>::iterator i
;
2117 for (i
= _route_groups
.begin(); i
!= _route_groups
.end(); ++i
) {
2118 if ((*i
)->name() == name
) {
2126 Session::start_reversible_command (const string
& name
)
2128 UndoTransaction
* trans
= new UndoTransaction();
2129 trans
->set_name(name
);
2134 Session::finish_reversible_command (UndoTransaction
& ut
)
2137 gettimeofday(&now
, 0);
2138 ut
.set_timestamp(now
);
2143 Session::begin_reversible_command(const string
& name
)
2145 UndoTransaction
* trans
= new UndoTransaction();
2146 trans
->set_name(name
);
2148 if (!_current_trans
.empty()) {
2149 _current_trans
.top()->add_command (trans
);
2151 _current_trans
.push(trans
);
2156 Session::commit_reversible_command(Command
*cmd
)
2158 assert(!_current_trans
.empty());
2162 _current_trans
.top()->add_command(cmd
);
2165 if (_current_trans
.top()->empty()) {
2166 _current_trans
.pop();
2170 gettimeofday(&now
, 0);
2171 _current_trans
.top()->set_timestamp(now
);
2173 _history
.add(_current_trans
.top());
2174 _current_trans
.pop();
2178 accept_all_non_peak_files (const string
& path
, void */
*arg*/
)
2180 return (path
.length() > 5 && path
.find (peakfile_suffix
) != (path
.length() - 5));
2184 accept_all_state_files (const string
& path
, void */
*arg*/
)
2186 return (path
.length() > 7 && path
.find (".ardour") == (path
.length() - 7));
2190 Session::find_all_sources (string path
, set
<string
>& result
)
2195 if (!tree
.read (path
)) {
2199 if ((node
= find_named_node (*tree
.root(), "Sources")) == 0) {
2204 XMLNodeConstIterator niter
;
2206 nlist
= node
->children();
2210 for (niter
= nlist
.begin(); niter
!= nlist
.end(); ++niter
) {
2214 if ((prop
= (*niter
)->property (X_("type"))) == 0) {
2218 DataType
type (prop
->value());
2220 if ((prop
= (*niter
)->property (X_("name"))) == 0) {
2224 if (prop
->value()[0] == '/') {
2225 /* external file, ignore */
2229 Glib::ustring found_path
;
2233 if (FileSource::find (type
, prop
->value(), true, is_new
, chan
, found_path
)) {
2234 result
.insert (found_path
);
2242 Session::find_all_sources_across_snapshots (set
<string
>& result
, bool exclude_this_snapshot
)
2244 PathScanner scanner
;
2245 vector
<string
*>* state_files
;
2247 string this_snapshot_path
;
2253 if (ripped
[ripped
.length()-1] == '/') {
2254 ripped
= ripped
.substr (0, ripped
.length() - 1);
2257 state_files
= scanner (ripped
, accept_all_state_files
, (void *) 0, false, true);
2259 if (state_files
== 0) {
2264 this_snapshot_path
= _path
;
2265 this_snapshot_path
+= legalize_for_path (_current_snapshot_name
);
2266 this_snapshot_path
+= statefile_suffix
;
2268 for (vector
<string
*>::iterator i
= state_files
->begin(); i
!= state_files
->end(); ++i
) {
2270 if (exclude_this_snapshot
&& **i
== this_snapshot_path
) {
2274 if (find_all_sources (**i
, result
) < 0) {
2282 struct RegionCounter
{
2283 typedef std::map
<PBD::ID
,boost::shared_ptr
<AudioSource
> > AudioSourceList
;
2284 AudioSourceList::iterator iter
;
2285 boost::shared_ptr
<Region
> region
;
2288 RegionCounter() : count (0) {}
2292 Session::ask_about_playlist_deletion (boost::shared_ptr
<Playlist
> p
)
2294 return *AskAboutPlaylistDeletion (p
);
2298 Session::cleanup_sources (CleanupReport
& rep
)
2300 // FIXME: needs adaptation to midi
2302 vector
<boost::shared_ptr
<Source
> > dead_sources
;
2303 PathScanner scanner
;
2305 vector
<space_and_path
>::iterator i
;
2306 vector
<space_and_path
>::iterator nexti
;
2307 vector
<string
*>* soundfiles
;
2308 vector
<string
> unused
;
2309 set
<string
> all_sources
;
2314 _state_of_the_state
= (StateOfTheState
) (_state_of_the_state
| InCleanup
);
2316 /* step 1: consider deleting all unused playlists */
2318 if (playlists
->maybe_delete_unused (boost::bind (Session::ask_about_playlist_deletion
, _1
))) {
2323 /* step 2: find all un-used sources */
2328 for (SourceMap::iterator i
= sources
.begin(); i
!= sources
.end(); ) {
2330 SourceMap::iterator tmp
;
2335 /* do not bother with files that are zero size, otherwise we remove the current "nascent"
2339 if (!playlists
->source_use_count(i
->second
) && i
->second
->length(i
->second
->timeline_position()) > 0) {
2340 dead_sources
.push_back (i
->second
);
2341 i
->second
->drop_references ();
2347 /* build a list of all the possible sound directories for the session */
2349 for (i
= session_dirs
.begin(); i
!= session_dirs
.end(); ) {
2354 SessionDirectory
sdir ((*i
).path
);
2355 sound_path
+= sdir
.sound_path().to_string();
2357 if (nexti
!= session_dirs
.end()) {
2364 /* now do the same thing for the files that ended up in the sounds dir(s)
2365 but are not referenced as sources in any snapshot.
2368 soundfiles
= scanner (sound_path
, accept_all_non_peak_files
, (void *) 0, false, true);
2370 if (soundfiles
== 0) {
2374 /* find all sources, but don't use this snapshot because the
2375 state file on disk still references sources we may have already
2379 find_all_sources_across_snapshots (all_sources
, true);
2381 /* add our current source list
2384 for (SourceMap::iterator i
= sources
.begin(); i
!= sources
.end(); ++i
) {
2385 boost::shared_ptr
<FileSource
> fs
;
2387 if ((fs
= boost::dynamic_pointer_cast
<FileSource
> (i
->second
)) != 0) {
2388 all_sources
.insert (fs
->path());
2392 char tmppath1
[PATH_MAX
+1];
2393 char tmppath2
[PATH_MAX
+1];
2395 for (vector
<string
*>::iterator x
= soundfiles
->begin(); x
!= soundfiles
->end(); ++x
) {
2400 for (set
<string
>::iterator i
= all_sources
.begin(); i
!= all_sources
.end(); ++i
) {
2402 realpath(spath
.c_str(), tmppath1
);
2403 realpath((*i
).c_str(), tmppath2
);
2405 if (strcmp(tmppath1
, tmppath2
) == 0) {
2412 unused
.push_back (spath
);
2416 /* now try to move all unused files into the "dead_sounds" directory(ies) */
2418 for (vector
<string
>::iterator x
= unused
.begin(); x
!= unused
.end(); ++x
) {
2419 struct stat statbuf
;
2421 rep
.paths
.push_back (*x
);
2422 if (stat ((*x
).c_str(), &statbuf
) == 0) {
2423 rep
.space
+= statbuf
.st_size
;
2428 /* don't move the file across filesystems, just
2429 stick it in the `dead_sound_dir_name' directory
2430 on whichever filesystem it was already on.
2433 if ((*x
).find ("/sounds/") != string::npos
) {
2435 /* old school, go up 1 level */
2437 newpath
= Glib::path_get_dirname (*x
); // "sounds"
2438 newpath
= Glib::path_get_dirname (newpath
); // "session-name"
2442 /* new school, go up 4 levels */
2444 newpath
= Glib::path_get_dirname (*x
); // "audiofiles"
2445 newpath
= Glib::path_get_dirname (newpath
); // "session-name"
2446 newpath
= Glib::path_get_dirname (newpath
); // "interchange"
2447 newpath
= Glib::path_get_dirname (newpath
); // "session-dir"
2451 newpath
+= dead_sound_dir_name
;
2453 if (g_mkdir_with_parents (newpath
.c_str(), 0755) < 0) {
2454 error
<< string_compose(_("Session: cannot create session peakfile folder \"%1\" (%2)"), newpath
, strerror (errno
)) << endmsg
;
2459 newpath
+= Glib::path_get_basename ((*x
));
2461 if (access (newpath
.c_str(), F_OK
) == 0) {
2463 /* the new path already exists, try versioning */
2465 char buf
[PATH_MAX
+1];
2469 snprintf (buf
, sizeof (buf
), "%s.%d", newpath
.c_str(), version
);
2472 while (access (newpath_v
.c_str(), F_OK
) == 0 && version
< 999) {
2473 snprintf (buf
, sizeof (buf
), "%s.%d", newpath
.c_str(), ++version
);
2477 if (version
== 999) {
2478 error
<< string_compose (_("there are already 1000 files with names like %1; versioning discontinued"),
2482 newpath
= newpath_v
;
2487 /* it doesn't exist, or we can't read it or something */
2491 if (::rename ((*x
).c_str(), newpath
.c_str()) != 0) {
2492 error
<< string_compose (_("cannot rename audio file source from %1 to %2 (%3)"),
2493 (*x
), newpath
, strerror (errno
))
2498 /* see if there an easy to find peakfile for this file, and remove it.
2501 string peakpath
= (*x
).substr (0, (*x
).find_last_of ('.'));
2502 peakpath
+= peakfile_suffix
;
2504 if (access (peakpath
.c_str(), W_OK
) == 0) {
2505 if (::unlink (peakpath
.c_str()) != 0) {
2506 error
<< string_compose (_("cannot remove peakfile %1 for %2 (%3)"),
2507 peakpath
, _path
, strerror (errno
))
2509 /* try to back out */
2510 rename (newpath
.c_str(), _path
.c_str());
2518 /* dump the history list */
2522 /* save state so we don't end up a session file
2523 referring to non-existent sources.
2529 _state_of_the_state
= (StateOfTheState
) (_state_of_the_state
& ~InCleanup
);
2535 Session::cleanup_trash_sources (CleanupReport
& rep
)
2537 // FIXME: needs adaptation for MIDI
2539 vector
<space_and_path
>::iterator i
;
2540 string dead_sound_dir
;
2541 struct dirent
* dentry
;
2542 struct stat statbuf
;
2548 for (i
= session_dirs
.begin(); i
!= session_dirs
.end(); ++i
) {
2550 dead_sound_dir
= (*i
).path
;
2551 dead_sound_dir
+= dead_sound_dir_name
;
2553 if ((dead
= opendir (dead_sound_dir
.c_str())) == 0) {
2557 while ((dentry
= readdir (dead
)) != 0) {
2559 /* avoid '.' and '..' */
2561 if ((dentry
->d_name
[0] == '.' && dentry
->d_name
[1] == '\0') ||
2562 (dentry
->d_name
[2] == '\0' && dentry
->d_name
[0] == '.' && dentry
->d_name
[1] == '.')) {
2568 fullpath
= dead_sound_dir
;
2570 fullpath
+= dentry
->d_name
;
2572 if (stat (fullpath
.c_str(), &statbuf
)) {
2576 if (!S_ISREG (statbuf
.st_mode
)) {
2580 if (unlink (fullpath
.c_str())) {
2581 error
<< string_compose (_("cannot remove dead sound file %1 (%2)"),
2582 fullpath
, strerror (errno
))
2586 rep
.paths
.push_back (dentry
->d_name
);
2587 rep
.space
+= statbuf
.st_size
;
2598 Session::set_dirty ()
2600 bool was_dirty
= dirty();
2602 _state_of_the_state
= StateOfTheState (_state_of_the_state
| Dirty
);
2606 DirtyChanged(); /* EMIT SIGNAL */
2612 Session::set_clean ()
2614 bool was_dirty
= dirty();
2616 _state_of_the_state
= Clean
;
2620 DirtyChanged(); /* EMIT SIGNAL */
2625 Session::set_deletion_in_progress ()
2627 _state_of_the_state
= StateOfTheState (_state_of_the_state
| Deletion
);
2631 Session::clear_deletion_in_progress ()
2633 _state_of_the_state
= StateOfTheState (_state_of_the_state
& (~Deletion
));
2637 Session::add_controllable (boost::shared_ptr
<Controllable
> c
)
2639 /* this adds a controllable to the list managed by the Session.
2640 this is a subset of those managed by the Controllable class
2641 itself, and represents the only ones whose state will be saved
2642 as part of the session.
2645 Glib::Mutex::Lock
lm (controllables_lock
);
2646 controllables
.insert (c
);
2649 struct null_deleter
{ void operator()(void const *) const {} };
2652 Session::remove_controllable (Controllable
* c
)
2654 if (_state_of_the_state
| Deletion
) {
2658 Glib::Mutex::Lock
lm (controllables_lock
);
2660 Controllables::iterator x
= controllables
.find (boost::shared_ptr
<Controllable
>(c
, null_deleter()));
2662 if (x
!= controllables
.end()) {
2663 controllables
.erase (x
);
2667 boost::shared_ptr
<Controllable
>
2668 Session::controllable_by_id (const PBD::ID
& id
)
2670 Glib::Mutex::Lock
lm (controllables_lock
);
2672 for (Controllables::iterator i
= controllables
.begin(); i
!= controllables
.end(); ++i
) {
2673 if ((*i
)->id() == id
) {
2678 return boost::shared_ptr
<Controllable
>();
2681 boost::shared_ptr
<Controllable
>
2682 Session::controllable_by_descriptor (const ControllableDescriptor
& desc
)
2684 boost::shared_ptr
<Controllable
> c
;
2685 boost::shared_ptr
<Route
> r
;
2687 switch (desc
.top_level_type()) {
2688 case ControllableDescriptor::NamedRoute
:
2690 std::string str
= desc
.top_level_name();
2691 if (str
== "master") {
2693 } else if (str
== "control" || str
== "listen") {
2696 r
= route_by_name (desc
.top_level_name());
2701 case ControllableDescriptor::RemoteControlID
:
2702 r
= route_by_remote_id (desc
.rid());
2710 switch (desc
.subtype()) {
2711 case ControllableDescriptor::Gain
:
2712 c
= r
->gain_control ();
2715 case ControllableDescriptor::Solo
:
2716 c
= r
->solo_control();
2719 case ControllableDescriptor::Mute
:
2720 c
= r
->mute_control();
2723 case ControllableDescriptor::Recenable
:
2725 boost::shared_ptr
<Track
> t
= boost::dynamic_pointer_cast
<Track
>(r
);
2728 c
= t
->rec_enable_control ();
2733 case ControllableDescriptor::Pan
:
2734 /* XXX pan control */
2737 case ControllableDescriptor::Balance
:
2738 /* XXX simple pan control */
2741 case ControllableDescriptor::PluginParameter
:
2743 uint32_t plugin
= desc
.target (0);
2744 uint32_t parameter_index
= desc
.target (1);
2746 /* revert to zero based counting */
2752 if (parameter_index
> 0) {
2756 boost::shared_ptr
<Processor
> p
= r
->nth_plugin (plugin
);
2759 c
= boost::dynamic_pointer_cast
<ARDOUR::AutomationControl
>(
2760 p
->data().control(Evoral::Parameter(PluginAutomation
, 0, parameter_index
)));
2765 case ControllableDescriptor::SendGain
:
2767 uint32_t send
= desc
.target (0);
2769 /* revert to zero-based counting */
2775 boost::shared_ptr
<Processor
> p
= r
->nth_send (send
);
2778 boost::shared_ptr
<Send
> s
= boost::dynamic_pointer_cast
<Send
>(p
);
2779 boost::shared_ptr
<Amp
> a
= s
->amp();
2782 c
= s
->amp()->gain_control();
2789 /* relax and return a null pointer */
2797 Session::add_instant_xml (XMLNode
& node
, bool write_to_config
)
2800 Stateful::add_instant_xml (node
, _path
);
2803 if (write_to_config
) {
2804 Config
->add_instant_xml (node
);
2809 Session::instant_xml (const string
& node_name
)
2811 return Stateful::instant_xml (node_name
, _path
);
2815 Session::save_history (string snapshot_name
)
2823 if (snapshot_name
.empty()) {
2824 snapshot_name
= _current_snapshot_name
;
2827 const string history_filename
= legalize_for_path (snapshot_name
) + history_suffix
;
2828 const string backup_filename
= history_filename
+ backup_suffix
;
2829 const sys::path xml_path
= _session_dir
->root_path() / history_filename
;
2830 const sys::path backup_path
= _session_dir
->root_path() / backup_filename
;
2832 if (sys::exists (xml_path
)) {
2835 sys::rename (xml_path
, backup_path
);
2837 catch (const sys::filesystem_error
& err
)
2839 error
<< _("could not backup old history file, current history not saved") << endmsg
;
2844 if (!Config
->get_save_history() || Config
->get_saved_history_depth() < 0) {
2848 tree
.set_root (&_history
.get_state (Config
->get_saved_history_depth()));
2850 if (!tree
.write (xml_path
.to_string()))
2852 error
<< string_compose (_("history could not be saved to %1"), xml_path
.to_string()) << endmsg
;
2856 sys::remove (xml_path
);
2857 sys::rename (backup_path
, xml_path
);
2859 catch (const sys::filesystem_error
& err
)
2861 error
<< string_compose (_("could not restore history file from backup %1 (%2)"),
2862 backup_path
.to_string(), err
.what()) << endmsg
;
2872 Session::restore_history (string snapshot_name
)
2876 if (snapshot_name
.empty()) {
2877 snapshot_name
= _current_snapshot_name
;
2880 const string xml_filename
= legalize_for_path (snapshot_name
) + history_suffix
;
2881 const sys::path xml_path
= _session_dir
->root_path() / xml_filename
;
2883 info
<< "Loading history from " << xml_path
.to_string() << endmsg
;
2885 if (!sys::exists (xml_path
)) {
2886 info
<< string_compose (_("%1: no history file \"%2\" for this session."),
2887 _name
, xml_path
.to_string()) << endmsg
;
2891 if (!tree
.read (xml_path
.to_string())) {
2892 error
<< string_compose (_("Could not understand session history file \"%1\""),
2893 xml_path
.to_string()) << endmsg
;
2900 for (XMLNodeConstIterator it
= tree
.root()->children().begin(); it
!= tree
.root()->children().end(); it
++) {
2903 UndoTransaction
* ut
= new UndoTransaction ();
2906 ut
->set_name(t
->property("name")->value());
2907 stringstream
ss(t
->property("tv-sec")->value());
2909 ss
.str(t
->property("tv-usec")->value());
2911 ut
->set_timestamp(tv
);
2913 for (XMLNodeConstIterator child_it
= t
->children().begin();
2914 child_it
!= t
->children().end(); child_it
++)
2916 XMLNode
*n
= *child_it
;
2919 if (n
->name() == "MementoCommand" ||
2920 n
->name() == "MementoUndoCommand" ||
2921 n
->name() == "MementoRedoCommand") {
2923 if ((c
= memento_command_factory(n
))) {
2927 } else if (n
->name() == "DeltaCommand") {
2928 PBD::ID
id(n
->property("midi-source")->value());
2929 boost::shared_ptr
<MidiSource
> midi_source
=
2930 boost::dynamic_pointer_cast
<MidiSource
, Source
>(source_by_id(id
));
2932 ut
->add_command(new MidiModel::DeltaCommand(midi_source
->model(), *n
));
2934 error
<< _("Failed to downcast MidiSource for DeltaCommand") << endmsg
;
2937 } else if (n
->name() == "DiffCommand") {
2938 PBD::ID
id(n
->property("midi-source")->value());
2939 boost::shared_ptr
<MidiSource
> midi_source
=
2940 boost::dynamic_pointer_cast
<MidiSource
, Source
>(source_by_id(id
));
2942 ut
->add_command(new MidiModel::DiffCommand(midi_source
->model(), *n
));
2944 error
<< _("Failed to downcast MidiSource for DeltaCommand") << endmsg
;
2948 error
<< string_compose(_("Couldn't figure out how to make a Command out of a %1 XMLNode."), n
->name()) << endmsg
;
2959 Session::config_changed (std::string p
, bool ours
)
2965 if (p
== "seamless-loop") {
2967 } else if (p
== "rf-speed") {
2969 } else if (p
== "auto-loop") {
2971 } else if (p
== "auto-input") {
2973 if (Config
->get_monitoring_model() == HardwareMonitoring
&& transport_rolling()) {
2974 /* auto-input only makes a difference if we're rolling */
2976 boost::shared_ptr
<DiskstreamList
> dsl
= diskstreams
.reader();
2978 for (DiskstreamList::iterator i
= dsl
->begin(); i
!= dsl
->end(); ++i
) {
2979 if ((*i
)->record_enabled ()) {
2980 (*i
)->monitor_input (!config
.get_auto_input());
2985 } else if (p
== "punch-in") {
2989 if ((location
= _locations
.auto_punch_location()) != 0) {
2991 if (config
.get_punch_in ()) {
2992 replace_event (SessionEvent::PunchIn
, location
->start());
2994 remove_event (location
->start(), SessionEvent::PunchIn
);
2998 } else if (p
== "punch-out") {
3002 if ((location
= _locations
.auto_punch_location()) != 0) {
3004 if (config
.get_punch_out()) {
3005 replace_event (SessionEvent::PunchOut
, location
->end());
3007 clear_events (SessionEvent::PunchOut
);
3011 } else if (p
== "edit-mode") {
3013 Glib::Mutex::Lock
lm (playlists
->lock
);
3015 for (SessionPlaylists::List::iterator i
= playlists
->playlists
.begin(); i
!= playlists
->playlists
.end(); ++i
) {
3016 (*i
)->set_edit_mode (Config
->get_edit_mode ());
3019 } else if (p
== "use-video-sync") {
3021 waiting_for_sync_offset
= config
.get_use_video_sync();
3023 } else if (p
== "mmc-control") {
3025 //poke_midi_thread ();
3027 } else if (p
== "mmc-device-id" || p
== "mmc-receive-id") {
3030 mmc
->set_receive_device_id (Config
->get_mmc_receive_device_id());
3033 } else if (p
== "mmc-send-id") {
3036 mmc
->set_send_device_id (Config
->get_mmc_send_device_id());
3039 } else if (p
== "midi-control") {
3041 //poke_midi_thread ();
3043 } else if (p
== "raid-path") {
3045 setup_raid_path (config
.get_raid_path());
3047 } else if (p
== "timecode-format") {
3051 } else if (p
== "video-pullup") {
3055 } else if (p
== "seamless-loop") {
3057 if (play_loop
&& transport_rolling()) {
3058 // to reset diskstreams etc
3059 request_play_loop (true);
3062 } else if (p
== "rf-speed") {
3064 cumulative_rf_motion
= 0;
3067 } else if (p
== "click-sound") {
3069 setup_click_sounds (1);
3071 } else if (p
== "click-emphasis-sound") {
3073 setup_click_sounds (-1);
3075 } else if (p
== "clicking") {
3077 if (Config
->get_clicking()) {
3078 if (_click_io
&& click_data
) { // don't require emphasis data
3085 } else if (p
== "send-mtc") {
3087 /* only set the internal flag if we have
3091 if (_mtc_port
!= 0) {
3092 session_send_mtc
= Config
->get_send_mtc();
3093 if (session_send_mtc
) {
3094 /* mark us ready to send */
3095 next_quarter_frame_to_send
= 0;
3098 session_send_mtc
= false;
3101 } else if (p
== "send-mmc") {
3103 /* only set the internal flag if we have
3107 if (_mmc_port
!= 0) {
3108 session_send_mmc
= Config
->get_send_mmc();
3111 session_send_mmc
= false;
3114 } else if (p
== "midi-feedback") {
3116 /* only set the internal flag if we have
3120 if (_mtc_port
!= 0) {
3121 session_midi_feedback
= Config
->get_midi_feedback();
3124 } else if (p
== "jack-time-master") {
3126 engine().reset_timebase ();
3128 } else if (p
== "native-file-header-format") {
3130 if (!first_file_header_format_reset
) {
3131 reset_native_file_format ();
3134 first_file_header_format_reset
= false;
3136 } else if (p
== "native-file-data-format") {
3138 if (!first_file_data_format_reset
) {
3139 reset_native_file_format ();
3142 first_file_data_format_reset
= false;
3144 } else if (p
== "external-sync") {
3145 if (!config
.get_external_sync()) {
3146 drop_sync_source ();
3148 switch_to_sync_source (config
.get_sync_source());
3150 } else if (p
== "remote-model") {
3151 set_remote_control_ids ();
3152 } else if (p
== "denormal-model") {
3154 } else if (p
== "history-depth") {
3155 set_history_depth (Config
->get_history_depth());
3156 } else if (p
== "sync-all-route-ordering") {
3157 sync_order_keys ("session");
3158 } else if (p
== "initial-program-change") {
3160 if (_mmc_port
&& Config
->get_initial_program_change() >= 0) {
3163 buf
[0] = MIDI::program
; // channel zero by default
3164 buf
[1] = (Config
->get_initial_program_change() & 0x7f);
3166 _mmc_port
->midimsg (buf
, sizeof (buf
), 0);
3168 } else if (p
== "initial-program-change") {
3170 if (_mmc_port
&& Config
->get_initial_program_change() >= 0) {
3171 MIDI::byte
* buf
= new MIDI::byte
[2];
3173 buf
[0] = MIDI::program
; // channel zero by default
3174 buf
[1] = (Config
->get_initial_program_change() & 0x7f);
3175 // deliver_midi (_mmc_port, buf, 2);
3177 } else if (p
== "solo-mute-override") {
3178 // catch_up_on_solo_mute_override ();
3179 } else if (p
== "listen-position") {
3180 listen_position_changed ();
3181 } else if (p
== "solo-control-is-listen-control") {
3182 solo_control_mode_changed ();
3190 Session::set_history_depth (uint32_t d
)
3192 _history
.set_depth (d
);