diff --git a/cmake/FindFFmpeg.cmake b/cmake/FindFFmpeg.cmake new file mode 100644 index 000000000..b34be8637 --- /dev/null +++ b/cmake/FindFFmpeg.cmake @@ -0,0 +1,97 @@ +# - Try to find ffmpeg libraries (libavcodec, libavformat and libavutil) +# Once done this will define +# +# FFMPEG_FOUND - system has ffmpeg or libav +# FFMPEG_INCLUDE_DIR - the ffmpeg include directory +# FFMPEG_LIBRARIES - Link these to use ffmpeg +# FFMPEG_LIBAVCODEC +# FFMPEG_LIBAVFORMAT +# FFMPEG_LIBAVUTIL +# +# Copyright (c) 2008 Andreas Schneider +# Modified for other libraries by Lasse Kärkkäinen +# Modified for Hedgewars by Stepik777 +# Modified for FFmpeg-example Tuukka Pasanen 2018 +# +# Redistribution and use is allowed according to the terms of the New +# BSD license. +# + +include(FindPackageHandleStandardArgs) + +if(FFMPEG_LIBRARIES AND FFMPEG_INCLUDE_DIR) + # in cache already + set(FFMPEG_FOUND TRUE) +else() + # use pkg-config to get the directories and then use these values + # in the FIND_PATH() and FIND_LIBRARY() calls + find_package(PkgConfig) + if(PKG_CONFIG_FOUND) + pkg_check_modules(_FFMPEG_AVCODEC libavcodec) + pkg_check_modules(_FFMPEG_AVFORMAT libavformat) + pkg_check_modules(_FFMPEG_AVUTIL libavutil) + endif() + + find_path(FFMPEG_AVCODEC_INCLUDE_DIR + NAMES libavcodec/avcodec.h + PATHS ${_FFMPEG_AVCODEC_INCLUDE_DIRS} + /usr/include + /usr/local/include + /opt/local/include + /sw/include + PATH_SUFFIXES ffmpeg libav) + + find_library(FFMPEG_LIBAVCODEC + NAMES avcodec + PATHS ${_FFMPEG_AVCODEC_LIBRARY_DIRS} + /usr/lib + /usr/local/lib + /opt/local/lib + /sw/lib) + + find_library(FFMPEG_LIBAVFORMAT + NAMES avformat + PATHS ${_FFMPEG_AVFORMAT_LIBRARY_DIRS} + /usr/lib + /usr/local/lib + /opt/local/lib + /sw/lib) + + find_library(FFMPEG_LIBAVUTIL + NAMES avutil + PATHS ${_FFMPEG_AVUTIL_LIBRARY_DIRS} + /usr/lib + /usr/local/lib + /opt/local/lib + /sw/lib) + + if(FFMPEG_LIBAVCODEC AND FFMPEG_LIBAVFORMAT) + set(FFMPEG_FOUND TRUE) + endif() + + if(FFMPEG_FOUND) + set(FFMPEG_INCLUDE_DIR ${FFMPEG_AVCODEC_INCLUDE_DIR}) + set(FFMPEG_LIBRARIES + ${FFMPEG_LIBAVCODEC} + ${FFMPEG_LIBAVFORMAT} + ${FFMPEG_LIBAVUTIL}) + endif() + + if(FFMPEG_FOUND) + if(NOT FFMPEG_FIND_QUIETLY) + message(STATUS + "Found FFMPEG or Libav: ${FFMPEG_LIBRARIES}, ${FFMPEG_INCLUDE_DIR}") + endif() + else() + message(FATAL_ERROR + "Could not find libavcodec or libavformat or libavutil") + endif() +endif() + +find_package_handle_standard_args(FFMPEG +FOUND_VAR FFMPEG_FOUND +REQUIRED_VARS + FFMPEG_LIBRARIES + FFMPEG_INCLUDE_DIR +VERSION_VAR FFMPEG_VERSION +) diff --git a/cmake/FindPulseAudio.cmake b/cmake/FindPulseAudio.cmake new file mode 100644 index 000000000..f0ba75e39 --- /dev/null +++ b/cmake/FindPulseAudio.cmake @@ -0,0 +1,18 @@ + +include(FindPackageHandleStandardArgs) + +find_path(PULSEAUDIO_INCLUDE_DIRS + NAMES pulse/pulseaudio.h + DOC "PulseAudio include directory" +) + +find_library(PULSEAUDIO_LIBRARIES + NAMES pulse + DOC "PulseAudio library" +) + +find_package_handle_standard_args(PulseAudio + REQUIRED_VARS PULSEAUDIO_LIBRARIES PULSEAUDIO_INCLUDE_DIRS VERSION_VAR PULSEAUDIO_VERSION + FAIL_MESSAGE "Could NOT find PulseAudio!") + +mark_as_advanced(PULSEAUDIO_INCLUDE_DIRS PULSEAUDIO_LIBRARIES) diff --git a/src/CoreAudio/CoreAudio/AudioHardware.cpp b/src/CoreAudio/CoreAudio/AudioHardware.cpp index 48b53782d..fcc9ba2be 100644 --- a/src/CoreAudio/CoreAudio/AudioHardware.cpp +++ b/src/CoreAudio/CoreAudio/AudioHardware.cpp @@ -19,7 +19,9 @@ along with Darling. If not, see . #include #include "AudioHardwareImpl.h" +#include "AudioHardwareImplPA.h" #include +#include #include #include "stub.h" @@ -27,16 +29,11 @@ static std::unique_ptr g_systemObject; static AudioHardwareImpl* GetSystemObject() { - if (!g_systemObject) - { - static std::mutex singleLock; - singleLock.lock(); - - if (!g_systemObject) - g_systemObject.reset(nullptr); // TODO: create ALSA or PA here - - singleLock.unlock(); - } + static dispatch_once_t once; + dispatch_once(&once, ^{ + // TODO: Or ALSA + g_systemObject.reset(new AudioHardwareImplPA); + }); return g_systemObject.get(); } @@ -45,6 +42,8 @@ static AudioHardwareImpl* GetObject(AudioObjectID objID) { if (objID == kAudioObjectSystemObject) return GetSystemObject(); + + // TODO: For ALSA, support more objects for every device return nullptr; } @@ -136,7 +135,6 @@ OSStatus AudioObjectRemovePropertyListener(AudioObjectID inObjectID, OSStatus AudioHardwareUnload(void) { - g_systemObject.reset(nullptr); return noErr; } @@ -157,14 +155,61 @@ OSStatus AudioHardwareDestroyAggregateDevice(AudioObjectID inDeviceID) OSStatus AudioHardwareGetProperty(AudioHardwarePropertyID inPropId, UInt32* ioPropertyDataSize, void* outPropertyData) { - STUB(); - return unimpErr; + if (!ioPropertyDataSize) + return paramErr; + + return AudioDeviceGetProperty(kAudioObjectSystemObject, 0, false, inPropId, ioPropertyDataSize, outPropertyData); +} + +OSStatus AudioDeviceGetProperty(AudioDeviceID inDevice, UInt32 inChannel, Boolean isInput, AudioDevicePropertyID inPropertyID, UInt32* ioPropertyDataSize, void* outPropertyData) +{ + AudioObjectPropertyAddress aopa = { + inPropertyID, + kAudioObjectPropertyScopeGlobal, + kAudioObjectPropertyElementMaster + }; + + return AudioObjectGetPropertyData(inDevice, &aopa, 0, nullptr, ioPropertyDataSize, outPropertyData); +} + +OSStatus AudioDeviceGetPropertyInfo(AudioDeviceID inDevice, UInt32 inChannel, Boolean isInput, AudioDevicePropertyID inPropertyID, UInt32* outSize, Boolean* outWritable) +{ + AudioObjectPropertyAddress aopa = { + inPropertyID, + kAudioObjectPropertyScopeGlobal, + kAudioObjectPropertyElementMaster + }; + + OSStatus status; + if (outSize) + { + status = AudioObjectGetPropertyDataSize(inDevice, &aopa, 0, nullptr, outSize); + if (status != noErr) + return status; + } + + if (outWritable) + { + status = AudioObjectIsPropertySettable(inDevice, &aopa, outWritable); + } + return status; +} + +OSStatus AudioDeviceSetProperty(AudioDeviceID inDevice, const AudioTimeStamp *inWhen, UInt32 inChannel, + Boolean isInput, AudioDevicePropertyID inPropertyID, UInt32 inPropertyDataSize, const void *inPropertyData) +{ + AudioObjectPropertyAddress aopa = { + inPropertyID, + kAudioObjectPropertyScopeGlobal, + kAudioObjectPropertyElementMaster + }; + + return AudioObjectSetPropertyData(inDevice, &aopa, 0, nullptr, inPropertyDataSize, inPropertyData); } OSStatus AudioHardwareGetPropertyInfo(AudioHardwarePropertyID inPropertyID, UInt32 *outSize, Boolean *outWritable) { - STUB(); - return unimpErr; + return AudioDeviceGetPropertyInfo(kAudioObjectSystemObject, 0, false, inPropertyID, outSize, outWritable); } OSStatus AudioDeviceCreateIOProcID(AudioObjectID inDevice, @@ -178,6 +223,14 @@ OSStatus AudioDeviceCreateIOProcID(AudioObjectID inDevice, return obj->createIOProcID(inProc, inClientData, outIOProcID); } +OSStatus AudioDeviceAddIOProc(AudioDeviceID inDevice, AudioDeviceIOProc inProc, void *inClientData) +{ + AudioHardwareImpl* obj = GetObject(inDevice); + if (!obj) + return kAudioHardwareBadObjectError; + return obj->createIOProcID(inProc, inClientData, nullptr); +} + OSStatus AudioDeviceDestroyIOProcID(AudioObjectID inDevice, AudioDeviceIOProcID inIOProcID) { @@ -188,6 +241,15 @@ OSStatus AudioDeviceDestroyIOProcID(AudioObjectID inDevice, return obj->destroyIOProcID(inIOProcID); } +OSStatus AudioDeviceRemoveIOProc(AudioDeviceID inDevice, AudioDeviceIOProc inProc) +{ + AudioHardwareImpl* obj = GetObject(inDevice); + if (!obj) + return kAudioHardwareBadObjectError; + + return obj->destroyIOProcID(AudioDeviceIOProcID(inProc)); +} + OSStatus AudioDeviceStart(AudioObjectID inDevice, AudioDeviceIOProcID inProcID) { AudioHardwareImpl* obj = GetObject(inDevice); diff --git a/src/CoreAudio/CoreAudio/AudioHardwareImpl.cpp b/src/CoreAudio/CoreAudio/AudioHardwareImpl.cpp index 5a6bb06d6..23f71fc5d 100644 --- a/src/CoreAudio/CoreAudio/AudioHardwareImpl.cpp +++ b/src/CoreAudio/CoreAudio/AudioHardwareImpl.cpp @@ -1,7 +1,7 @@ /* This file is part of Darling. -Copyright (C) 2015-2016 Lubos Dolezel +Copyright (C) 2015-2020 Lubos Dolezel Darling is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -20,6 +20,7 @@ along with Darling. If not, see . #include "AudioHardwareImpl.h" #include #include +#include #include AudioHardwareImpl::AudioHardwareImpl() @@ -41,11 +42,16 @@ OSStatus AudioHardwareImpl::createIOProcID(AudioDeviceIOProc inProc, void* inCli { std::lock_guard guard(m_procMutex); - if (!outIOProcID || !inProc) + if (!inProc) return paramErr; - *outIOProcID = reinterpret_cast(m_nextProcId++); - m_proc[*outIOProcID] = std::make_pair(inProc, inClientData); + AudioDeviceIOProcID procId; + if (outIOProcID) + *outIOProcID = procId = reinterpret_cast(m_nextProcId++); + else + procId = inProc; + + m_proc[procId] = std::make_pair(inProc, inClientData); return noErr; } @@ -71,6 +77,8 @@ OSStatus AudioHardwareImpl::start(AudioDeviceIOProcID inProcID, return paramErr; stream = createStream(inProcID); + if (!stream) + return kAudioHardwareBadStreamError; m_streams.emplace(std::make_pair(inProcID, std::unique_ptr(stream))); // TODO: time @@ -90,13 +98,15 @@ OSStatus AudioHardwareImpl::stop(AudioDeviceIOProcID inProcID) bool AudioHardwareImpl::hasProperty(const AudioObjectPropertyAddress* address) { - return false; + UInt32 ds; + OSStatus status = getPropertyDataSize(address, 0, nullptr, &ds); + return status != kAudioHardwareUnknownPropertyError; } OSStatus AudioHardwareImpl::getPropertyDataSize(const AudioObjectPropertyAddress* inAddress, UInt32 inQualifierDataSize, const void* inQualifierData, UInt32* outDataSize) { - return kAudioHardwareUnknownPropertyError; + return getPropertyData(inAddress, inQualifierDataSize, inQualifierData, outDataSize, nullptr); } OSStatus AudioHardwareImpl::isPropertySettable(const AudioObjectPropertyAddress* inAddress, Boolean* outIsSettable) @@ -105,15 +115,98 @@ OSStatus AudioHardwareImpl::isPropertySettable(const AudioObjectPropertyAddress* return kAudioHardwareUnknownPropertyError; } +// Examples: +// https://gist.github.com/robotconscience/490ee50d8ad75b47ea1f +// https://gist.github.com/hpux735/2913436 + OSStatus AudioHardwareImpl::getPropertyData(const AudioObjectPropertyAddress* inAddress, UInt32 inQualifierDataSize, const void* inQualifierData, UInt32* ioDataSize, void* outData) { + switch (inAddress->mSelector) + { + case kAudioDevicePropertyStreamFormat: // returns AudioStreamBasicDescription + { + if (AudioStreamBasicDescription* asbd = static_cast(outData); asbd && *ioDataSize >= sizeof(AudioStreamBasicDescription)) + { + // These are standard values macOS applications have learned to expect + asbd->mChannelsPerFrame = 2; + asbd->mSampleRate = 44100; + asbd->mBitsPerChannel = 32; + asbd->mFormatID = kAudioFormatLinearPCM; + asbd->mFormatFlags = kLinearPCMFormatFlagIsFloat; + asbd->mFramesPerPacket = 1; + asbd->mBytesPerFrame = UInt32(asbd->mBytesPerPacket = asbd->mChannelsPerFrame * asbd->mSampleRate * asbd->mBitsPerChannel / 8); + } + *ioDataSize = sizeof(AudioStreamBasicDescription); + return noErr; + } + case kAudioDevicePropertyDeviceManufacturer: + return getPropertyString(m_manufacturer, ioDataSize, outData); + case kAudioDevicePropertyDeviceManufacturerCFString: + return getPropertyCFString(m_manufacturer, ioDataSize, outData); + case kAudioDevicePropertyDeviceUID: // returns CFStringRef + return getPropertyCFString(m_uid, ioDataSize, outData); + case kAudioDevicePropertyDeviceNameCFString: + return getPropertyCFString(m_name, ioDataSize, outData); + case kAudioDevicePropertyDeviceName: // return char[] + return getPropertyString(m_name, ioDataSize, outData); + case kAudioDevicePropertyNominalSampleRate: // Float64 + { + if (Float64* flt = static_cast(outData); flt && *ioDataSize >= sizeof(Float64)) + *flt = 44100; + + *ioDataSize = sizeof(Float64); + return noErr; + } + case kAudioDevicePropertyAvailableNominalSampleRates: // AudioValueRange[] + { + if (AudioValueRange* avr = static_cast(outData); avr && *ioDataSize >= sizeof(AudioValueRange)*1) + { + avr->mMinimum = 44100; + avr->mMaximum = 44100; + } + *ioDataSize = sizeof(AudioValueRange) * 1; + return noErr; + } + + } return kAudioHardwareUnknownPropertyError; } +OSStatus AudioHardwareImpl::getPropertyCFString(CFStringRef str, UInt32* ioDataSize, void* outData) +{ + if (CFStringRef* ref = static_cast(outData); ref && *ioDataSize >= sizeof(CFStringRef)) + { + *ref = str; + } + *ioDataSize = sizeof(CFStringRef); + return noErr; +} + +OSStatus AudioHardwareImpl::getPropertyString(CFStringRef str, UInt32* ioDataSize, void* outData) +{ + const char* cstr = CFStringGetCStringPtr(str, kCFStringEncodingUTF8); + if (char* target = static_cast(outData)) + strlcpy(target, cstr, *ioDataSize); + *ioDataSize = strlen(cstr) + 1; + return noErr; +} + OSStatus AudioHardwareImpl::setPropertyData(const AudioObjectPropertyAddress* inAddress, UInt32 inQualifierDataSize, const void* inQualifierData, UInt32 inDataSize, const void* inData) { + switch (inAddress->mSelector) + { + case kAudioDevicePropertyBufferSize: + { + return setBufferSize(*static_cast(inData)); + } + // These make sense only for ALSA, but I find it ridiculous that these properties can be set... + case kAudioHardwarePropertyDefaultOutputDevice: + return noErr; + case kAudioHardwarePropertyDefaultInputDevice: + return noErr; + } return kAudioHardwareUnknownPropertyError; } @@ -128,3 +221,27 @@ OSStatus AudioHardwareImpl::removePropertyListener(const AudioObjectPropertyAddr { return kAudioHardwareUnknownPropertyError; } + +OSStatus AudioHardwareImpl::setBufferSize(uint32_t bufferSize) +{ + m_bufferSize = bufferSize; + return noErr; +} + +OSStatus AudioHardwareImpl::getCurrentTime(AudioTimeStamp* outTime) +{ + std::memset(outTime, 0, sizeof(*outTime)); + return noErr; +} + +OSStatus AudioHardwareImpl::translateTime(const AudioTimeStamp* inTime, AudioTimeStamp* outTime) +{ + *outTime = *inTime; + return noErr; +} + +OSStatus AudioHardwareImpl::getNearestStartTime(AudioTimeStamp* ioRequestedStartTime, UInt32 inFlags) +{ + std::memset(ioRequestedStartTime, 0, sizeof(*ioRequestedStartTime)); + return noErr; +} diff --git a/src/CoreAudio/CoreAudio/AudioHardwareImpl.h b/src/CoreAudio/CoreAudio/AudioHardwareImpl.h index acdd5c59b..a76bab88a 100644 --- a/src/CoreAudio/CoreAudio/AudioHardwareImpl.h +++ b/src/CoreAudio/CoreAudio/AudioHardwareImpl.h @@ -20,6 +20,7 @@ along with Darling. If not, see . #ifndef AUDIOHARDWAREIMPL_H #define AUDIOHARDWAREIMPL_H #include +#include #include #include #include "AudioHardwareStream.h" @@ -57,13 +58,17 @@ public: AudioTimeStamp* ioRequestedStartTime, UInt32 inFlags); virtual OSStatus stop(AudioDeviceIOProcID inProcID); - virtual OSStatus getCurrentTime(AudioTimeStamp* outTime) = 0; + virtual OSStatus getCurrentTime(AudioTimeStamp* outTime); virtual OSStatus translateTime(const AudioTimeStamp* inTime, - AudioTimeStamp* outTime) = 0; + AudioTimeStamp* outTime); virtual OSStatus getNearestStartTime(AudioTimeStamp* ioRequestedStartTime, - UInt32 inFlags) = 0; + UInt32 inFlags); + virtual OSStatus setBufferSize(uint32_t bufferSize); +private: + static OSStatus getPropertyCFString(CFStringRef str, UInt32* ioDataSize, void* outData); + static OSStatus getPropertyString(CFStringRef str, UInt32* ioDataSize, void* outData); protected: virtual AudioHardwareStream* createStream(AudioDeviceIOProcID procID) = 0; protected: @@ -72,6 +77,9 @@ protected: int m_nextProcId = 1; std::map> m_streams; + uint32_t m_bufferSize = 8192; + + CFStringRef m_name = CFSTR("unknown"), m_uid = CFSTR("unknown"), m_manufacturer = CFSTR("unknown"); }; #endif /* AUDIOHARDWAREIMPL_H */ diff --git a/src/CoreAudio/CoreAudio/AudioHardwareImplPA.cpp b/src/CoreAudio/CoreAudio/AudioHardwareImplPA.cpp new file mode 100644 index 000000000..ef54ebb8a --- /dev/null +++ b/src/CoreAudio/CoreAudio/AudioHardwareImplPA.cpp @@ -0,0 +1,98 @@ +/* +This file is part of Darling. + +Copyright (C) 2020 Lubos Dolezel + +Darling is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +Darling is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with Darling. If not, see . +*/ + +#include "AudioHardwareImplPA.h" + +AudioHardwareImplPA::AudioHardwareImplPA() +{ + m_name = CFSTR("PulseAudio"); + m_manufacturer = CFSTR("PulseAudio"); + m_uid = CFSTR("100"); +} + +OSStatus AudioHardwareImplPA::getPropertyData(const AudioObjectPropertyAddress* inAddress, UInt32 inQualifierDataSize, + const void* inQualifierData, UInt32* ioDataSize, void* outData) +{ + switch (inAddress->mSelector) + { + // BEGIN kAudioObjectSystemObject properties + case kAudioHardwarePropertyDefaultInputDevice: // returns AudioDeviceID + if (AudioDeviceID* devId = static_cast(outData); devId && *ioDataSize >= sizeof(AudioDeviceID)) + { + // We're doing a bit of an abuse here, which works only for PA where we have a single virtual device. + // For ALSA, we could do kAudioObjectSystemObject + INDEX of device. + *devId = kAudioObjectSystemObject; + } + *ioDataSize = sizeof(AudioDeviceID); + break; + case kAudioHardwarePropertyDefaultOutputDevice: // returns AudioDeviceID + if (AudioDeviceID* devId = static_cast(outData); devId && *ioDataSize >= sizeof(AudioDeviceID)) + { + *devId = kAudioObjectSystemObject; + } + *ioDataSize = sizeof(AudioDeviceID); + break; + case kAudioHardwarePropertyDevices: + { + if (AudioDeviceID* devId = static_cast(outData); devId && *ioDataSize >= sizeof(AudioDeviceID)) + { + devId[0] = kAudioObjectSystemObject; + } + *ioDataSize = sizeof(AudioDeviceID) * 1; + break; + } + // END kAudioObjectSystemObject properties + + // BEGIN properties of a specific audio device (in case of PA, it is kAudioObjectSystemObject as well) + case kAudioDevicePropertyStreamConfiguration: // returns AudioBufferList + { + const size_t size = sizeof(AudioBufferList) + 1* sizeof(AudioBuffer); + + // Number of returned buffers is the number of channels + // check inAddress->mScope. If it equals kAudioDevicePropertyScopeInput, the caller cares about input only. + if (AudioBufferList* abl = static_cast(outData); abl && *ioDataSize >= size) + { + abl->mNumberBuffers = 1; + abl->mBuffers[0].mNumberChannels = 2; + + // TODO: Is the below stuff ever used? How? + abl->mBuffers[0].mData = nullptr; + abl->mBuffers[0].mDataByteSize = 0; + } + + *ioDataSize = size; + break; + } + + } + + return AudioHardwareImpl::getPropertyData(inAddress, inQualifierDataSize, inQualifierData, ioDataSize, outData); +} + +OSStatus AudioHardwareImplPA::setPropertyData(const AudioObjectPropertyAddress* inAddress, UInt32 inQualifierDataSize, + const void* inQualifierData, UInt32 inDataSize, const void* inData) +{ + return AudioHardwareImpl::setPropertyData(inAddress, inQualifierDataSize, inQualifierData, inDataSize, inData); +} + +AudioHardwareStream* AudioHardwareImplPA::createStream(AudioDeviceIOProcID procID) +{ + // TODO + return nullptr; +} diff --git a/src/CoreAudio/CoreAudio/AudioHardwareImplPA.h b/src/CoreAudio/CoreAudio/AudioHardwareImplPA.h new file mode 100644 index 000000000..96ad63042 --- /dev/null +++ b/src/CoreAudio/CoreAudio/AudioHardwareImplPA.h @@ -0,0 +1,39 @@ +/* +This file is part of Darling. + +Copyright (C) 2020 Lubos Dolezel + +Darling is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +Darling is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with Darling. If not, see . +*/ + +#ifndef AUDIOHARDWAREIMPLPA_H +#define AUDIOHARDWAREIMPLPA_H +#include "AudioHardwareImpl.h" + +class AudioHardwareImplPA : public AudioHardwareImpl +{ +public: + AudioHardwareImplPA(); + + OSStatus getPropertyData(const AudioObjectPropertyAddress* inAddress, UInt32 inQualifierDataSize, + const void* inQualifierData, UInt32* ioDataSize, void* outData) override; + + OSStatus setPropertyData(const AudioObjectPropertyAddress* inAddress, UInt32 inQualifierDataSize, + const void* inQualifierData, UInt32 inDataSize, const void* inData) override; +protected: + AudioHardwareStream* createStream(AudioDeviceIOProcID procID) override; +}; + +#endif + diff --git a/src/CoreAudio/CoreAudio/CMakeLists.txt b/src/CoreAudio/CoreAudio/CMakeLists.txt index 10d3a60a6..a5e1a902c 100644 --- a/src/CoreAudio/CoreAudio/CMakeLists.txt +++ b/src/CoreAudio/CoreAudio/CMakeLists.txt @@ -2,9 +2,12 @@ project(CoreAudio) include_directories(BEFORE ${CMAKE_SOURCE_DIR}/src/external/libcxx/include ${CMAKE_CURRENT_BINARY_DIR}) +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++17") + set(coreaudio_sources AudioHardware.cpp - AudioHardwareImpl.cpp + AudioHardwareImpl.cpp + AudioHardwareImplPA.cpp AudioHardwareStream.cpp ) diff --git a/src/CoreAudio/include/CoreAudio/AudioHardware.h b/src/CoreAudio/include/CoreAudio/AudioHardware.h index b9f48a5c9..d7c9c8546 100644 --- a/src/CoreAudio/include/CoreAudio/AudioHardware.h +++ b/src/CoreAudio/include/CoreAudio/AudioHardware.h @@ -176,6 +176,7 @@ typedef AudioDeviceIOProc AudioDeviceIOProcID; OSStatus AudioDeviceCreateIOProcID(AudioObjectID inDevice, AudioDeviceIOProc inProc, void* inClientData, AudioDeviceIOProcID* outIOProcID); +OSStatus AudioDeviceAddIOProc(AudioDeviceID inDevice, AudioDeviceIOProc inProc, void *inClientData); #ifdef __BLOCKS__ @@ -191,6 +192,7 @@ OSStatus AudioDeviceCreateIOProcIDWithBlock(AudioDeviceIOProcID* outIOProcID, OSStatus AudioDeviceDestroyIOProcID(AudioObjectID inDevice, AudioDeviceIOProcID inIOProcID); +OSStatus AudioDeviceRemoveIOProc(AudioDeviceID inDevice, AudioDeviceIOProc inProc); OSStatus AudioDeviceStart(AudioObjectID inDevice, AudioDeviceIOProcID inProcID); @@ -208,6 +210,7 @@ struct AudioHardwareIOProcStreamUsage OSStatus AudioDeviceGetProperty(AudioDeviceID inDevice, UInt32 inChannel, Boolean isInput, AudioDevicePropertyID inPropertyID, UInt32* ioPropertyDataSize, void* outPropertyData); OSStatus AudioDeviceGetPropertyInfo(AudioDeviceID inDevice, UInt32 inChannel, Boolean isInput, AudioDevicePropertyID inPropertyID, UInt32* outSize, Boolean* outWritable); +OSStatus AudioDeviceSetProperty(AudioDeviceID inDevice, const AudioTimeStamp *inWhen, UInt32 inChannel, Boolean isInput, AudioDevicePropertyID inPropertyID, UInt32 inPropertyDataSize, const void *inPropertyData); OSStatus AudioDeviceGetCurrentTime(AudioObjectID inDevice, AudioTimeStamp* outTime); diff --git a/src/CoreAudio/include/CoreAudio/CoreAudioTypes.h b/src/CoreAudio/include/CoreAudio/CoreAudioTypes.h index e3f3d01b5..b5e9235e7 100644 --- a/src/CoreAudio/include/CoreAudio/CoreAudioTypes.h +++ b/src/CoreAudio/include/CoreAudio/CoreAudioTypes.h @@ -7,7 +7,7 @@ typedef Float32 AudioSampleType; typedef Float32 AudioUnitSampleType; -struct AudioStreamBasicDescription +typedef struct { Float64 mSampleRate; UInt32 mFormatID; @@ -18,43 +18,49 @@ struct AudioStreamBasicDescription UInt32 mChannelsPerFrame; UInt32 mBitsPerChannel; UInt32 mReserved; -}; +} AudioStreamBasicDescription; -struct AudioClassDescription +typedef struct { OSType mType; OSType mSubType; OSType mManufacturer; -}; +} AudioClassDescription; -struct AudioBuffer +typedef struct { UInt32 mNumberChannels; UInt32 mDataByteSize; void* mData; -}; +} AudioBuffer; -struct AudioBufferList +typedef struct { UInt32 mNumberBuffers; AudioBuffer mBuffers[1]; -}; +} AudioBufferList; -struct AudioStreamPacketDescription +typedef struct +{ + Float64 mMinimum; + Float64 mMaximum; +} AudioValueRange; + +typedef struct { SInt64 mStartOffset; UInt32 mVariableFramesInPacket; // 0 for constant streams UInt32 mDataByteSize; -}; +} AudioStreamPacketDescription; -struct SMPTETime +typedef struct { SInt64 mSubframes, mSubframeDivisor; UInt32 mCounter, mType, mFlags; SInt16 mHours, mMinutes, mSeconds, mFrames; -}; +} SMPTETime; -struct AudioTimeStamp +typedef struct { Float64 mSampleTime; UInt64 mHostTime; @@ -62,7 +68,7 @@ struct AudioTimeStamp UInt64 mWordClockTime; SMPTETime mSMPTETime; UInt32 mFlags, mReserved; -}; +} AudioTimeStamp; enum {