summaryrefslogtreecommitdiff
path: root/libs/appleutility/CoreAudio/AudioFile
diff options
context:
space:
mode:
Diffstat (limited to 'libs/appleutility/CoreAudio/AudioFile')
-rw-r--r--libs/appleutility/CoreAudio/AudioFile/AFPublic/AudioFileComponentBase.cpp1040
-rw-r--r--libs/appleutility/CoreAudio/AudioFile/AFPublic/AudioFileComponentBase.h311
-rw-r--r--libs/appleutility/CoreAudio/AudioFile/AFPublic/AudioFileFormat.cpp71
-rw-r--r--libs/appleutility/CoreAudio/AudioFile/AFPublic/AudioFileFormat.h125
-rw-r--r--libs/appleutility/CoreAudio/AudioFile/AFPublic/AudioFileObject.cpp1966
-rw-r--r--libs/appleutility/CoreAudio/AudioFile/AFPublic/AudioFileObject.h667
-rw-r--r--libs/appleutility/CoreAudio/AudioFile/AFPublic/CompressedPacketTable.cpp216
-rw-r--r--libs/appleutility/CoreAudio/AudioFile/AFPublic/CompressedPacketTable.h186
-rw-r--r--libs/appleutility/CoreAudio/AudioFile/AFPublic/DataSource.cpp689
-rw-r--r--libs/appleutility/CoreAudio/AudioFile/AFPublic/DataSource.h372
10 files changed, 5643 insertions, 0 deletions
diff --git a/libs/appleutility/CoreAudio/AudioFile/AFPublic/AudioFileComponentBase.cpp b/libs/appleutility/CoreAudio/AudioFile/AFPublic/AudioFileComponentBase.cpp
new file mode 100644
index 0000000000..053da0a5d0
--- /dev/null
+++ b/libs/appleutility/CoreAudio/AudioFile/AFPublic/AudioFileComponentBase.cpp
@@ -0,0 +1,1040 @@
+/*
+ File: AudioFileComponentBase.cpp
+ Abstract: AudioFileComponentBase.h
+ Version: 1.1
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms. If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+
+*/
+#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
+ #include <AudioToolbox/AudioFileComponent.h>
+#else
+ #include "AudioFileComponent.h"
+#endif
+
+#include "AudioFileComponentBase.h"
+
+#if TARGET_OS_MAC
+ #if __LP64__
+ // comp instance, parameters in forward order
+ #define PARAM(_typ, _name, _index, _nparams) \
+ _typ _name = *(_typ *)&params->params[_index + 1];
+ #else
+ // parameters in reverse order, then comp instance
+ #define PARAM(_typ, _name, _index, _nparams) \
+ _typ _name = *(_typ *)&params->params[_nparams - 1 - _index];
+ #endif
+#elif TARGET_OS_WIN32
+ // (no comp instance), parameters in forward order
+ #define PARAM(_typ, _name, _index, _nparams) \
+ _typ _name = *(_typ *)&params->params[_index];
+#endif
+
+#define ACPI ((AudioComponentPlugInInstance *)self)
+#define AFC ((AudioFileComponentBase *)&ACPI->mInstanceStorage)
+
+//----------------------------------------------------------------------------------------
+
+static OSStatus CreateURL(
+ void * self,
+ CFURLRef inFileRef,
+ const AudioStreamBasicDescription *inFormat,
+ UInt32 inFlags)
+{
+ return AFC->AFAPI_CreateURL(inFileRef, inFormat, inFlags);
+}
+
+static OSStatus OpenURL(
+ void * self,
+ CFURLRef inFileRef,
+ SInt8 inPermissions,
+ int inFileDescriptor)
+{
+ return AFC->AFAPI_OpenURL(inFileRef, inPermissions, inFileDescriptor);
+}
+
+static OSStatus OpenWithCallbacks(
+ void * self,
+ void * inRefCon,
+ AudioFile_ReadProc inReadFunc,
+ AudioFile_WriteProc inWriteFunc,
+ AudioFile_GetSizeProc inGetSizeFunc,
+ AudioFile_SetSizeProc inSetSizeFunc)
+{
+ return AFC->AFAPI_OpenWithCallbacks(inRefCon, inReadFunc, inWriteFunc, inGetSizeFunc, inSetSizeFunc);
+}
+
+static OSStatus InitializeWithCallbacks(
+ void * self,
+ void * inRefCon,
+ AudioFile_ReadProc inReadFunc,
+ AudioFile_WriteProc inWriteFunc,
+ AudioFile_GetSizeProc inGetSizeFunc,
+ AudioFile_SetSizeProc inSetSizeFunc,
+ UInt32 inFileType,
+ const AudioStreamBasicDescription *inFormat,
+ UInt32 inFlags)
+{
+ return AFC->AFAPI_InitializeWithCallbacks(inRefCon, inReadFunc, inWriteFunc, inGetSizeFunc, inSetSizeFunc, inFileType, inFormat, inFlags);
+}
+
+static OSStatus Close(
+ void * self)
+{
+ return AFC->AFAPI_Close();
+}
+
+static OSStatus Optimize(
+ void * self)
+{
+ return AFC->AFAPI_Optimize();
+}
+
+static OSStatus ReadBytes(
+ void * self,
+ Boolean inUseCache,
+ SInt64 inStartingByte,
+ UInt32 *ioNumBytes,
+ void *outBuffer)
+{
+ return AFC->AFAPI_ReadBytes(inUseCache, inStartingByte, ioNumBytes, outBuffer);
+}
+
+
+static OSStatus WriteBytes(
+ void * self,
+ Boolean inUseCache,
+ SInt64 inStartingByte,
+ UInt32 *ioNumBytes,
+ const void *inBuffer)
+{
+ return AFC->AFAPI_WriteBytes(inUseCache, inStartingByte, ioNumBytes, inBuffer);
+}
+
+
+static OSStatus ReadPackets(
+ void * self,
+ Boolean inUseCache,
+ UInt32 *outNumBytes,
+ AudioStreamPacketDescription *outPacketDescriptions,
+ SInt64 inStartingPacket,
+ UInt32 *ioNumPackets,
+ void *outBuffer)
+{
+ return AFC->AFAPI_ReadPackets(inUseCache, outNumBytes, outPacketDescriptions,
+ inStartingPacket, ioNumPackets, outBuffer);
+}
+
+static OSStatus ReadPacketData(
+ void * self,
+ Boolean inUseCache,
+ UInt32 *ioNumBytes,
+ AudioStreamPacketDescription *outPacketDescriptions,
+ SInt64 inStartingPacket,
+ UInt32 *ioNumPackets,
+ void *outBuffer)
+{
+ return AFC->AFAPI_ReadPacketData(inUseCache, ioNumBytes, outPacketDescriptions,
+ inStartingPacket, ioNumPackets, outBuffer);
+}
+
+#if COREAUDIOTYPES_VERSION < 1050
+static OSStatus WritePackets(
+ void * self,
+ Boolean inUseCache,
+ UInt32 inNumBytes,
+ AudioStreamPacketDescription *inPacketDescriptions,
+ SInt64 inStartingPacket,
+ UInt32 *ioNumPackets,
+ const void *inBuffer)
+#else
+static OSStatus WritePackets(
+ void * self,
+ Boolean inUseCache,
+ UInt32 inNumBytes,
+ const AudioStreamPacketDescription *inPacketDescriptions,
+ SInt64 inStartingPacket,
+ UInt32 *ioNumPackets,
+ const void *inBuffer)
+#endif
+{
+ return AFC->AFAPI_WritePackets(inUseCache, inNumBytes,
+ (const AudioStreamPacketDescription *)inPacketDescriptions, // this should be const (and is in 10.5 headers)
+ inStartingPacket, ioNumPackets, inBuffer);
+}
+
+static OSStatus GetPropertyInfo(
+ void * self,
+ AudioFilePropertyID inPropertyID,
+ UInt32 *outDataSize,
+ UInt32 *isWritable)
+{
+ return AFC->AFAPI_GetPropertyInfo(inPropertyID, outDataSize, isWritable);
+}
+
+static OSStatus GetProperty(
+ void * self,
+ AudioFilePropertyID inPropertyID,
+ UInt32 *ioDataSize,
+ void *ioData)
+{
+ return AFC->AFAPI_GetProperty(inPropertyID, ioDataSize, ioData);
+}
+
+
+static OSStatus SetProperty(
+ void * self,
+ AudioFilePropertyID inPropertyID,
+ UInt32 inDataSize,
+ const void *inData)
+{
+ return AFC->AFAPI_SetProperty(inPropertyID, inDataSize, inData);
+}
+
+static OSStatus CountUserData(
+ void * self,
+ UInt32 inUserDataID,
+ UInt32 *outNumberItems)
+{
+ return AFC->AFAPI_CountUserData(inUserDataID, outNumberItems);
+}
+
+static OSStatus GetUserDataSize(
+ void * self,
+ UInt32 inUserDataID,
+ UInt32 inIndex,
+ UInt32 *outDataSize)
+{
+ return AFC->AFAPI_GetUserDataSize(inUserDataID, inIndex, outDataSize);
+}
+
+static OSStatus GetUserData(
+ void * self,
+ UInt32 inUserDataID,
+ UInt32 inIndex,
+ UInt32 *ioUserDataSize,
+ void *outUserData)
+{
+ return AFC->AFAPI_GetUserData(inUserDataID, inIndex, ioUserDataSize, outUserData);
+}
+
+static OSStatus SetUserData(
+ void * self,
+ UInt32 inUserDataID,
+ UInt32 inIndex,
+ UInt32 inUserDataSize,
+ const void *inUserData)
+{
+ return AFC->AFAPI_SetUserData(inUserDataID, inIndex, inUserDataSize, inUserData);
+}
+
+static OSStatus RemoveUserData(
+ void * self,
+ UInt32 inUserDataID,
+ UInt32 inIndex)
+{
+ return AFC->AFAPI_RemoveUserData(inUserDataID, inIndex);
+}
+
+static OSStatus ExtensionIsThisFormat(
+ void * self,
+ CFStringRef inExtension,
+ UInt32 *outResult)
+{
+ AudioFileFormatBase* aff = AFC->GetAudioFileFormatBase();
+ if (!aff) return kAudio_ParamError;
+
+ UInt32 res = aff->ExtensionIsThisFormat(inExtension);
+ if (outResult) *outResult = res;
+ return noErr;
+}
+
+static OSStatus FileDataIsThisFormat(
+ void * self,
+ UInt32 inDataByteSize,
+ const void* inData,
+ UInt32 *outResult)
+{
+ AudioFileFormatBase* aff = AFC->GetAudioFileFormatBase();
+ if (!aff) return kAudio_ParamError;
+
+ UncertainResult res = aff->FileDataIsThisFormat(inDataByteSize, inData);
+ if (outResult) *outResult = res;
+ return noErr;
+}
+
+static OSStatus GetGlobalInfoSize(
+ void * self,
+ AudioFilePropertyID inPropertyID,
+ UInt32 inSpecifierSize,
+ const void* inSpecifier,
+ UInt32 *outPropertySize)
+{
+ return AFC->AFAPI_GetGlobalInfoSize(inPropertyID, inSpecifierSize, inSpecifier, outPropertySize);
+}
+
+static OSStatus GetGlobalInfo(
+ void * self,
+ AudioFilePropertyID inPropertyID,
+ UInt32 inSpecifierSize,
+ const void* inSpecifier,
+ UInt32 *ioPropertySize,
+ void *ioPropertyData)
+{
+ return AFC->AFAPI_GetGlobalInfo(inPropertyID, inSpecifierSize, inSpecifier, ioPropertySize, ioPropertyData);
+}
+
+//----------------------------------------------------------------------------------------
+
+
+AudioFileComponentBase::AudioFileComponentBase(AudioComponentInstance inInstance)
+ : ComponentBase(inInstance)
+{
+}
+
+AudioFileComponentBase::~AudioFileComponentBase()
+{
+}
+
+AudioFileObjectComponentBase::AudioFileObjectComponentBase(AudioComponentInstance inInstance)
+ : AudioFileComponentBase(inInstance), mAudioFileObject(0)
+{
+ // derived class should create an AudioFileObject here and if NULL, the AudioFormat as well.
+}
+
+AudioFileObjectComponentBase::~AudioFileObjectComponentBase()
+{
+ delete mAudioFileObject;
+}
+
+OSStatus AudioFileObjectComponentBase::AFAPI_CreateURL(
+ CFURLRef inFileRef,
+ const AudioStreamBasicDescription *inFormat,
+ UInt32 inFlags)
+{
+ if (!mAudioFileObject) return kAudio_ParamError;
+
+ OSStatus result = mAudioFileObject->DoCreate (inFileRef, inFormat, inFlags);
+ return result;
+}
+
+
+OSStatus AudioFileObjectComponentBase::AFAPI_OpenURL(
+ CFURLRef inFileRef,
+ SInt8 inPermissions,
+ int inFD)
+{
+ if (!mAudioFileObject) return kAudio_ParamError;
+
+ OSStatus result = mAudioFileObject->DoOpen(inFileRef, inPermissions, inFD);
+ return result;
+}
+
+
+OSStatus AudioFileObjectComponentBase::AFAPI_OpenWithCallbacks(
+ void * inRefCon,
+ AudioFile_ReadProc inReadFunc,
+ AudioFile_WriteProc inWriteFunc,
+ AudioFile_GetSizeProc inGetSizeFunc,
+ AudioFile_SetSizeProc inSetSizeFunc)
+{
+ if (!mAudioFileObject) return kAudio_ParamError;
+ return mAudioFileObject->DoOpenWithCallbacks(inRefCon, inReadFunc, inWriteFunc, inGetSizeFunc, inSetSizeFunc);
+}
+
+
+OSStatus AudioFileObjectComponentBase::AFAPI_InitializeWithCallbacks(
+ void * inRefCon,
+ AudioFile_ReadProc inReadFunc,
+ AudioFile_WriteProc inWriteFunc,
+ AudioFile_GetSizeProc inGetSizeFunc,
+ AudioFile_SetSizeProc inSetSizeFunc,
+ UInt32 inFileType,
+ const AudioStreamBasicDescription *inFormat,
+ UInt32 inFlags)
+{
+ if (!mAudioFileObject) return kAudio_ParamError;
+ return mAudioFileObject->DoInitializeWithCallbacks(inRefCon, inReadFunc, inWriteFunc, inGetSizeFunc, inSetSizeFunc,
+ inFileType, inFormat, inFlags);
+}
+
+
+OSStatus AudioFileObjectComponentBase::AFAPI_Close()
+{
+ if (!mAudioFileObject) return kAudio_ParamError;
+ return mAudioFileObject->DoClose();
+}
+
+OSStatus AudioFileObjectComponentBase::AFAPI_Optimize()
+{
+ if (!mAudioFileObject) return kAudio_ParamError;
+ return mAudioFileObject->DoOptimize();
+}
+
+OSStatus AudioFileObjectComponentBase::AFAPI_ReadBytes(
+ Boolean inUseCache,
+ SInt64 inStartingByte,
+ UInt32 *ioNumBytes,
+ void *outBuffer)
+{
+ if (!mAudioFileObject) return kAudio_ParamError;
+ return mAudioFileObject->ReadBytes(inUseCache, inStartingByte, ioNumBytes, outBuffer);
+}
+
+
+OSStatus AudioFileObjectComponentBase::AFAPI_WriteBytes(
+ Boolean inUseCache,
+ SInt64 inStartingByte,
+ UInt32 *ioNumBytes,
+ const void *inBuffer)
+{
+ if (!mAudioFileObject) return kAudio_ParamError;
+ return mAudioFileObject->WriteBytes(inUseCache, inStartingByte, ioNumBytes, inBuffer);
+}
+
+
+
+
+OSStatus AudioFileObjectComponentBase::AFAPI_ReadPackets(
+ Boolean inUseCache,
+ UInt32 *outNumBytes,
+ AudioStreamPacketDescription *outPacketDescriptions,
+ SInt64 inStartingPacket,
+ UInt32 *ioNumPackets,
+ void *outBuffer)
+{
+ if (!mAudioFileObject) return kAudio_ParamError;
+ return mAudioFileObject->ReadPackets(inUseCache, outNumBytes, outPacketDescriptions,
+ inStartingPacket, ioNumPackets, outBuffer);
+}
+
+OSStatus AudioFileObjectComponentBase::AFAPI_ReadPacketData(
+ Boolean inUseCache,
+ UInt32 *ioNumBytes,
+ AudioStreamPacketDescription *outPacketDescriptions,
+ SInt64 inStartingPacket,
+ UInt32 *ioNumPackets,
+ void *outBuffer)
+{
+ if (!mAudioFileObject) return kAudio_ParamError;
+ return mAudioFileObject->ReadPacketData(inUseCache, ioNumBytes, outPacketDescriptions,
+ inStartingPacket, ioNumPackets, outBuffer);
+}
+
+
+OSStatus AudioFileObjectComponentBase::AFAPI_WritePackets(
+ Boolean inUseCache,
+ UInt32 inNumBytes,
+ const AudioStreamPacketDescription *inPacketDescriptions,
+ SInt64 inStartingPacket,
+ UInt32 *ioNumPackets,
+ const void *inBuffer)
+{
+ if (!mAudioFileObject) return kAudio_ParamError;
+ return mAudioFileObject->WritePackets(inUseCache, inNumBytes, inPacketDescriptions,
+ inStartingPacket, ioNumPackets, inBuffer);
+}
+
+
+
+OSStatus AudioFileObjectComponentBase::AFAPI_GetPropertyInfo(
+ AudioFilePropertyID inPropertyID,
+ UInt32 *outDataSize,
+ UInt32 *isWritable)
+{
+ if (!mAudioFileObject) return kAudio_ParamError;
+ return mAudioFileObject->GetPropertyInfo(inPropertyID, outDataSize, isWritable);
+}
+
+
+OSStatus AudioFileObjectComponentBase::AFAPI_GetProperty(
+ AudioFilePropertyID inPropertyID,
+ UInt32 *ioPropertySize,
+ void *ioPropertyData)
+{
+ OSStatus err = noErr;
+
+ if (!ioPropertyData) return kAudio_ParamError;
+
+ if (!mAudioFileObject) return kAudio_ParamError;
+ err = mAudioFileObject->GetProperty(inPropertyID, ioPropertySize, ioPropertyData);
+ return err;
+}
+
+
+OSStatus AudioFileObjectComponentBase::AFAPI_SetProperty(
+ AudioFilePropertyID inPropertyID,
+ UInt32 inPropertySize,
+ const void *inPropertyData)
+{
+ if (!mAudioFileObject) return kAudio_ParamError;
+ return mAudioFileObject->SetProperty(inPropertyID, inPropertySize, inPropertyData);
+}
+
+
+OSStatus AudioFileObjectComponentBase::AFAPI_CountUserData(
+ UInt32 inUserDataID,
+ UInt32 *outNumberItems)
+{
+ if (!mAudioFileObject) return kAudio_ParamError;
+ return mAudioFileObject->CountUserData(inUserDataID, outNumberItems);
+}
+
+OSStatus AudioFileObjectComponentBase::AFAPI_GetUserDataSize(
+ UInt32 inUserDataID,
+ UInt32 inIndex,
+ UInt32 *outUserDataSize)
+{
+ if (!mAudioFileObject) return kAudio_ParamError;
+ return mAudioFileObject->GetUserDataSize(inUserDataID, inIndex, outUserDataSize);
+}
+
+OSStatus AudioFileObjectComponentBase::AFAPI_GetUserData(
+ UInt32 inUserDataID,
+ UInt32 inIndex,
+ UInt32 *ioUserDataSize,
+ void *outUserData)
+{
+ if (!mAudioFileObject) return kAudio_ParamError;
+ return mAudioFileObject->GetUserData(inUserDataID, inIndex, ioUserDataSize, outUserData);
+}
+
+OSStatus AudioFileObjectComponentBase::AFAPI_SetUserData(
+ UInt32 inUserDataID,
+ UInt32 inIndex,
+ UInt32 inUserDataSize,
+ const void *inUserData)
+{
+ if (!mAudioFileObject) return kAudio_ParamError;
+ return mAudioFileObject->SetUserData(inUserDataID, inIndex, inUserDataSize, inUserData);
+}
+
+OSStatus AudioFileObjectComponentBase::AFAPI_RemoveUserData(
+ UInt32 inUserDataID,
+ UInt32 inIndex)
+{
+ if (!mAudioFileObject) return kAudio_ParamError;
+ return mAudioFileObject->RemoveUserData(inUserDataID, inIndex);
+}
+
+
+OSStatus AudioFileComponentBase::AFAPI_GetGlobalInfoSize(
+ AudioFilePropertyID inPropertyID,
+ UInt32 inSpecifierSize,
+ const void* inSpecifier,
+ UInt32 *outPropertySize)
+{
+ OSStatus err = noErr;
+
+ switch (inPropertyID)
+ {
+ case kAudioFileComponent_CanRead :
+ case kAudioFileComponent_CanWrite :
+ *outPropertySize = sizeof(UInt32);
+ break;
+
+ case kAudioFileComponent_FileTypeName :
+ *outPropertySize = sizeof(CFStringRef);
+ break;
+
+ case kAudioFileComponent_ExtensionsForType :
+ *outPropertySize = sizeof(CFArrayRef);
+ break;
+
+ case kAudioFileComponent_UTIsForType :
+ *outPropertySize = sizeof(CFArrayRef);
+ break;
+
+ case kAudioFileComponent_MIMETypesForType :
+ *outPropertySize = sizeof(CFArrayRef);
+ break;
+
+ case kAudioFileComponent_AvailableFormatIDs :
+ {
+ UInt32 size = 0xFFFFFFFF;
+ err = GetAudioFileFormatBase()->GetAvailableFormatIDs(&size, NULL);
+ if (!err) *outPropertySize = size;
+ break;
+ }
+ case kAudioFileComponent_HFSTypeCodesForType :
+ {
+ UInt32 size = 0xFFFFFFFF;
+ err = GetAudioFileFormatBase()->GetHFSCodes(&size, NULL);
+ if (!err) *outPropertySize = size;
+ break;
+ }
+ case kAudioFileComponent_AvailableStreamDescriptionsForFormat :
+ {
+ if (inSpecifierSize != sizeof(UInt32)) return kAudioFileBadPropertySizeError;
+ UInt32 inFormatID = *(UInt32*)inSpecifier;
+ err = GetAudioFileFormatBase()->GetAvailableStreamDescriptions(inFormatID, outPropertySize, NULL);
+ }
+ break;
+
+ default:
+ err = kAudioFileUnsupportedPropertyError;
+ }
+ return err;
+}
+
+
+OSStatus AudioFileComponentBase::AFAPI_GetGlobalInfo(
+ AudioFilePropertyID inPropertyID,
+ UInt32 inSpecifierSize,
+ const void* inSpecifier,
+ UInt32 *ioPropertySize,
+ void *ioPropertyData)
+{
+ OSStatus err = noErr;
+
+ if (!ioPropertyData || !ioPropertySize) return kAudio_ParamError;
+
+ switch (inPropertyID)
+ {
+ case kAudioFileComponent_CanRead :
+ {
+ if (*ioPropertySize != sizeof(UInt32)) return kAudioFileBadPropertySizeError;
+ UInt32* flag = (UInt32*)ioPropertyData;
+ *flag = GetAudioFileFormatBase()->CanRead();
+ }
+ break;
+
+ case kAudioFileComponent_CanWrite :
+ {
+ if (*ioPropertySize != sizeof(UInt32)) return kAudioFileBadPropertySizeError;
+ UInt32* flag = (UInt32*)ioPropertyData;
+ *flag = GetAudioFileFormatBase()->CanWrite();
+ }
+ break;
+
+ case kAudioFileComponent_FileTypeName :
+ {
+ if (*ioPropertySize != sizeof(CFStringRef)) return kAudioFileBadPropertySizeError;
+ CFStringRef* name = (CFStringRef*)ioPropertyData;
+ GetAudioFileFormatBase()->GetFileTypeName(name);
+ }
+ break;
+
+ case kAudioFileComponent_ExtensionsForType :
+ {
+ if (*ioPropertySize != sizeof(CFArrayRef)) return kAudioFileBadPropertySizeError;
+ CFArrayRef* array = (CFArrayRef*)ioPropertyData;
+ GetAudioFileFormatBase()->GetExtensions(array);
+ }
+ break;
+
+ case kAudioFileComponent_UTIsForType :
+ {
+ if (*ioPropertySize != sizeof(CFArrayRef)) return kAudioFileBadPropertySizeError;
+ CFArrayRef* array = (CFArrayRef*)ioPropertyData;
+ GetAudioFileFormatBase()->GetUTIs(array);
+ }
+ break;
+
+ case kAudioFileComponent_MIMETypesForType :
+ {
+ if (*ioPropertySize != sizeof(CFArrayRef)) return kAudioFileBadPropertySizeError;
+ CFArrayRef* array = (CFArrayRef*)ioPropertyData;
+ GetAudioFileFormatBase()->GetMIMETypes(array);
+ }
+ break;
+
+ case kAudioFileComponent_HFSTypeCodesForType :
+ {
+ err = GetAudioFileFormatBase()->GetHFSCodes(ioPropertySize, ioPropertyData);
+ }
+ break;
+
+ case kAudioFileComponent_AvailableFormatIDs :
+ {
+ err = GetAudioFileFormatBase()->GetAvailableFormatIDs(ioPropertySize, ioPropertyData);
+ }
+ break;
+
+ case kAudioFileComponent_AvailableStreamDescriptionsForFormat :
+ {
+ if (inSpecifierSize != sizeof(UInt32)) return kAudioFileBadPropertySizeError;
+ UInt32 inFormatID = *(UInt32*)inSpecifier;
+ err = GetAudioFileFormatBase()->GetAvailableStreamDescriptions(inFormatID, ioPropertySize, ioPropertyData);
+ }
+ break;
+
+ default:
+ err = kAudioFileUnsupportedPropertyError;
+ }
+ return err;
+}
+
+
+#if !CA_USE_AUDIO_PLUGIN_ONLY
+OSStatus AudioFileComponentBase::ComponentEntryDispatch(ComponentParameters* params, AudioFileComponentBase* inThis)
+{
+ OSStatus result = noErr;
+ if (inThis == NULL) return kAudio_ParamError;
+
+ try
+ {
+ switch (params->what)
+ {
+ case kComponentCanDoSelect:
+ switch (GetSelectorForCanDo(params))
+ {
+ case kAudioFileCreateURLSelect:
+ case kAudioFileOpenURLSelect:
+ case kAudioFileOpenWithCallbacksSelect:
+ case kAudioFileInitializeWithCallbacksSelect:
+ case kAudioFileCloseSelect:
+ case kAudioFileOptimizeSelect:
+ case kAudioFileReadBytesSelect:
+ case kAudioFileWriteBytesSelect:
+ case kAudioFileReadPacketsSelect:
+ case kAudioFileWritePacketsSelect:
+ case kAudioFileGetPropertyInfoSelect:
+ case kAudioFileGetPropertySelect:
+ case kAudioFileSetPropertySelect:
+ case kAudioFileExtensionIsThisFormatSelect:
+ case kAudioFileFileDataIsThisFormatSelect:
+ case kAudioFileGetGlobalInfoSizeSelect:
+ case kAudioFileGetGlobalInfoSelect:
+
+ case kAudioFileCountUserDataSelect:
+ case kAudioFileGetUserDataSizeSelect:
+ case kAudioFileGetUserDataSelect:
+ case kAudioFileSetUserDataSelect:
+ case kAudioFileRemoveUserDataSelect:
+ result = 1;
+ break;
+ default:
+ // these are no longer supported
+/* case kAudioFileCreateSelect:
+ case kAudioFileOpenSelect:
+ case kAudioFileInitializeSelect:
+*/ result = ComponentBase::ComponentEntryDispatch(params, inThis);
+ };
+ break;
+
+ case kAudioFileCreateURLSelect:
+ {
+ PARAM(CFURLRef, inFileRef, 0, 3);
+ PARAM(const AudioStreamBasicDescription*, inFormat, 1, 3);
+ PARAM(UInt32, inFlags, 2, 3);
+
+ result = inThis->AFAPI_CreateURL(inFileRef, inFormat, inFlags);
+ }
+ break;
+ case kAudioFileOpenURLSelect:
+ {
+ PARAM(CFURLRef, inFileRef, 0, 3);
+ PARAM(SInt32, inPermissions, 1, 3);
+ PARAM(int, inFileDescriptor, 2, 3);
+
+ result = inThis->AFAPI_OpenURL(inFileRef, inPermissions, inFileDescriptor);
+ }
+ break;
+ case kAudioFileOpenWithCallbacksSelect:
+ {
+ PARAM(void*, inRefCon, 0, 5);
+ PARAM(AudioFile_ReadProc, inReadFunc, 1, 5);
+ PARAM(AudioFile_WriteProc, inWriteFunc, 2, 5);
+ PARAM(AudioFile_GetSizeProc, inGetSizeFunc, 3, 5);
+ PARAM(AudioFile_SetSizeProc, inSetSizeFunc, 4, 5);
+
+ result = inThis->AFAPI_OpenWithCallbacks(inRefCon, inReadFunc, inWriteFunc,
+ inGetSizeFunc, inSetSizeFunc);
+ }
+ break;
+ case kAudioFileInitializeWithCallbacksSelect:
+ {
+ PARAM(void*, inRefCon, 0, 8);
+ PARAM(AudioFile_ReadProc, inReadFunc, 1, 8);
+ PARAM(AudioFile_WriteProc, inWriteFunc, 2, 8);
+ PARAM(AudioFile_GetSizeProc, inGetSizeFunc, 3, 8);
+ PARAM(AudioFile_SetSizeProc, inSetSizeFunc, 4, 8);
+ PARAM(UInt32, inFileType, 5, 8);
+ PARAM(const AudioStreamBasicDescription*, inFormat, 6, 8);
+ PARAM(UInt32, inFlags, 7, 8);
+
+ result = inThis->AFAPI_InitializeWithCallbacks(inRefCon, inReadFunc, inWriteFunc,
+ inGetSizeFunc, inSetSizeFunc,
+ inFileType, inFormat, inFlags);
+ }
+ break;
+ case kAudioFileCloseSelect:
+ {
+ result = inThis->AFAPI_Close();
+ }
+ break;
+ case kAudioFileOptimizeSelect:
+ {
+ result = inThis->AFAPI_Optimize();
+ }
+ break;
+ case kAudioFileReadBytesSelect:
+ {
+ PARAM(UInt32, inUseCache, 0, 4);
+ PARAM(SInt64*, inStartingByte, 1, 4);
+ PARAM(UInt32*, ioNumBytes, 2, 4);
+ PARAM(void*, outBuffer, 3, 4);
+
+ result = inThis->AFAPI_ReadBytes(inUseCache, *inStartingByte, ioNumBytes,
+ outBuffer);
+ }
+ break;
+ case kAudioFileWriteBytesSelect:
+ {
+ PARAM(UInt32, inUseCache, 0, 4);
+ PARAM(SInt64*, inStartingByte, 1, 4);
+ PARAM(UInt32*, ioNumBytes, 2, 4);
+ PARAM(const void*, inBuffer, 3, 4);
+
+ result = inThis->AFAPI_WriteBytes(inUseCache, *inStartingByte, ioNumBytes,
+ inBuffer);
+ }
+ break;
+ case kAudioFileReadPacketsSelect:
+ {
+ PARAM(UInt32, inUseCache, 0, 6);
+ PARAM(UInt32*, outNumBytes, 1, 6);
+ PARAM(AudioStreamPacketDescription*, outPacketDescriptions, 2, 6);
+ PARAM(SInt64*, inStartingPacket, 3, 6);
+ PARAM(UInt32*, ioNumPackets, 4, 6);
+ PARAM(void*, outBuffer, 5, 6);
+
+ result = inThis->AFAPI_ReadPackets(inUseCache, outNumBytes, outPacketDescriptions,
+ *inStartingPacket, ioNumPackets, outBuffer);
+ }
+ break;
+ case kAudioFileWritePacketsSelect:
+ {
+ PARAM(UInt32, inUseCache, 0, 6);
+ PARAM(UInt32, inNumBytes, 1, 6);
+ PARAM(const AudioStreamPacketDescription*, inPacketDescriptions, 2, 6);
+ PARAM(SInt64*, inStartingPacket, 3, 6);
+ PARAM(UInt32*, ioNumPackets, 4, 6);
+ PARAM(const void*, inBuffer, 5, 6);
+
+ result = inThis->AFAPI_WritePackets(inUseCache, inNumBytes, inPacketDescriptions,
+ *inStartingPacket, ioNumPackets, inBuffer);
+ }
+ break;
+
+ case kAudioFileGetPropertyInfoSelect:
+ {
+ PARAM(AudioFileComponentPropertyID, inPropertyID, 0, 3);
+ PARAM(UInt32*, outPropertySize, 1, 3);
+ PARAM(UInt32*, outWritable, 2, 3);
+
+ result = inThis->AFAPI_GetPropertyInfo(inPropertyID, outPropertySize, outWritable);
+ }
+ break;
+
+ case kAudioFileGetPropertySelect:
+ {
+ PARAM(AudioFileComponentPropertyID, inPropertyID, 0, 3);
+ PARAM(UInt32*, ioPropertyDataSize, 1, 3);
+ PARAM(void*, outPropertyData, 2, 3);
+
+ result = inThis->AFAPI_GetProperty(inPropertyID, ioPropertyDataSize, outPropertyData);
+ }
+ break;
+ case kAudioFileSetPropertySelect:
+ {
+ PARAM(AudioFileComponentPropertyID, inPropertyID, 0, 3);
+ PARAM(UInt32, inPropertyDataSize, 1, 3);
+ PARAM(const void*, inPropertyData, 2, 3);
+
+ result = inThis->AFAPI_SetProperty(inPropertyID, inPropertyDataSize, inPropertyData);
+ }
+ break;
+
+ case kAudioFileGetGlobalInfoSizeSelect:
+ {
+ PARAM(AudioFileComponentPropertyID, inPropertyID, 0, 4);
+ PARAM(UInt32, inSpecifierSize, 1, 4);
+ PARAM(const void*, inSpecifier, 2, 4);
+ PARAM(UInt32*, outPropertyDataSize, 3, 4);
+
+ result = inThis->AFAPI_GetGlobalInfoSize(inPropertyID, inSpecifierSize, inSpecifier,
+ outPropertyDataSize);
+ }
+ break;
+ case kAudioFileGetGlobalInfoSelect:
+ {
+ PARAM(AudioFileComponentPropertyID, inPropertyID, 0, 5);
+ PARAM(UInt32, inSpecifierSize, 1, 5);
+ PARAM(const void*, inSpecifier, 2, 5);
+ PARAM(UInt32*, ioPropertyDataSize, 3, 5);
+ PARAM(void*, outPropertyData, 4, 5);
+
+ result = inThis->AFAPI_GetGlobalInfo(inPropertyID, inSpecifierSize, inSpecifier,
+ ioPropertyDataSize, outPropertyData);
+ }
+ break;
+
+ case kAudioFileExtensionIsThisFormatSelect:
+ {
+ PARAM(CFStringRef, inExtension, 0, 2);
+ PARAM(UInt32*, outResult, 1, 2);
+
+ AudioFileFormatBase* aff = inThis->GetAudioFileFormatBase();
+ if (!aff) return kAudio_ParamError;
+
+ UInt32 res = aff->ExtensionIsThisFormat(inExtension);
+ if (outResult) *outResult = res;
+ }
+ break;
+
+ case kAudioFileFileDataIsThisFormatSelect:
+ {
+ PARAM(UInt32, inDataByteSize, 0, 3);
+ PARAM(const void*, inData, 1, 3);
+ PARAM(UInt32*, outResult, 2, 3);
+
+ AudioFileFormatBase* aff = inThis->GetAudioFileFormatBase();
+ if (!aff) return kAudio_ParamError;
+
+ UncertainResult res = aff->FileDataIsThisFormat(inDataByteSize, inData);
+ if (outResult) *outResult = res;
+ }
+ break;
+
+ case kAudioFileCountUserDataSelect:
+ {
+ PARAM(UInt32, inUserDataID, 0, 2);
+ PARAM(UInt32*, outNumberItems, 1, 2);
+
+ result = inThis->AFAPI_CountUserData(inUserDataID, outNumberItems);
+ }
+ break;
+
+ case kAudioFileGetUserDataSizeSelect:
+ {
+ PARAM(UInt32, inUserDataID, 0, 3);
+ PARAM(UInt32, inIndex, 1, 3);
+ PARAM(UInt32*, outUserDataSize, 2, 3);
+
+ result = inThis->AFAPI_GetUserDataSize(inUserDataID, inIndex, outUserDataSize);
+ }
+ break;
+
+ case kAudioFileGetUserDataSelect:
+ {
+ PARAM(UInt32, inUserDataID, 0, 4);
+ PARAM(UInt32, inIndex, 1, 4);
+ PARAM(UInt32*, ioUserDataSize, 2, 4);
+ PARAM(void*, outUserData, 3, 4);
+
+ result = inThis->AFAPI_GetUserData(inUserDataID, inIndex,
+ ioUserDataSize, outUserData);
+ }
+ break;
+
+ case kAudioFileSetUserDataSelect:
+ {
+ PARAM(UInt32, inUserDataID, 0, 4);
+ PARAM(UInt32, inIndex, 1, 4);
+ PARAM(UInt32, inUserDataSize, 2, 4);
+ PARAM(const void*, inUserData, 3, 4);
+
+ result = inThis->AFAPI_SetUserData(inUserDataID, inIndex,
+ inUserDataSize, inUserData);
+ }
+ break;
+
+ case kAudioFileRemoveUserDataSelect:
+ {
+ PARAM(UInt32, inUserDataID, 0, 2);
+ PARAM(UInt32, inIndex, 1, 2);
+
+ result = inThis->AFAPI_RemoveUserData(inUserDataID, inIndex);
+ }
+ break;
+
+
+ default:
+ result = ComponentBase::ComponentEntryDispatch(params, inThis);
+ break;
+ }
+ }
+ COMPONENT_CATCH
+ return result;
+}
+#endif
+
+AudioComponentMethod AudioFileComponentLookup::Lookup (SInt16 selector)
+{
+ switch (selector) {
+
+#define DefCase(NAME) case kAudioFile##NAME##Select: return (AudioComponentMethod)NAME
+
+ DefCase(OpenWithCallbacks);
+ DefCase(InitializeWithCallbacks);
+ DefCase(Close);
+ DefCase(Optimize);
+ DefCase(ReadBytes);
+ DefCase(WriteBytes);
+ DefCase(ReadPackets);
+ DefCase(WritePackets);
+ DefCase(GetPropertyInfo);
+ DefCase(GetProperty);
+ DefCase(SetProperty);
+
+ DefCase(ExtensionIsThisFormat);
+ DefCase(GetGlobalInfoSize);
+ DefCase(GetGlobalInfo);
+
+ DefCase(CountUserData);
+ DefCase(GetUserDataSize);
+ DefCase(GetUserData);
+ DefCase(SetUserData);
+ DefCase(RemoveUserData);
+ DefCase(CreateURL);
+ DefCase(OpenURL);
+ DefCase(FileDataIsThisFormat);
+ DefCase(ReadPacketData);
+
+ // These selectors are deprecated and do not appear: Create, Open, Initialize, FileIsThisFormat, DataIsThisFormat.
+
+ default:
+ break;
+ }
+ return NULL;
+}
diff --git a/libs/appleutility/CoreAudio/AudioFile/AFPublic/AudioFileComponentBase.h b/libs/appleutility/CoreAudio/AudioFile/AFPublic/AudioFileComponentBase.h
new file mode 100644
index 0000000000..5a11934e76
--- /dev/null
+++ b/libs/appleutility/CoreAudio/AudioFile/AFPublic/AudioFileComponentBase.h
@@ -0,0 +1,311 @@
+/*
+ File: AudioFileComponentBase.h
+ Abstract: Part of CoreAudio Utility Classes
+ Version: 1.1
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms. If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+
+*/
+#ifndef __AudioFileComponentBase_h__
+#define __AudioFileComponentBase_h__
+
+#include "ComponentBase.h"
+#include "AudioFileFormat.h"
+
+struct AudioFileComponentLookup {
+ static AudioComponentMethod Lookup (SInt16 selector);
+};
+template <class Implementor>
+class AudioFileComponentFactory : public APFactory<AudioFileComponentLookup, Implementor>
+{
+};
+
+/* subclass, override AudioFileComponentBase() and GetAudioFormat() and that's it. */
+
+class AudioFileComponentBase : public ComponentBase
+{
+public:
+ AudioFileComponentBase(AudioComponentInstance inInstance);
+ virtual ~AudioFileComponentBase();
+
+ virtual AudioFileFormatBase* GetAudioFileFormatBase() const = 0;
+
+ /* Public API Function Support */
+ virtual OSStatus AFAPI_CreateURL(
+ CFURLRef inFileRef,
+ const AudioStreamBasicDescription *inFormat,
+ UInt32 inFlags) { return kAudio_UnimplementedError; }
+
+ virtual OSStatus AFAPI_OpenURL(
+ CFURLRef inFileRef,
+ SInt8 inPermissions,
+ int inFD) { return kAudio_UnimplementedError; }
+
+
+ virtual OSStatus AFAPI_Create(
+ const FSRef *inParentRef,
+ CFStringRef inFileName,
+ const AudioStreamBasicDescription *inFormat,
+ UInt32 inFlags,
+ FSRef *outNewFileRef) { return kAudio_UnimplementedError; }
+
+ virtual OSStatus AFAPI_Initialize(
+ const FSRef *inFileRef,
+ const AudioStreamBasicDescription *inFormat,
+ UInt32 inFlags) { return kAudio_UnimplementedError; }
+
+ virtual OSStatus AFAPI_Open(
+ const FSRef *inFileRef,
+ SInt8 inPermissions,
+ SInt16 inRefNum) { return kAudio_UnimplementedError; }
+
+ virtual OSStatus AFAPI_OpenWithCallbacks(
+ void * inRefCon,
+ AudioFile_ReadProc inReadFunc,
+ AudioFile_WriteProc inWriteFunc,
+ AudioFile_GetSizeProc inGetSizeFunc,
+ AudioFile_SetSizeProc inSetSizeFunc)=0;
+
+ virtual OSStatus AFAPI_InitializeWithCallbacks(
+ void * inRefCon,
+ AudioFile_ReadProc inReadFunc,
+ AudioFile_WriteProc inWriteFunc,
+ AudioFile_GetSizeProc inGetSizeFunc,
+ AudioFile_SetSizeProc inSetSizeFunc,
+ UInt32 inFileType,
+ const AudioStreamBasicDescription *inFormat,
+ UInt32 inFlags)=0;
+
+ virtual OSStatus AFAPI_Close()=0;
+ virtual OSStatus AFAPI_Optimize()=0;
+ virtual OSStatus AFAPI_ReadBytes( Boolean inUseCache,
+ SInt64 inStartingByte,
+ UInt32 *ioNumBytes,
+ void *outBuffer)=0;
+
+ virtual OSStatus AFAPI_WriteBytes( Boolean inUseCache,
+ SInt64 inStartingByte,
+ UInt32 *ioNumBytes,
+ const void *inBuffer)=0;
+
+ virtual OSStatus AFAPI_ReadPackets( Boolean inUseCache,
+ UInt32 *outNumBytes,
+ AudioStreamPacketDescription *outPacketDescriptions,
+ SInt64 inStartingPacket,
+ UInt32 *ioNumPackets,
+ void *outBuffer)=0;
+
+ virtual OSStatus AFAPI_ReadPacketData( Boolean inUseCache,
+ UInt32 *ioNumBytes,
+ AudioStreamPacketDescription *outPacketDescriptions,
+ SInt64 inStartingPacket,
+ UInt32 *ioNumPackets,
+ void *outBuffer)=0;
+
+ virtual OSStatus AFAPI_WritePackets( Boolean inUseCache,
+ UInt32 inNumBytes,
+ const AudioStreamPacketDescription *inPacketDescriptions,
+ SInt64 inStartingPacket,
+ UInt32 *ioNumPackets,
+ const void *inBuffer)=0;
+
+ virtual OSStatus AFAPI_GetPropertyInfo( AudioFilePropertyID inPropertyID,
+ UInt32 *outDataSize,
+ UInt32 *isWritable)=0;
+
+ virtual OSStatus AFAPI_GetProperty( AudioFilePropertyID inPropertyID,
+ UInt32 *ioDataSize,
+ void *ioPropertyData)=0;
+
+ virtual OSStatus AFAPI_SetProperty( AudioFilePropertyID inPropertyID,
+ UInt32 inDataSize,
+ const void *inPropertyData)=0;
+ virtual OSStatus AFAPI_GetGlobalInfoSize(
+ AudioFilePropertyID inPropertyID,
+ UInt32 inSpecifierSize,
+ const void* inSpecifier,
+ UInt32 *outPropertySize);
+
+ virtual OSStatus AFAPI_GetGlobalInfo(
+ AudioFilePropertyID inPropertyID,
+ UInt32 inSpecifierSize,
+ const void* inSpecifier,
+ UInt32 *ioPropertySize,
+ void *ioPropertyData);
+
+ virtual OSStatus AFAPI_CountUserData( UInt32 inUserDataID,
+ UInt32 *outNumberItems)=0;
+
+ virtual OSStatus AFAPI_GetUserDataSize( UInt32 inUserDataID,
+ UInt32 inIndex,
+ UInt32 *outDataSize)=0;
+
+ virtual OSStatus AFAPI_GetUserData( UInt32 inUserDataID,
+ UInt32 inIndex,
+ UInt32 *ioDataSize,
+ void *ioUserData)=0;
+
+ virtual OSStatus AFAPI_SetUserData( UInt32 inUserDataID,
+ UInt32 inIndex,
+ UInt32 inDataSize,
+ const void *inUserData)=0;
+
+ virtual OSStatus AFAPI_RemoveUserData( UInt32 inUserDataID,
+ UInt32 inIndex)=0;
+#if !CA_USE_AUDIO_PLUGIN_ONLY
+ static OSStatus ComponentEntryDispatch(ComponentParameters *p, AudioFileComponentBase *This);
+#endif
+
+protected:
+};
+
+
+
+class AudioFileObjectComponentBase : public AudioFileComponentBase
+{
+public:
+ AudioFileObjectComponentBase(AudioComponentInstance inInstance);
+ virtual ~AudioFileObjectComponentBase();
+
+ virtual AudioFileFormat* GetAudioFormat() const = 0;
+ virtual AudioFileFormatBase* GetAudioFileFormatBase() const { return GetAudioFormat(); }
+
+ void SetAudioFileObject(AudioFileObject* inObject) { mAudioFileObject = inObject; }
+
+ /* Public API Function Support */
+
+ virtual OSStatus AFAPI_CreateURL(
+ CFURLRef inFileRef,
+ const AudioStreamBasicDescription *inFormat,
+ UInt32 inFlags);
+
+ virtual OSStatus AFAPI_OpenURL(
+ CFURLRef inFileRef,
+ SInt8 inPermissions,
+ int inFD);
+
+ virtual OSStatus AFAPI_OpenWithCallbacks(
+ void * inRefCon,
+ AudioFile_ReadProc inReadFunc,
+ AudioFile_WriteProc inWriteFunc,
+ AudioFile_GetSizeProc inGetSizeFunc,
+ AudioFile_SetSizeProc inSetSizeFunc);
+
+ virtual OSStatus AFAPI_InitializeWithCallbacks(
+ void * inRefCon,
+ AudioFile_ReadProc inReadFunc,
+ AudioFile_WriteProc inWriteFunc,
+ AudioFile_GetSizeProc inGetSizeFunc,
+ AudioFile_SetSizeProc inSetSizeFunc,
+ UInt32 inFileType,
+ const AudioStreamBasicDescription *inFormat,
+ UInt32 inFlags);
+
+ virtual OSStatus AFAPI_Close();
+ virtual OSStatus AFAPI_Optimize();
+ virtual OSStatus AFAPI_ReadBytes( Boolean inUseCache,
+ SInt64 inStartingByte,
+ UInt32 *ioNumBytes,
+ void *outBuffer);
+
+ virtual OSStatus AFAPI_WriteBytes( Boolean inUseCache,
+ SInt64 inStartingByte,
+ UInt32 *ioNumBytes,
+ const void *inBuffer);
+
+ virtual OSStatus AFAPI_ReadPackets( Boolean inUseCache,
+ UInt32 *outNumBytes,
+ AudioStreamPacketDescription *outPacketDescriptions,
+ SInt64 inStartingPacket,
+ UInt32 *ioNumPackets,
+ void *outBuffer);
+
+ virtual OSStatus AFAPI_ReadPacketData( Boolean inUseCache,
+ UInt32 *ioNumBytes,
+ AudioStreamPacketDescription *outPacketDescriptions,
+ SInt64 inStartingPacket,
+ UInt32 *ioNumPackets,
+ void *outBuffer);
+
+ virtual OSStatus AFAPI_WritePackets( Boolean inUseCache,
+ UInt32 inNumBytes,
+ const AudioStreamPacketDescription *inPacketDescriptions,
+ SInt64 inStartingPacket,
+ UInt32 *ioNumPackets,
+ const void *inBuffer);
+
+ virtual OSStatus AFAPI_GetPropertyInfo( AudioFilePropertyID inPropertyID,
+ UInt32 *outDataSize,
+ UInt32 *isWritable);
+
+ virtual OSStatus AFAPI_GetProperty( AudioFilePropertyID inPropertyID,
+ UInt32 *ioDataSize,
+ void *ioPropertyData);
+
+ virtual OSStatus AFAPI_SetProperty( AudioFilePropertyID inPropertyID,
+ UInt32 inDataSize,
+ const void *inPropertyData);
+
+ virtual OSStatus AFAPI_CountUserData( UInt32 inUserDataID,
+ UInt32 *outNumberItems);
+
+ virtual OSStatus AFAPI_GetUserDataSize( UInt32 inUserDataID,
+ UInt32 inIndex,
+ UInt32 *outDataSize);
+
+ virtual OSStatus AFAPI_GetUserData( UInt32 inUserDataID,
+ UInt32 inIndex,
+ UInt32 *ioDataSize,
+ void *ioUserData);
+
+ virtual OSStatus AFAPI_SetUserData( UInt32 inUserDataID,
+ UInt32 inIndex,
+ UInt32 inDataSize,
+ const void *inUserData);
+
+ virtual OSStatus AFAPI_RemoveUserData( UInt32 inUserDataID,
+ UInt32 inIndex);
+
+protected:
+ AudioFileObject* mAudioFileObject;
+};
+
+#endif
diff --git a/libs/appleutility/CoreAudio/AudioFile/AFPublic/AudioFileFormat.cpp b/libs/appleutility/CoreAudio/AudioFile/AFPublic/AudioFileFormat.cpp
new file mode 100644
index 0000000000..ee6bedd593
--- /dev/null
+++ b/libs/appleutility/CoreAudio/AudioFile/AFPublic/AudioFileFormat.cpp
@@ -0,0 +1,71 @@
+/*
+ File: AudioFileFormat.cpp
+ Abstract: AudioFileFormat.h
+ Version: 1.1
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms. If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+
+*/
+#include "AudioFileFormat.h"
+#include "DataSource.h"
+
+AudioFileFormatBase::AudioFileFormatBase(UInt32 inFileType)
+ : mFileType(inFileType)
+{
+}
+
+AudioFileFormatBase::~AudioFileFormatBase()
+{
+}
+
+OSStatus AudioFileFormatBase::GetHFSCodes(UInt32* ioDataSize, void* outPropertyData)
+{
+ return kAudioFileUnsupportedPropertyError;
+}
+
+AudioFileFormat::AudioFileFormat(UInt32 inFileType)
+ : AudioFileFormatBase(inFileType)
+{
+}
+
+AudioFileFormat::~AudioFileFormat()
+{
+}
diff --git a/libs/appleutility/CoreAudio/AudioFile/AFPublic/AudioFileFormat.h b/libs/appleutility/CoreAudio/AudioFile/AFPublic/AudioFileFormat.h
new file mode 100644
index 0000000000..9436199569
--- /dev/null
+++ b/libs/appleutility/CoreAudio/AudioFile/AFPublic/AudioFileFormat.h
@@ -0,0 +1,125 @@
+/*
+ File: AudioFileFormat.h
+ Abstract: Part of CoreAudio Utility Classes
+ Version: 1.1
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms. If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+
+*/
+#ifndef _AudioFileFormat_H_
+#define _AudioFileFormat_H_
+
+#include "AudioFileObject.h"
+
+// AudioFileFormat is a factory class for AudioFileObjects.
+
+// UncertainResult is needed for DataIsThisFormat.
+// In the case of SoundDesigner 2 we can't determine if the data is SoundDesigner 2 or not.
+
+typedef int UncertainResult;
+
+enum {
+ kFalse = 0,
+ kTrue = 1,
+ kCantDetermine = -1
+};
+
+class AudioFileHandle;
+class AudioFileFormat;
+class AudioFileFormatComponent;
+
+class AudioFileFormatBase
+{
+public:
+ AudioFileFormatBase(UInt32 inFileType);
+ virtual ~AudioFileFormatBase();
+
+ // return true if extension is of this format type
+ virtual Boolean ExtensionIsThisFormat(CFStringRef inExtension) = 0;
+
+ virtual UncertainResult FileDataIsThisFormat(
+ UInt32 /*inDataByteSize*/,
+ const void* /*inData*/) = 0;
+
+ // support SoundDesigner II files while minimizing opening and closing files.
+ virtual Boolean ResourceIsThisFormat(const FSRef* /*inRef*/) { return false; }
+
+ UInt32 GetFileType() const { return mFileType; }
+
+ virtual UInt32 CanRead() const { return 1; }
+ virtual UInt32 CanWrite() const { return 1; }
+ virtual UInt32 HasResourceFork() const { return 0; }
+
+ virtual void GetExtensions(CFArrayRef *outArray) = 0;
+ virtual void GetUTIs(CFArrayRef *outArray) {}
+ virtual void GetMIMETypes(CFArrayRef *outArray) {}
+ virtual void GetFileTypeName(CFStringRef *outName) = 0;
+ virtual OSStatus GetAvailableFormatIDs(UInt32* ioDataSize, void* outPropertyData) = 0;
+ virtual OSStatus GetAvailableStreamDescriptions(UInt32 inFormatID, UInt32* ioDataSize, void* outPropertyData) = 0;
+ virtual OSStatus GetHFSCodes(UInt32* ioDataSize, void* outPropertyData);
+
+ virtual AudioFileFormat* AsAudioFileFormat() { return NULL; }
+ virtual AudioFileFormatComponent* AsAudioFileFormatComponent() { return NULL; }
+
+private:
+ UInt32 mFileType;
+};
+
+class AudioFileStreamObject;
+
+class AudioFileFormat : public AudioFileFormatBase
+{
+public:
+ AudioFileFormat(UInt32 inFileType);
+ virtual ~AudioFileFormat();
+
+ // create an AudioFileObject for this format type.
+ virtual AudioFileObject* New() = 0;
+ virtual AudioFileStreamObject* NewStream() { return NULL; }
+
+ // return true if file is of this format type
+ virtual UncertainResult FileDataIsThisFormat(UInt32 inDataByteSize, const void* inData) = 0;
+
+ virtual AudioFileFormat* AsAudioFileFormat() { return this; }
+};
+
+
+#endif
diff --git a/libs/appleutility/CoreAudio/AudioFile/AFPublic/AudioFileObject.cpp b/libs/appleutility/CoreAudio/AudioFile/AFPublic/AudioFileObject.cpp
new file mode 100644
index 0000000000..1a00f96251
--- /dev/null
+++ b/libs/appleutility/CoreAudio/AudioFile/AFPublic/AudioFileObject.cpp
@@ -0,0 +1,1966 @@
+/*
+ File: AudioFileObject.cpp
+ Abstract: AudioFileObject.h
+ Version: 1.1
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms. If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+
+*/
+#include "AudioFileObject.h"
+#include "CADebugMacros.h"
+#include <algorithm>
+#include <sys/stat.h>
+
+#define kAudioFileNoCacheMask 0x20
+
+const SInt64 kScanToEnd = 0x7fffFFFFffffFFFFLL;
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+AudioFileObject::~AudioFileObject()
+{
+ delete mDataSource;
+ DeletePacketTable();
+ SetURL(NULL);
+}
+
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+OSStatus AudioFileObject::DoCreate(
+ CFURLRef inFileRef,
+ const AudioStreamBasicDescription *inFormat,
+ UInt32 inFlags)
+{
+ // common prologue
+ if (!IsDataFormatValid(inFormat))
+ return kAudioFileUnsupportedDataFormatError;
+
+ if (!IsDataFormatSupported(inFormat))
+ return kAudioFileUnsupportedDataFormatError;
+
+ SetPermissions(kAudioFileReadWritePermission);
+
+ SetAlignDataWithFillerChunks(!(inFlags & 2 /* kAudioFileFlags_DontPageAlignAudioData */ ));
+
+ // call virtual method for particular format.
+ return Create(inFileRef, inFormat);
+}
+
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+OSStatus AudioFileObject::Create(
+ CFURLRef inFileRef,
+ const AudioStreamBasicDescription *inFormat)
+{
+ int fileD;
+ OSStatus err = CreateDataFile (inFileRef, fileD);
+ FailIf (err != noErr, Bail, "CreateDataFile failed");
+
+ SetURL (inFileRef);
+
+ err = OpenFile(kAudioFileReadWritePermission, fileD);
+ FailIf (err != noErr, Bail, "OpenFile failed");
+
+ err = SetDataFormat(inFormat);
+ FailIf (err != noErr, Bail, "SetDataFormat failed");
+
+ mIsInitialized = false;
+
+Bail:
+ return err;
+}
+
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+OSStatus AudioFileObject::DoOpen(
+ CFURLRef inFileRef,
+ SInt8 inPermissions,
+ int inFD)
+{
+ OSStatus err = noErr;
+ SetPermissions(inPermissions);
+
+ err = Open(inFileRef, inPermissions, inFD);
+ FailIf (err != noErr, Bail, "Open failed");
+
+ err = ValidateFormatAndData();
+ FailIf (err != noErr, Bail, "ValidateFormatAndData failed");
+
+Bail:
+ return err;
+}
+
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+OSStatus AudioFileObject::Open(
+ CFURLRef inFileRef,
+ SInt8 inPermissions,
+ int inFD)
+{
+ if (!(inPermissions & kAudioFileReadPermission))
+ return kAudioFilePermissionsError; // file must have read permissions
+
+ SetURL(inFileRef);
+
+ OSStatus err = OpenFile(inPermissions, inFD);
+ FailIf (err != noErr, Bail, "OpenFile failed");
+
+ err = OpenFromDataSource();
+ FailIf (err != noErr, Bail, "OpenFromDataSource failed");
+
+Bail:
+ return err;
+}
+
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+OSStatus AudioFileObject::ValidateFormatAndData()
+{
+
+
+ AudioStreamBasicDescription asbd = GetDataFormat();
+
+ if (!IsDataFormatValid(&asbd))
+ return kAudioFileInvalidFileError;
+
+ if (asbd.mFormatID == kAudioFormatLinearPCM)
+ {
+ SInt64 maxPackets = GetNumBytes() / asbd.mBytesPerPacket;
+ if (GetNumPackets() > maxPackets)
+ return kAudioFileInvalidFileError;
+ }
+ return noErr;
+}
+
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+OSStatus AudioFileObject::DoOpenWithCallbacks(
+ void * inRefCon,
+ AudioFile_ReadProc inReadFunc,
+ AudioFile_WriteProc inWriteFunc,
+ AudioFile_GetSizeProc inGetSizeFunc,
+ AudioFile_SetSizeProc inSetSizeFunc)
+{
+ SInt8 perms = (inSetSizeFunc || inWriteFunc) ? kAudioFileReadWritePermission : kAudioFileReadPermission;
+ SetPermissions(perms);
+
+ DataSource* dataSource = new Seekable_DataSource(inRefCon, inReadFunc, inWriteFunc, inGetSizeFunc, inSetSizeFunc);
+ SetDataSource(dataSource);
+ return OpenFromDataSource();
+}
+
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+OSStatus AudioFileObject::OpenFromDataSource(void)
+{
+ return noErr;
+}
+
+
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+OSStatus AudioFileObject::DoInitializeWithCallbacks(
+ void * inRefCon,
+ AudioFile_ReadProc inReadFunc,
+ AudioFile_WriteProc inWriteFunc,
+ AudioFile_GetSizeProc inGetSizeFunc,
+ AudioFile_SetSizeProc inSetSizeFunc,
+ UInt32 inFileType,
+ const AudioStreamBasicDescription *inFormat,
+ UInt32 inFlags)
+{
+ DataSource* dataSource = new Seekable_DataSource(inRefCon, inReadFunc, inWriteFunc, inGetSizeFunc, inSetSizeFunc);
+ if (!dataSource->CanWrite()) return -54/*permErr*/;
+ dataSource->SetSize(0);
+ SetDataSource(dataSource);
+ SetPermissions(kAudioFileReadWritePermission);
+
+ SetAlignDataWithFillerChunks(!(inFlags & 2 /* kAudioFileFlags_DontPageAlignAudioData */ ));
+
+ OSStatus err = SetDataFormat(inFormat);
+ if (err) return err;
+
+ return InitializeDataSource(inFormat, inFlags);
+}
+
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+OSStatus AudioFileObject::DoInitialize(
+ CFURLRef inFileRef,
+ const AudioStreamBasicDescription *inFormat,
+ UInt32 inFlags)
+{
+ SetURL (inFileRef);
+ SetPermissions(kAudioFileReadWritePermission);
+
+ SetAlignDataWithFillerChunks(!(inFlags & 2 /* kAudioFileFlags_DontPageAlignAudioData */ ));
+
+ return Initialize(inFileRef, inFormat, inFlags);
+}
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+OSStatus AudioFileObject::Initialize(
+ CFURLRef inFileRef,
+ const AudioStreamBasicDescription *inFormat,
+ UInt32 inFlags)
+{
+ OSStatus err = noErr;
+
+ UInt8 fPath[FILENAME_MAX];
+ if (!CFURLGetFileSystemRepresentation (inFileRef, true, fPath, FILENAME_MAX))
+ return kAudio_FileNotFoundError;
+
+#if TARGET_OS_WIN32
+ int filePerms = 0;
+ int flags = O_TRUNC | O_RDWR | O_BINARY;
+#else
+ mode_t filePerms = 0;
+ int flags = O_TRUNC | O_RDWR;
+#endif
+
+ int fileD = open((const char*)fPath, flags, filePerms);
+ if (fileD < 0)
+ return AudioFileTranslateErrno(errno);
+
+ err = OpenFile(kAudioFileReadWritePermission, fileD);
+ FailIf (err != noErr, Bail, "OpenFile failed");
+
+ // don't need to do this as open has an option to truncate the file
+// GetDataSource()->SetSize(0);
+
+ err = SetDataFormat(inFormat);
+ FailIf (err != noErr, Bail, "SetDataFormat failed");
+
+ InitializeDataSource(inFormat, inFlags);
+
+Bail:
+ return err;
+}
+
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+OSStatus AudioFileObject::InitializeDataSource(const AudioStreamBasicDescription *inFormat, UInt32 /*inFlags*/)
+{
+ return noErr;
+}
+
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+OSStatus AudioFileObject::DoClose()
+{
+ OSStatus err = UpdateSizeIfNeeded();
+ if (err) return err;
+
+ return Close();
+}
+
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+OSStatus AudioFileObject::Close()
+{
+ try {
+ delete mDataSource;
+ mDataSource = 0;
+ } catch (OSStatus err) {
+ return err;
+ } catch (...) {
+ return kAudioFileUnspecifiedError;
+ }
+ return noErr;
+}
+
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+
+OSStatus AudioFileObject::Optimize()
+{
+ // default is that nothing needs to be done. This happens to be true for Raw, SD2 and NeXT/Sun types.
+ SetIsOptimized(true);
+ return noErr;
+}
+
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+
+OSStatus AudioFileObject::DoOptimize()
+{
+ if (!CanWrite()) return kAudioFilePermissionsError;
+
+ OSStatus err = UpdateSizeIfNeeded();
+ if (err) return err;
+
+ if (IsOptimized()) return noErr;
+
+ err = Optimize();
+ return err;
+}
+
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+OSStatus AudioFileObject::UpdateNumBytes(SInt64 inNumBytes)
+{
+ OSStatus err = noErr;
+ if (inNumBytes != GetNumBytes()) {
+ SetNumBytes(inNumBytes);
+
+ // #warning " this will not work for vbr formats"
+ SetNumPackets(GetNumBytes() / mDataFormat.mBytesPerPacket);
+ SizeChanged();
+ }
+ return err;
+}
+
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+OSStatus AudioFileObject::UpdateNumPackets(SInt64 inNumPackets)
+{
+ OSStatus err = noErr;
+ if (inNumPackets != GetNumPackets()) {
+ // sync current state.
+ SetNeedsSizeUpdate(true);
+ UpdateSizeIfNeeded();
+ SetNumPackets(inNumPackets);
+
+ // #warning " this will not work for vbr formats"
+ SetNumBytes(GetNumPackets() * mDataFormat.mBytesPerFrame);
+ SizeChanged();
+ }
+ return err;
+}
+
+
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+OSStatus AudioFileObject::PacketToFrame(SInt64 inPacket, SInt64& outFirstFrameInPacket)
+{
+ if (mDataFormat.mFramesPerPacket == 0)
+ {
+ OSStatus err = ScanForPackets(inPacket+1); // the packet count must be one greater than the packet index
+ if (err) return err;
+
+ SInt64 packetTableSize = GetPacketTableSize();
+
+ if (mPacketTable && inPacket >= packetTableSize)
+ return kAudioFileEndOfFileError;
+
+ CompressedPacketTable* packetTable = GetPacketTable();
+ if (!packetTable)
+ return kAudioFileInvalidPacketOffsetError;
+
+ if (inPacket < 0 || inPacket >= packetTableSize)
+ return kAudioFileInvalidPacketOffsetError;
+
+ outFirstFrameInPacket = (*packetTable)[(size_t)inPacket].mFrameOffset;
+ }
+ else
+ {
+ outFirstFrameInPacket = inPacket * mDataFormat.mFramesPerPacket;
+ }
+ return noErr;
+}
+
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+OSStatus AudioFileObject::FrameToPacket(SInt64 inFrame, SInt64& outPacket, UInt32& outFrameOffsetInPacket)
+{
+ if (mDataFormat.mFramesPerPacket == 0)
+ {
+ CompressedPacketTable* packetTable = GetPacketTable();
+ if (!packetTable)
+ return kAudioFileInvalidPacketOffsetError;
+
+ // search packet table
+ AudioStreamPacketDescriptionExtended pext;
+ memset(&pext, 0, sizeof(pext));
+ pext.mFrameOffset = inFrame;
+ CompressedPacketTable::iterator iter = std::lower_bound(packetTable->begin(), packetTable->end(), pext);
+
+ if (iter == packetTable->end())
+ return kAudioFileInvalidPacketOffsetError;
+
+ if (iter > packetTable->begin()) --iter;
+
+ outPacket = iter - packetTable->begin();
+ outFrameOffsetInPacket = (UInt32)(inFrame - iter->mFrameOffset);
+ }
+ else
+ {
+ outPacket = inFrame / mDataFormat.mFramesPerPacket;
+ outFrameOffsetInPacket = (UInt32)(inFrame % mDataFormat.mFramesPerPacket);
+ }
+ return noErr;
+}
+
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+OSStatus AudioFileObject::PacketToByte(AudioBytePacketTranslation* abpt)
+{
+ if (abpt->mPacket < 0)
+ return kAudioFileInvalidPacketOffsetError;
+
+ if (mDataFormat.mBytesPerPacket == 0)
+ {
+ CompressedPacketTable* packetTable = GetPacketTable();
+ if (!packetTable)
+ return kAudioFileInvalidPacketOffsetError;
+
+ if (abpt->mPacket < GetPacketTableSize()) {
+ abpt->mByte = (*packetTable)[(int)abpt->mPacket].mStartOffset;
+ abpt->mFlags = 0;
+ } else {
+ SInt64 numPackets = packetTable->size();
+ if (numPackets < 8)
+ return 'more' /*kAudioFileStreamError_DataUnavailable*/ ;
+
+ const AudioStreamPacketDescriptionExtended lastPacket = (*packetTable)[numPackets - 1];
+ SInt64 bytesReadSoFar = lastPacket.mStartOffset + lastPacket.mDataByteSize;
+ double averageBytesPerPacket = (double)(bytesReadSoFar - GetDataOffset()) / (double)numPackets;
+ abpt->mByte = (SInt64)floor((double)abpt->mPacket * averageBytesPerPacket);
+ abpt->mFlags = kBytePacketTranslationFlag_IsEstimate;
+ }
+ }
+ else
+ {
+ abpt->mByte = abpt->mPacket * mDataFormat.mBytesPerPacket;
+ abpt->mFlags = 0;
+ }
+ return noErr;
+}
+
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+inline bool byte_less_than (const AudioStreamPacketDescriptionExtended& a, const AudioStreamPacketDescriptionExtended& b)
+{
+ return a.mStartOffset < b.mStartOffset;
+}
+
+OSStatus AudioFileObject::ByteToPacket(AudioBytePacketTranslation* abpt)
+{
+ if (abpt->mByte < 0)
+ return kAudioFileInvalidPacketOffsetError;
+
+ if (mDataFormat.mBytesPerPacket == 0)
+ {
+ CompressedPacketTable* packetTable = GetPacketTable();
+ if (!packetTable)
+ return kAudioFileInvalidPacketOffsetError;
+ // search packet table
+ AudioStreamPacketDescriptionExtended pext;
+ memset(&pext, 0, sizeof(pext));
+ pext.mStartOffset = abpt->mByte;
+ CompressedPacketTable::iterator iter = std::lower_bound(packetTable->begin(), packetTable->end(), pext, byte_less_than);
+
+ if (iter == packetTable->end()) {
+ SInt64 numPackets = packetTable->size();
+ if (numPackets < 8)
+ return 'more' /*kAudioFileStreamError_DataUnavailable*/ ;
+
+ const AudioStreamPacketDescriptionExtended lastPacket = (*packetTable)[numPackets - 1];
+ SInt64 bytesReadSoFar = lastPacket.mStartOffset + lastPacket.mDataByteSize;
+ double averageBytesPerPacket = (double)(bytesReadSoFar - GetDataOffset()) / (double)numPackets;
+
+ double fpacket = (double)abpt->mByte / averageBytesPerPacket;
+ abpt->mPacket = (SInt64)floor(fpacket);
+ abpt->mByteOffsetInPacket = (UInt32)floor((fpacket - (double)abpt->mPacket) * averageBytesPerPacket);
+ abpt->mFlags = kBytePacketTranslationFlag_IsEstimate;
+
+ } else {
+ if (iter > packetTable->begin()) --iter;
+ abpt->mPacket = iter - packetTable->begin();
+ abpt->mByteOffsetInPacket = (UInt32)(abpt->mByte - iter->mStartOffset);
+ abpt->mFlags = 0;
+ }
+ }
+ else
+ {
+ abpt->mPacket = abpt->mByte / mDataFormat.mBytesPerPacket;
+ abpt->mByteOffsetInPacket = (UInt32)(abpt->mByte % mDataFormat.mBytesPerPacket);
+ abpt->mFlags = 0;
+ }
+ return noErr;
+}
+
+
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+OSStatus AudioFileObject::ReadBytes(
+ Boolean inUseCache,
+ SInt64 inStartingByte,
+ UInt32 *ioNumBytes,
+ void *outBuffer)
+{
+ OSStatus err = noErr;
+ UInt16 mode = SEEK_SET;
+ SInt64 fileOffset = mDataOffset + inStartingByte;
+ bool readingPastEnd = false;
+
+ FailWithAction((ioNumBytes == NULL) || (outBuffer == NULL), err = kAudio_ParamError,
+ Bail, "invalid num bytes parameter");
+
+ //printf("inStartingByte %lld GetNumBytes %lld\n", inStartingByte, GetNumBytes());
+
+ if (inStartingByte >= GetNumBytes())
+ {
+ *ioNumBytes = 0;
+ return kAudioFileEndOfFileError;
+ }
+
+ if ((fileOffset + *ioNumBytes) > (GetNumBytes() + mDataOffset))
+ {
+ *ioNumBytes = (UInt32)(GetNumBytes() + mDataOffset - fileOffset);
+ readingPastEnd = true;
+ }
+ //printf("fileOffset %lld mDataOffset %lld readingPastEnd %d\n", fileOffset, mDataOffset, readingPastEnd);
+
+ if (!inUseCache)
+ mode |= kAudioFileNoCacheMask;
+
+ err = GetDataSource()->ReadBytes(mode, fileOffset, *ioNumBytes, outBuffer, ioNumBytes);
+
+ if (readingPastEnd && err == noErr)
+ err = kAudioFileEndOfFileError;
+
+Bail:
+ return err;
+}
+
+
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+OSStatus AudioFileObject::WriteBytes(
+ Boolean inUseCache,
+ SInt64 inStartingByte,
+ UInt32 *ioNumBytes,
+ const void *inBuffer)
+{
+ OSStatus err = noErr;
+ UInt16 mode = SEEK_SET;
+ bool extendingTheAudioData;
+
+ if (!CanWrite()) return kAudioFilePermissionsError;
+
+ FailWithAction((ioNumBytes == NULL) || (inBuffer == NULL), err = kAudioFileUnspecifiedError, Bail, "invalid parameters");
+
+ // Do not try to write to a postion greater than 32 bits for some file types
+ // see if starting byte + ioNumBytes is greater than 32 bits
+ // if so, see if file type supports this and bail if not
+ err = IsValidFilePosition(inStartingByte + *ioNumBytes);
+ FailIf(err != noErr, Bail, "invalid file position");
+
+ extendingTheAudioData = inStartingByte + *ioNumBytes > GetNumBytes();
+
+ // if file is not optimized, then do not write data that would overwrite chunks following the sound data chunk
+ FailWithAction( extendingTheAudioData && !IsOptimized(),
+ err = kAudioFileNotOptimizedError, Bail, "Can't write more data until the file is optimized");
+
+ if (!inUseCache)
+ mode |= kAudioFileNoCacheMask;
+
+ err = GetDataSource()->WriteBytes(mode, mDataOffset + inStartingByte, *ioNumBytes,
+ inBuffer, ioNumBytes);
+
+ FailIf(err != noErr, Bail, "couldn't write new data");
+
+ if (extendingTheAudioData) {
+ SInt64 nuEOF; // Get the total bytes of audio data
+ SInt64 nuByteTotal;
+
+ err = GetDataSource()->GetSize(nuEOF);
+ FailIf(err != noErr, Bail, "GetSize failed");
+
+ nuByteTotal = nuEOF - mDataOffset;
+ err = UpdateNumBytes(nuByteTotal);
+ }
+
+Bail:
+ return err;
+}
+
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+OSStatus AudioFileObject::ReadPackets(
+ Boolean inUseCache,
+ UInt32 *outNumBytes,
+ AudioStreamPacketDescription *outPacketDescriptions,
+ SInt64 inStartingPacket,
+ UInt32 *ioNumPackets,
+ void *outBuffer)
+{
+ // This only works with CBR. To suppport VBR you must override.
+ OSStatus err = noErr;
+
+ FailWithAction(outBuffer == NULL, err = kAudio_ParamError, Bail, "NULL buffer");
+
+ FailWithAction((ioNumPackets == NULL) || (*ioNumPackets < 1), err = kAudio_ParamError, Bail, "invalid num packets parameter");
+
+ {
+ UInt32 byteCount = *ioNumPackets * mDataFormat.mBytesPerPacket;
+ SInt64 startingByte = inStartingPacket * mDataFormat.mBytesPerPacket;
+
+ err = ReadBytes (inUseCache, startingByte, &byteCount, outBuffer);
+ if ((err == noErr) || (err == kAudioFileEndOfFileError))
+ {
+ if (byteCount != (*ioNumPackets * mDataFormat.mBytesPerPacket))
+ {
+ *ioNumPackets = byteCount / mDataFormat.mBytesPerPacket;
+ byteCount = *ioNumPackets * mDataFormat.mBytesPerPacket;
+ }
+
+ if (outNumBytes)
+ *outNumBytes = byteCount;
+
+ if (err == kAudioFileEndOfFileError)
+ err = noErr;
+ }
+ }
+Bail:
+ return err;
+}
+
+
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+OSStatus AudioFileObject::ReadPacketData(
+ Boolean inUseCache,
+ UInt32 *ioNumBytes,
+ AudioStreamPacketDescription *outPacketDescriptions,
+ SInt64 inStartingPacket,
+ UInt32 *ioNumPackets,
+ void *outBuffer)
+{
+ OSStatus err = noErr;
+ FailWithAction(ioNumPackets == NULL || *ioNumPackets < 1, err = kAudio_ParamError, Bail, "invalid ioNumPackets parameter");
+ FailWithAction(ioNumBytes == NULL || *ioNumBytes < 1, err = kAudio_ParamError, Bail, "invalid ioNumBytes parameter");
+ if (mDataFormat.mBytesPerPacket) {
+ // CBR
+ FailWithAction(outBuffer == NULL, err = kAudio_ParamError, Bail, "NULL buffer");
+ UInt32 maxPackets = *ioNumBytes / mDataFormat.mBytesPerPacket;
+ if (*ioNumPackets > maxPackets) *ioNumPackets = maxPackets;
+
+ if (outBuffer) {
+ UInt32 byteCount = *ioNumPackets * mDataFormat.mBytesPerPacket;
+ SInt64 startingByte = inStartingPacket * mDataFormat.mBytesPerPacket;
+ err = ReadBytes (inUseCache, startingByte, &byteCount, outBuffer);
+ if (err == noErr || err == kAudioFileEndOfFileError) {
+ if (byteCount != (*ioNumPackets * mDataFormat.mBytesPerPacket)) {
+ *ioNumPackets = byteCount / mDataFormat.mBytesPerPacket;
+ byteCount = *ioNumPackets * mDataFormat.mBytesPerPacket;
+ }
+ *ioNumBytes = byteCount;
+ }
+ }
+ } else {
+ FailWithAction(outPacketDescriptions == NULL, err = kAudio_ParamError, Bail, "invalid outPacketDescriptions parameter");
+ err = ReadPacketDataVBR(inUseCache, ioNumBytes, outPacketDescriptions, inStartingPacket, ioNumPackets, outBuffer);
+ }
+Bail:
+ return err;
+}
+
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+OSStatus AudioFileObject::ReadPacketDataVBR(
+ Boolean inUseCache,
+ UInt32 *ioNumBytes,
+ AudioStreamPacketDescription *outPacketDescriptions,
+ SInt64 inStartingPacket,
+ UInt32 *ioNumPackets,
+ void *outBuffer)
+{
+ OSStatus err = ScanForPackets(inStartingPacket+1); // need to scan packets up to start
+ if (err && err != kAudioFileEndOfFileError)
+ return err;
+
+ SInt64 dataOffset = GetDataOffset();
+
+ CompressedPacketTable* packetTable = GetPacketTable();
+ if (!packetTable)
+ return kAudioFileInvalidFileError;
+
+ SInt64 packetTableSize = GetPacketTableSize();
+
+ if (inStartingPacket >= packetTableSize) {
+ *ioNumBytes = 0;
+ *ioNumPackets = 0;
+ return kAudioFileEndOfFileError;
+ }
+
+ if (inStartingPacket + *ioNumPackets <= packetTableSize) {
+ err = ReadPacketDataVBR_InTable(inUseCache, ioNumBytes, outPacketDescriptions, inStartingPacket, ioNumPackets, outBuffer);
+ } else {
+
+ AudioStreamPacketDescription firstPacket = (*packetTable)[inStartingPacket];
+ SInt64 firstPacketOffset = firstPacket.mStartOffset;
+ UInt32 bytesRead = *ioNumBytes;
+ SInt64 fileSize = 0;
+ GetDataSource()->GetSize(fileSize);
+ SInt64 remainingBytesInFile = fileSize - firstPacketOffset - dataOffset;
+ if (bytesRead > remainingBytesInFile)
+ bytesRead = (UInt32)remainingBytesInFile;
+
+ err = ReadBytes (inUseCache, firstPacketOffset, &bytesRead, outBuffer);
+ if (err && err != kAudioFileEndOfFileError) {
+ *ioNumBytes = 0;
+ *ioNumPackets = 0;
+ return err;
+ }
+
+ Buffer_DataSource bufSrc(bytesRead, outBuffer, dataOffset + firstPacketOffset);
+
+ OSStatus scanErr = ScanForPackets(kScanToEnd, &bufSrc, false);
+ if (scanErr && scanErr != kAudioFileEndOfFileError)
+ return scanErr;
+ packetTableSize = packetTable->size();
+
+ UInt32 numPacketsRead = 0;
+ UInt32 endOfData = 0;
+ SInt64 packetNumber = inStartingPacket;
+ for (; numPacketsRead < *ioNumPackets && packetNumber < packetTableSize; ++numPacketsRead, ++packetNumber) {
+ AudioStreamPacketDescription curPacket = (*packetTable)[numPacketsRead + inStartingPacket];
+ SInt64 curPacketOffset = curPacket.mStartOffset - firstPacketOffset;
+ SInt64 endOfPacket = curPacketOffset + curPacket.mDataByteSize;
+ if (endOfPacket > bytesRead) break;
+ endOfData = (UInt32)endOfPacket;
+ outPacketDescriptions[numPacketsRead] = curPacket;
+ outPacketDescriptions[numPacketsRead].mStartOffset = curPacketOffset;
+ }
+
+ *ioNumBytes = endOfData;
+ *ioNumPackets = numPacketsRead;
+ }
+ return err;
+}
+
+
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+OSStatus AudioFileObject::HowManyPacketsCanBeReadIntoBuffer(UInt32* ioNumBytes, SInt64 inStartingPacket, UInt32 *ioNumPackets)
+{
+ CompressedPacketTable* packetTable = GetPacketTable();
+ SInt64 packetTableSize = GetPacketTableSize();
+
+ if (inStartingPacket + *ioNumPackets > (SInt64)packetTableSize) {
+ *ioNumPackets = (UInt32)(packetTableSize - inStartingPacket);
+ }
+
+ AudioStreamPacketDescription firstPacket = (*packetTable)[inStartingPacket];
+
+ if (*ioNumBytes < firstPacket.mDataByteSize) {
+ *ioNumBytes = 0;
+ *ioNumPackets = 0;
+ return kAudio_ParamError;
+ }
+
+ SInt64 lastPacketIndex = inStartingPacket + *ioNumPackets - 1;
+ if (lastPacketIndex >= packetTableSize)
+ lastPacketIndex = packetTableSize - 1;
+
+ AudioStreamPacketDescription lastPacket = (*packetTable)[lastPacketIndex];
+
+ SInt64 readBytes = lastPacket.mStartOffset + lastPacket.mDataByteSize - firstPacket.mStartOffset;
+ if (readBytes <= *ioNumBytes) {
+ *ioNumBytes = (UInt32)readBytes;
+ return noErr;
+ }
+
+ SInt64 lowBound = inStartingPacket;
+ SInt64 highBound = lastPacketIndex + 1;
+ SInt64 okIndex = lowBound;
+ while (highBound >= lowBound) {
+ SInt64 tryBound = (lowBound + highBound) >> 1;
+ if (tryBound > lastPacketIndex)
+ break;
+ AudioStreamPacketDescription tryPacket = (*packetTable)[tryBound];
+
+ SInt64 readBytes = tryPacket.mStartOffset + tryPacket.mDataByteSize - firstPacket.mStartOffset;
+
+ if (readBytes > (SInt64)*ioNumBytes) {
+ highBound = tryBound - 1;
+ } else if (readBytes < (SInt64)*ioNumBytes) {
+ okIndex = tryBound;
+ lowBound = tryBound + 1;
+ } else {
+ okIndex = tryBound;
+ break;
+ }
+ }
+
+ SInt64 numPackets = okIndex - inStartingPacket + 1;
+ if (numPackets > *ioNumPackets) {
+ numPackets = *ioNumPackets;
+ okIndex = inStartingPacket + numPackets - 1;
+ }
+
+ AudioStreamPacketDescription packet = (*packetTable)[okIndex];
+ *ioNumBytes = (UInt32)(packet.mStartOffset + packet.mDataByteSize - firstPacket.mStartOffset);
+ *ioNumPackets = (UInt32)numPackets;
+ return noErr;
+}
+
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+
+
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+OSStatus AudioFileObject::ReadPacketDataVBR_InTable(
+ Boolean inUseCache,
+ UInt32 *ioNumBytes,
+ AudioStreamPacketDescription *outPacketDescriptions,
+ SInt64 inStartingPacket,
+ UInt32 *ioNumPackets,
+ void *outBuffer)
+{
+ CompressedPacketTable* packetTable = GetPacketTable();
+ if (!packetTable)
+ return kAudioFileInvalidFileError;
+
+ OSStatus err = HowManyPacketsCanBeReadIntoBuffer(ioNumBytes, inStartingPacket, ioNumPackets);
+ if (err) return err;
+
+ AudioStreamPacketDescription firstPacket = (*packetTable)[inStartingPacket];
+ SInt64 firstPacketOffset = firstPacket.mStartOffset;
+ UInt32 bytesRead = *ioNumBytes;
+
+ if (outBuffer) {
+ err = ReadBytes (inUseCache, firstPacketOffset, &bytesRead, outBuffer);
+ if (err && err != kAudioFileEndOfFileError) {
+ *ioNumBytes = 0;
+ *ioNumPackets = 0;
+ return err;
+ }
+ *ioNumBytes = bytesRead;
+ }
+
+ // fill out packet descriptions
+ if (outPacketDescriptions) {
+ for (UInt32 i = 0; i < *ioNumPackets; i++) {
+ AudioStreamPacketDescription curPacket = (*packetTable)[i + inStartingPacket];
+ outPacketDescriptions[i] = curPacket;
+ outPacketDescriptions[i].mStartOffset = curPacket.mStartOffset - firstPacketOffset;
+ }
+ }
+
+ return err;
+}
+
+
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+OSStatus AudioFileObject::WritePackets(
+ Boolean inUseCache,
+ UInt32 inNumBytes,
+ const AudioStreamPacketDescription *inPacketDescriptions,
+ SInt64 inStartingPacket,
+ UInt32 *ioNumPackets,
+ const void *inBuffer)
+{
+ // This only works with CBR. To suppport VBR you must override.
+ OSStatus err = noErr;
+
+ FailWithAction(inStartingPacket > GetNumPackets(), err = kAudioFileInvalidPacketOffsetError, Bail, "write past end");
+ FailWithAction((ioNumPackets == NULL) || (inBuffer == NULL), err = kAudioFileUnspecifiedError, Bail, "invalid parameter");
+
+ {
+ UInt32 byteCount = *ioNumPackets * mDataFormat.mBytesPerPacket;
+ SInt64 startingByte = inStartingPacket * mDataFormat.mBytesPerPacket;
+
+ err = WriteBytes(inUseCache, startingByte, &byteCount, inBuffer);
+ FailIf (err != noErr, Bail, "Write Bytes Failed");
+
+ if (byteCount != (*ioNumPackets * mDataFormat.mBytesPerPacket))
+ *ioNumPackets = byteCount / mDataFormat.mBytesPerPacket;
+ }
+Bail:
+ return (err);
+}
+
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+OSStatus AudioFileObject::GetBitRate( UInt32 *outBitRate)
+{
+
+ if (!outBitRate) return kAudioFileUnspecifiedError;
+
+ UInt32 bytesPerPacket = GetDataFormat().mBytesPerPacket;
+ UInt32 framesPerPacket = GetDataFormat().mFramesPerPacket;
+ Float64 sampleRate = GetDataFormat().mSampleRate;
+ const Float64 bitsPerByte = 8.;
+
+ if (bytesPerPacket && framesPerPacket) {
+ *outBitRate = (UInt32)(bitsPerByte * (Float64)bytesPerPacket * sampleRate / (Float64)framesPerPacket);
+ } else {
+ SInt64 numPackets = GetNumPackets();
+ SInt64 numBytes = GetNumBytes();
+ SInt64 numFrames = 0;
+
+ if (framesPerPacket) {
+ numFrames = numPackets * framesPerPacket;
+ } else {
+ // count frames
+ CompressedPacketTable* packetTable = GetPacketTable();
+ if (packetTable) {
+ if (packetTable->size() != numPackets) {
+ return kAudioFileInvalidFileError;
+ }
+#if !TARGET_OS_WIN32
+ for (ssize_t i = 0; i < numPackets; i++)
+#else
+ for (int i = 0; i < numPackets; i++)
+#endif
+ {
+ numFrames += (*packetTable)[i].mVariableFramesInPacket;
+ }
+ } else {
+ return kAudioFileUnsupportedPropertyError;
+ }
+ }
+
+ if (numFrames == 0 || (sampleRate == 0.)) {
+ *outBitRate = 0;
+ return noErr;
+ }
+ Float64 duration = (Float64)numFrames / sampleRate;
+ *outBitRate = (UInt32)(bitsPerByte * (Float64)numBytes / duration);
+ }
+
+ return noErr;
+}
+
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+OSStatus AudioFileObject::GetMagicCookieDataSize(
+ UInt32 *outDataSize,
+ UInt32 *isWritable)
+{
+ if (outDataSize) *outDataSize = 0;
+ if (isWritable) *isWritable = 0;
+ return kAudioFileUnsupportedPropertyError;
+}
+
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+OSStatus AudioFileObject::GetMagicCookieData(
+ UInt32 *ioDataSize,
+ void *ioPropertyData)
+{
+ *ioDataSize = 0;
+ return kAudioFileUnsupportedPropertyError;
+}
+
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+OSStatus AudioFileObject::SetMagicCookieData( UInt32 /*inDataSize*/,
+ const void *inPropertyData)
+{
+ return kAudioFileInvalidChunkError;
+}
+
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+OSStatus AudioFileObject::GetMarkerListSize(
+ UInt32 *outDataSize,
+ UInt32 *isWritable)
+{
+ if (outDataSize) *outDataSize = 0;
+ if (isWritable) *isWritable = 0;
+ return kAudioFileUnsupportedPropertyError;
+}
+
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+OSStatus AudioFileObject::GetMarkerList(
+ UInt32 *ioDataSize,
+ AudioFileMarkerList* /*ioPropertyData*/)
+{
+ *ioDataSize = 0;
+ return kAudioFileUnsupportedPropertyError;
+}
+
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+OSStatus AudioFileObject::SetMarkerList( UInt32 /*inDataSize*/,
+ const AudioFileMarkerList* /*inPropertyData*/)
+{
+ return kAudioFileUnsupportedPropertyError;
+}
+
+
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+OSStatus AudioFileObject::GetRegionListSize(
+ UInt32 *outDataSize,
+ UInt32 *isWritable)
+{
+ if (outDataSize) *outDataSize = 0;
+ if (isWritable) *isWritable = 0;
+ return kAudioFileUnsupportedPropertyError;
+}
+
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+OSStatus AudioFileObject::GetRegionList(
+ UInt32 *ioDataSize,
+ AudioFileRegionList *ioPropertyData)
+{
+ *ioDataSize = 0;
+ return kAudioFileUnsupportedPropertyError;
+}
+
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+OSStatus AudioFileObject::SetRegionList( UInt32 /*inDataSize*/,
+ const AudioFileRegionList* /*inPropertyData*/)
+{
+ return kAudioFileUnsupportedPropertyError;
+}
+
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+OSStatus AudioFileObject::GetChannelLayoutSize(
+ UInt32 *outDataSize,
+ UInt32 *isWritable)
+{
+ if (outDataSize) *outDataSize = 0;
+ if (isWritable) *isWritable = 0;
+ return kAudioFileUnsupportedPropertyError;
+}
+
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+OSStatus AudioFileObject::GetChannelLayout(
+ UInt32 *ioDataSize,
+ AudioChannelLayout* /*ioPropertyData*/)
+{
+ *ioDataSize = 0;
+ return kAudioFileUnsupportedPropertyError;
+}
+
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+OSStatus AudioFileObject::SetChannelLayout( UInt32 /*inDataSize*/,
+ const AudioChannelLayout* /*inPropertyData*/)
+{
+ return kAudioFileUnsupportedPropertyError;
+}
+
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+OSStatus AudioFileObject::GetInfoDictionarySize( UInt32 *outDataSize,
+ UInt32 *isWritable)
+{
+ if (outDataSize) *outDataSize = sizeof(CFDictionaryRef);
+ if (isWritable) *isWritable = 0;
+ return noErr;
+}
+
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+OSStatus AudioFileObject::GetInfoDictionary(CACFDictionary *infoDict)
+{
+ Float64 fl;
+ if (GetEstimatedDuration(&fl) == noErr)
+ return AddDurationToInfoDictionary(infoDict, fl);
+
+ return kAudioFileUnsupportedPropertyError;
+}
+
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+OSStatus AudioFileObject::SetInfoDictionary(CACFDictionary *infoDict)
+{
+ return kAudioFileUnsupportedPropertyError;
+}
+
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+OSStatus AudioFileObject::GetEstimatedDuration(Float64* duration)
+{
+ // calculate duration
+ AudioStreamBasicDescription ASBD = GetDataFormat();
+
+ *duration = (ASBD.mFramesPerPacket != 0) ? (GetNumPackets() * ASBD.mFramesPerPacket) / ASBD.mSampleRate : 0.0;
+
+ /*
+ For now, assume that any ASBD that has zero in the frames per packet field has been subclassed for this
+ method. i.e. A CAF file has a frame count in one of it's chunks.
+
+ MP3 has been subclassed because it guesstimates a duration so the entire file does not
+ need to be parsed in order to calculate the total frames.
+ */
+
+ return noErr;
+
+}
+
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+OSStatus AudioFileObject::GetPropertyInfo (
+ AudioFilePropertyID inPropertyID,
+ UInt32 *outDataSize,
+ UInt32 *isWritable)
+{
+ OSStatus err = noErr;
+ UInt32 writable = 0;
+
+ switch (inPropertyID)
+ {
+ case kAudioFilePropertyDeferSizeUpdates :
+ if (outDataSize) *outDataSize = sizeof(UInt32);
+ writable = 1;
+ break;
+
+ case kAudioFilePropertyFileFormat:
+ if (outDataSize) *outDataSize = sizeof(UInt32);
+ writable = 0;
+ break;
+
+ case kAudioFilePropertyDataFormat:
+ if (outDataSize) *outDataSize = sizeof(AudioStreamBasicDescription);
+ writable = 1;
+ break;
+
+ case kAudioFilePropertyFormatList:
+ err = GetFormatListInfo(*outDataSize, writable);
+ break;
+
+ case kAudioFilePropertyPacketSizeUpperBound:
+ case kAudioFilePropertyIsOptimized:
+ case kAudioFilePropertyMaximumPacketSize:
+ if (outDataSize) *outDataSize = sizeof(UInt32);
+ writable = 0;
+ break;
+
+ case kAudioFilePropertyAudioDataByteCount:
+ case kAudioFilePropertyAudioDataPacketCount:
+ writable = 1;
+ if (outDataSize) *outDataSize = sizeof(SInt64);
+ break;
+
+ case kAudioFilePropertyDataOffset:
+ writable = 0;
+ if (outDataSize) *outDataSize = sizeof(SInt64);
+ break;
+
+ case kAudioFilePropertyBitRate:
+ writable = 0;
+ if (outDataSize) *outDataSize = sizeof(UInt32);
+ break;
+
+ case kAudioFilePropertyMagicCookieData:
+ err = GetMagicCookieDataSize(outDataSize, &writable);
+ break;
+
+ case kAudioFilePropertyMarkerList :
+ err = GetMarkerListSize(outDataSize, &writable);
+ break;
+
+ case kAudioFilePropertyRegionList :
+ err = GetRegionListSize(outDataSize, &writable);
+ break;
+
+ case kAudioFilePropertyChannelLayout :
+ err = GetChannelLayoutSize(outDataSize, &writable);
+ break;
+
+ case kAudioFilePropertyPacketToFrame :
+ case kAudioFilePropertyFrameToPacket :
+ if (outDataSize) *outDataSize = sizeof(AudioFramePacketTranslation);
+ writable = 0;
+ break;
+
+ case kAudioFilePropertyPacketToByte :
+ case kAudioFilePropertyByteToPacket :
+ if (outDataSize) *outDataSize = sizeof(AudioBytePacketTranslation);
+ writable = 0;
+ break;
+
+ case kAudioFilePropertyInfoDictionary :
+ err = GetInfoDictionarySize(outDataSize, &writable);
+ break;
+
+ case kTEMPAudioFilePropertySoundCheckDictionary :
+ err = GetSoundCheckDictionarySize(outDataSize, &writable);
+ break;
+
+ case kTEMPAudioFilePropertyGenerateLoudnessInfo :
+ err = GetLoudnessInfoSize(outDataSize, &writable);
+ writable = 0;
+ break;
+
+ case kTEMPAudioFilePropertyLoudnessInfo :
+ err = GetLoudnessInfoSize(outDataSize, &writable);
+ break;
+
+ case kAudioFilePropertyEstimatedDuration :
+ if (outDataSize) *outDataSize = sizeof(Float64);
+ writable = 0;
+ break;
+
+ case 'LYRC':
+ if (outDataSize) *outDataSize = sizeof(CFStringRef);
+ if (isWritable) *isWritable = 0;
+ break;
+
+ case 'eof?':
+ if (outDataSize) *outDataSize = sizeof(UInt32);
+ if (isWritable) *isWritable = 0;
+ break;
+
+ case 'sbtd' /*kAudioFilePropertySourceBitDepth*/ :
+ if (outDataSize) *outDataSize = sizeof(SInt32);
+ if (isWritable) *isWritable = CanWrite();
+ break;
+
+ default:
+ writable = 0;
+ err = kAudioFileUnsupportedPropertyError;
+ break;
+ }
+
+ if (isWritable)
+ *isWritable = writable;
+ return (err);
+}
+
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+OSStatus AudioFileObject::GetProperty(
+ AudioFilePropertyID inPropertyID,
+ UInt32 *ioDataSize,
+ void *ioPropertyData)
+{
+ OSStatus err = noErr;
+ UInt32 neededSize;
+ UInt32 writable;
+
+ switch (inPropertyID)
+ {
+ case kAudioFilePropertyFileFormat:
+ FailWithAction(*ioDataSize != sizeof(UInt32),
+ err = kAudioFileBadPropertySizeError, Bail, "inDataSize is wrong");
+
+ *(UInt32 *) ioPropertyData = GetFileType();
+ break;
+
+ case kAudioFilePropertyFormatList:
+ err = GetFormatList(*ioDataSize, (AudioFormatListItem*)ioPropertyData);
+ break;
+
+ case kAudioFilePropertyDataFormat:
+ FailWithAction(*ioDataSize != sizeof(AudioStreamBasicDescription),
+ err = kAudioFileBadPropertySizeError, Bail, "inDataSize is wrong");
+
+ memcpy(ioPropertyData, &mDataFormat, sizeof(AudioStreamBasicDescription));
+ break;
+ case kAudioFilePropertyDataOffset:
+ FailWithAction(*ioDataSize != sizeof(SInt64),
+ err = kAudioFileBadPropertySizeError, Bail, "inDataSize is wrong");
+ *(SInt64 *) ioPropertyData = mDataOffset;
+ break;
+ case kAudioFilePropertyIsOptimized:
+ FailWithAction(*ioDataSize != sizeof(UInt32),
+ err = kAudioFileBadPropertySizeError, Bail, "inDataSize is wrong");
+ *(UInt32 *) ioPropertyData = mIsOptimized;
+ break;
+
+ case kAudioFilePropertyAudioDataByteCount:
+ FailWithAction(*ioDataSize != sizeof(SInt64),
+ err = kAudioFileBadPropertySizeError, Bail, "inDataSize is wrong");
+ *(SInt64 *)ioPropertyData = GetNumBytes();
+ break;
+
+ case kAudioFilePropertyAudioDataPacketCount:
+ FailWithAction(*ioDataSize != sizeof(SInt64),
+ err = kAudioFileBadPropertySizeError, Bail, "inDataSize is wrong");
+ *(SInt64 *)ioPropertyData = GetNumPackets();
+ break;
+
+ case kAudioFilePropertyPacketSizeUpperBound:
+ FailWithAction(*ioDataSize != sizeof(UInt32),
+ err = kAudioFileBadPropertySizeError, Bail, "inDataSize is wrong");
+ *(UInt32 *)ioPropertyData = GetPacketSizeUpperBound();
+ break;
+
+ case kAudioFilePropertyMaximumPacketSize:
+ FailWithAction(*ioDataSize != sizeof(UInt32),
+ err = kAudioFileBadPropertySizeError, Bail, "inDataSize is wrong");
+ *(UInt32 *)ioPropertyData = FindMaximumPacketSize();
+ break;
+
+
+ case kAudioFilePropertyBitRate:
+ FailWithAction(*ioDataSize != sizeof(UInt32),
+ err = kAudioFileBadPropertySizeError, Bail, "inDataSize is wrong");
+ err = GetBitRate((UInt32*)ioPropertyData);
+ break;
+
+ case kAudioFilePropertyMagicCookieData:
+
+ err = GetMagicCookieData(ioDataSize, ioPropertyData);
+ break;
+
+ case kAudioFilePropertyMarkerList :
+ err = GetMarkerList(ioDataSize, static_cast<AudioFileMarkerList*>(ioPropertyData));
+ break;
+
+ case kAudioFilePropertyRegionList :
+ memset(ioPropertyData, 0, *ioDataSize);
+ err = GetRegionList(ioDataSize, static_cast<AudioFileRegionList*>(ioPropertyData));
+ break;
+
+ case kAudioFilePropertyChannelLayout :
+ err = GetChannelLayoutSize(&neededSize, &writable);
+ FailIf(err, Bail, "GetChannelLayoutSize failed");
+ FailWithAction(*ioDataSize != neededSize, err = kAudioFileBadPropertySizeError, Bail, "inDataSize is wrong");
+
+ err = GetChannelLayout(ioDataSize, static_cast<AudioChannelLayout*>(ioPropertyData));
+ break;
+
+ case kAudioFilePropertyDeferSizeUpdates :
+ FailWithAction(*ioDataSize != sizeof(UInt32),
+ err = kAudioFileBadPropertySizeError, Bail, "inDataSize is wrong");
+
+ *(UInt32 *) ioPropertyData = DeferSizeUpdates();
+ break;
+
+ case kAudioFilePropertyPacketToFrame :
+ {
+ FailWithAction(*ioDataSize != sizeof(AudioFramePacketTranslation),
+ err = kAudioFileBadPropertySizeError, Bail, "inDataSize is wrong");
+
+ AudioFramePacketTranslation* afpt = (AudioFramePacketTranslation*)ioPropertyData;
+ err = PacketToFrame(afpt->mPacket, afpt->mFrame);
+ break;
+ }
+ case kAudioFilePropertyFrameToPacket :
+ {
+ FailWithAction(*ioDataSize != sizeof(AudioFramePacketTranslation),
+ err = kAudioFileBadPropertySizeError, Bail, "inDataSize is wrong");
+
+ AudioFramePacketTranslation* afpt = (AudioFramePacketTranslation*)ioPropertyData;
+ err = FrameToPacket(afpt->mFrame, afpt->mPacket, afpt->mFrameOffsetInPacket);
+ break;
+ }
+
+ case kAudioFilePropertyPacketToByte :
+ {
+ FailWithAction(*ioDataSize != sizeof(AudioBytePacketTranslation),
+ err = kAudioFileBadPropertySizeError, Bail, "inDataSize is wrong");
+
+ AudioBytePacketTranslation* abpt = (AudioBytePacketTranslation*)ioPropertyData;
+ err = PacketToByte(abpt);
+ break;
+ }
+ case kAudioFilePropertyByteToPacket :
+ {
+ FailWithAction(*ioDataSize != sizeof(AudioBytePacketTranslation),
+ err = kAudioFileBadPropertySizeError, Bail, "inDataSize is wrong");
+
+ AudioBytePacketTranslation* abpt = (AudioBytePacketTranslation*)ioPropertyData;
+ err = ByteToPacket(abpt);
+ break;
+ }
+
+ case kAudioFilePropertyInfoDictionary :
+ {
+ FailWithAction(*ioDataSize != sizeof(CFDictionaryRef),
+ err = kAudioFileBadPropertySizeError, Bail, "inDataSize is wrong");
+
+ CACFDictionary afInfoDictionary(true);
+
+ err = GetInfoDictionary(&afInfoDictionary);
+
+ if (!err)
+ {
+ *(CFMutableDictionaryRef *)ioPropertyData = afInfoDictionary.CopyCFMutableDictionary();
+ }
+ break;
+ }
+
+ case kTEMPAudioFilePropertySoundCheckDictionary :
+ {
+ FailWithAction(*ioDataSize != sizeof(CFDictionaryRef),
+ err = kAudioFileBadPropertySizeError, Bail, "inDataSize is wrong");
+
+ CACFDictionary afInfoDictionary(true);
+
+ err = GetSoundCheckDictionary(&afInfoDictionary);
+ if (err) {
+ OSStatus err2 = GetSoundCheckDictionaryFromLoudnessInfo(&afInfoDictionary);
+ if (err2 == noErr) err = noErr; // else report original error from GetSoundCheckDictionary.
+ }
+
+ if (!err)
+ {
+ *(CFMutableDictionaryRef *)ioPropertyData = afInfoDictionary.CopyCFMutableDictionary();
+ }
+ break;
+ }
+
+ case kTEMPAudioFilePropertyLoudnessInfo :
+ {
+ FailWithAction(*ioDataSize != sizeof(CFDictionaryRef),
+ err = kAudioFileBadPropertySizeError, Bail, "inDataSize is wrong");
+
+ CACFDictionary afInfoDictionary(true);
+
+ err = GetLoudnessInfo(&afInfoDictionary);
+ if (err) {
+ OSStatus err2 = GetLoudnessInfoFromSoundCheckDictionary(&afInfoDictionary);
+ if (err2 == noErr) err = noErr; // else report original error from GetLoudnessInfo.
+ }
+
+ if (!err)
+ {
+ *(CFMutableDictionaryRef *)ioPropertyData = afInfoDictionary.CopyCFMutableDictionary();
+ }
+ break;
+ }
+
+ case kTEMPAudioFilePropertyGenerateLoudnessInfo :
+ {
+ FailWithAction(*ioDataSize != sizeof(CFDictionaryRef),
+ err = kAudioFileBadPropertySizeError, Bail, "inDataSize is wrong");
+
+ CACFDictionary afInfoDictionary(true);
+
+ err = GenerateLoudnessInfo(&afInfoDictionary);
+
+ if (!err)
+ {
+ *(CFMutableDictionaryRef *)ioPropertyData = afInfoDictionary.CopyCFMutableDictionary();
+ }
+ break;
+ }
+
+ case kAudioFilePropertyEstimatedDuration :
+ {
+ FailWithAction(*ioDataSize != sizeof(Float64),
+ err = kAudioFileBadPropertySizeError, Bail, "inDataSize is wrong");
+
+ err = GetEstimatedDuration((Float64*)ioPropertyData);
+ break;
+ }
+
+ case 'LYRC' :
+ if (*ioDataSize < sizeof(CFStringRef))
+ return kAudioFileBadPropertySizeError;
+
+ *ioDataSize = sizeof(CFStringRef);
+ err = GetLyrics((CFStringRef*) ioPropertyData);
+ break;
+
+ case 'eof?' :
+ {
+ if (*ioDataSize != sizeof(UInt32))
+ return kAudioFileBadPropertySizeError;
+
+ SInt64 pos;
+ err = GetDataSource()->GetPos(pos);
+ if (err) break;
+
+ SInt64 endOfData = GetDataOffset() + GetNumBytes();
+ *(UInt32*)ioPropertyData = pos >= endOfData;
+
+ break;
+ }
+ case 'sbtd' /*kAudioFilePropertySourceBitDepth*/ :
+ {
+ if (*ioDataSize != sizeof(SInt32))
+ return kAudioFileBadPropertySizeError;
+
+ SInt32 outValue = 0;
+ err = GetSourceBitDepth(outValue);
+ if ((err || outValue == 0) && GetDataFormat().mFormatID == kAudioFormatLinearPCM) {
+ // if there was no stored source bit depth, and this file is LPCM, then report this file's bit depth.
+ err = noErr;
+ outValue = GetDataFormat().mBitsPerChannel;
+ if (GetDataFormat().mFormatFlags & kAudioFormatFlagIsFloat)
+ outValue = -outValue;
+ } else if (err)
+ break;
+
+ *(SInt32 *) ioPropertyData = outValue;
+
+ break;
+ }
+ default:
+ err = kAudioFileUnsupportedPropertyError;
+ break;
+ }
+
+Bail:
+ return err;
+}
+
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+OSStatus AudioFileObject::SetProperty(
+ AudioFilePropertyID inPropertyID,
+ UInt32 inDataSize,
+ const void *inPropertyData)
+{
+ OSStatus err = noErr;
+
+ switch (inPropertyID)
+ {
+ case kAudioFilePropertyDataFormat:
+ FailWithAction(inDataSize != sizeof(AudioStreamBasicDescription),
+ err = kAudioFileBadPropertySizeError, Bail, "Incorrect data size");
+ err = UpdateDataFormat((AudioStreamBasicDescription *) inPropertyData);
+ break;
+ case kAudioFilePropertyFormatList:
+ err = SetFormatList(inDataSize, (AudioFormatListItem*)inPropertyData);
+ break;
+
+ case kAudioFilePropertyAudioDataByteCount: {
+ FailWithAction(inDataSize != sizeof(SInt64), err = kAudioFileBadPropertySizeError, Bail, "Incorrect data size");
+ SInt64 numBytes = *(SInt64 *) inPropertyData;
+ if (numBytes > GetNumBytes()) {
+ // can't use this to increase data size.
+ return kAudioFileOperationNotSupportedError;
+ }
+ UInt32 saveDefer = DeferSizeUpdates();
+ SetDeferSizeUpdates(0); // force an update.
+ err = UpdateNumBytes(numBytes);
+ SetDeferSizeUpdates(saveDefer);
+ } break;
+
+ case kAudioFilePropertyAudioDataPacketCount: {
+ SInt64 numPackets = *(SInt64 *) inPropertyData;
+ if (numPackets > GetNumPackets()) {
+ // can't use this to increase data size.
+ return kAudioFileOperationNotSupportedError;
+ }
+ err = UpdateNumPackets(numPackets);
+ } break;
+
+ case kAudioFilePropertyMagicCookieData:
+ err = SetMagicCookieData(inDataSize, inPropertyData);
+ break;
+
+
+ case kAudioFilePropertyMarkerList :
+ err = SetMarkerList(inDataSize, static_cast<const AudioFileMarkerList*>(inPropertyData));
+ break;
+
+ case kAudioFilePropertyRegionList :
+ err = SetRegionList(inDataSize, static_cast<const AudioFileRegionList*>(inPropertyData));
+ break;
+
+ case kAudioFilePropertyChannelLayout :
+ err = SetChannelLayout(inDataSize, static_cast<const AudioChannelLayout*>(inPropertyData));
+ break;
+
+ case kAudioFilePropertyDeferSizeUpdates :
+ FailWithAction(inDataSize != sizeof(UInt32),
+ err = kAudioFileBadPropertySizeError, Bail, "inDataSize is wrong");
+ SetDeferSizeUpdates(*(UInt32 *) inPropertyData);
+ break;
+
+ case kAudioFilePropertyInfoDictionary :
+ {
+ FailWithAction(inDataSize != sizeof(CFDictionaryRef),
+ err = kAudioFileBadPropertySizeError, Bail, "inDataSize is wrong");
+
+ // pass the SetInfoDictionary a CACFDictionary object made with the provided CFDictionaryRef
+ // Let the caller release their own CFObject so pass false for th erelease parameter
+ CACFDictionary afInfoDictionary(*(CFDictionaryRef *)inPropertyData, false);
+ err = SetInfoDictionary(&afInfoDictionary);
+
+ break;
+ }
+
+ case kTEMPAudioFilePropertySoundCheckDictionary :
+ {
+ FailWithAction(inDataSize != sizeof(CFDictionaryRef),
+ err = kAudioFileBadPropertySizeError, Bail, "inDataSize is wrong");
+
+ // pass the SetInfoDictionary a CACFDictionary object made with the provided CFDictionaryRef
+ // Let the caller release their own CFObject so pass false for the release parameter
+ CACFDictionary afInfoDictionary(*(CFDictionaryRef *)inPropertyData, false);
+ err = SetSoundCheckDictionary(&afInfoDictionary);
+
+ break;
+ }
+
+ case kTEMPAudioFilePropertyLoudnessInfo :
+ {
+ FailWithAction(inDataSize != sizeof(CFDictionaryRef),
+ err = kAudioFileBadPropertySizeError, Bail, "inDataSize is wrong");
+
+ // pass the SetInfoDictionary a CACFDictionary object made with the provided CFDictionaryRef
+ // Let the caller release their own CFObject so pass false for the release parameter
+ CACFDictionary afInfoDictionary(*(CFDictionaryRef *)inPropertyData, false);
+ err = SetLoudnessInfo(&afInfoDictionary);
+
+ break;
+ }
+
+ case 'sbtd' /*kAudioFilePropertySourceBitDepth*/ :
+ {
+ FailWithAction(inDataSize != sizeof(SInt32),
+ err = kAudioFileBadPropertySizeError, Bail, "inDataSize is wrong");
+
+ SInt32 inValue = *(SInt32 *)inPropertyData;
+ err = SetSourceBitDepth(inValue);
+
+ break;
+ }
+
+ default:
+ err = kAudioFileUnsupportedPropertyError;
+ break;
+ }
+
+Bail:
+ return err;
+}
+
+
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+OSStatus AudioFileObject::SetDataFormat(const AudioStreamBasicDescription* inStreamFormat)
+{
+ OSStatus err = noErr;
+
+ if (!IsDataFormatValid(inStreamFormat))
+ return kAudioFileUnsupportedDataFormatError;
+
+ if (!IsDataFormatSupported(inStreamFormat))
+ return kAudioFileUnsupportedDataFormatError;
+
+ UInt32 prevBytesPerPacket = mDataFormat.mBytesPerPacket;
+
+ mDataFormat = *inStreamFormat;
+
+ // if CBR and bytes per packet changes, we need to change the number of packets we think we have.
+ if (mDataFormat.mBytesPerPacket && mDataFormat.mBytesPerPacket != prevBytesPerPacket)
+ {
+ SInt64 numPackets = GetNumBytes() / mDataFormat.mBytesPerPacket;
+ SetNumPackets(numPackets);
+ SetMaximumPacketSize(mDataFormat.mBytesPerPacket);
+
+ if (!mFirstSetFormat)
+ SizeChanged();
+ }
+
+ mFirstSetFormat = false;
+
+ return err;
+}
+
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+OSStatus AudioFileObject::GetFormatListInfo( UInt32 &outDataSize,
+ UInt32 &outWritable)
+{
+ // default implementation is to just return the data format
+ outDataSize = sizeof(AudioFormatListItem);
+ outWritable = false;
+ return noErr;
+}
+
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+OSStatus AudioFileObject::GetFormatList( UInt32 &ioDataSize,
+ AudioFormatListItem *ioPropertyData)
+{
+ // default implementation is to just return the data format
+ if (ioDataSize < sizeof(AudioFormatListItem))
+ return kAudioFileBadPropertySizeError;
+
+ AudioFormatListItem afli;
+ afli.mASBD = mDataFormat;
+ AudioChannelLayoutTag layoutTag = /*kAudioChannelLayoutTag_Unknown*/ 0xFFFF0000 | mDataFormat.mChannelsPerFrame;
+ UInt32 layoutSize, isWritable;
+ OSStatus err = GetChannelLayoutSize(&layoutSize, &isWritable);
+ if (err == noErr)
+ {
+ CAAutoFree<AudioChannelLayout> layout;
+ layout.allocBytes(layoutSize);
+ err = GetChannelLayout(&layoutSize, layout());
+ if (err == noErr) {
+ layoutTag = layout->mChannelLayoutTag;
+ }
+ }
+ afli.mChannelLayoutTag = layoutTag;
+
+ memcpy(ioPropertyData, &afli, sizeof(AudioFormatListItem));
+
+ ioDataSize = sizeof(AudioFormatListItem);
+ return noErr;
+}
+
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+OSStatus AudioFileObject::SetFormatList( UInt32 inDataSize,
+ const AudioFormatListItem *inPropertyData)
+{
+ return kAudioFileOperationNotSupportedError;
+}
+
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+OSStatus AudioFileObject::UpdateDataFormat(const AudioStreamBasicDescription* inStreamFormat)
+{
+ return SetDataFormat(inStreamFormat);
+}
+
+
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Boolean AudioFileObject::IsDataFormatValid(AudioStreamBasicDescription const* inDesc)
+{
+ if (inDesc->mSampleRate < 0.)
+ return false;
+
+ if (inDesc->mSampleRate > 3e6)
+ return false;
+
+ if (inDesc->mChannelsPerFrame < 1 || inDesc->mChannelsPerFrame > 0x000FFFFF)
+ return false;
+
+ if (inDesc->mFormatID == kAudioFormatLinearPCM)
+ {
+ if (inDesc->mBitsPerChannel < 1 || inDesc->mBitsPerChannel > 64)
+ return false;
+
+ if (inDesc->mFramesPerPacket != 1)
+ return false;
+
+ if (inDesc->mBytesPerPacket == 0)
+ return false;
+
+ if (inDesc->mBytesPerFrame != inDesc->mBytesPerPacket)
+ return false;
+
+ // [3605260] we assume here that a packet is an integer number of frames.
+ UInt32 minimumBytesPerPacket = (inDesc->mBitsPerChannel * inDesc->mChannelsPerFrame + 7) / 8;
+ if (inDesc->mBytesPerPacket < minimumBytesPerPacket)
+ return false;
+ }
+ return true;
+}
+
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+void AudioFileObject::SetDataSource(DataSource* inDataSource)
+{
+ if (mDataSource != inDataSource) {
+ delete mDataSource;
+ mDataSource = inDataSource;
+ }
+}
+
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+void AudioFileObject::SetURL (CFURLRef inURL)
+{
+ if (mFileRef == inURL) return;
+ if (inURL) CFRetain (inURL);
+ if (mFileRef) CFRelease(mFileRef);
+ mFileRef = inURL;
+}
+
+OSStatus AudioFileObject::OpenFile(SInt8 inPermissions, int inFD)
+{
+ OSStatus err = noErr;
+
+ SetDataSource(new Cached_DataSource(new UnixFile_DataSource(inFD, inPermissions, true)));
+
+ mFileD = inFD;
+ SetPermissions (inPermissions);
+
+ return err;
+}
+
+OSStatus AudioFileObject::CreateDataFile (CFURLRef inFileRef, int &outFileD)
+{
+ UInt8 fPath[FILENAME_MAX];
+ if (!CFURLGetFileSystemRepresentation (inFileRef, true, fPath, FILENAME_MAX))
+ return kAudio_FileNotFoundError;
+
+ struct stat stbuf;
+ if (stat ((const char*)fPath, &stbuf) == 0)
+ return kAudioFilePermissionsError;
+
+#if TARGET_OS_WIN32
+ int filePerms = S_IREAD | S_IWRITE;
+ int flags = O_CREAT | O_EXCL | O_RDWR | O_BINARY;
+#else
+ mode_t filePerms = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH;
+ int flags = O_CREAT | O_EXCL | O_RDWR;
+#endif
+ outFileD = open((const char*)fPath, flags, filePerms);
+ if (outFileD < 0)
+ return AudioFileTranslateErrno(errno);
+
+ return noErr;
+}
+
+OSStatus AudioFileObject::AddDurationToInfoDictionary(CACFDictionary *infoDict, Float64 &inDuration)
+{
+#if !TARGET_OS_WIN32
+ CFLocaleRef currentLocale = CFLocaleGetSystem();
+ CFNumberFormatterRef numberFormatter = NULL;
+ numberFormatter = CFNumberFormatterCreate(kCFAllocatorDefault, currentLocale, kCFNumberFormatterDecimalStyle);
+ CFStringRef cfStr = CFNumberFormatterCreateStringWithValue( kCFAllocatorDefault, numberFormatter, kCFNumberFloat64Type, &inDuration);
+ if (cfStr)
+ {
+ if (CFStringGetLength(cfStr) != 0)
+ infoDict->AddString(CFSTR(kAFInfoDictionary_ApproximateDurationInSeconds), cfStr);
+ CFRelease(cfStr);
+ }
+ CFRelease(numberFormatter);
+#endif
+ return noErr;
+}
+
+OSStatus AudioFileObject::SizeChanged()
+{
+ OSStatus err = noErr;
+ if (mPermissions & kAudioFileWritePermission)
+ {
+ if (DeferSizeUpdates())
+ SetNeedsSizeUpdate(true);
+ else
+ err = UpdateSize();
+ }
+ return err;
+}
+
+OSStatus AudioFileObject::UpdateSizeIfNeeded()
+{
+ if (GetNeedsSizeUpdate())
+ {
+ OSStatus err = UpdateSize();
+ if (err) return err;
+ SetNeedsSizeUpdate(false);
+ }
+ return noErr;
+}
+
+OSStatus AudioFileObject::CountUserData( UInt32 /*inUserDataID*/,
+ UInt32* /*outNumberItems*/)
+{
+ return kAudioFileOperationNotSupportedError;
+}
+
+OSStatus AudioFileObject::GetUserDataSize( UInt32 /*inUserDataID*/,
+ UInt32 /*inIndex*/,
+ UInt32* /*outDataSize*/)
+{
+ return kAudioFileOperationNotSupportedError;
+}
+
+OSStatus AudioFileObject::GetUserData( UInt32 /*inUserDataID*/,
+ UInt32 /*inIndex*/,
+ UInt32* /*ioDataSize*/,
+ void* /*ioUserData*/)
+{
+ return kAudioFileOperationNotSupportedError;
+}
+
+OSStatus AudioFileObject::SetUserData( UInt32 /*inUserDataID*/,
+ UInt32 /*inIndex*/,
+ UInt32 /*inDataSize*/,
+ const void* /*inUserData*/)
+{
+ return kAudioFileOperationNotSupportedError;
+}
+
+OSStatus AudioFileObject::RemoveUserData( UInt32 /*inUserDataID*/,
+ UInt32 /*inIndex*/)
+{
+ return kAudioFileOperationNotSupportedError;
+}
+
+OSStatus AudioFileObject::MoveData(SInt64 fromPos, SInt64 toPos, SInt64 size)
+{
+ if (fromPos == toPos)
+ return noErr;
+
+ OSStatus err = noErr;
+ CAAutoFree<char> audioData(kCopySoundDataBufferSize, true);
+
+ SInt64 bytesRemaining = size;
+ if (fromPos < toPos) {
+ while (bytesRemaining > 0)
+ {
+ // read from old file
+ UInt32 byteCount;
+ SInt64 count = (bytesRemaining < kCopySoundDataBufferSize) ? bytesRemaining : kCopySoundDataBufferSize;
+ err = GetDataSource()->ReadBytes(SEEK_SET, fromPos+(bytesRemaining-count), (UInt32)count, audioData(), &byteCount);
+ FailIf (err != noErr, Bail, "MoveData ReadBytes failed");
+
+ err = GetDataSource()->WriteBytes(SEEK_SET, toPos+(bytesRemaining-count), (UInt32)count, audioData(), &byteCount);
+ FailIf (err != noErr, Bail, "WriteBytes failed");
+
+ bytesRemaining -= count;
+ }
+ } else {
+ while (bytesRemaining > 0)
+ {
+ // read from old file
+ UInt32 byteCount;
+ SInt64 count = (bytesRemaining < kCopySoundDataBufferSize) ? bytesRemaining : kCopySoundDataBufferSize;
+ err = GetDataSource()->ReadBytes(SEEK_SET, fromPos+(size - bytesRemaining), (UInt32)count, audioData(), &byteCount);
+ FailIf (err != noErr, Bail, "MoveData ReadBytes failed");
+
+ err = GetDataSource()->WriteBytes(SEEK_SET, toPos+(size - bytesRemaining), (UInt32)count, audioData(), &byteCount);
+ FailIf (err != noErr, Bail, "WriteBytes failed");
+
+ bytesRemaining -= count;
+ }
+ }
+
+Bail:
+ return err;
+}
+
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
diff --git a/libs/appleutility/CoreAudio/AudioFile/AFPublic/AudioFileObject.h b/libs/appleutility/CoreAudio/AudioFile/AFPublic/AudioFileObject.h
new file mode 100644
index 0000000000..6d7c868976
--- /dev/null
+++ b/libs/appleutility/CoreAudio/AudioFile/AFPublic/AudioFileObject.h
@@ -0,0 +1,667 @@
+/*
+ File: AudioFileObject.h
+ Abstract: Part of CoreAudio Utility Classes
+ Version: 1.1
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms. If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+
+*/
+#ifndef _AudioFileObject_H_
+#define _AudioFileObject_H_
+
+#include <TargetConditionals.h>
+
+#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
+ #include <CoreAudio/CoreAudioTypes.h>
+ #include <AudioToolbox/AudioFile.h>
+ #include <AudioToolbox/AudioFormat.h>
+#else
+ #include "CoreAudioTypes.h"
+ #include "AudioFile.h"
+ #include "AudioFormat.h"
+#endif
+
+#include "CompressedPacketTable.h"
+#include "CACFDictionary.h"
+#include "DataSource.h"
+#include <vector>
+#include <fcntl.h>
+
+#if TARGET_OS_WIN32
+#include <io.h>
+#endif
+
+/*
+ These are structs defined in 10.5. They are included here for compatibility with sources
+*/
+#if COREAUDIOTYPES_VERSION < 1050
+
+struct AudioFormatListItem
+{
+ AudioStreamBasicDescription mASBD;
+ AudioChannelLayoutTag mChannelLayoutTag;
+};
+typedef struct AudioFormatListItem AudioFormatListItem;
+
+struct AudioFormatInfo
+{
+ AudioStreamBasicDescription mASBD;
+ const void* mMagicCookie;
+ UInt32 mMagicCookieSize;
+};
+typedef struct AudioFormatInfo AudioFormatInfo;
+
+enum {
+
+ kAudioFormatProperty_FormatList = 'flst',
+ // Returns a list of AudioFormatListItem structs describing the audio formats contained within the compressed bit stream
+ // as described by the magic cookie.
+ // The specifier is an AudioFormatInfo struct. At a minimum formatID member of the ASBD struct must filled in. Other fields
+ // may be filled in.
+
+ kAudioFormatProperty_OutputFormatList = 'ofls',
+ // Returns a list of AudioFormatListItem structs describing the audio formats which may be obtained by decoding the format
+ // described by the specifier.
+ // The specifier is an AudioFormatInfo struct. At a minimum formatID member of the ASBD struct must filled in. Other fields
+ // may be filled in. If there is no magic cookie, then the number of channels and sample rate should be filled in.
+
+};
+
+enum {
+ kAudioFilePropertyPacketSizeUpperBound = 'pkub',
+ kAudioFilePropertyFormatList = 'flst',
+ kAudioFilePropertyEstimatedDuration = 'edur',
+ kAudioFilePropertyBitRate = 'brat'
+};
+
+enum {
+ kAudioFileCreateURLSelect = 0x0019,
+ kAudioFileOpenURLSelect = 0x001A,
+ kAudioFileFileDataIsThisFormatSelect = 0x001B
+};
+#endif
+
+enum {
+ kTEMPAudioFilePropertySoundCheckDictionary = 'scdc',
+ kTEMPAudioFilePropertyLoudnessInfo = 'loud',
+ kTEMPAudioFilePropertyGenerateLoudnessInfo = 'glou'
+};
+
+const UInt32 kCopySoundDataBufferSize = 1024 * 1024;
+
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+// some files encode these as upper case
+enum {
+ kUpperCase_IMACompression = 'IMA4', /*IMA 4:1*/
+ kUpperCase_ULawCompression = 'ULAW', /*µLaw 2:1*/
+ kUpperCase_ALawCompression = 'ALAW', /*aLaw 2:1*/
+
+ kUpperCase_Float32 = 'FL32',
+ kUpperCase_Float64 = 'FL64'
+};
+
+enum
+{
+ // in what header is this defined? what is it?
+ kGSM = 'agsm',
+ kUpperCase_GSM = 'GSM '
+};
+
+#define kPackedBESInt (kLinearPCMFormatFlagIsSignedInteger | kLinearPCMFormatFlagIsBigEndian | kLinearPCMFormatFlagIsPacked)
+#define kPackedLESInt (kLinearPCMFormatFlagIsSignedInteger | kLinearPCMFormatFlagIsPacked)
+#define kPackedBEFloat (kLinearPCMFormatFlagIsFloat | kLinearPCMFormatFlagIsBigEndian | kLinearPCMFormatFlagIsPacked)
+#define kPackedLEFloat (kLinearPCMFormatFlagIsFloat | kLinearPCMFormatFlagIsPacked)
+
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+inline int TransformPerm_FS_O (SInt8 inPerm)
+{
+ switch (inPerm) {
+ case kAudioFileReadPermission: return O_RDONLY;
+ case kAudioFileWritePermission: return O_WRONLY;
+ case kAudioFileReadWritePermission: return O_RDWR;
+ }
+ return O_RDONLY;
+}
+
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+#pragma mark "File Error Handling"
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+#include <errno.h>
+#include <CoreAudio/CoreAudioTypes.h>
+
+inline OSErr AudioFileTranslateErrno(int err)
+{
+ switch (err) {
+#if !TARGET_OS_WIN32
+ case ENFILE:
+#endif
+ case EMFILE:
+ return -42 /* kAudio_TooManyFilesOpenError */;
+#if !TARGET_OS_WIN32
+ case EPERM:
+ case EROFS:
+#endif
+ case EACCES:
+ case EEXIST:
+ return -54 /* kAudio_FilePermissionError */;
+#if !TARGET_OS_WIN32
+ case EMLINK:
+ return (OSErr)'!pth' /* kAudio_BadFilePathError */;
+ case ENOTDIR:
+ case ELOOP:
+#endif
+ case ENOENT:
+ default:
+ return (OSErr)kAudioFileUnspecifiedError;
+ }
+}
+
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+class AudioFileObject
+{
+protected:
+
+private:
+ SInt64 mNumBytes; // total bytes of audio data in the audio file
+ SInt64 mNumPackets; // total frames of audio data in the audio file
+ AudioStreamBasicDescription mDataFormat; // format of the audio data
+ SInt64 mDataOffset; // position if the file where audio data begins
+ UInt32 mIsOptimized; // 1 if there is nothing in the file following the audio data, 0 if there is
+ UInt32 mFileType; // file type of the audio file (i.e. AIFF, WAVE, etc.)
+ CFURLRef mFileRef; // URL of the file passed to AudioFileOpen or AudioFileCreate
+ int mFileD; // Ref num of the file after opening within Audio File
+ SInt8 mPermissions; // file permissions indicated by the caller, passed by AudioFileOpen or set with SetProperty function
+ Boolean mIsInitialized; // has the AudioFileObject for this file been intialized?
+ DataSource *mDataSource;
+ UInt32 mMaximumPacketSize;
+ CompressedPacketTable *mPacketTable;
+ UInt32 mDeferSizeUpdates;
+ Boolean mNeedsSizeUpdate;
+ Boolean mFirstSetFormat;
+ Boolean mAlignDataWithFillerChunks;
+
+public:
+
+ AudioFileObject (UInt32 inFileType)
+ : mNumBytes(0),
+ mNumPackets(0),
+ mDataOffset(0),
+ mIsOptimized(1),
+ mFileType(inFileType),
+ mFileRef(NULL),
+ mFileD(-1),
+ mPermissions(0),
+ mIsInitialized (false),
+ mDataSource(0),
+ mMaximumPacketSize(0),
+ mPacketTable(NULL),
+ mDeferSizeUpdates(1),
+ mNeedsSizeUpdate(false),
+ mFirstSetFormat(true),
+ mAlignDataWithFillerChunks(true)
+ {
+ memset(&mDataFormat, 0, sizeof(mDataFormat));
+ }
+
+ virtual ~AudioFileObject();
+
+
+/* Public API Function Implementation */
+ // The DoSomething() versions of these functions are wrappers that perform a standard prologue.
+ // The Something() methods are those which should be overridden in the subclasses.
+
+ OSStatus DoCreate( CFURLRef inFileRef,
+ const AudioStreamBasicDescription *inFormat,
+ UInt32 inFlags);
+
+ virtual OSStatus Create( CFURLRef inFileRef,
+ const AudioStreamBasicDescription *inFormat);
+
+ OSStatus DoOpen( CFURLRef inFileRef,
+ SInt8 inPermissions,
+ int inFD);
+
+ virtual OSStatus Open( CFURLRef inFileRef,
+ SInt8 inPermissions,
+ int inFD);
+
+ OSStatus DoOpenWithCallbacks(
+ void * inRefCon,
+ AudioFile_ReadProc inReadFunc,
+ AudioFile_WriteProc inWriteFunc,
+ AudioFile_GetSizeProc inGetSizeFunc,
+ AudioFile_SetSizeProc inSetSizeFunc);
+
+
+ OSStatus DoInitialize( CFURLRef inFileRef,
+ const AudioStreamBasicDescription *inFormat,
+ UInt32 inFlags);
+
+ virtual OSStatus Initialize( CFURLRef inFileRef,
+ const AudioStreamBasicDescription *inFormat,
+ UInt32 inFlags);
+
+ OSStatus DoInitializeWithCallbacks(
+ void * inRefCon,
+ AudioFile_ReadProc inReadFunc,
+ AudioFile_WriteProc inWriteFunc,
+ AudioFile_GetSizeProc inGetSizeFunc,
+ AudioFile_SetSizeProc inSetSizeFunc,
+ UInt32 inFileType,
+ const AudioStreamBasicDescription *inFormat,
+ UInt32 inFlags);
+
+ virtual OSStatus OpenFromDataSource(void);
+
+ virtual OSStatus InitializeDataSource(const AudioStreamBasicDescription *inFormat, UInt32 inFlags);
+
+ OSStatus DoClose();
+
+ virtual OSStatus Close();
+
+ OSStatus DoOptimize();
+
+ virtual OSStatus Optimize();
+
+ virtual OSStatus ReadBytes( Boolean inUseCache,
+ SInt64 inStartingByte,
+ UInt32 *ioNumBytes,
+ void *outBuffer);
+
+ virtual OSStatus WriteBytes( Boolean inUseCache,
+ SInt64 inStartingByte,
+ UInt32 *ioNumBytes,
+ const void *inBuffer);
+
+ virtual OSStatus ReadPackets( Boolean inUseCache,
+ UInt32 *outNumBytes,
+ AudioStreamPacketDescription *outPacketDescriptions,
+ SInt64 inStartingPacket,
+ UInt32 *ioNumPackets,
+ void *outBuffer);
+
+ virtual OSStatus ReadPacketData(
+ Boolean inUseCache,
+ UInt32 *ioNumBytes,
+ AudioStreamPacketDescription *outPacketDescriptions,
+ SInt64 inStartingPacket,
+ UInt32 *ioNumPackets,
+ void *outBuffer);
+
+ virtual OSStatus ReadPacketDataVBR(
+ Boolean inUseCache,
+ UInt32 *ioNumBytes,
+ AudioStreamPacketDescription *outPacketDescriptions,
+ SInt64 inStartingPacket,
+ UInt32 *ioNumPackets,
+ void *outBuffer);
+
+ virtual OSStatus HowManyPacketsCanBeReadIntoBuffer(UInt32* ioNumBytes, SInt64 inStartingPacket, UInt32 *ioNumPackets);
+
+ virtual OSStatus ReadPacketDataVBR_InTable(
+ Boolean inUseCache,
+ UInt32 *ioNumBytes,
+ AudioStreamPacketDescription *outPacketDescriptions,
+ SInt64 inStartingPacket,
+ UInt32 *ioNumPackets,
+ void *outBuffer);
+
+ virtual OSStatus WritePackets( Boolean inUseCache,
+ UInt32 inNumBytes,
+ const AudioStreamPacketDescription *inPacketDescriptions,
+ SInt64 inStartingPacket,
+ UInt32 *ioNumPackets,
+ const void *inBuffer);
+/* Property Support */
+
+ virtual OSStatus GetPropertyInfo (
+ AudioFilePropertyID inPropertyID,
+ UInt32 *outDataSize,
+ UInt32 *isWritable);
+
+ virtual OSStatus GetProperty ( AudioFilePropertyID inPropertyID,
+ UInt32 *ioDataSize,
+ void *ioPropertyData);
+
+ virtual OSStatus SetProperty ( AudioFilePropertyID inPropertyID,
+ UInt32 inDataSize,
+ const void *inPropertyData);
+
+ UInt32 GetFileType() const { return mFileType; }
+ void SetFileType(UInt32 inFileType) { mFileType = inFileType; }
+
+ // this will set the format in memory only.
+ virtual OSStatus SetDataFormat(const AudioStreamBasicDescription* inStreamFormat);
+
+ // this will update the format info on disk and in memory.
+ virtual OSStatus UpdateDataFormat(const AudioStreamBasicDescription* inStreamFormat);
+
+ const UInt32 GetBytesPerPacket() const { return mDataFormat.mBytesPerPacket; }
+
+ const AudioStreamBasicDescription &GetDataFormat() const { return mDataFormat; }
+
+ virtual OSStatus GetFormatListInfo( UInt32 &outDataSize,
+ UInt32 &outWritable);
+
+ virtual OSStatus GetFormatList( UInt32 &ioDataSize,
+ AudioFormatListItem *ioPropertyData);
+
+ virtual OSStatus SetFormatList( UInt32 inDataSize,
+ const AudioFormatListItem *inPropertyData);
+
+ virtual OSStatus UpdateSize() { return noErr; }
+ UInt32 DeferSizeUpdates() { return mDeferSizeUpdates; }
+ void SetDeferSizeUpdates(UInt32 inFlag) { mDeferSizeUpdates = inFlag; }
+ OSStatus UpdateSizeIfNeeded();
+ OSStatus SizeChanged();
+
+ Boolean IsOptimized() const { return mIsOptimized != 0; }
+ void SetIsOptimized(Boolean inIsOptimized) { mIsOptimized = inIsOptimized ? 1 : 0; }
+
+ Boolean AlignDataWithFillerChunks() const { return mAlignDataWithFillerChunks; }
+
+ virtual SInt64 GetNumBytes() { return mNumBytes; }
+ virtual void SetNumBytes(SInt64 inNumBytes) { mNumBytes = inNumBytes; }
+
+ // this will update the header size info on disk
+ OSStatus UpdateNumBytes(SInt64 inNumBytes);
+
+ virtual SInt64 GetNumPackets(){ return mNumPackets; }
+ virtual void SetNumPackets(SInt64 inNumPackets) { mNumPackets = inNumPackets; }
+
+ // this will update the header size info on disk
+ OSStatus UpdateNumPackets(SInt64 inNumPackets);
+
+ virtual OSStatus PacketToFrame(SInt64 inPacket, SInt64& outFirstFrameInPacket);
+ virtual OSStatus FrameToPacket(SInt64 inFrame, SInt64& outPacket, UInt32& outFrameOffsetInPacket);
+
+ virtual OSStatus PacketToByte(AudioBytePacketTranslation* abpt);
+
+ virtual OSStatus ByteToPacket(AudioBytePacketTranslation* abpt);
+
+ virtual OSStatus GetBitRate( UInt32 *outBitRate);
+
+ virtual OSStatus GetMagicCookieDataSize( UInt32 *outDataSize,
+ UInt32 *isWritable);
+
+ virtual OSStatus GetMagicCookieData( UInt32 *ioDataSize,
+ void *ioPropertyData);
+
+ virtual OSStatus SetMagicCookieData( UInt32 inDataSize,
+ const void *inPropertyData);
+
+ virtual OSStatus GetMarkerListSize( UInt32 *outDataSize,
+ UInt32 *isWritable);
+
+ virtual OSStatus GetMarkerList( UInt32 *ioDataSize,
+ AudioFileMarkerList *ioMarkerList);
+
+ virtual OSStatus SetMarkerList( UInt32 inDataSize,
+ const AudioFileMarkerList *inMarkerList);
+
+
+ virtual OSStatus GetRegionListSize( UInt32 *outDataSize,
+ UInt32 *isWritable);
+
+ virtual OSStatus GetRegionList( UInt32 *ioDataSize,
+ AudioFileRegionList *ioRegionList);
+
+ virtual OSStatus SetRegionList( UInt32 inDataSize,
+ const AudioFileRegionList *inRegionList);
+
+ virtual OSStatus GetChannelLayoutSize( UInt32 *outDataSize,
+ UInt32 *isWritable);
+
+ virtual OSStatus GetChannelLayout( UInt32 *ioDataSize,
+ AudioChannelLayout *ioChannelLayout);
+
+ virtual OSStatus SetChannelLayout( UInt32 inDataSize,
+ const AudioChannelLayout *inChannelLayout);
+
+
+ virtual OSStatus GetInfoDictionarySize( UInt32 *outDataSize,
+ UInt32 *isWritable);
+
+ virtual OSStatus GetInfoDictionary( CACFDictionary *infoDict);
+
+ virtual OSStatus SetInfoDictionary( CACFDictionary *infoDict);
+
+ virtual OSStatus GetSoundCheckDictionarySize( UInt32 *outDataSize,
+ UInt32 *isWritable) { return kAudioFileUnsupportedPropertyError; }
+
+ virtual OSStatus GetSoundCheckDictionary( CACFDictionary *infoDict) { return kAudioFileUnsupportedPropertyError; }
+
+ virtual OSStatus SetSoundCheckDictionary( CACFDictionary *infoDict) { return kAudioFileUnsupportedPropertyError; }
+
+ virtual OSStatus GetLoudnessInfo( CACFDictionary *infoDict) { return kAudioFileUnsupportedPropertyError; }
+
+ virtual OSStatus GetSoundCheckDictionaryFromLoudnessInfo(CACFDictionary* outInfoDict) { return kAudioFileUnsupportedPropertyError; }
+ virtual OSStatus GetLoudnessInfoFromSoundCheckDictionary(CACFDictionary* outInfoDict) { return kAudioFileUnsupportedPropertyError; }
+
+ virtual OSStatus SetLoudnessInfo( CACFDictionary *infoDict) { return kAudioFileUnsupportedPropertyError; }
+
+ virtual OSStatus GetLoudnessInfoSize( UInt32 *outDataSize,
+ UInt32 *isWritable) { return kAudioFileUnsupportedPropertyError; }
+
+ virtual OSStatus GenerateLoudnessInfo( CACFDictionary *infoDict) { return kAudioFileUnsupportedPropertyError; }
+
+ virtual OSStatus GetEstimatedDuration( Float64* duration);
+
+ virtual OSStatus CountUserData( UInt32 inUserDataID,
+ UInt32 *outNumberItems);
+
+ virtual OSStatus GetUserDataSize( UInt32 inUserDataID,
+ UInt32 inIndex,
+ UInt32 *outDataSize);
+
+ virtual OSStatus GetUserData( UInt32 inUserDataID,
+ UInt32 inIndex,
+ UInt32 *ioDataSize,
+ void *ioUserData);
+
+ virtual OSStatus SetUserData( UInt32 inUserDataID,
+ UInt32 inIndex,
+ UInt32 inDataSize,
+ const void *inUserData);
+
+ virtual OSStatus RemoveUserData( UInt32 inUserDataID,
+ UInt32 inIndex);
+
+ virtual OSStatus GetLyrics(CFStringRef *outLyrics) { return kAudioFileUnsupportedPropertyError; }
+
+
+ Boolean CanRead() const { return mPermissions & kAudioFileReadPermission; }
+ Boolean CanWrite() const { return mPermissions & kAudioFileWritePermission; }
+
+ void SetPermissions(SInt8 inPermissions) { mPermissions = inPermissions; }
+
+/* Other Helper Methods: (some may not be necessary depending on how things are refactored) */
+
+ OSStatus OpenFile(SInt8 inPermissions, int inFD);
+
+ OSStatus CreateDataFile (CFURLRef inFileRef, int &outFileD);
+
+ OSStatus AddDurationToInfoDictionary(CACFDictionary *infoDict, Float64 &inDuration);
+
+ virtual Boolean IsDataFormatSupported(const AudioStreamBasicDescription *inFormat) = 0;
+ virtual Boolean IsDataFormatValid(const AudioStreamBasicDescription *inFormat);
+
+ virtual OSStatus IsValidFilePosition(SInt64 /*position*/) { return noErr; }
+
+ OSStatus MoveData(SInt64 fromPos, SInt64 toPos, SInt64 size);
+
+/* Accessors: */
+ Boolean IsInitialized() const { return mIsInitialized; }
+ void SetInitialized(Boolean inFlag) { mIsInitialized = inFlag; }
+
+ DataSource* GetDataSource() const { return mDataSource; }
+ void SetDataSource(DataSource *inDataSource);
+
+ void SetURL (CFURLRef inURL);
+
+ virtual UInt32 GetMaximumPacketSize() { return mMaximumPacketSize; }
+ virtual UInt32 FindMaximumPacketSize() { return mMaximumPacketSize; }
+ virtual void SetMaximumPacketSize(const UInt32 inPacketSize) { mMaximumPacketSize = inPacketSize; }
+
+ virtual UInt32 GetPacketSizeUpperBound() { return GetMaximumPacketSize (); }
+
+ SInt64 GetDataOffset() const { return mDataOffset; }
+ void SetDataOffset(SInt64 inOffset) { mDataOffset = inOffset; }
+
+ // I like this idiom better than DoesPacketTableExist+NewPacketTable:
+ CompressedPacketTable* GetPacketTable(Boolean inCreateIt = false)
+ {
+ if (!mPacketTable && inCreateIt)
+ mPacketTable = new CompressedPacketTable(mDataFormat.mFramesPerPacket);
+ return mPacketTable;
+ }
+ void ClearPacketTable()
+ {
+ DeletePacketTable();
+ GetPacketTable(true);
+ }
+
+ virtual OSStatus ScanForPackets(SInt64 inToPacketCount, DataSource* inDataSrc = NULL, bool fullyParsedIfEndOfDataReached = true)
+ {
+ // In formats that read packets lazily, this will be overridden to scan for packets up to the index.
+ if (inToPacketCount > GetNumPackets())
+ return kAudioFileEndOfFileError;
+
+ return noErr;
+ }
+
+ void AppendPacket(const AudioStreamPacketDescription &inPacket)
+ {
+ CompressedPacketTable* packetTable = GetPacketTable(true);
+ UInt32 numFramesInPacket = mDataFormat.mFramesPerPacket ? mDataFormat.mFramesPerPacket : inPacket.mVariableFramesInPacket;
+
+ AudioStreamPacketDescriptionExtended pext;
+ memset(&pext, 0, sizeof(pext));
+ pext.mStartOffset = inPacket.mStartOffset;
+ pext.mDataByteSize = inPacket.mDataByteSize;
+ pext.mVariableFramesInPacket = inPacket.mVariableFramesInPacket;
+ pext.mFrameOffset = numFramesInPacket + (packetTable->size() ? packetTable->back().mFrameOffset : 0);
+
+ packetTable->push_back(pext);
+ if (inPacket.mDataByteSize > mMaximumPacketSize)
+ mMaximumPacketSize = inPacket.mDataByteSize;
+ }
+ void DeletePacketTable() { delete mPacketTable; mPacketTable = NULL;}
+ SInt64 GetPacketTableSize() { return mPacketTable ? mPacketTable->size() : 0; }
+ OSStatus GetPacketDescriptions(UInt32 inStartingPacket, UInt32 *ioDataSize, AudioStreamPacketDescription *outPacketDescriptions)
+ {
+ if (outPacketDescriptions == NULL) return kAudioFileUnspecifiedError;
+ if (mPacketTable)
+ {
+ // only get as many packet descriptions as can fit in outPacketDescriptions
+ UInt32 count = *ioDataSize / sizeof(AudioStreamPacketDescription);
+ if (count + inStartingPacket > GetPacketTableSize())
+ count = (UInt32)(GetPacketTableSize() - inStartingPacket);
+
+ *ioDataSize = 0;
+ for (UInt32 i = inStartingPacket; i < (count + inStartingPacket); i++)
+ {
+ AudioStreamPacketDescription curPacket = (*mPacketTable)[i];
+ outPacketDescriptions[i].mStartOffset = curPacket.mStartOffset - GetDataOffset();
+ outPacketDescriptions[i].mVariableFramesInPacket = curPacket.mVariableFramesInPacket;
+ outPacketDescriptions[i].mDataByteSize = curPacket.mDataByteSize;
+ *ioDataSize += sizeof(AudioStreamPacketDescription);
+ }
+ }
+ else
+ *ioDataSize = 0;
+
+ return noErr;
+ }
+
+#if DEBUG
+ void DumpPacketTable()
+ {
+ if (mPacketTable) {
+ SInt64 size = mPacketTable->size();
+ printf("PacketTable size %d\n", (int)size);
+ for (SInt64 i = 0; i < size; i++) {
+ AudioStreamPacketDescription curPacket = (*mPacketTable)[i];
+ printf("dpkt %5qd %8qd %5d %5d\n", i, curPacket.mStartOffset, (int)curPacket.mDataByteSize, (int)curPacket.mVariableFramesInPacket);
+ }
+ }
+ }
+#endif
+
+ Boolean GetNeedsSizeUpdate() const { return mNeedsSizeUpdate; }
+ void SetNeedsSizeUpdate(Boolean inNeedsSizeUpdate) { mNeedsSizeUpdate = inNeedsSizeUpdate; }
+
+ CFURLRef GetURL () const { return mFileRef; }
+
+ virtual OSStatus GetSourceBitDepth(SInt32& outValue) { outValue = 0; return kAudioFileUnsupportedPropertyError; }
+ virtual OSStatus SetSourceBitDepth(SInt32 inValue) { return kAudioFileUnsupportedPropertyError; }
+
+ virtual OSStatus GetAlbumArtwork(CFDataRef& outValue) { outValue = NULL; return kAudioFileUnsupportedPropertyError; }
+ virtual OSStatus SetAlbumArtwork(CFDataRef inValue){ return kAudioFileUnsupportedPropertyError; }
+
+private:
+
+ void SetAlignDataWithFillerChunks(Boolean inFlag) { mAlignDataWithFillerChunks = inFlag; }
+
+ OSStatus ValidateFormatAndData();
+
+/* debug */
+// virtual void PrintFile (FILE* inFile, const char *indent) = 0;
+};
+
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+inline Boolean cfstrcmpi(CFStringRef a, CFStringRef b)
+{
+ // case insensitive CFString compare
+ return CFStringCompare(a, b, kCFCompareCaseInsensitive) == kCFCompareEqualTo;
+}
+
+CFBundleRef GetAudioToolboxBundle();
+
+
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+#endif
diff --git a/libs/appleutility/CoreAudio/AudioFile/AFPublic/CompressedPacketTable.cpp b/libs/appleutility/CoreAudio/AudioFile/AFPublic/CompressedPacketTable.cpp
new file mode 100644
index 0000000000..ba07580bba
--- /dev/null
+++ b/libs/appleutility/CoreAudio/AudioFile/AFPublic/CompressedPacketTable.cpp
@@ -0,0 +1,216 @@
+/*
+ File: CompressedPacketTable.cpp
+ Abstract: CompressedPacketTable.h
+ Version: 1.1
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms. If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+
+*/
+#include "CompressedPacketTable.h"
+#include "CAAutoDisposer.h"
+
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+const UInt32 CompressedPacketTable::kShift = 5;
+const UInt32 CompressedPacketTable::kMask = 31;
+
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+CompressedPacketTable::~CompressedPacketTable()
+{
+ size_t size = mBases.size();
+ for (size_t i = 0; i < size; ++i) {
+ free(mBases[i].mDescs);
+ }
+}
+
+void CompressedPacketTable::push_back(const AudioStreamPacketDescriptionExtended& inDesc)
+{
+ SInt64 baseIndex = mSize >> kShift;
+ UInt32 packetIndex = (UInt32)(mSize & kMask);
+
+ if (packetIndex == 0) {
+ // first packet in a new sequence. create a new PacketBase.
+ PacketBase newBase;
+ newBase.mBaseOffset = 0;
+ newBase.mDescs = CA_malloc((kMask+1) * sizeof(AudioStreamPacketDescriptionExtended));
+ newBase.mDescType = kExtendedPacketDescription;
+ mBases.push_back(newBase);
+ }
+
+ PacketBase& base = mBases[(size_t)baseIndex];
+ AudioStreamPacketDescriptionExtended* descs = (AudioStreamPacketDescriptionExtended*)base.mDescs;
+ descs[packetIndex] = inDesc;
+
+ if (packetIndex == kMask) {
+ // last packet in a sequence. compress the sequence.
+ Compress(base);
+ }
+
+ mSize++;
+}
+
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+#define ACCESS_TYPE(TYPE) \
+ case k##TYPE##ContiguousPacketDescription : { \
+ TYPE##ContiguousPacketDescription* descs = (TYPE##ContiguousPacketDescription*)base.mDescs; \
+ packetOffset = packetIndex ? descs[packetIndex-1].mNextOffset : 0; \
+ packetSize = (UInt32)(descs[packetIndex].mNextOffset - packetOffset); \
+ } break; \
+ case k##TYPE##DiscontiguousPacketDescription : { \
+ TYPE##DiscontiguousPacketDescription* descs = (TYPE##DiscontiguousPacketDescription*)base.mDescs; \
+ packetOffset = packetIndex ? descs[packetIndex-1].mNextOffset : 0; \
+ packetSize = descs[packetIndex].mDataByteSize; \
+ } break;
+
+const AudioStreamPacketDescriptionExtended CompressedPacketTable::operator[](SInt64 inPacketIndex) const
+{
+ SInt64 baseIndex = inPacketIndex >> kShift;
+ UInt32 packetIndex = (UInt32)(inPacketIndex & kMask);
+
+ if ((size_t)baseIndex >= mBases.size())
+ throw -1;
+
+ const PacketBase& base = mBases[(size_t)baseIndex];
+
+ SInt64 packetOffset = 0;
+ UInt32 packetSize = 0;
+
+ switch (base.mDescType)
+ {
+ ACCESS_TYPE(Tiny)
+ ACCESS_TYPE(Small)
+ ACCESS_TYPE(Big)
+ case kExtendedPacketDescription :
+ return ((AudioStreamPacketDescriptionExtended*)base.mDescs)[packetIndex];
+ }
+
+ AudioStreamPacketDescriptionExtended outDesc;
+ outDesc.mStartOffset = base.mBaseOffset + packetOffset;
+ outDesc.mDataByteSize = packetSize;
+ outDesc.mVariableFramesInPacket = 0;
+ outDesc.mFrameOffset = mFramesPerPacket * inPacketIndex;
+
+ //printf("get %d %10qd %10qd %2d %10qd %6d %10qd\n", base.mDescType, inPacketIndex, baseIndex, packetIndex, outDesc.mStartOffset, outDesc.mDataByteSize, outDesc.mFrameOffset);
+
+ return outDesc;
+}
+
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+bool CompressedPacketTable::isContiguous(PacketBase& base)
+{
+ AudioStreamPacketDescriptionExtended* descs = (AudioStreamPacketDescriptionExtended*)base.mDescs;
+ SInt64 expectedOffset = descs[0].mStartOffset + descs[0].mDataByteSize;
+ for (UInt32 i = 1; i <= kMask; ++i) {
+ if (expectedOffset != descs[i].mStartOffset) return false;
+ expectedOffset += descs[i].mDataByteSize;
+ }
+ return true;
+}
+
+bool CompressedPacketTable::hasVariableFrames(PacketBase& base)
+{
+ AudioStreamPacketDescriptionExtended* descs = (AudioStreamPacketDescriptionExtended*)base.mDescs;
+ for (UInt32 i = 0; i <= kMask; ++i) {
+ if (descs[i].mVariableFramesInPacket) return true;
+ }
+ return false;
+}
+
+UInt32 CompressedPacketTable::largestPacket(PacketBase& base)
+{
+ UInt32 maxPacketSize = 0;
+ AudioStreamPacketDescriptionExtended* descs = (AudioStreamPacketDescriptionExtended*)base.mDescs;
+ for (UInt32 i = 0; i <= kMask; ++i) {
+ UInt32 packetSize = descs[i].mDataByteSize;
+ if (packetSize > maxPacketSize) maxPacketSize = packetSize;
+ }
+ return maxPacketSize;
+}
+
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+#define COMPRESS_TYPE(TYPE, BITS) \
+ if (contiguous) { \
+ TYPE##ContiguousPacketDescription* newDescs = (TYPE##ContiguousPacketDescription*)CA_malloc((kMask+1) * sizeof(TYPE##ContiguousPacketDescription)); \
+ base.mDescs = newDescs; \
+ base.mDescType = k##TYPE##ContiguousPacketDescription; \
+ for (UInt32 i = 0; i <= kMask; ++i) { \
+ newDescs[i].mNextOffset = (BITS)(descs[i].mStartOffset + descs[i].mDataByteSize - baseOffset); \
+ } \
+ free(descs); \
+ } else { \
+ TYPE##DiscontiguousPacketDescription* newDescs = (TYPE##DiscontiguousPacketDescription*)CA_malloc((kMask+1) * sizeof(TYPE##DiscontiguousPacketDescription)); \
+ base.mDescs = newDescs; \
+ base.mDescType = k##TYPE##DiscontiguousPacketDescription; \
+ for (UInt32 i = 0; i <= kMask; ++i) { \
+ newDescs[i].mNextOffset = i == kMask ? 0 : (BITS)(descs[i+1].mStartOffset - baseOffset); \
+ newDescs[i].mDataByteSize = descs[i].mDataByteSize; \
+ } \
+ free(descs); \
+ } \
+ return;
+
+void CompressedPacketTable::Compress(PacketBase& base)
+{
+ if (hasVariableFrames(base))
+ return;
+
+ bool contiguous = isContiguous(base);
+
+ AudioStreamPacketDescriptionExtended* descs = (AudioStreamPacketDescriptionExtended*)base.mDescs;
+ SInt64 delta = descs[kMask].mStartOffset + descs[kMask].mDataByteSize - descs[0].mStartOffset;
+
+ SInt64 baseOffset = descs[0].mStartOffset;
+ base.mBaseOffset = baseOffset;
+
+ if (delta <= 65535LL) {
+ COMPRESS_TYPE(Tiny, UInt16)
+ } else if (delta <= 4294967295LL && largestPacket(base) <= 65535) {
+ COMPRESS_TYPE(Small, UInt32)
+ } else {
+ COMPRESS_TYPE(Big, SInt64)
+ }
+}
+
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
diff --git a/libs/appleutility/CoreAudio/AudioFile/AFPublic/CompressedPacketTable.h b/libs/appleutility/CoreAudio/AudioFile/AFPublic/CompressedPacketTable.h
new file mode 100644
index 0000000000..47e28ca499
--- /dev/null
+++ b/libs/appleutility/CoreAudio/AudioFile/AFPublic/CompressedPacketTable.h
@@ -0,0 +1,186 @@
+/*
+ File: CompressedPacketTable.h
+ Abstract: Part of CoreAudio Utility Classes
+ Version: 1.1
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms. If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+
+*/
+#include <iterator>
+#include <vector>
+#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
+ #include <CoreAudio/CoreAudioTypes.h>
+#else
+ #include "CoreAudioTypes.h"
+#endif
+
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+struct AudioStreamPacketDescriptionExtended : AudioStreamPacketDescription
+{
+ SInt64 mFrameOffset; // this is the sum of the mVariableFramesInPacket up to this point so we can binary search.
+};
+typedef struct AudioStreamPacketDescriptionExtended AudioStreamPacketDescriptionExtended;
+
+inline bool operator < (const AudioStreamPacketDescriptionExtended& a, const AudioStreamPacketDescriptionExtended& b)
+{
+ return a.mFrameOffset < b.mFrameOffset;
+}
+
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+class CompressedPacketTable
+{
+public:
+ CompressedPacketTable(UInt32 inFramesPerPacket) : mSize(0), mFramesPerPacket(inFramesPerPacket) {}
+ ~CompressedPacketTable();
+
+ SInt64 size() const { return mSize; }
+ void push_back(const AudioStreamPacketDescriptionExtended& inDesc);
+
+ const AudioStreamPacketDescriptionExtended operator[](SInt64 inPacketIndex) const;
+ const AudioStreamPacketDescriptionExtended front() const { return (*this)[0]; }
+ const AudioStreamPacketDescriptionExtended back() const { return (*this)[mSize-1]; }
+
+ //SInt64 PacketForByte(SInt64 inByteOffset) const;
+ SInt64 ByteForPacket(SInt64 inPacketIndex) const { return (*this)[inPacketIndex].mStartOffset; }
+
+ class iterator {
+ public:
+ typedef std::input_iterator_tag iterator_category;
+ typedef iterator pointer;
+ typedef SInt64 difference_type;
+ typedef AudioStreamPacketDescriptionExtended value_type;
+ typedef value_type& reference;
+
+ iterator() : mTable(NULL), mIndex(0) {}
+ iterator(const CompressedPacketTable* table, SInt64 index) : mTable(table), mIndex(index) {}
+ iterator(const iterator& that) : mTable(that.mTable), mIndex(that.mIndex) {}
+
+ iterator& operator=(const iterator& that) { mTable = that.mTable; mIndex = that.mIndex; return *this; }
+
+ const AudioStreamPacketDescriptionExtended operator*() const { return (*mTable)[mIndex]; }
+ const AudioStreamPacketDescriptionExtended* const operator->() { mValue = (*mTable)[mIndex]; return &mValue; }
+ iterator& operator++() { ++mIndex; return *this; }
+ iterator& operator--() { --mIndex; return *this; }
+
+ SInt64 operator-(const iterator& that) { return mIndex - that.mIndex; }
+ const iterator operator-(SInt64 index) { return iterator(mTable, mIndex - index); }
+ const iterator operator+(SInt64 index) { return iterator(mTable, mIndex + index); }
+ bool operator==(const iterator& that) { return mIndex == that.mIndex; }
+ bool operator!=(const iterator& that) { return mIndex != that.mIndex; }
+ bool operator>(const iterator& that) { return mIndex > that.mIndex; }
+ bool operator<(const iterator& that) { return mIndex < that.mIndex; }
+ private:
+ const CompressedPacketTable* mTable;
+ SInt64 mIndex;
+ AudioStreamPacketDescriptionExtended mValue; // in order to support operator-> .
+ };
+
+ iterator begin() const { return iterator(this, 0); }
+ iterator end() const { return iterator(this, mSize); }
+
+private:
+ struct TinyContiguousPacketDescription
+ {
+ UInt16 mNextOffset;
+ };
+
+ struct TinyDiscontiguousPacketDescription : TinyContiguousPacketDescription
+ {
+ UInt16 mDataByteSize;
+ };
+
+ // There could be a 24 bit packet description. But ALAC is who usually needs SmallContiguousPacketDescription and
+ // it already uses 8x fewer packet descriptions than AAC due to the mFramesPerPacket being 8x greater.
+ // So there isn't as great a need for saving space. 4 bytes per packet is OK for ALAC.
+
+ struct SmallContiguousPacketDescription
+ {
+ UInt32 mNextOffset;
+ };
+
+ struct SmallDiscontiguousPacketDescription : SmallContiguousPacketDescription
+ {
+ UInt16 mDataByteSize;
+ };
+
+ struct BigContiguousPacketDescription
+ {
+ UInt64 mNextOffset;
+ };
+
+ struct BigDiscontiguousPacketDescription : BigContiguousPacketDescription
+ {
+ UInt32 mDataByteSize;
+ };
+
+ struct PacketBase
+ {
+ SInt64 mBaseOffset;
+ UInt8 mDescType;
+ void* mDescs;
+ };
+
+ enum {
+ kTinyContiguousPacketDescription,
+ kTinyDiscontiguousPacketDescription,
+ kSmallContiguousPacketDescription,
+ kSmallDiscontiguousPacketDescription,
+ kBigContiguousPacketDescription,
+ kBigDiscontiguousPacketDescription,
+ kExtendedPacketDescription
+ };
+ static const UInt32 kShift;
+ static const UInt32 kMask;
+
+ bool isContiguous(PacketBase& base);
+ bool hasVariableFrames(PacketBase& base);
+ UInt32 largestPacket(PacketBase& base);
+
+ void Compress(PacketBase& base);
+
+private:
+ std::vector<PacketBase> mBases;
+ UInt64 mSize;
+ UInt32 mFramesPerPacket;
+};
+
diff --git a/libs/appleutility/CoreAudio/AudioFile/AFPublic/DataSource.cpp b/libs/appleutility/CoreAudio/AudioFile/AFPublic/DataSource.cpp
new file mode 100644
index 0000000000..c8a93d2756
--- /dev/null
+++ b/libs/appleutility/CoreAudio/AudioFile/AFPublic/DataSource.cpp
@@ -0,0 +1,689 @@
+/*
+ File: DataSource.cpp
+ Abstract: DataSource.h
+ Version: 1.1
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms. If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+
+*/
+#include "DataSource.h"
+#if TARGET_OS_WIN32
+ #include <io.h>
+#else
+ #include <unistd.h>
+ #include <fcntl.h>
+#endif
+#include <sys/stat.h>
+#include <algorithm>
+
+#define VERBOSE 0
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+
+const UInt16 kPositionModeMask = 3;
+
+DataSource::DataSource(Boolean inCloseOnDelete)
+ : mCloseOnDelete(inCloseOnDelete)
+{
+}
+
+DataSource::~DataSource()
+{
+}
+
+SInt64 DataSource::CalcOffset( UInt16 positionMode,
+ SInt64 positionOffset,
+ SInt64 currentOffset,
+ SInt64 size)
+{
+ SInt64 newOffset = 0;
+ switch (positionMode & kPositionModeMask) {
+ //case fsAtMark : newOffset = currentOffset; break;
+ case SEEK_SET : newOffset = positionOffset; break;
+ case SEEK_END : newOffset = size + positionOffset; break;
+ case SEEK_CUR : newOffset = positionOffset + currentOffset; break;
+ }
+ return newOffset;
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////////////////////
+
+#if 0
+
+MacFile_DataSource::MacFile_DataSource( FSIORefNum inForkRefNum, SInt8 inPermissions, Boolean inCloseOnDelete)
+ : DataSource(inCloseOnDelete), mFileNum(inForkRefNum), mPermissions(inPermissions)
+{
+}
+
+MacFile_DataSource::~MacFile_DataSource()
+{
+ if (mCloseOnDelete) FSCloseFork(mFileNum);
+}
+
+
+OSStatus MacFile_DataSource::GetSize(SInt64& outSize)
+{
+ outSize = -1; // in case of error
+ OSStatus err = FSGetForkSize(mFileNum, &outSize);
+ return err;
+}
+
+OSStatus MacFile_DataSource::GetPos(SInt64& outPos) const
+{
+ return FSGetForkPosition(mFileNum, &outPos);
+}
+
+OSStatus MacFile_DataSource::SetSize(SInt64 inSize)
+{
+ return FSSetForkSize(mFileNum, SEEK_SET, inSize);
+}
+
+
+OSStatus MacFile_DataSource::ReadBytes(
+ UInt16 positionMode,
+ SInt64 positionOffset,
+ UInt32 requestCount,
+ void *buffer,
+ UInt32* actualCount)
+{
+ if (actualCount) *actualCount = 0;
+ if (!buffer) return kAudio_ParamError;
+ ByteCount bc_actualCount = 0;
+ OSStatus err = FSReadFork(mFileNum, positionMode, positionOffset, requestCount, buffer, &bc_actualCount);
+ if (actualCount) *actualCount = (UInt32)bc_actualCount;
+ return err;
+}
+
+OSStatus MacFile_DataSource::WriteBytes(
+ UInt16 positionMode,
+ SInt64 positionOffset,
+ UInt32 requestCount,
+ const void *buffer,
+ UInt32* actualCount)
+{
+ if (!buffer) return kAudio_ParamError;
+ ByteCount bc_actualCount = 0;
+ OSStatus err = FSWriteFork(mFileNum, positionMode, positionOffset, requestCount, buffer, &bc_actualCount);
+ if (actualCount) *actualCount = (UInt32)bc_actualCount;
+ return err;
+}
+#endif
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+#define kAudioFileNoCacheMask 0x20
+
+UnixFile_DataSource::UnixFile_DataSource( int inFD, SInt8 inPermissions, Boolean inCloseOnDelete)
+ : DataSource(inCloseOnDelete), mFileD(inFD), mPermissions(inPermissions), mNoCache(0), mCachedSize(-1), mFilePointer(0)
+{
+}
+
+UnixFile_DataSource::~UnixFile_DataSource()
+{
+ if (mCloseOnDelete) close(mFileD);
+}
+
+OSStatus UnixFile_DataSource::GetSize(SInt64& outSize)
+{
+#if 0 // 6764274 using the cached file size causes a regression for apps that play a file while writing to it.
+ if (mCachedSize >= 0) {
+ outSize = mCachedSize;
+ return noErr;
+ }
+#endif
+ outSize = -1; // in case of error
+ struct stat stbuf;
+ if (fstat (mFileD, &stbuf) == -1) return kAudio_FileNotFoundError;
+ outSize = mCachedSize = stbuf.st_size;
+ return noErr;
+}
+
+OSStatus UnixFile_DataSource::SetSize(SInt64 inSize)
+{
+ mCachedSize = -1;
+#if TARGET_OS_WIN32
+ if (chsize (mFileD, inSize)) return kAudioFilePermissionsError;
+#else
+ if (ftruncate (mFileD, inSize) == -1) return kAudioFilePermissionsError;
+#endif
+ mCachedSize = inSize;
+ return noErr;
+}
+
+
+OSStatus UnixFile_DataSource::GetPos(SInt64& outPos) const
+{
+ outPos = mFilePointer;
+ return noErr;
+}
+
+SInt64 UnixFile_DataSource::UFCurrentOffset (UInt16 positionMode,
+ SInt64 positionOffset)
+{
+ SInt64 offset = -1;
+ switch (positionMode & kPositionModeMask)
+ {
+ /*case fsAtMark :
+ {
+ SInt64 pos;
+ OSStatus result = GetPos (pos);
+ if (result) return result;
+ offset = pos;
+ break;
+ }*/
+ case SEEK_SET :
+ {
+ offset = positionOffset;
+ break;
+ }
+ case SEEK_END :
+ {
+ SInt64 size;
+ OSStatus result = GetSize (size);
+ if (result) return result;
+ offset = size + positionOffset;
+ break;
+ }
+ case SEEK_CUR :
+ {
+ SInt64 pos;
+ OSStatus result = GetPos (pos);
+ if (result) return result;
+ offset = positionOffset + pos;
+ break;
+ }
+ }
+ return offset;
+}
+
+OSStatus UnixFile_DataSource::ReadBytes( UInt16 positionMode,
+ SInt64 positionOffset,
+ UInt32 requestCount,
+ void *buffer,
+ UInt32* actualCount)
+{
+ if (actualCount) *actualCount = 0;
+ if (!buffer) return kAudio_ParamError;
+
+ // can't use current offset as we need to go to the disk too much
+ SInt64 offset = UFCurrentOffset (positionMode, positionOffset);
+ if (offset < 0) return kAudioFilePositionError;
+
+#if 0 // 6571050 fstat-ing the file every read causes a performance regression
+ // 5931571 check that read may exceed eof and curtail it.
+ do {
+ SInt64 size;
+ OSStatus serr = GetSize(size);
+ if (serr) break;
+ SInt64 remain = size - offset;
+ if (remain < 0) requestCount = 0;
+ else if (requestCount > remain) requestCount = remain;
+ } while (false);
+#endif
+
+ if (requestCount <= 0) {
+ if (actualCount) *actualCount = 0;
+ return noErr;
+ }
+
+#if !TARGET_OS_WIN32
+ UInt32 noCache = positionMode & kAudioFileNoCacheMask ? 1 : 0;
+ if (noCache != mNoCache) {
+ mNoCache = noCache;
+ fcntl(mFileD, F_NOCACHE, mNoCache);
+ }
+#endif
+
+ size_t readBytes = requestCount;
+#if TARGET_OS_WIN32
+ lseek(mFileD, offset, SEEK_SET);
+ int numBytes = read (mFileD, buffer, readBytes);
+#else
+ ssize_t numBytes = pread (mFileD, buffer, readBytes, offset);
+#endif
+ if (numBytes == -1) return kAudioFilePositionError;
+ mFilePointer = offset + numBytes;
+
+ if (actualCount) *actualCount = (UInt32)numBytes;
+ return noErr;
+}
+
+OSStatus UnixFile_DataSource::WriteBytes(UInt16 positionMode,
+ SInt64 positionOffset,
+ UInt32 requestCount,
+ const void *buffer,
+ UInt32* actualCount)
+{
+ if (!buffer) return kAudio_ParamError;
+
+ // can't use current offset as we need to go to the disk too much
+ SInt64 offset = UFCurrentOffset (positionMode, positionOffset);
+ if (offset < 0) return kAudioFilePositionError;
+
+ mCachedSize = -1;
+
+ size_t writeBytes = requestCount;
+
+#if !TARGET_OS_WIN32
+ UInt32 noCache = positionMode & kAudioFileNoCacheMask ? 1 : 0;
+ if (noCache != mNoCache) {
+ mNoCache = noCache;
+ fcntl(mFileD, F_NOCACHE, mNoCache);
+ }
+#endif
+
+#if TARGET_OS_WIN32
+ lseek(mFileD, offset, SEEK_SET);
+ int numBytes = write (mFileD, buffer, writeBytes);
+#else
+ ssize_t numBytes = pwrite (mFileD, buffer, writeBytes, offset);
+#endif
+ if (numBytes == -1) return kAudioFilePositionError;
+ mFilePointer = offset + numBytes;
+
+ if (actualCount) *actualCount = (UInt32)numBytes;
+ return noErr;
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+#define NO_CACHE 0
+
+OSStatus Cached_DataSource::ReadFromHeaderCache(
+ SInt64 offset,
+ UInt32 requestCount,
+ void *buffer,
+ UInt32* actualCount)
+{
+ if (actualCount) *actualCount = 0;
+ OSStatus err = noErr;
+ ByteCount theActualCount = 0;
+
+#if VERBOSE
+ printf("read from header %lld %lu %lld %lu\n", offset, requestCount, 0LL, mHeaderCacheSize);
+#endif
+
+ if (!mHeaderCache())
+ {
+ mHeaderCache.allocBytes(mHeaderCacheSize, true);
+ err = mDataSource->ReadBytes(SEEK_SET, 0, mHeaderCacheSize, mHeaderCache(), &mHeaderCacheSize);
+ if (err == kAudioFileEndOfFileError) err = noErr;
+ if (err) return err;
+ }
+
+ ByteCount firstPart = std::min((ByteCount)requestCount, (ByteCount)(mHeaderCacheSize - offset));
+ ByteCount secondPart = requestCount - firstPart;
+
+ memcpy(buffer, mHeaderCache + (ByteCount)offset, firstPart);
+ theActualCount = firstPart;
+
+ if (secondPart) {
+ UInt32 secondPartActualCount = 0;
+ err = mDataSource->ReadBytes(SEEK_SET, mHeaderCacheSize, static_cast<UInt32>(secondPart), (char*)buffer + firstPart, &secondPartActualCount);
+ theActualCount += secondPartActualCount;
+ }
+
+ if (actualCount) *actualCount = (UInt32)theActualCount;
+ mOffset = offset + theActualCount;
+
+ return err;
+}
+
+OSStatus Cached_DataSource::ReadBytes(
+ UInt16 positionMode,
+ SInt64 positionOffset,
+ UInt32 requestCount,
+ void *buffer,
+ UInt32* actualCount)
+{
+ if (actualCount) *actualCount = 0;
+ OSStatus err = noErr;
+ SInt64 size;
+ UInt32 theActualCount = 0;
+
+ if (!buffer) return kAudio_ParamError;
+
+ if ((positionMode & kPositionModeMask) != SEEK_END) size = 0; // not used in this case
+ else
+ {
+ err = GetSize(size);
+ if (err) return err;
+ }
+
+ SInt64 offset = CalcOffset(positionMode, positionOffset, mOffset, size);
+ if (offset < 0) return kAudioFilePositionError;
+
+ if (offset < mHeaderCacheSize) {
+ return ReadFromHeaderCache(offset, requestCount, buffer, actualCount);
+ }
+
+#if NO_CACHE
+ err = mDataSource->ReadBytes(positionMode, positionOffset, requestCount, buffer, &theActualCount);
+ mOffset = offset + theActualCount;
+#else
+
+ SInt64 cacheEnd = mBodyCacheOffset + mBodyCacheCurSize;
+ if (mBodyCache() && requestCount < mBodyCacheSize && offset >= mBodyCacheOffset && offset < cacheEnd)
+ {
+ if (offset + requestCount <= cacheEnd)
+ {
+ // request is entirely within cache
+#if VERBOSE
+ printf("request is entirely within cache %lld %lu %lld %lu\n", offset, requestCount, mBodyCacheOffset, mBodyCacheCurSize);
+#endif
+ memcpy(buffer, mBodyCache + (size_t)(offset - mBodyCacheOffset), requestCount);
+ theActualCount = requestCount;
+ }
+ else
+ {
+ // part of request is within cache. copy, read next cache block, copy.
+#if VERBOSE
+ printf("part of request is within cache %lld %lu %lld %lu\n", offset, requestCount, mBodyCacheOffset, mBodyCacheCurSize);
+#endif
+
+ // copy first part.
+ ByteCount firstPart = (ByteCount)(cacheEnd - offset);
+ ByteCount secondPart = requestCount - firstPart;
+#if VERBOSE
+ printf("memcpy offset %lld mBodyCacheOffset %lld offset - mBodyCacheOffset %lld firstPart %lu requestCount %lu\n",
+ offset, mBodyCacheOffset, offset - mBodyCacheOffset, firstPart, requestCount);
+#endif
+ memcpy(buffer, mBodyCache + (size_t)(offset - mBodyCacheOffset), firstPart);
+
+ theActualCount = static_cast<UInt32>(firstPart);
+
+ // read new block
+ SInt64 nextOffset = mBodyCacheOffset + mBodyCacheCurSize;
+ err = mDataSource->ReadBytes(SEEK_SET, nextOffset, mBodyCacheSize, mBodyCache(), &mBodyCacheCurSize);
+
+ if (err == kAudioFileEndOfFileError) err = noErr;
+ if (err) goto leave;
+
+ mBodyCacheOffset = nextOffset;
+
+ // copy second part
+ secondPart = std::min(secondPart, (ByteCount)mBodyCacheCurSize);
+ if (secondPart) memcpy((char*)buffer + firstPart, mBodyCache(), secondPart);
+ theActualCount = static_cast<UInt32>(firstPart + secondPart);
+ }
+ }
+ else
+ {
+ if (requestCount > mBodyCacheSize)
+ {
+#if VERBOSE
+ printf("large request %lld %lu %lld %lu\n", offset, requestCount, mBodyCacheOffset, mBodyCacheCurSize);
+#endif
+ // the request is larger than we normally cache, just do a read and don't cache.
+ err = mDataSource->ReadBytes(positionMode, positionOffset, requestCount, buffer, &theActualCount);
+ mOffset = offset + theActualCount;
+ }
+ else
+ {
+ // request is outside cache. read new block.
+#if VERBOSE
+ printf("request is outside cache %lld %lu %lld %lu\n", offset, requestCount, mBodyCacheOffset, mBodyCacheCurSize);
+#endif
+ if (!mBodyCache())
+ {
+ mBodyCache.allocBytes(mBodyCacheSize, true);
+#if VERBOSE
+ printf("alloc mBodyCache %08X\n", mBodyCache());
+#endif
+ }
+ mBodyCacheOffset = offset;
+ err = mDataSource->ReadBytes(SEEK_SET, mBodyCacheOffset, mBodyCacheSize, mBodyCache(), &mBodyCacheCurSize);
+#if VERBOSE
+ printf("read %08X %d mBodyCacheOffset %lld %lu %lu\n", err, err, mBodyCacheOffset, mBodyCacheSize, mBodyCacheCurSize);
+#endif
+ if (err == kAudioFileEndOfFileError) err = noErr;
+ if (err) return err;
+
+ theActualCount = std::min(requestCount, mBodyCacheCurSize);
+ memcpy(buffer, mBodyCache(), theActualCount);
+ }
+
+ }
+
+leave:
+#endif
+ if (actualCount) *actualCount = (UInt32)theActualCount;
+#if VERBOSE
+ printf("<<read err %d actualCount %lu\n", err, *actualCount);
+#endif
+ return err;
+}
+
+OSStatus Cached_DataSource::WriteBytes(
+ UInt16 positionMode,
+ SInt64 positionOffset,
+ UInt32 requestCount,
+ const void *buffer,
+ UInt32* actualCount)
+{
+ OSStatus err = noErr;
+ SInt64 size;
+
+ if (!buffer) return kAudio_ParamError;
+
+ if ((positionMode & kPositionModeMask) != SEEK_END) size = 0; // not used in this case
+ else
+ {
+ err = GetSize(size);
+ if (err) return err;
+ }
+
+ SInt64 offset = CalcOffset(positionMode, positionOffset, mOffset, size);
+ if (offset < 0) return kAudioFilePositionError;
+
+ if (mHeaderCache() && offset < mHeaderCacheSize)
+ {
+ // header cache write through
+ ByteCount firstPart = std::min((ByteCount)requestCount, (ByteCount)(mHeaderCacheSize - offset));
+#if VERBOSE
+ printf("header cache write through %lu %lu\n", mHeaderCacheSize, firstPart);
+#endif
+ memcpy(mHeaderCache + (size_t)offset, buffer, firstPart);
+ }
+
+#if VERBOSE
+ printf("write %lld %lu %lld %d %lld\n", offset, requestCount, mOffset, positionMode, positionOffset);
+#endif
+
+ SInt64 cacheEnd = mBodyCacheOffset + mBodyCacheCurSize;
+ if (mBodyCache() && offset >= mBodyCacheOffset && offset < cacheEnd)
+ {
+ // body cache write through
+ ByteCount firstPart = std::min((SInt64)requestCount, cacheEnd - offset);
+#if VERBOSE
+ printf("body cache write through %lld %lu %lld %lu\n", mBodyCacheOffset, mBodyCacheCurSize, offset, firstPart);
+#endif
+ memcpy(mBodyCache + (offset - mBodyCacheOffset), buffer, firstPart);
+ }
+
+ UInt32 theActualCount;
+ err = mDataSource->WriteBytes(positionMode, positionOffset, requestCount, buffer, &theActualCount);
+
+ mOffset = offset + theActualCount;
+ if (actualCount) *actualCount = (UInt32)theActualCount;
+
+ return err;
+}
+
+
+//////////////////////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////////////////////
+
+Seekable_DataSource::Seekable_DataSource( void * inClientData,
+ AudioFile_ReadProc inReadFunc,
+ AudioFile_WriteProc inWriteFunc,
+ AudioFile_GetSizeProc inGetSizeFunc,
+ AudioFile_SetSizeProc inSetSizeFunc)
+ : DataSource(false), mClientData(inClientData), mReadFunc(inReadFunc), mWriteFunc(inWriteFunc),
+ mSizeFunc(inGetSizeFunc), mSetSizeFunc(inSetSizeFunc)
+{
+}
+
+Seekable_DataSource::~Seekable_DataSource()
+{
+}
+
+
+OSStatus Seekable_DataSource::GetSize(SInt64& outSize)
+{
+ if (!mSizeFunc) {
+ outSize = LLONG_MAX;
+ } else {
+ outSize = (*mSizeFunc)(mClientData);
+ }
+ return noErr;
+}
+
+OSStatus Seekable_DataSource::SetSize(SInt64 inSize)
+{
+ if (!mSetSizeFunc) return kAudioFileOperationNotSupportedError;
+ return (*mSetSizeFunc)(mClientData, inSize);
+}
+
+OSStatus Seekable_DataSource::ReadBytes(
+ UInt16 positionMode,
+ SInt64 positionOffset,
+ UInt32 requestCount,
+ void *buffer,
+ UInt32* actualCount)
+{
+ OSStatus err;
+
+ if (actualCount) *actualCount = 0;
+ if (!mReadFunc) return kAudioFileOperationNotSupportedError;
+ if (!buffer) return kAudio_ParamError;
+
+ positionMode &= kPositionModeMask;
+
+ SInt64 size;
+ err = GetSize(size);
+ if (err) return err;
+
+ SInt64 offset = CalcOffset(positionMode, positionOffset, mOffset, size);
+
+ // request is outside bounds of file
+ if (offset < 0)
+ return kAudioFilePositionError;
+ if (offset >= size)
+ return kAudioFileEndOfFileError;
+
+ // reduce request if it exceeds the amount available
+ requestCount = static_cast<UInt32>(std::min((SInt64)requestCount, size - offset));
+
+ UInt32 theActualCount = 0;
+ err = (*mReadFunc)(mClientData, offset, requestCount, buffer, &theActualCount);
+ if (actualCount) *actualCount = theActualCount;
+ mOffset = offset + theActualCount;
+ return err;
+}
+
+
+OSStatus Seekable_DataSource::WriteBytes(
+ UInt16 positionMode,
+ SInt64 positionOffset,
+ UInt32 requestCount,
+ const void *buffer,
+ UInt32* actualCount)
+{
+ OSStatus err;
+
+ if (!mWriteFunc) return kAudioFileOperationNotSupportedError;
+ if (!buffer) return kAudio_ParamError;
+
+ SInt64 size;
+ positionMode &= kPositionModeMask;
+ if (positionMode != SEEK_END) size = 0; // not used in this case
+ else
+ {
+ err = GetSize(size);
+ if (err) return err;
+ }
+
+ SInt64 offset = CalcOffset(positionMode, positionOffset, mOffset, size);
+ if (offset < 0) return kAudioFilePositionError;
+
+ UInt32 theActualCount;
+ err = (*mWriteFunc)(mClientData, offset, requestCount, buffer, &theActualCount);
+ if (err) return err;
+ if (actualCount) *actualCount = theActualCount;
+ mOffset = offset + theActualCount;
+ return noErr;
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+OSStatus Buffer_DataSource::ReadBytes(
+ UInt16 positionMode,
+ SInt64 positionOffset,
+ UInt32 requestCount,
+ void *buffer,
+ UInt32* actualCount)
+{
+ if (actualCount) *actualCount = 0;
+ SInt64 offsetWithinBuffer = CalcOffset(positionMode, positionOffset, mOffset, mDataByteSize + mStartOffset) - mStartOffset;
+ if (offsetWithinBuffer < 0 || offsetWithinBuffer >= mDataByteSize) return kAudioFilePositionError;
+
+ SInt64 bytesAfterOffset = mDataByteSize - offsetWithinBuffer;
+ SInt64 theActualCount = std::min(bytesAfterOffset, (SInt64)requestCount);
+
+ if (theActualCount <= 0) {
+ if (actualCount) *actualCount = 0;
+ return kAudio_ParamError;
+ }
+
+ memcpy(buffer, mData + offsetWithinBuffer, theActualCount);
+
+ if (actualCount) *actualCount = static_cast<UInt32>(theActualCount);
+ mOffset = offsetWithinBuffer + theActualCount;
+
+ return noErr;
+}
+
+
+
+//////////////////////////////////////////////////////////////////////////////////////////
diff --git a/libs/appleutility/CoreAudio/AudioFile/AFPublic/DataSource.h b/libs/appleutility/CoreAudio/AudioFile/AFPublic/DataSource.h
new file mode 100644
index 0000000000..6c79c94df9
--- /dev/null
+++ b/libs/appleutility/CoreAudio/AudioFile/AFPublic/DataSource.h
@@ -0,0 +1,372 @@
+/*
+ File: DataSource.h
+ Abstract: Part of CoreAudio Utility Classes
+ Version: 1.1
+
+ Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms. If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ Copyright (C) 2014 Apple Inc. All Rights Reserved.
+
+*/
+#ifndef __DataSource_h__
+#define __DataSource_h__
+
+#if !defined(__COREAUDIO_USE_FLAT_INCLUDES__)
+ #include <AudioToolbox/AudioFile.h>
+#else
+ #include <ConditionalMacros.h>
+ #include "AudioFile.h"
+#endif
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdexcept>
+#include "CAAutoDisposer.h"
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+class DataSource
+{
+public:
+
+ DataSource(Boolean inCloseOnDelete);
+ virtual ~DataSource();
+
+ virtual OSStatus GetSize32(UInt32& outSize)
+ {
+ SInt64 size64;
+ OSStatus err = GetSize(size64);
+ if (err) return err;
+ if (size64 > 0x00000000FFFFffffLL) return kAudioFileDoesNotAllow64BitDataSizeError;
+ outSize = (UInt32)size64;
+ return noErr;
+ }
+
+ virtual OSStatus GetSize(SInt64& outSize) =0;
+
+ virtual OSStatus SetSize(SInt64 inSize)=0;
+
+ virtual OSStatus GetPos(SInt64& outPos) const=0;
+
+ /* non seekable data sources should use fsAtMark for the positionMode (or SEEK_CUR with offset zero,
+ or SEEK_SET with offset equal to the current position in the stream, in other words no seeking from the
+ current position is allowed.)
+ */
+
+ virtual OSStatus ReadBytes( UInt16 positionMode,
+ SInt64 positionOffset,
+ UInt32 requestCount,
+ void *buffer,
+ UInt32* actualCount)=0;
+
+ virtual OSStatus WriteBytes(UInt16 positionMode,
+ SInt64 positionOffset,
+ UInt32 requestCount,
+ const void *buffer,
+ UInt32* actualCount)=0;
+
+ virtual void SetCloseOnDelete(Boolean inFlag) { mCloseOnDelete = inFlag; }
+
+ virtual Boolean CanSeek() const=0;
+ virtual Boolean CanGetSize() const=0;
+ virtual Boolean CanSetSize() const=0;
+ virtual Boolean CanRead() const=0;
+ virtual Boolean CanWrite() const=0;
+
+protected:
+ Boolean mCloseOnDelete;
+
+ /* utility method */
+ SInt64 CalcOffset( UInt16 positionMode,
+ SInt64 positionOffset,
+ SInt64 currentOffset,
+ SInt64 size);
+};
+
+//////////////////////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////////////////////
+
+/*
+ Initialize with a Macintosh file fork ref num as obtained from FSOpenFork.
+*/
+
+#if 0
+
+class MacFile_DataSource : public DataSource
+{
+ FSIORefNum mFileNum;
+ SInt8 mPermissions;
+
+public:
+
+ MacFile_DataSource( FSIORefNum inForkRefNum, SInt8 inPermissions, Boolean inCloseOnDelete);
+ virtual ~MacFile_DataSource();
+
+ virtual OSStatus GetSize(SInt64& outSize);
+ virtual OSStatus GetPos(SInt64& outPos) const;
+
+ virtual OSStatus SetSize(SInt64 inSize);
+
+ virtual OSStatus ReadBytes( UInt16 positionMode,
+ SInt64 positionOffset,
+ UInt32 requestCount,
+ void *buffer,
+ UInt32* actualCount);
+
+ virtual OSStatus WriteBytes(UInt16 positionMode,
+ SInt64 positionOffset,
+ UInt32 requestCount,
+ const void *buffer,
+ UInt32* actualCount);
+
+ virtual Boolean CanSeek() const { return true; }
+ virtual Boolean CanGetSize() const { return true; }
+ virtual Boolean CanSetSize() const { return true; }
+
+ virtual Boolean CanRead() const { return mPermissions & kAudioFileReadPermission; }
+ virtual Boolean CanWrite() const { return mPermissions & kAudioFileWritePermission; }
+};
+#endif
+
+
+class UnixFile_DataSource : public DataSource
+{
+ int mFileD;
+ SInt8 mPermissions;
+ UInt32 mNoCache;
+ SInt64 mCachedSize;
+ SInt64 mFilePointer;
+
+public:
+
+ UnixFile_DataSource( int inFD, SInt8 inPermissions, Boolean inCloseOnDelete);
+ virtual ~UnixFile_DataSource();
+
+ virtual OSStatus GetSize(SInt64& outSize);
+ virtual OSStatus GetPos(SInt64& outPos) const;
+
+ virtual OSStatus SetSize(SInt64 inSize);
+
+ virtual OSStatus ReadBytes( UInt16 positionMode,
+ SInt64 positionOffset,
+ UInt32 requestCount,
+ void *buffer,
+ UInt32* actualCount);
+
+ virtual OSStatus WriteBytes(UInt16 positionMode,
+ SInt64 positionOffset,
+ UInt32 requestCount,
+ const void *buffer,
+ UInt32* actualCount);
+
+ virtual Boolean CanSeek() const { return true; }
+ virtual Boolean CanGetSize() const { return true; }
+ virtual Boolean CanSetSize() const { return true; }
+
+ virtual Boolean CanRead() const { return mPermissions & kAudioFileReadPermission; }
+ virtual Boolean CanWrite() const { return mPermissions & kAudioFileWritePermission; }
+
+private:
+
+ SInt64 UFCurrentOffset (UInt16 positionMode,
+ SInt64 positionOffset);
+};
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+/*
+ A wrapper that caches the wrapped source's header.
+*/
+class Cached_DataSource : public DataSource
+{
+ DataSource* mDataSource;
+ CAAutoFree<UInt8> mHeaderCache;
+ UInt32 mHeaderCacheSize;
+ CAAutoFree<UInt8> mBodyCache;
+ UInt32 mBodyCacheSize;
+ UInt32 mBodyCacheCurSize;
+ SInt64 mBodyCacheOffset;
+ SInt64 mOffset;
+ Boolean mOwnDataSource;
+
+public:
+
+ Cached_DataSource(DataSource* inDataSource, UInt32 inHeaderCacheSize = 4096, UInt32 inBodyCacheSize = 32768, Boolean inOwnDataSource = true)
+ : DataSource(false),
+ mDataSource(inDataSource), mHeaderCacheSize(inHeaderCacheSize),
+ mBodyCacheSize(inBodyCacheSize), mBodyCacheCurSize(0), mBodyCacheOffset(-1),
+ mOffset(0),
+ mOwnDataSource(inOwnDataSource)
+ {
+ }
+
+ virtual ~Cached_DataSource()
+ {
+ if (mOwnDataSource) delete mDataSource;
+ }
+
+
+ virtual OSStatus GetSize(SInt64& outSize) { return mDataSource->GetSize(outSize); }
+ virtual OSStatus GetPos(SInt64& outPos) const { return mDataSource->GetPos(outPos); }
+
+ virtual OSStatus SetSize(SInt64 inSize) { return mDataSource->SetSize(inSize); }
+
+ virtual OSStatus ReadBytes( UInt16 positionMode,
+ SInt64 positionOffset,
+ UInt32 requestCount,
+ void *buffer,
+ UInt32* actualCount);
+
+ virtual OSStatus WriteBytes( UInt16 positionMode,
+ SInt64 positionOffset,
+ UInt32 requestCount,
+ const void *buffer,
+ UInt32* actualCount);
+
+ OSStatus ReadFromHeaderCache( SInt64 offset,
+ UInt32 requestCount,
+ void *buffer,
+ UInt32* actualCount);
+
+ virtual Boolean CanSeek() const { return mDataSource->CanSeek(); }
+ virtual Boolean CanGetSize() const { return mDataSource->CanGetSize(); }
+ virtual Boolean CanSetSize() const { return mDataSource->CanSetSize(); }
+
+ virtual Boolean CanRead() const { return mDataSource->CanRead(); }
+ virtual Boolean CanWrite() const { return mDataSource->CanWrite(); }
+};
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+
+/* This class calls user supplied routines on demand. */
+
+class Seekable_DataSource : public DataSource
+{
+ void * mClientData;
+ SInt64 mOffset;
+
+ AudioFile_ReadProc mReadFunc;
+ AudioFile_WriteProc mWriteFunc;
+ AudioFile_GetSizeProc mSizeFunc;
+ AudioFile_SetSizeProc mSetSizeFunc;
+
+public:
+ Seekable_DataSource( void * inClientData,
+ AudioFile_ReadProc inReadFunc,
+ AudioFile_WriteProc inWriteFunc,
+ AudioFile_GetSizeProc inGetSizeFunc,
+ AudioFile_SetSizeProc inSetSizeFunc
+ );
+
+ virtual ~Seekable_DataSource();
+
+ virtual OSStatus GetSize(SInt64& outSize);
+ virtual OSStatus GetPos(SInt64& outPos) const { outPos = mOffset; return noErr; };
+
+ virtual OSStatus SetSize(SInt64 inSize);
+
+ virtual OSStatus ReadBytes( UInt16 positionMode,
+ SInt64 positionOffset,
+ UInt32 requestCount,
+ void *buffer,
+ UInt32* actualCount);
+
+ virtual OSStatus WriteBytes(UInt16 positionMode,
+ SInt64 positionOffset,
+ UInt32 requestCount,
+ const void *buffer,
+ UInt32* actualCount);
+
+ virtual Boolean CanSeek() const { return true; }
+ virtual Boolean CanGetSize() const { return mSizeFunc != 0; }
+ virtual Boolean CanSetSize() const { return mSetSizeFunc != 0; }
+ virtual Boolean CanRead() const { return mReadFunc != 0; }
+ virtual Boolean CanWrite() const { return mWriteFunc != 0; }
+};
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+class Buffer_DataSource : public DataSource
+{
+ UInt32 mDataByteSize;
+ const char * mData;
+
+ SInt64 mStartOffset;
+ SInt64 mOffset;
+public:
+ Buffer_DataSource( UInt32 inDataByteSize,
+ const void * inData,
+ SInt64 inStartOffset = 0
+ ) : DataSource(false), mDataByteSize(inDataByteSize), mData((const char*)inData), mStartOffset(inStartOffset), mOffset(mStartOffset) {}
+
+ virtual ~Buffer_DataSource() {}
+
+ virtual OSStatus GetSize(SInt64& outSize) { outSize = mDataByteSize + mStartOffset; return noErr; }
+ virtual OSStatus GetPos(SInt64& outPos) const { outPos = mOffset; return noErr; };
+
+ virtual OSStatus SetSize(SInt64 inSize) { throw std::runtime_error("not writable"); }
+
+ virtual OSStatus ReadBytes( UInt16 positionMode,
+ SInt64 positionOffset,
+ UInt32 requestCount,
+ void *buffer,
+ UInt32* actualCount);
+
+ virtual OSStatus WriteBytes(UInt16 positionMode,
+ SInt64 positionOffset,
+ UInt32 requestCount,
+ const void *buffer,
+ UInt32* actualCount) { throw std::runtime_error("not writable"); }
+
+ virtual Boolean CanSeek() const { return true; }
+ virtual Boolean CanGetSize() const { return true; }
+ virtual Boolean CanSetSize() const { return false; }
+ virtual Boolean CanRead() const { return true; }
+ virtual Boolean CanWrite() const { return false; }
+};
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+#endif