this repo has no description
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Progress on CoreAudio.framework

+490 -39
+97
cmake/FindFFmpeg.cmake
··· 1 + # - Try to find ffmpeg libraries (libavcodec, libavformat and libavutil) 2 + # Once done this will define 3 + # 4 + # FFMPEG_FOUND - system has ffmpeg or libav 5 + # FFMPEG_INCLUDE_DIR - the ffmpeg include directory 6 + # FFMPEG_LIBRARIES - Link these to use ffmpeg 7 + # FFMPEG_LIBAVCODEC 8 + # FFMPEG_LIBAVFORMAT 9 + # FFMPEG_LIBAVUTIL 10 + # 11 + # Copyright (c) 2008 Andreas Schneider <mail@cynapses.org> 12 + # Modified for other libraries by Lasse Kärkkäinen <tronic> 13 + # Modified for Hedgewars by Stepik777 14 + # Modified for FFmpeg-example Tuukka Pasanen 2018 15 + # 16 + # Redistribution and use is allowed according to the terms of the New 17 + # BSD license. 18 + # 19 + 20 + include(FindPackageHandleStandardArgs) 21 + 22 + if(FFMPEG_LIBRARIES AND FFMPEG_INCLUDE_DIR) 23 + # in cache already 24 + set(FFMPEG_FOUND TRUE) 25 + else() 26 + # use pkg-config to get the directories and then use these values 27 + # in the FIND_PATH() and FIND_LIBRARY() calls 28 + find_package(PkgConfig) 29 + if(PKG_CONFIG_FOUND) 30 + pkg_check_modules(_FFMPEG_AVCODEC libavcodec) 31 + pkg_check_modules(_FFMPEG_AVFORMAT libavformat) 32 + pkg_check_modules(_FFMPEG_AVUTIL libavutil) 33 + endif() 34 + 35 + find_path(FFMPEG_AVCODEC_INCLUDE_DIR 36 + NAMES libavcodec/avcodec.h 37 + PATHS ${_FFMPEG_AVCODEC_INCLUDE_DIRS} 38 + /usr/include 39 + /usr/local/include 40 + /opt/local/include 41 + /sw/include 42 + PATH_SUFFIXES ffmpeg libav) 43 + 44 + find_library(FFMPEG_LIBAVCODEC 45 + NAMES avcodec 46 + PATHS ${_FFMPEG_AVCODEC_LIBRARY_DIRS} 47 + /usr/lib 48 + /usr/local/lib 49 + /opt/local/lib 50 + /sw/lib) 51 + 52 + find_library(FFMPEG_LIBAVFORMAT 53 + NAMES avformat 54 + PATHS ${_FFMPEG_AVFORMAT_LIBRARY_DIRS} 55 + /usr/lib 56 + /usr/local/lib 57 + /opt/local/lib 58 + /sw/lib) 59 + 60 + find_library(FFMPEG_LIBAVUTIL 61 + NAMES avutil 62 + PATHS ${_FFMPEG_AVUTIL_LIBRARY_DIRS} 63 + /usr/lib 64 + /usr/local/lib 65 + /opt/local/lib 66 + /sw/lib) 67 + 68 + if(FFMPEG_LIBAVCODEC AND FFMPEG_LIBAVFORMAT) 69 + set(FFMPEG_FOUND TRUE) 70 + endif() 71 + 72 + if(FFMPEG_FOUND) 73 + set(FFMPEG_INCLUDE_DIR ${FFMPEG_AVCODEC_INCLUDE_DIR}) 74 + set(FFMPEG_LIBRARIES 75 + ${FFMPEG_LIBAVCODEC} 76 + ${FFMPEG_LIBAVFORMAT} 77 + ${FFMPEG_LIBAVUTIL}) 78 + endif() 79 + 80 + if(FFMPEG_FOUND) 81 + if(NOT FFMPEG_FIND_QUIETLY) 82 + message(STATUS 83 + "Found FFMPEG or Libav: ${FFMPEG_LIBRARIES}, ${FFMPEG_INCLUDE_DIR}") 84 + endif() 85 + else() 86 + message(FATAL_ERROR 87 + "Could not find libavcodec or libavformat or libavutil") 88 + endif() 89 + endif() 90 + 91 + find_package_handle_standard_args(FFMPEG 92 + FOUND_VAR FFMPEG_FOUND 93 + REQUIRED_VARS 94 + FFMPEG_LIBRARIES 95 + FFMPEG_INCLUDE_DIR 96 + VERSION_VAR FFMPEG_VERSION 97 + )
+18
cmake/FindPulseAudio.cmake
··· 1 + 2 + include(FindPackageHandleStandardArgs) 3 + 4 + find_path(PULSEAUDIO_INCLUDE_DIRS 5 + NAMES pulse/pulseaudio.h 6 + DOC "PulseAudio include directory" 7 + ) 8 + 9 + find_library(PULSEAUDIO_LIBRARIES 10 + NAMES pulse 11 + DOC "PulseAudio library" 12 + ) 13 + 14 + find_package_handle_standard_args(PulseAudio 15 + REQUIRED_VARS PULSEAUDIO_LIBRARIES PULSEAUDIO_INCLUDE_DIRS VERSION_VAR PULSEAUDIO_VERSION 16 + FAIL_MESSAGE "Could NOT find PulseAudio!") 17 + 18 + mark_as_advanced(PULSEAUDIO_INCLUDE_DIRS PULSEAUDIO_LIBRARIES)
+77 -15
src/CoreAudio/CoreAudio/AudioHardware.cpp
··· 19 19 20 20 #include <CoreAudio/AudioHardware.h> 21 21 #include "AudioHardwareImpl.h" 22 + #include "AudioHardwareImplPA.h" 22 23 #include <CoreServices/MacErrors.h> 24 + #include <dispatch/dispatch.h> 23 25 #include <memory> 24 26 #include "stub.h" 25 27 ··· 27 29 28 30 static AudioHardwareImpl* GetSystemObject() 29 31 { 30 - if (!g_systemObject) 31 - { 32 - static std::mutex singleLock; 33 - singleLock.lock(); 34 - 35 - if (!g_systemObject) 36 - g_systemObject.reset(nullptr); // TODO: create ALSA or PA here 37 - 38 - singleLock.unlock(); 39 - } 32 + static dispatch_once_t once; 33 + dispatch_once(&once, ^{ 34 + // TODO: Or ALSA 35 + g_systemObject.reset(new AudioHardwareImplPA); 36 + }); 40 37 41 38 return g_systemObject.get(); 42 39 } ··· 45 42 { 46 43 if (objID == kAudioObjectSystemObject) 47 44 return GetSystemObject(); 45 + 46 + // TODO: For ALSA, support more objects for every device 48 47 49 48 return nullptr; 50 49 } ··· 136 135 137 136 OSStatus AudioHardwareUnload(void) 138 137 { 139 - g_systemObject.reset(nullptr); 140 138 return noErr; 141 139 } 142 140 ··· 157 155 158 156 OSStatus AudioHardwareGetProperty(AudioHardwarePropertyID inPropId, UInt32* ioPropertyDataSize, void* outPropertyData) 159 157 { 160 - STUB(); 161 - return unimpErr; 158 + if (!ioPropertyDataSize) 159 + return paramErr; 160 + 161 + return AudioDeviceGetProperty(kAudioObjectSystemObject, 0, false, inPropId, ioPropertyDataSize, outPropertyData); 162 + } 163 + 164 + OSStatus AudioDeviceGetProperty(AudioDeviceID inDevice, UInt32 inChannel, Boolean isInput, AudioDevicePropertyID inPropertyID, UInt32* ioPropertyDataSize, void* outPropertyData) 165 + { 166 + AudioObjectPropertyAddress aopa = { 167 + inPropertyID, 168 + kAudioObjectPropertyScopeGlobal, 169 + kAudioObjectPropertyElementMaster 170 + }; 171 + 172 + return AudioObjectGetPropertyData(inDevice, &aopa, 0, nullptr, ioPropertyDataSize, outPropertyData); 173 + } 174 + 175 + OSStatus AudioDeviceGetPropertyInfo(AudioDeviceID inDevice, UInt32 inChannel, Boolean isInput, AudioDevicePropertyID inPropertyID, UInt32* outSize, Boolean* outWritable) 176 + { 177 + AudioObjectPropertyAddress aopa = { 178 + inPropertyID, 179 + kAudioObjectPropertyScopeGlobal, 180 + kAudioObjectPropertyElementMaster 181 + }; 182 + 183 + OSStatus status; 184 + if (outSize) 185 + { 186 + status = AudioObjectGetPropertyDataSize(inDevice, &aopa, 0, nullptr, outSize); 187 + if (status != noErr) 188 + return status; 189 + } 190 + 191 + if (outWritable) 192 + { 193 + status = AudioObjectIsPropertySettable(inDevice, &aopa, outWritable); 194 + } 195 + return status; 196 + } 197 + 198 + OSStatus AudioDeviceSetProperty(AudioDeviceID inDevice, const AudioTimeStamp *inWhen, UInt32 inChannel, 199 + Boolean isInput, AudioDevicePropertyID inPropertyID, UInt32 inPropertyDataSize, const void *inPropertyData) 200 + { 201 + AudioObjectPropertyAddress aopa = { 202 + inPropertyID, 203 + kAudioObjectPropertyScopeGlobal, 204 + kAudioObjectPropertyElementMaster 205 + }; 206 + 207 + return AudioObjectSetPropertyData(inDevice, &aopa, 0, nullptr, inPropertyDataSize, inPropertyData); 162 208 } 163 209 164 210 OSStatus AudioHardwareGetPropertyInfo(AudioHardwarePropertyID inPropertyID, UInt32 *outSize, Boolean *outWritable) 165 211 { 166 - STUB(); 167 - return unimpErr; 212 + return AudioDeviceGetPropertyInfo(kAudioObjectSystemObject, 0, false, inPropertyID, outSize, outWritable); 168 213 } 169 214 170 215 OSStatus AudioDeviceCreateIOProcID(AudioObjectID inDevice, ··· 178 223 return obj->createIOProcID(inProc, inClientData, outIOProcID); 179 224 } 180 225 226 + OSStatus AudioDeviceAddIOProc(AudioDeviceID inDevice, AudioDeviceIOProc inProc, void *inClientData) 227 + { 228 + AudioHardwareImpl* obj = GetObject(inDevice); 229 + if (!obj) 230 + return kAudioHardwareBadObjectError; 231 + return obj->createIOProcID(inProc, inClientData, nullptr); 232 + } 233 + 181 234 OSStatus AudioDeviceDestroyIOProcID(AudioObjectID inDevice, 182 235 AudioDeviceIOProcID inIOProcID) 183 236 { ··· 186 239 return kAudioHardwareBadObjectError; 187 240 188 241 return obj->destroyIOProcID(inIOProcID); 242 + } 243 + 244 + OSStatus AudioDeviceRemoveIOProc(AudioDeviceID inDevice, AudioDeviceIOProc inProc) 245 + { 246 + AudioHardwareImpl* obj = GetObject(inDevice); 247 + if (!obj) 248 + return kAudioHardwareBadObjectError; 249 + 250 + return obj->destroyIOProcID(AudioDeviceIOProcID(inProc)); 189 251 } 190 252 191 253 OSStatus AudioDeviceStart(AudioObjectID inDevice, AudioDeviceIOProcID inProcID)
+123 -6
src/CoreAudio/CoreAudio/AudioHardwareImpl.cpp
··· 1 1 /* 2 2 This file is part of Darling. 3 3 4 - Copyright (C) 2015-2016 Lubos Dolezel 4 + Copyright (C) 2015-2020 Lubos Dolezel 5 5 6 6 Darling is free software: you can redistribute it and/or modify 7 7 it under the terms of the GNU General Public License as published by ··· 20 20 #include "AudioHardwareImpl.h" 21 21 #include <typeinfo> 22 22 #include <iostream> 23 + #include <cstring> 23 24 #include <CoreServices/MacErrors.h> 24 25 25 26 AudioHardwareImpl::AudioHardwareImpl() ··· 41 42 { 42 43 std::lock_guard<std::mutex> guard(m_procMutex); 43 44 44 - if (!outIOProcID || !inProc) 45 + if (!inProc) 45 46 return paramErr; 46 47 47 - *outIOProcID = reinterpret_cast<AudioDeviceIOProcID>(m_nextProcId++); 48 - m_proc[*outIOProcID] = std::make_pair(inProc, inClientData); 48 + AudioDeviceIOProcID procId; 49 + if (outIOProcID) 50 + *outIOProcID = procId = reinterpret_cast<AudioDeviceIOProcID>(m_nextProcId++); 51 + else 52 + procId = inProc; 53 + 54 + m_proc[procId] = std::make_pair(inProc, inClientData); 49 55 50 56 return noErr; 51 57 } ··· 71 77 return paramErr; 72 78 73 79 stream = createStream(inProcID); 80 + if (!stream) 81 + return kAudioHardwareBadStreamError; 74 82 m_streams.emplace(std::make_pair(inProcID, std::unique_ptr<AudioHardwareStream>(stream))); 75 83 76 84 // TODO: time ··· 90 98 91 99 bool AudioHardwareImpl::hasProperty(const AudioObjectPropertyAddress* address) 92 100 { 93 - return false; 101 + UInt32 ds; 102 + OSStatus status = getPropertyDataSize(address, 0, nullptr, &ds); 103 + return status != kAudioHardwareUnknownPropertyError; 94 104 } 95 105 96 106 OSStatus AudioHardwareImpl::getPropertyDataSize(const AudioObjectPropertyAddress* inAddress, UInt32 inQualifierDataSize, 97 107 const void* inQualifierData, UInt32* outDataSize) 98 108 { 99 - return kAudioHardwareUnknownPropertyError; 109 + return getPropertyData(inAddress, inQualifierDataSize, inQualifierData, outDataSize, nullptr); 100 110 } 101 111 102 112 OSStatus AudioHardwareImpl::isPropertySettable(const AudioObjectPropertyAddress* inAddress, Boolean* outIsSettable) ··· 105 115 return kAudioHardwareUnknownPropertyError; 106 116 } 107 117 118 + // Examples: 119 + // https://gist.github.com/robotconscience/490ee50d8ad75b47ea1f 120 + // https://gist.github.com/hpux735/2913436 121 + 108 122 OSStatus AudioHardwareImpl::getPropertyData(const AudioObjectPropertyAddress* inAddress, UInt32 inQualifierDataSize, 109 123 const void* inQualifierData, UInt32* ioDataSize, void* outData) 110 124 { 125 + switch (inAddress->mSelector) 126 + { 127 + case kAudioDevicePropertyStreamFormat: // returns AudioStreamBasicDescription 128 + { 129 + if (AudioStreamBasicDescription* asbd = static_cast<AudioStreamBasicDescription*>(outData); asbd && *ioDataSize >= sizeof(AudioStreamBasicDescription)) 130 + { 131 + // These are standard values macOS applications have learned to expect 132 + asbd->mChannelsPerFrame = 2; 133 + asbd->mSampleRate = 44100; 134 + asbd->mBitsPerChannel = 32; 135 + asbd->mFormatID = kAudioFormatLinearPCM; 136 + asbd->mFormatFlags = kLinearPCMFormatFlagIsFloat; 137 + asbd->mFramesPerPacket = 1; 138 + asbd->mBytesPerFrame = UInt32(asbd->mBytesPerPacket = asbd->mChannelsPerFrame * asbd->mSampleRate * asbd->mBitsPerChannel / 8); 139 + } 140 + *ioDataSize = sizeof(AudioStreamBasicDescription); 141 + return noErr; 142 + } 143 + case kAudioDevicePropertyDeviceManufacturer: 144 + return getPropertyString(m_manufacturer, ioDataSize, outData); 145 + case kAudioDevicePropertyDeviceManufacturerCFString: 146 + return getPropertyCFString(m_manufacturer, ioDataSize, outData); 147 + case kAudioDevicePropertyDeviceUID: // returns CFStringRef 148 + return getPropertyCFString(m_uid, ioDataSize, outData); 149 + case kAudioDevicePropertyDeviceNameCFString: 150 + return getPropertyCFString(m_name, ioDataSize, outData); 151 + case kAudioDevicePropertyDeviceName: // return char[] 152 + return getPropertyString(m_name, ioDataSize, outData); 153 + case kAudioDevicePropertyNominalSampleRate: // Float64 154 + { 155 + if (Float64* flt = static_cast<Float64*>(outData); flt && *ioDataSize >= sizeof(Float64)) 156 + *flt = 44100; 157 + 158 + *ioDataSize = sizeof(Float64); 159 + return noErr; 160 + } 161 + case kAudioDevicePropertyAvailableNominalSampleRates: // AudioValueRange[] 162 + { 163 + if (AudioValueRange* avr = static_cast<AudioValueRange*>(outData); avr && *ioDataSize >= sizeof(AudioValueRange)*1) 164 + { 165 + avr->mMinimum = 44100; 166 + avr->mMaximum = 44100; 167 + } 168 + *ioDataSize = sizeof(AudioValueRange) * 1; 169 + return noErr; 170 + } 171 + 172 + } 111 173 return kAudioHardwareUnknownPropertyError; 112 174 } 113 175 176 + OSStatus AudioHardwareImpl::getPropertyCFString(CFStringRef str, UInt32* ioDataSize, void* outData) 177 + { 178 + if (CFStringRef* ref = static_cast<CFStringRef*>(outData); ref && *ioDataSize >= sizeof(CFStringRef)) 179 + { 180 + *ref = str; 181 + } 182 + *ioDataSize = sizeof(CFStringRef); 183 + return noErr; 184 + } 185 + 186 + OSStatus AudioHardwareImpl::getPropertyString(CFStringRef str, UInt32* ioDataSize, void* outData) 187 + { 188 + const char* cstr = CFStringGetCStringPtr(str, kCFStringEncodingUTF8); 189 + if (char* target = static_cast<char*>(outData)) 190 + strlcpy(target, cstr, *ioDataSize); 191 + *ioDataSize = strlen(cstr) + 1; 192 + return noErr; 193 + } 194 + 114 195 OSStatus AudioHardwareImpl::setPropertyData(const AudioObjectPropertyAddress* inAddress, UInt32 inQualifierDataSize, 115 196 const void* inQualifierData, UInt32 inDataSize, const void* inData) 116 197 { 198 + switch (inAddress->mSelector) 199 + { 200 + case kAudioDevicePropertyBufferSize: 201 + { 202 + return setBufferSize(*static_cast<const uint32_t*>(inData)); 203 + } 204 + // These make sense only for ALSA, but I find it ridiculous that these properties can be set... 205 + case kAudioHardwarePropertyDefaultOutputDevice: 206 + return noErr; 207 + case kAudioHardwarePropertyDefaultInputDevice: 208 + return noErr; 209 + } 117 210 return kAudioHardwareUnknownPropertyError; 118 211 } 119 212 ··· 128 221 { 129 222 return kAudioHardwareUnknownPropertyError; 130 223 } 224 + 225 + OSStatus AudioHardwareImpl::setBufferSize(uint32_t bufferSize) 226 + { 227 + m_bufferSize = bufferSize; 228 + return noErr; 229 + } 230 + 231 + OSStatus AudioHardwareImpl::getCurrentTime(AudioTimeStamp* outTime) 232 + { 233 + std::memset(outTime, 0, sizeof(*outTime)); 234 + return noErr; 235 + } 236 + 237 + OSStatus AudioHardwareImpl::translateTime(const AudioTimeStamp* inTime, AudioTimeStamp* outTime) 238 + { 239 + *outTime = *inTime; 240 + return noErr; 241 + } 242 + 243 + OSStatus AudioHardwareImpl::getNearestStartTime(AudioTimeStamp* ioRequestedStartTime, UInt32 inFlags) 244 + { 245 + std::memset(ioRequestedStartTime, 0, sizeof(*ioRequestedStartTime)); 246 + return noErr; 247 + }
+11 -3
src/CoreAudio/CoreAudio/AudioHardwareImpl.h
··· 20 20 #ifndef AUDIOHARDWAREIMPL_H 21 21 #define AUDIOHARDWAREIMPL_H 22 22 #include <CoreAudio/AudioHardware.h> 23 + #include <CoreFoundation/CFString.h> 23 24 #include <map> 24 25 #include <mutex> 25 26 #include "AudioHardwareStream.h" ··· 57 58 AudioTimeStamp* ioRequestedStartTime, UInt32 inFlags); 58 59 virtual OSStatus stop(AudioDeviceIOProcID inProcID); 59 60 60 - virtual OSStatus getCurrentTime(AudioTimeStamp* outTime) = 0; 61 + virtual OSStatus getCurrentTime(AudioTimeStamp* outTime); 61 62 62 63 virtual OSStatus translateTime(const AudioTimeStamp* inTime, 63 - AudioTimeStamp* outTime) = 0; 64 + AudioTimeStamp* outTime); 64 65 65 66 virtual OSStatus getNearestStartTime(AudioTimeStamp* ioRequestedStartTime, 66 - UInt32 inFlags) = 0; 67 + UInt32 inFlags); 68 + virtual OSStatus setBufferSize(uint32_t bufferSize); 69 + private: 70 + static OSStatus getPropertyCFString(CFStringRef str, UInt32* ioDataSize, void* outData); 71 + static OSStatus getPropertyString(CFStringRef str, UInt32* ioDataSize, void* outData); 67 72 protected: 68 73 virtual AudioHardwareStream* createStream(AudioDeviceIOProcID procID) = 0; 69 74 protected: ··· 72 77 int m_nextProcId = 1; 73 78 74 79 std::map<AudioDeviceIOProcID, std::unique_ptr<AudioHardwareStream>> m_streams; 80 + uint32_t m_bufferSize = 8192; 81 + 82 + CFStringRef m_name = CFSTR("unknown"), m_uid = CFSTR("unknown"), m_manufacturer = CFSTR("unknown"); 75 83 }; 76 84 77 85 #endif /* AUDIOHARDWAREIMPL_H */
+98
src/CoreAudio/CoreAudio/AudioHardwareImplPA.cpp
··· 1 + /* 2 + This file is part of Darling. 3 + 4 + Copyright (C) 2020 Lubos Dolezel 5 + 6 + Darling is free software: you can redistribute it and/or modify 7 + it under the terms of the GNU General Public License as published by 8 + the Free Software Foundation, either version 3 of the License, or 9 + (at your option) any later version. 10 + 11 + Darling is distributed in the hope that it will be useful, 12 + but WITHOUT ANY WARRANTY; without even the implied warranty of 13 + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 + GNU General Public License for more details. 15 + 16 + You should have received a copy of the GNU General Public License 17 + along with Darling. If not, see <http://www.gnu.org/licenses/>. 18 + */ 19 + 20 + #include "AudioHardwareImplPA.h" 21 + 22 + AudioHardwareImplPA::AudioHardwareImplPA() 23 + { 24 + m_name = CFSTR("PulseAudio"); 25 + m_manufacturer = CFSTR("PulseAudio"); 26 + m_uid = CFSTR("100"); 27 + } 28 + 29 + OSStatus AudioHardwareImplPA::getPropertyData(const AudioObjectPropertyAddress* inAddress, UInt32 inQualifierDataSize, 30 + const void* inQualifierData, UInt32* ioDataSize, void* outData) 31 + { 32 + switch (inAddress->mSelector) 33 + { 34 + // BEGIN kAudioObjectSystemObject properties 35 + case kAudioHardwarePropertyDefaultInputDevice: // returns AudioDeviceID 36 + if (AudioDeviceID* devId = static_cast<AudioDeviceID*>(outData); devId && *ioDataSize >= sizeof(AudioDeviceID)) 37 + { 38 + // We're doing a bit of an abuse here, which works only for PA where we have a single virtual device. 39 + // For ALSA, we could do kAudioObjectSystemObject + INDEX of device. 40 + *devId = kAudioObjectSystemObject; 41 + } 42 + *ioDataSize = sizeof(AudioDeviceID); 43 + break; 44 + case kAudioHardwarePropertyDefaultOutputDevice: // returns AudioDeviceID 45 + if (AudioDeviceID* devId = static_cast<AudioDeviceID*>(outData); devId && *ioDataSize >= sizeof(AudioDeviceID)) 46 + { 47 + *devId = kAudioObjectSystemObject; 48 + } 49 + *ioDataSize = sizeof(AudioDeviceID); 50 + break; 51 + case kAudioHardwarePropertyDevices: 52 + { 53 + if (AudioDeviceID* devId = static_cast<AudioDeviceID*>(outData); devId && *ioDataSize >= sizeof(AudioDeviceID)) 54 + { 55 + devId[0] = kAudioObjectSystemObject; 56 + } 57 + *ioDataSize = sizeof(AudioDeviceID) * 1; 58 + break; 59 + } 60 + // END kAudioObjectSystemObject properties 61 + 62 + // BEGIN properties of a specific audio device (in case of PA, it is kAudioObjectSystemObject as well) 63 + case kAudioDevicePropertyStreamConfiguration: // returns AudioBufferList 64 + { 65 + const size_t size = sizeof(AudioBufferList) + 1* sizeof(AudioBuffer); 66 + 67 + // Number of returned buffers is the number of channels 68 + // check inAddress->mScope. If it equals kAudioDevicePropertyScopeInput, the caller cares about input only. 69 + if (AudioBufferList* abl = static_cast<AudioBufferList*>(outData); abl && *ioDataSize >= size) 70 + { 71 + abl->mNumberBuffers = 1; 72 + abl->mBuffers[0].mNumberChannels = 2; 73 + 74 + // TODO: Is the below stuff ever used? How? 75 + abl->mBuffers[0].mData = nullptr; 76 + abl->mBuffers[0].mDataByteSize = 0; 77 + } 78 + 79 + *ioDataSize = size; 80 + break; 81 + } 82 + 83 + } 84 + 85 + return AudioHardwareImpl::getPropertyData(inAddress, inQualifierDataSize, inQualifierData, ioDataSize, outData); 86 + } 87 + 88 + OSStatus AudioHardwareImplPA::setPropertyData(const AudioObjectPropertyAddress* inAddress, UInt32 inQualifierDataSize, 89 + const void* inQualifierData, UInt32 inDataSize, const void* inData) 90 + { 91 + return AudioHardwareImpl::setPropertyData(inAddress, inQualifierDataSize, inQualifierData, inDataSize, inData); 92 + } 93 + 94 + AudioHardwareStream* AudioHardwareImplPA::createStream(AudioDeviceIOProcID procID) 95 + { 96 + // TODO 97 + return nullptr; 98 + }
+39
src/CoreAudio/CoreAudio/AudioHardwareImplPA.h
··· 1 + /* 2 + This file is part of Darling. 3 + 4 + Copyright (C) 2020 Lubos Dolezel 5 + 6 + Darling is free software: you can redistribute it and/or modify 7 + it under the terms of the GNU General Public License as published by 8 + the Free Software Foundation, either version 3 of the License, or 9 + (at your option) any later version. 10 + 11 + Darling is distributed in the hope that it will be useful, 12 + but WITHOUT ANY WARRANTY; without even the implied warranty of 13 + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 + GNU General Public License for more details. 15 + 16 + You should have received a copy of the GNU General Public License 17 + along with Darling. If not, see <http://www.gnu.org/licenses/>. 18 + */ 19 + 20 + #ifndef AUDIOHARDWAREIMPLPA_H 21 + #define AUDIOHARDWAREIMPLPA_H 22 + #include "AudioHardwareImpl.h" 23 + 24 + class AudioHardwareImplPA : public AudioHardwareImpl 25 + { 26 + public: 27 + AudioHardwareImplPA(); 28 + 29 + OSStatus getPropertyData(const AudioObjectPropertyAddress* inAddress, UInt32 inQualifierDataSize, 30 + const void* inQualifierData, UInt32* ioDataSize, void* outData) override; 31 + 32 + OSStatus setPropertyData(const AudioObjectPropertyAddress* inAddress, UInt32 inQualifierDataSize, 33 + const void* inQualifierData, UInt32 inDataSize, const void* inData) override; 34 + protected: 35 + AudioHardwareStream* createStream(AudioDeviceIOProcID procID) override; 36 + }; 37 + 38 + #endif 39 +
+4 -1
src/CoreAudio/CoreAudio/CMakeLists.txt
··· 2 2 3 3 include_directories(BEFORE ${CMAKE_SOURCE_DIR}/src/external/libcxx/include ${CMAKE_CURRENT_BINARY_DIR}) 4 4 5 + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++17") 6 + 5 7 set(coreaudio_sources 6 8 AudioHardware.cpp 7 - AudioHardwareImpl.cpp 9 + AudioHardwareImpl.cpp 10 + AudioHardwareImplPA.cpp 8 11 AudioHardwareStream.cpp 9 12 ) 10 13
+3
src/CoreAudio/include/CoreAudio/AudioHardware.h
··· 176 176 OSStatus AudioDeviceCreateIOProcID(AudioObjectID inDevice, 177 177 AudioDeviceIOProc inProc, void* inClientData, 178 178 AudioDeviceIOProcID* outIOProcID); 179 + OSStatus AudioDeviceAddIOProc(AudioDeviceID inDevice, AudioDeviceIOProc inProc, void *inClientData); 179 180 180 181 #ifdef __BLOCKS__ 181 182 ··· 191 192 192 193 OSStatus AudioDeviceDestroyIOProcID(AudioObjectID inDevice, 193 194 AudioDeviceIOProcID inIOProcID); 195 + OSStatus AudioDeviceRemoveIOProc(AudioDeviceID inDevice, AudioDeviceIOProc inProc); 194 196 195 197 OSStatus AudioDeviceStart(AudioObjectID inDevice, AudioDeviceIOProcID inProcID); 196 198 ··· 208 210 209 211 OSStatus AudioDeviceGetProperty(AudioDeviceID inDevice, UInt32 inChannel, Boolean isInput, AudioDevicePropertyID inPropertyID, UInt32* ioPropertyDataSize, void* outPropertyData); 210 212 OSStatus AudioDeviceGetPropertyInfo(AudioDeviceID inDevice, UInt32 inChannel, Boolean isInput, AudioDevicePropertyID inPropertyID, UInt32* outSize, Boolean* outWritable); 213 + OSStatus AudioDeviceSetProperty(AudioDeviceID inDevice, const AudioTimeStamp *inWhen, UInt32 inChannel, Boolean isInput, AudioDevicePropertyID inPropertyID, UInt32 inPropertyDataSize, const void *inPropertyData); 211 214 212 215 OSStatus AudioDeviceGetCurrentTime(AudioObjectID inDevice, AudioTimeStamp* outTime); 213 216
+20 -14
src/CoreAudio/include/CoreAudio/CoreAudioTypes.h
··· 7 7 typedef Float32 AudioSampleType; 8 8 typedef Float32 AudioUnitSampleType; 9 9 10 - struct AudioStreamBasicDescription 10 + typedef struct 11 11 { 12 12 Float64 mSampleRate; 13 13 UInt32 mFormatID; ··· 18 18 UInt32 mChannelsPerFrame; 19 19 UInt32 mBitsPerChannel; 20 20 UInt32 mReserved; 21 - }; 21 + } AudioStreamBasicDescription; 22 22 23 - struct AudioClassDescription 23 + typedef struct 24 24 { 25 25 OSType mType; 26 26 OSType mSubType; 27 27 OSType mManufacturer; 28 - }; 28 + } AudioClassDescription; 29 29 30 - struct AudioBuffer 30 + typedef struct 31 31 { 32 32 UInt32 mNumberChannels; 33 33 UInt32 mDataByteSize; 34 34 void* mData; 35 - }; 35 + } AudioBuffer; 36 36 37 - struct AudioBufferList 37 + typedef struct 38 38 { 39 39 UInt32 mNumberBuffers; 40 40 AudioBuffer mBuffers[1]; 41 - }; 41 + } AudioBufferList; 42 42 43 - struct AudioStreamPacketDescription 43 + typedef struct 44 + { 45 + Float64 mMinimum; 46 + Float64 mMaximum; 47 + } AudioValueRange; 48 + 49 + typedef struct 44 50 { 45 51 SInt64 mStartOffset; 46 52 UInt32 mVariableFramesInPacket; // 0 for constant streams 47 53 UInt32 mDataByteSize; 48 - }; 54 + } AudioStreamPacketDescription; 49 55 50 - struct SMPTETime 56 + typedef struct 51 57 { 52 58 SInt64 mSubframes, mSubframeDivisor; 53 59 UInt32 mCounter, mType, mFlags; 54 60 SInt16 mHours, mMinutes, mSeconds, mFrames; 55 - }; 61 + } SMPTETime; 56 62 57 - struct AudioTimeStamp 63 + typedef struct 58 64 { 59 65 Float64 mSampleTime; 60 66 UInt64 mHostTime; ··· 62 68 UInt64 mWordClockTime; 63 69 SMPTETime mSMPTETime; 64 70 UInt32 mFlags, mReserved; 65 - }; 71 + } AudioTimeStamp; 66 72 67 73 enum 68 74 {