this repo has no description
1
fork

Configure Feed

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

CoreServices: Untested code for locating Components and loading them on demand

+346 -5
+314 -3
src/frameworks/CoreServices/ComponentManager.cpp
··· 20 20 #include "ComponentManager.h" 21 21 #include <CoreServices/MacErrors.h> 22 22 #include <CoreServices/Resources.h> 23 + #include <CoreServices/MacMemory.h> 24 + #include <dirent.h> 25 + #include <cstdlib> 26 + #include <CoreFoundation/CFBundle.h> 27 + #include <CoreFoundation/CFURL.h> 28 + #include <CoreFoundation/CFString.h> 29 + #include <CoreFoundation/CFArray.h> 23 30 24 - // Some clues about how this work can be found here: 31 + // Some clues about how this works can be found here: 25 32 // https://vintageapple.org/develop/pdf/develop-12_9212_December_1992.pdf 26 33 34 + #if defined(__i386__) 35 + # define CURRENT_PLATFORM platformIA32NativeEntryPoint 36 + #elif defined(__x86_64__) 37 + # define CURRENT_PLATFORM platformX86_64NativeEntryPoint 38 + #elif defined(__ppc__) 39 + # define CURRENT_PLATFORM platformPowerPCNativeEntryPoint 40 + #elif defined(__ppc64__) 41 + # define CURRENT_PLATFORM platformPowerPC64NativeEntryPoint 42 + #endif 43 + 27 44 ComponentManager* ComponentManager::instance() 28 45 { 29 46 static ComponentManager inst; ··· 37 54 38 55 void ComponentManager::discoverComponents() 39 56 { 40 - // TODO 57 + discoverComponents("/System/Library/Components"); 58 + 59 + const char* home = ::getenv("HOME"); 60 + if (home != NULL) 61 + { 62 + std::string userPath = home; 63 + userPath += "/Library/Audio/Plug-Ins/Components"; 64 + 65 + discoverComponents(userPath.c_str()); 66 + } 67 + } 68 + 69 + void ComponentManager::discoverComponents(const char* dir) 70 + { 71 + CFArrayRef componentBundles; 72 + CFURLRef urlDir; 73 + CFStringRef strDir; 74 + 75 + strDir = CFStringCreateWithCStringNoCopy(nullptr, dir, kCFStringEncodingUTF8, kCFAllocatorNull); 76 + urlDir = CFURLCreateWithFileSystemPath(nullptr, strDir, kCFURLPOSIXPathStyle, true); 77 + CFRelease(strDir); 78 + 79 + componentBundles = CFBundleCreateBundlesFromDirectory(nullptr, urlDir, CFSTR("component")); 80 + 81 + CFRelease(urlDir); 82 + 83 + for (CFIndex i = 0; i < CFArrayGetCount(componentBundles); i++) 84 + analyzeComponent((CFBundleRef) CFArrayGetValueAtIndex(componentBundles, i)); 85 + 86 + CFRelease(componentBundles); 87 + } 88 + 89 + void ComponentManager::analyzeComponent(CFBundleRef bundle) 90 + { 91 + OSStatus status; 92 + FSRef fsref; 93 + bool analyzed = false; 94 + 95 + CFURLRef url = CFBundleCopyExecutableURL(bundle); 96 + if (url != nullptr) 97 + { 98 + CFStringRef filePath = CFURLCopyFileSystemPath(url, kCFURLPOSIXPathStyle); 99 + 100 + // Check for a resource fork to analyze 101 + status = FSPathMakeRef((const uint8_t*) CFStringGetCStringPtr(filePath, kCFStringEncodingUTF8), &fsref, nullptr); 102 + 103 + if (status == noErr) 104 + { 105 + HFSUniStr255 rsrcForkName; 106 + ResFileRefNum resFile; 107 + 108 + FSGetResourceForkName(&rsrcForkName); 109 + 110 + status = FSOpenResourceFile(&fsref, rsrcForkName.length, rsrcForkName.unicode, fsRdPerm, &resFile); 111 + 112 + if (status == noErr) 113 + { 114 + analyzeComponent(bundle, resFile); 115 + CloseResFile(resFile); 116 + analyzed = true; 117 + } 118 + } 119 + 120 + CFRelease(filePath); 121 + CFRelease(url); 122 + } 123 + 124 + if (analyzed) 125 + return; 126 + 127 + CFURLRef bundleUrl = CFBundleCopyBundleURL(bundle); 128 + CFURLRef bundleUrlNoExt = CFURLCreateCopyDeletingPathExtension(nullptr, bundleUrl); 129 + CFRelease(bundleUrl); 130 + 131 + CFStringRef bundleName = CFURLCopyLastPathComponent(bundleUrlNoExt); 132 + CFRelease(bundleUrlNoExt); 133 + 134 + url = CFBundleCopyResourceURL(bundle, bundleName, CFSTR("rsrc"), nullptr); 135 + CFRelease(bundleName); 136 + 137 + // Check for a resource file 138 + if (url != nullptr) 139 + { 140 + CFStringRef filePath = CFURLCopyFileSystemPath(url, kCFURLPOSIXPathStyle); 141 + 142 + status = FSPathMakeRef((const uint8_t*) CFStringGetCStringPtr(filePath, kCFStringEncodingUTF8), &fsref, nullptr); 143 + 144 + if (status == noErr) 145 + { 146 + HFSUniStr255 rsrcForkName; 147 + ResFileRefNum resFile; 148 + 149 + FSGetDataForkName(&rsrcForkName); 150 + 151 + status = FSOpenResourceFile(&fsref, rsrcForkName.length, rsrcForkName.unicode, fsRdPerm, &resFile); 152 + 153 + if (status == noErr) 154 + { 155 + analyzeComponent(bundle, resFile); 156 + CloseResFile(resFile); 157 + } 158 + } 159 + 160 + CFRelease(filePath); 161 + CFRelease(url); 162 + } 163 + } 164 + 165 + #pragma pack(push, 1) 166 + struct PlatformInfo 167 + { 168 + uint32_t ComponentFlags; 169 + uint32_t CodeType; 170 + uint16_t CodeId; 171 + uint16_t PlatformType; 172 + }; 173 + 174 + struct CarbonThng 175 + { 176 + uint32_t Type; 177 + uint32_t Subtype; 178 + uint32_t Manufacturer; 179 + uint32_t ComponentFlags; 180 + uint32_t ComponentFlagsMask; 181 + uint32_t CodeType; 182 + uint16_t CodeId; 183 + uint32_t NameType; 184 + uint16_t NameId; 185 + uint32_t InfoType; 186 + uint16_t InfoId; 187 + uint32_t IconType; 188 + uint16_t IconId; 189 + uint32_t ComponentVersion; 190 + uint32_t RegistrationFlags; 191 + uint16_t IconFamilyId; 192 + 193 + uint32_t PlatformInfoCount; 194 + PlatformInfo PlatformInfos[]; 195 + }; 196 + #pragma pack(pop) 197 + 198 + #ifdef __LITTLE_ENDIAN__ 199 + # define SWAP(x) x = _bswap(x) 200 + 201 + static inline uint16_t _bswap(uint16_t v) { return __builtin_bswap16(v); } 202 + static inline int16_t _bswap(int16_t v) { return __builtin_bswap16(v); } 203 + static inline uint32_t _bswap(uint32_t v) { return __builtin_bswap32(v); } 204 + 205 + #else 206 + # define SWAP(x) 207 + #endif 208 + 209 + static std::string loadResString(ResType type, ResID id) 210 + { 211 + Handle h = Get1Resource(type, id); 212 + if (!h) 213 + return std::string(); 214 + 215 + return std::string(*h, GetHandleSize(h)); 216 + } 217 + 218 + void ComponentManager::analyzeComponent(CFBundleRef bundle, ResFileRefNum resFile) 219 + { 220 + ResFileRefNum origRes = CurResFile(); 221 + UseResFile(resFile); 222 + 223 + ResourceCount thingCount = Count1Resources('thng'); 224 + for (int i = 1; i <= thingCount; i++) 225 + { 226 + Handle handle = Get1IndResource('thng', i); 227 + if (handle && GetHandleSize(handle) >= sizeof(CarbonThng)) 228 + { 229 + CarbonThng thng = *((CarbonThng*) *handle); 230 + 231 + SWAP(thng.Type); 232 + SWAP(thng.Subtype); 233 + SWAP(thng.Manufacturer); 234 + 235 + SWAP(thng.CodeType); 236 + SWAP(thng.CodeId); 237 + 238 + SWAP(thng.NameType); 239 + SWAP(thng.NameId); 240 + 241 + SWAP(thng.InfoType); 242 + SWAP(thng.InfoId); 243 + 244 + SWAP(thng.ComponentFlags); 245 + SWAP(thng.ComponentFlagsMask); 246 + 247 + SWAP(thng.PlatformInfoCount); 248 + SWAP(thng.RegistrationFlags); 249 + 250 + ComponentDescription cd; 251 + cd.componentType = thng.Type; 252 + cd.componentSubType = thng.Subtype; 253 + cd.componentManufacturer = thng.Manufacturer; 254 + 255 + std::string name, info, entryPoint; 256 + name = loadResString(thng.NameType, thng.NameId); 257 + info = loadResString(thng.InfoType, thng.InfoId); 258 + 259 + for (int p = 0; p < thng.PlatformInfoCount; p++) 260 + { 261 + SWAP(thng.PlatformInfos[p].PlatformType); 262 + 263 + if (thng.PlatformInfos[p].PlatformType == CURRENT_PLATFORM) 264 + { 265 + SWAP(thng.PlatformInfos[p].CodeType); 266 + SWAP(thng.PlatformInfos[p].CodeId); 267 + entryPoint = loadResString(thng.PlatformInfos[p].CodeType, thng.PlatformInfos[p].CodeId); 268 + } 269 + } 270 + 271 + if (!entryPoint.empty()) 272 + { 273 + CFURLRef url = CFBundleCopyBundleURL(bundle); 274 + CFStringRef cfpath = CFURLCopyFileSystemPath(url, kCFURLPOSIXPathStyle); 275 + 276 + CFRelease(url); 277 + 278 + const char* path = CFStringGetCStringPtr(cfpath, kCFStringEncodingUTF8); 279 + registerComponent(&cd, thng.RegistrationFlags, path, entryPoint.c_str(), name.c_str(), info.c_str(), nullptr); 280 + CFRelease(cfpath); 281 + } 282 + } 283 + } 284 + 285 + UseResFile(origRes); 286 + } 287 + 288 + #undef SWAP 289 + 290 + Component ComponentManager::registerComponent(const ComponentDescription* cd, SInt16 flags, const char* bundlePath, 291 + const char* entryPoint, const char* name, const char* info, void* icon) 292 + { 293 + std::unique_lock<std::recursive_mutex> l(m_componentsMutex); 294 + 295 + ComponentData data; 296 + data.cd = *cd; 297 + data.instances = 0; 298 + 299 + if (name) 300 + data.name = name; 301 + if (info) 302 + data.info = info; 303 + 304 + data.entryPoint = nullptr; 305 + data.entryPointName = entryPoint; 306 + data.bundlePath = bundlePath; 307 + 308 + ComponentData* dataPtr; 309 + if (flags & registerComponentAfterExisting) 310 + { 311 + m_components.push_back(data); 312 + dataPtr = &m_components.back(); 313 + } 314 + else 315 + { 316 + m_components.push_front(data); 317 + dataPtr = &m_components.front(); 318 + } 319 + 320 + Component c = Component(uintptr_t(nextComponentId++)); 321 + dataPtr->component = c; 322 + 323 + m_componentsMap.insert(std::make_pair(c, dataPtr)); 324 + 325 + return c; 41 326 } 42 327 43 328 Component ComponentManager::registerComponent(const ComponentDescription* cd, ComponentRoutineUPP entryPointIn, SInt16 flags, ··· 169 454 if (itMap == m_componentsMap.end()) 170 455 return invalidComponentID; 171 456 457 + ComponentData* cd = itMap->second; 458 + 459 + if (!cd->entryPoint) 460 + { 461 + CFStringRef cfpath = CFStringCreateWithCString(nullptr, cd->bundlePath.c_str(), kCFStringEncodingUTF8); 462 + 463 + CFURLRef url = CFURLCreateWithFileSystemPath(nullptr, cfpath, kCFURLPOSIXPathStyle, true); 464 + CFRelease(cfpath); 465 + 466 + CFBundleRef bundle = CFBundleCreate(nullptr, url); 467 + CFRelease(url); 468 + 469 + if (!bundle) 470 + return invalidComponentID; 471 + 472 + CFStringRef cfEntryPointName = CFStringCreateWithCString(nullptr, cd->entryPointName.c_str(), kCFStringEncodingUTF8); 473 + cd->entryPoint = (ComponentRoutineUPP) CFBundleGetFunctionPointerForName(bundle, cfEntryPointName); 474 + CFRelease(cfEntryPointName); 475 + 476 + if (!cd->entryPoint) 477 + return invalidComponentID; 478 + 479 + // Releasing the bundle triggers CFBundleUnloadExecutable(), 480 + // so we leak the bundle instance here. 481 + } 482 + 172 483 ComponentInstanceData cid; 173 484 174 485 cid.component = c; 175 - cid.componentData = itMap->second; 486 + cid.componentData = cd; 176 487 cid.componentData->instances++; 177 488 cid.storage = nullptr; 178 489
+13 -2
src/frameworks/CoreServices/ComponentManager.h
··· 28 28 #include <string> 29 29 #include <stdint.h> 30 30 #include <CoreServices/MacTypes.h> 31 + #include <CoreFoundation/CFBundle.h> 31 32 32 33 class ComponentManager 33 34 { ··· 37 38 // Search in /System/Library/Components for components 38 39 // Examine resource forks of the main binary, but also check for Resources/$BUNDLE_NAME.rsrc 39 40 void discoverComponents(); 41 + void discoverComponents(const char* dir); 42 + void analyzeComponent(CFBundleRef bundle); 43 + void analyzeComponent(CFBundleRef bundle, ResFileRefNum resFile); 40 44 public: 41 45 static ComponentManager* instance(); 42 46 43 - Component registerComponent(const ComponentDescription* cd, ComponentRoutineUPP entryPoint, SInt16 flags, const char* name, const char* info, void* icon); 47 + // Dynamic registration (in memory) 48 + Component registerComponent(const ComponentDescription* cd, ComponentRoutineUPP entryPoint, SInt16 flags, 49 + const char* name, const char* info, void* icon); 50 + 51 + // Bundle registration (automatic) 52 + Component registerComponent(const ComponentDescription* cd, SInt16 flags, const char* path, const char* entryPoint, 53 + const char* name, const char* info, void* icon); 54 + 44 55 void setDefault(Component c, SInt16 flags); 45 56 OSStatus unregisterComponent(Component c); 46 57 ··· 68 79 ComponentRoutineUPP entryPoint; 69 80 std::string name, info; 70 81 71 - std::string bundlePath; 82 + std::string bundlePath, entryPointName; 72 83 73 84 uint32_t instances; 74 85 };
+8
src/frameworks/CoreServices/Resources.cpp
··· 117 117 { 118 118 std::unique_lock<std::mutex> l(g_resourcesLock); 119 119 120 + if (ref == kResFileNotOpened) 121 + { 122 + g_currentResFile = ref; 123 + g_currentResources = nullptr; 124 + g_lastError = noErr; 125 + return; 126 + } 127 + 120 128 if (auto it = g_resources.find(ref); it != g_resources.end()) 121 129 { 122 130 g_currentResFile = ref;
+11
src/frameworks/CoreServices/include/CoreServices/Components.h
··· 82 82 defaultComponentAnyFlagsAnyManufacturerAnySubType = (defaultComponentFlags + defaultComponentAnyManufacturer + defaultComponentAnySubType), 83 83 }; 84 84 85 + enum { 86 + platform68k = 1, 87 + platformPowerPC = 2, 88 + platformInterpreted = 3, 89 + platformWin32 = 4, 90 + platformPowerPCNativeEntryPoint = 5, 91 + platformIA32NativeEntryPoint = 6, 92 + platformPowerPC64NativeEntryPoint = 7, 93 + platformX86_64NativeEntryPoint = 8, 94 + }; 95 + 85 96 typedef struct ResourceSpec 86 97 { 87 98 OSType resType;