Merging from trunk
[ardour.git] / libs / ardour / coreaudio_source.cc
index 91c69dab2fbaf5b34122259c90208e97d2f705e0..1b0ee565e757a617c91d4e55a55e05345b86c869 100644 (file)
@@ -1,5 +1,5 @@
 /*
-    Copyright (C) 2000 Paul Davis 
+    Copyright (C) 2006 Paul Davis 
 
     This program is free software; you can redistribute it and/or modify
     it under the terms of the GNU General Public License as published by
     along with this program; if not, write to the Free Software
     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 
-    $Id$
 */
 
-#include <string>
-#include <sys/stat.h>
-#include <unistd.h>
-#include <sys/time.h>
+#include <pbd/error.h>
 
-#include <pbd/mountpoint.h>
 #include <ardour/coreaudio_source.h>
 
 #include "i18n.h"
 
-using namespace ARDOUR;
+#include <AudioToolbox/AudioFormat.h>
 
-string CoreAudioSource::peak_dir = "";
+using namespace ARDOUR;
+using namespace PBD;
 
 CoreAudioSource::CoreAudioSource (const XMLNode& node)
-       : Source (node)
+       : AudioFileSource (node)
 {
-       if (set_state (node)) {
-               throw failed_constructor();
-       }
-
        init (_name, true);
-       SourceCreated (this); /* EMIT SIGNAL */
+       AudioSourceCreated (this); /* EMIT SIGNAL */
 }
 
 CoreAudioSource::CoreAudioSource (const string& idstr, bool build_peak)
-       : Source(build_peak)
+       : AudioFileSource(idstr, build_peak)
 {
        init (idstr, build_peak);
 
        if (build_peak) {
-                SourceCreated (this); /* EMIT SIGNAL */
+                AudioSourceCreated (this); /* EMIT SIGNAL */
        }
 }
 
@@ -61,7 +53,8 @@ CoreAudioSource::init (const string& idstr, bool build_peak)
 
        tmpbuf = 0;
        tmpbufsize = 0;
-       sf = 0;
+       af = 0;
+       OSStatus err = noErr;
 
        _name = idstr;
 
@@ -74,42 +67,86 @@ CoreAudioSource::init (const string& idstr, bool build_peak)
        }
 
        /* note that we temporarily truncated _id at the colon */
-       FSRef* ref;
-       OSStatus err = FSPathMakeRef (file.c_str(), ref, 0);
-       if (err) {
+       FSRef fsr;
+       err = FSPathMakeRef ((UInt8*)file.c_str(), &fsr, 0);
+       if (err != noErr) {
+               cerr << "FSPathMakeRef " << err << endl;
                throw failed_constructor();
        }
-       err = AudioFileOpen (ref, fsCurPerm, 0, sf);
-       if (err) {
+
+       err = ExtAudioFileOpen (&fsr, &af);
+       if (err != noErr) {
+               cerr << "ExtAudioFileOpen " << err << endl;
+               ExtAudioFileDispose (af);
                throw failed_constructor();
        }
+
+       AudioStreamBasicDescription file_asbd;
+       memset(&file_asbd, 0, sizeof(AudioStreamBasicDescription));
+       size_t asbd_size = sizeof(AudioStreamBasicDescription);
+       err = ExtAudioFileGetProperty(af,
+                       kExtAudioFileProperty_FileDataFormat, &asbd_size, &file_asbd);
+       if (err != noErr) {
+               cerr << "ExtAudioFileGetProperty1 " << err << endl;
+               ExtAudioFileDispose (af);
+               throw failed_constructor();
+       }
+       n_channels = file_asbd.mChannelsPerFrame;
+
+       cerr << "number of channels: " << n_channels << endl;
        
-       if (channel >= _info.channels) {
-               error << string_compose(_("CoreAudioSource: file only contains %1 channels; %2 is invalid as a channel number"), _info.channels, channel) << endmsg;
-               sf_close (sf);
-               sf = 0;
+       if (channel >= n_channels) {
+               error << string_compose(_("CoreAudioSource: file only contains %1 channels; %2 is invalid as a channel number"), n_channels, channel) << endmsg;
+               ExtAudioFileDispose (af);
                throw failed_constructor();
        }
 
-       _length = _info.frames;
+       int64_t ca_frames;
+       size_t prop_size = sizeof(int64_t);
+
+       err = ExtAudioFileGetProperty(af, kExtAudioFileProperty_FileLengthFrames, &prop_size, &ca_frames);
+       if (err != noErr) {
+               cerr << "ExtAudioFileGetProperty2 " << err << endl;
+               ExtAudioFileDispose (af);
+               throw failed_constructor();
+       }
+
+       _length = ca_frames;
        _path = file;
 
+       AudioStreamBasicDescription client_asbd;
+       memset(&client_asbd, 0, sizeof(AudioStreamBasicDescription));
+       client_asbd.mSampleRate = file_asbd.mSampleRate;
+       client_asbd.mFormatID = kAudioFormatLinearPCM;
+       client_asbd.mFormatFlags = kLinearPCMFormatFlagIsFloat;
+       client_asbd.mBytesPerPacket = file_asbd.mChannelsPerFrame * 4;
+       client_asbd.mFramesPerPacket = 1;
+       client_asbd.mBytesPerFrame = client_asbd.mBytesPerPacket;
+       client_asbd.mChannelsPerFrame = file_asbd.mChannelsPerFrame;
+       client_asbd.mBitsPerChannel = 32;
+
+       err = ExtAudioFileSetProperty (af, kExtAudioFileProperty_ClientDataFormat, asbd_size, &client_asbd);
+       if (err != noErr) {
+               cerr << "ExtAudioFileSetProperty3 " << err << endl;
+               ExtAudioFileDispose (af);
+               throw failed_constructor ();
+       }
+       
        if (build_peak) {
                if (initialize_peakfile (false, file)) {
-                       sf_close (sf);
-                       sf = 0;
+                       error << "initialize peakfile failed" << endmsg;
+                       ExtAudioFileDispose (af);
                        throw failed_constructor ();
                }
        }
 }
 
 CoreAudioSource::~CoreAudioSource ()
-
 {
-        GoingAway (this); /* EMIT SIGNAL */
+       GoingAway (this); /* EMIT SIGNAL */
 
-       if (sf) {
-               sf_close (sf);
+       if (af) {
+               ExtAudioFileDispose (af);
        }
 
        if (tmpbuf) {
@@ -118,35 +155,32 @@ CoreAudioSource::~CoreAudioSource ()
 }
 
 jack_nframes_t
-CoreAudioSource::read_unlocked (Sample *dst, jack_nframes_t start, jack_nframes_t cnt) const
+CoreAudioSource::read (Sample *dst, jack_nframes_t start, jack_nframes_t cnt, char * workbuf) const
 {
-       return read (dst, start, cnt);
-}
+       OSStatus err = noErr;
 
-jack_nframes_t
-CoreAudioSource::read (Sample *dst, jack_nframes_t start, jack_nframes_t cnt) const
-{
-       int32_t nread;
-       float *ptr;
-       uint32_t real_cnt;
-
-       if (sf_seek (sf, (off_t) start, SEEK_SET) < 0) {
-               char errbuf[256];
-               sf_error_str (0, errbuf, sizeof (errbuf) - 1);
-               error << string_compose(_("CoreAudioSource: could not seek to frame %1 within %2 (%3)"), start, _name.substr (1), errbuf) << endmsg;
+       err = ExtAudioFileSeek(af, start);
+       if (err != noErr) {
+               error << string_compose(_("CoreAudioSource: could not seek to frame %1 within %2 (%3)"), start, _name.substr (1), err) << endmsg;
                return 0;
        }
 
-       if (_info.channels == 1) {
-               jack_nframes_t ret = sf_read_float (sf, dst, cnt);
+       AudioBufferList abl;
+       abl.mNumberBuffers = 1;
+       abl.mBuffers[0].mNumberChannels = n_channels;
+       abl.mBuffers[0].mDataByteSize = cnt * sizeof(Sample);
+       abl.mBuffers[0].mData = dst;
+
+       if (n_channels == 1) {
+               err = ExtAudioFileRead(af, (UInt32*) &cnt, &abl);
                _read_data_count = cnt * sizeof(float);
-               return ret;
+               return cnt;
        }
 
-       real_cnt = cnt * _info.channels;
+       uint32_t real_cnt = cnt * n_channels;
 
        {
-               LockMonitor lm (_tmpbuf_lock, __LINE__, __FILE__);
+               Glib::Mutex::Lock lm (_tmpbuf_lock);
                
                if (tmpbufsize < real_cnt) {
                        
@@ -156,48 +190,31 @@ CoreAudioSource::read (Sample *dst, jack_nframes_t start, jack_nframes_t cnt) co
                        tmpbufsize = real_cnt;
                        tmpbuf = new float[tmpbufsize];
                }
+
+               abl.mBuffers[0].mDataByteSize = real_cnt * sizeof(Sample);
+               abl.mBuffers[0].mData = tmpbuf;
                
-               nread = sf_read_float (sf, tmpbuf, real_cnt);
-               ptr = tmpbuf + channel;
-               nread /= _info.channels;
+               err = ExtAudioFileRead(af, (UInt32*) &real_cnt, &abl);
+               float *ptr = tmpbuf + channel;
+               real_cnt /= n_channels;
                
                /* stride through the interleaved data */
                
-               for (int32_t n = 0; n < nread; ++n) {
+               for (uint32_t n = 0; n < real_cnt; ++n) {
                        dst[n] = *ptr;
-                       ptr += _info.channels;
+                       ptr += n_channels;
                }
        }
 
        _read_data_count = cnt * sizeof(float);
                
-       return nread;
+       return real_cnt;
 }
 
-string
-CoreAudioSource::peak_path (string audio_path)
+float
+CoreAudioSource::sample_rate() const
 {
-       /* XXX hardly bombproof! fix me */
-
-       struct stat stat_file;
-       struct stat stat_mount;
+       /* XXX taybin fill me in please */
 
-       string mp = mountpoint (audio_path);
-
-       stat (audio_path.c_str(), &stat_file);
-       stat (mp.c_str(), &stat_mount);
-
-       char buf[32];
-       snprintf (buf, sizeof (buf), "%ld-%ld-%d.peak", stat_mount.st_ino, stat_file.st_ino, channel);
-
-       string res = peak_dir;
-       res += buf;
-
-       return res;
-}
-
-string
-CoreAudioSource::old_peak_path (string audio_path)
-{
-       return peak_path (audio_path);
+       return 44100.0f;
 }