diff --git a/etc/dylib.conf b/etc/dylib.conf index 4bb742d2d..a0381bce1 100644 --- a/etc/dylib.conf +++ b/etc/dylib.conf @@ -21,6 +21,11 @@ @rpath/libclang.dylib=libclang.so @rpath/libobjc.A.dylib=libobjc.A.dylib.so +[AudioToolbox.framework] +A=libAudioToolbox.so + +[AudioUnit.framework] +A=libAudioUnit.so [CoreFoundation.framework] A=libCoreFoundation.so diff --git a/src/AudioToolbox/AudioConverter.cpp b/src/AudioToolbox/AudioConverter.cpp index 30592f52a..49f8460e8 100644 --- a/src/AudioToolbox/AudioConverter.cpp +++ b/src/AudioToolbox/AudioConverter.cpp @@ -1,6 +1,6 @@ #include "AudioConverterInternal.h" #include -#include "log.h" +#include // http://blinkingblip.wordpress.com/ @@ -39,19 +39,19 @@ OSStatus AudioConverterDispose(AudioConverterRef inAudioConverter) OSStatus AudioConverterGetProperty(AudioConverterRef inAudioConverter, AudioConverterPropertyID inPropertyID, UInt32 *ioPropertyDataSize, void *outPropertyData) { - LOG << "AudioConverterGetProperty(): FIXME\n"; + STUB(); return unimpErr; } OSStatus AudioConverterGetPropertyInfo(AudioConverterRef inAudioConverter, AudioConverterPropertyID inPropertyID, UInt32 *outSize, Boolean *outWritable) { - LOG << "AudioConverterGetPropertyInfo(): FIXME\n"; + STUB(); return unimpErr; } OSStatus AudioConverterSetProperty(AudioConverterRef inAudioConverter, AudioConverterPropertyID inPropertyID, UInt32 inPropertyDataSize, const void *inPropertyData) { - LOG << "AudioConverterSetProperty(): FIXME\n"; + STUB(); return unimpErr; } @@ -79,7 +79,7 @@ OSStatus AudioConverterConvertBuffer(AudioConverterRef inAudioConverter, UInt32 OSStatus AudioConverterFillComplexBuffer(AudioConverterRef inAudioConverter, AudioConverterComplexInputDataProc inInputDataProc, void *inInputDataProcUserData, UInt32 *ioOutputDataPacketSize, AudioBufferList *outOutputData, AudioStreamPacketDescription*outPacketDescription) { - LOG << "AudioConverterFillComplexBuffer(): FIXME\n"; + STUB(); return unimpErr; } @@ -95,6 +95,8 @@ OSStatus AudioConverterConvertComplexBuffer(AudioConverterRef inAudioConverter, if (dataPacketDescription) *dataPacketDescription = nullptr; + + // TODO return unimpErr; }; @@ -126,7 +128,12 @@ void AudioConverter::flush() OSStatus AudioConverter::create(const AudioStreamBasicDescription* inSourceFormat, const AudioStreamBasicDescription* inDestinationFormat, AudioConverter** out) { + TRACE2(inSourceFormat, inDestinationFormat); + + // TODO: create a special case for when *inSourceFormat == *inDestinationFormat? + AVCodec *codecIn, *codecOut; + AVCodecContext *cIn; enum AVCodecID idIn, idOut; *out = nullptr; @@ -150,7 +157,16 @@ OSStatus AudioConverter::create(const AudioStreamBasicDescription* inSourceForma *out = new AudioConverter(inSourceFormat, inDestinationFormat); - (*out)->m_decoder = avcodec_alloc_context3(codecIn); + (*out)->m_decoder = cIn = avcodec_alloc_context3(codecIn); + + if (inSourceFormat->mFormatID == kAudioFormatLinearPCM) + { + cIn->channels = inSourceFormat->mChannelsPerFrame; + cIn->sample_rate = inSourceFormat->mSampleRate; + + LOG << "Converting from PCM with " << cIn->channels << " channels at " << cIn->sample_rate << " Hz\n"; + } + if (avcodec_open2((*out)->m_decoder, codecIn, nullptr) < 0) { delete *out; diff --git a/src/AudioToolbox/AudioConverter.h b/src/AudioToolbox/AudioConverter.h index 4fe4ef888..6685df60a 100644 --- a/src/AudioToolbox/AudioConverter.h +++ b/src/AudioToolbox/AudioConverter.h @@ -1,7 +1,7 @@ #ifndef AUDIOCONVERTER_H #define AUDIOCONVERTER_H #include -#include "CoreAudioTypes.h" +#include extern "C" { diff --git a/src/AudioToolbox/AudioConverterInternal.h b/src/AudioToolbox/AudioConverterInternal.h index e93db7e46..85e65af81 100644 --- a/src/AudioToolbox/AudioConverterInternal.h +++ b/src/AudioToolbox/AudioConverterInternal.h @@ -1,8 +1,11 @@ #ifndef AUDIOCONVERTERINTERNAL_H #define AUDIOCONVERTERINTERNAL_H #include "AudioConverter.h" + +extern "C" { //#include #include +} class AudioConverter { diff --git a/src/AudioToolbox/CMakeLists.txt b/src/AudioToolbox/CMakeLists.txt index 80804d364..07537fe62 100644 --- a/src/AudioToolbox/CMakeLists.txt +++ b/src/AudioToolbox/CMakeLists.txt @@ -22,7 +22,7 @@ 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) +target_link_libraries(AudioToolbox util -lavcodec -lavresample CoreFoundation) install(TARGETS AudioToolbox DESTINATION "lib${SUFFIX}/darling") diff --git a/src/AudioUnit/AUComponent.cpp b/src/AudioUnit/AUComponent.cpp index 943e5b0b2..f53a220ef 100644 --- a/src/AudioUnit/AUComponent.cpp +++ b/src/AudioUnit/AUComponent.cpp @@ -1,11 +1,13 @@ #include "AUComponent.h" -#include "AUComponentInternal.h" -#include "log.h" +#include "AudioUnitALSA.h" +#include #include #include AudioComponent AudioComponentFindNext(AudioComponent inAComponent, AudioComponentDescription *inDesc) { + TRACE2(inAComponent, inDesc); + int index = -1; if (inDesc->componentType != kAudioUnitType_Output && inDesc->componentType != kAudioUnitType_Mixer) @@ -44,6 +46,8 @@ Boolean AudioComponentInstanceCanDo(AudioComponentInstance inInstance, SInt16 in OSStatus AudioComponentInstanceDispose(AudioComponentInstance inInstance) { + TRACE1(inInstance); + delete inInstance; return noErr; } @@ -55,7 +59,9 @@ AudioComponent AudioComponentInstanceGetComponent(AudioComponentInstance inInsta OSStatus AudioComponentInstanceNew(AudioComponent inComponent, AudioComponentInstance *outInstance) { - *outInstance = AudioUnitComponent::create(GetComponentIndex(inComponent)); + TRACE1(inComponent); + + *outInstance = AudioUnitALSA::create(GetComponentIndex(inComponent)); return *outInstance ? noErr : paramErr; } @@ -93,31 +99,3 @@ UInt32 AudioComponentCount(AudioComponentDescription *inDesc) 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 index f8bb69c5f..6a68353ae 100644 --- a/src/AudioUnit/AUComponent.h +++ b/src/AudioUnit/AUComponent.h @@ -5,6 +5,7 @@ #include class AudioUnitComponent; + typedef Component AudioComponent; typedef AudioUnitComponent* AudioComponentInstance; typedef ComponentDescription AudioComponentDescription; diff --git a/src/AudioUnit/AUComponentInternal.h b/src/AudioUnit/AUComponentInternal.h deleted file mode 100644 index 0f96d091f..000000000 --- a/src/AudioUnit/AUComponentInternal.h +++ /dev/null @@ -1,21 +0,0 @@ -#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 index ae011ea23..74e530112 100644 --- a/src/AudioUnit/AudioUnit.cpp +++ b/src/AudioUnit/AudioUnit.cpp @@ -1,4 +1,67 @@ #include "AudioUnit.h" +#include "AudioUnitALSA.h" +#include +#include +#include +#include +OSStatus AudioUnitInitialize(AudioUnit inUnit) +{ + return inUnit->init(); +} + +OSStatus AudioUnitUninitialize(AudioUnit inUnit) +{ + return inUnit->deinit(); +} + +OSStatus AudioUnitAddRenderNotify(AudioUnit inUnit, AURenderCallback inProc, void* opaque) +{ + STUB(); + return unimpErr; +} + +OSStatus AudioUnitRemoveRenderNotify(AudioUnit inUnit, AURenderCallback inProc, void* opaque) +{ + STUB(); + return unimpErr; +} + +OSStatus AudioUnitRender(AudioUnit inUnit, AudioUnitRenderActionFlags *ioActionFlags, const AudioTimeStamp *inTimeStamp, UInt32 inOutputBusNumber, UInt32 inNumberFrames, AudioBufferList *ioData) +{ + STUB(); + return unimpErr; +} + +OSStatus AudioUnitReset(AudioUnit inUnit, AudioUnitScope inScope, AudioUnitElement inElement) +{ + STUB(); + return noErr; +} + +OSStatus AudioUnitGetProperty(AudioUnit inUnit, AudioUnitPropertyID inID, AudioUnitScope inScope, AudioUnitElement inElement, void* outData, UInt32 *ioDataSize) +{ + return inUnit->getProperty(inID, inScope, inElement, outData, ioDataSize); +} + +OSStatus AudioUnitGetPropertyInfo(AudioUnit inUnit, AudioUnitPropertyID inID, AudioUnitScope inScope, AudioUnitElement inElement, UInt32 *outDataSize, Boolean *outWritable) +{ + return inUnit->getPropertyInfo(inID, inScope, inElement, outDataSize, outWritable); +} + +OSStatus AudioUnitSetProperty(AudioUnit inUnit, AudioUnitPropertyID inID, AudioUnitScope inScope, AudioUnitElement inElement, const void *inData, UInt32 inDataSize) +{ + return inUnit->setProperty(inID, inScope, inElement, inData, inDataSize); +} + +OSStatus AudioOutputUnitStart(AudioUnit inUnit) +{ + return inUnit->start(); +} + +OSStatus AudioOutputUnitStop(AudioUnit inUnit) +{ + return inUnit->stop(); +} diff --git a/src/AudioUnit/AudioUnit.h b/src/AudioUnit/AudioUnit.h index 0139f3aeb..b25df9ca8 100644 --- a/src/AudioUnit/AudioUnit.h +++ b/src/AudioUnit/AudioUnit.h @@ -1,6 +1,47 @@ #ifndef AUDIOUNIT_H #define AUDIOUNIT_H +#include +#include +#include "AUComponent.h" +typedef AudioComponentInstance AudioUnit; +typedef UInt32 AudioUnitRenderActionFlags; +typedef UInt32 AudioUnitElement; +typedef UInt32 AudioUnitScope; +typedef UInt32 AudioUnitPropertyID; + +typedef OSStatus (*AURenderCallback) (void *inRefCon, AudioUnitRenderActionFlags *ioActionFlags, const AudioTimeStamp *inTimeStamp, UInt32 inBusNumber, UInt32 inNumberFrames, AudioBufferList *ioData); + +enum { + kAudioUnitRenderAction_PreRender = (1 << 2), + kAudioUnitRenderAction_PostRender = (1 << 3), + kAudioUnitRenderAction_OutputIsSilence = (1 << 4), + kAudioOfflineUnitRenderAction_Preflight = (1 << 5), + kAudioOfflineUnitRenderAction_Render = (1 << 6), + kAudioOfflineUnitRenderAction_Complete = (1 << 7), + kAudioUnitRenderAction_PostRenderError = (1 << 8), + kAudioUnitRenderAction_DoNotCheckRenderArgs = (1 << 9) +}; + +extern "C" { + +OSStatus AudioUnitInitialize(AudioUnit inUnit); +OSStatus AudioUnitUninitialize(AudioUnit inUnit); + +OSStatus AudioUnitAddRenderNotify(AudioUnit inUnit, AURenderCallback inProc, void* opaque); +OSStatus AudioUnitRemoveRenderNotify(AudioUnit inUnit, AURenderCallback inProc, void* opaque); + +OSStatus AudioUnitRender(AudioUnit inUnit, AudioUnitRenderActionFlags *ioActionFlags, const AudioTimeStamp *inTimeStamp, UInt32 inOutputBusNumber, UInt32 inNumberFrames, AudioBufferList *ioData); +OSStatus AudioUnitReset(AudioUnit inUnit, AudioUnitScope inScope, AudioUnitElement inElement); + +OSStatus AudioUnitGetProperty(AudioUnit inUnit, AudioUnitPropertyID inID, AudioUnitScope inScope, AudioUnitElement inElement, void* outData, UInt32 *ioDataSize); +OSStatus AudioUnitGetPropertyInfo(AudioUnit inUnit, AudioUnitPropertyID inID, AudioUnitScope inScope, AudioUnitElement inElement, UInt32 *outDataSize, Boolean *outWritable); +OSStatus AudioUnitSetProperty(AudioUnit inUnit, AudioUnitPropertyID inID, AudioUnitScope inScope, AudioUnitElement inElement, const void *inData, UInt32 inDataSize); + +OSStatus AudioOutputUnitStart(AudioUnit inUnit); +OSStatus AudioOutputUnitStop(AudioUnit inUnit); + +} #endif diff --git a/src/AudioUnit/AudioUnitALSA.cpp b/src/AudioUnit/AudioUnitALSA.cpp new file mode 100644 index 000000000..ee96a1332 --- /dev/null +++ b/src/AudioUnit/AudioUnitALSA.cpp @@ -0,0 +1,103 @@ +#include "AudioUnitALSA.h" +#include "AudioUnitProperties.h" +#include +#include + + +AudioUnitALSA::AudioUnitALSA(int cardIndex, char* cardName) +: m_cardIndex(cardIndex), m_cardName(cardName), m_pcmOutput(nullptr), m_pcmInput(nullptr) +{ +} + +AudioUnitComponent* AudioUnitALSA::create(int cardIndex) +{ + char* name; + + if (cardIndex > 0) + { + if (snd_card_get_name(cardIndex, &name)) + return nullptr; + } + else + { + name = strdup("default"); + } + + return new AudioUnitALSA(cardIndex, name); +} + +AudioUnitALSA::~AudioUnitALSA() +{ + deinit(); + free(m_cardName); +} + +OSStatus AudioUnitALSA::init() +{ + if (m_pcmOutput || m_pcmInput) + return kAudioUnitErr_Initialized; + + if (m_enableOutput && snd_pcm_open(&m_pcmOutput, m_cardName, SND_PCM_STREAM_PLAYBACK, 0)) + { + LOG << "Failed to initialize playback PCM " << m_cardName; + return kAudioUnitErr_FailedInitialization; + } + if (m_enableInput && snd_pcm_open(&m_pcmInput, m_cardName, SND_PCM_STREAM_CAPTURE, 0)) + { + deinit(); + + LOG << "Failed to initialize capture PCM " << m_cardName; + return kAudioUnitErr_FailedInitialization; + } + return noErr; +} + +OSStatus AudioUnitALSA::deinit() +{ + if (m_pcmOutput) + { + snd_pcm_close(m_pcmOutput); + m_pcmOutput = nullptr; + } + if (m_pcmInput) + { + snd_pcm_close(m_pcmInput); + m_pcmInput = nullptr; + } + return noErr; +} + + +OSStatus AudioUnitALSA::start() +{ + if (m_pcmInput) + { + if (snd_pcm_start(m_pcmInput)) + { + return kAudioUnitErr_FailedInitialization; + } + } + + if (m_pcmOutput) + { + if (snd_pcm_start(m_pcmOutput)) + { + if (m_pcmInput) + snd_pcm_drop(m_pcmInput); + + return kAudioUnitErr_FailedInitialization; + } + } + + return noErr; +} + +OSStatus AudioUnitALSA::stop() +{ + if (m_pcmInput) + snd_pcm_drop(m_pcmInput); + if (m_pcmOutput) + snd_pcm_drop(m_pcmOutput); + return noErr; +} + diff --git a/src/AudioUnit/AudioUnitALSA.h b/src/AudioUnit/AudioUnitALSA.h new file mode 100644 index 000000000..b02651aa3 --- /dev/null +++ b/src/AudioUnit/AudioUnitALSA.h @@ -0,0 +1,30 @@ +#ifndef AUCOMPONENTINTERNAL_H +#define AUCOMPONENTINTERNAL_H +#include "AudioUnit.h" +#include +#include +#include "AudioUnitBase.h" + +class AudioUnitALSA : public AudioUnitComponent +{ +private: + AudioUnitALSA(int cardIndex, char* cardName); +public: + static AudioUnitComponent* create(int cardIndex); + virtual ~AudioUnitALSA(); + + int cardIndex() const override { return m_cardIndex; } + + OSStatus init() override; + OSStatus deinit() override; + + OSStatus start() override; + OSStatus stop() override; +private: + int m_cardIndex; + char* m_cardName; + snd_pcm_t *m_pcmOutput, *m_pcmInput; +}; + +#endif + diff --git a/src/AudioUnit/AudioUnitBase.cpp b/src/AudioUnit/AudioUnitBase.cpp new file mode 100644 index 000000000..2c78df6ed --- /dev/null +++ b/src/AudioUnit/AudioUnitBase.cpp @@ -0,0 +1,191 @@ +#include "AudioUnitBase.h" +#include "AudioUnitProperties.h" +#include +#include +#include + +AudioUnitComponent::AudioUnitComponent() + : m_enableOutput(true), m_enableInput(false) +{ + // Default audio params + m_configOutputPlayback = AudioStreamBasicDescription { + 44100.0, kAudioFormatLinearPCM, kAudioFormatFlagIsSignedInteger | kAudioFormatFlagIsPacked, + 4, 1, 4, 2, 16, 0 + }; + memcpy(&m_configInputPlayback, &m_configOutputPlayback, sizeof(AudioStreamBasicDescription)); + memcpy(&m_configInputCapture, &m_configOutputPlayback, sizeof(AudioStreamBasicDescription)); + memcpy(&m_configOutputCapture, &m_configOutputPlayback, sizeof(AudioStreamBasicDescription)); + + memset(&m_renderCallback, 0, sizeof(m_renderCallback)); +} + + +OSStatus AudioUnitComponent::getPropertyInfo(AudioUnitPropertyID prop, AudioUnitScope scope, AudioUnitElement elem, UInt32* dataSize, Boolean* writable) +{ + switch (prop) + { + case kAudioUnitProperty_StreamFormat: + *dataSize = sizeof(AudioStreamBasicDescription); + *writable = true; + break; + case kAudioOutputUnitProperty_EnableIO: + *dataSize = sizeof(UInt32); + *writable = true; + break; + case kAudioUnitProperty_SetRenderCallback: + *dataSize = sizeof(AURenderCallbackStruct); + *writable = true; + break; + default: + return kAudioUnitErr_InvalidProperty; + } + + return noErr; +} + +OSStatus AudioUnitComponent::setProperty(AudioUnitPropertyID prop, AudioUnitScope scope, AudioUnitElement elem, const void* data, UInt32 dataSize) +{ + TRACE5(prop, scope, elem, data, dataSize); + + switch (prop) + { + case kAudioUnitProperty_StreamFormat: + { + if (dataSize != sizeof(AudioStreamBasicDescription)) + return kAudioUnitErr_InvalidParameter; + + // TODO: perform validation + + if (scope == kAudioUnitScope_Output) + { + if (elem == 0) + memcpy(&m_configOutputPlayback, data, dataSize); + else if (elem == 1) + memcpy(&m_configOutputCapture, data, dataSize); + else + return kAudioUnitErr_InvalidElement; + } + else if (scope == kAudioUnitScope_Input) + { + if (elem == 0) + memcpy(&m_configInputPlayback, data, dataSize); + else if (elem == 1) + memcpy(&m_configInputCapture, data, dataSize); + else + return kAudioUnitErr_InvalidElement; + } + else + return kAudioUnitErr_InvalidScope; + + return noErr; + } + case kAudioOutputUnitProperty_EnableIO: + { + const UInt32* state; + + if (dataSize != sizeof(UInt32)) + return kAudioUnitErr_InvalidParameter; + + state = static_cast(data); + + if (scope == kAudioUnitScope_Output) + { + if (elem != 0) + return kAudioUnitErr_InvalidElement; + m_enableOutput = *state != 0; + } + else if (scope == kAudioUnitScope_Input) + { + if (elem != 1) + return kAudioUnitErr_InvalidElement; + m_enableInput = *state != 0; + } + else + return kAudioUnitErr_InvalidScope; + + return noErr; + } + case kAudioUnitProperty_SetRenderCallback: + { + if (dataSize != sizeof(AURenderCallbackStruct)) + return kAudioUnitErr_InvalidParameter; + if (scope != kAudioUnitScope_Input) + return kAudioUnitErr_InvalidScope; + if (elem != 0) + return kAudioUnitErr_InvalidElement; + + memcpy(&m_renderCallback, data, dataSize); + return noErr; + } + default: + return kAudioUnitErr_InvalidProperty; + } +} + +OSStatus AudioUnitComponent::getProperty(AudioUnitPropertyID prop, AudioUnitScope scope, AudioUnitElement elem, void* data, UInt32* dataSize) +{ + TRACE5(prop, scope, elem, data, dataSize); + + switch (prop) + { + case kAudioUnitProperty_StreamFormat: + { + if (*dataSize < sizeof(AudioStreamBasicDescription)) + return kAudioUnitErr_InvalidParameter; + + if (scope == kAudioUnitScope_Output) + { + if (elem == 0) + memcpy(data, &m_configOutputPlayback, *dataSize); + else if (elem == 1) + memcpy(data, &m_configOutputCapture, *dataSize); + else + return kAudioUnitErr_InvalidElement; + } + else if (scope == kAudioUnitScope_Input) + { + if (elem == 0) + memcpy(data, &m_configInputPlayback, *dataSize); + else if (elem == 1) + memcpy(data, &m_configInputCapture, *dataSize); + else + return kAudioUnitErr_InvalidElement; + } + else + return kAudioUnitErr_InvalidScope; + + *dataSize = sizeof(AudioStreamBasicDescription); + + return noErr; + } + case kAudioOutputUnitProperty_EnableIO: + { + UInt32* state; + + if (*dataSize < sizeof(UInt32)) + return kAudioUnitErr_InvalidParameter; + + state = static_cast(data); + + if (scope == kAudioUnitScope_Output) + { + if (elem != 0) + return kAudioUnitErr_InvalidElement; + *state = m_enableOutput; + } + else if (scope == kAudioUnitScope_Input) + { + if (elem != 1) + return kAudioUnitErr_InvalidElement; + *state = m_enableInput; + } + else + return kAudioUnitErr_InvalidScope; + + *dataSize = sizeof(UInt32); + return noErr; + } + default: + return kAudioUnitErr_InvalidProperty; + } +} diff --git a/src/AudioUnit/AudioUnitBase.h b/src/AudioUnit/AudioUnitBase.h new file mode 100644 index 000000000..701490e5a --- /dev/null +++ b/src/AudioUnit/AudioUnitBase.h @@ -0,0 +1,31 @@ +#ifndef AUDIOUNITBASE_H +#define AUDIOUNITBASE_H + +#include "AudioUnit.h" +#include "AudioUnitProperties.h" +#include + +class AudioUnitComponent : public CarbonComponent +{ +public: + AudioUnitComponent(); + + virtual int cardIndex() const = 0; + + virtual OSStatus init() = 0; + virtual OSStatus deinit() = 0; + + virtual OSStatus start() = 0; + virtual OSStatus stop() = 0; + + virtual OSStatus setProperty(AudioUnitPropertyID prop, AudioUnitScope scope, AudioUnitElement elem, const void* data, UInt32 dataSize); + virtual OSStatus getProperty(AudioUnitPropertyID prop, AudioUnitScope scope, AudioUnitElement elem, void* data, UInt32* dataSize); + virtual OSStatus getPropertyInfo(AudioUnitPropertyID prop, AudioUnitScope scope, AudioUnitElement elem, UInt32* dataSize, Boolean* writable); +protected: + bool m_enableOutput, m_enableInput; + AudioStreamBasicDescription m_configOutputPlayback, m_configInputPlayback, m_configInputCapture, m_configOutputCapture; + AURenderCallbackStruct m_renderCallback; +}; + +#endif + diff --git a/src/AudioUnit/AudioUnitProperties.h b/src/AudioUnit/AudioUnitProperties.h new file mode 100644 index 000000000..c4f279a66 --- /dev/null +++ b/src/AudioUnit/AudioUnitProperties.h @@ -0,0 +1,61 @@ +#ifndef AUDIOUNITPROPERTIES_H +#define AUDIOUNITPROPERTIES_H + +enum { + kAudioOutputUnitProperty_CurrentDevice = 2000, + kAudioOutputUnitProperty_ChannelMap = 2002, + kAudioOutputUnitProperty_EnableIO = 2003, + kAudioOutputUnitProperty_StartTime = 2004, + kAudioOutputUnitProperty_SetInputCallback = 2005, + kAudioOutputUnitProperty_HasIO = 2006, + kAudioOutputUnitProperty_StartTimestampsAtZero = 2007 +}; + +enum { + kAudioUnitScope_Global = 0, + kAudioUnitScope_Input = 1, + kAudioUnitScope_Output = 2, + kAudioUnitScope_Group = 3, + kAudioUnitScope_Part = 4, + kAudioUnitScope_Note = 5, + kAudioUnitScope_Layer = 6, + kAudioUnitScope_LayerItem = 7 +}; + +enum +{ + kAudioUnitProperty_ClassInfo = 0, + kAudioUnitProperty_MakeConnection = 1, + kAudioUnitProperty_SampleRate = 2, + kAudioUnitProperty_ParameterList = 3, + kAudioUnitProperty_ParameterInfo = 4, + kAudioUnitProperty_CPULoad = 6, + kAudioUnitProperty_StreamFormat = 8, + kAudioUnitProperty_ElementCount = 11, + kAudioUnitProperty_Latency = 12, + kAudioUnitProperty_SupportedNumChannels = 13, + kAudioUnitProperty_MaximumFramesPerSlice = 14, + kAudioUnitProperty_ParameterValueStrings = 16, + kAudioUnitProperty_AudioChannelLayout = 19, + kAudioUnitProperty_TailTime = 20, + kAudioUnitProperty_BypassEffect = 21, + kAudioUnitProperty_LastRenderError = 22, + kAudioUnitProperty_SetRenderCallback = 23, + kAudioUnitProperty_FactoryPresets = 24, + kAudioUnitProperty_RenderQuality = 26, + kAudioUnitProperty_InPlaceProcessing = 29, + kAudioUnitProperty_ElementName = 30, + kAudioUnitProperty_SupportedChannelLayoutTags = 32, + kAudioUnitProperty_PresentPreset = 36, + kAudioUnitProperty_ShouldAllocateBuffer = 51, + kAudioUnitProperty_ParameterHistoryInfo = 53 +}; + +struct AURenderCallbackStruct +{ + AURenderCallback inputProc; + void *inputProcRefCon; +}; + +#endif + diff --git a/src/AudioUnit/CMakeLists.txt b/src/AudioUnit/CMakeLists.txt index 610bdccc7..3d4054bd5 100644 --- a/src/AudioUnit/CMakeLists.txt +++ b/src/AudioUnit/CMakeLists.txt @@ -15,6 +15,8 @@ include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../util) set(AudioUnit_SRCS AUComponent.cpp AudioUnit.cpp + AudioUnitBase.cpp + AudioUnitALSA.cpp ) SET(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/lib${SUFFIX}/darling") diff --git a/src/AudioToolbox/CoreAudioTypes.h b/src/CoreAudio/CoreAudioTypes.h similarity index 95% rename from src/AudioToolbox/CoreAudioTypes.h rename to src/CoreAudio/CoreAudioTypes.h index 7c5712c0f..f777f3799 100644 --- a/src/AudioToolbox/CoreAudioTypes.h +++ b/src/CoreAudio/CoreAudioTypes.h @@ -42,6 +42,23 @@ struct AudioStreamPacketDescription UInt32 mDataByteSize; }; +struct SMPTETime +{ + SInt64 mSubframes, mSubframeDivisor; + UInt32 mCounter, mType, mFlags; + SInt16 mHours, mMinutes, mSeconds, mFrames; +}; + +struct AudioTimeStamp +{ + Float64 mSampleTime; + UInt64 mHostTime; + Float64 mRateScalar; + UInt64 mWordClockTime; + SMPTETime mSMPTETime; + UInt32 mFlags, mReserved; +}; + enum { kAudioFormatLinearPCM = 'lpcm', diff --git a/src/CoreServices/Components.cpp b/src/CoreServices/Components.cpp index b6dc0849b..acf0f3542 100644 --- a/src/CoreServices/Components.cpp +++ b/src/CoreServices/Components.cpp @@ -1,11 +1,13 @@ #include "Components.h" #include "ComponentsInternal.h" #include -#include +#include #include +#include Component FindNextComponent(Component prev, ComponentDescription* desc) { + TRACE2(prev, desc); if ((desc->componentType & 0xffff0000) == kComponentTypeAudioUnit) { return AudioComponentFindNext((AudioComponent) prev, (AudioComponentDescription*) desc); @@ -26,6 +28,8 @@ long CountComponents(ComponentDescription* desc) OSErr OpenAComponent(Component comp, ComponentInstance* out) { + TRACE1(comp); + if (!out) return paramErr; @@ -47,6 +51,8 @@ OSErr OpenAComponent(Component comp, ComponentInstance* out) ComponentInstance OpenComponent(Component comp) { + TRACE1(comp); + ComponentInstance inst; OpenAComponent(comp, &inst); return inst; @@ -54,6 +60,8 @@ ComponentInstance OpenComponent(Component comp) OSErr CloseComponent(ComponentInstance inst) { + TRACE1(inst); + delete inst; return noErr; } diff --git a/src/CoreServices/MacErrors.h b/src/CoreServices/MacErrors.h index 08f74750c..52d4be8bc 100644 --- a/src/CoreServices/MacErrors.h +++ b/src/CoreServices/MacErrors.h @@ -12,4 +12,26 @@ inline OSStatus makeOSStatus(int errNo) { return 100000 + errNo; } #define kLocalesBufferTooSmallErr -30001 #define kUCOutputBufferTooSmall -25340 +#define kAudioUnitErr_InvalidProperty -10879 +#define kAudioUnitErr_InvalidParameter -10878 +#define kAudioUnitErr_InvalidElement -10877 +#define kAudioUnitErr_NoConnection -10876 +#define kAudioUnitErr_FailedInitialization -10875 +#define kAudioUnitErr_TooManyFramesToProcess -10874 +#define kAudioUnitErr_IllegalInstrument -10873 +#define kAudioUnitErr_InstrumentTypeNotFound -10872 +#define kAudioUnitErr_InvalidFile -10871 +#define kAudioUnitErr_UnknownFileType -10870 +#define kAudioUnitErr_FileNotSpecified -10869 +#define kAudioUnitErr_FormatNotSupported -10868 +#define kAudioUnitErr_Uninitialized -10867 +#define kAudioUnitErr_InvalidScope -10866 +#define kAudioUnitErr_PropertyNotWritable -10865 +#define kAudioUnitErr_CannotDoInCurrentContext -10863 +#define kAudioUnitErr_InvalidPropertyValue -10851 +#define kAudioUnitErr_PropertyNotInUse -10850 +#define kAudioUnitErr_Initialized -10849 +#define kAudioUnitErr_InvalidOfflineRender -10848 +#define kAudioUnitErr_Unauthorized -10847 + #endif diff --git a/src/dyld/ld.cpp b/src/dyld/ld.cpp index 078970fad..1223c5109 100644 --- a/src/dyld/ld.cpp +++ b/src/dyld/ld.cpp @@ -629,7 +629,7 @@ const char* NSLibraryNameForModule(NSModule m) void* __darwin_dlsym(void* handle, const char* symbol, void* extra) { - TRACE2(handle, symbol); + // TRACE2(handle, symbol); Darling::MutexLock l(g_ldMutex); g_ldError[0] = 0; diff --git a/src/util/CMakeLists.txt b/src/util/CMakeLists.txt index 326ab89b9..f18b1f7c7 100644 --- a/src/util/CMakeLists.txt +++ b/src/util/CMakeLists.txt @@ -7,8 +7,7 @@ if(COMMAND cmake_policy) endif(COMMAND cmake_policy) set(util-SRCS - log.cpp - trace.cpp + debug.cpp stlutils.cpp IniConfig.cpp leb.cpp diff --git a/src/util/debug.cpp b/src/util/debug.cpp new file mode 100644 index 000000000..6adc84378 --- /dev/null +++ b/src/util/debug.cpp @@ -0,0 +1,113 @@ +#include "debug.h" +#include +#include +#include "stlutils.h" + +extern "C" bool g_loggingEnabled = false; // "debug" channel +static bool m_traceEnabled = false; +static bool m_errorEnabled = true; + +__attribute__((constructor)) static void initLogging() +{ + const char* v = getenv("DYLD_DEBUG"); + if (v != nullptr) + { + std::vector specs = string_explode(v, ',', false); + for (std::string str : specs) + { + bool enable = true, none = false; + + if (str[0] == '+') + enable = true; + else if (str[0] == '-') + enable = false; + else + none = true; + + if (!none) + str = str.substr(1); + + if (str == "debug") + g_loggingEnabled = enable; + else if (str == "trace") + m_traceEnabled = enable; + else if (str == "error") + m_errorEnabled = enable; + } + } +} + +bool Darling::debugChannelEnabled(DebugChannel channel) +{ + switch (channel) + { + case DebugChannel::Debug: + return g_loggingEnabled; + case DebugChannel::Trace: + return m_traceEnabled; + case DebugChannel::Error: + return m_errorEnabled; + default: + return false; + } +} + +static const char* shortenFileName(const char* file) +{ + const char* s = strrchr(file, '/'); + if (!s) + return file; + else + return s+1; +} + +Darling::TraceHelper::TraceHelper(const char* funcName, DebugChannel chan, const char* file, int line) +{ + m_print = debugChannelEnabled(chan); + + if (m_print) + { + switch (chan) + { + case DebugChannel::Debug: + std::cerr << "DEBUG"; break; + case DebugChannel::Trace: + std::cerr << "TRACE"; break; + case DebugChannel::Error: + std::cerr << "ERROR"; break; + } + + if (!file) + std::cerr << " in " << funcName << ':'; + else + std::cerr << " @" << shortenFileName(file) << ':' << line << " in " << funcName << ':'; + } +} + +Darling::TraceHelper::TraceHelper(DebugChannel chan) +{ + m_print = debugChannelEnabled(chan); +} + +Darling::TraceHelper::~TraceHelper() +{ + if (m_print) + std::cerr << std::endl << std::flush; +} + +template<> void Darling::logPrint(std::string value) +{ + //if (g_loggingEnabled) + std::cerr << '\"' << value << '\"'; +} +template<> void Darling::logPrint(const char* value) +{ + //if (g_loggingEnabled) + std::cerr << '\"' << value << '\"'; +} +template<> void Darling::logPrint(Darling::ArgName value) +{ + //if (g_loggingEnabled) + std::cerr << value.name; +} + diff --git a/src/util/debug.h b/src/util/debug.h new file mode 100644 index 000000000..3fd417304 --- /dev/null +++ b/src/util/debug.h @@ -0,0 +1,83 @@ +#ifndef UTIL_DEBUG_H +#define UTIL_DEBUG_H + +#include +#include +#include + +extern "C" bool g_loggingEnabled; + +namespace Darling { + +enum class DebugChannel { Error, Trace, Debug }; + +bool debugChannelEnabled(DebugChannel channel); + + +#define LOG if (g_loggingEnabled) std::cerr +#define LOGF(...) if (g_loggingEnabled) fprintf(stderr, __VA_ARGS__) + +void logTrace(const char* funcName, ...); + +struct ArgName +{ + ArgName(const char* p) : name(p) {} + const char* name; +}; + +template void logPrint(T value) +{ + std::cerr << value; +} +template<> void logPrint(const char* value); +template<> void logPrint(std::string value); +template<> void logPrint(ArgName value); + +class TraceHelper +{ +public: + TraceHelper(const char* funcName, DebugChannel chan, const char* file = nullptr, int line = 0); + TraceHelper(DebugChannel chan); + ~TraceHelper(); + + template TraceHelper& operator << (T value) + { + if (m_print) + logPrint(value); + return *this; + } + + template TraceHelper& write(T value) + { + if (m_print) + std::cerr << value; + return *this; + } +private: + bool m_print; +}; + +#define ARG(a) (Darling::ArgName(" " #a "=")) << a +#define ARGP(a) (Darling::ArgName(" " #a "=")) << ((void*)a) +#define TRACE() Darling::TraceHelper(__PRETTY_FUNCTION__, Darling::DebugChannel::Trace, __FILE__, __LINE__) +#define TRACE1(a) TRACE() << ARG(a) +#define TRACE2(a,b) TRACE() << ARG(a) << ARG(b) +#define TRACE3(a,b,c) TRACE() << ARG(a) << ARG(b) << ARG(c) +#define TRACE4(a,b,c,d) TRACE() << ARG(a) << ARG(b) << ARG(c) << ARG(d) +#define TRACE5(a,b,c,d,e) TRACE() << ARG(a) << ARG(b) << ARG(c) << ARG(d) << ARG(e) +#define TRACE6(a,b,c,d,e,f) TRACE() << ARG(a) << ARG(b) << ARG(c) << ARG(d) << ARG(e) << ARG(f) + +#define ERROR() Darling::TraceHelper(__PRETTY_FUNCTION__, Darling::DebugChannel::Error, __FILE__, __LINE__) +#define ERROR1(a) ERROR() << ARG(a) +#define ERROR2(a,b) ERROR() << ARG(a) << ARG(b) +#define ERROR3(a,b,c) ERROR() << ARG(a) << ARG(b) << ARG(c) +#define ERROR4(a,b,c,d) ERROR() << ARG(a) << ARG(b) << ARG(c) << ARG(d) +#define ERROR5(a,b,c,d,e) ERROR() << ARG(a) << ARG(b) << ARG(c) << ARG(d) << ARG(e) +#define ERROR6(a,b,c,d,e,f) ERROR() << ARG(a) << ARG(b) << ARG(c) << ARG(d) << ARG(e) << ARG(f) + +#define STUB() ERROR().write(" STUB!") + +} // namespace Darling + +#endif + diff --git a/src/util/log.cpp b/src/util/log.cpp deleted file mode 100644 index b54e524c4..000000000 --- a/src/util/log.cpp +++ /dev/null @@ -1,12 +0,0 @@ -#include -#include - -extern "C" bool g_loggingEnabled = false; - -__attribute__((constructor)) static void initLogging() -{ - const char* v = getenv("DYLD_DEBUG"); - if (v && atoi(v)) - g_loggingEnabled = true; -} - diff --git a/src/util/log.h b/src/util/log.h index d676ddd0c..95234dbe3 100644 --- a/src/util/log.h +++ b/src/util/log.h @@ -1,13 +1,2 @@ -#ifndef UTIL_LOG_H -#define UTIL_LOG_H +#include "debug.h" -#include -#include -#include - -extern "C" bool g_loggingEnabled; - -#define LOG if (g_loggingEnabled) std::cerr -#define LOGF(...) if (g_loggingEnabled) fprintf(stderr, __VA_ARGS__) - -#endif diff --git a/src/util/trace.cpp b/src/util/trace.cpp deleted file mode 100644 index 3c8edc1bc..000000000 --- a/src/util/trace.cpp +++ /dev/null @@ -1,30 +0,0 @@ -#include "trace.h" -#include -#include - -TraceHelper::TraceHelper(const char* funcName) -{ - if (g_loggingEnabled) - std::cerr << "TRACE(): " << funcName << ""; -} -TraceHelper::~TraceHelper() -{ - if (g_loggingEnabled) - std::cerr << std::endl << std::flush; -} - -template<> void logPrint(std::string value) -{ - if (g_loggingEnabled) - std::cerr << '\"' << value << '\"'; -} -template<> void logPrint(const char* value) -{ - if (g_loggingEnabled) - std::cerr << '\"' << value << '\"'; -} -template<> void logPrint(ArgName value) -{ - if (g_loggingEnabled) - std::cerr << value.name; -} diff --git a/src/util/trace.h b/src/util/trace.h index d8fb9702d..95234dbe3 100644 --- a/src/util/trace.h +++ b/src/util/trace.h @@ -1,46 +1,2 @@ -#ifndef DARLING_TRACE_H -#define DARLING_TRACE_H -#include -#include "log.h" +#include "debug.h" -void logTrace(const char* funcName, ...); - -struct ArgName -{ - ArgName(const char* p) : name(p) {} - const char* name; -}; - -template void logPrint(T value) -{ - if (g_loggingEnabled) - std::cerr << value; -} -template<> void logPrint(const char* value); -template<> void logPrint(std::string value); -template<> void logPrint(ArgName value); - -class TraceHelper -{ -public: - TraceHelper(const char* funcName); - ~TraceHelper(); - - template TraceHelper& operator << (T value) - { - logPrint(value); - return *this; - } -}; - -#define ARG(a) (ArgName(" " #a "=")) << a -#define ARGP(a) (ArgName(" " #a "=")) << ((void*)a) -#define TRACE() TraceHelper(__PRETTY_FUNCTION__) -#define TRACE1(a) TRACE() << ARG(a) -#define TRACE2(a,b) TRACE() << ARG(a) << ARG(b) -#define TRACE3(a,b,c) TRACE() << ARG(a) << ARG(b) << ARG(c) -#define TRACE4(a,b,c,d) TRACE() << ARG(a) << ARG(b) << ARG(c) << ARG(d) -#define TRACE5(a,b,c,d,e) TRACE() << ARG(a) << ARG(b) << ARG(c) << ARG(d) << ARG(e) -#define TRACE6(a,b,c,d,e,f) TRACE() << ARG(a) << ARG(b) << ARG(c) << ARG(d) << ARG(e) << ARG(f) - -#endif