this repo has no description
at fixPythonPipStalling 255 lines 7.0 kB view raw
1/* 2This file is part of Darling. 3 4Copyright (C) 2020 Lubos Dolezel 5 6Darling is free software: you can redistribute it and/or modify 7it under the terms of the GNU General Public License as published by 8the Free Software Foundation, either version 3 of the License, or 9(at your option) any later version. 10 11Darling is distributed in the hope that it will be useful, 12but WITHOUT ANY WARRANTY; without even the implied warranty of 13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14GNU General Public License for more details. 15 16You should have received a copy of the GNU General Public License 17along with Darling. If not, see <http://www.gnu.org/licenses/>. 18*/ 19 20#include "AudioFileFormatManager.h" 21 22AudioFileFormatManager::AudioFileFormatManager() 23{ 24 25} 26 27void AudioFileFormatManager::buildDatabase() 28{ 29 AudioComponentDescription acd = { 0 }; 30 acd.componentType = 'afil'; 31 32 AudioComponent component = nullptr; 33 34 while ((component = ::AudioComponentFindNext(component, &acd)) != nullptr) 35 { 36 AudioComponentInstance inst; 37 OSStatus status = ::AudioComponentInstanceNew(component, &inst); 38 39 if (status != noErr) 40 continue; 41 42 analyzeAudioFileComponent(inst); 43 ::AudioComponentInstanceDispose(inst); 44 } 45} 46 47static 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 63void AudioFileFormatManager::analyzeAudioFileComponent(AudioFileComponent component) 64{ 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 145void 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 153void 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); 167} 168 169AudioFileFormatManager* AudioFileFormatManager::instance() 170{ 171 static AudioFileFormatManager inst; 172 return &inst; 173} 174 175std::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 190const 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 198std::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 213std::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 227std::set<UInt32> AudioFileFormatManager::typesForMIME(const char* mime) const 228{ 229 return findTypes(m_mimeMap, mime); 230} 231 232std::set<UInt32> AudioFileFormatManager::typesForUTI(const char* uti) const 233{ 234 return findTypes(m_utiMap, uti); 235} 236 237std::set<UInt32> AudioFileFormatManager::typesForExtension(const char* ext) const 238{ 239 return findTypes(m_extensionMap, ext); 240} 241 242std::set<std::string> AudioFileFormatManager::allMIMEs() const 243{ 244 return allKeys(m_mimeMap); 245} 246 247std::set<std::string> AudioFileFormatManager::allUTIs() const 248{ 249 return allKeys(m_utiMap); 250} 251 252std::set<std::string> AudioFileFormatManager::allExtensions() const 253{ 254 return allKeys(m_extensionMap); 255}