+}
+
+void
+SndFileSource::setup_standard_crossfades (Session const & s, framecnt_t rate)
+{
+ /* This static method is assumed to have been called by the Session
+ before any DFS's are created.
+ */
+
+ xfade_frames = (framecnt_t) floor ((s.config.get_destructive_xfade_msecs () / 1000.0) * rate);
+
+ delete [] out_coefficient;
+ delete [] in_coefficient;
+
+ out_coefficient = new gain_t[xfade_frames];
+ in_coefficient = new gain_t[xfade_frames];
+
+ compute_equal_power_fades (xfade_frames, in_coefficient, out_coefficient);
+}
+
+void
+SndFileSource::set_timeline_position (framepos_t pos)
+{
+ // destructive track timeline postion does not change
+ // except at instantion or when header_position_offset
+ // (session start) changes
+
+ if (!destructive()) {
+ AudioFileSource::set_timeline_position (pos);
+ }
+}
+
+int
+SndFileSource::get_soundfile_info (const string& path, SoundFileInfo& info, string& error_msg)
+{
+ SNDFILE *sf;
+ SF_INFO sf_info;
+ BroadcastInfo binfo;
+
+ sf_info.format = 0; // libsndfile says to clear this before sf_open().
+
+ if ((sf = sf_open ((char*) path.c_str(), SFM_READ, &sf_info)) == 0) {
+ char errbuf[256];
+ error_msg = sf_error_str (0, errbuf, sizeof (errbuf) - 1);
+ return false;
+ }
+
+ info.samplerate = sf_info.samplerate;
+ info.channels = sf_info.channels;
+ info.length = sf_info.frames;
+
+ string major = sndfile_major_format(sf_info.format);
+ string minor = sndfile_minor_format(sf_info.format);
+
+ if (major.length() + minor.length() < 16) { /* arbitrary */
+ info.format_name = string_compose("%1/%2", major, minor);
+ } else {
+ info.format_name = string_compose("%1\n%2", major, minor);
+ }
+
+ info.timecode = binfo.load_from_file (sf) ? binfo.get_time_reference() : 0;
+
+ sf_close (sf);
+
+ return true;
+}
+
+bool
+SndFileSource::one_of_several_channels () const
+{
+ return _info.channels > 1;
+}
+
+bool
+SndFileSource::clamped_at_unity () const
+{
+ int const type = _info.format & SF_FORMAT_TYPEMASK;
+ int const sub = _info.format & SF_FORMAT_SUBMASK;
+ /* XXX: this may not be the full list of formats that are unclamped */
+ return (sub != SF_FORMAT_FLOAT && sub != SF_FORMAT_DOUBLE && type != SF_FORMAT_OGG);
+}
+
+void
+SndFileSource::file_closed ()
+{
+ /* stupid libsndfile updated the headers on close,
+ so touch the peakfile if it exists and has data
+ to make sure its time is as new as the audio
+ file.
+ */
+
+ touch_peakfile ();
+}
+
+void
+SndFileSource::set_path (const string& p)
+{
+ FileSource::set_path (p);
+
+ if (_descriptor) {
+ _descriptor->set_path (_path);
+ }