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