+
+int
+SndFileSource::get_soundfile_info (const ustring& path, SoundFileInfo& info, string& error_msg)
+{
+ SNDFILE *sf;
+ SF_INFO sf_info;
+ SF_BROADCAST_INFO binfo;
+ bool timecode_exists;
+
+ 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;
+ info.format_name = string_compose("Format: %1, %2",
+ sndfile_major_format(sf_info.format),
+ sndfile_minor_format(sf_info.format));
+
+ memset (&binfo, 0, sizeof (binfo));
+ info.timecode = get_timecode_info (sf, &binfo, timecode_exists);
+
+ if (!timecode_exists) {
+ info.timecode = 0;
+ }
+
+ sf_close (sf);
+
+ return true;
+}
+
+int64_t
+SndFileSource::get_timecode_info (SNDFILE* sf, SF_BROADCAST_INFO* binfo, bool& exists)
+{
+ if (sf_command (sf, SFC_GET_BROADCAST_INFO, binfo, sizeof (*binfo)) != SF_TRUE) {
+ exists = false;
+ return (header_position_offset);
+ }
+
+ /* XXX 64 bit alert: when JACK switches to a 64 bit frame count, this needs to use the high bits
+ of the time reference.
+ */
+
+ exists = true;
+ int64_t ret = (uint32_t) binfo->time_reference_high;
+ ret <<= 32;
+ ret |= (uint32_t) binfo->time_reference_low;
+ return ret;
+}
+
+bool
+SndFileSource::one_of_several_channels () const
+{
+ return _info.channels > 1;
+}
+
+Sample*
+SndFileSource::get_interleave_buffer (nframes_t size)
+{
+ SizedSampleBuffer* ssb;
+
+ if ((ssb = thread_interleave_buffer.get()) == 0) {
+ ssb = new SizedSampleBuffer (size);
+ thread_interleave_buffer.set (ssb);
+ }
+
+ if (ssb->size < size) {
+ ssb = new SizedSampleBuffer (size);
+ thread_interleave_buffer.set (ssb);
+ }
+
+ return ssb->buf;
+}