* Add SysEx Support to MidiModel / SMF
[ardour.git] / libs / ardour / caimportable.cc
1 #include <ardour/caimportable.h>
2 #include <sndfile.h>
3 #include <pbd/error.h>
4
5 #include "i18n.h"
6
7 using namespace ARDOUR;
8 using namespace std;
9 using namespace PBD;
10
11 CAImportableSource::CAImportableSource (const string& path)
12 {
13         try {
14                 af.Open (path.c_str());
15
16                 CAStreamBasicDescription file_format (af.GetFileDataFormat());
17                 CAStreamBasicDescription client_format (file_format);
18
19                 /* set canonial form (PCM, native float packed, 32 bit, with the correct number of channels
20                    and interleaved (since we plan to deinterleave ourselves)
21                 */
22
23                 client_format.SetCanonical(client_format.NumberChannels(), true);
24                 af.SetClientFormat (client_format);
25
26         } catch (CAXException& cax) {
27                 error << string_compose ("CAImportable: %1", cax.mOperation) << endmsg;
28                 throw failed_constructor ();
29         }
30
31 }
32
33 CAImportableSource::~CAImportableSource ()
34 {
35 }
36
37 nframes_t
38 CAImportableSource::read (Sample* buffer, nframes_t nframes) 
39 {
40         nframes_t nread = 0;
41         AudioBufferList abl;
42         nframes_t per_channel;
43         bool at_end = false;
44
45         abl.mNumberBuffers = 1;
46         abl.mBuffers[0].mNumberChannels = channels();
47
48         per_channel = nframes / abl.mBuffers[0].mNumberChannels;
49
50         while (nread < per_channel) {
51                 
52                 UInt32 new_cnt = per_channel - nread;
53                 
54                 abl.mBuffers[0].mDataByteSize = new_cnt * abl.mBuffers[0].mNumberChannels * sizeof(Sample);
55                 abl.mBuffers[0].mData = buffer + nread;
56                         
57                 try {
58                         af.Read (new_cnt, &abl);
59                 } catch (CAXException& cax) {
60                         error << string_compose("CAImportable: %1", cax.mOperation);
61                         return -1;
62                 }
63
64                 if (new_cnt == 0) {
65                         /* EOF */
66                         at_end = true;
67                         break;
68                 }
69
70                 nread += new_cnt;
71         }
72
73         if (!at_end && nread < per_channel) {
74                 return 0;
75         } else {
76                 return nread *  abl.mBuffers[0].mNumberChannels;
77         }
78 }
79
80 uint
81 CAImportableSource::channels () const 
82 {
83         return af.GetFileDataFormat().NumberChannels();
84 }
85
86 nframes_t
87 CAImportableSource::length () const 
88 {
89         return af.GetNumberFrames();
90 }
91
92 nframes_t
93 CAImportableSource::samplerate() const
94 {
95         CAStreamBasicDescription client_asbd;
96
97         try {
98                 client_asbd = af.GetClientDataFormat ();
99         } catch (CAXException& cax) {
100                 error << string_compose ("CAImportable: %1", cax.mOperation) << endmsg;
101                 return 0.0;
102         }
103
104         return client_asbd.mSampleRate;
105 }
106
107 void
108 CAImportableSource::seek (nframes_t pos)
109 {
110         try {
111                 af.Seek (pos);
112         } catch (CAXException& cax) {
113                 error << string_compose ("CAImportable: %1 to %2", cax.mOperation, pos) << endmsg;
114         }
115 }
116
117         
118