1 /*
2 File: AudioFileObject.h
3 Abstract: Part of CoreAudio Utility Classes
4 Version: 1.1
5
6 Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
7 Inc. ("Apple") in consideration of your agreement to the following
8 terms, and your use, installation, modification or redistribution of
9 this Apple software constitutes acceptance of these terms. If you do
10 not agree with these terms, please do not use, install, modify or
11 redistribute this Apple software.
12
13 In consideration of your agreement to abide by the following terms, and
14 subject to these terms, Apple grants you a personal, non-exclusive
15 license, under Apple's copyrights in this original Apple software (the
16 "Apple Software"), to use, reproduce, modify and redistribute the Apple
17 Software, with or without modifications, in source and/or binary forms;
18 provided that if you redistribute the Apple Software in its entirety and
19 without modifications, you must retain this notice and the following
20 text and disclaimers in all such redistributions of the Apple Software.
21 Neither the name, trademarks, service marks or logos of Apple Inc. may
22 be used to endorse or promote products derived from the Apple Software
23 without specific prior written permission from Apple. Except as
24 expressly stated in this notice, no other rights or licenses, express or
25 implied, are granted by Apple herein, including but not limited to any
26 patent rights that may be infringed by your derivative works or by other
27 works in which the Apple Software may be incorporated.
28
29 The Apple Software is provided by Apple on an "AS IS" basis. APPLE
30 MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
31 THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
32 FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
33 OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
34
35 IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
36 OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
37 SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
38 INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
39 MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
40 AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
41 STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
42 POSSIBILITY OF SUCH DAMAGE.
43
44 Copyright (C) 2014 Apple Inc. All Rights Reserved.
45
46 */
47 #ifndef _AudioFileObject_H_
48 #define _AudioFileObject_H_
49
50 #include <TargetConditionals.h>
51
52 #if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
53 #include <CoreAudio/CoreAudioTypes.h>
54 #include <AudioToolbox/AudioFile.h>
55 #include <AudioToolbox/AudioFormat.h>
56 #else
57 #include "CoreAudioTypes.h"
58 #include "AudioFile.h"
59 #include "AudioFormat.h"
60 #endif
61
62 #include "CompressedPacketTable.h"
63 #include "CACFDictionary.h"
64 #include "DataSource.h"
65 #include <vector>
66 #include <fcntl.h>
67
68 #if TARGET_OS_WIN32
69 #include <io.h>
70 #endif
71
72 /*
73 These are structs defined in 10.5. They are included here for compatibility with sources
74 */
75 #if COREAUDIOTYPES_VERSION < 1050
76
77 struct AudioFormatListItem
78 {
79 AudioStreamBasicDescription mASBD;
80 AudioChannelLayoutTag mChannelLayoutTag;
81 };
82 typedef struct AudioFormatListItem AudioFormatListItem;
83
84 struct AudioFormatInfo
85 {
86 AudioStreamBasicDescription mASBD;
87 const void* mMagicCookie;
88 UInt32 mMagicCookieSize;
89 };
90 typedef struct AudioFormatInfo AudioFormatInfo;
91
92 enum {
93
94 kAudioFormatProperty_FormatList = 'flst',
95 // Returns a list of AudioFormatListItem structs describing the audio formats contained within the compressed bit stream
96 // as described by the magic cookie.
97 // The specifier is an AudioFormatInfo struct. At a minimum formatID member of the ASBD struct must filled in. Other fields
98 // may be filled in.
99
100 kAudioFormatProperty_OutputFormatList = 'ofls',
101 // Returns a list of AudioFormatListItem structs describing the audio formats which may be obtained by decoding the format
102 // described by the specifier.
103 // The specifier is an AudioFormatInfo struct. At a minimum formatID member of the ASBD struct must filled in. Other fields
104 // may be filled in. If there is no magic cookie, then the number of channels and sample rate should be filled in.
105
106 };
107
108 enum {
109 kAudioFilePropertyPacketSizeUpperBound = 'pkub',
110 kAudioFilePropertyFormatList = 'flst',
111 kAudioFilePropertyEstimatedDuration = 'edur',
112 kAudioFilePropertyBitRate = 'brat'
113 };
114
115 enum {
116 kAudioFileCreateURLSelect = 0x0019,
117 kAudioFileOpenURLSelect = 0x001A,
118 kAudioFileFileDataIsThisFormatSelect = 0x001B
119 };
120 #endif
121
122 enum {
123 kTEMPAudioFilePropertySoundCheckDictionary = 'scdc',
124 kTEMPAudioFilePropertyLoudnessInfo = 'loud',
125 kTEMPAudioFilePropertyGenerateLoudnessInfo = 'glou'
126 };
127
128 const UInt32 kCopySoundDataBufferSize = 1024 * 1024;
129
130 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
131
132 // some files encode these as upper case
133 enum {
134 kUpperCase_IMACompression = 'IMA4', /*IMA 4:1*/
135 kUpperCase_ULawCompression = 'ULAW', /*�Law 2:1*/
136 kUpperCase_ALawCompression = 'ALAW', /*aLaw 2:1*/
137
138 kUpperCase_Float32 = 'FL32',
139 kUpperCase_Float64 = 'FL64'
140 };
141
142 enum
143 {
144 // in what header is this defined? what is it?
145 kGSM = 'agsm',
146 kUpperCase_GSM = 'GSM '
147 };
148
149 #define kPackedBESInt (kLinearPCMFormatFlagIsSignedInteger | kLinearPCMFormatFlagIsBigEndian | kLinearPCMFormatFlagIsPacked)
150 #define kPackedLESInt (kLinearPCMFormatFlagIsSignedInteger | kLinearPCMFormatFlagIsPacked)
151 #define kPackedBEFloat (kLinearPCMFormatFlagIsFloat | kLinearPCMFormatFlagIsBigEndian | kLinearPCMFormatFlagIsPacked)
152 #define kPackedLEFloat (kLinearPCMFormatFlagIsFloat | kLinearPCMFormatFlagIsPacked)
153
154 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
155
TransformPerm_FS_O(SInt8 inPerm)156 inline int TransformPerm_FS_O (SInt8 inPerm)
157 {
158 switch (inPerm) {
159 case kAudioFileReadPermission: return O_RDONLY;
160 case kAudioFileWritePermission: return O_WRONLY;
161 case kAudioFileReadWritePermission: return O_RDWR;
162 }
163 return O_RDONLY;
164 }
165
166 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
167 #pragma mark "File Error Handling"
168 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
169
170 #include <errno.h>
171 #include <CoreAudio/CoreAudioTypes.h>
172
AudioFileTranslateErrno(int err)173 inline OSErr AudioFileTranslateErrno(int err)
174 {
175 switch (err) {
176 #if !TARGET_OS_WIN32
177 case ENFILE:
178 #endif
179 case EMFILE:
180 return -42 /* kAudio_TooManyFilesOpenError */;
181 #if !TARGET_OS_WIN32
182 case EPERM:
183 case EROFS:
184 #endif
185 case EACCES:
186 case EEXIST:
187 return -54 /* kAudio_FilePermissionError */;
188 #if !TARGET_OS_WIN32
189 case EMLINK:
190 return (OSErr)'!pth' /* kAudio_BadFilePathError */;
191 case ENOTDIR:
192 case ELOOP:
193 #endif
194 case ENOENT:
195 default:
196 return (OSErr)kAudioFileUnspecifiedError;
197 }
198 }
199
200 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
201
202 class AudioFileObject
203 {
204 protected:
205
206 private:
207 SInt64 mNumBytes; // total bytes of audio data in the audio file
208 SInt64 mNumPackets; // total frames of audio data in the audio file
209 AudioStreamBasicDescription mDataFormat; // format of the audio data
210 SInt64 mDataOffset; // position if the file where audio data begins
211 UInt32 mIsOptimized; // 1 if there is nothing in the file following the audio data, 0 if there is
212 UInt32 mFileType; // file type of the audio file (i.e. AIFF, WAVE, etc.)
213 CFURLRef mFileRef; // URL of the file passed to AudioFileOpen or AudioFileCreate
214 int mFileD; // Ref num of the file after opening within Audio File
215 SInt8 mPermissions; // file permissions indicated by the caller, passed by AudioFileOpen or set with SetProperty function
216 Boolean mIsInitialized; // has the AudioFileObject for this file been intialized?
217 DataSource *mDataSource;
218 UInt32 mMaximumPacketSize;
219 CompressedPacketTable *mPacketTable;
220 UInt32 mDeferSizeUpdates;
221 Boolean mNeedsSizeUpdate;
222 Boolean mFirstSetFormat;
223 Boolean mAlignDataWithFillerChunks;
224
225 public:
226
AudioFileObject(UInt32 inFileType)227 AudioFileObject (UInt32 inFileType)
228 : mNumBytes(0),
229 mNumPackets(0),
230 mDataOffset(0),
231 mIsOptimized(1),
232 mFileType(inFileType),
233 mFileRef(NULL),
234 mFileD(-1),
235 mPermissions(0),
236 mIsInitialized (false),
237 mDataSource(0),
238 mMaximumPacketSize(0),
239 mPacketTable(NULL),
240 mDeferSizeUpdates(1),
241 mNeedsSizeUpdate(false),
242 mFirstSetFormat(true),
243 mAlignDataWithFillerChunks(true)
244 {
245 memset(&mDataFormat, 0, sizeof(mDataFormat));
246 }
247
248 virtual ~AudioFileObject();
249
250
251 /* Public API Function Implementation */
252 // The DoSomething() versions of these functions are wrappers that perform a standard prologue.
253 // The Something() methods are those which should be overridden in the subclasses.
254
255 OSStatus DoCreate( CFURLRef inFileRef,
256 const AudioStreamBasicDescription *inFormat,
257 UInt32 inFlags);
258
259 virtual OSStatus Create( CFURLRef inFileRef,
260 const AudioStreamBasicDescription *inFormat);
261
262 OSStatus DoOpen( CFURLRef inFileRef,
263 SInt8 inPermissions,
264 int inFD);
265
266 virtual OSStatus Open( CFURLRef inFileRef,
267 SInt8 inPermissions,
268 int inFD);
269
270 OSStatus DoOpenWithCallbacks(
271 void * inRefCon,
272 AudioFile_ReadProc inReadFunc,
273 AudioFile_WriteProc inWriteFunc,
274 AudioFile_GetSizeProc inGetSizeFunc,
275 AudioFile_SetSizeProc inSetSizeFunc);
276
277
278 OSStatus DoInitialize( CFURLRef inFileRef,
279 const AudioStreamBasicDescription *inFormat,
280 UInt32 inFlags);
281
282 virtual OSStatus Initialize( CFURLRef inFileRef,
283 const AudioStreamBasicDescription *inFormat,
284 UInt32 inFlags);
285
286 OSStatus DoInitializeWithCallbacks(
287 void * inRefCon,
288 AudioFile_ReadProc inReadFunc,
289 AudioFile_WriteProc inWriteFunc,
290 AudioFile_GetSizeProc inGetSizeFunc,
291 AudioFile_SetSizeProc inSetSizeFunc,
292 UInt32 inFileType,
293 const AudioStreamBasicDescription *inFormat,
294 UInt32 inFlags);
295
296 virtual OSStatus OpenFromDataSource(void);
297
298 virtual OSStatus InitializeDataSource(const AudioStreamBasicDescription *inFormat, UInt32 inFlags);
299
300 OSStatus DoClose();
301
302 virtual OSStatus Close();
303
304 OSStatus DoOptimize();
305
306 virtual OSStatus Optimize();
307
308 virtual OSStatus ReadBytes( Boolean inUseCache,
309 SInt64 inStartingByte,
310 UInt32 *ioNumBytes,
311 void *outBuffer);
312
313 virtual OSStatus WriteBytes( Boolean inUseCache,
314 SInt64 inStartingByte,
315 UInt32 *ioNumBytes,
316 const void *inBuffer);
317
318 virtual OSStatus ReadPackets( Boolean inUseCache,
319 UInt32 *outNumBytes,
320 AudioStreamPacketDescription *outPacketDescriptions,
321 SInt64 inStartingPacket,
322 UInt32 *ioNumPackets,
323 void *outBuffer);
324
325 virtual OSStatus ReadPacketData(
326 Boolean inUseCache,
327 UInt32 *ioNumBytes,
328 AudioStreamPacketDescription *outPacketDescriptions,
329 SInt64 inStartingPacket,
330 UInt32 *ioNumPackets,
331 void *outBuffer);
332
333 virtual OSStatus ReadPacketDataVBR(
334 Boolean inUseCache,
335 UInt32 *ioNumBytes,
336 AudioStreamPacketDescription *outPacketDescriptions,
337 SInt64 inStartingPacket,
338 UInt32 *ioNumPackets,
339 void *outBuffer);
340
341 virtual OSStatus HowManyPacketsCanBeReadIntoBuffer(UInt32* ioNumBytes, SInt64 inStartingPacket, UInt32 *ioNumPackets);
342
343 virtual OSStatus ReadPacketDataVBR_InTable(
344 Boolean inUseCache,
345 UInt32 *ioNumBytes,
346 AudioStreamPacketDescription *outPacketDescriptions,
347 SInt64 inStartingPacket,
348 UInt32 *ioNumPackets,
349 void *outBuffer);
350
351 virtual OSStatus WritePackets( Boolean inUseCache,
352 UInt32 inNumBytes,
353 const AudioStreamPacketDescription *inPacketDescriptions,
354 SInt64 inStartingPacket,
355 UInt32 *ioNumPackets,
356 const void *inBuffer);
357 /* Property Support */
358
359 virtual OSStatus GetPropertyInfo (
360 AudioFilePropertyID inPropertyID,
361 UInt32 *outDataSize,
362 UInt32 *isWritable);
363
364 virtual OSStatus GetProperty ( AudioFilePropertyID inPropertyID,
365 UInt32 *ioDataSize,
366 void *ioPropertyData);
367
368 virtual OSStatus SetProperty ( AudioFilePropertyID inPropertyID,
369 UInt32 inDataSize,
370 const void *inPropertyData);
371
GetFileType()372 UInt32 GetFileType() const { return mFileType; }
SetFileType(UInt32 inFileType)373 void SetFileType(UInt32 inFileType) { mFileType = inFileType; }
374
375 // this will set the format in memory only.
376 virtual OSStatus SetDataFormat(const AudioStreamBasicDescription* inStreamFormat);
377
378 // this will update the format info on disk and in memory.
379 virtual OSStatus UpdateDataFormat(const AudioStreamBasicDescription* inStreamFormat);
380
GetBytesPerPacket()381 const UInt32 GetBytesPerPacket() const { return mDataFormat.mBytesPerPacket; }
382
GetDataFormat()383 const AudioStreamBasicDescription &GetDataFormat() const { return mDataFormat; }
384
385 virtual OSStatus GetFormatListInfo( UInt32 &outDataSize,
386 UInt32 &outWritable);
387
388 virtual OSStatus GetFormatList( UInt32 &ioDataSize,
389 AudioFormatListItem *ioPropertyData);
390
391 virtual OSStatus SetFormatList( UInt32 inDataSize,
392 const AudioFormatListItem *inPropertyData);
393
UpdateSize()394 virtual OSStatus UpdateSize() { return noErr; }
DeferSizeUpdates()395 UInt32 DeferSizeUpdates() { return mDeferSizeUpdates; }
SetDeferSizeUpdates(UInt32 inFlag)396 void SetDeferSizeUpdates(UInt32 inFlag) { mDeferSizeUpdates = inFlag; }
397 OSStatus UpdateSizeIfNeeded();
398 OSStatus SizeChanged();
399
IsOptimized()400 Boolean IsOptimized() const { return mIsOptimized != 0; }
SetIsOptimized(Boolean inIsOptimized)401 void SetIsOptimized(Boolean inIsOptimized) { mIsOptimized = inIsOptimized ? 1 : 0; }
402
AlignDataWithFillerChunks()403 Boolean AlignDataWithFillerChunks() const { return mAlignDataWithFillerChunks; }
404
GetNumBytes()405 virtual SInt64 GetNumBytes() { return mNumBytes; }
SetNumBytes(SInt64 inNumBytes)406 virtual void SetNumBytes(SInt64 inNumBytes) { mNumBytes = inNumBytes; }
407
408 // this will update the header size info on disk
409 OSStatus UpdateNumBytes(SInt64 inNumBytes);
410
GetNumPackets()411 virtual SInt64 GetNumPackets(){ return mNumPackets; }
SetNumPackets(SInt64 inNumPackets)412 virtual void SetNumPackets(SInt64 inNumPackets) { mNumPackets = inNumPackets; }
413
414 // this will update the header size info on disk
415 OSStatus UpdateNumPackets(SInt64 inNumPackets);
416
417 virtual OSStatus PacketToFrame(SInt64 inPacket, SInt64& outFirstFrameInPacket);
418 virtual OSStatus FrameToPacket(SInt64 inFrame, SInt64& outPacket, UInt32& outFrameOffsetInPacket);
419
420 virtual OSStatus PacketToByte(AudioBytePacketTranslation* abpt);
421
422 virtual OSStatus ByteToPacket(AudioBytePacketTranslation* abpt);
423
424 virtual OSStatus GetBitRate( UInt32 *outBitRate);
425
426 virtual OSStatus GetMagicCookieDataSize( UInt32 *outDataSize,
427 UInt32 *isWritable);
428
429 virtual OSStatus GetMagicCookieData( UInt32 *ioDataSize,
430 void *ioPropertyData);
431
432 virtual OSStatus SetMagicCookieData( UInt32 inDataSize,
433 const void *inPropertyData);
434
435 virtual OSStatus GetMarkerListSize( UInt32 *outDataSize,
436 UInt32 *isWritable);
437
438 virtual OSStatus GetMarkerList( UInt32 *ioDataSize,
439 AudioFileMarkerList *ioMarkerList);
440
441 virtual OSStatus SetMarkerList( UInt32 inDataSize,
442 const AudioFileMarkerList *inMarkerList);
443
444
445 virtual OSStatus GetRegionListSize( UInt32 *outDataSize,
446 UInt32 *isWritable);
447
448 virtual OSStatus GetRegionList( UInt32 *ioDataSize,
449 AudioFileRegionList *ioRegionList);
450
451 virtual OSStatus SetRegionList( UInt32 inDataSize,
452 const AudioFileRegionList *inRegionList);
453
454 virtual OSStatus GetChannelLayoutSize( UInt32 *outDataSize,
455 UInt32 *isWritable);
456
457 virtual OSStatus GetChannelLayout( UInt32 *ioDataSize,
458 AudioChannelLayout *ioChannelLayout);
459
460 virtual OSStatus SetChannelLayout( UInt32 inDataSize,
461 const AudioChannelLayout *inChannelLayout);
462
463
464 virtual OSStatus GetInfoDictionarySize( UInt32 *outDataSize,
465 UInt32 *isWritable);
466
467 virtual OSStatus GetInfoDictionary( CACFDictionary *infoDict);
468
469 virtual OSStatus SetInfoDictionary( CACFDictionary *infoDict);
470
GetSoundCheckDictionarySize(UInt32 * outDataSize,UInt32 * isWritable)471 virtual OSStatus GetSoundCheckDictionarySize( UInt32 *outDataSize,
472 UInt32 *isWritable) { return kAudioFileUnsupportedPropertyError; }
473
GetSoundCheckDictionary(CACFDictionary * infoDict)474 virtual OSStatus GetSoundCheckDictionary( CACFDictionary *infoDict) { return kAudioFileUnsupportedPropertyError; }
475
SetSoundCheckDictionary(CACFDictionary * infoDict)476 virtual OSStatus SetSoundCheckDictionary( CACFDictionary *infoDict) { return kAudioFileUnsupportedPropertyError; }
477
GetLoudnessInfo(CACFDictionary * infoDict)478 virtual OSStatus GetLoudnessInfo( CACFDictionary *infoDict) { return kAudioFileUnsupportedPropertyError; }
479
GetSoundCheckDictionaryFromLoudnessInfo(CACFDictionary * outInfoDict)480 virtual OSStatus GetSoundCheckDictionaryFromLoudnessInfo(CACFDictionary* outInfoDict) { return kAudioFileUnsupportedPropertyError; }
GetLoudnessInfoFromSoundCheckDictionary(CACFDictionary * outInfoDict)481 virtual OSStatus GetLoudnessInfoFromSoundCheckDictionary(CACFDictionary* outInfoDict) { return kAudioFileUnsupportedPropertyError; }
482
SetLoudnessInfo(CACFDictionary * infoDict)483 virtual OSStatus SetLoudnessInfo( CACFDictionary *infoDict) { return kAudioFileUnsupportedPropertyError; }
484
GetLoudnessInfoSize(UInt32 * outDataSize,UInt32 * isWritable)485 virtual OSStatus GetLoudnessInfoSize( UInt32 *outDataSize,
486 UInt32 *isWritable) { return kAudioFileUnsupportedPropertyError; }
487
GenerateLoudnessInfo(CACFDictionary * infoDict)488 virtual OSStatus GenerateLoudnessInfo( CACFDictionary *infoDict) { return kAudioFileUnsupportedPropertyError; }
489
490 virtual OSStatus GetEstimatedDuration( Float64* duration);
491
492 virtual OSStatus CountUserData( UInt32 inUserDataID,
493 UInt32 *outNumberItems);
494
495 virtual OSStatus GetUserDataSize( UInt32 inUserDataID,
496 UInt32 inIndex,
497 UInt32 *outDataSize);
498
499 virtual OSStatus GetUserData( UInt32 inUserDataID,
500 UInt32 inIndex,
501 UInt32 *ioDataSize,
502 void *ioUserData);
503
504 virtual OSStatus SetUserData( UInt32 inUserDataID,
505 UInt32 inIndex,
506 UInt32 inDataSize,
507 const void *inUserData);
508
509 virtual OSStatus RemoveUserData( UInt32 inUserDataID,
510 UInt32 inIndex);
511
GetLyrics(CFStringRef * outLyrics)512 virtual OSStatus GetLyrics(CFStringRef *outLyrics) { return kAudioFileUnsupportedPropertyError; }
513
514
CanRead()515 Boolean CanRead() const { return mPermissions & kAudioFileReadPermission; }
CanWrite()516 Boolean CanWrite() const { return mPermissions & kAudioFileWritePermission; }
517
SetPermissions(SInt8 inPermissions)518 void SetPermissions(SInt8 inPermissions) { mPermissions = inPermissions; }
519
520 /* Other Helper Methods: (some may not be necessary depending on how things are refactored) */
521
522 OSStatus OpenFile(SInt8 inPermissions, int inFD);
523
524 OSStatus CreateDataFile (CFURLRef inFileRef, int &outFileD);
525
526 OSStatus AddDurationToInfoDictionary(CACFDictionary *infoDict, Float64 &inDuration);
527
528 virtual Boolean IsDataFormatSupported(const AudioStreamBasicDescription *inFormat) = 0;
529 virtual Boolean IsDataFormatValid(const AudioStreamBasicDescription *inFormat);
530
IsValidFilePosition(SInt64)531 virtual OSStatus IsValidFilePosition(SInt64 /*position*/) { return noErr; }
532
533 OSStatus MoveData(SInt64 fromPos, SInt64 toPos, SInt64 size);
534
535 /* Accessors: */
IsInitialized()536 Boolean IsInitialized() const { return mIsInitialized; }
SetInitialized(Boolean inFlag)537 void SetInitialized(Boolean inFlag) { mIsInitialized = inFlag; }
538
GetDataSource()539 DataSource* GetDataSource() const { return mDataSource; }
540 void SetDataSource(DataSource *inDataSource);
541
542 void SetURL (CFURLRef inURL);
543
GetMaximumPacketSize()544 virtual UInt32 GetMaximumPacketSize() { return mMaximumPacketSize; }
FindMaximumPacketSize()545 virtual UInt32 FindMaximumPacketSize() { return mMaximumPacketSize; }
SetMaximumPacketSize(const UInt32 inPacketSize)546 virtual void SetMaximumPacketSize(const UInt32 inPacketSize) { mMaximumPacketSize = inPacketSize; }
547
GetPacketSizeUpperBound()548 virtual UInt32 GetPacketSizeUpperBound() { return GetMaximumPacketSize (); }
549
GetDataOffset()550 SInt64 GetDataOffset() const { return mDataOffset; }
SetDataOffset(SInt64 inOffset)551 void SetDataOffset(SInt64 inOffset) { mDataOffset = inOffset; }
552
553 // I like this idiom better than DoesPacketTableExist+NewPacketTable:
554 CompressedPacketTable* GetPacketTable(Boolean inCreateIt = false)
555 {
556 if (!mPacketTable && inCreateIt)
557 mPacketTable = new CompressedPacketTable(mDataFormat.mFramesPerPacket);
558 return mPacketTable;
559 }
ClearPacketTable()560 void ClearPacketTable()
561 {
562 DeletePacketTable();
563 GetPacketTable(true);
564 }
565
566 virtual OSStatus ScanForPackets(SInt64 inToPacketCount, DataSource* inDataSrc = NULL, bool fullyParsedIfEndOfDataReached = true)
567 {
568 // In formats that read packets lazily, this will be overridden to scan for packets up to the index.
569 if (inToPacketCount > GetNumPackets())
570 return kAudioFileEndOfFileError;
571
572 return noErr;
573 }
574
AppendPacket(const AudioStreamPacketDescription & inPacket)575 void AppendPacket(const AudioStreamPacketDescription &inPacket)
576 {
577 CompressedPacketTable* packetTable = GetPacketTable(true);
578 UInt32 numFramesInPacket = mDataFormat.mFramesPerPacket ? mDataFormat.mFramesPerPacket : inPacket.mVariableFramesInPacket;
579
580 AudioStreamPacketDescriptionExtended pext;
581 memset(&pext, 0, sizeof(pext));
582 pext.mStartOffset = inPacket.mStartOffset;
583 pext.mDataByteSize = inPacket.mDataByteSize;
584 pext.mVariableFramesInPacket = inPacket.mVariableFramesInPacket;
585 pext.mFrameOffset = numFramesInPacket + (packetTable->size() ? packetTable->back().mFrameOffset : 0);
586
587 packetTable->push_back(pext);
588 if (inPacket.mDataByteSize > mMaximumPacketSize)
589 mMaximumPacketSize = inPacket.mDataByteSize;
590 }
DeletePacketTable()591 void DeletePacketTable() { delete mPacketTable; mPacketTable = NULL;}
GetPacketTableSize()592 SInt64 GetPacketTableSize() { return mPacketTable ? mPacketTable->size() : 0; }
GetPacketDescriptions(UInt32 inStartingPacket,UInt32 * ioDataSize,AudioStreamPacketDescription * outPacketDescriptions)593 OSStatus GetPacketDescriptions(UInt32 inStartingPacket, UInt32 *ioDataSize, AudioStreamPacketDescription *outPacketDescriptions)
594 {
595 if (outPacketDescriptions == NULL) return kAudioFileUnspecifiedError;
596 if (mPacketTable)
597 {
598 // only get as many packet descriptions as can fit in outPacketDescriptions
599 UInt32 count = *ioDataSize / sizeof(AudioStreamPacketDescription);
600 if (count + inStartingPacket > GetPacketTableSize())
601 count = (UInt32)(GetPacketTableSize() - inStartingPacket);
602
603 *ioDataSize = 0;
604 for (UInt32 i = inStartingPacket; i < (count + inStartingPacket); i++)
605 {
606 AudioStreamPacketDescription curPacket = (*mPacketTable)[i];
607 outPacketDescriptions[i].mStartOffset = curPacket.mStartOffset - GetDataOffset();
608 outPacketDescriptions[i].mVariableFramesInPacket = curPacket.mVariableFramesInPacket;
609 outPacketDescriptions[i].mDataByteSize = curPacket.mDataByteSize;
610 *ioDataSize += sizeof(AudioStreamPacketDescription);
611 }
612 }
613 else
614 *ioDataSize = 0;
615
616 return noErr;
617 }
618
619 #if DEBUG
DumpPacketTable()620 void DumpPacketTable()
621 {
622 if (mPacketTable) {
623 SInt64 size = mPacketTable->size();
624 printf("PacketTable size %d\n", (int)size);
625 for (SInt64 i = 0; i < size; i++) {
626 AudioStreamPacketDescription curPacket = (*mPacketTable)[i];
627 printf("dpkt %5qd %8qd %5d %5d\n", i, curPacket.mStartOffset, (int)curPacket.mDataByteSize, (int)curPacket.mVariableFramesInPacket);
628 }
629 }
630 }
631 #endif
632
GetNeedsSizeUpdate()633 Boolean GetNeedsSizeUpdate() const { return mNeedsSizeUpdate; }
SetNeedsSizeUpdate(Boolean inNeedsSizeUpdate)634 void SetNeedsSizeUpdate(Boolean inNeedsSizeUpdate) { mNeedsSizeUpdate = inNeedsSizeUpdate; }
635
GetURL()636 CFURLRef GetURL () const { return mFileRef; }
637
GetSourceBitDepth(SInt32 & outValue)638 virtual OSStatus GetSourceBitDepth(SInt32& outValue) { outValue = 0; return kAudioFileUnsupportedPropertyError; }
SetSourceBitDepth(SInt32 inValue)639 virtual OSStatus SetSourceBitDepth(SInt32 inValue) { return kAudioFileUnsupportedPropertyError; }
640
GetAlbumArtwork(CFDataRef & outValue)641 virtual OSStatus GetAlbumArtwork(CFDataRef& outValue) { outValue = NULL; return kAudioFileUnsupportedPropertyError; }
SetAlbumArtwork(CFDataRef inValue)642 virtual OSStatus SetAlbumArtwork(CFDataRef inValue){ return kAudioFileUnsupportedPropertyError; }
643
644 private:
645
SetAlignDataWithFillerChunks(Boolean inFlag)646 void SetAlignDataWithFillerChunks(Boolean inFlag) { mAlignDataWithFillerChunks = inFlag; }
647
648 OSStatus ValidateFormatAndData();
649
650 /* debug */
651 // virtual void PrintFile (FILE* inFile, const char *indent) = 0;
652 };
653
654 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
655
cfstrcmpi(CFStringRef a,CFStringRef b)656 inline Boolean cfstrcmpi(CFStringRef a, CFStringRef b)
657 {
658 // case insensitive CFString compare
659 return CFStringCompare(a, b, kCFCompareCaseInsensitive) == kCFCompareEqualTo;
660 }
661
662 CFBundleRef GetAudioToolboxBundle();
663
664
665 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
666
667 #endif
668