diff --git a/CMakeLists.txt b/CMakeLists.txt index 02e500b9e..676dfb8bb 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -102,6 +102,8 @@ add_subdirectory(src/CoreGraphics) add_subdirectory(src/IOKit) add_subdirectory(src/Foundation) add_subdirectory(src/Carbon) +add_subdirectory(src/AudioUnit) +add_subdirectory(src/AudioToolbox) #add_subdirectory(src/libcrashhandler) add_subdirectory(src/thin) add_subdirectory(src/libstdc++darwin) diff --git a/etc/dylib.conf b/etc/dylib.conf index 6d70f3fde..4bb742d2d 100644 --- a/etc/dylib.conf +++ b/etc/dylib.conf @@ -16,6 +16,7 @@ /usr/lib/libncurses.5.4.dylib=libncurses.5.4.dylib.so /usr/lib/libltdl.7.dylib=libc.so.6 /usr/lib/libmx.A.dylib=libc.so.6 +/usr/lib/libpcap.A.dylib=libpcap.so.1 @rpath/libclang.dylib=libclang.so @rpath/libobjc.A.dylib=libobjc.A.dylib.so diff --git a/src/AudioToolbox/AudioConverter.cpp b/src/AudioToolbox/AudioConverter.cpp new file mode 100644 index 000000000..30592f52a --- /dev/null +++ b/src/AudioToolbox/AudioConverter.cpp @@ -0,0 +1,279 @@ +#include "AudioConverterInternal.h" +#include +#include "log.h" + +// http://blinkingblip.wordpress.com/ + +__attribute__((constructor)) static void init_avcodec() +{ + avcodec_register_all(); +} + +OSStatus AudioConverterNew(const AudioStreamBasicDescription* inSourceFormat, const AudioStreamBasicDescription* inDestinationFormat, AudioConverterRef* outAudioConverter) +{ + return AudioConverter::create(inSourceFormat, inDestinationFormat, outAudioConverter); +} + +OSStatus AudioConverterNewSpecific(const AudioStreamBasicDescription* inSourceFormat, const AudioStreamBasicDescription* inDestinationFormat, UInt32 inNumberClassDescriptions, AudioClassDescription* nClassDescriptions, AudioConverterRef* outAudioConverter) +{ + // FIXME + return AudioConverterNew(inSourceFormat, inDestinationFormat, outAudioConverter); +} + +OSStatus AudioConverterReset(AudioConverterRef inAudioConverter) +{ + if (inAudioConverter) + { + inAudioConverter->flush(); + return noErr; + } + else + return paramErr; +} + +OSStatus AudioConverterDispose(AudioConverterRef inAudioConverter) +{ + delete inAudioConverter; + return noErr; +} + +OSStatus AudioConverterGetProperty(AudioConverterRef inAudioConverter, AudioConverterPropertyID inPropertyID, UInt32 *ioPropertyDataSize, void *outPropertyData) +{ + LOG << "AudioConverterGetProperty(): FIXME\n"; + return unimpErr; +} + +OSStatus AudioConverterGetPropertyInfo(AudioConverterRef inAudioConverter, AudioConverterPropertyID inPropertyID, UInt32 *outSize, Boolean *outWritable) +{ + LOG << "AudioConverterGetPropertyInfo(): FIXME\n"; + return unimpErr; +} + +OSStatus AudioConverterSetProperty(AudioConverterRef inAudioConverter, AudioConverterPropertyID inPropertyID, UInt32 inPropertyDataSize, const void *inPropertyData) +{ + LOG << "AudioConverterSetProperty(): FIXME\n"; + return unimpErr; +} + +OSStatus AudioConverterConvertBuffer(AudioConverterRef inAudioConverter, UInt32 inInputDataSize, const void* inInputData, UInt32 *ioOutputDataSize, void *outOutputData) +{ + AudioBufferList in, out; + OSStatus stat; + + in.mNumberBuffers = out.mNumberBuffers = 1; + + in.mBuffers[0].mNumberChannels = 2; + out.mBuffers[0].mNumberChannels = 2; + + in.mBuffers[0].mDataByteSize = inInputDataSize; + in.mBuffers[0].mData = const_cast(inInputData); + + out.mBuffers[0].mDataByteSize = *ioOutputDataSize; + out.mBuffers[0].mData = outOutputData; + + stat = AudioConverterConvertComplexBuffer(inAudioConverter, inInputDataSize/inAudioConverter->frameSize(), &in, &out); + *ioOutputDataSize = out.mBuffers[0].mDataByteSize; + + return stat; +} + +OSStatus AudioConverterFillComplexBuffer(AudioConverterRef inAudioConverter, AudioConverterComplexInputDataProc inInputDataProc, void *inInputDataProcUserData, UInt32 *ioOutputDataPacketSize, AudioBufferList *outOutputData, AudioStreamPacketDescription*outPacketDescription) +{ + LOG << "AudioConverterFillComplexBuffer(): FIXME\n"; + return unimpErr; +} + +OSStatus AudioConverterConvertComplexBuffer(AudioConverterRef inAudioConverter, UInt32 inNumberPCMFrames, const AudioBufferList *inInputData, AudioBufferList *outOutputData) +{ + OSStatus status; + UInt32 dataPacketSize; + int64_t totalOutBytes = 0; + + AudioConverterComplexInputDataProc proc = [](AudioConverterRef audioConverter, UInt32* numberDataPackets, AudioBufferList* data, AudioStreamPacketDescription** dataPacketDescription, void* userData) -> OSStatus + { + const AudioBufferList *inInputData = (AudioBufferList*) inInputData; + + if (dataPacketDescription) + *dataPacketDescription = nullptr; + + return unimpErr; + }; + + for (UInt32 i = 0; i < outOutputData->mNumberBuffers; i++) + totalOutBytes += outOutputData->mBuffers[i].mDataByteSize; + + dataPacketSize = totalOutBytes / inAudioConverter->frameSize(); + + status = AudioConverterFillComplexBuffer(inAudioConverter, proc, (void*) inInputData, &dataPacketSize, outOutputData, nullptr); + return status; +} + +AudioConverter::AudioConverter(const AudioStreamBasicDescription* inSourceFormat, const AudioStreamBasicDescription* inDestinationFormat) + : m_sourceFormat(*inSourceFormat), m_destinationFormat(*inDestinationFormat), m_decoder(nullptr), m_encoder(nullptr), m_hadData(false) +{ +} + +void AudioConverter::flush() +{ + if (m_hadData) + { + avcodec_flush_buffers(m_decoder); + avcodec_flush_buffers(m_encoder); + avcodec_close(m_encoder); + m_hadData = false; + } +} + +OSStatus AudioConverter::create(const AudioStreamBasicDescription* inSourceFormat, const AudioStreamBasicDescription* inDestinationFormat, AudioConverter** out) +{ + AVCodec *codecIn, *codecOut; + enum AVCodecID idIn, idOut; + + *out = nullptr; + idIn = CACodecToAV(inSourceFormat); + idOut = CACodecToAV(inDestinationFormat); + + if (idIn == AV_CODEC_ID_NONE || idOut == AV_CODEC_ID_NONE) + { + LOG << "AudioConverter::create(): Unsupported codec, format in = " << std::hex << inSourceFormat->mFormatID << ", out = " << inDestinationFormat->mFormatID << std::dec << std::endl; + return paramErr; + } + + codecIn = avcodec_find_decoder(idIn); + codecOut = avcodec_find_encoder(idOut); + + if (!codecIn || !codecOut) + { + LOG << "AudioConverter::create(): avcodec_find_*() failed, format in = " << std::hex << inSourceFormat->mFormatID << ", out = " << inDestinationFormat->mFormatID << std::dec << std::endl; + return paramErr; + } + + *out = new AudioConverter(inSourceFormat, inDestinationFormat); + + (*out)->m_decoder = avcodec_alloc_context3(codecIn); + if (avcodec_open2((*out)->m_decoder, codecIn, nullptr) < 0) + { + delete *out; + LOG << "AudioConverter::create(): avcodec_open() failed, format in = " << std::hex << inSourceFormat->mFormatID << ", out = " << inDestinationFormat->mFormatID << std::dec << std::endl; + + return paramErr; + } + + // The encoder will be initialized after we process the first packet + (*out)->m_encoder = avcodec_alloc_context3(codecOut); + + return noErr; +} + +AudioConverter::~AudioConverter() +{ + if (m_decoder) + av_free(m_decoder); + if (m_encoder) + av_free(m_encoder); + //if (m_resampler) + // avresample_free(&m_resampler); +} + +enum AVCodecID AudioConverter::CACodecToAV(const AudioStreamBasicDescription* desc) +{ + switch (desc->mFormatID) + { + case kAudioFormatLinearPCM: + { + if (desc->mFormatFlags & kAudioFormatFlagIsFloat) + { + if (desc->mFormatFlags & kAudioFormatFlagIsBigEndian) + { + if (desc->mBitsPerChannel == 32) + return AV_CODEC_ID_PCM_F32BE; + else if (desc->mBitsPerChannel == 64) + return AV_CODEC_ID_PCM_F64BE; + } + else + { + if (desc->mBitsPerChannel == 32) + return AV_CODEC_ID_PCM_F32LE; + else if (desc->mBitsPerChannel == 64) + return AV_CODEC_ID_PCM_F64LE; + } + } + else if (desc->mFormatFlags & kAudioFormatFlagIsSignedInteger) + { + enum AVCodecID cid; + + switch (desc->mBitsPerChannel) + { + case 8: cid = AV_CODEC_ID_PCM_S8; break; + case 16: cid = AV_CODEC_ID_PCM_S16LE; break; + case 24: cid = AV_CODEC_ID_PCM_S24LE; break; + case 32: cid = AV_CODEC_ID_PCM_S32LE; break; + default: return AV_CODEC_ID_NONE; + } + + if (desc->mBitsPerChannel != 8 && desc->mFormatFlags & kAudioFormatFlagIsBigEndian) + cid++; + return cid; + } + else + { + enum AVCodecID cid; + + switch (desc->mBitsPerChannel) + { + case 8: cid = AV_CODEC_ID_PCM_U8; break; + case 16: cid = AV_CODEC_ID_PCM_U16LE; break; + case 24: cid = AV_CODEC_ID_PCM_U24LE; break; + case 32: cid = AV_CODEC_ID_PCM_U32LE; break; + default: return AV_CODEC_ID_NONE; + } + + if (desc->mBitsPerChannel != 8 && desc->mFormatFlags & kAudioFormatFlagIsBigEndian) + cid++; + return cid; + } + return AV_CODEC_ID_NONE; + } + case kAudioFormatULaw: + return AV_CODEC_ID_PCM_MULAW; + case kAudioFormatALaw: + return AV_CODEC_ID_PCM_ALAW; + case kAudioFormatMPEGLayer1: + return AV_CODEC_ID_MP1; + case kAudioFormatMPEGLayer2: + return AV_CODEC_ID_MP2; + case kAudioFormatMPEGLayer3: + return AV_CODEC_ID_MP3; + case kAudioFormatAC3: + case kAudioFormat60958AC3: // TODO: is this correct? + return AV_CODEC_ID_AC3; + case kAudioFormatAppleIMA4: + return AV_CODEC_ID_ADPCM_IMA_DK4; // TODO: is this correct? + case kAudioFormatMPEG4AAC: + case kAudioFormatMPEG4AAC_HE: + case kAudioFormatMPEG4AAC_LD: + case kAudioFormatMPEG4AAC_ELD: + case kAudioFormatMPEG4AAC_ELD_SBR: + case kAudioFormatMPEG4AAC_ELD_V2: + case kAudioFormatMPEG4AAC_HE_V2: + case kAudioFormatMPEG4AAC_Spatial: + return AV_CODEC_ID_AAC; + case kAudioFormatMPEG4CELP: + return AV_CODEC_ID_QCELP; // TODO: is this correct? + case kAudioFormatAMR: + return AV_CODEC_ID_AMR_NB; + case kAudioFormatiLBC: + return AV_CODEC_ID_ILBC; + case kAudioFormatAppleLossless: + return AV_CODEC_ID_APE; + case kAudioFormatMicrosoftGSM: + return AV_CODEC_ID_GSM_MS; + case kAudioFormatMACE3: + return AV_CODEC_ID_MACE3; + case kAudioFormatMACE6: + return AV_CODEC_ID_MACE6; + default: + return AV_CODEC_ID_NONE; + } +} + diff --git a/src/AudioToolbox/AudioConverter.h b/src/AudioToolbox/AudioConverter.h new file mode 100644 index 000000000..4fe4ef888 --- /dev/null +++ b/src/AudioToolbox/AudioConverter.h @@ -0,0 +1,33 @@ +#ifndef AUDIOCONVERTER_H +#define AUDIOCONVERTER_H +#include +#include "CoreAudioTypes.h" + +extern "C" { + + + +class AudioConverter; + +typedef UInt32 AudioConverterPropertyID; +typedef AudioConverter* AudioConverterRef; +typedef OSStatus (*AudioConverterComplexInputDataProc)(AudioConverterRef audioConverter, UInt32* numberDataPackets, AudioBufferList* data, AudioStreamPacketDescription** dataPacketDescription, void* userData); + +OSStatus AudioConverterNew(const AudioStreamBasicDescription* inSourceFormat, const AudioStreamBasicDescription* inDestinationFormat, AudioConverterRef* outAudioConverter); +OSStatus AudioConverterNewSpecific(const AudioStreamBasicDescription* inSourceFormat, const AudioStreamBasicDescription* inDestinationFormat, UInt32 inNumberClassDescriptions, AudioClassDescription* nClassDescriptions, AudioConverterRef* outAudioConverter); +OSStatus AudioConverterDispose(AudioConverterRef inAudioConverter); +OSStatus AudioConverterReset(AudioConverterRef inAudioConverter); + +OSStatus AudioConverterGetProperty(AudioConverterRef inAudioConverter, AudioConverterPropertyID inPropertyID, UInt32 *ioPropertyDataSize, void *outPropertyData); +OSStatus AudioConverterGetPropertyInfo(AudioConverterRef inAudioConverter, AudioConverterPropertyID inPropertyID, UInt32 *outSize, Boolean *outWritable); +OSStatus AudioConverterSetProperty(AudioConverterRef inAudioConverter, AudioConverterPropertyID inPropertyID, UInt32 inPropertyDataSize, const void *inPropertyData); + +OSStatus AudioConverterConvertBuffer(AudioConverterRef inAudioConverter, UInt32 inInputDataSize, const void* inInputData, UInt32 *ioOutputDataSize, void *outOutputData); +OSStatus AudioConverterFillComplexBuffer(AudioConverterRef inAudioConverter, AudioConverterComplexInputDataProc inInputDataProc, void *inInputDataProcUserData, UInt32 *ioOutputDataPacketSize, AudioBufferList *outOutputData, AudioStreamPacketDescription*outPacketDescription); +OSStatus AudioConverterConvertComplexBuffer(AudioConverterRef inAudioConverter, UInt32 inNumberPCMFrames, const AudioBufferList *inInputData, AudioBufferList *outOutputData); + +} + + +#endif + diff --git a/src/AudioToolbox/AudioConverterInternal.h b/src/AudioToolbox/AudioConverterInternal.h new file mode 100644 index 000000000..e93db7e46 --- /dev/null +++ b/src/AudioToolbox/AudioConverterInternal.h @@ -0,0 +1,28 @@ +#ifndef AUDIOCONVERTERINTERNAL_H +#define AUDIOCONVERTERINTERNAL_H +#include "AudioConverter.h" +//#include +#include + +class AudioConverter +{ + AudioConverter(const AudioStreamBasicDescription* inSourceFormat, const AudioStreamBasicDescription* inDestinationFormat); +public: + static OSStatus create(const AudioStreamBasicDescription* inSourceFormat, const AudioStreamBasicDescription* inDestinationFormat, AudioConverter** out); + ~AudioConverter(); + + void flush(); + UInt32 frameSize() const { return m_sourceFormat.mBytesPerFrame; } +private: + static enum AVCodecID CACodecToAV(const AudioStreamBasicDescription* desc); +private: + AudioStreamBasicDescription m_sourceFormat, m_destinationFormat; + AVCodecContext* m_decoder; + AVCodecContext* m_encoder; + //AVAudioResampleContext* m_resampler; + bool m_hadData; +}; + +#endif + + diff --git a/src/AudioToolbox/CMakeLists.txt b/src/AudioToolbox/CMakeLists.txt new file mode 100644 index 000000000..80804d364 --- /dev/null +++ b/src/AudioToolbox/CMakeLists.txt @@ -0,0 +1,28 @@ +project(AudioToolbox) + +cmake_minimum_required(VERSION 2.4.0) +if(COMMAND cmake_policy) + cmake_policy(SET CMP0003 NEW) +endif(COMMAND cmake_policy) + +#configure_file(config.h.in config.h) +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") + +include_directories(${CMAKE_CURRENT_SOURCE_DIR}) +include_directories(${CMAKE_CURRENT_SOURCE_DIR}/..) +include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../util) + +set(AudioToolbox_SRCS + AudioConverter.cpp +) + +SET(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/lib${SUFFIX}/darling") +#SET(CMAKE_EXE_LINKER_FLAGS "-Wl,--enable-new-dtags") +SET(CMAKE_BUILD_WITH_INSTALL_RPATH TRUE) +SET(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE) + +add_library(AudioToolbox SHARED ${AudioToolbox_SRCS}) +target_link_libraries(AudioToolbox util -lavcodec -lavresample) + +install(TARGETS AudioToolbox DESTINATION "lib${SUFFIX}/darling") + diff --git a/src/AudioToolbox/CoreAudioTypes.h b/src/AudioToolbox/CoreAudioTypes.h new file mode 100644 index 000000000..7c5712c0f --- /dev/null +++ b/src/AudioToolbox/CoreAudioTypes.h @@ -0,0 +1,152 @@ +#ifndef COREAUDIOTYPES_H +#define COREAUDIOTYPES_H +#include + +struct AudioStreamBasicDescription +{ + Float64 mSampleRate; + UInt32 mFormatID; + UInt32 mFormatFlags; + UInt32 mBytesPerPacket; + UInt32 mFramesPerPacket; + UInt32 mBytesPerFrame; + UInt32 mChannelsPerFrame; + UInt32 mBitsPerChannel; + UInt32 mReserved; +}; + +struct AudioClassDescription +{ + OSType mType; + OSType mSubType; + OSType mManufacturer; +}; + +struct AudioBuffer +{ + UInt32 mNumberChannels; + UInt32 mDataByteSize; + void* mData; +}; + +struct AudioBufferList +{ + UInt32 mNumberBuffers; + AudioBuffer mBuffers[1]; +}; + +struct AudioStreamPacketDescription +{ + SInt64 mStartOffset; + UInt32 mVariableFramesInPacket; // 0 for constant streams + UInt32 mDataByteSize; +}; + +enum +{ + kAudioFormatLinearPCM = 'lpcm', + kAudioFormatAC3 = 'ac-3', + kAudioFormat60958AC3 = 'cac3', + kAudioFormatAppleIMA4 = 'ima4', + kAudioFormatMPEG4AAC = 'aac ', + kAudioFormatMPEG4CELP = 'celp', + kAudioFormatMPEG4HVXC = 'hvxc', + kAudioFormatMPEG4TwinVQ = 'twvq', + kAudioFormatMACE3 = 'MAC3', + kAudioFormatMACE6 = 'MAC6', + kAudioFormatULaw = 'ulaw', + kAudioFormatALaw = 'alaw', + kAudioFormatQDesign = 'QDMC', + kAudioFormatQDesign2 = 'QDM2', + kAudioFormatQUALCOMM = 'Qclp', + kAudioFormatMPEGLayer1 = '.mp1', + kAudioFormatMPEGLayer2 = '.mp2', + kAudioFormatMPEGLayer3 = '.mp3', + kAudioFormatTimeCode = 'time', + kAudioFormatMIDIStream = 'midi', + kAudioFormatParameterValueStream = 'apvs', + kAudioFormatAppleLossless = 'alac', + kAudioFormatMPEG4AAC_HE = 'aach', + kAudioFormatMPEG4AAC_LD = 'aacl', + kAudioFormatMPEG4AAC_ELD = 'aace', + kAudioFormatMPEG4AAC_ELD_SBR = 'aacf', + kAudioFormatMPEG4AAC_ELD_V2 = 'aacg', + kAudioFormatMPEG4AAC_HE_V2 = 'aacp', + kAudioFormatMPEG4AAC_Spatial = 'aacs', + kAudioFormatAMR = 'samr', + kAudioFormatAudible = 'AUDB', + kAudioFormatiLBC = 'ilbc', + kAudioFormatDVIIntelIMA = 0x6D730011, + kAudioFormatMicrosoftGSM = 0x6D730031, + kAudioFormatAES3 = 'aes3' +}; + +enum +{ + kAudioFormatFlagIsFloat = (1 << 0), // 0x1 + kAudioFormatFlagIsBigEndian = (1 << 1), // 0x2 + kAudioFormatFlagIsSignedInteger = (1 << 2), // 0x4 + kAudioFormatFlagIsPacked = (1 << 3), // 0x8 + kAudioFormatFlagIsAlignedHigh = (1 << 4), // 0x10 + kAudioFormatFlagIsNonInterleaved = (1 << 5), // 0x20 + kAudioFormatFlagIsNonMixable = (1 << 6), // 0x40 + kAudioFormatFlagsAreAllClear = (1 << 31), + + kLinearPCMFormatFlagIsFloat = kAudioFormatFlagIsFloat, + kLinearPCMFormatFlagIsBigEndian = kAudioFormatFlagIsBigEndian, + kLinearPCMFormatFlagIsSignedInteger = kAudioFormatFlagIsSignedInteger, + kLinearPCMFormatFlagIsPacked = kAudioFormatFlagIsPacked, + kLinearPCMFormatFlagIsAlignedHigh = kAudioFormatFlagIsAlignedHigh, + kLinearPCMFormatFlagIsNonInterleaved = kAudioFormatFlagIsNonInterleaved, + kLinearPCMFormatFlagIsNonMixable = kAudioFormatFlagIsNonMixable, + kLinearPCMFormatFlagsSampleFractionShift = 7, + kLinearPCMFormatFlagsSampleFractionMask = (0x3F << kLinearPCMFormatFlagsSampleFractionShift), + kLinearPCMFormatFlagsAreAllClear = kAudioFormatFlagsAreAllClear, + + kAppleLosslessFormatFlag_16BitSourceData = 1, + kAppleLosslessFormatFlag_20BitSourceData = 2, + kAppleLosslessFormatFlag_24BitSourceData = 3, + kAppleLosslessFormatFlag_32BitSourceData = 4 +}; + +enum // typedef UInt32 AudioConverterPropertyID +{ + kAudioConverterPropertyMinimumInputBufferSize = 'mibs', + kAudioConverterPropertyMinimumOutputBufferSize = 'mobs', + kAudioConverterPropertyMaximumInputBufferSize = 'xibs', + kAudioConverterPropertyMaximumInputPacketSize = 'xips', + kAudioConverterPropertyMaximumOutputPacketSize = 'xops', + kAudioConverterPropertyCalculateInputBufferSize = 'cibs', + kAudioConverterPropertyCalculateOutputBufferSize = 'cobs', + kAudioConverterPropertyInputCodecParameters = 'icdp', + kAudioConverterPropertyOutputCodecParameters = 'ocdp', + kAudioConverterSampleRateConverterAlgorithm = 'srci', + kAudioConverterSampleRateConverterComplexity = 'srca', + kAudioConverterSampleRateConverterQuality = 'srcq', + kAudioConverterSampleRateConverterInitialPhase = 'srcp', + kAudioConverterCodecQuality = 'cdqu', + kAudioConverterPrimeMethod = 'prmm', + kAudioConverterPrimeInfo = 'prim', + kAudioConverterChannelMap = 'chmp', + kAudioConverterDecompressionMagicCookie = 'dmgc', + kAudioConverterCompressionMagicCookie = 'cmgc', + kAudioConverterEncodeBitRate = 'brat', + kAudioConverterEncodeAdjustableSampleRate = 'ajsr', + kAudioConverterInputChannelLayout = 'icl ', + kAudioConverterOutputChannelLayout = 'ocl ', + kAudioConverterApplicableEncodeBitRates = 'aebr', + kAudioConverterAvailableEncodeBitRates = 'vebr', + kAudioConverterApplicableEncodeSampleRates = 'aesr', + kAudioConverterAvailableEncodeSampleRates = 'vesr', + kAudioConverterAvailableEncodeChannelLayoutTags = 'aecl', + kAudioConverterCurrentOutputStreamDescription = 'acod', + kAudioConverterCurrentInputStreamDescription = 'acid', + kAudioConverterPropertySettings = 'acps', + kAudioConverterPropertyBitDepthHint = 'acbd', + kAudioConverterPropertyFormatList = 'flst', + kAudioConverterPropertyDithering = 'dith', + kAudioConverterPropertyDitherBitDepth = 'dbit' +}; + +#endif + diff --git a/src/AudioUnit/AUComponent.cpp b/src/AudioUnit/AUComponent.cpp new file mode 100644 index 000000000..943e5b0b2 --- /dev/null +++ b/src/AudioUnit/AUComponent.cpp @@ -0,0 +1,123 @@ +#include "AUComponent.h" +#include "AUComponentInternal.h" +#include "log.h" +#include +#include + +AudioComponent AudioComponentFindNext(AudioComponent inAComponent, AudioComponentDescription *inDesc) +{ + int index = -1; + + if (inDesc->componentType != kAudioUnitType_Output && inDesc->componentType != kAudioUnitType_Mixer) + return nullptr; + + if (inAComponent != nullptr) + index = GetComponentIndex(inAComponent); + + if (snd_card_next(&index) || index == -1) + return nullptr; + + return CreateComponent(kComponentTypeAudioUnit, index); +} + +OSStatus AudioComponentGetDescription(AudioComponent inComponent, AudioComponentDescription *outDesc) +{ + if (!outDesc) + return paramErr; + + memset(outDesc, 0, sizeof(*outDesc)); + outDesc->componentType = kAudioUnitType_Output; + + return noErr; +} + +OSStatus AudioComponentGetVersion(AudioComponent inComponent, UInt32 *outVersion) +{ + *outVersion = 0; + return noErr; +} + +Boolean AudioComponentInstanceCanDo(AudioComponentInstance inInstance, SInt16 inSelectorID) +{ + return true; +} + +OSStatus AudioComponentInstanceDispose(AudioComponentInstance inInstance) +{ + delete inInstance; + return noErr; +} + +AudioComponent AudioComponentInstanceGetComponent(AudioComponentInstance inInstance) +{ + return CreateComponent(kComponentTypeAudioUnit, inInstance->cardIndex()); +} + +OSStatus AudioComponentInstanceNew(AudioComponent inComponent, AudioComponentInstance *outInstance) +{ + *outInstance = AudioUnitComponent::create(GetComponentIndex(inComponent)); + return *outInstance ? noErr : paramErr; +} + +OSStatus AudioComponentCopyName(AudioComponent inComponent, CFStringRef *outName) +{ + int index = GetComponentIndex(inComponent); + char* name; + + if (!outName) + return paramErr; + + if (snd_card_get_longname(index, &name)) + return paramErr; + + *outName = CFStringCreateWithCString(nullptr, name, kCFStringEncodingUTF8); + free(name); + + return noErr; +} + +UInt32 AudioComponentCount(AudioComponentDescription *inDesc) +{ + UInt32 count = 0; + int index = -1; + + // Is there a better way? + do + { + snd_card_next(&index); + if (index != -1) + count++; + } + while (index != -1); + + return count; +} + +////////////////// + +AudioUnitComponent::AudioUnitComponent(int cardIndex, char* cardName) +: m_cardIndex(cardIndex), m_cardName(cardName) +{ +} + +AudioUnitComponent* AudioUnitComponent::create(int cardIndex) +{ + char* name; + + if (cardIndex > 0) + { + if (snd_card_get_name(cardIndex, &name)) + return nullptr; + } + else + { + name = strdup("default"); + } + + return new AudioUnitComponent(cardIndex, name); +} + +AudioUnitComponent::~AudioUnitComponent() +{ + free(m_cardName); +} diff --git a/src/AudioUnit/AUComponent.h b/src/AudioUnit/AUComponent.h new file mode 100644 index 000000000..f8bb69c5f --- /dev/null +++ b/src/AudioUnit/AUComponent.h @@ -0,0 +1,40 @@ +#ifndef AUCOMPONENT_H +#define AUCOMPONENT_H +#include +#include +#include + +class AudioUnitComponent; +typedef Component AudioComponent; +typedef AudioUnitComponent* AudioComponentInstance; +typedef ComponentDescription AudioComponentDescription; + +enum +{ + kAudioUnitType_Output = 'auou', + kAudioUnitType_MusicDevice = 'aumu', + kAudioUnitType_MusicEffect = 'aumf', + kAudioUnitType_FormatConverter = 'aufc', + kAudioUnitType_Effect = 'aufx', + kAudioUnitType_Mixer = 'aumx', + kAudioUnitType_Panner = 'aupn', + kAudioUnitType_Generator = 'augn', + kAudioUnitType_OfflineEffect = 'auol' +}; + +extern "C" { + +AudioComponent AudioComponentFindNext(AudioComponent inAComponent, AudioComponentDescription *inDesc); +OSStatus AudioComponentGetDescription(AudioComponent inComponent, AudioComponentDescription *outDesc); +OSStatus AudioComponentGetVersion(AudioComponent inComponent, UInt32 *outVersion); +Boolean AudioComponentInstanceCanDo(AudioComponentInstance inInstance, SInt16 inSelectorID); +OSStatus AudioComponentInstanceDispose(AudioComponentInstance inInstance); +AudioComponent AudioComponentInstanceGetComponent(AudioComponentInstance inInstance); +OSStatus AudioComponentInstanceNew(AudioComponent inComponent, AudioComponentInstance *outInstance); +OSStatus AudioComponentCopyName(AudioComponent inComponent, CFStringRef *outName); +UInt32 AudioComponentCount(AudioComponentDescription *inDesc); + +} + +#endif + diff --git a/src/AudioUnit/AUComponentInternal.h b/src/AudioUnit/AUComponentInternal.h new file mode 100644 index 000000000..0f96d091f --- /dev/null +++ b/src/AudioUnit/AUComponentInternal.h @@ -0,0 +1,21 @@ +#ifndef AUCOMPONENTINTERNAL_H +#define AUCOMPONENTINTERNAL_H +#include "AUComponent.h" +#include + +class AudioUnitComponent : public CarbonComponent +{ +private: + AudioUnitComponent(int cardIndex, char* cardName); +public: + static AudioUnitComponent* create(int cardIndex); + virtual ~AudioUnitComponent(); + + inline int cardIndex() const { return m_cardIndex; } +private: + int m_cardIndex; + char* m_cardName; +}; + +#endif + diff --git a/src/AudioUnit/AudioUnit.cpp b/src/AudioUnit/AudioUnit.cpp new file mode 100644 index 000000000..ae011ea23 --- /dev/null +++ b/src/AudioUnit/AudioUnit.cpp @@ -0,0 +1,4 @@ +#include "AudioUnit.h" + + + diff --git a/src/AudioUnit/AudioUnit.h b/src/AudioUnit/AudioUnit.h new file mode 100644 index 000000000..0139f3aeb --- /dev/null +++ b/src/AudioUnit/AudioUnit.h @@ -0,0 +1,6 @@ +#ifndef AUDIOUNIT_H +#define AUDIOUNIT_H + + +#endif + diff --git a/src/AudioUnit/CMakeLists.txt b/src/AudioUnit/CMakeLists.txt new file mode 100644 index 000000000..610bdccc7 --- /dev/null +++ b/src/AudioUnit/CMakeLists.txt @@ -0,0 +1,29 @@ +project(AudioUnit) + +cmake_minimum_required(VERSION 2.4.0) +if(COMMAND cmake_policy) + cmake_policy(SET CMP0003 NEW) +endif(COMMAND cmake_policy) + +#configure_file(config.h.in config.h) +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") + +include_directories(${CMAKE_CURRENT_SOURCE_DIR}) +include_directories(${CMAKE_CURRENT_SOURCE_DIR}/..) +include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../util) + +set(AudioUnit_SRCS + AUComponent.cpp + AudioUnit.cpp +) + +SET(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/lib${SUFFIX}/darling") +#SET(CMAKE_EXE_LINKER_FLAGS "-Wl,--enable-new-dtags") +SET(CMAKE_BUILD_WITH_INSTALL_RPATH TRUE) +SET(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE) + +add_library(AudioUnit SHARED ${AudioUnit_SRCS}) +target_link_libraries(AudioUnit util -lasound) + +install(TARGETS AudioUnit DESTINATION "lib${SUFFIX}/darling") + diff --git a/src/CoreServices/CMakeLists.txt b/src/CoreServices/CMakeLists.txt index 3eba24ea5..bff6a3713 100644 --- a/src/CoreServices/CMakeLists.txt +++ b/src/CoreServices/CMakeLists.txt @@ -32,6 +32,7 @@ set(CoreServices_SRCS Math64.cpp DriverSynchronization.cpp DriverServices.cpp + Components.cpp ) SET(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/lib${SUFFIX}/darling") @@ -40,7 +41,7 @@ SET(CMAKE_BUILD_WITH_INSTALL_RPATH TRUE) SET(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE) add_library(CoreServices SHARED ${CoreServices_SRCS}) -target_link_libraries(CoreServices -licuuc System.B.dylib util +target_link_libraries(CoreServices -licuuc System.B.dylib util AudioUnit -lgnustep-corebase) install(TARGETS CoreServices DESTINATION "lib${SUFFIX}/darling") diff --git a/src/CoreServices/Components.cpp b/src/CoreServices/Components.cpp new file mode 100644 index 000000000..b6dc0849b --- /dev/null +++ b/src/CoreServices/Components.cpp @@ -0,0 +1,60 @@ +#include "Components.h" +#include "ComponentsInternal.h" +#include +#include +#include + +Component FindNextComponent(Component prev, ComponentDescription* desc) +{ + if ((desc->componentType & 0xffff0000) == kComponentTypeAudioUnit) + { + return AudioComponentFindNext((AudioComponent) prev, (AudioComponentDescription*) desc); + } + else + return nullptr; +} + +long CountComponents(ComponentDescription* desc) +{ + if ((desc->componentType & 0xffff0000) == kComponentTypeAudioUnit) + { + return AudioComponentCount((AudioComponentDescription*) desc); + } + else + return 0; +} + +OSErr OpenAComponent(Component comp, ComponentInstance* out) +{ + if (!out) + return paramErr; + + *out = nullptr; + + if (GetComponentType(comp) == kComponentTypeAudioUnit) + { + AudioComponentInstance inst; + OSErr err; + + err = AudioComponentInstanceNew((AudioComponent) comp, &inst); + + *out = inst; + return err; + } + else + return unimpErr; +} + +ComponentInstance OpenComponent(Component comp) +{ + ComponentInstance inst; + OpenAComponent(comp, &inst); + return inst; +} + +OSErr CloseComponent(ComponentInstance inst) +{ + delete inst; + return noErr; +} + diff --git a/src/CoreServices/Components.h b/src/CoreServices/Components.h new file mode 100644 index 000000000..11b62defc --- /dev/null +++ b/src/CoreServices/Components.h @@ -0,0 +1,34 @@ +#ifndef COMPONENTS_H +#define COMPONENTS_H +#include + +class CarbonComponent; +struct ComponentDescription; + +typedef CarbonComponent* ComponentInstance; +typedef void* Component; + +extern "C" { + +Component FindNextComponent(Component prev, ComponentDescription* desc); +long CountComponents(ComponentDescription* desc); + +OSErr OpenAComponent(Component comp, ComponentInstance* out); +ComponentInstance OpenComponent(Component comp); +OSErr CloseComponent(ComponentInstance inst); + +} + +struct ComponentDescription +{ + OSType componentType, componentSubType, componentManufacturer; + UInt32 componentFlags, componentFlagsMask; +}; + +enum +{ + kAppleManufacturer = 'appl' +}; + +#endif + diff --git a/src/CoreServices/ComponentsInternal.h b/src/CoreServices/ComponentsInternal.h new file mode 100644 index 000000000..64a7a19db --- /dev/null +++ b/src/CoreServices/ComponentsInternal.h @@ -0,0 +1,35 @@ +#ifndef COMPONENTSINTERNAL_H +#define COMPONENTSINTERNAL_H + +class CarbonComponent +{ +public: + virtual ~CarbonComponent() {} +}; + +inline static UInt32 GetComponentType(Component comp) +{ + long l = long(comp); + return l & 0xffff0000; +} + +inline static UInt32 GetComponentIndex(Component comp) +{ + long l = long(comp); + return l & 0xffff; +} + +inline static Component CreateComponent(UInt32 type, UInt32 index) +{ + long l = type & 0xffff0000; + l |= (index & 0xffff); + return (void*) l; +} + +enum +{ + kComponentTypeAudioUnit = 'au\0\0' +}; + +#endif + diff --git a/src/CoreServices/FileManager.cpp b/src/CoreServices/FileManager.cpp index 37e79ce82..30516412e 100644 --- a/src/CoreServices/FileManager.cpp +++ b/src/CoreServices/FileManager.cpp @@ -395,6 +395,7 @@ static std::string extractXDGValue(const char* home, const std::string& line) return std::string(); } +// TODO: Test this function! OSStatus FSFindFolder(long vRefNum, OSType folderType, Boolean createFolder, FSRef* location) { if (folderType == kTemporaryFolderType) diff --git a/src/CoreServices/MacTypes.h b/src/CoreServices/MacTypes.h index 80fbd0ae6..c97bce00b 100644 --- a/src/CoreServices/MacTypes.h +++ b/src/CoreServices/MacTypes.h @@ -1,8 +1,10 @@ #ifndef MACTYPES_H #define MACTYPES_H #include +#include class _StringHandle; +#if 0 // declared in CFBase.h typedef int8_t SInt8; typedef uint8_t UInt8; typedef int16_t SInt16; @@ -11,6 +13,9 @@ typedef int32_t SInt32; typedef uint32_t UInt32; typedef int64_t SInt64; typedef uint64_t UInt64; +typedef float Float32; +typedef double Float64; +#endif typedef uint32_t OptionBits; @@ -42,6 +47,7 @@ typedef char* Ptr; typedef char** Handle; typedef int32_t OSStatus; +typedef uint32_t OSType; #endif