this repo has no description
1
fork

Configure Feed

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

AudioToolbox: Some work around AudioFileComponents

+412 -10
+165 -1
src/CoreAudio/AudioToolbox/AudioFile.cpp
··· 19 19 20 20 #include <AudioToolbox/AudioFile.h> 21 21 #include <CoreServices/MacErrors.h> 22 + #include "AudioFileFormatManager.h" 22 23 23 24 OSStatus AudioFileCreateWithURL (CFURLRef inFileRef, 24 25 AudioFileTypeID inFileType, ··· 193 194 void * _Nullable inSpecifier, 194 195 UInt32 *outDataSize) 195 196 { 196 - return unimpErr; 197 + return AudioFileGetGlobalInfo(inPropertyID, inSpecifierSize, inSpecifier, outDataSize, nullptr); 198 + } 199 + 200 + static void writeUInt32Set(const std::set<UInt32>& set, void *outPropertyData) 201 + { 202 + if (outPropertyData) 203 + { 204 + UInt32* out = static_cast<UInt32*>(outPropertyData); 205 + int i = 0; 206 + for (UInt32 v : set) 207 + out[i++] = v; 208 + } 209 + } 210 + 211 + template <typename ContainerType> 212 + CFArrayRef stringContainerToArray(const ContainerType& t) 213 + { 214 + std::unique_ptr<CFStringRef[]> ptrs(new CFStringRef[t.size()]); 215 + int i = 0; 216 + 217 + for (const std::string& str : t) 218 + ptrs[i++] = CFStringCreateWithCString(nullptr, str.c_str(), kCFStringEncodingUTF8); 219 + 220 + CFArrayRef rv = CFArrayCreate(nullptr, (const void**) ptrs.get(), t.size(), &kCFTypeArrayCallBacks); 221 + 222 + for (int i = 0; i < t.size(); i++) 223 + CFRelease(ptrs[i]); 224 + return rv; 197 225 } 198 226 199 227 OSStatus AudioFileGetGlobalInfo( AudioFilePropertyID inPropertyID, ··· 202 230 UInt32 *ioDataSize, 203 231 void *outPropertyData) 204 232 { 233 + switch (inPropertyID) 234 + { 235 + case kAudioFileGlobalInfo_ReadableTypes: 236 + case kAudioFileGlobalInfo_WritableTypes: 237 + { 238 + std::set<UInt32> types = AudioFileFormatManager::instance()->types(inPropertyID == kAudioFileGlobalInfo_WritableTypes); 239 + 240 + *ioDataSize = types.size() * sizeof(UInt32); 241 + writeUInt32Set(types, outPropertyData); 242 + 243 + return noErr; 244 + } 245 + case kAudioFileGlobalInfo_FileTypeName: 246 + { 247 + const UInt32* fileType = static_cast<const UInt32*>(inSpecifier); 248 + if (inSpecifierSize != sizeof(*fileType)) 249 + return kAudioFileBadPropertySizeError; 250 + 251 + const AudioFileFormatManager::ComponentInfo* ci; 252 + 253 + ci = AudioFileFormatManager::instance()->fileType(*fileType); 254 + if (!ci) 255 + return kAudioFileUnsupportedFileTypeError; 256 + 257 + CFStringRef* out = static_cast<CFStringRef*>(outPropertyData); 258 + *ioDataSize = sizeof(*out); 259 + 260 + if (out) 261 + *out = CFStringCreateWithCString(nullptr, ci->name.c_str(), kCFStringEncodingUTF8); 262 + 263 + return noErr; 264 + } 265 + case kAudioFileGlobalInfo_AvailableStreamDescriptionsForFormat: 266 + { 267 + const AudioFileTypeAndFormatID* spec = static_cast<const AudioFileTypeAndFormatID*>(inSpecifier); 268 + if (inSpecifierSize != sizeof(*spec)) 269 + return kAudioFileBadPropertySizeError; 270 + break; 271 + } 272 + case kAudioFileGlobalInfo_AvailableFormatIDs: 273 + { 274 + const UInt32* fileType = static_cast<const UInt32*>(inSpecifier); 275 + if (inSpecifierSize != sizeof(*fileType)) 276 + return kAudioFileBadPropertySizeError; 277 + 278 + auto set = AudioFileFormatManager::instance()->availableFormatIDs(*fileType); 279 + *ioDataSize = set.size() * sizeof(UInt32); 280 + 281 + writeUInt32Set(set, outPropertyData); 282 + 283 + return noErr; 284 + } 285 + case kAudioFileGlobalInfo_AllHFSTypeCodes: 286 + case kAudioFileGlobalInfo_HFSTypeCodesForType: 287 + case kAudioFileGlobalInfo_TypesForHFSTypeCode: 288 + *ioDataSize = 0; 289 + return noErr; 290 + case kAudioFileGlobalInfo_AllExtensions: 291 + case kAudioFileGlobalInfo_AllUTIs: 292 + case kAudioFileGlobalInfo_AllMIMETypes: 293 + { 294 + *ioDataSize = sizeof(CFArrayRef); 295 + 296 + if (outPropertyData) 297 + { 298 + std::set<std::string> set; 299 + AudioFileFormatManager* mgr = AudioFileFormatManager::instance(); 300 + 301 + if (inPropertyID == kAudioFileGlobalInfo_AllExtensions) 302 + set = mgr->allExtensions(); 303 + else if (inPropertyID == kAudioFileGlobalInfo_AllUTIs) 304 + set = mgr->allUTIs(); 305 + else if (inPropertyID == kAudioFileGlobalInfo_AllMIMETypes) 306 + set = mgr->allMIMEs(); 307 + 308 + *((CFArrayRef*)outPropertyData) = stringContainerToArray(set); 309 + } 310 + 311 + return noErr; 312 + } 313 + case kAudioFileGlobalInfo_ExtensionsForType: 314 + case kAudioFileGlobalInfo_UTIsForType: 315 + case kAudioFileGlobalInfo_MIMETypesForType: 316 + { 317 + const UInt32* fileType = static_cast<const UInt32*>(inSpecifier); 318 + if (inSpecifierSize != sizeof(*fileType)) 319 + return kAudioFileBadPropertySizeError; 320 + 321 + *ioDataSize = sizeof(CFArrayRef); 322 + 323 + if (outPropertyData) 324 + { 325 + const std::vector<std::string>* vector; 326 + const AudioFileFormatManager::ComponentInfo* ci; 327 + 328 + ci = AudioFileFormatManager::instance()->fileType(*fileType); 329 + if (!ci) 330 + return kAudioFileUnsupportedFileTypeError; 331 + 332 + if (inPropertyID == kAudioFileGlobalInfo_ExtensionsForType) 333 + vector = &ci->extensions; 334 + else if (inPropertyID == kAudioFileGlobalInfo_UTIsForType) 335 + vector = &ci->utis; 336 + else if (inPropertyID == kAudioFileGlobalInfo_MIMETypesForType) 337 + vector = &ci->mimeTypes; 338 + 339 + *((CFArrayRef*)outPropertyData) = stringContainerToArray(*vector); 340 + } 341 + 342 + return noErr; 343 + } 344 + case kAudioFileGlobalInfo_TypesForMIMEType: 345 + case kAudioFileGlobalInfo_TypesForUTI: 346 + case kAudioFileGlobalInfo_TypesForExtension: 347 + { 348 + CFStringRef str = static_cast<CFStringRef>(inSpecifier); 349 + if (inSpecifierSize != sizeof(str)) 350 + return kAudioFileBadPropertySizeError; 351 + 352 + AudioFileFormatManager* mgr = AudioFileFormatManager::instance(); 353 + const char* cstr = CFStringGetCStringPtr(str, kCFStringEncodingUTF8); 354 + std::set<UInt32> set; 355 + 356 + if (inPropertyID == kAudioFileGlobalInfo_TypesForMIMEType) 357 + set = mgr->typesForMIME(cstr); 358 + else if (inPropertyID == kAudioFileGlobalInfo_TypesForUTI) 359 + set = mgr->typesForUTI(cstr); 360 + else if (inPropertyID == kAudioFileGlobalInfo_TypesForExtension) 361 + set = mgr->typesForExtension(cstr); 362 + 363 + *ioDataSize = set.size() * sizeof(UInt32); 364 + writeUInt32Set(set, outPropertyData); 365 + 366 + return noErr; 367 + } 368 + } 205 369 return unimpErr; 206 370 } 207 371
+200 -7
src/CoreAudio/AudioToolbox/AudioFileFormatManager.cpp
··· 44 44 } 45 45 } 46 46 47 + static std::vector<std::string> cfArrayToVector(CFArrayRef array) 48 + { 49 + std::vector<std::string> rv; 50 + const CFIndex count = CFArrayGetCount(array); 51 + 52 + rv.reserve(count); 53 + 54 + for (CFIndex i = 0; i < count; i++) 55 + { 56 + CFStringRef str = (CFStringRef) CFArrayGetValueAtIndex(array, i); 57 + rv.push_back(CFStringGetCStringPtr(str, kCFStringEncodingUTF8)); 58 + } 59 + 60 + return rv; 61 + } 62 + 47 63 void AudioFileFormatManager::analyzeAudioFileComponent(AudioFileComponent component) 48 64 { 49 - /* 50 - kAudioFileComponent_FileTypeName = 'ftnm', 51 - kAudioFileComponent_UTIsForType = 'futi', 52 - kAudioFileComponent_MIMETypesForType = 'fmim', 53 - kAudioFileComponent_ExtensionsForType = 'fext', 54 - kAudioFileComponent_AvailableFormatIDs = 'fmid', 55 - */ 65 + ComponentInfo ci; 66 + UInt32 propSize; 67 + 68 + ::AudioComponentGetDescription(AudioComponent(component), &ci.acd); 69 + 70 + ci.fileType = ci.acd.componentSubType; // TODO: Is this correct? 71 + 72 + { 73 + CFStringRef name = nullptr; 74 + propSize = sizeof(name); 75 + 76 + if (::AudioFileComponentGetGlobalInfo(component, kAudioFileComponent_FileTypeName, 0, nullptr, &propSize, &name) == noErr && name) 77 + { 78 + ci.name = CFStringGetCStringPtr(name, kCFStringEncodingUTF8); 79 + CFRelease(name); 80 + } 81 + } 82 + { 83 + UInt32 can; 84 + 85 + propSize = sizeof(can); 86 + ci.canRead = ci.canWrite = false; 87 + 88 + if (::AudioFileComponentGetGlobalInfo(component, kAudioFileComponent_CanRead, 0, nullptr, &propSize, &can) == noErr && can) 89 + ci.canRead = true; 90 + if (::AudioFileComponentGetGlobalInfo(component, kAudioFileComponent_CanWrite, 0, nullptr, &propSize, &can) == noErr && can) 91 + ci.canWrite = true; 92 + } 93 + 94 + CFArrayRef array = nullptr; 95 + if (::AudioFileComponentGetGlobalInfo(component, kAudioFileComponent_UTIsForType, 0, nullptr, &propSize, &array) == noErr && array) 96 + { 97 + ci.utis = cfArrayToVector(array); 98 + CFRelease(array); 99 + } 100 + 101 + array = nullptr; 102 + if (::AudioFileComponentGetGlobalInfo(component, kAudioFileComponent_MIMETypesForType, 0, nullptr, &propSize, &array) == noErr && array) 103 + { 104 + ci.mimeTypes = cfArrayToVector(array); 105 + CFRelease(array); 106 + } 107 + 108 + array = nullptr; 109 + if (::AudioFileComponentGetGlobalInfo(component, kAudioFileComponent_ExtensionsForType, 0, nullptr, &propSize, &array) == noErr && array) 110 + { 111 + ci.extensions = cfArrayToVector(array); 112 + CFRelease(array); 113 + } 114 + 115 + if (::AudioFileComponentGetGlobalInfoSize(component, kAudioFileComponent_AvailableFormatIDs, 0, nullptr, &propSize) == noErr) 116 + { 117 + const size_t formatCount = propSize / sizeof(UInt32); 118 + std::unique_ptr<UInt32[]> formatIds(new UInt32[formatCount]); 119 + 120 + if (::AudioFileComponentGetGlobalInfo(component, kAudioFileComponent_AvailableFormatIDs, 0, nullptr, &propSize, formatIds.get()) == noErr) 121 + { 122 + for (size_t i = 0; i < formatCount; i++) 123 + { 124 + UInt32 format = formatIds[i]; 125 + std::vector<AudioStreamBasicDescription> asbds; 126 + 127 + if (::AudioFileComponentGetGlobalInfoSize(component, kAudioFileComponent_AvailableStreamDescriptionsForFormat, sizeof(UInt32), &format, &propSize) == noErr) 128 + { 129 + asbds.resize(propSize / sizeof(AudioStreamBasicDescription)); 130 + 131 + if (::AudioFileComponentGetGlobalInfo(component, kAudioFileComponent_AvailableStreamDescriptionsForFormat, sizeof(UInt32), &format, &propSize, asbds.data()) != noErr) 132 + asbds.resize(0); 133 + 134 + ci.formatDescriptions.emplace(format, std::move(asbds)); 135 + } 136 + else 137 + ci.formatDescriptions.emplace(format, asbds); 138 + } 139 + } 140 + } 141 + 142 + registerComponent(ci); 143 + } 144 + 145 + void AudioFileFormatManager::addToMap(std::unordered_map<std::string, std::vector<ComponentInfo*>>& map, const std::string& key, ComponentInfo* ci) 146 + { 147 + auto it = map.find(key); 148 + if (it == map.end()) 149 + it = map.emplace(key, std::vector<ComponentInfo*>()).first; 150 + it->second.push_back(ci); 151 + } 152 + 153 + void AudioFileFormatManager::registerComponent(const ComponentInfo& ci) 154 + { 155 + m_components.push_back(ci); 156 + 157 + // Add format into various maps 158 + ComponentInfo* pci = &m_components.back(); 159 + m_fileTypeMap.emplace(ci.fileType, pci); 160 + 161 + for (const std::string& uti : ci.utis) 162 + addToMap(m_utiMap, uti, pci); 163 + for (const std::string& mime : ci.mimeTypes) 164 + addToMap(m_mimeMap, mime, pci); 165 + for (const std::string& ext : ci.extensions) 166 + addToMap(m_extensionMap, ext, pci); 56 167 } 57 168 58 169 AudioFileFormatManager* AudioFileFormatManager::instance() ··· 60 171 static AudioFileFormatManager inst; 61 172 return &inst; 62 173 } 174 + 175 + std::set<UInt32> AudioFileFormatManager::availableFormatIDs(UInt32 fileType) const 176 + { 177 + std::set<UInt32> rv; 178 + 179 + auto it = m_fileTypeMap.find(fileType); 180 + if (it == m_fileTypeMap.end()) 181 + return rv; 182 + 183 + const ComponentInfo* ci = it->second; 184 + 185 + for (auto const& [key, value] : ci->formatDescriptions) 186 + rv.insert(key); 187 + return rv; 188 + } 189 + 190 + const AudioFileFormatManager::ComponentInfo* AudioFileFormatManager::fileType(UInt32 fileType) const 191 + { 192 + auto it = m_fileTypeMap.find(fileType); 193 + if (it == m_fileTypeMap.end()) 194 + return nullptr; 195 + return it->second; 196 + } 197 + 198 + std::set<UInt32> AudioFileFormatManager::types(bool writableTypes) const 199 + { 200 + std::set<UInt32> rv; 201 + 202 + for (const ComponentInfo& ci : m_components) 203 + { 204 + if (writableTypes && ci.canWrite) 205 + rv.insert(ci.fileType); 206 + else if (!writableTypes && ci.canRead) 207 + rv.insert(ci.fileType); 208 + } 209 + 210 + return rv; 211 + } 212 + 213 + std::set<UInt32> AudioFileFormatManager::findTypes(const std::unordered_map<std::string, std::vector<ComponentInfo*>>& map, const char* key) 214 + { 215 + std::set<UInt32> rv; 216 + 217 + auto it = map.find(key); 218 + if (it == map.end()) 219 + return rv; 220 + 221 + for (const ComponentInfo* ci : it->second) 222 + rv.insert(ci->fileType); 223 + 224 + return rv; 225 + } 226 + 227 + std::set<UInt32> AudioFileFormatManager::typesForMIME(const char* mime) const 228 + { 229 + return findTypes(m_mimeMap, mime); 230 + } 231 + 232 + std::set<UInt32> AudioFileFormatManager::typesForUTI(const char* uti) const 233 + { 234 + return findTypes(m_utiMap, uti); 235 + } 236 + 237 + std::set<UInt32> AudioFileFormatManager::typesForExtension(const char* ext) const 238 + { 239 + return findTypes(m_extensionMap, ext); 240 + } 241 + 242 + std::set<std::string> AudioFileFormatManager::allMIMEs() const 243 + { 244 + return allKeys(m_mimeMap); 245 + } 246 + 247 + std::set<std::string> AudioFileFormatManager::allUTIs() const 248 + { 249 + return allKeys(m_utiMap); 250 + } 251 + 252 + std::set<std::string> AudioFileFormatManager::allExtensions() const 253 + { 254 + return allKeys(m_extensionMap); 255 + }
+47 -2
src/CoreAudio/AudioToolbox/AudioFileFormatManager.h
··· 22 22 #define _AUDIO_FILE_FORMAT_MANAGER_H 23 23 #include <AudioToolbox/AudioComponent.h> 24 24 #include <AudioToolbox/AudioFileComponent.h> 25 + #include <vector> 26 + #include <string> 27 + #include <set> 28 + #include <list> 29 + #include <unordered_map> 25 30 26 31 class __attribute__((visibility("hidden"))) AudioFileFormatManager 27 32 { 33 + public: 34 + static AudioFileFormatManager* instance(); 35 + 36 + std::set<UInt32> availableFormatIDs(UInt32 fileType) const; 37 + 38 + struct ComponentInfo 39 + { 40 + AudioComponentDescription acd; 41 + UInt32 fileType; // container type 42 + std::string name; 43 + std::vector<std::string> utis, extensions, mimeTypes; 44 + // codec type 45 + std::unordered_map<UInt32, std::vector<AudioStreamBasicDescription>> formatDescriptions; 46 + bool canRead, canWrite; 47 + }; 48 + 49 + const ComponentInfo* fileType(UInt32 type) const; 50 + std::set<UInt32> types(bool writableTypes) const; 51 + 52 + std::set<UInt32> typesForMIME(const char* mime) const; 53 + std::set<UInt32> typesForUTI(const char* uti) const; 54 + std::set<UInt32> typesForExtension(const char* ext) const; 55 + 56 + std::set<std::string> allMIMEs() const; 57 + std::set<std::string> allUTIs() const; 58 + std::set<std::string> allExtensions() const; 28 59 private: 29 60 AudioFileFormatManager(); 30 61 void buildDatabase(); 31 62 void analyzeAudioFileComponent(AudioFileComponent component); 32 - public: 33 - static AudioFileFormatManager* instance(); 63 + void registerComponent(const ComponentInfo& ci); 64 + static void addToMap(std::unordered_map<std::string, std::vector<ComponentInfo*>>& map, const std::string& key, ComponentInfo* ci); 65 + static std::set<UInt32> findTypes(const std::unordered_map<std::string, std::vector<ComponentInfo*>>& map, const char* key); 66 + 67 + template <typename K, typename V> 68 + std::set<K> allKeys(const std::unordered_map<K,V>& map) const 69 + { 70 + std::set<K> rv; 71 + for (auto const& [k, v] : map) 72 + rv.insert(k); 73 + return rv; 74 + } 75 + private: 76 + std::list<ComponentInfo> m_components; 77 + std::unordered_map<UInt32, ComponentInfo*> m_fileTypeMap; 78 + std::unordered_map<std::string, std::vector<ComponentInfo*>> m_mimeMap, m_utiMap, m_extensionMap; 34 79 }; 35 80 36 81 #endif