#import #import #include #if defined(__GNUC__) #define PQ_EXPORT extern "C" __attribute__((visibility("default"))) #else #define PQ_EXPORT extern "C" #endif namespace { SPUStandardUpdaterController *s_updaterController = nil; std::string s_lastError; void SetError(NSString *message) { s_lastError = message == nil ? std::string() : std::string(message.UTF8String); } bool RequireMainThread() { if ([NSThread isMainThread]) return true; SetError(@"Sparkle updater calls must run on the macOS main thread."); return false; } } PQ_EXPORT bool PQUpdaterInitialize() { @autoreleasepool { if (!RequireMainThread()) return false; if (s_updaterController != nil) return true; @try { s_updaterController = [[SPUStandardUpdaterController alloc] initWithStartingUpdater:YES updaterDelegate:nil userDriverDelegate:nil]; if (s_updaterController == nil) { SetError(@"Sparkle updater controller could not be created."); return false; } s_lastError.clear(); return true; } @catch (NSException *exception) { SetError(exception.reason ?: exception.name); s_updaterController = nil; return false; } } } PQ_EXPORT bool PQUpdaterCanCheckForUpdates() { @autoreleasepool { if (!RequireMainThread() || s_updaterController == nil) return false; return s_updaterController.updater.canCheckForUpdates; } } PQ_EXPORT bool PQUpdaterCheckForUpdates() { @autoreleasepool { if (!RequireMainThread()) return false; if (s_updaterController == nil) { SetError(@"Sparkle updater has not been initialized."); return false; } if (!s_updaterController.updater.canCheckForUpdates) { SetError(@"Sparkle is already checking for an update."); return false; } [s_updaterController checkForUpdates:nil]; s_lastError.clear(); return true; } } PQ_EXPORT void PQUpdaterShutdown() { @autoreleasepool { if (!RequireMainThread()) return; s_updaterController = nil; s_lastError.clear(); } } PQ_EXPORT const char *PQUpdaterGetLastError() { return s_lastError.c_str(); }