diff --git a/UI/frontend-plugins/frontend-tools/auto-scene-switcher-osx.mm b/UI/frontend-plugins/frontend-tools/auto-scene-switcher-osx.mm index 98752404e..a2474b3da 100644 --- a/UI/frontend-plugins/frontend-tools/auto-scene-switcher-osx.mm +++ b/UI/frontend-plugins/frontend-tools/auto-scene-switcher-osx.mm @@ -6,40 +6,41 @@ using namespace std; void GetWindowList(vector &windows) { - windows.resize(0); + windows.resize(0); - @autoreleasepool { - NSWorkspace *ws = [NSWorkspace sharedWorkspace]; - NSArray *array = [ws runningApplications]; - for (NSRunningApplication *app in array) { - NSString *name = app.localizedName; - if (!name) - continue; + @autoreleasepool { + NSWorkspace *ws = [NSWorkspace sharedWorkspace]; + NSArray *array = [ws runningApplications]; + for (NSRunningApplication *app in array) { + NSString *name = app.localizedName; + if (!name) + continue; - const char *str = name.UTF8String; - if (str && *str) - windows.emplace_back(str); - } - } + const char *str = name.UTF8String; + if (str && *str) + windows.emplace_back(str); + } + } } void GetCurrentWindowTitle(string &title) { - title.resize(0); + title.resize(0); - @autoreleasepool { - NSWorkspace *ws = [NSWorkspace sharedWorkspace]; - NSRunningApplication *app = [ws frontmostApplication]; - if (app) { - NSString *name = app.localizedName; - if (!name) - return; + @autoreleasepool { + NSWorkspace *ws = [NSWorkspace sharedWorkspace]; + NSRunningApplication *app = [ws frontmostApplication]; + if (app) { + NSString *name = app.localizedName; + if (!name) + return; - const char *str = name.UTF8String; - if (str && *str) - title = str; - } - } + const char *str = name.UTF8String; + if (str && *str) + title = str; + } + } } -void CleanupSceneSwitcher() {} +void CleanupSceneSwitcher() +{} diff --git a/UI/platform-osx.mm b/UI/platform-osx.mm index 8506163cd..5ce79e0ce 100644 --- a/UI/platform-osx.mm +++ b/UI/platform-osx.mm @@ -34,341 +34,289 @@ using namespace std; bool isInBundle() { - NSRunningApplication *app = [NSRunningApplication currentApplication]; - return [app bundleIdentifier] != nil; + NSRunningApplication *app = [NSRunningApplication currentApplication]; + return [app bundleIdentifier] != nil; } bool GetDataFilePath(const char *data, string &output) { - NSURL *bundleUrl = [[NSBundle mainBundle] bundleURL]; - NSString *path = [[bundleUrl path] - stringByAppendingFormat:@"/%@/%s", @"Contents/Resources", data]; - output = path.UTF8String; + NSURL *bundleUrl = [[NSBundle mainBundle] bundleURL]; + NSString *path = [[bundleUrl path] stringByAppendingFormat:@"/%@/%s", @"Contents/Resources", data]; + output = path.UTF8String; - return !access(output.c_str(), R_OK); + return !access(output.c_str(), R_OK); } void CheckIfAlreadyRunning(bool &already_running) { - NSString *bundleId = [[NSBundle mainBundle] bundleIdentifier]; + NSString *bundleId = [[NSBundle mainBundle] bundleIdentifier]; - NSUInteger appCount = [[NSRunningApplication - runningApplicationsWithBundleIdentifier:bundleId] count]; + NSUInteger appCount = [[NSRunningApplication runningApplicationsWithBundleIdentifier:bundleId] count]; - already_running = appCount > 1; + already_running = appCount > 1; } string GetDefaultVideoSavePath() { - NSFileManager *fm = [NSFileManager defaultManager]; - NSURL *url = [fm URLForDirectory:NSMoviesDirectory - inDomain:NSUserDomainMask - appropriateForURL:nil - create:true - error:nil]; + NSFileManager *fm = [NSFileManager defaultManager]; + NSURL *url = [fm URLForDirectory:NSMoviesDirectory inDomain:NSUserDomainMask appropriateForURL:nil create:true + error:nil]; - if (!url) - return getenv("HOME"); + if (!url) + return getenv("HOME"); - return url.path.fileSystemRepresentation; + return url.path.fileSystemRepresentation; } vector GetPreferredLocales() { - NSArray *preferred = [NSLocale preferredLanguages]; + NSArray *preferred = [NSLocale preferredLanguages]; - auto locales = GetLocaleNames(); - auto lang_to_locale = [&locales](string lang) -> string { - string lang_match = ""; + auto locales = GetLocaleNames(); + auto lang_to_locale = [&locales](string lang) -> string { + string lang_match = ""; - for (const auto &locale : locales) { - if (locale.first == lang.substr(0, locale.first.size())) - return locale.first; + for (const auto &locale : locales) { + if (locale.first == lang.substr(0, locale.first.size())) + return locale.first; - if (!lang_match.size() && - locale.first.substr(0, 2) == lang.substr(0, 2)) - lang_match = locale.first; - } + if (!lang_match.size() && locale.first.substr(0, 2) == lang.substr(0, 2)) + lang_match = locale.first; + } - return lang_match; - }; + return lang_match; + }; - vector result; - result.reserve(preferred.count); + vector result; + result.reserve(preferred.count); - for (NSString *lang in preferred) { - string locale = lang_to_locale(lang.UTF8String); - if (!locale.size()) - continue; + for (NSString *lang in preferred) { + string locale = lang_to_locale(lang.UTF8String); + if (!locale.size()) + continue; - if (find(begin(result), end(result), locale) != end(result)) - continue; + if (find(begin(result), end(result), locale) != end(result)) + continue; - result.emplace_back(locale); - } + result.emplace_back(locale); + } - return result; + return result; } bool IsAlwaysOnTop(QWidget *window) { - return (window->windowFlags() & Qt::WindowStaysOnTopHint) != 0; + return (window->windowFlags() & Qt::WindowStaysOnTopHint) != 0; } void disableColorSpaceConversion(QWidget *window) { - NSView *view = - (__bridge NSView *)reinterpret_cast(window->winId()); - view.window.colorSpace = NSColorSpace.sRGBColorSpace; + NSView *view = (__bridge NSView *) reinterpret_cast(window->winId()); + view.window.colorSpace = NSColorSpace.sRGBColorSpace; } void SetAlwaysOnTop(QWidget *window, bool enable) { - Qt::WindowFlags flags = window->windowFlags(); + Qt::WindowFlags flags = window->windowFlags(); - if (enable) { - NSView *view = (__bridge NSView *)reinterpret_cast( - window->winId()); + if (enable) { + NSView *view = (__bridge NSView *) reinterpret_cast(window->winId()); - [[view window] setLevel:NSScreenSaverWindowLevel]; + [[view window] setLevel:NSScreenSaverWindowLevel]; - flags |= Qt::WindowStaysOnTopHint; - } else { - flags &= ~Qt::WindowStaysOnTopHint; - } + flags |= Qt::WindowStaysOnTopHint; + } else { + flags &= ~Qt::WindowStaysOnTopHint; + } - window->setWindowFlags(flags); - window->show(); + window->setWindowFlags(flags); + window->show(); } bool SetDisplayAffinitySupported(void) { - // Not implemented yet - return false; + // Not implemented yet + return false; } typedef void (*set_int_t)(int); void EnableOSXVSync(bool enable) { - static bool initialized = false; - static bool valid = false; - static set_int_t set_debug_options = nullptr; - static set_int_t deferred_updates = nullptr; + static bool initialized = false; + static bool valid = false; + static set_int_t set_debug_options = nullptr; + static set_int_t deferred_updates = nullptr; - if (!initialized) { - void *quartzCore = dlopen("/System/Library/Frameworks/" - "QuartzCore.framework/QuartzCore", - RTLD_LAZY); - if (quartzCore) { - set_debug_options = (set_int_t)dlsym( - quartzCore, "CGSSetDebugOptions"); - deferred_updates = (set_int_t)dlsym( - quartzCore, "CGSDeferredUpdates"); + if (!initialized) { + void *quartzCore = dlopen("/System/Library/Frameworks/" + "QuartzCore.framework/QuartzCore", + RTLD_LAZY); + if (quartzCore) { + set_debug_options = (set_int_t) dlsym(quartzCore, "CGSSetDebugOptions"); + deferred_updates = (set_int_t) dlsym(quartzCore, "CGSDeferredUpdates"); - valid = set_debug_options && deferred_updates; - } + valid = set_debug_options && deferred_updates; + } - initialized = true; - } + initialized = true; + } - if (valid) { - set_debug_options(enable ? 0 : 0x08000000); - deferred_updates(enable ? 1 : 0); - } + if (valid) { + set_debug_options(enable ? 0 : 0x08000000); + deferred_updates(enable ? 1 : 0); + } } void EnableOSXDockIcon(bool enable) { - if (enable) - [NSApp setActivationPolicy:NSApplicationActivationPolicyRegular]; - else - [NSApp setActivationPolicy: - NSApplicationActivationPolicyProhibited]; + if (enable) + [NSApp setActivationPolicy:NSApplicationActivationPolicyRegular]; + else + [NSApp setActivationPolicy:NSApplicationActivationPolicyProhibited]; } @interface DockView : NSView { -@private - QIcon _icon; + @private + QIcon _icon; } @end @implementation DockView - (id)initWithIcon:(QIcon)icon { - self = [super init]; - _icon = icon; - return self; + self = [super init]; + _icon = icon; + return self; } - (void)drawRect:(NSRect)dirtyRect { - CGSize size = dirtyRect.size; + CGSize size = dirtyRect.size; - /* Draw regular app icon */ - NSImage *appIcon = [[NSWorkspace sharedWorkspace] - iconForFile:[[NSBundle mainBundle] bundlePath]]; - [appIcon drawInRect:CGRectMake(0, 0, size.width, size.height)]; + /* Draw regular app icon */ + NSImage *appIcon = [[NSWorkspace sharedWorkspace] iconForFile:[[NSBundle mainBundle] bundlePath]]; + [appIcon drawInRect:CGRectMake(0, 0, size.width, size.height)]; - /* Draw small icon on top */ - float iconSize = 0.45; - CGImageRef image = - _icon.pixmap(size.width, size.height).toImage().toCGImage(); - CGContextRef context = [[NSGraphicsContext currentContext] CGContext]; - CGContextDrawImage(context, - CGRectMake(size.width * (1 - iconSize), 0, - size.width * iconSize, - size.height * iconSize), - image); - CGImageRelease(image); + /* Draw small icon on top */ + float iconSize = 0.45; + CGImageRef image = _icon.pixmap(size.width, size.height).toImage().toCGImage(); + CGContextRef context = [[NSGraphicsContext currentContext] CGContext]; + CGContextDrawImage( + context, CGRectMake(size.width * (1 - iconSize), 0, size.width * iconSize, size.height * iconSize), image); + CGImageRelease(image); } @end -MacPermissionStatus CheckPermissionWithPrompt(MacPermissionType type, - bool prompt_for_permission) +MacPermissionStatus CheckPermissionWithPrompt(MacPermissionType type, bool prompt_for_permission) { - __block MacPermissionStatus permissionResponse = - kPermissionNotDetermined; + __block MacPermissionStatus permissionResponse = kPermissionNotDetermined; - switch (type) { - case kAudioDeviceAccess: { - AVAuthorizationStatus audioStatus = [AVCaptureDevice - authorizationStatusForMediaType:AVMediaTypeAudio]; + switch (type) { + case kAudioDeviceAccess: { + AVAuthorizationStatus audioStatus = [AVCaptureDevice authorizationStatusForMediaType:AVMediaTypeAudio]; - if (audioStatus == AVAuthorizationStatusNotDetermined && - prompt_for_permission) { - os_event_t *block_finished; - os_event_init(&block_finished, OS_EVENT_TYPE_MANUAL); - [AVCaptureDevice - requestAccessForMediaType:AVMediaTypeAudio - completionHandler:^( - BOOL granted - __attribute((unused))) { - os_event_signal(block_finished); - }]; - os_event_wait(block_finished); - os_event_destroy(block_finished); - audioStatus = [AVCaptureDevice - authorizationStatusForMediaType:AVMediaTypeAudio]; - } + if (audioStatus == AVAuthorizationStatusNotDetermined && prompt_for_permission) { + os_event_t *block_finished; + os_event_init(&block_finished, OS_EVENT_TYPE_MANUAL); + [AVCaptureDevice requestAccessForMediaType:AVMediaTypeAudio + completionHandler:^(BOOL granted __attribute((unused))) { + os_event_signal(block_finished); + }]; + os_event_wait(block_finished); + os_event_destroy(block_finished); + audioStatus = [AVCaptureDevice authorizationStatusForMediaType:AVMediaTypeAudio]; + } - permissionResponse = (MacPermissionStatus)audioStatus; + permissionResponse = (MacPermissionStatus) audioStatus; - blog(LOG_INFO, "[macOS] Permission for audio device access %s.", - permissionResponse == kPermissionAuthorized ? "granted" - : "denied"); + blog(LOG_INFO, "[macOS] Permission for audio device access %s.", + permissionResponse == kPermissionAuthorized ? "granted" : "denied"); - break; - } - case kVideoDeviceAccess: { - AVAuthorizationStatus videoStatus = [AVCaptureDevice - authorizationStatusForMediaType:AVMediaTypeVideo]; + break; + } + case kVideoDeviceAccess: { + AVAuthorizationStatus videoStatus = [AVCaptureDevice authorizationStatusForMediaType:AVMediaTypeVideo]; - if (videoStatus == AVAuthorizationStatusNotDetermined && - prompt_for_permission) { - os_event_t *block_finished; - os_event_init(&block_finished, OS_EVENT_TYPE_MANUAL); - [AVCaptureDevice - requestAccessForMediaType:AVMediaTypeVideo - completionHandler:^( - BOOL granted - __attribute((unused))) { - os_event_signal(block_finished); - }]; + if (videoStatus == AVAuthorizationStatusNotDetermined && prompt_for_permission) { + os_event_t *block_finished; + os_event_init(&block_finished, OS_EVENT_TYPE_MANUAL); + [AVCaptureDevice requestAccessForMediaType:AVMediaTypeVideo + completionHandler:^(BOOL granted __attribute((unused))) { + os_event_signal(block_finished); + }]; - os_event_wait(block_finished); - os_event_destroy(block_finished); - videoStatus = [AVCaptureDevice - authorizationStatusForMediaType:AVMediaTypeVideo]; - } + os_event_wait(block_finished); + os_event_destroy(block_finished); + videoStatus = [AVCaptureDevice authorizationStatusForMediaType:AVMediaTypeVideo]; + } - permissionResponse = (MacPermissionStatus)videoStatus; + permissionResponse = (MacPermissionStatus) videoStatus; - blog(LOG_INFO, "[macOS] Permission for video device access %s.", - permissionResponse == kPermissionAuthorized ? "granted" - : "denied"); + blog(LOG_INFO, "[macOS] Permission for video device access %s.", + permissionResponse == kPermissionAuthorized ? "granted" : "denied"); - break; - } - case kScreenCapture: { - permissionResponse = (CGPreflightScreenCaptureAccess() - ? kPermissionAuthorized - : kPermissionDenied); + break; + } + case kScreenCapture: { + permissionResponse = (CGPreflightScreenCaptureAccess() ? kPermissionAuthorized : kPermissionDenied); - if (permissionResponse != kPermissionAuthorized && - prompt_for_permission) { - permissionResponse = (CGRequestScreenCaptureAccess() - ? kPermissionAuthorized - : kPermissionDenied); - } + if (permissionResponse != kPermissionAuthorized && prompt_for_permission) { + permissionResponse = (CGRequestScreenCaptureAccess() ? kPermissionAuthorized : kPermissionDenied); + } - blog(LOG_INFO, "[macOS] Permission for screen capture %s.", - permissionResponse == kPermissionAuthorized ? "granted" - : "denied"); + blog(LOG_INFO, "[macOS] Permission for screen capture %s.", + permissionResponse == kPermissionAuthorized ? "granted" : "denied"); - break; - } - case kAccessibility: { - permissionResponse = (AXIsProcessTrusted() - ? kPermissionAuthorized - : kPermissionDenied); + break; + } + case kAccessibility: { + permissionResponse = (AXIsProcessTrusted() ? kPermissionAuthorized : kPermissionDenied); - if (permissionResponse != kPermissionAuthorized && - prompt_for_permission) { - NSDictionary *options = @{ - (__bridge id)kAXTrustedCheckOptionPrompt: @YES - }; - permissionResponse = (AXIsProcessTrustedWithOptions( - (CFDictionaryRef)options) - ? kPermissionAuthorized - : kPermissionDenied); - } + if (permissionResponse != kPermissionAuthorized && prompt_for_permission) { + NSDictionary *options = @{(__bridge id) kAXTrustedCheckOptionPrompt: @YES}; + permissionResponse = (AXIsProcessTrustedWithOptions((CFDictionaryRef) options) ? kPermissionAuthorized + : kPermissionDenied); + } - blog(LOG_INFO, "[macOS] Permission for accessibility %s.", - permissionResponse == kPermissionAuthorized ? "granted" - : "denied"); - break; - } - } + blog(LOG_INFO, "[macOS] Permission for accessibility %s.", + permissionResponse == kPermissionAuthorized ? "granted" : "denied"); + break; + } + } - return permissionResponse; + return permissionResponse; } void OpenMacOSPrivacyPreferences(const char *tab) { - NSURL *url = [NSURL - URLWithString: - [NSString - stringWithFormat: - @"x-apple.systempreferences:com.apple.preference.security?Privacy_%s", - tab]]; - [[NSWorkspace sharedWorkspace] openURL:url]; + NSURL *url = [NSURL + URLWithString:[NSString + stringWithFormat:@"x-apple.systempreferences:com.apple.preference.security?Privacy_%s", tab]]; + [[NSWorkspace sharedWorkspace] openURL:url]; } void SetMacOSDarkMode(bool dark) { - if (dark) { - NSApp.appearance = - [NSAppearance appearanceNamed:NSAppearanceNameDarkAqua]; - } else { - NSApp.appearance = - [NSAppearance appearanceNamed:NSAppearanceNameAqua]; - } + if (dark) { + NSApp.appearance = [NSAppearance appearanceNamed:NSAppearanceNameDarkAqua]; + } else { + NSApp.appearance = [NSAppearance appearanceNamed:NSAppearanceNameAqua]; + } } -void TaskbarOverlayInit() {} +void TaskbarOverlayInit() +{} void TaskbarOverlaySetStatus(TaskbarOverlayStatus status) { - QIcon icon; - if (status == TaskbarOverlayStatusActive) - icon = QIcon::fromTheme("obs-active", - QIcon(":/res/images/active_mac.png")); - else if (status == TaskbarOverlayStatusPaused) - icon = QIcon::fromTheme("obs-paused", - QIcon(":/res/images/paused_mac.png")); + QIcon icon; + if (status == TaskbarOverlayStatusActive) + icon = QIcon::fromTheme("obs-active", QIcon(":/res/images/active_mac.png")); + else if (status == TaskbarOverlayStatusPaused) + icon = QIcon::fromTheme("obs-paused", QIcon(":/res/images/paused_mac.png")); - NSDockTile *tile = [NSApp dockTile]; - [tile setContentView:[[DockView alloc] initWithIcon:icon]]; - [tile display]; + NSDockTile *tile = [NSApp dockTile]; + [tile setContentView:[[DockView alloc] initWithIcon:icon]]; + [tile display]; } /* @@ -389,22 +337,22 @@ void TaskbarOverlaySetStatus(TaskbarOverlayStatus status) @implementation OBSApplication - (void)sendEvent:(NSEvent *)event { - _handlingSendEvent = YES; - [super sendEvent:event]; - _handlingSendEvent = NO; + _handlingSendEvent = YES; + [super sendEvent:event]; + _handlingSendEvent = NO; } @end void InstallNSThreadLocks() { - [[NSThread new] start]; + [[NSThread new] start]; - if ([NSThread isMultiThreaded] != 1) { - abort(); - } + if ([NSThread isMultiThreaded] != 1) { + abort(); + } } void InstallNSApplicationSubclass() { - [OBSApplication sharedApplication]; + [OBSApplication sharedApplication]; } diff --git a/UI/update/crypto-helpers-mac.mm b/UI/update/crypto-helpers-mac.mm index 75ee0dc84..bb9811f78 100644 --- a/UI/update/crypto-helpers-mac.mm +++ b/UI/update/crypto-helpers-mac.mm @@ -4,29 +4,25 @@ #import #import -bool VerifySignature(const uint8_t *pubKey, const size_t pubKeyLen, - const uint8_t *buf, const size_t len, const uint8_t *sig, - const size_t sigLen) +bool VerifySignature(const uint8_t *pubKey, const size_t pubKeyLen, const uint8_t *buf, const size_t len, + const uint8_t *sig, const size_t sigLen) { - NSData *pubKeyData = [NSData dataWithBytes:pubKey length:pubKeyLen]; - CFArrayRef items = nullptr; + NSData *pubKeyData = [NSData dataWithBytes:pubKey length:pubKeyLen]; + CFArrayRef items = nullptr; - OSStatus res = SecItemImport((CFDataRef)pubKeyData, nullptr, nullptr, - nullptr, (SecItemImportExportFlags)0, - nullptr, nullptr, &items); - if (res != errSecSuccess) - return false; + OSStatus res = SecItemImport((CFDataRef) pubKeyData, nullptr, nullptr, nullptr, (SecItemImportExportFlags) 0, + nullptr, nullptr, &items); + if (res != errSecSuccess) + return false; - SecKeyRef pubKeyRef = (SecKeyRef)CFArrayGetValueAtIndex(items, 0); - NSData *signedData = [NSData dataWithBytes:buf length:len]; - NSData *signature = [NSData dataWithBytes:sig length:sigLen]; + SecKeyRef pubKeyRef = (SecKeyRef) CFArrayGetValueAtIndex(items, 0); + NSData *signedData = [NSData dataWithBytes:buf length:len]; + NSData *signature = [NSData dataWithBytes:sig length:sigLen]; - CFErrorRef errRef; - bool result = SecKeyVerifySignature( - pubKeyRef, kSecKeyAlgorithmRSASignatureMessagePKCS1v15SHA512, - (__bridge CFDataRef)signedData, (__bridge CFDataRef)signature, - &errRef); + CFErrorRef errRef; + bool result = SecKeyVerifySignature(pubKeyRef, kSecKeyAlgorithmRSASignatureMessagePKCS1v15SHA512, + (__bridge CFDataRef) signedData, (__bridge CFDataRef) signature, &errRef); - CFRelease(items); - return result; + CFRelease(items); + return result; }; diff --git a/UI/update/sparkle-updater.mm b/UI/update/sparkle-updater.mm index ce253d1b6..2afc7e83c 100644 --- a/UI/update/sparkle-updater.mm +++ b/UI/update/sparkle-updater.mm @@ -16,80 +16,64 @@ @synthesize branch; -- (nonnull NSSet *)allowedChannelsForUpdater: - (nonnull SPUUpdater *)updater +- (nonnull NSSet *)allowedChannelsForUpdater:(nonnull SPUUpdater *)updater { - return [NSSet setWithObject:branch]; + return [NSSet setWithObject:branch]; } - (void)observeCanCheckForUpdatesWithAction:(QAction *)action { - [_updaterController.updater - addObserver:self - forKeyPath:NSStringFromSelector(@selector(canCheckForUpdates)) - options:(NSKeyValueObservingOptionInitial | - NSKeyValueObservingOptionNew) - context:(void *)action]; + [_updaterController.updater addObserver:self forKeyPath:NSStringFromSelector(@selector(canCheckForUpdates)) + options:(NSKeyValueObservingOptionInitial | NSKeyValueObservingOptionNew) + context:(void *) action]; } - (void)observeValueForKeyPath:(NSString *)keyPath - ofObject:(id)object - change:(NSDictionary *)change - context:(void *)context + ofObject:(id)object + change:(NSDictionary *)change + context:(void *)context { - if ([keyPath isEqualToString:NSStringFromSelector( - @selector(canCheckForUpdates))]) { - QAction *menuAction = (QAction *)context; - menuAction->setEnabled( - _updaterController.updater.canCheckForUpdates); - } else { - [super observeValueForKeyPath:keyPath - ofObject:object - change:change - context:context]; - } + if ([keyPath isEqualToString:NSStringFromSelector(@selector(canCheckForUpdates))]) { + QAction *menuAction = (QAction *) context; + menuAction->setEnabled(_updaterController.updater.canCheckForUpdates); + } else { + [super observeValueForKeyPath:keyPath ofObject:object change:change context:context]; + } } - (void)dealloc { - @autoreleasepool { - [_updaterController.updater - removeObserver:self - forKeyPath:NSStringFromSelector( - @selector(canCheckForUpdates))]; - } + @autoreleasepool { + [_updaterController.updater removeObserver:self forKeyPath:NSStringFromSelector(@selector(canCheckForUpdates))]; + } } @end OBSSparkle::OBSSparkle(const char *branch, QAction *checkForUpdatesAction) { - @autoreleasepool { - updaterDelegate = [[OBSUpdateDelegate alloc] init]; - updaterDelegate.branch = [NSString stringWithUTF8String:branch]; - updaterDelegate.updaterController = - [[SPUStandardUpdaterController alloc] - initWithStartingUpdater:YES - updaterDelegate:updaterDelegate - userDriverDelegate:nil]; - [updaterDelegate observeCanCheckForUpdatesWithAction: - checkForUpdatesAction]; - } + @autoreleasepool { + updaterDelegate = [[OBSUpdateDelegate alloc] init]; + updaterDelegate.branch = [NSString stringWithUTF8String:branch]; + updaterDelegate.updaterController = + [[SPUStandardUpdaterController alloc] initWithStartingUpdater:YES updaterDelegate:updaterDelegate + userDriverDelegate:nil]; + [updaterDelegate observeCanCheckForUpdatesWithAction:checkForUpdatesAction]; + } } void OBSSparkle::setBranch(const char *branch) { - updaterDelegate.branch = [NSString stringWithUTF8String:branch]; + updaterDelegate.branch = [NSString stringWithUTF8String:branch]; } void OBSSparkle::checkForUpdates(bool manualCheck) { - @autoreleasepool { - if (manualCheck) { - [updaterDelegate.updaterController checkForUpdates:nil]; - } else { - [updaterDelegate.updaterController - .updater checkForUpdatesInBackground]; - } - } + @autoreleasepool { + if (manualCheck) { + [updaterDelegate.updaterController checkForUpdates:nil]; + } else { + [updaterDelegate.updaterController.updater checkForUpdatesInBackground]; + } + } } diff --git a/libobs-opengl/gl-cocoa.m b/libobs-opengl/gl-cocoa.m index 1dec0b2ae..3d1bcbc75 100644 --- a/libobs-opengl/gl-cocoa.m +++ b/libobs-opengl/gl-cocoa.m @@ -22,443 +22,421 @@ #import struct gl_windowinfo { - NSView *view; - NSOpenGLContext *context; - gs_texture_t *texture; - GLuint fbo; + NSView *view; + NSOpenGLContext *context; + gs_texture_t *texture; + GLuint fbo; }; struct gl_platform { - NSOpenGLContext *context; + NSOpenGLContext *context; }; static NSOpenGLContext *gl_context_create(NSOpenGLContext *share) { - NSOpenGLPixelFormatAttribute attributes[] = { - NSOpenGLPFADoubleBuffer, NSOpenGLPFAOpenGLProfile, - NSOpenGLProfileVersion3_2Core, 0}; + NSOpenGLPixelFormatAttribute attributes[] = {NSOpenGLPFADoubleBuffer, NSOpenGLPFAOpenGLProfile, + NSOpenGLProfileVersion3_2Core, 0}; - NSOpenGLPixelFormat *pf; - pf = [[NSOpenGLPixelFormat alloc] initWithAttributes:attributes]; - if (!pf) { - blog(LOG_ERROR, "Failed to create pixel format"); - return NULL; - } + NSOpenGLPixelFormat *pf; + pf = [[NSOpenGLPixelFormat alloc] initWithAttributes:attributes]; + if (!pf) { + blog(LOG_ERROR, "Failed to create pixel format"); + return NULL; + } - NSOpenGLContext *context; - context = [[NSOpenGLContext alloc] initWithFormat:pf - shareContext:share]; - [pf release]; - if (!context) { - blog(LOG_ERROR, "Failed to create context"); - return NULL; - } + NSOpenGLContext *context; + context = [[NSOpenGLContext alloc] initWithFormat:pf shareContext:share]; + [pf release]; + if (!context) { + blog(LOG_ERROR, "Failed to create context"); + return NULL; + } - [context clearDrawable]; + [context clearDrawable]; - return context; + return context; } -struct gl_platform *gl_platform_create(gs_device_t *device __unused, - uint32_t adapter __unused) +struct gl_platform *gl_platform_create(gs_device_t *device __unused, uint32_t adapter __unused) { - NSOpenGLContext *context = gl_context_create(nil); - if (!context) { - blog(LOG_ERROR, "gl_context_create failed"); - return NULL; - } + NSOpenGLContext *context = gl_context_create(nil); + if (!context) { + blog(LOG_ERROR, "gl_context_create failed"); + return NULL; + } - [context makeCurrentContext]; - GLint interval = 0; - [context setValues:&interval - forParameter:NSOpenGLContextParameterSwapInterval]; - const bool success = gladLoadGL() != 0; + [context makeCurrentContext]; + GLint interval = 0; + [context setValues:&interval forParameter:NSOpenGLContextParameterSwapInterval]; + const bool success = gladLoadGL() != 0; - if (!success) { - blog(LOG_ERROR, "gladLoadGL failed"); - [context release]; - return NULL; - } + if (!success) { + blog(LOG_ERROR, "gladLoadGL failed"); + [context release]; + return NULL; + } - struct gl_platform *plat = bzalloc(sizeof(struct gl_platform)); - plat->context = context; - return plat; + struct gl_platform *plat = bzalloc(sizeof(struct gl_platform)); + plat->context = context; + return plat; } void gl_platform_destroy(struct gl_platform *platform) { - if (!platform) - return; + if (!platform) + return; - [platform->context release]; - platform->context = nil; + [platform->context release]; + platform->context = nil; - bfree(platform); + bfree(platform); } bool gl_platform_init_swapchain(struct gs_swap_chain *swap) { - NSOpenGLContext *parent = swap->device->plat->context; - NSOpenGLContext *context = gl_context_create(parent); - bool success = context != nil; - if (success) { - CGLContextObj parent_obj = [parent CGLContextObj]; - CGLLockContext(parent_obj); + NSOpenGLContext *parent = swap->device->plat->context; + NSOpenGLContext *context = gl_context_create(parent); + bool success = context != nil; + if (success) { + CGLContextObj parent_obj = [parent CGLContextObj]; + CGLLockContext(parent_obj); - [parent makeCurrentContext]; - struct gs_init_data *init_data = &swap->info; - swap->wi->texture = device_texture_create( - swap->device, init_data->cx, init_data->cy, - init_data->format, 1, NULL, GS_RENDER_TARGET); - glFlush(); - [NSOpenGLContext clearCurrentContext]; + [parent makeCurrentContext]; + struct gs_init_data *init_data = &swap->info; + swap->wi->texture = device_texture_create(swap->device, init_data->cx, init_data->cy, init_data->format, 1, + NULL, GS_RENDER_TARGET); + glFlush(); + [NSOpenGLContext clearCurrentContext]; - CGLContextObj context_obj = [context CGLContextObj]; - CGLLockContext(context_obj); + CGLContextObj context_obj = [context CGLContextObj]; + CGLLockContext(context_obj); - [context makeCurrentContext]; + [context makeCurrentContext]; #pragma clang diagnostic push #pragma GCC diagnostic ignored "-Wdeprecated-declarations" - [context setView:swap->wi->view]; + [context setView:swap->wi->view]; #pragma clang diagnostic pop - GLint interval = 0; - [context setValues:&interval - forParameter:NSOpenGLContextParameterSwapInterval]; - gl_gen_framebuffers(1, &swap->wi->fbo); - gl_bind_framebuffer(GL_FRAMEBUFFER, swap->wi->fbo); - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, - GL_TEXTURE_2D, - swap->wi->texture->texture, 0); - gl_success("glFrameBufferTexture2D"); - glFlush(); - [NSOpenGLContext clearCurrentContext]; + GLint interval = 0; + [context setValues:&interval forParameter:NSOpenGLContextParameterSwapInterval]; + gl_gen_framebuffers(1, &swap->wi->fbo); + gl_bind_framebuffer(GL_FRAMEBUFFER, swap->wi->fbo); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, swap->wi->texture->texture, 0); + gl_success("glFrameBufferTexture2D"); + glFlush(); + [NSOpenGLContext clearCurrentContext]; - CGLUnlockContext(context_obj); + CGLUnlockContext(context_obj); - CGLUnlockContext(parent_obj); + CGLUnlockContext(parent_obj); - swap->wi->context = context; - } + swap->wi->context = context; + } - return success; + return success; } void gl_platform_cleanup_swapchain(struct gs_swap_chain *swap) { - NSOpenGLContext *parent = swap->device->plat->context; - CGLContextObj parent_obj = [parent CGLContextObj]; - CGLLockContext(parent_obj); + NSOpenGLContext *parent = swap->device->plat->context; + CGLContextObj parent_obj = [parent CGLContextObj]; + CGLLockContext(parent_obj); - NSOpenGLContext *context = swap->wi->context; - CGLContextObj context_obj = [context CGLContextObj]; - CGLLockContext(context_obj); + NSOpenGLContext *context = swap->wi->context; + CGLContextObj context_obj = [context CGLContextObj]; + CGLLockContext(context_obj); - [context makeCurrentContext]; - gl_delete_framebuffers(1, &swap->wi->fbo); - glFlush(); - [NSOpenGLContext clearCurrentContext]; + [context makeCurrentContext]; + gl_delete_framebuffers(1, &swap->wi->fbo); + glFlush(); + [NSOpenGLContext clearCurrentContext]; - CGLUnlockContext(context_obj); + CGLUnlockContext(context_obj); - [parent makeCurrentContext]; - gs_texture_destroy(swap->wi->texture); - glFlush(); - [NSOpenGLContext clearCurrentContext]; - swap->wi->context = nil; + [parent makeCurrentContext]; + gs_texture_destroy(swap->wi->texture); + glFlush(); + [NSOpenGLContext clearCurrentContext]; + swap->wi->context = nil; - CGLUnlockContext(parent_obj); + CGLUnlockContext(parent_obj); } struct gl_windowinfo *gl_windowinfo_create(const struct gs_init_data *info) { - if (!info) - return NULL; + if (!info) + return NULL; - if (!info->window.view) - return NULL; + if (!info->window.view) + return NULL; - struct gl_windowinfo *wi = bzalloc(sizeof(struct gl_windowinfo)); + struct gl_windowinfo *wi = bzalloc(sizeof(struct gl_windowinfo)); - wi->view = info->window.view; - wi->view.window.colorSpace = NSColorSpace.sRGBColorSpace; + wi->view = info->window.view; + wi->view.window.colorSpace = NSColorSpace.sRGBColorSpace; #pragma clang diagnostic push #pragma GCC diagnostic ignored "-Wdeprecated-declarations" - wi->view.wantsBestResolutionOpenGLSurface = YES; + wi->view.wantsBestResolutionOpenGLSurface = YES; #pragma clang diagnostic pop - return wi; + return wi; } void gl_windowinfo_destroy(struct gl_windowinfo *wi) { - if (!wi) - return; + if (!wi) + return; - wi->view = nil; - bfree(wi); + wi->view = nil; + bfree(wi); } void gl_update(gs_device_t *device) { - gs_swapchain_t *swap = device->cur_swap; - NSOpenGLContext *parent = device->plat->context; - NSOpenGLContext *context = swap->wi->context; - dispatch_async(dispatch_get_main_queue(), ^() { - if (!swap || !swap->wi) { - return; - } + gs_swapchain_t *swap = device->cur_swap; + NSOpenGLContext *parent = device->plat->context; + NSOpenGLContext *context = swap->wi->context; + dispatch_async(dispatch_get_main_queue(), ^() { + if (!swap || !swap->wi) { + return; + } - CGLContextObj parent_obj = [parent CGLContextObj]; - CGLLockContext(parent_obj); + CGLContextObj parent_obj = [parent CGLContextObj]; + CGLLockContext(parent_obj); - CGLContextObj context_obj = [context CGLContextObj]; - CGLLockContext(context_obj); + CGLContextObj context_obj = [context CGLContextObj]; + CGLLockContext(context_obj); - [context makeCurrentContext]; - [context update]; - struct gs_init_data *info = &swap->info; - gs_texture_t *previous = swap->wi->texture; - swap->wi->texture = device_texture_create(device, info->cx, - info->cy, - info->format, 1, NULL, - GS_RENDER_TARGET); - gl_bind_framebuffer(GL_FRAMEBUFFER, swap->wi->fbo); - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, - GL_TEXTURE_2D, - swap->wi->texture->texture, 0); - gl_success("glFrameBufferTexture2D"); - gs_texture_destroy(previous); - glFlush(); - [NSOpenGLContext clearCurrentContext]; + [context makeCurrentContext]; + [context update]; + struct gs_init_data *info = &swap->info; + gs_texture_t *previous = swap->wi->texture; + swap->wi->texture = device_texture_create(device, info->cx, info->cy, info->format, 1, NULL, GS_RENDER_TARGET); + gl_bind_framebuffer(GL_FRAMEBUFFER, swap->wi->fbo); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, swap->wi->texture->texture, 0); + gl_success("glFrameBufferTexture2D"); + gs_texture_destroy(previous); + glFlush(); + [NSOpenGLContext clearCurrentContext]; - CGLUnlockContext(context_obj); + CGLUnlockContext(context_obj); - CGLUnlockContext(parent_obj); - }); + CGLUnlockContext(parent_obj); + }); } void gl_clear_context(gs_device_t *device) { - UNUSED_PARAMETER(device); - [NSOpenGLContext clearCurrentContext]; + UNUSED_PARAMETER(device); + [NSOpenGLContext clearCurrentContext]; } void device_enter_context(gs_device_t *device) { - CGLLockContext([device->plat->context CGLContextObj]); + CGLLockContext([device->plat->context CGLContextObj]); - [device->plat->context makeCurrentContext]; + [device->plat->context makeCurrentContext]; } void device_leave_context(gs_device_t *device) { - glFlush(); - [NSOpenGLContext clearCurrentContext]; - device->cur_vertex_buffer = NULL; - device->cur_index_buffer = NULL; - device->cur_render_target = NULL; - device->cur_zstencil_buffer = NULL; - device->cur_swap = NULL; - device->cur_fbo = NULL; + glFlush(); + [NSOpenGLContext clearCurrentContext]; + device->cur_vertex_buffer = NULL; + device->cur_index_buffer = NULL; + device->cur_render_target = NULL; + device->cur_zstencil_buffer = NULL; + device->cur_swap = NULL; + device->cur_fbo = NULL; - CGLUnlockContext([device->plat->context CGLContextObj]); + CGLUnlockContext([device->plat->context CGLContextObj]); } void *device_get_device_obj(gs_device_t *device) { - return device->plat->context; + return device->plat->context; } void device_load_swapchain(gs_device_t *device, gs_swapchain_t *swap) { - if (device->cur_swap == swap) - return; + if (device->cur_swap == swap) + return; - device->cur_swap = swap; - if (swap) { - device_set_render_target(device, swap->wi->texture, NULL); - } + device->cur_swap = swap; + if (swap) { + device_set_render_target(device, swap->wi->texture, NULL); + } } bool device_is_present_ready(gs_device_t *device __unused) { - return true; + return true; } void device_present(gs_device_t *device) { - glFlush(); - [NSOpenGLContext clearCurrentContext]; + glFlush(); + [NSOpenGLContext clearCurrentContext]; - CGLLockContext([device->cur_swap->wi->context CGLContextObj]); + CGLLockContext([device->cur_swap->wi->context CGLContextObj]); - [device->cur_swap->wi->context makeCurrentContext]; - gl_bind_framebuffer(GL_READ_FRAMEBUFFER, device->cur_swap->wi->fbo); - gl_bind_framebuffer(GL_DRAW_FRAMEBUFFER, 0); - const uint32_t width = device->cur_swap->info.cx; - const uint32_t height = device->cur_swap->info.cy; - glBlitFramebuffer(0, 0, width, height, 0, height, width, 0, - GL_COLOR_BUFFER_BIT, GL_NEAREST); - [device->cur_swap->wi->context flushBuffer]; - glFlush(); - [NSOpenGLContext clearCurrentContext]; + [device->cur_swap->wi->context makeCurrentContext]; + gl_bind_framebuffer(GL_READ_FRAMEBUFFER, device->cur_swap->wi->fbo); + gl_bind_framebuffer(GL_DRAW_FRAMEBUFFER, 0); + const uint32_t width = device->cur_swap->info.cx; + const uint32_t height = device->cur_swap->info.cy; + glBlitFramebuffer(0, 0, width, height, 0, height, width, 0, GL_COLOR_BUFFER_BIT, GL_NEAREST); + [device->cur_swap->wi->context flushBuffer]; + glFlush(); + [NSOpenGLContext clearCurrentContext]; - CGLUnlockContext([device->cur_swap->wi->context CGLContextObj]); + CGLUnlockContext([device->cur_swap->wi->context CGLContextObj]); - [device->plat->context makeCurrentContext]; + [device->plat->context makeCurrentContext]; } bool device_is_monitor_hdr(gs_device_t *device __unused, void *monitor __unused) { - return false; + return false; } -void gl_getclientsize(const struct gs_swap_chain *swap, uint32_t *width, - uint32_t *height) +void gl_getclientsize(const struct gs_swap_chain *swap, uint32_t *width, uint32_t *height) { - if (width) - *width = swap->info.cx; - if (height) - *height = swap->info.cy; + if (width) + *width = swap->info.cx; + if (height) + *height = swap->info.cy; } -gs_texture_t *device_texture_create_from_iosurface(gs_device_t *device, - void *iosurf) +gs_texture_t *device_texture_create_from_iosurface(gs_device_t *device, void *iosurf) { - IOSurfaceRef ref = (IOSurfaceRef)iosurf; - struct gs_texture_2d *tex = bzalloc(sizeof(struct gs_texture_2d)); + IOSurfaceRef ref = (IOSurfaceRef) iosurf; + struct gs_texture_2d *tex = bzalloc(sizeof(struct gs_texture_2d)); - OSType pf = IOSurfaceGetPixelFormat(ref); + OSType pf = IOSurfaceGetPixelFormat(ref); - FourCharCode l10r_code = 0; - l10r_code = ('l' << 24) | ('1' << 16) | ('0' << 8) | 'r'; + FourCharCode l10r_code = 0; + l10r_code = ('l' << 24) | ('1' << 16) | ('0' << 8) | 'r'; - FourCharCode bgra_code = 0; - bgra_code = ('B' << 24) | ('G' << 16) | ('R' << 8) | 'A'; + FourCharCode bgra_code = 0; + bgra_code = ('B' << 24) | ('G' << 16) | ('R' << 8) | 'A'; - const bool l10r = pf == l10r_code; - if (pf == 0) - blog(LOG_ERROR, "Invalid IOSurface Buffer"); - else if ((pf != bgra_code) && !l10r) - blog(LOG_ERROR, "Unexpected pixel format: %d (%c%c%c%c)", pf, - pf >> 24, pf >> 16, pf >> 8, pf); + const bool l10r = pf == l10r_code; + if (pf == 0) + blog(LOG_ERROR, "Invalid IOSurface Buffer"); + else if ((pf != bgra_code) && !l10r) + blog(LOG_ERROR, "Unexpected pixel format: %d (%c%c%c%c)", pf, pf >> 24, pf >> 16, pf >> 8, pf); - const enum gs_color_format color_format = l10r ? GS_R10G10B10A2 - : GS_BGRA; + const enum gs_color_format color_format = l10r ? GS_R10G10B10A2 : GS_BGRA; - tex->base.device = device; - tex->base.type = GS_TEXTURE_2D; - tex->base.format = color_format; - tex->base.levels = 1; - tex->base.gl_format = l10r ? GL_BGRA : convert_gs_format(color_format); - tex->base.gl_internal_format = convert_gs_internal_format(color_format); - tex->base.gl_type = l10r ? GL_UNSIGNED_INT_2_10_10_10_REV - : GL_UNSIGNED_INT_8_8_8_8_REV; - tex->base.gl_target = GL_TEXTURE_RECTANGLE_ARB; - tex->base.is_dynamic = false; - tex->base.is_render_target = false; - tex->base.gen_mipmaps = false; - tex->width = (uint32_t)IOSurfaceGetWidth(ref); - tex->height = (uint32_t)IOSurfaceGetHeight(ref); + tex->base.device = device; + tex->base.type = GS_TEXTURE_2D; + tex->base.format = color_format; + tex->base.levels = 1; + tex->base.gl_format = l10r ? GL_BGRA : convert_gs_format(color_format); + tex->base.gl_internal_format = convert_gs_internal_format(color_format); + tex->base.gl_type = l10r ? GL_UNSIGNED_INT_2_10_10_10_REV : GL_UNSIGNED_INT_8_8_8_8_REV; + tex->base.gl_target = GL_TEXTURE_RECTANGLE_ARB; + tex->base.is_dynamic = false; + tex->base.is_render_target = false; + tex->base.gen_mipmaps = false; + tex->width = (uint32_t) IOSurfaceGetWidth(ref); + tex->height = (uint32_t) IOSurfaceGetHeight(ref); - if (!gl_gen_textures(1, &tex->base.texture)) - goto fail; + if (!gl_gen_textures(1, &tex->base.texture)) + goto fail; - if (!gl_bind_texture(tex->base.gl_target, tex->base.texture)) - goto fail; + if (!gl_bind_texture(tex->base.gl_target, tex->base.texture)) + goto fail; - CGLError err = CGLTexImageIOSurface2D( - [[NSOpenGLContext currentContext] CGLContextObj], - tex->base.gl_target, tex->base.gl_internal_format, tex->width, - tex->height, tex->base.gl_format, tex->base.gl_type, ref, 0); + CGLError err = CGLTexImageIOSurface2D([[NSOpenGLContext currentContext] CGLContextObj], tex->base.gl_target, + tex->base.gl_internal_format, tex->width, tex->height, tex->base.gl_format, + tex->base.gl_type, ref, 0); - if (err != kCGLNoError) { - blog(LOG_ERROR, - "CGLTexImageIOSurface2D: %u, %s" - " (device_texture_create_from_iosurface)", - err, CGLErrorString(err)); + if (err != kCGLNoError) { + blog(LOG_ERROR, + "CGLTexImageIOSurface2D: %u, %s" + " (device_texture_create_from_iosurface)", + err, CGLErrorString(err)); - gl_success("CGLTexImageIOSurface2D"); - goto fail; - } + gl_success("CGLTexImageIOSurface2D"); + goto fail; + } - if (!gl_tex_param_i(tex->base.gl_target, GL_TEXTURE_MAX_LEVEL, 0)) - goto fail; + if (!gl_tex_param_i(tex->base.gl_target, GL_TEXTURE_MAX_LEVEL, 0)) + goto fail; - if (!gl_bind_texture(tex->base.gl_target, 0)) - goto fail; + if (!gl_bind_texture(tex->base.gl_target, 0)) + goto fail; - return (gs_texture_t *)tex; + return (gs_texture_t *) tex; fail: - gs_texture_destroy((gs_texture_t *)tex); - blog(LOG_ERROR, "device_texture_create_from_iosurface (GL) failed"); - return NULL; + gs_texture_destroy((gs_texture_t *) tex); + blog(LOG_ERROR, "device_texture_create_from_iosurface (GL) failed"); + return NULL; } gs_texture_t *device_texture_open_shared(gs_device_t *device, uint32_t handle) { - gs_texture_t *texture = NULL; - IOSurfaceRef ref = IOSurfaceLookupFromMachPort((mach_port_t)handle); - texture = device_texture_create_from_iosurface(device, ref); - CFRelease(ref); - return texture; + gs_texture_t *texture = NULL; + IOSurfaceRef ref = IOSurfaceLookupFromMachPort((mach_port_t) handle); + texture = device_texture_create_from_iosurface(device, ref); + CFRelease(ref); + return texture; } bool device_shared_texture_available(void) { - return true; + return true; } bool gs_texture_rebind_iosurface(gs_texture_t *texture, void *iosurf) { - if (!texture) - return false; + if (!texture) + return false; - if (!iosurf) - return false; + if (!iosurf) + return false; - FourCharCode l10r_code = 0; - l10r_code = ('l' << 24) | ('1' << 16) | ('0' << 8) | 'r'; + FourCharCode l10r_code = 0; + l10r_code = ('l' << 24) | ('1' << 16) | ('0' << 8) | 'r'; - FourCharCode bgra_code = 0; - bgra_code = ('B' << 24) | ('G' << 16) | ('R' << 8) | 'A'; + FourCharCode bgra_code = 0; + bgra_code = ('B' << 24) | ('G' << 16) | ('R' << 8) | 'A'; - struct gs_texture_2d *tex = (struct gs_texture_2d *)texture; - IOSurfaceRef ref = (IOSurfaceRef)iosurf; + struct gs_texture_2d *tex = (struct gs_texture_2d *) texture; + IOSurfaceRef ref = (IOSurfaceRef) iosurf; - OSType pf = IOSurfaceGetPixelFormat(ref); - if (pf == 0) { - blog(LOG_ERROR, "Invalid IOSurface buffer"); - } else if ((pf != bgra_code) && (pf != l10r_code)) { - blog(LOG_ERROR, "Unexpected pixel format: %d (%c%c%c%c)", pf, - pf >> 24, pf >> 16, pf >> 8, pf); - } + OSType pf = IOSurfaceGetPixelFormat(ref); + if (pf == 0) { + blog(LOG_ERROR, "Invalid IOSurface buffer"); + } else if ((pf != bgra_code) && (pf != l10r_code)) { + blog(LOG_ERROR, "Unexpected pixel format: %d (%c%c%c%c)", pf, pf >> 24, pf >> 16, pf >> 8, pf); + } - tex->width = (uint32_t)IOSurfaceGetWidth(ref); - tex->height = (uint32_t)IOSurfaceGetHeight(ref); + tex->width = (uint32_t) IOSurfaceGetWidth(ref); + tex->height = (uint32_t) IOSurfaceGetHeight(ref); - if (!gl_bind_texture(tex->base.gl_target, tex->base.texture)) - return false; + if (!gl_bind_texture(tex->base.gl_target, tex->base.texture)) + return false; - CGLError err = CGLTexImageIOSurface2D( - [[NSOpenGLContext currentContext] CGLContextObj], - tex->base.gl_target, tex->base.gl_internal_format, tex->width, - tex->height, tex->base.gl_format, tex->base.gl_type, ref, 0); + CGLError err = CGLTexImageIOSurface2D([[NSOpenGLContext currentContext] CGLContextObj], tex->base.gl_target, + tex->base.gl_internal_format, tex->width, tex->height, tex->base.gl_format, + tex->base.gl_type, ref, 0); - if (err != kCGLNoError) { - blog(LOG_ERROR, - "CGLTexImageIOSurface2D: %u, %s" - " (gs_texture_rebind_iosurface)", - err, CGLErrorString(err)); + if (err != kCGLNoError) { + blog(LOG_ERROR, + "CGLTexImageIOSurface2D: %u, %s" + " (gs_texture_rebind_iosurface)", + err, CGLErrorString(err)); - gl_success("CGLTexImageIOSurface2D"); - return false; - } + gl_success("CGLTexImageIOSurface2D"); + return false; + } - if (!gl_bind_texture(tex->base.gl_target, 0)) - return false; + if (!gl_bind_texture(tex->base.gl_target, 0)) + return false; - return true; + return true; } diff --git a/libobs/obs-cocoa.m b/libobs/obs-cocoa.m index 781d73362..2fba73cb4 100644 --- a/libobs/obs-cocoa.m +++ b/libobs/obs-cocoa.m @@ -15,7 +15,6 @@ along with this program. If not, see . ******************************************************************************/ -#include "util/platform.h" #include "util/dstr.h" #include "obs.h" #include "obs-internal.h" @@ -32,562 +31,546 @@ bool is_in_bundle() { - NSRunningApplication *app = [NSRunningApplication currentApplication]; - return [app bundleIdentifier] != nil; + NSRunningApplication *app = [NSRunningApplication currentApplication]; + return [app bundleIdentifier] != nil; } const char *get_module_extension(void) { - return ""; + return ""; } void add_default_module_paths(void) { - NSURL *pluginURL = [[NSBundle mainBundle] builtInPlugInsURL]; - NSString *pluginModulePath = [[pluginURL path] - stringByAppendingString:@"/%module%.plugin/Contents/MacOS/"]; - NSString *pluginDataPath = [[pluginURL path] - stringByAppendingString:@"/%module%.plugin/Contents/Resources/"]; + NSURL *pluginURL = [[NSBundle mainBundle] builtInPlugInsURL]; + NSString *pluginModulePath = [[pluginURL path] stringByAppendingString:@"/%module%.plugin/Contents/MacOS/"]; + NSString *pluginDataPath = [[pluginURL path] stringByAppendingString:@"/%module%.plugin/Contents/Resources/"]; - obs_add_module_path(pluginModulePath.UTF8String, - pluginDataPath.UTF8String); + obs_add_module_path(pluginModulePath.UTF8String, pluginDataPath.UTF8String); } char *find_libobs_data_file(const char *file) { - NSBundle *frameworkBundle = - [NSBundle bundleWithIdentifier:@"com.obsproject.libobs"]; - NSString *libobsDataPath = [[[frameworkBundle bundleURL] path] - stringByAppendingFormat:@"/%@/%s", @"Resources", file]; - size_t path_length = strlen(libobsDataPath.UTF8String); + NSBundle *frameworkBundle = [NSBundle bundleWithIdentifier:@"com.obsproject.libobs"]; + NSString *libobsDataPath = + [[[frameworkBundle bundleURL] path] stringByAppendingFormat:@"/%@/%s", @"Resources", file]; + size_t path_length = strlen(libobsDataPath.UTF8String); - char *path = bmalloc(path_length + 1); - snprintf(path, (path_length + 1), "%s", libobsDataPath.UTF8String); + char *path = bmalloc(path_length + 1); + snprintf(path, (path_length + 1), "%s", libobsDataPath.UTF8String); - return path; + return path; } static void log_processor_name(void) { - char *name = NULL; - size_t size; - int ret; + char *name = NULL; + size_t size; + int ret; - ret = sysctlbyname("machdep.cpu.brand_string", NULL, &size, NULL, 0); - if (ret != 0) - return; + ret = sysctlbyname("machdep.cpu.brand_string", NULL, &size, NULL, 0); + if (ret != 0) + return; - name = malloc(size); + name = malloc(size); - ret = sysctlbyname("machdep.cpu.brand_string", name, &size, NULL, 0); - if (ret == 0) - blog(LOG_INFO, "CPU Name: %s", name); + ret = sysctlbyname("machdep.cpu.brand_string", name, &size, NULL, 0); + if (ret == 0) + blog(LOG_INFO, "CPU Name: %s", name); - free(name); + free(name); } static void log_processor_speed(void) { - size_t size; - long long freq; - int ret; + size_t size; + long long freq; + int ret; - size = sizeof(freq); - ret = sysctlbyname("hw.cpufrequency", &freq, &size, NULL, 0); - if (ret == 0) - blog(LOG_INFO, "CPU Speed: %lldMHz", freq / 1000000); + size = sizeof(freq); + ret = sysctlbyname("hw.cpufrequency", &freq, &size, NULL, 0); + if (ret == 0) + blog(LOG_INFO, "CPU Speed: %lldMHz", freq / 1000000); } static void log_processor_cores(void) { - blog(LOG_INFO, "Physical Cores: %d, Logical Cores: %d", - os_get_physical_cores(), os_get_logical_cores()); + blog(LOG_INFO, "Physical Cores: %d, Logical Cores: %d", os_get_physical_cores(), os_get_logical_cores()); } static void log_emulation_status(void) { - blog(LOG_INFO, "Rosetta translation used: %s", - os_get_emulation_status() ? "true" : "false"); + blog(LOG_INFO, "Rosetta translation used: %s", os_get_emulation_status() ? "true" : "false"); } static void log_available_memory(void) { - size_t size; - long long memory_available; - int ret; + size_t size; + long long memory_available; + int ret; - size = sizeof(memory_available); - ret = sysctlbyname("hw.memsize", &memory_available, &size, NULL, 0); - if (ret == 0) - blog(LOG_INFO, "Physical Memory: %lldMB Total", - memory_available / 1024 / 1024); + size = sizeof(memory_available); + ret = sysctlbyname("hw.memsize", &memory_available, &size, NULL, 0); + if (ret == 0) + blog(LOG_INFO, "Physical Memory: %lldMB Total", memory_available / 1024 / 1024); } static void log_os(void) { - NSProcessInfo *pi = [NSProcessInfo processInfo]; - blog(LOG_INFO, "OS Name: macOS"); - blog(LOG_INFO, "OS Version: %s", - [[pi operatingSystemVersionString] UTF8String]); + NSProcessInfo *pi = [NSProcessInfo processInfo]; + blog(LOG_INFO, "OS Name: macOS"); + blog(LOG_INFO, "OS Version: %s", [[pi operatingSystemVersionString] UTF8String]); } static void log_kernel_version(void) { - char kernel_version[1024]; - size_t size = sizeof(kernel_version); - int ret; + char kernel_version[1024]; + size_t size = sizeof(kernel_version); + int ret; - ret = sysctlbyname("kern.osrelease", kernel_version, &size, NULL, 0); - if (ret == 0) - blog(LOG_INFO, "Kernel Version: %s", kernel_version); + ret = sysctlbyname("kern.osrelease", kernel_version, &size, NULL, 0); + if (ret == 0) + blog(LOG_INFO, "Kernel Version: %s", kernel_version); } void log_system_info(void) { - log_processor_name(); - log_processor_speed(); - log_processor_cores(); - log_available_memory(); - log_os(); - log_emulation_status(); - log_kernel_version(); + log_processor_name(); + log_processor_speed(); + log_processor_cores(); + log_available_memory(); + log_os(); + log_emulation_status(); + log_kernel_version(); } static bool dstr_from_cfstring(struct dstr *str, CFStringRef ref) { - CFIndex length = CFStringGetLength(ref); - CFIndex max_size = CFStringGetMaximumSizeForEncoding( - length, kCFStringEncodingUTF8); - dstr_reserve(str, max_size); + CFIndex length = CFStringGetLength(ref); + CFIndex max_size = CFStringGetMaximumSizeForEncoding(length, kCFStringEncodingUTF8); + dstr_reserve(str, max_size); - if (!CFStringGetCString(ref, str->array, max_size, - kCFStringEncodingUTF8)) - return false; + if (!CFStringGetCString(ref, str->array, max_size, kCFStringEncodingUTF8)) + return false; - str->len = strlen(str->array); - return true; + str->len = strlen(str->array); + return true; } struct obs_hotkeys_platform { - volatile long refs; - CFTypeRef monitor; - bool is_key_down[OBS_KEY_LAST_VALUE]; - TISInputSourceRef tis; - CFDataRef layout_data; - UCKeyboardLayout *layout; + volatile long refs; + CFTypeRef monitor; + bool is_key_down[OBS_KEY_LAST_VALUE]; + TISInputSourceRef tis; + CFDataRef layout_data; + UCKeyboardLayout *layout; }; static void hotkeys_retain(struct obs_hotkeys_platform *plat) { - os_atomic_inc_long(&plat->refs); + os_atomic_inc_long(&plat->refs); } static inline void free_hotkeys_platform(obs_hotkeys_platform_t *plat); static void hotkeys_release(struct obs_hotkeys_platform *plat) { - if (os_atomic_dec_long(&plat->refs) == -1) - free_hotkeys_platform(plat); + if (os_atomic_dec_long(&plat->refs) == -1) + free_hotkeys_platform(plat); } #define INVALID_KEY 0xff #pragma GCC diagnostic ignored "-Winitializer-overrides" static const int virtual_keys[] = { - [0 ... OBS_KEY_LAST_VALUE] = INVALID_KEY, + [0 ... OBS_KEY_LAST_VALUE] = INVALID_KEY, - [OBS_KEY_A] = kVK_ANSI_A, - [OBS_KEY_B] = kVK_ANSI_B, - [OBS_KEY_C] = kVK_ANSI_C, - [OBS_KEY_D] = kVK_ANSI_D, - [OBS_KEY_E] = kVK_ANSI_E, - [OBS_KEY_F] = kVK_ANSI_F, - [OBS_KEY_G] = kVK_ANSI_G, - [OBS_KEY_H] = kVK_ANSI_H, - [OBS_KEY_I] = kVK_ANSI_I, - [OBS_KEY_J] = kVK_ANSI_J, - [OBS_KEY_K] = kVK_ANSI_K, - [OBS_KEY_L] = kVK_ANSI_L, - [OBS_KEY_M] = kVK_ANSI_M, - [OBS_KEY_N] = kVK_ANSI_N, - [OBS_KEY_O] = kVK_ANSI_O, - [OBS_KEY_P] = kVK_ANSI_P, - [OBS_KEY_Q] = kVK_ANSI_Q, - [OBS_KEY_R] = kVK_ANSI_R, - [OBS_KEY_S] = kVK_ANSI_S, - [OBS_KEY_T] = kVK_ANSI_T, - [OBS_KEY_U] = kVK_ANSI_U, - [OBS_KEY_V] = kVK_ANSI_V, - [OBS_KEY_W] = kVK_ANSI_W, - [OBS_KEY_X] = kVK_ANSI_X, - [OBS_KEY_Y] = kVK_ANSI_Y, - [OBS_KEY_Z] = kVK_ANSI_Z, + [OBS_KEY_A] = kVK_ANSI_A, + [OBS_KEY_B] = kVK_ANSI_B, + [OBS_KEY_C] = kVK_ANSI_C, + [OBS_KEY_D] = kVK_ANSI_D, + [OBS_KEY_E] = kVK_ANSI_E, + [OBS_KEY_F] = kVK_ANSI_F, + [OBS_KEY_G] = kVK_ANSI_G, + [OBS_KEY_H] = kVK_ANSI_H, + [OBS_KEY_I] = kVK_ANSI_I, + [OBS_KEY_J] = kVK_ANSI_J, + [OBS_KEY_K] = kVK_ANSI_K, + [OBS_KEY_L] = kVK_ANSI_L, + [OBS_KEY_M] = kVK_ANSI_M, + [OBS_KEY_N] = kVK_ANSI_N, + [OBS_KEY_O] = kVK_ANSI_O, + [OBS_KEY_P] = kVK_ANSI_P, + [OBS_KEY_Q] = kVK_ANSI_Q, + [OBS_KEY_R] = kVK_ANSI_R, + [OBS_KEY_S] = kVK_ANSI_S, + [OBS_KEY_T] = kVK_ANSI_T, + [OBS_KEY_U] = kVK_ANSI_U, + [OBS_KEY_V] = kVK_ANSI_V, + [OBS_KEY_W] = kVK_ANSI_W, + [OBS_KEY_X] = kVK_ANSI_X, + [OBS_KEY_Y] = kVK_ANSI_Y, + [OBS_KEY_Z] = kVK_ANSI_Z, - [OBS_KEY_1] = kVK_ANSI_1, - [OBS_KEY_2] = kVK_ANSI_2, - [OBS_KEY_3] = kVK_ANSI_3, - [OBS_KEY_4] = kVK_ANSI_4, - [OBS_KEY_5] = kVK_ANSI_5, - [OBS_KEY_6] = kVK_ANSI_6, - [OBS_KEY_7] = kVK_ANSI_7, - [OBS_KEY_8] = kVK_ANSI_8, - [OBS_KEY_9] = kVK_ANSI_9, - [OBS_KEY_0] = kVK_ANSI_0, + [OBS_KEY_1] = kVK_ANSI_1, + [OBS_KEY_2] = kVK_ANSI_2, + [OBS_KEY_3] = kVK_ANSI_3, + [OBS_KEY_4] = kVK_ANSI_4, + [OBS_KEY_5] = kVK_ANSI_5, + [OBS_KEY_6] = kVK_ANSI_6, + [OBS_KEY_7] = kVK_ANSI_7, + [OBS_KEY_8] = kVK_ANSI_8, + [OBS_KEY_9] = kVK_ANSI_9, + [OBS_KEY_0] = kVK_ANSI_0, - [OBS_KEY_RETURN] = kVK_Return, - [OBS_KEY_ESCAPE] = kVK_Escape, - [OBS_KEY_BACKSPACE] = kVK_Delete, - [OBS_KEY_TAB] = kVK_Tab, - [OBS_KEY_SPACE] = kVK_Space, - [OBS_KEY_MINUS] = kVK_ANSI_Minus, - [OBS_KEY_EQUAL] = kVK_ANSI_Equal, - [OBS_KEY_BRACKETLEFT] = kVK_ANSI_LeftBracket, - [OBS_KEY_BRACKETRIGHT] = kVK_ANSI_RightBracket, - [OBS_KEY_BACKSLASH] = kVK_ANSI_Backslash, - [OBS_KEY_SEMICOLON] = kVK_ANSI_Semicolon, - [OBS_KEY_QUOTE] = kVK_ANSI_Quote, - [OBS_KEY_DEAD_GRAVE] = kVK_ANSI_Grave, - [OBS_KEY_COMMA] = kVK_ANSI_Comma, - [OBS_KEY_PERIOD] = kVK_ANSI_Period, - [OBS_KEY_SLASH] = kVK_ANSI_Slash, - [OBS_KEY_CAPSLOCK] = kVK_CapsLock, - [OBS_KEY_SECTION] = kVK_ISO_Section, + [OBS_KEY_RETURN] = kVK_Return, + [OBS_KEY_ESCAPE] = kVK_Escape, + [OBS_KEY_BACKSPACE] = kVK_Delete, + [OBS_KEY_TAB] = kVK_Tab, + [OBS_KEY_SPACE] = kVK_Space, + [OBS_KEY_MINUS] = kVK_ANSI_Minus, + [OBS_KEY_EQUAL] = kVK_ANSI_Equal, + [OBS_KEY_BRACKETLEFT] = kVK_ANSI_LeftBracket, + [OBS_KEY_BRACKETRIGHT] = kVK_ANSI_RightBracket, + [OBS_KEY_BACKSLASH] = kVK_ANSI_Backslash, + [OBS_KEY_SEMICOLON] = kVK_ANSI_Semicolon, + [OBS_KEY_QUOTE] = kVK_ANSI_Quote, + [OBS_KEY_DEAD_GRAVE] = kVK_ANSI_Grave, + [OBS_KEY_COMMA] = kVK_ANSI_Comma, + [OBS_KEY_PERIOD] = kVK_ANSI_Period, + [OBS_KEY_SLASH] = kVK_ANSI_Slash, + [OBS_KEY_CAPSLOCK] = kVK_CapsLock, + [OBS_KEY_SECTION] = kVK_ISO_Section, - [OBS_KEY_F1] = kVK_F1, - [OBS_KEY_F2] = kVK_F2, - [OBS_KEY_F3] = kVK_F3, - [OBS_KEY_F4] = kVK_F4, - [OBS_KEY_F5] = kVK_F5, - [OBS_KEY_F6] = kVK_F6, - [OBS_KEY_F7] = kVK_F7, - [OBS_KEY_F8] = kVK_F8, - [OBS_KEY_F9] = kVK_F9, - [OBS_KEY_F10] = kVK_F10, - [OBS_KEY_F11] = kVK_F11, - [OBS_KEY_F12] = kVK_F12, + [OBS_KEY_F1] = kVK_F1, + [OBS_KEY_F2] = kVK_F2, + [OBS_KEY_F3] = kVK_F3, + [OBS_KEY_F4] = kVK_F4, + [OBS_KEY_F5] = kVK_F5, + [OBS_KEY_F6] = kVK_F6, + [OBS_KEY_F7] = kVK_F7, + [OBS_KEY_F8] = kVK_F8, + [OBS_KEY_F9] = kVK_F9, + [OBS_KEY_F10] = kVK_F10, + [OBS_KEY_F11] = kVK_F11, + [OBS_KEY_F12] = kVK_F12, - [OBS_KEY_HELP] = kVK_Help, - [OBS_KEY_HOME] = kVK_Home, - [OBS_KEY_PAGEUP] = kVK_PageUp, - [OBS_KEY_DELETE] = kVK_ForwardDelete, - [OBS_KEY_END] = kVK_End, - [OBS_KEY_PAGEDOWN] = kVK_PageDown, + [OBS_KEY_HELP] = kVK_Help, + [OBS_KEY_HOME] = kVK_Home, + [OBS_KEY_PAGEUP] = kVK_PageUp, + [OBS_KEY_DELETE] = kVK_ForwardDelete, + [OBS_KEY_END] = kVK_End, + [OBS_KEY_PAGEDOWN] = kVK_PageDown, - [OBS_KEY_RIGHT] = kVK_RightArrow, - [OBS_KEY_LEFT] = kVK_LeftArrow, - [OBS_KEY_DOWN] = kVK_DownArrow, - [OBS_KEY_UP] = kVK_UpArrow, + [OBS_KEY_RIGHT] = kVK_RightArrow, + [OBS_KEY_LEFT] = kVK_LeftArrow, + [OBS_KEY_DOWN] = kVK_DownArrow, + [OBS_KEY_UP] = kVK_UpArrow, - [OBS_KEY_CLEAR] = kVK_ANSI_KeypadClear, - [OBS_KEY_NUMSLASH] = kVK_ANSI_KeypadDivide, - [OBS_KEY_NUMASTERISK] = kVK_ANSI_KeypadMultiply, - [OBS_KEY_NUMMINUS] = kVK_ANSI_KeypadMinus, - [OBS_KEY_NUMPLUS] = kVK_ANSI_KeypadPlus, - [OBS_KEY_ENTER] = kVK_ANSI_KeypadEnter, + [OBS_KEY_CLEAR] = kVK_ANSI_KeypadClear, + [OBS_KEY_NUMSLASH] = kVK_ANSI_KeypadDivide, + [OBS_KEY_NUMASTERISK] = kVK_ANSI_KeypadMultiply, + [OBS_KEY_NUMMINUS] = kVK_ANSI_KeypadMinus, + [OBS_KEY_NUMPLUS] = kVK_ANSI_KeypadPlus, + [OBS_KEY_ENTER] = kVK_ANSI_KeypadEnter, - [OBS_KEY_NUM1] = kVK_ANSI_Keypad1, - [OBS_KEY_NUM2] = kVK_ANSI_Keypad2, - [OBS_KEY_NUM3] = kVK_ANSI_Keypad3, - [OBS_KEY_NUM4] = kVK_ANSI_Keypad4, - [OBS_KEY_NUM5] = kVK_ANSI_Keypad5, - [OBS_KEY_NUM6] = kVK_ANSI_Keypad6, - [OBS_KEY_NUM7] = kVK_ANSI_Keypad7, - [OBS_KEY_NUM8] = kVK_ANSI_Keypad8, - [OBS_KEY_NUM9] = kVK_ANSI_Keypad9, - [OBS_KEY_NUM0] = kVK_ANSI_Keypad0, + [OBS_KEY_NUM1] = kVK_ANSI_Keypad1, + [OBS_KEY_NUM2] = kVK_ANSI_Keypad2, + [OBS_KEY_NUM3] = kVK_ANSI_Keypad3, + [OBS_KEY_NUM4] = kVK_ANSI_Keypad4, + [OBS_KEY_NUM5] = kVK_ANSI_Keypad5, + [OBS_KEY_NUM6] = kVK_ANSI_Keypad6, + [OBS_KEY_NUM7] = kVK_ANSI_Keypad7, + [OBS_KEY_NUM8] = kVK_ANSI_Keypad8, + [OBS_KEY_NUM9] = kVK_ANSI_Keypad9, + [OBS_KEY_NUM0] = kVK_ANSI_Keypad0, - [OBS_KEY_NUMPERIOD] = kVK_ANSI_KeypadDecimal, - [OBS_KEY_NUMEQUAL] = kVK_ANSI_KeypadEquals, + [OBS_KEY_NUMPERIOD] = kVK_ANSI_KeypadDecimal, + [OBS_KEY_NUMEQUAL] = kVK_ANSI_KeypadEquals, - [OBS_KEY_F13] = kVK_F13, - [OBS_KEY_F14] = kVK_F14, - [OBS_KEY_F15] = kVK_F15, - [OBS_KEY_F16] = kVK_F16, - [OBS_KEY_F17] = kVK_F17, - [OBS_KEY_F18] = kVK_F18, - [OBS_KEY_F19] = kVK_F19, - [OBS_KEY_F20] = kVK_F20, + [OBS_KEY_F13] = kVK_F13, + [OBS_KEY_F14] = kVK_F14, + [OBS_KEY_F15] = kVK_F15, + [OBS_KEY_F16] = kVK_F16, + [OBS_KEY_F17] = kVK_F17, + [OBS_KEY_F18] = kVK_F18, + [OBS_KEY_F19] = kVK_F19, + [OBS_KEY_F20] = kVK_F20, - [OBS_KEY_CONTROL] = kVK_Control, - [OBS_KEY_SHIFT] = kVK_Shift, - [OBS_KEY_ALT] = kVK_Option, - [OBS_KEY_META] = kVK_Command, - [OBS_KEY_CONTROL] = kVK_RightControl, + [OBS_KEY_CONTROL] = kVK_Control, + [OBS_KEY_SHIFT] = kVK_Shift, + [OBS_KEY_ALT] = kVK_Option, + [OBS_KEY_META] = kVK_Command, + [OBS_KEY_CONTROL] = kVK_RightControl, }; int obs_key_to_virtual_key(obs_key_t code) { - return virtual_keys[code]; + return virtual_keys[code]; } obs_key_t obs_key_from_virtual_key(int code) { - if (code == kVK_RightShift) - return OBS_KEY_SHIFT; - if (code == kVK_RightOption) - return OBS_KEY_ALT; - if (code == kVK_RightCommand) - return OBS_KEY_META; - if (code == kVK_RightControl) - return OBS_KEY_META; - for (size_t i = 0; i < OBS_KEY_LAST_VALUE; i++) { - if (virtual_keys[i] == code) { - return i; - } - } - return OBS_KEY_NONE; + if (code == kVK_RightShift) + return OBS_KEY_SHIFT; + if (code == kVK_RightOption) + return OBS_KEY_ALT; + if (code == kVK_RightCommand) + return OBS_KEY_META; + if (code == kVK_RightControl) + return OBS_KEY_META; + for (size_t i = 0; i < OBS_KEY_LAST_VALUE; i++) { + if (virtual_keys[i] == code) { + return i; + } + } + return OBS_KEY_NONE; } static bool localized_key_to_str(obs_key_t key, struct dstr *str) { -#define MAP_KEY(k, s) \ - case k: \ - dstr_copy(str, obs_get_hotkey_translation(k, s)); \ - return true +#define MAP_KEY(k, s) \ + case k: \ + dstr_copy(str, obs_get_hotkey_translation(k, s)); \ + return true -#define MAP_BUTTON(i) \ - case OBS_KEY_MOUSE##i: \ - dstr_copy(str, obs_get_hotkey_translation(key, "Mouse " #i)); \ - return true +#define MAP_BUTTON(i) \ + case OBS_KEY_MOUSE##i: \ + dstr_copy(str, obs_get_hotkey_translation(key, "Mouse " #i)); \ + return true - switch (key) { - MAP_KEY(OBS_KEY_SPACE, "Space"); - MAP_KEY(OBS_KEY_NUMEQUAL, "= (Keypad)"); - MAP_KEY(OBS_KEY_NUMASTERISK, "* (Keypad)"); - MAP_KEY(OBS_KEY_NUMPLUS, "+ (Keypad)"); - MAP_KEY(OBS_KEY_NUMMINUS, "- (Keypad)"); - MAP_KEY(OBS_KEY_NUMPERIOD, ". (Keypad)"); - MAP_KEY(OBS_KEY_NUMSLASH, "/ (Keypad)"); - MAP_KEY(OBS_KEY_NUM0, "0 (Keypad)"); - MAP_KEY(OBS_KEY_NUM1, "1 (Keypad)"); - MAP_KEY(OBS_KEY_NUM2, "2 (Keypad)"); - MAP_KEY(OBS_KEY_NUM3, "3 (Keypad)"); - MAP_KEY(OBS_KEY_NUM4, "4 (Keypad)"); - MAP_KEY(OBS_KEY_NUM5, "5 (Keypad)"); - MAP_KEY(OBS_KEY_NUM6, "6 (Keypad)"); - MAP_KEY(OBS_KEY_NUM7, "7 (Keypad)"); - MAP_KEY(OBS_KEY_NUM8, "8 (Keypad)"); - MAP_KEY(OBS_KEY_NUM9, "9 (Keypad)"); + switch (key) { + MAP_KEY(OBS_KEY_SPACE, "Space"); + MAP_KEY(OBS_KEY_NUMEQUAL, "= (Keypad)"); + MAP_KEY(OBS_KEY_NUMASTERISK, "* (Keypad)"); + MAP_KEY(OBS_KEY_NUMPLUS, "+ (Keypad)"); + MAP_KEY(OBS_KEY_NUMMINUS, "- (Keypad)"); + MAP_KEY(OBS_KEY_NUMPERIOD, ". (Keypad)"); + MAP_KEY(OBS_KEY_NUMSLASH, "/ (Keypad)"); + MAP_KEY(OBS_KEY_NUM0, "0 (Keypad)"); + MAP_KEY(OBS_KEY_NUM1, "1 (Keypad)"); + MAP_KEY(OBS_KEY_NUM2, "2 (Keypad)"); + MAP_KEY(OBS_KEY_NUM3, "3 (Keypad)"); + MAP_KEY(OBS_KEY_NUM4, "4 (Keypad)"); + MAP_KEY(OBS_KEY_NUM5, "5 (Keypad)"); + MAP_KEY(OBS_KEY_NUM6, "6 (Keypad)"); + MAP_KEY(OBS_KEY_NUM7, "7 (Keypad)"); + MAP_KEY(OBS_KEY_NUM8, "8 (Keypad)"); + MAP_KEY(OBS_KEY_NUM9, "9 (Keypad)"); - MAP_BUTTON(1); - MAP_BUTTON(2); - MAP_BUTTON(3); - MAP_BUTTON(4); - MAP_BUTTON(5); - MAP_BUTTON(6); - MAP_BUTTON(7); - MAP_BUTTON(8); - MAP_BUTTON(9); - MAP_BUTTON(10); - MAP_BUTTON(11); - MAP_BUTTON(12); - MAP_BUTTON(13); - MAP_BUTTON(14); - MAP_BUTTON(15); - MAP_BUTTON(16); - MAP_BUTTON(17); - MAP_BUTTON(18); - MAP_BUTTON(19); - MAP_BUTTON(20); - MAP_BUTTON(21); - MAP_BUTTON(22); - MAP_BUTTON(23); - MAP_BUTTON(24); - MAP_BUTTON(25); - MAP_BUTTON(26); - MAP_BUTTON(27); - MAP_BUTTON(28); - MAP_BUTTON(29); - default: - break; - } + MAP_BUTTON(1); + MAP_BUTTON(2); + MAP_BUTTON(3); + MAP_BUTTON(4); + MAP_BUTTON(5); + MAP_BUTTON(6); + MAP_BUTTON(7); + MAP_BUTTON(8); + MAP_BUTTON(9); + MAP_BUTTON(10); + MAP_BUTTON(11); + MAP_BUTTON(12); + MAP_BUTTON(13); + MAP_BUTTON(14); + MAP_BUTTON(15); + MAP_BUTTON(16); + MAP_BUTTON(17); + MAP_BUTTON(18); + MAP_BUTTON(19); + MAP_BUTTON(20); + MAP_BUTTON(21); + MAP_BUTTON(22); + MAP_BUTTON(23); + MAP_BUTTON(24); + MAP_BUTTON(25); + MAP_BUTTON(26); + MAP_BUTTON(27); + MAP_BUTTON(28); + MAP_BUTTON(29); + default: + break; + } #undef MAP_BUTTON #undef MAP_KEY - return false; + return false; } static bool code_to_str(int code, struct dstr *str) { -#define MAP_GLYPH(c, g) \ - case c: \ - dstr_from_wcs(str, (wchar_t[]){g, 0}); \ - return true -#define MAP_STR(c, s) \ - case c: \ - dstr_copy(str, s); \ - return true - switch (code) { - MAP_GLYPH(kVK_Return, 0x21A9); - MAP_GLYPH(kVK_Escape, 0x238B); - MAP_GLYPH(kVK_Delete, 0x232B); - MAP_GLYPH(kVK_Tab, 0x21e5); - MAP_GLYPH(kVK_CapsLock, 0x21EA); - MAP_GLYPH(kVK_ANSI_KeypadClear, 0x2327); - MAP_GLYPH(kVK_ANSI_KeypadEnter, 0x2305); - MAP_GLYPH(kVK_Help, 0x003F); - MAP_GLYPH(kVK_Home, 0x2196); - MAP_GLYPH(kVK_PageUp, 0x21de); - MAP_GLYPH(kVK_ForwardDelete, 0x2326); - MAP_GLYPH(kVK_End, 0x2198); - MAP_GLYPH(kVK_PageDown, 0x21df); +#define MAP_GLYPH(c, g) \ + case c: \ + dstr_from_wcs(str, (wchar_t[]) {g, 0}); \ + return true +#define MAP_STR(c, s) \ + case c: \ + dstr_copy(str, s); \ + return true + switch (code) { + MAP_GLYPH(kVK_Return, 0x21A9); + MAP_GLYPH(kVK_Escape, 0x238B); + MAP_GLYPH(kVK_Delete, 0x232B); + MAP_GLYPH(kVK_Tab, 0x21e5); + MAP_GLYPH(kVK_CapsLock, 0x21EA); + MAP_GLYPH(kVK_ANSI_KeypadClear, 0x2327); + MAP_GLYPH(kVK_ANSI_KeypadEnter, 0x2305); + MAP_GLYPH(kVK_Help, 0x003F); + MAP_GLYPH(kVK_Home, 0x2196); + MAP_GLYPH(kVK_PageUp, 0x21de); + MAP_GLYPH(kVK_ForwardDelete, 0x2326); + MAP_GLYPH(kVK_End, 0x2198); + MAP_GLYPH(kVK_PageDown, 0x21df); - MAP_GLYPH(kVK_RightArrow, 0x2192); - MAP_GLYPH(kVK_LeftArrow, 0x2190); - MAP_GLYPH(kVK_DownArrow, 0x2193); - MAP_GLYPH(kVK_UpArrow, 0x2191); + MAP_GLYPH(kVK_RightArrow, 0x2192); + MAP_GLYPH(kVK_LeftArrow, 0x2190); + MAP_GLYPH(kVK_DownArrow, 0x2193); + MAP_GLYPH(kVK_UpArrow, 0x2191); - MAP_STR(kVK_F1, "F1"); - MAP_STR(kVK_F2, "F2"); - MAP_STR(kVK_F3, "F3"); - MAP_STR(kVK_F4, "F4"); - MAP_STR(kVK_F5, "F5"); - MAP_STR(kVK_F6, "F6"); - MAP_STR(kVK_F7, "F7"); - MAP_STR(kVK_F8, "F8"); - MAP_STR(kVK_F9, "F9"); - MAP_STR(kVK_F10, "F10"); - MAP_STR(kVK_F11, "F11"); - MAP_STR(kVK_F12, "F12"); - MAP_STR(kVK_F13, "F13"); - MAP_STR(kVK_F14, "F14"); - MAP_STR(kVK_F15, "F15"); - MAP_STR(kVK_F16, "F16"); - MAP_STR(kVK_F17, "F17"); - MAP_STR(kVK_F18, "F18"); - MAP_STR(kVK_F19, "F19"); - MAP_STR(kVK_F20, "F20"); - MAP_GLYPH(kVK_Control, kControlUnicode); - MAP_GLYPH(kVK_Shift, kShiftUnicode); - MAP_GLYPH(kVK_Option, kOptionUnicode); - MAP_GLYPH(kVK_Command, kCommandUnicode); - MAP_GLYPH(kVK_RightControl, kControlUnicode); - MAP_GLYPH(kVK_RightShift, kShiftUnicode); - MAP_GLYPH(kVK_RightOption, kOptionUnicode); - } + MAP_STR(kVK_F1, "F1"); + MAP_STR(kVK_F2, "F2"); + MAP_STR(kVK_F3, "F3"); + MAP_STR(kVK_F4, "F4"); + MAP_STR(kVK_F5, "F5"); + MAP_STR(kVK_F6, "F6"); + MAP_STR(kVK_F7, "F7"); + MAP_STR(kVK_F8, "F8"); + MAP_STR(kVK_F9, "F9"); + MAP_STR(kVK_F10, "F10"); + MAP_STR(kVK_F11, "F11"); + MAP_STR(kVK_F12, "F12"); + MAP_STR(kVK_F13, "F13"); + MAP_STR(kVK_F14, "F14"); + MAP_STR(kVK_F15, "F15"); + MAP_STR(kVK_F16, "F16"); + MAP_STR(kVK_F17, "F17"); + MAP_STR(kVK_F18, "F18"); + MAP_STR(kVK_F19, "F19"); + MAP_STR(kVK_F20, "F20"); + MAP_GLYPH(kVK_Control, kControlUnicode); + MAP_GLYPH(kVK_Shift, kShiftUnicode); + MAP_GLYPH(kVK_Option, kOptionUnicode); + MAP_GLYPH(kVK_Command, kCommandUnicode); + MAP_GLYPH(kVK_RightControl, kControlUnicode); + MAP_GLYPH(kVK_RightShift, kShiftUnicode); + MAP_GLYPH(kVK_RightOption, kOptionUnicode); + } #undef MAP_STR #undef MAP_GLYPH - return false; + return false; } void obs_key_to_str(obs_key_t key, struct dstr *str) { - const UniCharCount max_length = 16; - UniChar buffer[max_length]; + const UniCharCount max_length = 16; + UniChar buffer[max_length]; - if (localized_key_to_str(key, str)) - return; + if (localized_key_to_str(key, str)) + return; - int code = obs_key_to_virtual_key(key); - if (code_to_str(code, str)) - return; + int code = obs_key_to_virtual_key(key); + if (code_to_str(code, str)) + return; - if (code == INVALID_KEY) { - blog(LOG_ERROR, - "hotkey-cocoa: Got invalid key while " - "translating key '%d' (%s)", - key, obs_key_to_name(key)); - goto err; - } + if (code == INVALID_KEY) { + blog(LOG_ERROR, + "hotkey-cocoa: Got invalid key while " + "translating key '%d' (%s)", + key, obs_key_to_name(key)); + goto err; + } - struct obs_hotkeys_platform *plat = NULL; + struct obs_hotkeys_platform *plat = NULL; - if (obs) { - pthread_mutex_lock(&obs->hotkeys.mutex); - plat = obs->hotkeys.platform_context; - hotkeys_retain(plat); - pthread_mutex_unlock(&obs->hotkeys.mutex); - } + if (obs) { + pthread_mutex_lock(&obs->hotkeys.mutex); + plat = obs->hotkeys.platform_context; + hotkeys_retain(plat); + pthread_mutex_unlock(&obs->hotkeys.mutex); + } - if (!plat) { - blog(LOG_ERROR, - "hotkey-cocoa: Could not get hotkey platform " - "while translating key '%d' (%s)", - key, obs_key_to_name(key)); - goto err; - } + if (!plat) { + blog(LOG_ERROR, + "hotkey-cocoa: Could not get hotkey platform " + "while translating key '%d' (%s)", + key, obs_key_to_name(key)); + goto err; + } - UInt32 dead_key_state = 0; - UniCharCount len = 0; + UInt32 dead_key_state = 0; + UniCharCount len = 0; - OSStatus err = - UCKeyTranslate(plat->layout, code, kUCKeyActionDown, - 0x104, //caps lock for upper case letters - LMGetKbdType(), kUCKeyTranslateNoDeadKeysBit, - &dead_key_state, max_length, &len, buffer); + OSStatus err = UCKeyTranslate(plat->layout, code, kUCKeyActionDown, + 0x104, //caps lock for upper case letters + LMGetKbdType(), kUCKeyTranslateNoDeadKeysBit, &dead_key_state, max_length, &len, + buffer); - if (err == noErr && len <= 0 && dead_key_state) { - err = UCKeyTranslate(plat->layout, kVK_Space, kUCKeyActionDown, - 0x104, LMGetKbdType(), - kUCKeyTranslateNoDeadKeysBit, - &dead_key_state, max_length, &len, buffer); - } + if (err == noErr && len <= 0 && dead_key_state) { + err = UCKeyTranslate(plat->layout, kVK_Space, kUCKeyActionDown, 0x104, LMGetKbdType(), + kUCKeyTranslateNoDeadKeysBit, &dead_key_state, max_length, &len, buffer); + } - hotkeys_release(plat); + hotkeys_release(plat); - if (err != noErr) { - blog(LOG_ERROR, - "hotkey-cocoa: Error while translating key '%d'" - " (0x%x, %s) to string: %d", - key, code, obs_key_to_name(key), err); - goto err; - } + if (err != noErr) { + blog(LOG_ERROR, + "hotkey-cocoa: Error while translating key '%d'" + " (0x%x, %s) to string: %d", + key, code, obs_key_to_name(key), err); + goto err; + } - if (len == 0) { - blog(LOG_ERROR, - "hotkey-cocoa: Got 0 length string while " - "translating '%d' (0x%x, %s) to string", - key, code, obs_key_to_name(key)); - goto err; - } + if (len == 0) { + blog(LOG_ERROR, + "hotkey-cocoa: Got 0 length string while " + "translating '%d' (0x%x, %s) to string", + key, code, obs_key_to_name(key)); + goto err; + } - CFStringRef string = CFStringCreateWithCharactersNoCopy( - NULL, buffer, len, kCFAllocatorNull); - if (!string) { - blog(LOG_ERROR, - "hotkey-cocoa: Could not create CFStringRef " - "while translating '%d' (0x%x, %s) to string", - key, code, obs_key_to_name(key)); - goto err; - } + CFStringRef string = CFStringCreateWithCharactersNoCopy(NULL, buffer, len, kCFAllocatorNull); + if (!string) { + blog(LOG_ERROR, + "hotkey-cocoa: Could not create CFStringRef " + "while translating '%d' (0x%x, %s) to string", + key, code, obs_key_to_name(key)); + goto err; + } - if (!dstr_from_cfstring(str, string)) { - blog(LOG_ERROR, - "hotkey-cocoa: Could not translate CFStringRef " - "to CString while translating '%d' (0x%x, %s)", - key, code, obs_key_to_name(key)); + if (!dstr_from_cfstring(str, string)) { + blog(LOG_ERROR, + "hotkey-cocoa: Could not translate CFStringRef " + "to CString while translating '%d' (0x%x, %s)", + key, code, obs_key_to_name(key)); - goto release; - } + goto release; + } - CFRelease(string); - return; + CFRelease(string); + return; release: - CFRelease(string); + CFRelease(string); err: - dstr_copy(str, obs_key_to_name(key)); + dstr_copy(str, obs_key_to_name(key)); } #define OBS_COCOA_MODIFIER_SIZE 7 static void unichar_to_utf8(const UniChar *c, char *buff) { - CFStringRef string = CFStringCreateWithCharactersNoCopy( - NULL, c, 2, kCFAllocatorNull); - if (!string) { - blog(LOG_ERROR, "hotkey-cocoa: Could not create CFStringRef " - "while populating modifier strings"); - return; - } + CFStringRef string = CFStringCreateWithCharactersNoCopy(NULL, c, 2, kCFAllocatorNull); + if (!string) { + blog(LOG_ERROR, "hotkey-cocoa: Could not create CFStringRef " + "while populating modifier strings"); + return; + } - if (!CFStringGetCString(string, buff, OBS_COCOA_MODIFIER_SIZE, - kCFStringEncodingUTF8)) - blog(LOG_ERROR, - "hotkey-cocoa: Error while populating " - " modifier string with glyph %d (0x%x)", - c[0], c[0]); + if (!CFStringGetCString(string, buff, OBS_COCOA_MODIFIER_SIZE, kCFStringEncodingUTF8)) + blog(LOG_ERROR, + "hotkey-cocoa: Error while populating " + " modifier string with glyph %d (0x%x)", + c[0], c[0]); - CFRelease(string); + CFRelease(string); } static char ctrl_str[OBS_COCOA_MODIFIER_SIZE]; @@ -596,291 +579,270 @@ static char shift_str[OBS_COCOA_MODIFIER_SIZE]; static char cmd_str[OBS_COCOA_MODIFIER_SIZE]; static void init_utf_8_strings(void) { - const UniChar ctrl_uni[] = {kControlUnicode, 0}; - const UniChar opt_uni[] = {kOptionUnicode, 0}; - const UniChar shift_uni[] = {kShiftUnicode, 0}; - const UniChar cmd_uni[] = {kCommandUnicode, 0}; + const UniChar ctrl_uni[] = {kControlUnicode, 0}; + const UniChar opt_uni[] = {kOptionUnicode, 0}; + const UniChar shift_uni[] = {kShiftUnicode, 0}; + const UniChar cmd_uni[] = {kCommandUnicode, 0}; - unichar_to_utf8(ctrl_uni, ctrl_str); - unichar_to_utf8(opt_uni, opt_str); - unichar_to_utf8(shift_uni, shift_str); - unichar_to_utf8(cmd_uni, cmd_str); + unichar_to_utf8(ctrl_uni, ctrl_str); + unichar_to_utf8(opt_uni, opt_str); + unichar_to_utf8(shift_uni, shift_str); + unichar_to_utf8(cmd_uni, cmd_str); } static pthread_once_t strings_token = PTHREAD_ONCE_INIT; void obs_key_combination_to_str(obs_key_combination_t key, struct dstr *str) { - struct dstr key_str = {0}; - if (key.key != OBS_KEY_NONE) - obs_key_to_str(key.key, &key_str); + struct dstr key_str = {0}; + if (key.key != OBS_KEY_NONE) + obs_key_to_str(key.key, &key_str); - int res = pthread_once(&strings_token, init_utf_8_strings); - if (res) { - blog(LOG_ERROR, - "hotkeys-cocoa: Error while translating " - "modifiers %d (0x%x)", - res, res); - dstr_move(str, &key_str); - return; - } + int res = pthread_once(&strings_token, init_utf_8_strings); + if (res) { + blog(LOG_ERROR, + "hotkeys-cocoa: Error while translating " + "modifiers %d (0x%x)", + res, res); + dstr_move(str, &key_str); + return; + } #define CHECK_MODIFIER(mod, str) ((key.modifiers & mod) ? str : "") - dstr_printf(str, "%s%s%s%s%s", - CHECK_MODIFIER(INTERACT_CONTROL_KEY, ctrl_str), - CHECK_MODIFIER(INTERACT_ALT_KEY, opt_str), - CHECK_MODIFIER(INTERACT_SHIFT_KEY, shift_str), - CHECK_MODIFIER(INTERACT_COMMAND_KEY, cmd_str), - key_str.len ? key_str.array : ""); + dstr_printf(str, "%s%s%s%s%s", CHECK_MODIFIER(INTERACT_CONTROL_KEY, ctrl_str), + CHECK_MODIFIER(INTERACT_ALT_KEY, opt_str), CHECK_MODIFIER(INTERACT_SHIFT_KEY, shift_str), + CHECK_MODIFIER(INTERACT_COMMAND_KEY, cmd_str), key_str.len ? key_str.array : ""); #undef CHECK_MODIFIER - dstr_free(&key_str); + dstr_free(&key_str); } static bool log_layout_name(TISInputSourceRef tis) { - struct dstr layout_name = {0}; - CFStringRef sid = (CFStringRef)TISGetInputSourceProperty( - tis, kTISPropertyInputSourceID); - if (!sid) { - blog(LOG_ERROR, "hotkeys-cocoa: Failed getting InputSourceID"); - return false; - } + struct dstr layout_name = {0}; + CFStringRef sid = (CFStringRef) TISGetInputSourceProperty(tis, kTISPropertyInputSourceID); + if (!sid) { + blog(LOG_ERROR, "hotkeys-cocoa: Failed getting InputSourceID"); + return false; + } - if (!dstr_from_cfstring(&layout_name, sid)) { - blog(LOG_ERROR, "hotkeys-cocoa: Could not convert InputSourceID" - " to CString"); - goto fail; - } + if (!dstr_from_cfstring(&layout_name, sid)) { + blog(LOG_ERROR, "hotkeys-cocoa: Could not convert InputSourceID" + " to CString"); + goto fail; + } - blog(LOG_INFO, "hotkeys-cocoa: Using layout '%s'", layout_name.array); + blog(LOG_INFO, "hotkeys-cocoa: Using layout '%s'", layout_name.array); - dstr_free(&layout_name); - return true; + dstr_free(&layout_name); + return true; fail: - dstr_free(&layout_name); - return false; + dstr_free(&layout_name); + return false; } static void handle_monitor_event(obs_hotkeys_platform_t *plat, NSEvent *event) { - if (event.type == NSEventTypeFlagsChanged) { - NSEventModifierFlags flags = event.modifierFlags; - plat->is_key_down[OBS_KEY_CAPSLOCK] = - !!(flags & NSEventModifierFlagCapsLock); - plat->is_key_down[OBS_KEY_SHIFT] = - !!(flags & NSEventModifierFlagShift); - plat->is_key_down[OBS_KEY_ALT] = - !!(flags & NSEventModifierFlagOption); - plat->is_key_down[OBS_KEY_META] = - !!(flags & NSEventModifierFlagCommand); - plat->is_key_down[OBS_KEY_CONTROL] = - !!(flags & NSEventModifierFlagControl); - } else if (event.type == NSEventTypeKeyDown || - event.type == NSEventTypeKeyUp) { - plat->is_key_down[obs_key_from_virtual_key(event.keyCode)] = - (event.type == NSEventTypeKeyDown); - } + if (event.type == NSEventTypeFlagsChanged) { + NSEventModifierFlags flags = event.modifierFlags; + plat->is_key_down[OBS_KEY_CAPSLOCK] = !!(flags & NSEventModifierFlagCapsLock); + plat->is_key_down[OBS_KEY_SHIFT] = !!(flags & NSEventModifierFlagShift); + plat->is_key_down[OBS_KEY_ALT] = !!(flags & NSEventModifierFlagOption); + plat->is_key_down[OBS_KEY_META] = !!(flags & NSEventModifierFlagCommand); + plat->is_key_down[OBS_KEY_CONTROL] = !!(flags & NSEventModifierFlagControl); + } else if (event.type == NSEventTypeKeyDown || event.type == NSEventTypeKeyUp) { + plat->is_key_down[obs_key_from_virtual_key(event.keyCode)] = (event.type == NSEventTypeKeyDown); + } } static bool init_hotkeys_platform(obs_hotkeys_platform_t **plat_) { - if (!plat_) - return false; + if (!plat_) + return false; - *plat_ = bzalloc(sizeof(obs_hotkeys_platform_t)); - obs_hotkeys_platform_t *plat = *plat_; - if (!plat) { - *plat_ = NULL; - return false; - } + *plat_ = bzalloc(sizeof(obs_hotkeys_platform_t)); + obs_hotkeys_platform_t *plat = *plat_; + if (!plat) { + *plat_ = NULL; + return false; + } - void (^handler)(NSEvent *) = ^(NSEvent *event) { - handle_monitor_event(plat, event); - }; - plat->monitor = (__bridge CFTypeRef)[NSEvent - addGlobalMonitorForEventsMatchingMask:NSEventMaskKeyDown | - NSEventMaskKeyUp | - NSEventMaskFlagsChanged - handler:handler]; + void (^handler)(NSEvent *) = ^(NSEvent *event) { + handle_monitor_event(plat, event); + }; + plat->monitor = (__bridge CFTypeRef) + [NSEvent addGlobalMonitorForEventsMatchingMask:NSEventMaskKeyDown | NSEventMaskKeyUp | NSEventMaskFlagsChanged + handler:handler]; - plat->tis = TISCopyCurrentKeyboardLayoutInputSource(); - plat->layout_data = (CFDataRef)TISGetInputSourceProperty( - plat->tis, kTISPropertyUnicodeKeyLayoutData); + plat->tis = TISCopyCurrentKeyboardLayoutInputSource(); + plat->layout_data = (CFDataRef) TISGetInputSourceProperty(plat->tis, kTISPropertyUnicodeKeyLayoutData); - if (!plat->layout_data) { - blog(LOG_ERROR, "hotkeys-cocoa: Failed getting LayoutData"); - goto fail; - } + if (!plat->layout_data) { + blog(LOG_ERROR, "hotkeys-cocoa: Failed getting LayoutData"); + goto fail; + } - CFRetain(plat->layout_data); - plat->layout = (UCKeyboardLayout *)CFDataGetBytePtr(plat->layout_data); + CFRetain(plat->layout_data); + plat->layout = (UCKeyboardLayout *) CFDataGetBytePtr(plat->layout_data); - return true; + return true; fail: - hotkeys_release(plat); - *plat_ = NULL; - return false; + hotkeys_release(plat); + *plat_ = NULL; + return false; } static inline void free_hotkeys_platform(obs_hotkeys_platform_t *plat) { - if (!plat) - return; + if (!plat) + return; - if (plat->monitor) { - CFRelease(plat->monitor); - plat->monitor = NULL; - } + if (plat->monitor) { + CFRelease(plat->monitor); + plat->monitor = NULL; + } - if (plat->tis) { - CFRelease(plat->tis); - plat->tis = NULL; - } + if (plat->tis) { + CFRelease(plat->tis); + plat->tis = NULL; + } - if (plat->layout_data) { - CFRelease(plat->layout_data); - plat->layout_data = NULL; - } + if (plat->layout_data) { + CFRelease(plat->layout_data); + plat->layout_data = NULL; + } - bfree(plat); + bfree(plat); } -static void input_method_changed(CFNotificationCenterRef nc, void *observer, - CFStringRef name, const void *object, - CFDictionaryRef user_info) +static void input_method_changed(CFNotificationCenterRef nc, void *observer, CFStringRef name, const void *object, + CFDictionaryRef user_info) { - UNUSED_PARAMETER(nc); - UNUSED_PARAMETER(name); - UNUSED_PARAMETER(object); - UNUSED_PARAMETER(user_info); + UNUSED_PARAMETER(nc); + UNUSED_PARAMETER(name); + UNUSED_PARAMETER(object); + UNUSED_PARAMETER(user_info); - struct obs_core_hotkeys *hotkeys = observer; - obs_hotkeys_platform_t *new_plat; + struct obs_core_hotkeys *hotkeys = observer; + obs_hotkeys_platform_t *new_plat; - if (init_hotkeys_platform(&new_plat)) { - obs_hotkeys_platform_t *plat; + if (init_hotkeys_platform(&new_plat)) { + obs_hotkeys_platform_t *plat; - pthread_mutex_lock(&hotkeys->mutex); - plat = hotkeys->platform_context; + pthread_mutex_lock(&hotkeys->mutex); + plat = hotkeys->platform_context; - if (new_plat && plat && - new_plat->layout_data == plat->layout_data) { - pthread_mutex_unlock(&hotkeys->mutex); - hotkeys_release(new_plat); - return; - } + if (new_plat && plat && new_plat->layout_data == plat->layout_data) { + pthread_mutex_unlock(&hotkeys->mutex); + hotkeys_release(new_plat); + return; + } - hotkeys->platform_context = new_plat; - if (new_plat) - log_layout_name(new_plat->tis); - pthread_mutex_unlock(&hotkeys->mutex); + hotkeys->platform_context = new_plat; + if (new_plat) + log_layout_name(new_plat->tis); + pthread_mutex_unlock(&hotkeys->mutex); - calldata_t params = {0}; - signal_handler_signal(hotkeys->signals, "hotkey_layout_change", - ¶ms); - if (plat) - hotkeys_release(plat); - } + calldata_t params = {0}; + signal_handler_signal(hotkeys->signals, "hotkey_layout_change", ¶ms); + if (plat) + hotkeys_release(plat); + } } bool obs_hotkeys_platform_init(struct obs_core_hotkeys *hotkeys) { - CFNotificationCenterAddObserver( - CFNotificationCenterGetDistributedCenter(), hotkeys, - input_method_changed, - kTISNotifySelectedKeyboardInputSourceChanged, NULL, - CFNotificationSuspensionBehaviorDeliverImmediately); + CFNotificationCenterAddObserver(CFNotificationCenterGetDistributedCenter(), hotkeys, input_method_changed, + kTISNotifySelectedKeyboardInputSourceChanged, NULL, + CFNotificationSuspensionBehaviorDeliverImmediately); - input_method_changed(NULL, hotkeys, NULL, NULL, NULL); - return hotkeys->platform_context != NULL; + input_method_changed(NULL, hotkeys, NULL, NULL, NULL); + return hotkeys->platform_context != NULL; } void obs_hotkeys_platform_free(struct obs_core_hotkeys *hotkeys) { - CFNotificationCenterRemoveEveryObserver( - CFNotificationCenterGetDistributedCenter(), hotkeys); + CFNotificationCenterRemoveEveryObserver(CFNotificationCenterGetDistributedCenter(), hotkeys); - hotkeys_release(hotkeys->platform_context); + hotkeys_release(hotkeys->platform_context); } typedef unsigned long NSUInteger; static bool mouse_button_pressed(obs_key_t key, bool *pressed) { - int button = 0; - switch (key) { -#define MAP_BUTTON(n) \ - case OBS_KEY_MOUSE##n: \ - button = n - 1; \ - break - MAP_BUTTON(1); - MAP_BUTTON(2); - MAP_BUTTON(3); - MAP_BUTTON(4); - MAP_BUTTON(5); - MAP_BUTTON(6); - MAP_BUTTON(7); - MAP_BUTTON(8); - MAP_BUTTON(9); - MAP_BUTTON(10); - MAP_BUTTON(11); - MAP_BUTTON(12); - MAP_BUTTON(13); - MAP_BUTTON(14); - MAP_BUTTON(15); - MAP_BUTTON(16); - MAP_BUTTON(17); - MAP_BUTTON(18); - MAP_BUTTON(19); - MAP_BUTTON(20); - MAP_BUTTON(21); - MAP_BUTTON(22); - MAP_BUTTON(23); - MAP_BUTTON(24); - MAP_BUTTON(25); - MAP_BUTTON(26); - MAP_BUTTON(27); - MAP_BUTTON(28); - MAP_BUTTON(29); - break; + int button = 0; + switch (key) { +#define MAP_BUTTON(n) \ + case OBS_KEY_MOUSE##n: \ + button = n - 1; \ + break + MAP_BUTTON(1); + MAP_BUTTON(2); + MAP_BUTTON(3); + MAP_BUTTON(4); + MAP_BUTTON(5); + MAP_BUTTON(6); + MAP_BUTTON(7); + MAP_BUTTON(8); + MAP_BUTTON(9); + MAP_BUTTON(10); + MAP_BUTTON(11); + MAP_BUTTON(12); + MAP_BUTTON(13); + MAP_BUTTON(14); + MAP_BUTTON(15); + MAP_BUTTON(16); + MAP_BUTTON(17); + MAP_BUTTON(18); + MAP_BUTTON(19); + MAP_BUTTON(20); + MAP_BUTTON(21); + MAP_BUTTON(22); + MAP_BUTTON(23); + MAP_BUTTON(24); + MAP_BUTTON(25); + MAP_BUTTON(26); + MAP_BUTTON(27); + MAP_BUTTON(28); + MAP_BUTTON(29); + break; #undef MAP_BUTTON - default: - return false; - } + default: + return false; + } - NSUInteger buttons = [NSEvent pressedMouseButtons]; - *pressed = (buttons & (1 << button)) != 0; - return true; + NSUInteger buttons = [NSEvent pressedMouseButtons]; + *pressed = (buttons & (1 << button)) != 0; + return true; } -bool obs_hotkeys_platform_is_pressed(obs_hotkeys_platform_t *plat, - obs_key_t key) +bool obs_hotkeys_platform_is_pressed(obs_hotkeys_platform_t *plat, obs_key_t key) { - bool mouse_pressed = false; - if (mouse_button_pressed(key, &mouse_pressed)) - return mouse_pressed; + bool mouse_pressed = false; + if (mouse_button_pressed(key, &mouse_pressed)) + return mouse_pressed; - if (!plat) - return false; + if (!plat) + return false; - if (key >= OBS_KEY_LAST_VALUE) - return false; + if (key >= OBS_KEY_LAST_VALUE) + return false; - return plat->is_key_down[key]; + return plat->is_key_down[key]; } void *obs_graphics_thread_autorelease(void *param) { - @autoreleasepool { - return obs_graphics_thread(param); - } + @autoreleasepool { + return obs_graphics_thread(param); + } } bool obs_graphics_thread_loop_autorelease(struct obs_graphics_context *context) { - @autoreleasepool { - return obs_graphics_thread_loop(context); - } + @autoreleasepool { + return obs_graphics_thread_loop(context); + } } diff --git a/libobs/util/platform-cocoa.m b/libobs/util/platform-cocoa.m index 678fc010b..f01a4202c 100644 --- a/libobs/util/platform-cocoa.m +++ b/libobs/util/platform-cocoa.m @@ -40,279 +40,264 @@ uint64_t os_gettime_ns(void) { - return clock_gettime_nsec_np(CLOCK_UPTIME_RAW); + return clock_gettime_nsec_np(CLOCK_UPTIME_RAW); } /* gets the location [domain mask]/Library/Application Support/[name] */ -static int os_get_path_internal(char *dst, size_t size, const char *name, - NSSearchPathDomainMask domainMask) +static int os_get_path_internal(char *dst, size_t size, const char *name, NSSearchPathDomainMask domainMask) { - NSArray *paths = NSSearchPathForDirectoriesInDomains( - NSApplicationSupportDirectory, domainMask, YES); + NSArray *paths = NSSearchPathForDirectoriesInDomains(NSApplicationSupportDirectory, domainMask, YES); - if ([paths count] == 0) - bcrash("Could not get home directory (platform-cocoa)"); + if ([paths count] == 0) + bcrash("Could not get home directory (platform-cocoa)"); - NSString *application_support = paths[0]; - const char *base_path = [application_support UTF8String]; + NSString *application_support = paths[0]; + const char *base_path = [application_support UTF8String]; - if (!name || !*name) - return snprintf(dst, size, "%s", base_path); - else - return snprintf(dst, size, "%s/%s", base_path, name); + if (!name || !*name) + return snprintf(dst, size, "%s", base_path); + else + return snprintf(dst, size, "%s/%s", base_path, name); } -static char *os_get_path_ptr_internal(const char *name, - NSSearchPathDomainMask domainMask) +static char *os_get_path_ptr_internal(const char *name, NSSearchPathDomainMask domainMask) { - NSArray *paths = NSSearchPathForDirectoriesInDomains( - NSApplicationSupportDirectory, domainMask, YES); + NSArray *paths = NSSearchPathForDirectoriesInDomains(NSApplicationSupportDirectory, domainMask, YES); - if ([paths count] == 0) - bcrash("Could not get home directory (platform-cocoa)"); + if ([paths count] == 0) + bcrash("Could not get home directory (platform-cocoa)"); - NSString *application_support = paths[0]; + NSString *application_support = paths[0]; - NSUInteger len = [application_support - lengthOfBytesUsingEncoding:NSUTF8StringEncoding]; + NSUInteger len = [application_support lengthOfBytesUsingEncoding:NSUTF8StringEncoding]; - char *path_ptr = bmalloc(len + 1); + char *path_ptr = bmalloc(len + 1); - path_ptr[len] = 0; + path_ptr[len] = 0; - memcpy(path_ptr, [application_support UTF8String], len); + memcpy(path_ptr, [application_support UTF8String], len); - struct dstr path; - dstr_init_move_array(&path, path_ptr); - dstr_cat(&path, "/"); - dstr_cat(&path, name); - return path.array; + struct dstr path; + dstr_init_move_array(&path, path_ptr); + dstr_cat(&path, "/"); + dstr_cat(&path, name); + return path.array; } int os_get_config_path(char *dst, size_t size, const char *name) { - return os_get_path_internal(dst, size, name, NSUserDomainMask); + return os_get_path_internal(dst, size, name, NSUserDomainMask); } char *os_get_config_path_ptr(const char *name) { - return os_get_path_ptr_internal(name, NSUserDomainMask); + return os_get_path_ptr_internal(name, NSUserDomainMask); } int os_get_program_data_path(char *dst, size_t size, const char *name) { - return os_get_path_internal(dst, size, name, NSLocalDomainMask); + return os_get_path_internal(dst, size, name, NSLocalDomainMask); } char *os_get_program_data_path_ptr(const char *name) { - return os_get_path_ptr_internal(name, NSLocalDomainMask); + return os_get_path_ptr_internal(name, NSLocalDomainMask); } char *os_get_executable_path_ptr(const char *name) { - char exe[PATH_MAX]; - char abs_path[PATH_MAX]; - uint32_t size = sizeof(exe); - struct dstr path; - char *slash; + char exe[PATH_MAX]; + char abs_path[PATH_MAX]; + uint32_t size = sizeof(exe); + struct dstr path; + char *slash; - if (_NSGetExecutablePath(exe, &size) != 0) { - return NULL; - } + if (_NSGetExecutablePath(exe, &size) != 0) { + return NULL; + } - if (!realpath(exe, abs_path)) { - return NULL; - } + if (!realpath(exe, abs_path)) { + return NULL; + } - dstr_init_copy(&path, abs_path); - slash = strrchr(path.array, '/'); - if (slash) { - size_t len = slash - path.array + 1; - dstr_resize(&path, len); - } + dstr_init_copy(&path, abs_path); + slash = strrchr(path.array, '/'); + if (slash) { + size_t len = slash - path.array + 1; + dstr_resize(&path, len); + } - if (name && *name) { - dstr_cat(&path, name); - } - return path.array; + if (name && *name) { + dstr_cat(&path, name); + } + return path.array; } struct os_cpu_usage_info { - int64_t last_cpu_time; - int64_t last_sys_time; - int core_count; + int64_t last_cpu_time; + int64_t last_sys_time; + int core_count; }; -static inline void add_time_value(time_value_t *dst, time_value_t *a, - time_value_t *b) +static inline void add_time_value(time_value_t *dst, time_value_t *a, time_value_t *b) { - dst->microseconds = a->microseconds + b->microseconds; - dst->seconds = a->seconds + b->seconds; + dst->microseconds = a->microseconds + b->microseconds; + dst->seconds = a->seconds + b->seconds; - if (dst->microseconds >= 1000000) { - dst->seconds += dst->microseconds / 1000000; - dst->microseconds %= 1000000; - } + if (dst->microseconds >= 1000000) { + dst->seconds += dst->microseconds / 1000000; + dst->microseconds %= 1000000; + } } static bool get_time_info(int64_t *cpu_time, int64_t *sys_time) { - mach_port_t task = mach_task_self(); - struct task_thread_times_info thread_data; - struct task_basic_info_64 task_data; - mach_msg_type_number_t count; - kern_return_t kern_ret; - time_value_t cur_time; + mach_port_t task = mach_task_self(); + struct task_thread_times_info thread_data; + struct task_basic_info_64 task_data; + mach_msg_type_number_t count; + kern_return_t kern_ret; + time_value_t cur_time; - *cpu_time = 0; - *sys_time = 0; + *cpu_time = 0; + *sys_time = 0; - count = TASK_THREAD_TIMES_INFO_COUNT; - kern_ret = task_info(task, TASK_THREAD_TIMES_INFO, - (task_info_t)&thread_data, &count); - if (kern_ret != KERN_SUCCESS) - return false; + count = TASK_THREAD_TIMES_INFO_COUNT; + kern_ret = task_info(task, TASK_THREAD_TIMES_INFO, (task_info_t) &thread_data, &count); + if (kern_ret != KERN_SUCCESS) + return false; - count = TASK_BASIC_INFO_64_COUNT; - kern_ret = task_info(task, TASK_BASIC_INFO_64, (task_info_t)&task_data, - &count); - if (kern_ret != KERN_SUCCESS) - return false; + count = TASK_BASIC_INFO_64_COUNT; + kern_ret = task_info(task, TASK_BASIC_INFO_64, (task_info_t) &task_data, &count); + if (kern_ret != KERN_SUCCESS) + return false; - add_time_value(&cur_time, &thread_data.user_time, - &thread_data.system_time); - add_time_value(&cur_time, &cur_time, &task_data.user_time); - add_time_value(&cur_time, &cur_time, &task_data.system_time); + add_time_value(&cur_time, &thread_data.user_time, &thread_data.system_time); + add_time_value(&cur_time, &cur_time, &task_data.user_time); + add_time_value(&cur_time, &cur_time, &task_data.system_time); - *cpu_time = os_gettime_ns() / 1000; - *sys_time = cur_time.seconds * 1000000 + cur_time.microseconds; - return true; + *cpu_time = os_gettime_ns() / 1000; + *sys_time = cur_time.seconds * 1000000 + cur_time.microseconds; + return true; } os_cpu_usage_info_t *os_cpu_usage_info_start(void) { - struct os_cpu_usage_info *info = bmalloc(sizeof(*info)); + struct os_cpu_usage_info *info = bmalloc(sizeof(*info)); - if (!get_time_info(&info->last_cpu_time, &info->last_sys_time)) { - bfree(info); - return NULL; - } + if (!get_time_info(&info->last_cpu_time, &info->last_sys_time)) { + bfree(info); + return NULL; + } - info->core_count = sysconf(_SC_NPROCESSORS_ONLN); - return info; + info->core_count = sysconf(_SC_NPROCESSORS_ONLN); + return info; } double os_cpu_usage_info_query(os_cpu_usage_info_t *info) { - int64_t sys_time, cpu_time; - int64_t sys_time_delta, cpu_time_delta; + int64_t sys_time, cpu_time; + int64_t sys_time_delta, cpu_time_delta; - if (!info || !get_time_info(&cpu_time, &sys_time)) - return 0.0; + if (!info || !get_time_info(&cpu_time, &sys_time)) + return 0.0; - sys_time_delta = sys_time - info->last_sys_time; - cpu_time_delta = cpu_time - info->last_cpu_time; + sys_time_delta = sys_time - info->last_sys_time; + cpu_time_delta = cpu_time - info->last_cpu_time; - if (cpu_time_delta == 0) - return 0.0; + if (cpu_time_delta == 0) + return 0.0; - info->last_sys_time = sys_time; - info->last_cpu_time = cpu_time; + info->last_sys_time = sys_time; + info->last_cpu_time = cpu_time; - return (double)sys_time_delta * 100.0 / (double)cpu_time_delta / - (double)info->core_count; + return (double) sys_time_delta * 100.0 / (double) cpu_time_delta / (double) info->core_count; } void os_cpu_usage_info_destroy(os_cpu_usage_info_t *info) { - if (info) - bfree(info); + if (info) + bfree(info); } os_performance_token_t *os_request_high_performance(const char *reason) { - @autoreleasepool { - NSProcessInfo *pi = [NSProcessInfo processInfo]; - SEL sel = @selector(beginActivityWithOptions:reason:); - if (![pi respondsToSelector:sel]) - return nil; + @autoreleasepool { + NSProcessInfo *pi = [NSProcessInfo processInfo]; + SEL sel = @selector(beginActivityWithOptions:reason:); + if (![pi respondsToSelector:sel]) + return nil; - //taken from http://stackoverflow.com/a/20100906 - id activity = [pi beginActivityWithOptions:0x00FFFFFF - reason:@(reason)]; + //taken from http://stackoverflow.com/a/20100906 + id activity = [pi beginActivityWithOptions:0x00FFFFFF reason:@(reason)]; - return CFBridgingRetain(activity); - } + return CFBridgingRetain(activity); + } } void os_end_high_performance(os_performance_token_t *token) { - @autoreleasepool { - NSProcessInfo *pi = [NSProcessInfo processInfo]; - SEL sel = @selector(beginActivityWithOptions:reason:); - if (![pi respondsToSelector:sel]) - return; + @autoreleasepool { + NSProcessInfo *pi = [NSProcessInfo processInfo]; + SEL sel = @selector(beginActivityWithOptions:reason:); + if (![pi respondsToSelector:sel]) + return; - [pi endActivity:CFBridgingRelease(token)]; - } + [pi endActivity:CFBridgingRelease(token)]; + } } struct os_inhibit_info { - CFStringRef reason; - IOPMAssertionID sleep_id; - IOPMAssertionID user_id; - bool active; + CFStringRef reason; + IOPMAssertionID sleep_id; + IOPMAssertionID user_id; + bool active; }; os_inhibit_t *os_inhibit_sleep_create(const char *reason) { - struct os_inhibit_info *info = bzalloc(sizeof(*info)); - if (!reason) - info->reason = CFStringCreateWithCString( - kCFAllocatorDefault, reason, kCFStringEncodingUTF8); - else - info->reason = - CFStringCreateCopy(kCFAllocatorDefault, CFSTR("")); + struct os_inhibit_info *info = bzalloc(sizeof(*info)); + if (!reason) + info->reason = CFStringCreateWithCString(kCFAllocatorDefault, reason, kCFStringEncodingUTF8); + else + info->reason = CFStringCreateCopy(kCFAllocatorDefault, CFSTR("")); - return info; + return info; } bool os_inhibit_sleep_set_active(os_inhibit_t *info, bool active) { - IOReturn success; + IOReturn success; - if (!info) - return false; - if (info->active == active) - return false; + if (!info) + return false; + if (info->active == active) + return false; - if (active) { - IOPMAssertionDeclareUserActivity( - info->reason, kIOPMUserActiveLocal, &info->user_id); - success = IOPMAssertionCreateWithName( - kIOPMAssertionTypeNoDisplaySleep, kIOPMAssertionLevelOn, - info->reason, &info->sleep_id); + if (active) { + IOPMAssertionDeclareUserActivity(info->reason, kIOPMUserActiveLocal, &info->user_id); + success = IOPMAssertionCreateWithName(kIOPMAssertionTypeNoDisplaySleep, kIOPMAssertionLevelOn, info->reason, + &info->sleep_id); - if (success != kIOReturnSuccess) { - blog(LOG_WARNING, "Failed to disable sleep"); - return false; - } - } else { - IOPMAssertionRelease(info->sleep_id); - } + if (success != kIOReturnSuccess) { + blog(LOG_WARNING, "Failed to disable sleep"); + return false; + } + } else { + IOPMAssertionRelease(info->sleep_id); + } - info->active = active; - return true; + info->active = active; + return true; } void os_inhibit_sleep_destroy(os_inhibit_t *info) { - if (info) { - os_inhibit_sleep_set_active(info, false); - CFRelease(info->reason); - bfree(info); - } + if (info) { + os_inhibit_sleep_set_active(info, false); + CFRelease(info->reason); + bfree(info); + } } static int physical_cores = 0; @@ -322,68 +307,64 @@ static bool core_count_initialized = false; bool os_get_emulation_status(void) { #ifdef __aarch64__ - return false; + return false; #else - int rosettaTranslated = 0; - size_t size = sizeof(rosettaTranslated); - if (sysctlbyname("sysctl.proc_translated", &rosettaTranslated, &size, - NULL, 0) == -1) - return false; + int rosettaTranslated = 0; + size_t size = sizeof(rosettaTranslated); + if (sysctlbyname("sysctl.proc_translated", &rosettaTranslated, &size, NULL, 0) == -1) + return false; - return rosettaTranslated == 1; + return rosettaTranslated == 1; #endif } static void os_get_cores_internal(void) { - if (core_count_initialized) - return; + if (core_count_initialized) + return; - core_count_initialized = true; + core_count_initialized = true; - size_t size; - int ret; + size_t size; + int ret; - size = sizeof(physical_cores); - ret = sysctlbyname("machdep.cpu.core_count", &physical_cores, &size, - NULL, 0); - if (ret != 0) - return; + size = sizeof(physical_cores); + ret = sysctlbyname("machdep.cpu.core_count", &physical_cores, &size, NULL, 0); + if (ret != 0) + return; - ret = sysctlbyname("machdep.cpu.thread_count", &logical_cores, &size, - NULL, 0); + ret = sysctlbyname("machdep.cpu.thread_count", &logical_cores, &size, NULL, 0); } int os_get_physical_cores(void) { - if (!core_count_initialized) - os_get_cores_internal(); - return physical_cores; + if (!core_count_initialized) + os_get_cores_internal(); + return physical_cores; } int os_get_logical_cores(void) { - if (!core_count_initialized) - os_get_cores_internal(); - return logical_cores; + if (!core_count_initialized) + os_get_cores_internal(); + return logical_cores; } static inline bool os_get_sys_memory_usage_internal(vm_statistics_t vmstat) { - mach_msg_type_number_t out_count = HOST_VM_INFO_COUNT; - if (host_statistics(mach_host_self(), HOST_VM_INFO, (host_info_t)vmstat, - &out_count) != KERN_SUCCESS) - return false; - return true; + mach_msg_type_number_t out_count = HOST_VM_INFO_COUNT; + if (host_statistics(mach_host_self(), HOST_VM_INFO, (host_info_t) vmstat, &out_count) != KERN_SUCCESS) + return false; + return true; } uint64_t os_get_sys_free_size(void) { - vm_statistics_data_t vmstat = {}; - if (!os_get_sys_memory_usage_internal(&vmstat)) - return 0; + vm_statistics_data_t vmstat = {}; + if (!os_get_sys_memory_usage_internal(&vmstat)) + return 0; - return vmstat.free_count * vm_page_size; + return vmstat.free_count * vm_page_size; } static uint64_t total_memory = 0; @@ -391,60 +372,58 @@ static bool total_memory_initialized = false; static void os_get_sys_total_size_internal() { - total_memory_initialized = true; + total_memory_initialized = true; - size_t size; - int ret; + size_t size; + int ret; - size = sizeof(total_memory); - ret = sysctlbyname("hw.memsize", &total_memory, &size, NULL, 0); + size = sizeof(total_memory); + ret = sysctlbyname("hw.memsize", &total_memory, &size, NULL, 0); } uint64_t os_get_sys_total_size(void) { - if (!total_memory_initialized) - os_get_sys_total_size_internal(); + if (!total_memory_initialized) + os_get_sys_total_size_internal(); - return total_memory; + return total_memory; } -static inline bool -os_get_proc_memory_usage_internal(mach_task_basic_info_data_t *taskinfo) +static inline bool os_get_proc_memory_usage_internal(mach_task_basic_info_data_t *taskinfo) { - const task_flavor_t flavor = MACH_TASK_BASIC_INFO; - mach_msg_type_number_t out_count = MACH_TASK_BASIC_INFO_COUNT; + const task_flavor_t flavor = MACH_TASK_BASIC_INFO; + mach_msg_type_number_t out_count = MACH_TASK_BASIC_INFO_COUNT; - if (task_info(mach_task_self(), flavor, (task_info_t)taskinfo, - &out_count) != KERN_SUCCESS) - return false; - return true; + if (task_info(mach_task_self(), flavor, (task_info_t) taskinfo, &out_count) != KERN_SUCCESS) + return false; + return true; } bool os_get_proc_memory_usage(os_proc_memory_usage_t *usage) { - mach_task_basic_info_data_t taskinfo = {}; - if (!os_get_proc_memory_usage_internal(&taskinfo)) - return false; + mach_task_basic_info_data_t taskinfo = {}; + if (!os_get_proc_memory_usage_internal(&taskinfo)) + return false; - usage->resident_size = taskinfo.resident_size; - usage->virtual_size = taskinfo.virtual_size; - return true; + usage->resident_size = taskinfo.resident_size; + usage->virtual_size = taskinfo.virtual_size; + return true; } uint64_t os_get_proc_resident_size(void) { - mach_task_basic_info_data_t taskinfo = {}; - if (!os_get_proc_memory_usage_internal(&taskinfo)) - return 0; - return taskinfo.resident_size; + mach_task_basic_info_data_t taskinfo = {}; + if (!os_get_proc_memory_usage_internal(&taskinfo)) + return 0; + return taskinfo.resident_size; } uint64_t os_get_proc_virtual_size(void) { - mach_task_basic_info_data_t taskinfo = {}; - if (!os_get_proc_memory_usage_internal(&taskinfo)) - return 0; - return taskinfo.virtual_size; + mach_task_basic_info_data_t taskinfo = {}; + if (!os_get_proc_memory_usage_internal(&taskinfo)) + return 0; + return taskinfo.virtual_size; } /* Obtains a copy of the contents of a CFString in specified encoding. @@ -452,84 +431,77 @@ uint64_t os_get_proc_virtual_size(void) */ char *cfstr_copy_cstr(CFStringRef cfstring, CFStringEncoding cfstring_encoding) { - if (!cfstring) - return NULL; + if (!cfstring) + return NULL; - // Try the quick way to obtain the buffer - const char *tmp_buffer = - CFStringGetCStringPtr(cfstring, cfstring_encoding); + // Try the quick way to obtain the buffer + const char *tmp_buffer = CFStringGetCStringPtr(cfstring, cfstring_encoding); - if (tmp_buffer != NULL) - return bstrdup(tmp_buffer); + if (tmp_buffer != NULL) + return bstrdup(tmp_buffer); - // The quick way did not work, try the more expensive one - CFIndex length = CFStringGetLength(cfstring); - CFIndex max_size = - CFStringGetMaximumSizeForEncoding(length, cfstring_encoding); + // The quick way did not work, try the more expensive one + CFIndex length = CFStringGetLength(cfstring); + CFIndex max_size = CFStringGetMaximumSizeForEncoding(length, cfstring_encoding); - // If result would exceed LONG_MAX, kCFNotFound is returned - if (max_size == kCFNotFound) - return NULL; + // If result would exceed LONG_MAX, kCFNotFound is returned + if (max_size == kCFNotFound) + return NULL; - // Account for the null terminator - max_size++; + // Account for the null terminator + max_size++; - char *buffer = bmalloc(max_size); + char *buffer = bmalloc(max_size); - if (buffer == NULL) { - return NULL; - } + if (buffer == NULL) { + return NULL; + } - // Copy CFString in requested encoding to buffer - Boolean success = CFStringGetCString(cfstring, buffer, max_size, - cfstring_encoding); + // Copy CFString in requested encoding to buffer + Boolean success = CFStringGetCString(cfstring, buffer, max_size, cfstring_encoding); - if (!success) { - bfree(buffer); - buffer = NULL; - } - return buffer; + if (!success) { + bfree(buffer); + buffer = NULL; + } + return buffer; } /* Copies the contents of a CFString in specified encoding to a given dstr. * Returns true on success or false on failure. * In case of failure, the dstr capacity but not size is changed. */ -bool cfstr_copy_dstr(CFStringRef cfstring, CFStringEncoding cfstring_encoding, - struct dstr *str) +bool cfstr_copy_dstr(CFStringRef cfstring, CFStringEncoding cfstring_encoding, struct dstr *str) { - if (!cfstring) - return false; + if (!cfstring) + return false; - // Try the quick way to obtain the buffer - const char *tmp_buffer = - CFStringGetCStringPtr(cfstring, cfstring_encoding); + // Try the quick way to obtain the buffer + const char *tmp_buffer = CFStringGetCStringPtr(cfstring, cfstring_encoding); - if (tmp_buffer != NULL) { - dstr_copy(str, tmp_buffer); - return true; - } + if (tmp_buffer != NULL) { + dstr_copy(str, tmp_buffer); + return true; + } - // The quick way did not work, try the more expensive one - CFIndex length = CFStringGetLength(cfstring); - CFIndex max_size = - CFStringGetMaximumSizeForEncoding(length, cfstring_encoding); + // The quick way did not work, try the more expensive one + CFIndex length = CFStringGetLength(cfstring); + CFIndex max_size = CFStringGetMaximumSizeForEncoding(length, cfstring_encoding); - // If result would exceed LONG_MAX, kCFNotFound is returned - if (max_size == kCFNotFound) - return NULL; + // If result would exceed LONG_MAX, kCFNotFound is returned + if (max_size == kCFNotFound) + return NULL; - // Account for the null terminator - max_size++; + // Account for the null terminator + max_size++; - dstr_ensure_capacity(str, max_size); + dstr_ensure_capacity(str, max_size); - // Copy CFString in requested encoding to dstr buffer - Boolean success = CFStringGetCString(cfstring, str->array, max_size, - cfstring_encoding); + // Copy CFString in requested encoding to dstr buffer + Boolean success = CFStringGetCString(cfstring, str->array, max_size, cfstring_encoding); - if (success) - dstr_resize(str, max_size); + if (success) + dstr_resize(str, max_size); - return (bool)success; + return (bool) success; } diff --git a/plugins/mac-avcapture/av-capture.mm b/plugins/mac-avcapture/av-capture.mm index 2f87aa634..5e73cf300 100644 --- a/plugins/mac-avcapture/av-capture.mm +++ b/plugins/mac-avcapture/av-capture.mm @@ -27,29 +27,35 @@ using namespace std; namespace std { -template<> struct default_delete { - void operator()(obs_data_t *data) { obs_data_release(data); } -}; + template<> struct default_delete { + void operator()(obs_data_t *data) + { + obs_data_release(data); + } + }; -template<> struct default_delete { - void operator()(obs_data_item_t *item) { obs_data_item_release(&item); } -}; + template<> struct default_delete { + void operator()(obs_data_item_t *item) + { + obs_data_item_release(&item); + } + }; } -#define TEXT_AVCAPTURE obs_module_text("AVCapture") -#define TEXT_DEVICE obs_module_text("Device") -#define TEXT_USE_PRESET obs_module_text("UsePreset") -#define TEXT_PRESET obs_module_text("Preset") -#define TEXT_RESOLUTION obs_module_text("Resolution") -#define TEXT_FRAME_RATE obs_module_text("FrameRate") -#define TEXT_MATCH_OBS obs_module_text("MatchOBS") -#define TEXT_INPUT_FORMAT obs_module_text("InputFormat") -#define TEXT_COLOR_SPACE obs_module_text("ColorSpace") -#define TEXT_VIDEO_RANGE obs_module_text("VideoRange") +#define TEXT_AVCAPTURE obs_module_text("AVCapture") +#define TEXT_DEVICE obs_module_text("Device") +#define TEXT_USE_PRESET obs_module_text("UsePreset") +#define TEXT_PRESET obs_module_text("Preset") +#define TEXT_RESOLUTION obs_module_text("Resolution") +#define TEXT_FRAME_RATE obs_module_text("FrameRate") +#define TEXT_MATCH_OBS obs_module_text("MatchOBS") +#define TEXT_INPUT_FORMAT obs_module_text("InputFormat") +#define TEXT_COLOR_SPACE obs_module_text("ColorSpace") +#define TEXT_VIDEO_RANGE obs_module_text("VideoRange") #define TEXT_RANGE_PARTIAL obs_module_text("VideoRange.Partial") -#define TEXT_RANGE_FULL obs_module_text("VideoRange.Full") -#define TEXT_AUTO obs_module_text("Auto") +#define TEXT_RANGE_FULL obs_module_text("VideoRange.Full") +#define TEXT_AUTO obs_module_text("Auto") #define TEXT_COLOR_UNKNOWN_NAME "Unknown" #define TEXT_RANGE_UNKNOWN_NAME "Unknown" @@ -60,843 +66,792 @@ static const int VIDEO_RANGE_AUTO = -1; #define MILLI_TIMESCALE 1000 #define MICRO_TIMESCALE (MILLI_TIMESCALE * 1000) -#define NANO_TIMESCALE (MICRO_TIMESCALE * 1000) +#define NANO_TIMESCALE (MICRO_TIMESCALE * 1000) -#define AV_FOURCC_STR(code) \ - (char[5]) \ - { \ - static_cast((code >> 24) & 0xFF), \ - static_cast((code >> 16) & 0xFF), \ - static_cast((code >> 8) & 0xFF), \ - static_cast(code & 0xFF), 0 \ - } +#define AV_FOURCC_STR(code) \ + (char[5]) \ + { \ + static_cast((code >> 24) & 0xFF), static_cast((code >> 16) & 0xFF), \ + static_cast((code >> 8) & 0xFF), static_cast(code & 0xFF), 0 \ + } struct av_capture; -#define AVLOG(level, format, ...) \ - blog(level, "%s: " format, obs_source_get_name(capture->source), \ - ##__VA_ARGS__) +#define AVLOG(level, format, ...) blog(level, "%s: " format, obs_source_get_name(capture->source), ##__VA_ARGS__) @interface OBSAVCaptureDelegate - : NSObject { -@public - struct av_capture *capture; + : NSObject { + @public + struct av_capture *capture; } - (void)captureOutput:(AVCaptureOutput *)out - didDropSampleBuffer:(CMSampleBufferRef)sampleBuffer - fromConnection:(AVCaptureConnection *)connection; + didDropSampleBuffer:(CMSampleBufferRef)sampleBuffer + fromConnection:(AVCaptureConnection *)connection; - (void)captureOutput:(AVCaptureOutput *)captureOutput - didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer - fromConnection:(AVCaptureConnection *)connection; + didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer + fromConnection:(AVCaptureConnection *)connection; @end namespace { -static auto remove_observer = [](id observer) { - [[NSNotificationCenter defaultCenter] removeObserver:observer]; -}; + static auto remove_observer = [](id observer) { + [[NSNotificationCenter defaultCenter] removeObserver:observer]; + }; -struct observer_handle - : unique_ptr::type, decltype(remove_observer)> { + struct observer_handle : unique_ptr::type, decltype(remove_observer)> { + using base = unique_ptr::type, decltype(remove_observer)>; - using base = - unique_ptr::type, decltype(remove_observer)>; + explicit observer_handle(id observer = nullptr) : base(observer, remove_observer) + {} + }; - explicit observer_handle(id observer = nullptr) - : base(observer, remove_observer) - { - } -}; - -struct av_video_info { - video_colorspace colorspace; - video_range_type video_range; - bool video_params_valid = false; -}; + struct av_video_info { + video_colorspace colorspace; + video_range_type video_range; + bool video_params_valid = false; + }; } struct av_capture { - OBSAVCaptureDelegate *delegate; - dispatch_queue_t queue; - dispatch_queue_t audioQueue; - bool has_clock; + OBSAVCaptureDelegate *delegate; + dispatch_queue_t queue; + dispatch_queue_t audioQueue; + bool has_clock; - bool device_locked; + bool device_locked; - left_right::left_right video_info; + left_right::left_right video_info; - AVCaptureVideoDataOutput *out; - AVCaptureAudioDataOutput *audioOut; - AVCaptureDevice *device; - AVCaptureDeviceInput *device_input; - AVCaptureSession *session; + AVCaptureVideoDataOutput *out; + AVCaptureAudioDataOutput *audioOut; + AVCaptureDevice *device; + AVCaptureDeviceInput *device_input; + AVCaptureSession *session; - NSString *uid; - observer_handle connect_observer; - observer_handle disconnect_observer; + NSString *uid; + observer_handle connect_observer; + observer_handle disconnect_observer; - FourCharCode fourcc; - video_format video_format; + FourCharCode fourcc; + video_format video_format; - bool use_preset = false; - int requested_colorspace = COLOR_SPACE_AUTO; - int requested_video_range = VIDEO_RANGE_AUTO; - bool enable_audio; + bool use_preset = false; + int requested_colorspace = COLOR_SPACE_AUTO; + int requested_video_range = VIDEO_RANGE_AUTO; + bool enable_audio; - obs_source_t *source; + obs_source_t *source; - obs_source_frame frame; - obs_source_audio audio; + obs_source_frame frame; + obs_source_audio audio; }; static NSString *get_string(obs_data_t *data, char const *name) { - return @(obs_data_get_string(data, name)); + return @(obs_data_get_string(data, name)); } static AVCaptureDevice *get_device(obs_data_t *settings) { - auto uid = get_string(settings, "device"); - return [AVCaptureDevice deviceWithUniqueID:uid]; + auto uid = get_string(settings, "device"); + return [AVCaptureDevice deviceWithUniqueID:uid]; } template -static void clamp(T &store, U val, T low = numeric_limits::min(), - T high = numeric_limits::max()) +static void clamp(T &store, U val, T low = numeric_limits::min(), T high = numeric_limits::max()) { - store = static_cast(val) < static_cast(low) - ? low - : (static_cast(val) > - static_cast(high) - ? high - : static_cast(val)); + store = static_cast(val) < static_cast(low) + ? low + : (static_cast(val) > static_cast(high) ? high : static_cast(val)); } static bool get_resolution(obs_data_t *settings, CMVideoDimensions &dims) { - using item_ptr = unique_ptr; - item_ptr item{obs_data_item_byname(settings, "resolution")}; - if (!item) - return false; + using item_ptr = unique_ptr; + item_ptr item {obs_data_item_byname(settings, "resolution")}; + if (!item) + return false; - auto res_str = obs_data_item_get_string(item.get()); - unique_ptr res{obs_data_create_from_json(res_str)}; - if (!res) - return false; + auto res_str = obs_data_item_get_string(item.get()); + unique_ptr res {obs_data_create_from_json(res_str)}; + if (!res) + return false; - item_ptr width{obs_data_item_byname(res.get(), "width")}; - item_ptr height{obs_data_item_byname(res.get(), "height")}; + item_ptr width {obs_data_item_byname(res.get(), "width")}; + item_ptr height {obs_data_item_byname(res.get(), "height")}; - if (!width || !height) - return false; + if (!width || !height) + return false; - clamp(dims.width, obs_data_item_get_int(width.get()), 0); - clamp(dims.height, obs_data_item_get_int(height.get()), 0); + clamp(dims.width, obs_data_item_get_int(width.get()), 0); + clamp(dims.height, obs_data_item_get_int(height.get()), 0); - if (!dims.width || !dims.height) - return false; + if (!dims.width || !dims.height) + return false; - return true; + return true; } static bool get_input_format(obs_data_t *settings, FourCharCode &fourcc) { - auto item = unique_ptr{ - obs_data_item_byname(settings, "input_format")}; - if (!item) - return false; + auto item = unique_ptr {obs_data_item_byname(settings, "input_format")}; + if (!item) + return false; - fourcc = (FourCharCode)obs_data_item_get_int(item.get()); - return true; + fourcc = (FourCharCode) obs_data_item_get_int(item.get()); + return true; } namespace { -struct config_helper { - obs_data_t *settings = nullptr; + struct config_helper { + obs_data_t *settings = nullptr; - AVCaptureDevice *dev_ = nullptr; + AVCaptureDevice *dev_ = nullptr; - bool dims_valid : 1; - bool fr_valid : 1; - bool fps_valid : 1; - bool if_valid : 1; + bool dims_valid : 1; + bool fr_valid : 1; + bool fps_valid : 1; + bool if_valid : 1; - CMVideoDimensions dims_{}; + CMVideoDimensions dims_ {}; - const char *frame_rate_ = nullptr; - media_frames_per_second fps_{}; + const char *frame_rate_ = nullptr; + media_frames_per_second fps_ {}; - FourCharCode input_format_ = INPUT_FORMAT_AUTO; + FourCharCode input_format_ = INPUT_FORMAT_AUTO; - explicit config_helper(obs_data_t *settings) : settings(settings) - { - dev_ = get_device(settings); + explicit config_helper(obs_data_t *settings) : settings(settings) + { + dev_ = get_device(settings); - dims_valid = get_resolution(settings, dims_); + dims_valid = get_resolution(settings, dims_); - fr_valid = obs_data_get_frames_per_second( - settings, "frame_rate", nullptr, &frame_rate_); - fps_valid = obs_data_get_frames_per_second( - settings, "frame_rate", &fps_, nullptr); + fr_valid = obs_data_get_frames_per_second(settings, "frame_rate", nullptr, &frame_rate_); + fps_valid = obs_data_get_frames_per_second(settings, "frame_rate", &fps_, nullptr); - if_valid = get_input_format(settings, input_format_); - } + if_valid = get_input_format(settings, input_format_); + } - AVCaptureDevice *dev() const { return dev_; } + AVCaptureDevice *dev() const + { + return dev_; + } - const CMVideoDimensions *dims() const - { - return dims_valid ? &dims_ : nullptr; - } + const CMVideoDimensions *dims() const + { + return dims_valid ? &dims_ : nullptr; + } - const char *frame_rate() const - { - return fr_valid ? frame_rate_ : nullptr; - } + const char *frame_rate() const + { + return fr_valid ? frame_rate_ : nullptr; + } - const media_frames_per_second *fps() const - { - return fps_valid ? &fps_ : nullptr; - } + const media_frames_per_second *fps() const + { + return fps_valid ? &fps_ : nullptr; + } - const FourCharCode *input_format() const - { - return if_valid ? &input_format_ : nullptr; - } -}; + const FourCharCode *input_format() const + { + return if_valid ? &input_format_ : nullptr; + } + }; -struct av_capture_ref { - av_capture *capture = nullptr; - OBSSource source; + struct av_capture_ref { + av_capture *capture = nullptr; + OBSSource source; - av_capture_ref() = default; + av_capture_ref() = default; - av_capture_ref(av_capture *capture_, obs_weak_source_t *weak_source) - : source(OBSGetStrongRef(weak_source)) - { - if (!source) - return; + av_capture_ref(av_capture *capture_, obs_weak_source_t *weak_source) : source(OBSGetStrongRef(weak_source)) + { + if (!source) + return; - capture = capture_; - } + capture = capture_; + } - operator av_capture *() { return capture; } + operator av_capture *() + { + return capture; + } - av_capture *operator->() { return capture; } -}; + av_capture *operator->() + { + return capture; + } + }; -struct properties_param { - av_capture *capture = nullptr; - OBSWeakSource weak_source; + struct properties_param { + av_capture *capture = nullptr; + OBSWeakSource weak_source; - properties_param(av_capture *capture) : capture(capture) - { - if (!capture) - return; + properties_param(av_capture *capture) : capture(capture) + { + if (!capture) + return; - weak_source = OBSGetWeakRef(capture->source); - } + weak_source = OBSGetWeakRef(capture->source); + } - av_capture_ref get_ref() { return {capture, weak_source}; } -}; + av_capture_ref get_ref() + { + return {capture, weak_source}; + } + }; } static av_capture_ref get_ref(obs_properties_t *props) { - void *param = obs_properties_get_param(props); - if (!param) - return {}; + void *param = obs_properties_get_param(props); + if (!param) + return {}; - return static_cast(param)->get_ref(); + return static_cast(param)->get_ref(); } static inline video_format format_from_subtype(FourCharCode subtype) { - //TODO: uncomment VIDEO_FORMAT_NV12 and VIDEO_FORMAT_ARGB once libobs - // gains matching GPU conversions or a CPU fallback is implemented - switch (subtype) { - case kCVPixelFormatType_422YpCbCr8: - return VIDEO_FORMAT_UYVY; - case kCVPixelFormatType_422YpCbCr8_yuvs: - return VIDEO_FORMAT_YUY2; - /*case kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange: - case kCVPixelFormatType_420YpCbCr8BiPlanarFullRange: - return VIDEO_FORMAT_NV12;*/ - /*case kCVPixelFormatType_32ARGB: - return VIDEO_FORMAT_ARGB;*/ - case kCVPixelFormatType_32BGRA: - return VIDEO_FORMAT_BGRA; - default: - return VIDEO_FORMAT_NONE; - } + //TODO: uncomment VIDEO_FORMAT_NV12 and VIDEO_FORMAT_ARGB once libobs + // gains matching GPU conversions or a CPU fallback is implemented + switch (subtype) { + case kCVPixelFormatType_422YpCbCr8: + return VIDEO_FORMAT_UYVY; + case kCVPixelFormatType_422YpCbCr8_yuvs: + return VIDEO_FORMAT_YUY2; + /* case kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange: + * case kCVPixelFormatType_420YpCbCr8BiPlanarFullRange: + * return VIDEO_FORMAT_NV12; + * case kCVPixelFormatType_32ARGB: + * return VIDEO_FORMAT_ARGB; + */ + case kCVPixelFormatType_32BGRA: + return VIDEO_FORMAT_BGRA; + default: + return VIDEO_FORMAT_NONE; + } } static const char *fourcc_subtype_name(FourCharCode fourcc); -static const char * -format_description_subtype_name(CMFormatDescriptionRef desc, - FourCharCode *fourcc_ = nullptr) +static const char *format_description_subtype_name(CMFormatDescriptionRef desc, FourCharCode *fourcc_ = nullptr) { - FourCharCode fourcc = CMFormatDescriptionGetMediaSubType(desc); - if (fourcc_) - *fourcc_ = fourcc; + FourCharCode fourcc = CMFormatDescriptionGetMediaSubType(desc); + if (fourcc_) + *fourcc_ = fourcc; - return fourcc_subtype_name(fourcc); + return fourcc_subtype_name(fourcc); } static const char *fourcc_subtype_name(FourCharCode fourcc) { - switch (fourcc) { - case kCVPixelFormatType_422YpCbCr8: - return "UYVY - 422YpCbCr8"; //VIDEO_FORMAT_UYVY; - case kCVPixelFormatType_422YpCbCr8_yuvs: - return "YUY2 - 422YpCbCr8_yuvs"; //VIDEO_FORMAT_YUY2; - case kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange: - case kCVPixelFormatType_420YpCbCr8BiPlanarFullRange: - return "NV12 - 420YpCbCr8BiPlanar"; //VIDEO_FORMAT_NV12; - case kCVPixelFormatType_32ARGB: - return "ARGB - 32ARGB"; //VIDEO_FORMAT_ARGB;*/ - case kCVPixelFormatType_32BGRA: - return "BGRA - 32BGRA"; //VIDEO_FORMAT_BGRA; + switch (fourcc) { + case kCVPixelFormatType_422YpCbCr8: + return "UYVY - 422YpCbCr8"; //VIDEO_FORMAT_UYVY; + case kCVPixelFormatType_422YpCbCr8_yuvs: + return "YUY2 - 422YpCbCr8_yuvs"; //VIDEO_FORMAT_YUY2; + case kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange: + case kCVPixelFormatType_420YpCbCr8BiPlanarFullRange: + return "NV12 - 420YpCbCr8BiPlanar"; //VIDEO_FORMAT_NV12; + case kCVPixelFormatType_32ARGB: + return "ARGB - 32ARGB"; //VIDEO_FORMAT_ARGB;*/ + case kCVPixelFormatType_32BGRA: + return "BGRA - 32BGRA"; //VIDEO_FORMAT_BGRA; - case kCMVideoCodecType_Animation: - return "Apple Animation"; - case kCMVideoCodecType_Cinepak: - return "Cinepak"; - case kCMVideoCodecType_JPEG: - return "JPEG"; - case kCMVideoCodecType_JPEG_OpenDML: - return "MJPEG - JPEG OpenDML"; - case kCMVideoCodecType_SorensonVideo: - return "Sorenson Video"; - case kCMVideoCodecType_SorensonVideo3: - return "Sorenson Video 3"; - case kCMVideoCodecType_H263: - return "H.263"; - case kCMVideoCodecType_H264: - return "H.264"; - case kCMVideoCodecType_MPEG4Video: - return "MPEG-4"; - case kCMVideoCodecType_MPEG2Video: - return "MPEG-2"; - case kCMVideoCodecType_MPEG1Video: - return "MPEG-1"; + case kCMVideoCodecType_Animation: + return "Apple Animation"; + case kCMVideoCodecType_Cinepak: + return "Cinepak"; + case kCMVideoCodecType_JPEG: + return "JPEG"; + case kCMVideoCodecType_JPEG_OpenDML: + return "MJPEG - JPEG OpenDML"; + case kCMVideoCodecType_SorensonVideo: + return "Sorenson Video"; + case kCMVideoCodecType_SorensonVideo3: + return "Sorenson Video 3"; + case kCMVideoCodecType_H263: + return "H.263"; + case kCMVideoCodecType_H264: + return "H.264"; + case kCMVideoCodecType_MPEG4Video: + return "MPEG-4"; + case kCMVideoCodecType_MPEG2Video: + return "MPEG-2"; + case kCMVideoCodecType_MPEG1Video: + return "MPEG-1"; - case kCMVideoCodecType_DVCNTSC: - return "DV NTSC"; - case kCMVideoCodecType_DVCPAL: - return "DV PAL"; - case kCMVideoCodecType_DVCProPAL: - return "Panasonic DVCPro PAL"; - case kCMVideoCodecType_DVCPro50NTSC: - return "Panasonic DVCPro-50 NTSC"; - case kCMVideoCodecType_DVCPro50PAL: - return "Panasonic DVCPro-50 PAL"; - case kCMVideoCodecType_DVCPROHD720p60: - return "Panasonic DVCPro-HD 720p60"; - case kCMVideoCodecType_DVCPROHD720p50: - return "Panasonic DVCPro-HD 720p50"; - case kCMVideoCodecType_DVCPROHD1080i60: - return "Panasonic DVCPro-HD 1080i60"; - case kCMVideoCodecType_DVCPROHD1080i50: - return "Panasonic DVCPro-HD 1080i50"; - case kCMVideoCodecType_DVCPROHD1080p30: - return "Panasonic DVCPro-HD 1080p30"; - case kCMVideoCodecType_DVCPROHD1080p25: - return "Panasonic DVCPro-HD 1080p25"; + case kCMVideoCodecType_DVCNTSC: + return "DV NTSC"; + case kCMVideoCodecType_DVCPAL: + return "DV PAL"; + case kCMVideoCodecType_DVCProPAL: + return "Panasonic DVCPro PAL"; + case kCMVideoCodecType_DVCPro50NTSC: + return "Panasonic DVCPro-50 NTSC"; + case kCMVideoCodecType_DVCPro50PAL: + return "Panasonic DVCPro-50 PAL"; + case kCMVideoCodecType_DVCPROHD720p60: + return "Panasonic DVCPro-HD 720p60"; + case kCMVideoCodecType_DVCPROHD720p50: + return "Panasonic DVCPro-HD 720p50"; + case kCMVideoCodecType_DVCPROHD1080i60: + return "Panasonic DVCPro-HD 1080i60"; + case kCMVideoCodecType_DVCPROHD1080i50: + return "Panasonic DVCPro-HD 1080i50"; + case kCMVideoCodecType_DVCPROHD1080p30: + return "Panasonic DVCPro-HD 1080p30"; + case kCMVideoCodecType_DVCPROHD1080p25: + return "Panasonic DVCPro-HD 1080p25"; - case kCMVideoCodecType_AppleProRes4444: - return "Apple ProRes 4444"; - case kCMVideoCodecType_AppleProRes422HQ: - return "Apple ProRes 422 HQ"; - case kCMVideoCodecType_AppleProRes422: - return "Apple ProRes 422"; - case kCMVideoCodecType_AppleProRes422LT: - return "Apple ProRes 422 LT"; - case kCMVideoCodecType_AppleProRes422Proxy: - return "Apple ProRes 422 Proxy"; + case kCMVideoCodecType_AppleProRes4444: + return "Apple ProRes 4444"; + case kCMVideoCodecType_AppleProRes422HQ: + return "Apple ProRes 422 HQ"; + case kCMVideoCodecType_AppleProRes422: + return "Apple ProRes 422"; + case kCMVideoCodecType_AppleProRes422LT: + return "Apple ProRes 422 LT"; + case kCMVideoCodecType_AppleProRes422Proxy: + return "Apple ProRes 422 Proxy"; - default: - blog(LOG_INFO, "Unknown format %s", AV_FOURCC_STR(fourcc)); - return "unknown"; - } + default: + blog(LOG_INFO, "Unknown format %s", AV_FOURCC_STR(fourcc)); + return "unknown"; + } } static inline bool is_fullrange_yuv(FourCharCode pixel_format) { - switch (pixel_format) { - case kCVPixelFormatType_420YpCbCr8PlanarFullRange: - case kCVPixelFormatType_420YpCbCr8BiPlanarFullRange: - case kCVPixelFormatType_422YpCbCr8FullRange: - return true; + switch (pixel_format) { + case kCVPixelFormatType_420YpCbCr8PlanarFullRange: + case kCVPixelFormatType_420YpCbCr8BiPlanarFullRange: + case kCVPixelFormatType_422YpCbCr8FullRange: + return true; - default: - return false; - } + default: + return false; + } } static inline video_colorspace get_colorspace(CMFormatDescriptionRef desc) { - CFPropertyListRef matrix = CMFormatDescriptionGetExtension( - desc, kCMFormatDescriptionExtension_YCbCrMatrix); + CFPropertyListRef matrix = CMFormatDescriptionGetExtension(desc, kCMFormatDescriptionExtension_YCbCrMatrix); - if (!matrix) - return VIDEO_CS_DEFAULT; + if (!matrix) + return VIDEO_CS_DEFAULT; - if (CFStringCompare(static_cast(matrix), - kCVImageBufferYCbCrMatrix_ITU_R_601_4, - 0) == kCFCompareEqualTo) - return VIDEO_CS_601; + if (CFStringCompare(static_cast(matrix), kCVImageBufferYCbCrMatrix_ITU_R_601_4, 0) == + kCFCompareEqualTo) + return VIDEO_CS_601; - return VIDEO_CS_709; + return VIDEO_CS_709; } -static inline bool update_colorspace(av_capture *capture, - obs_source_frame *frame, - CMFormatDescriptionRef desc, - bool full_range, av_video_info &vi) +static inline bool update_colorspace(av_capture *capture, obs_source_frame *frame, CMFormatDescriptionRef desc, + bool full_range, av_video_info &vi) { - auto cs_auto = capture->use_preset || - capture->requested_colorspace == COLOR_SPACE_AUTO; - auto vr_auto = capture->use_preset || - capture->requested_video_range == VIDEO_RANGE_AUTO; + auto cs_auto = capture->use_preset || capture->requested_colorspace == COLOR_SPACE_AUTO; + auto vr_auto = capture->use_preset || capture->requested_video_range == VIDEO_RANGE_AUTO; - video_colorspace colorspace = get_colorspace(desc); - video_range_type range = full_range ? VIDEO_RANGE_FULL - : VIDEO_RANGE_PARTIAL; + video_colorspace colorspace = get_colorspace(desc); + video_range_type range = full_range ? VIDEO_RANGE_FULL : VIDEO_RANGE_PARTIAL; - bool cs_matches = false; - if (cs_auto) { - cs_matches = colorspace == vi.colorspace; - } else { - colorspace = static_cast( - capture->requested_colorspace); - cs_matches = colorspace == vi.colorspace; - } + bool cs_matches = false; + if (cs_auto) { + cs_matches = colorspace == vi.colorspace; + } else { + colorspace = static_cast(capture->requested_colorspace); + cs_matches = colorspace == vi.colorspace; + } - bool vr_matches = false; - if (vr_auto) { - vr_matches = range == vi.video_range; - } else { - range = static_cast( - capture->requested_video_range); - vr_matches = range == vi.video_range; - full_range = range == VIDEO_RANGE_FULL; - } + bool vr_matches = false; + if (vr_auto) { + vr_matches = range == vi.video_range; + } else { + range = static_cast(capture->requested_video_range); + vr_matches = range == vi.video_range; + full_range = range == VIDEO_RANGE_FULL; + } - if (cs_matches && vr_matches) { - if (!vi.video_params_valid) - capture->video_info.update([&](av_video_info &vi_) { - vi_.video_params_valid = vi.video_params_valid = - true; - }); - return true; - } + if (cs_matches && vr_matches) { + if (!vi.video_params_valid) + capture->video_info.update([&](av_video_info &vi_) { + vi_.video_params_valid = vi.video_params_valid = true; + }); + return true; + } - frame->full_range = full_range; + frame->full_range = full_range; - if (!video_format_get_parameters_for_format( - colorspace, range, frame->format, frame->color_matrix, - frame->color_range_min, frame->color_range_max)) { - AVLOG(LOG_ERROR, - "Failed to get colorspace parameters for " - "colorspace %u range %u", - colorspace, range); + if (!video_format_get_parameters_for_format(colorspace, range, frame->format, frame->color_matrix, + frame->color_range_min, frame->color_range_max)) { + AVLOG(LOG_ERROR, + "Failed to get colorspace parameters for " + "colorspace %u range %u", + colorspace, range); - if (vi.video_params_valid) - capture->video_info.update([&](av_video_info &vi_) { - vi_.video_params_valid = vi.video_params_valid = - false; - }); + if (vi.video_params_valid) + capture->video_info.update([&](av_video_info &vi_) { + vi_.video_params_valid = vi.video_params_valid = false; + }); - return false; - } + return false; + } - capture->video_info.update([&](av_video_info &vi_) { - vi_.colorspace = colorspace; - vi_.video_range = range; - vi_.video_params_valid = vi.video_params_valid = true; - }); + capture->video_info.update([&](av_video_info &vi_) { + vi_.colorspace = colorspace; + vi_.video_range = range; + vi_.video_params_valid = vi.video_params_valid = true; + }); - return true; + return true; } -static inline bool update_frame(av_capture *capture, obs_source_frame *frame, - CMSampleBufferRef sample_buffer) +static inline bool update_frame(av_capture *capture, obs_source_frame *frame, CMSampleBufferRef sample_buffer) { - CMFormatDescriptionRef desc = - CMSampleBufferGetFormatDescription(sample_buffer); + CMFormatDescriptionRef desc = CMSampleBufferGetFormatDescription(sample_buffer); - FourCharCode fourcc = CMFormatDescriptionGetMediaSubType(desc); - video_format format = format_from_subtype(fourcc); - CMVideoDimensions dims = CMVideoFormatDescriptionGetDimensions(desc); + FourCharCode fourcc = CMFormatDescriptionGetMediaSubType(desc); + video_format format = format_from_subtype(fourcc); + CMVideoDimensions dims = CMVideoFormatDescriptionGetDimensions(desc); - CVImageBufferRef img = CMSampleBufferGetImageBuffer(sample_buffer); + CVImageBufferRef img = CMSampleBufferGetImageBuffer(sample_buffer); - auto vi = capture->video_info.read(); + auto vi = capture->video_info.read(); - bool video_params_were_valid = vi.video_params_valid; - SCOPE_EXIT - { - if (video_params_were_valid != vi.video_params_valid) - obs_source_update_properties(capture->source); - }; + bool video_params_were_valid = vi.video_params_valid; + SCOPE_EXIT + { + if (video_params_were_valid != vi.video_params_valid) + obs_source_update_properties(capture->source); + }; - if (format == VIDEO_FORMAT_NONE) { - if (capture->fourcc == fourcc) - return false; + if (format == VIDEO_FORMAT_NONE) { + if (capture->fourcc == fourcc) + return false; - capture->fourcc = fourcc; - AVLOG(LOG_ERROR, "Unhandled fourcc: %s (0x%x) (%zu planes)", - AV_FOURCC_STR(fourcc), fourcc, - CVPixelBufferGetPlaneCount(img)); - return false; - } + capture->fourcc = fourcc; + AVLOG(LOG_ERROR, "Unhandled fourcc: %s (0x%x) (%zu planes)", AV_FOURCC_STR(fourcc), fourcc, + CVPixelBufferGetPlaneCount(img)); + return false; + } - if (frame->format != format) - AVLOG(LOG_DEBUG, - "Switching fourcc: " - "'%s' (0x%x) -> '%s' (0x%x)", - AV_FOURCC_STR(capture->fourcc), capture->fourcc, - AV_FOURCC_STR(fourcc), fourcc); + if (frame->format != format) + AVLOG(LOG_DEBUG, + "Switching fourcc: " + "'%s' (0x%x) -> '%s' (0x%x)", + AV_FOURCC_STR(capture->fourcc), capture->fourcc, AV_FOURCC_STR(fourcc), fourcc); - bool was_yuv = format_is_yuv(frame->format); + bool was_yuv = format_is_yuv(frame->format); - capture->fourcc = fourcc; - frame->format = format; - frame->width = dims.width; - frame->height = dims.height; + capture->fourcc = fourcc; + frame->format = format; + frame->width = dims.width; + frame->height = dims.height; - if (format_is_yuv(format) && - !update_colorspace(capture, frame, desc, is_fullrange_yuv(fourcc), - vi)) { - return false; - } else if (was_yuv == format_is_yuv(format)) { - capture->video_info.update([&](av_video_info &vi_) { - vi_.video_params_valid = vi.video_params_valid = true; - }); - } + if (format_is_yuv(format) && !update_colorspace(capture, frame, desc, is_fullrange_yuv(fourcc), vi)) { + return false; + } else if (was_yuv == format_is_yuv(format)) { + capture->video_info.update([&](av_video_info &vi_) { + vi_.video_params_valid = vi.video_params_valid = true; + }); + } - CVPixelBufferLockBaseAddress(img, kCVPixelBufferLock_ReadOnly); + CVPixelBufferLockBaseAddress(img, kCVPixelBufferLock_ReadOnly); - if (!CVPixelBufferIsPlanar(img)) { - frame->linesize[0] = (uint32_t)CVPixelBufferGetBytesPerRow(img); - frame->data[0] = static_cast( - CVPixelBufferGetBaseAddress(img)); - return true; - } + if (!CVPixelBufferIsPlanar(img)) { + frame->linesize[0] = (uint32_t) CVPixelBufferGetBytesPerRow(img); + frame->data[0] = static_cast(CVPixelBufferGetBaseAddress(img)); + return true; + } - size_t count = CVPixelBufferGetPlaneCount(img); - for (size_t i = 0; i < count; i++) { - frame->linesize[i] = - (uint32_t)CVPixelBufferGetBytesPerRowOfPlane(img, i); - frame->data[i] = static_cast( - CVPixelBufferGetBaseAddressOfPlane(img, i)); - } - return true; + size_t count = CVPixelBufferGetPlaneCount(img); + for (size_t i = 0; i < count; i++) { + frame->linesize[i] = (uint32_t) CVPixelBufferGetBytesPerRowOfPlane(img, i); + frame->data[i] = static_cast(CVPixelBufferGetBaseAddressOfPlane(img, i)); + } + return true; } -static inline bool update_audio(obs_source_audio *audio, - CMSampleBufferRef sample_buffer) +static inline bool update_audio(obs_source_audio *audio, CMSampleBufferRef sample_buffer) { - size_t requiredSize; - OSStatus status = CMSampleBufferGetAudioBufferListWithRetainedBlockBuffer( - sample_buffer, &requiredSize, nullptr, 0, nullptr, nullptr, - kCMSampleBufferFlag_AudioBufferList_Assure16ByteAlignment, - nullptr); + size_t requiredSize; + OSStatus status = CMSampleBufferGetAudioBufferListWithRetainedBlockBuffer( + sample_buffer, &requiredSize, nullptr, 0, nullptr, nullptr, + kCMSampleBufferFlag_AudioBufferList_Assure16ByteAlignment, nullptr); - if (status != noErr) { - blog(LOG_WARNING, - "[mac-avcapture]: Error while getting size of sample buffer"); - return false; - } + if (status != noErr) { + blog(LOG_WARNING, "[mac-avcapture]: Error while getting size of sample buffer"); + return false; + } - AudioBufferList *list = (AudioBufferList *)bmalloc(requiredSize); - CMBlockBufferRef buffer; + AudioBufferList *list = (AudioBufferList *) bmalloc(requiredSize); + CMBlockBufferRef buffer; - status = CMSampleBufferGetAudioBufferListWithRetainedBlockBuffer( - sample_buffer, nullptr, list, requiredSize, nullptr, nullptr, - kCMSampleBufferFlag_AudioBufferList_Assure16ByteAlignment, - &buffer); + status = CMSampleBufferGetAudioBufferListWithRetainedBlockBuffer( + sample_buffer, nullptr, list, requiredSize, nullptr, nullptr, + kCMSampleBufferFlag_AudioBufferList_Assure16ByteAlignment, &buffer); - if (status != noErr || !list) { - if (list) - bfree(list); + if (status != noErr || !list) { + if (list) + bfree(list); - blog(LOG_WARNING, - "[mac-avcapture]: Error while copying sample buffer to audio buffer list"); - return false; - } + blog(LOG_WARNING, "[mac-avcapture]: Error while copying sample buffer to audio buffer list"); + return false; + } - for (size_t i = 0; i < list->mNumberBuffers; i++) - audio->data[i] = (uint8_t *)list->mBuffers[i].mData; + for (size_t i = 0; i < list->mNumberBuffers; i++) + audio->data[i] = (uint8_t *) list->mBuffers[i].mData; - audio->frames = (uint32_t)CMSampleBufferGetNumSamples(sample_buffer); - CMFormatDescriptionRef desc = - CMSampleBufferGetFormatDescription(sample_buffer); - const AudioStreamBasicDescription *asbd = - CMAudioFormatDescriptionGetStreamBasicDescription(desc); - audio->samples_per_sec = (uint32_t)asbd->mSampleRate; - audio->speakers = (enum speaker_layout)asbd->mChannelsPerFrame; - switch (asbd->mBitsPerChannel) { - case 8: - audio->format = AUDIO_FORMAT_U8BIT; - break; - case 16: - audio->format = AUDIO_FORMAT_16BIT; - break; - case 32: - audio->format = AUDIO_FORMAT_32BIT; - break; - default: - audio->format = AUDIO_FORMAT_UNKNOWN; - } + audio->frames = (uint32_t) CMSampleBufferGetNumSamples(sample_buffer); + CMFormatDescriptionRef desc = CMSampleBufferGetFormatDescription(sample_buffer); + const AudioStreamBasicDescription *asbd = CMAudioFormatDescriptionGetStreamBasicDescription(desc); + audio->samples_per_sec = (uint32_t) asbd->mSampleRate; + audio->speakers = (enum speaker_layout) asbd->mChannelsPerFrame; + switch (asbd->mBitsPerChannel) { + case 8: + audio->format = AUDIO_FORMAT_U8BIT; + break; + case 16: + audio->format = AUDIO_FORMAT_16BIT; + break; + case 32: + audio->format = AUDIO_FORMAT_32BIT; + break; + default: + audio->format = AUDIO_FORMAT_UNKNOWN; + } - if (buffer) - CFRelease(buffer); + if (buffer) + CFRelease(buffer); - bfree(list); + bfree(list); - return true; + return true; } @implementation OBSAVCaptureDelegate - (void)captureOutput:(AVCaptureOutput *)out - didDropSampleBuffer:(CMSampleBufferRef)sampleBuffer - fromConnection:(AVCaptureConnection *)connection + didDropSampleBuffer:(CMSampleBufferRef)sampleBuffer + fromConnection:(AVCaptureConnection *)connection { - UNUSED_PARAMETER(out); - UNUSED_PARAMETER(sampleBuffer); - UNUSED_PARAMETER(connection); + UNUSED_PARAMETER(out); + UNUSED_PARAMETER(sampleBuffer); + UNUSED_PARAMETER(connection); } - (void)captureOutput:(AVCaptureOutput *)captureOutput - didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer - fromConnection:(AVCaptureConnection *)connection + didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer + fromConnection:(AVCaptureConnection *)connection { - UNUSED_PARAMETER(captureOutput); - UNUSED_PARAMETER(connection); + UNUSED_PARAMETER(captureOutput); + UNUSED_PARAMETER(connection); - CMItemCount count = CMSampleBufferGetNumSamples(sampleBuffer); - if (count < 1 || !capture) - return; + CMItemCount count = CMSampleBufferGetNumSamples(sampleBuffer); + if (count < 1 || !capture) + return; - CMTime target_pts = - CMSampleBufferGetOutputPresentationTimeStamp(sampleBuffer); - CMTime target_pts_nano = CMTimeConvertScale( - target_pts, NANO_TIMESCALE, kCMTimeRoundingMethod_Default); + CMTime target_pts = CMSampleBufferGetOutputPresentationTimeStamp(sampleBuffer); + CMTime target_pts_nano = CMTimeConvertScale(target_pts, NANO_TIMESCALE, kCMTimeRoundingMethod_Default); - CMFormatDescriptionRef desc = - CMSampleBufferGetFormatDescription(sampleBuffer); - CMMediaType type = CMFormatDescriptionGetMediaType(desc); - if (type == kCMMediaType_Video) { - obs_source_frame *frame = &capture->frame; - frame->timestamp = target_pts_nano.value; + CMFormatDescriptionRef desc = CMSampleBufferGetFormatDescription(sampleBuffer); + CMMediaType type = CMFormatDescriptionGetMediaType(desc); + if (type == kCMMediaType_Video) { + obs_source_frame *frame = &capture->frame; + frame->timestamp = target_pts_nano.value; - if (!update_frame(capture, frame, sampleBuffer)) { - obs_source_output_video(capture->source, nullptr); - return; - } + if (!update_frame(capture, frame, sampleBuffer)) { + obs_source_output_video(capture->source, nullptr); + return; + } - obs_source_output_video(capture->source, frame); + obs_source_output_video(capture->source, frame); - CVImageBufferRef img = - CMSampleBufferGetImageBuffer(sampleBuffer); - CVPixelBufferUnlockBaseAddress(img, - kCVPixelBufferLock_ReadOnly); - } else if (type == kCMMediaType_Audio) { - if (!capture->enable_audio) - return; + CVImageBufferRef img = CMSampleBufferGetImageBuffer(sampleBuffer); + CVPixelBufferUnlockBaseAddress(img, kCVPixelBufferLock_ReadOnly); + } else if (type == kCMMediaType_Audio) { + if (!capture->enable_audio) + return; - obs_source_audio *audio = &capture->audio; - audio->timestamp = target_pts_nano.value; + obs_source_audio *audio = &capture->audio; + audio->timestamp = target_pts_nano.value; - if (!update_audio(audio, sampleBuffer)) { - obs_source_output_audio(capture->source, nullptr); - return; - } - obs_source_output_audio(capture->source, audio); - } + if (!update_audio(audio, sampleBuffer)) { + obs_source_output_audio(capture->source, nullptr); + return; + } + obs_source_output_audio(capture->source, audio); + } } @end static void av_capture_enable_buffering(av_capture *capture, bool enabled) { - obs_source_set_async_unbuffered(capture->source, !enabled); + obs_source_set_async_unbuffered(capture->source, !enabled); } static const char *av_capture_getname(void *) { - return TEXT_AVCAPTURE; + return TEXT_AVCAPTURE; } static void unlock_device(av_capture *capture, AVCaptureDevice *dev = nullptr) { - if (!dev) - dev = capture->device; + if (!dev) + dev = capture->device; - if (dev && capture->device_locked) - [dev unlockForConfiguration]; + if (dev && capture->device_locked) + [dev unlockForConfiguration]; - capture->device_locked = false; + capture->device_locked = false; } static void start_capture(av_capture *capture) { - if (capture->session && !capture->session.running) - [capture->session startRunning]; + if (capture->session && !capture->session.running) + [capture->session startRunning]; } static void clear_capture(av_capture *capture) { - if (capture->session && capture->session.running) - [capture->session stopRunning]; + if (capture->session && capture->session.running) + [capture->session stopRunning]; - obs_source_output_video(capture->source, nullptr); - obs_source_output_audio(capture->source, nullptr); + obs_source_output_video(capture->source, nullptr); + obs_source_output_audio(capture->source, nullptr); } static void remove_device(av_capture *capture) { - clear_capture(capture); + clear_capture(capture); - [capture->session removeInput:capture->device_input]; + [capture->session removeInput:capture->device_input]; - unlock_device(capture); + unlock_device(capture); - capture->device_input = nullptr; - capture->device = nullptr; + capture->device_input = nullptr; + capture->device = nullptr; } static void av_capture_destroy(void *data) { - auto capture = static_cast(data); + auto capture = static_cast(data); - delete capture; + delete capture; } static bool init_session(av_capture *capture) { - auto session = [[AVCaptureSession alloc] init]; - if (!session) { - AVLOG(LOG_ERROR, "Could not create AVCaptureSession"); - return false; - } + auto session = [[AVCaptureSession alloc] init]; + if (!session) { + AVLOG(LOG_ERROR, "Could not create AVCaptureSession"); + return false; + } - auto delegate = [[OBSAVCaptureDelegate alloc] init]; - if (!delegate) { - AVLOG(LOG_ERROR, "Could not create OBSAVCaptureDelegate"); - return false; - } + auto delegate = [[OBSAVCaptureDelegate alloc] init]; + if (!delegate) { + AVLOG(LOG_ERROR, "Could not create OBSAVCaptureDelegate"); + return false; + } - delegate->capture = capture; + delegate->capture = capture; - auto out = [[AVCaptureVideoDataOutput alloc] init]; - if (!out) { - AVLOG(LOG_ERROR, "Could not create AVCaptureVideoDataOutput"); - return false; - } + auto out = [[AVCaptureVideoDataOutput alloc] init]; + if (!out) { + AVLOG(LOG_ERROR, "Could not create AVCaptureVideoDataOutput"); + return false; + } - auto audioOut = [[AVCaptureAudioDataOutput alloc] init]; - if (!audioOut) { - AVLOG(LOG_ERROR, "Could not create AVCaptureAudioDataOutput"); - return false; - } + auto audioOut = [[AVCaptureAudioDataOutput alloc] init]; + if (!audioOut) { + AVLOG(LOG_ERROR, "Could not create AVCaptureAudioDataOutput"); + return false; + } - auto queue = dispatch_queue_create(NULL, NULL); - if (!queue) { - AVLOG(LOG_ERROR, "Could not create dispatch queue"); - return false; - } + auto queue = dispatch_queue_create(NULL, NULL); + if (!queue) { + AVLOG(LOG_ERROR, "Could not create dispatch queue"); + return false; + } - auto audioQueue = dispatch_queue_create(NULL, NULL); - if (!queue) { - AVLOG(LOG_ERROR, "Could not create dispatch queue for audio"); - return false; - } + auto audioQueue = dispatch_queue_create(NULL, NULL); + if (!queue) { + AVLOG(LOG_ERROR, "Could not create dispatch queue for audio"); + return false; + } - capture->session = session; - capture->delegate = delegate; - capture->out = out; - capture->audioOut = audioOut; - capture->queue = queue; - capture->audioQueue = audioQueue; + capture->session = session; + capture->delegate = delegate; + capture->out = out; + capture->audioOut = audioOut; + capture->queue = queue; + capture->audioQueue = audioQueue; - [capture->session addOutput:capture->out]; - [capture->out setSampleBufferDelegate:capture->delegate - queue:capture->queue]; - [capture->session addOutput:capture->audioOut]; - [capture->audioOut setSampleBufferDelegate:capture->delegate - queue:capture->audioQueue]; + [capture->session addOutput:capture->out]; + [capture->out setSampleBufferDelegate:capture->delegate queue:capture->queue]; + [capture->session addOutput:capture->audioOut]; + [capture->audioOut setSampleBufferDelegate:capture->delegate queue:capture->audioQueue]; - return true; + return true; } static bool init_format(av_capture *capture, AVCaptureDevice *dev); static bool init_device_input(av_capture *capture, AVCaptureDevice *dev) { - NSError *err = nil; - AVCaptureDeviceInput *device_input = - [AVCaptureDeviceInput deviceInputWithDevice:dev error:&err]; - if (!device_input) { - AVLOG(LOG_ERROR, "Error while initializing device input: %s", - err.localizedFailureReason.UTF8String); - return false; - } + NSError *err = nil; + AVCaptureDeviceInput *device_input = [AVCaptureDeviceInput deviceInputWithDevice:dev error:&err]; + if (!device_input) { + AVLOG(LOG_ERROR, "Error while initializing device input: %s", err.localizedFailureReason.UTF8String); + return false; + } - [capture->session addInput:device_input]; + [capture->session addInput:device_input]; - if (!init_format(capture, dev)) { - [capture->session removeInput:device_input]; - return false; - } + if (!init_format(capture, dev)) { + [capture->session removeInput:device_input]; + return false; + } - capture->device_input = device_input; + capture->device_input = device_input; - return true; + return true; } static uint32_t uint_from_dict(NSDictionary *dict, CFStringRef key) { - return ((NSNumber *)dict[(__bridge NSString *)key]).unsignedIntValue; + return ((NSNumber *) dict[(__bridge NSString *) key]).unsignedIntValue; } static bool init_format(av_capture *capture, AVCaptureDevice *dev) { - AVCaptureDeviceFormat *format = dev.activeFormat; + AVCaptureDeviceFormat *format = dev.activeFormat; - CMMediaType mtype = - CMFormatDescriptionGetMediaType(format.formatDescription); - // TODO: support other media types - if (mtype != kCMMediaType_Video && mtype != kCMMediaType_Muxed) { - AVLOG(LOG_ERROR, "CMMediaType '%s' is unsupported", - AV_FOURCC_STR(mtype)); - return false; - } + CMMediaType mtype = CMFormatDescriptionGetMediaType(format.formatDescription); + // TODO: support other media types + if (mtype != kCMMediaType_Video && mtype != kCMMediaType_Muxed) { + AVLOG(LOG_ERROR, "CMMediaType '%s' is unsupported", AV_FOURCC_STR(mtype)); + return false; + } - capture->out.videoSettings = nil; - FourCharCode subtype = uint_from_dict(capture->out.videoSettings, - kCVPixelBufferPixelFormatTypeKey); - if (format_from_subtype(subtype) != VIDEO_FORMAT_NONE) { - AVLOG(LOG_DEBUG, "Using native fourcc '%s'", - AV_FOURCC_STR(subtype)); - return true; - } + capture->out.videoSettings = nil; + FourCharCode subtype = uint_from_dict(capture->out.videoSettings, kCVPixelBufferPixelFormatTypeKey); + if (format_from_subtype(subtype) != VIDEO_FORMAT_NONE) { + AVLOG(LOG_DEBUG, "Using native fourcc '%s'", AV_FOURCC_STR(subtype)); + return true; + } - AVLOG(LOG_DEBUG, "Using fallback fourcc '%s' ('%s' 0x%08x unsupported)", - AV_FOURCC_STR(kCVPixelFormatType_32BGRA), AV_FOURCC_STR(subtype), - subtype); + AVLOG(LOG_DEBUG, "Using fallback fourcc '%s' ('%s' 0x%08x unsupported)", AV_FOURCC_STR(kCVPixelFormatType_32BGRA), + AV_FOURCC_STR(subtype), subtype); - capture->out.videoSettings = @{ - (__bridge NSString *) - kCVPixelBufferPixelFormatTypeKey: @(kCVPixelFormatType_32BGRA) - }; - return true; + capture->out.videoSettings = + @{(__bridge NSString *) kCVPixelBufferPixelFormatTypeKey: @(kCVPixelFormatType_32BGRA)}; + return true; } static NSArray *presets(void); @@ -904,1500 +859,1340 @@ static NSString *preset_names(NSString *preset); static NSString *select_preset(AVCaptureDevice *dev, NSString *cur_preset) { - NSString *new_preset = nil; - bool found_previous_preset = false; - for (NSString *preset in presets().reverseObjectEnumerator) { - if (!found_previous_preset) - found_previous_preset = - [cur_preset isEqualToString:preset]; + NSString *new_preset = nil; + bool found_previous_preset = false; + for (NSString *preset in presets().reverseObjectEnumerator) { + if (!found_previous_preset) + found_previous_preset = [cur_preset isEqualToString:preset]; - if (![dev supportsAVCaptureSessionPreset:preset]) - continue; + if (![dev supportsAVCaptureSessionPreset:preset]) + continue; - if (!new_preset || !found_previous_preset) - new_preset = preset; - } + if (!new_preset || !found_previous_preset) + new_preset = preset; + } - return new_preset; + return new_preset; } -static bool init_preset(av_capture *capture, AVCaptureDevice *dev, - obs_data_t *settings) +static bool init_preset(av_capture *capture, AVCaptureDevice *dev, obs_data_t *settings) { - clear_capture(capture); + clear_capture(capture); - unlock_device(capture, dev); + unlock_device(capture, dev); - NSString *preset = get_string(settings, "preset"); - if (![dev supportsAVCaptureSessionPreset:preset]) { - AVLOG(LOG_WARNING, "Preset %s not available", - preset_names(preset).UTF8String); - preset = select_preset(dev, preset); - } + NSString *preset = get_string(settings, "preset"); + if (![dev supportsAVCaptureSessionPreset:preset]) { + AVLOG(LOG_WARNING, "Preset %s not available", preset_names(preset).UTF8String); + preset = select_preset(dev, preset); + } - if (!preset) { - AVLOG(LOG_WARNING, "Could not select a preset, " - "initialization failed"); - return false; - } + if (!preset) { + AVLOG(LOG_WARNING, "Could not select a preset, " + "initialization failed"); + return false; + } - capture->session.sessionPreset = preset; - AVLOG(LOG_INFO, "Using preset %s", preset_names(preset).UTF8String); + capture->session.sessionPreset = preset; + AVLOG(LOG_INFO, "Using preset %s", preset_names(preset).UTF8String); - return true; + return true; } static bool operator==(const CMVideoDimensions &a, const CMVideoDimensions &b); static CMVideoDimensions get_dimensions(AVCaptureDeviceFormat *format); -static AVCaptureDeviceFormat *find_format(AVCaptureDevice *dev, - CMVideoDimensions dims) +static AVCaptureDeviceFormat *find_format(AVCaptureDevice *dev, CMVideoDimensions dims) { - for (AVCaptureDeviceFormat *format in dev.formats) { - if (get_dimensions(format) == dims) - return format; - } + for (AVCaptureDeviceFormat *format in dev.formats) { + if (get_dimensions(format) == dims) + return format; + } - return nullptr; + return nullptr; } static CMTime convert(media_frames_per_second fps) { - CMTime time{}; - time.value = fps.denominator; - time.timescale = fps.numerator; - time.flags = 1; - return time; + CMTime time {}; + time.value = fps.denominator; + time.timescale = fps.numerator; + time.flags = 1; + return time; } static bool lock_device(av_capture *capture, AVCaptureDevice *dev) { - if (!dev) - dev = capture->device; + if (!dev) + dev = capture->device; - NSError *err; - if (![dev lockForConfiguration:&err]) { - AVLOG(LOG_WARNING, - "Could not lock device for configuration: " - "%s", - err.localizedDescription.UTF8String); - return false; - } + NSError *err; + if (![dev lockForConfiguration:&err]) { + AVLOG(LOG_WARNING, + "Could not lock device for configuration: " + "%s", + err.localizedDescription.UTF8String); + return false; + } - capture->device_locked = true; - return true; + capture->device_locked = true; + return true; } template -static void find_formats(media_frames_per_second fps, AVCaptureDevice *dev, - const CMVideoDimensions *dims, Func &&f) +static void find_formats(media_frames_per_second fps, AVCaptureDevice *dev, const CMVideoDimensions *dims, Func &&f) { - auto time = convert(fps); + auto time = convert(fps); - for (AVCaptureDeviceFormat *format in dev.formats) { - if (!(get_dimensions(format) == *dims)) - continue; + for (AVCaptureDeviceFormat *format in dev.formats) { + if (!(get_dimensions(format) == *dims)) + continue; - for (AVFrameRateRange *range in format - .videoSupportedFrameRateRanges) { - if (CMTimeCompare(range.maxFrameDuration, time) >= 0 && - CMTimeCompare(range.minFrameDuration, time) <= 0) - if (f(format)) - return; - } - } + for (AVFrameRateRange *range in format.videoSupportedFrameRateRanges) { + if (CMTimeCompare(range.maxFrameDuration, time) >= 0 && CMTimeCompare(range.minFrameDuration, time) <= 0) + if (f(format)) + return; + } + } } static bool color_space_valid(int color_space) { - switch (color_space) { - case COLOR_SPACE_AUTO: - case VIDEO_CS_DEFAULT: - case VIDEO_CS_601: - case VIDEO_CS_709: - return true; - } + switch (color_space) { + case COLOR_SPACE_AUTO: + case VIDEO_CS_DEFAULT: + case VIDEO_CS_601: + case VIDEO_CS_709: + return true; + } - return false; + return false; } static const char *color_space_name(int color_space) { - switch (color_space) { - case COLOR_SPACE_AUTO: - return "Auto"; - case VIDEO_CS_DEFAULT: - return "Default"; - case VIDEO_CS_601: - return "CS 601"; - case VIDEO_CS_709: - return "CS 709"; - } + switch (color_space) { + case COLOR_SPACE_AUTO: + return "Auto"; + case VIDEO_CS_DEFAULT: + return "Default"; + case VIDEO_CS_601: + return "CS 601"; + case VIDEO_CS_709: + return "CS 709"; + } - return "Unknown"; + return "Unknown"; } static bool video_range_valid(int video_range) { - switch (video_range) { - case VIDEO_RANGE_AUTO: - case VIDEO_RANGE_DEFAULT: - case VIDEO_RANGE_PARTIAL: - case VIDEO_RANGE_FULL: - return true; - } + switch (video_range) { + case VIDEO_RANGE_AUTO: + case VIDEO_RANGE_DEFAULT: + case VIDEO_RANGE_PARTIAL: + case VIDEO_RANGE_FULL: + return true; + } - return false; + return false; } static const char *video_range_name(int video_range) { - switch (video_range) { - case VIDEO_RANGE_AUTO: - return "Auto"; - case VIDEO_RANGE_DEFAULT: - return "Default"; - case VIDEO_RANGE_PARTIAL: - return "Partial"; - case VIDEO_RANGE_FULL: - return "Full"; - } + switch (video_range) { + case VIDEO_RANGE_AUTO: + return "Auto"; + case VIDEO_RANGE_DEFAULT: + return "Default"; + case VIDEO_RANGE_PARTIAL: + return "Partial"; + case VIDEO_RANGE_FULL: + return "Full"; + } - return "Unknown"; + return "Unknown"; } -static bool init_manual(av_capture *capture, AVCaptureDevice *dev, - obs_data_t *settings) +static bool init_manual(av_capture *capture, AVCaptureDevice *dev, obs_data_t *settings) { - clear_capture(capture); + clear_capture(capture); - auto input_format = obs_data_get_int(settings, "input_format"); - FourCharCode actual_format = (FourCharCode)input_format; + auto input_format = obs_data_get_int(settings, "input_format"); + FourCharCode actual_format = (FourCharCode) input_format; - SCOPE_EXIT - { - bool refresh = false; - if (input_format != actual_format) { - refresh = obs_data_get_autoselect_int(settings, - "input_format") != - actual_format; - obs_data_set_autoselect_int(settings, "input_format", - actual_format); - } else { - refresh = obs_data_has_autoselect_value(settings, - "input_format"); - obs_data_unset_autoselect_value(settings, - "input_format"); - } + SCOPE_EXIT + { + bool refresh = false; + if (input_format != actual_format) { + refresh = obs_data_get_autoselect_int(settings, "input_format") != actual_format; + obs_data_set_autoselect_int(settings, "input_format", actual_format); + } else { + refresh = obs_data_has_autoselect_value(settings, "input_format"); + obs_data_unset_autoselect_value(settings, "input_format"); + } - if (refresh) - obs_source_update_properties(capture->source); - }; + if (refresh) + obs_source_update_properties(capture->source); + }; - capture->requested_colorspace = - (int)obs_data_get_int(settings, "color_space"); - if (!color_space_valid(capture->requested_colorspace)) { - AVLOG(LOG_WARNING, "Unsupported color space: %d", - capture->requested_colorspace); - return false; - } + capture->requested_colorspace = (int) obs_data_get_int(settings, "color_space"); + if (!color_space_valid(capture->requested_colorspace)) { + AVLOG(LOG_WARNING, "Unsupported color space: %d", capture->requested_colorspace); + return false; + } - capture->requested_video_range = - (int)obs_data_get_int(settings, "video_range"); - if (!video_range_valid(capture->requested_video_range)) { - AVLOG(LOG_WARNING, "Unsupported color range: %d", - capture->requested_video_range); - return false; - } + capture->requested_video_range = (int) obs_data_get_int(settings, "video_range"); + if (!video_range_valid(capture->requested_video_range)) { + AVLOG(LOG_WARNING, "Unsupported color range: %d", capture->requested_video_range); + return false; + } - CMVideoDimensions dims{}; - if (!get_resolution(settings, dims)) { - AVLOG(LOG_WARNING, "Could not load resolution"); - return false; - } + CMVideoDimensions dims {}; + if (!get_resolution(settings, dims)) { + AVLOG(LOG_WARNING, "Could not load resolution"); + return false; + } - media_frames_per_second fps{}; - if (!obs_data_get_frames_per_second(settings, "frame_rate", &fps, - nullptr)) { - AVLOG(LOG_WARNING, "Could not load frame rate"); - return false; - } + media_frames_per_second fps {}; + if (!obs_data_get_frames_per_second(settings, "frame_rate", &fps, nullptr)) { + AVLOG(LOG_WARNING, "Could not load frame rate"); + return false; + } - AVCaptureDeviceFormat *format = nullptr; - find_formats(fps, dev, &dims, [&](AVCaptureDeviceFormat *format_) { - auto desc = format_.formatDescription; - auto fourcc = CMFormatDescriptionGetMediaSubType(desc); - if (input_format != INPUT_FORMAT_AUTO && fourcc != input_format) - return false; + AVCaptureDeviceFormat *format = nullptr; + find_formats(fps, dev, &dims, [&](AVCaptureDeviceFormat *format_) { + auto desc = format_.formatDescription; + auto fourcc = CMFormatDescriptionGetMediaSubType(desc); + if (input_format != INPUT_FORMAT_AUTO && fourcc != input_format) + return false; - actual_format = fourcc; - format = format_; - return true; - }); + actual_format = fourcc; + format = format_; + return true; + }); - if (!format) { - AVLOG(LOG_WARNING, - "Frame rate is not supported: %g FPS " - "(%u/%u)", - media_frames_per_second_to_fps(fps), fps.numerator, - fps.denominator); - return false; - } + if (!format) { + AVLOG(LOG_WARNING, + "Frame rate is not supported: %g FPS " + "(%u/%u)", + media_frames_per_second_to_fps(fps), fps.numerator, fps.denominator); + return false; + } - if (!lock_device(capture, dev)) - return false; + if (!lock_device(capture, dev)) + return false; - const char *if_name = - input_format == INPUT_FORMAT_AUTO - ? "Auto" - : fourcc_subtype_name((FourCharCode)input_format); + const char *if_name = input_format == INPUT_FORMAT_AUTO ? "Auto" : fourcc_subtype_name((FourCharCode) input_format); #define IF_AUTO(x) (input_format != INPUT_FORMAT_AUTO ? "" : x) - AVLOG(LOG_INFO, - "Capturing '%s' (%s):\n" - " Resolution: %ux%u\n" - " FPS: %g (%" PRIu32 "/%" PRIu32 ")\n" - " Frame interval: %g" NBSP "s\n" - " Input format: %s%s%s (%s)%s\n" - " Requested color space: %s (%d)\n" - " Requested video range: %s (%d)\n" - " Using format: %s", - dev.localizedName.UTF8String, dev.uniqueID.UTF8String, dims.width, - dims.height, media_frames_per_second_to_fps(fps), fps.numerator, - fps.denominator, media_frames_per_second_to_frame_interval(fps), - if_name, IF_AUTO(" (actual: "), - IF_AUTO(fourcc_subtype_name(actual_format)), - AV_FOURCC_STR(actual_format), IF_AUTO(")"), - color_space_name(capture->requested_colorspace), - capture->requested_colorspace, - video_range_name(capture->requested_video_range), - capture->requested_video_range, format.description.UTF8String); + AVLOG(LOG_INFO, + "Capturing '%s' (%s):\n" + " Resolution: %ux%u\n" + " FPS: %g (%" PRIu32 "/%" PRIu32 ")\n" + " Frame interval: %g" NBSP "s\n" + " Input format: %s%s%s (%s)%s\n" + " Requested color space: %s (%d)\n" + " Requested video range: %s (%d)\n" + " Using format: %s", + dev.localizedName.UTF8String, dev.uniqueID.UTF8String, dims.width, dims.height, + media_frames_per_second_to_fps(fps), fps.numerator, fps.denominator, + media_frames_per_second_to_frame_interval(fps), if_name, IF_AUTO(" (actual: "), + IF_AUTO(fourcc_subtype_name(actual_format)), AV_FOURCC_STR(actual_format), IF_AUTO(")"), + color_space_name(capture->requested_colorspace), capture->requested_colorspace, + video_range_name(capture->requested_video_range), capture->requested_video_range, + format.description.UTF8String); #undef IF_AUTO - dev.activeFormat = format; - dev.activeVideoMinFrameDuration = convert(fps); - dev.activeVideoMaxFrameDuration = convert(fps); + dev.activeFormat = format; + dev.activeVideoMinFrameDuration = convert(fps); + dev.activeVideoMaxFrameDuration = convert(fps); - capture->video_info.update( - [&](av_video_info &vi) { vi.video_params_valid = false; }); + capture->video_info.update([&](av_video_info &vi) { + vi.video_params_valid = false; + }); - return true; + return true; } static inline void av_capture_set_audio_active(av_capture *capture, bool active) { - obs_source_set_audio_active(capture->source, active); - capture->enable_audio = active; + obs_source_set_audio_active(capture->source, active); + capture->enable_audio = active; } -static void capture_device(av_capture *capture, AVCaptureDevice *dev, - obs_data_t *settings) +static void capture_device(av_capture *capture, AVCaptureDevice *dev, obs_data_t *settings) { - const char *name = dev.localizedName.UTF8String; - obs_data_set_string(settings, "device_name", name); - obs_data_set_string(settings, "device", dev.uniqueID.UTF8String); - AVLOG(LOG_INFO, "Selected device '%s'", name); + const char *name = dev.localizedName.UTF8String; + obs_data_set_string(settings, "device_name", name); + obs_data_set_string(settings, "device", dev.uniqueID.UTF8String); + AVLOG(LOG_INFO, "Selected device '%s'", name); - if ((capture->use_preset = obs_data_get_bool(settings, "use_preset"))) { - if (!init_preset(capture, dev, settings)) - return; + if ((capture->use_preset = obs_data_get_bool(settings, "use_preset"))) { + if (!init_preset(capture, dev, settings)) + return; - } else { - if (!init_manual(capture, dev, settings)) - return; - } + } else { + if (!init_manual(capture, dev, settings)) + return; + } - av_capture_set_audio_active( - capture, obs_data_get_bool(settings, "enable_audio") && - ([dev hasMediaType:AVMediaTypeAudio] || - [dev hasMediaType:AVMediaTypeMuxed])); + av_capture_set_audio_active(capture, + obs_data_get_bool(settings, "enable_audio") && + ([dev hasMediaType:AVMediaTypeAudio] || [dev hasMediaType:AVMediaTypeMuxed])); - if (!init_device_input(capture, dev)) - return; + if (!init_device_input(capture, dev)) + return; - AVCaptureInputPort *port = capture->device_input.ports[0]; - capture->has_clock = [port respondsToSelector:@selector(clock)]; + AVCaptureInputPort *port = capture->device_input.ports[0]; + capture->has_clock = [port respondsToSelector:@selector(clock)]; - capture->device = dev; - start_capture(capture); - return; + capture->device = dev; + start_capture(capture); + return; } -static inline void handle_disconnect_capture(av_capture *capture, - AVCaptureDevice *dev) +static inline void handle_disconnect_capture(av_capture *capture, AVCaptureDevice *dev) { - if (![dev.uniqueID isEqualTo:capture->uid]) - return; + if (![dev.uniqueID isEqualTo:capture->uid]) + return; - if (!capture->device) { - AVLOG(LOG_INFO, "Received disconnect for inactive device '%s'", - capture->uid.UTF8String); - return; - } + if (!capture->device) { + AVLOG(LOG_INFO, "Received disconnect for inactive device '%s'", capture->uid.UTF8String); + return; + } - AVLOG(LOG_WARNING, "Device with unique ID '%s' disconnected", - dev.uniqueID.UTF8String); + AVLOG(LOG_WARNING, "Device with unique ID '%s' disconnected", dev.uniqueID.UTF8String); - remove_device(capture); + remove_device(capture); } static inline void handle_disconnect(av_capture *capture, AVCaptureDevice *dev) { - if (!dev) - return; + if (!dev) + return; - handle_disconnect_capture(capture, dev); - obs_source_update_properties(capture->source); + handle_disconnect_capture(capture, dev); + obs_source_update_properties(capture->source); } -static inline void handle_connect_capture(av_capture *capture, - AVCaptureDevice *dev, - obs_data_t *settings) +static inline void handle_connect_capture(av_capture *capture, AVCaptureDevice *dev, obs_data_t *settings) { - if (![dev.uniqueID isEqualTo:capture->uid]) - return; + if (![dev.uniqueID isEqualTo:capture->uid]) + return; - if (capture->device) { - AVLOG(LOG_ERROR, "Received connect for in-use device '%s'", - capture->uid.UTF8String); - return; - } + if (capture->device) { + AVLOG(LOG_ERROR, "Received connect for in-use device '%s'", capture->uid.UTF8String); + return; + } - AVLOG(LOG_INFO, - "Device with unique ID '%s' connected, " - "resuming capture", - dev.uniqueID.UTF8String); + AVLOG(LOG_INFO, + "Device with unique ID '%s' connected, " + "resuming capture", + dev.uniqueID.UTF8String); - capture_device(capture, dev, settings); + capture_device(capture, dev, settings); } -static inline void handle_connect(av_capture *capture, AVCaptureDevice *dev, - obs_data_t *settings) +static inline void handle_connect(av_capture *capture, AVCaptureDevice *dev, obs_data_t *settings) { - if (!dev) - return; + if (!dev) + return; - handle_connect_capture(capture, dev, settings); - obs_source_update_properties(capture->source); + handle_connect_capture(capture, dev, settings); + obs_source_update_properties(capture->source); } static bool av_capture_init(av_capture *capture, obs_data_t *settings) { - if (!init_session(capture)) - return false; + if (!init_session(capture)) + return false; - capture->uid = get_string(settings, "device"); + capture->uid = get_string(settings, "device"); - NSNotificationCenter *nc = [NSNotificationCenter defaultCenter]; - capture->disconnect_observer.reset([nc - addObserverForName:AVCaptureDeviceWasDisconnectedNotification - object:nil - queue:[NSOperationQueue mainQueue] - usingBlock:^(NSNotification *note) { - handle_disconnect(capture, note.object); - }]); + NSNotificationCenter *nc = [NSNotificationCenter defaultCenter]; + capture->disconnect_observer.reset([nc addObserverForName:AVCaptureDeviceWasDisconnectedNotification object:nil + queue:[NSOperationQueue mainQueue] + usingBlock:^(NSNotification *note) { + handle_disconnect(capture, note.object); + }]); - capture->connect_observer.reset([nc - addObserverForName:AVCaptureDeviceWasConnectedNotification - object:nil - queue:[NSOperationQueue mainQueue] - usingBlock:^(NSNotification *note) { - handle_connect(capture, note.object, settings); - }]); + capture->connect_observer.reset([nc addObserverForName:AVCaptureDeviceWasConnectedNotification object:nil + queue:[NSOperationQueue mainQueue] + usingBlock:^(NSNotification *note) { + handle_connect(capture, note.object, settings); + }]); - AVCaptureDevice *dev = - [AVCaptureDevice deviceWithUniqueID:capture->uid]; + AVCaptureDevice *dev = [AVCaptureDevice deviceWithUniqueID:capture->uid]; - if (!dev) { - if (capture->uid.length < 1) - AVLOG(LOG_INFO, "No device selected"); - else - AVLOG(LOG_WARNING, - "Could not initialize device " - "with unique ID '%s'", - capture->uid.UTF8String); - return true; - } + if (!dev) { + if (capture->uid.length < 1) + AVLOG(LOG_INFO, "No device selected"); + else + AVLOG(LOG_WARNING, + "Could not initialize device " + "with unique ID '%s'", + capture->uid.UTF8String); + return true; + } - capture_device(capture, dev, settings); + capture_device(capture, dev, settings); - return true; + return true; } static void *av_capture_create(obs_data_t *settings, obs_source_t *source) { - unique_ptr capture; + unique_ptr capture; - try { - capture.reset(new av_capture()); - } catch (...) { - return capture.release(); - } + try { + capture.reset(new av_capture()); + } catch (...) { + return capture.release(); + } - capture->source = source; + capture->source = source; - if (!av_capture_init(capture.get(), settings)) { - AVLOG(LOG_ERROR, "av_capture_init failed"); - return nullptr; - } + if (!av_capture_init(capture.get(), settings)) { + AVLOG(LOG_ERROR, "av_capture_init failed"); + return nullptr; + } - av_capture_enable_buffering(capture.get(), - obs_data_get_bool(settings, "buffering")); + av_capture_enable_buffering(capture.get(), obs_data_get_bool(settings, "buffering")); - return capture.release(); + return capture.release(); } static NSArray *presets(void) { - return @[ - //AVCaptureSessionPresetiFrame1280x720, - //AVCaptureSessionPresetiFrame960x540, - AVCaptureSessionPreset3840x2160, - AVCaptureSessionPreset1920x1080, AVCaptureSessionPreset1280x720, - AVCaptureSessionPreset960x540, AVCaptureSessionPreset640x480, - AVCaptureSessionPreset352x288, AVCaptureSessionPreset320x240, - AVCaptureSessionPresetHigh, - //AVCaptureSessionPresetMedium, - //AVCaptureSessionPresetLow, - //AVCaptureSessionPresetPhoto, - ]; + return @[ + //AVCaptureSessionPresetiFrame1280x720, + //AVCaptureSessionPresetiFrame960x540, + AVCaptureSessionPreset3840x2160, AVCaptureSessionPreset1920x1080, AVCaptureSessionPreset1280x720, + AVCaptureSessionPreset960x540, AVCaptureSessionPreset640x480, AVCaptureSessionPreset352x288, + AVCaptureSessionPreset320x240, AVCaptureSessionPresetHigh, + //AVCaptureSessionPresetMedium, + //AVCaptureSessionPresetLow, + //AVCaptureSessionPresetPhoto, + ]; } static NSString *preset_names(NSString *preset) { - NSDictionary *preset_names = nil; - preset_names = @{ - AVCaptureSessionPresetLow: @"Low", - AVCaptureSessionPresetMedium: @"Medium", - AVCaptureSessionPresetHigh: @"High", - AVCaptureSessionPreset320x240: @"320x240", - AVCaptureSessionPreset352x288: @"352x288", - AVCaptureSessionPreset640x480: @"640x480", - AVCaptureSessionPreset960x540: @"960x540", - AVCaptureSessionPreset1280x720: @"1280x720", - AVCaptureSessionPreset1920x1080: @"1920x1080", - AVCaptureSessionPreset3840x2160: @"3840x2160", - AVCaptureSessionPresetHigh: @"High", - }; - NSString *name = preset_names[preset]; - if (name) - return name; - return [NSString stringWithFormat:@"Unknown (%@)", preset]; + NSDictionary *preset_names = nil; + preset_names = @ { + AVCaptureSessionPresetLow: @"Low", + AVCaptureSessionPresetMedium: @"Medium", + AVCaptureSessionPresetHigh: @"High", + AVCaptureSessionPreset320x240: @"320x240", + AVCaptureSessionPreset352x288: @"352x288", + AVCaptureSessionPreset640x480: @"640x480", + AVCaptureSessionPreset960x540: @"960x540", + AVCaptureSessionPreset1280x720: @"1280x720", + AVCaptureSessionPreset1920x1080: @"1920x1080", + AVCaptureSessionPreset3840x2160: @"3840x2160", + AVCaptureSessionPresetHigh: @"High", + }; + NSString *name = preset_names[preset]; + if (name) + return name; + return [NSString stringWithFormat:@"Unknown (%@)", preset]; } -inline static void av_capture_defaults(obs_data_t *settings, - bool enable_audio_and_high_preset) +inline static void av_capture_defaults(obs_data_t *settings, bool enable_audio_and_high_preset) { - obs_data_set_default_string(settings, "uid", ""); - obs_data_set_default_bool(settings, "use_preset", true); + obs_data_set_default_string(settings, "uid", ""); + obs_data_set_default_bool(settings, "use_preset", true); - obs_data_set_default_string( - settings, "preset", - enable_audio_and_high_preset - ? AVCaptureSessionPresetHigh.UTF8String - : AVCaptureSessionPreset1280x720.UTF8String); + obs_data_set_default_string(settings, "preset", + enable_audio_and_high_preset ? AVCaptureSessionPresetHigh.UTF8String + : AVCaptureSessionPreset1280x720.UTF8String); - obs_data_set_default_int(settings, "input_format", INPUT_FORMAT_AUTO); - obs_data_set_default_int(settings, "color_space", COLOR_SPACE_AUTO); - obs_data_set_default_int(settings, "video_range", VIDEO_RANGE_AUTO); + obs_data_set_default_int(settings, "input_format", INPUT_FORMAT_AUTO); + obs_data_set_default_int(settings, "color_space", COLOR_SPACE_AUTO); + obs_data_set_default_int(settings, "video_range", VIDEO_RANGE_AUTO); - obs_data_set_default_bool(settings, "enable_audio", - enable_audio_and_high_preset); + obs_data_set_default_bool(settings, "enable_audio", enable_audio_and_high_preset); } static void av_capture_defaults_v1(obs_data_t *settings) { - av_capture_defaults(settings, false); + av_capture_defaults(settings, false); } static void av_capture_defaults_v2(obs_data_t *settings) { - av_capture_defaults(settings, true); + av_capture_defaults(settings, true); } -static bool update_device_list(obs_property_t *list, NSString *uid, - NSString *name, bool disconnected) +static bool update_device_list(obs_property_t *list, NSString *uid, NSString *name, bool disconnected) { - bool dev_found = false; - bool list_modified = false; + bool dev_found = false; + bool list_modified = false; - size_t size = obs_property_list_item_count(list); - for (size_t i = 0; i < size;) { - const char *uid_ = obs_property_list_item_string(list, i); - bool found = [uid isEqualToString:@(uid_ ? uid_ : "")]; - bool disabled = obs_property_list_item_disabled(list, i); - if (!found && !disabled) { - i += 1; - continue; - } + size_t size = obs_property_list_item_count(list); + for (size_t i = 0; i < size;) { + const char *uid_ = obs_property_list_item_string(list, i); + bool found = [uid isEqualToString:@(uid_ ? uid_ : "")]; + bool disabled = obs_property_list_item_disabled(list, i); + if (!found && !disabled) { + i += 1; + continue; + } - if (disabled && !found) { - list_modified = true; - obs_property_list_item_remove(list, i); - continue; - } + if (disabled && !found) { + list_modified = true; + obs_property_list_item_remove(list, i); + continue; + } - if (disabled != disconnected) - list_modified = true; + if (disabled != disconnected) + list_modified = true; - dev_found = true; - obs_property_list_item_disable(list, i, disconnected); - i += 1; - } + dev_found = true; + obs_property_list_item_disable(list, i, disconnected); + i += 1; + } - if (dev_found) - return list_modified; + if (dev_found) + return list_modified; - size_t idx = obs_property_list_add_string(list, name.UTF8String, - uid.UTF8String); - obs_property_list_item_disable(list, idx, disconnected); + size_t idx = obs_property_list_add_string(list, name.UTF8String, uid.UTF8String); + obs_property_list_item_disable(list, idx, disconnected); - return true; + return true; } -static void fill_presets(AVCaptureDevice *dev, obs_property_t *list, - NSString *current_preset) +static void fill_presets(AVCaptureDevice *dev, obs_property_t *list, NSString *current_preset) { - obs_property_list_clear(list); + obs_property_list_clear(list); - bool preset_found = false; - for (NSString *preset in presets()) { - bool is_current = [preset isEqualToString:current_preset]; - bool supported = dev && - [dev supportsAVCaptureSessionPreset:preset]; + bool preset_found = false; + for (NSString *preset in presets()) { + bool is_current = [preset isEqualToString:current_preset]; + bool supported = dev && [dev supportsAVCaptureSessionPreset:preset]; - if (is_current) - preset_found = true; + if (is_current) + preset_found = true; - if (!supported && !is_current) - continue; + if (!supported && !is_current) + continue; - size_t idx = obs_property_list_add_string( - list, preset_names(preset).UTF8String, - preset.UTF8String); - obs_property_list_item_disable(list, idx, !supported); - } + size_t idx = obs_property_list_add_string(list, preset_names(preset).UTF8String, preset.UTF8String); + obs_property_list_item_disable(list, idx, !supported); + } - if (preset_found) - return; + if (preset_found) + return; - size_t idx = obs_property_list_add_string( - list, preset_names(current_preset).UTF8String, - current_preset.UTF8String); - obs_property_list_item_disable(list, idx, true); + size_t idx = obs_property_list_add_string(list, preset_names(current_preset).UTF8String, current_preset.UTF8String); + obs_property_list_item_disable(list, idx, true); } -static bool check_preset(AVCaptureDevice *dev, obs_property_t *list, - obs_data_t *settings) +static bool check_preset(AVCaptureDevice *dev, obs_property_t *list, obs_data_t *settings) { - NSString *current_preset = get_string(settings, "preset"); + NSString *current_preset = get_string(settings, "preset"); - size_t size = obs_property_list_item_count(list); - NSMutableSet *listed = [NSMutableSet setWithCapacity:size]; + size_t size = obs_property_list_item_count(list); + NSMutableSet *listed = [NSMutableSet setWithCapacity:size]; - for (size_t i = 0; i < size; i++) - [listed addObject:@(obs_property_list_item_string(list, i))]; + for (size_t i = 0; i < size; i++) + [listed addObject:@(obs_property_list_item_string(list, i))]; - bool presets_changed = false; - for (NSString *preset in presets()) { - bool is_listed = [listed member:preset] != nil; - bool supported = dev && - [dev supportsAVCaptureSessionPreset:preset]; + bool presets_changed = false; + for (NSString *preset in presets()) { + bool is_listed = [listed member:preset] != nil; + bool supported = dev && [dev supportsAVCaptureSessionPreset:preset]; - if (supported == is_listed) - continue; + if (supported == is_listed) + continue; - presets_changed = true; - } + presets_changed = true; + } - if (!presets_changed && [listed member:current_preset] != nil) - return false; + if (!presets_changed && [listed member:current_preset] != nil) + return false; - fill_presets(dev, list, current_preset); - return true; + fill_presets(dev, list, current_preset); + return true; } static bool autoselect_preset(AVCaptureDevice *dev, obs_data_t *settings) { - NSString *preset = get_string(settings, "preset"); - if (!dev || [dev supportsAVCaptureSessionPreset:preset]) { - if (obs_data_has_autoselect_value(settings, "preset")) { - obs_data_unset_autoselect_value(settings, "preset"); - return true; - } + NSString *preset = get_string(settings, "preset"); + if (!dev || [dev supportsAVCaptureSessionPreset:preset]) { + if (obs_data_has_autoselect_value(settings, "preset")) { + obs_data_unset_autoselect_value(settings, "preset"); + return true; + } - } else { - preset = select_preset(dev, preset); - const char *autoselect = - obs_data_get_autoselect_string(settings, "preset"); - if (![preset isEqualToString:@(autoselect)]) { - obs_data_set_autoselect_string(settings, "preset", - preset.UTF8String); - return true; - } - } + } else { + preset = select_preset(dev, preset); + const char *autoselect = obs_data_get_autoselect_string(settings, "preset"); + if (![preset isEqualToString:@(autoselect)]) { + obs_data_set_autoselect_string(settings, "preset", preset.UTF8String); + return true; + } + } - return false; + return false; } static CMVideoDimensions get_dimensions(AVCaptureDeviceFormat *format) { - auto desc = format.formatDescription; - return CMVideoFormatDescriptionGetDimensions(desc); + auto desc = format.formatDescription; + return CMVideoFormatDescriptionGetDimensions(desc); } using resolutions_t = vector; static resolutions_t enumerate_resolutions(AVCaptureDevice *dev) { - resolutions_t res; + resolutions_t res; - if (!dev) - return res; + if (!dev) + return res; - res.reserve(dev.formats.count + 1); + res.reserve(dev.formats.count + 1); - for (AVCaptureDeviceFormat *format in dev.formats) { - auto dims = get_dimensions(format); + for (AVCaptureDeviceFormat *format in dev.formats) { + auto dims = get_dimensions(format); - if (find(begin(res), end(res), dims) == end(res)) - res.push_back(dims); - } + if (find(begin(res), end(res), dims) == end(res)) + res.push_back(dims); + } - return res; + return res; } static void sort_resolutions(vector &resolutions) { - auto cmp = [](const CMVideoDimensions &a, const CMVideoDimensions &b) { - return a.width * a.height > b.width * b.height; - }; + auto cmp = [](const CMVideoDimensions &a, const CMVideoDimensions &b) { + return a.width * a.height > b.width * b.height; + }; - sort(begin(resolutions), end(resolutions), cmp); + sort(begin(resolutions), end(resolutions), cmp); } static void data_set_resolution(obs_data_t *data, const CMVideoDimensions &dims) { - obs_data_set_int(data, "width", dims.width); - obs_data_set_int(data, "height", dims.height); + obs_data_set_int(data, "width", dims.width); + obs_data_set_int(data, "height", dims.height); } -static void data_set_resolution(const unique_ptr &data, - const CMVideoDimensions &dims) +static void data_set_resolution(const unique_ptr &data, const CMVideoDimensions &dims) { - data_set_resolution(data.get(), dims); + data_set_resolution(data.get(), dims); } -static bool add_resolution_to_list(vector &res, - const CMVideoDimensions &dims) +static bool add_resolution_to_list(vector &res, const CMVideoDimensions &dims) { - if (find(begin(res), end(res), dims) != end(res)) - return false; + if (find(begin(res), end(res), dims) != end(res)) + return false; - res.push_back(dims); - return true; + res.push_back(dims); + return true; } static const char *obs_data_get_json(const unique_ptr &data) { - return obs_data_get_json(data.get()); + return obs_data_get_json(data.get()); } static bool operator==(const CMVideoDimensions &a, const CMVideoDimensions &b) { - return a.width == b.width && a.height == b.height; + return a.width == b.width && a.height == b.height; } -static bool resolution_property_needs_update(obs_property_t *p, - const resolutions_t &resolutions) +static bool resolution_property_needs_update(obs_property_t *p, const resolutions_t &resolutions) { - vector res_found(resolutions.size()); + vector res_found(resolutions.size()); - auto num = obs_property_list_item_count(p); - for (size_t i = 1; i < num; i++) { // skip empty entry - const char *json = obs_property_list_item_string(p, i); - unique_ptr buffer{obs_data_create_from_json(json)}; + auto num = obs_property_list_item_count(p); + for (size_t i = 1; i < num; i++) { // skip empty entry + const char *json = obs_property_list_item_string(p, i); + unique_ptr buffer {obs_data_create_from_json(json)}; - CMVideoDimensions dims{}; - if (!get_resolution(buffer.get(), dims)) - return true; + CMVideoDimensions dims {}; + if (!get_resolution(buffer.get(), dims)) + return true; - auto pos = find(begin(resolutions), end(resolutions), dims); - if (pos == end(resolutions)) - return true; + auto pos = find(begin(resolutions), end(resolutions), dims); + if (pos == end(resolutions)) + return true; - res_found[pos - begin(resolutions)] = true; - } + res_found[pos - begin(resolutions)] = true; + } - return any_of(begin(res_found), end(res_found), - [](bool b) { return !b; }); + return any_of(begin(res_found), end(res_found), [](bool b) { + return !b; + }); } -static bool update_resolution_property(obs_properties_t *props, - const config_helper &conf, - obs_property_t *p = nullptr) +static bool update_resolution_property(obs_properties_t *props, const config_helper &conf, obs_property_t *p = nullptr) { - if (!p) - p = obs_properties_get(props, "resolution"); + if (!p) + p = obs_properties_get(props, "resolution"); - if (!p) - return false; + if (!p) + return false; - auto valid_dims = conf.dims(); - auto resolutions = enumerate_resolutions(conf.dev()); + auto valid_dims = conf.dims(); + auto resolutions = enumerate_resolutions(conf.dev()); - bool unsupported = true; - if (valid_dims) - unsupported = add_resolution_to_list(resolutions, *valid_dims); + bool unsupported = true; + if (valid_dims) + unsupported = add_resolution_to_list(resolutions, *valid_dims); - bool was_enabled = obs_property_enabled(p); - obs_property_set_enabled(p, !!conf.dev()); + bool was_enabled = obs_property_enabled(p); + obs_property_set_enabled(p, !!conf.dev()); - if (!resolution_property_needs_update(p, resolutions)) - return was_enabled != obs_property_enabled(p); + if (!resolution_property_needs_update(p, resolutions)) + return was_enabled != obs_property_enabled(p); - sort_resolutions(resolutions); + sort_resolutions(resolutions); - obs_property_list_clear(p); - obs_property_list_add_string(p, "", "{}"); + obs_property_list_clear(p); + obs_property_list_add_string(p, "", "{}"); - DStr name; - unique_ptr buffer{obs_data_create()}; - for (const CMVideoDimensions &dims : resolutions) { - data_set_resolution(buffer, dims); - auto json = obs_data_get_json(buffer); - dstr_printf(name, "%dx%d", dims.width, dims.height); - size_t idx = obs_property_list_add_string(p, name->array, json); + DStr name; + unique_ptr buffer {obs_data_create()}; + for (const CMVideoDimensions &dims : resolutions) { + data_set_resolution(buffer, dims); + auto json = obs_data_get_json(buffer); + dstr_printf(name, "%dx%d", dims.width, dims.height); + size_t idx = obs_property_list_add_string(p, name->array, json); - if (unsupported && valid_dims && dims == *valid_dims) - obs_property_list_item_disable(p, idx, true); - } + if (unsupported && valid_dims && dims == *valid_dims) + obs_property_list_item_disable(p, idx, true); + } - return true; + return true; } static media_frames_per_second convert(CMTime time_) { - media_frames_per_second res{}; - clamp(res.numerator, time_.timescale); - clamp(res.denominator, time_.value); - return res; + media_frames_per_second res {}; + clamp(res.numerator, time_.timescale); + clamp(res.denominator, time_.value); + return res; } -using frame_rates_t = - vector>; -static frame_rates_t -enumerate_frame_rates(AVCaptureDevice *dev, - const CMVideoDimensions *dims = nullptr) +using frame_rates_t = vector>; +static frame_rates_t enumerate_frame_rates(AVCaptureDevice *dev, const CMVideoDimensions *dims = nullptr) { - frame_rates_t res; + frame_rates_t res; - if (!dev || !dims) - return res; + if (!dev || !dims) + return res; - auto add_unique_frame_rate_range = [&](AVFrameRateRange *range) { - auto min = convert(range.maxFrameDuration); - auto max = convert(range.minFrameDuration); + auto add_unique_frame_rate_range = [&](AVFrameRateRange *range) { + auto min = convert(range.maxFrameDuration); + auto max = convert(range.minFrameDuration); - auto pair = make_pair(min, max); + auto pair = make_pair(min, max); - if (find(begin(res), end(res), pair) != end(res)) - return; + if (find(begin(res), end(res), pair) != end(res)) + return; - res.push_back(pair); - }; + res.push_back(pair); + }; - for (AVCaptureDeviceFormat *format in dev.formats) { - if (!(get_dimensions(format) == *dims)) - continue; + for (AVCaptureDeviceFormat *format in dev.formats) { + if (!(get_dimensions(format) == *dims)) + continue; - for (AVFrameRateRange *range in format - .videoSupportedFrameRateRanges) { - add_unique_frame_rate_range(range); + for (AVFrameRateRange *range in format.videoSupportedFrameRateRanges) { + add_unique_frame_rate_range(range); - if (CMTimeCompare(range.minFrameDuration, - range.maxFrameDuration) != 0) { - blog(LOG_WARNING, - "Got actual frame rate range:" - " %g - %g " - "({%lld, %d} - {%lld, %d})", - range.minFrameRate, range.maxFrameRate, - range.maxFrameDuration.value, - range.maxFrameDuration.timescale, - range.minFrameDuration.value, - range.minFrameDuration.timescale); - } - } - } + if (CMTimeCompare(range.minFrameDuration, range.maxFrameDuration) != 0) { + blog(LOG_WARNING, + "Got actual frame rate range:" + " %g - %g " + "({%lld, %d} - {%lld, %d})", + range.minFrameRate, range.maxFrameRate, range.maxFrameDuration.value, + range.maxFrameDuration.timescale, range.minFrameDuration.value, range.minFrameDuration.timescale); + } + } + } - return res; + return res; } -static bool operator==(const media_frames_per_second &a, - const media_frames_per_second &b) +static bool operator==(const media_frames_per_second &a, const media_frames_per_second &b) { - return a.numerator == b.numerator && a.denominator == b.denominator; + return a.numerator == b.numerator && a.denominator == b.denominator; } -static bool operator!=(const media_frames_per_second &a, - const media_frames_per_second &b) +static bool operator!=(const media_frames_per_second &a, const media_frames_per_second &b) { - return !(a == b); + return !(a == b); } -static bool frame_rate_property_needs_update(obs_property_t *p, - const frame_rates_t &frame_rates) +static bool frame_rate_property_needs_update(obs_property_t *p, const frame_rates_t &frame_rates) { - auto fps_num = frame_rates.size(); - auto num = obs_property_frame_rate_fps_ranges_count(p); - if (fps_num != num) - return true; + auto fps_num = frame_rates.size(); + auto num = obs_property_frame_rate_fps_ranges_count(p); + if (fps_num != num) + return true; - vector fps_found(fps_num); - for (size_t i = 0; i < num; i++) { - auto min_ = obs_property_frame_rate_fps_range_min(p, i); - auto max_ = obs_property_frame_rate_fps_range_max(p, i); + vector fps_found(fps_num); + for (size_t i = 0; i < num; i++) { + auto min_ = obs_property_frame_rate_fps_range_min(p, i); + auto max_ = obs_property_frame_rate_fps_range_max(p, i); - auto it = find(begin(frame_rates), end(frame_rates), - make_pair(min_, max_)); - if (it == end(frame_rates)) - return true; + auto it = find(begin(frame_rates), end(frame_rates), make_pair(min_, max_)); + if (it == end(frame_rates)) + return true; - fps_found[it - begin(frame_rates)] = true; - } + fps_found[it - begin(frame_rates)] = true; + } - return any_of(begin(fps_found), end(fps_found), - [](bool b) { return !b; }); + return any_of(begin(fps_found), end(fps_found), [](bool b) { + return !b; + }); } -static bool update_frame_rate_property(obs_properties_t *props, - const config_helper &conf, - obs_property_t *p = nullptr) +static bool update_frame_rate_property(obs_properties_t *props, const config_helper &conf, obs_property_t *p = nullptr) { - if (!p) - p = obs_properties_get(props, "frame_rate"); + if (!p) + p = obs_properties_get(props, "frame_rate"); - if (!p) - return false; + if (!p) + return false; - auto valid_dims = conf.dims(); - auto frame_rates = enumerate_frame_rates(conf.dev(), valid_dims); + auto valid_dims = conf.dims(); + auto frame_rates = enumerate_frame_rates(conf.dev(), valid_dims); - bool was_enabled = obs_property_enabled(p); - obs_property_set_enabled(p, !frame_rates.empty()); + bool was_enabled = obs_property_enabled(p); + obs_property_set_enabled(p, !frame_rates.empty()); - if (!frame_rate_property_needs_update(p, frame_rates)) - return was_enabled != obs_property_enabled(p); + if (!frame_rate_property_needs_update(p, frame_rates)) + return was_enabled != obs_property_enabled(p); - obs_property_frame_rate_fps_ranges_clear(p); - for (auto &pair : frame_rates) - obs_property_frame_rate_fps_range_add(p, pair.first, - pair.second); + obs_property_frame_rate_fps_ranges_clear(p); + for (auto &pair : frame_rates) + obs_property_frame_rate_fps_range_add(p, pair.first, pair.second); - return true; + return true; } -static vector -enumerate_formats(AVCaptureDevice *dev, const CMVideoDimensions &dims, - const media_frames_per_second &fps) +static vector enumerate_formats(AVCaptureDevice *dev, const CMVideoDimensions &dims, + const media_frames_per_second &fps) { - vector result; + vector result; - find_formats(fps, dev, &dims, [&](AVCaptureDeviceFormat *format) { - result.push_back(format); - return false; - }); + find_formats(fps, dev, &dims, [&](AVCaptureDeviceFormat *format) { + result.push_back(format); + return false; + }); - return result; + return result; } -static bool input_format_property_needs_update( - obs_property_t *p, const vector &formats, - const FourCharCode *fourcc_) +static bool input_format_property_needs_update(obs_property_t *p, const vector &formats, + const FourCharCode *fourcc_) { - bool fourcc_found = !fourcc_; - vector if_found(formats.size()); + bool fourcc_found = !fourcc_; + vector if_found(formats.size()); - auto num = obs_property_list_item_count(p); - for (size_t i = 1; i < num; i++) { // skip auto entry - FourCharCode fourcc = - (FourCharCode)obs_property_list_item_int(p, i); - fourcc_found = fourcc_found || fourcc == *fourcc_; + auto num = obs_property_list_item_count(p); + for (size_t i = 1; i < num; i++) { // skip auto entry + FourCharCode fourcc = (FourCharCode) obs_property_list_item_int(p, i); + fourcc_found = fourcc_found || fourcc == *fourcc_; - auto pos = find_if(begin(formats), end(formats), - [&](AVCaptureDeviceFormat *format) { - FourCharCode fourcc_ = 0; - format_description_subtype_name( - format.formatDescription, - &fourcc_); - return fourcc_ == fourcc; - }); - if (pos == end(formats)) - return true; + auto pos = find_if(begin(formats), end(formats), [&](AVCaptureDeviceFormat *format) { + FourCharCode fourcc_ = 0; + format_description_subtype_name(format.formatDescription, &fourcc_); + return fourcc_ == fourcc; + }); + if (pos == end(formats)) + return true; - if_found[pos - begin(formats)] = true; - } + if_found[pos - begin(formats)] = true; + } - return fourcc_found || any_of(begin(if_found), end(if_found), - [](bool b) { return !b; }); + return fourcc_found || any_of(begin(if_found), end(if_found), [](bool b) { + return !b; + }); } -static bool update_input_format_property(obs_properties_t *props, - const config_helper &conf, - obs_property_t *p = nullptr) +static bool update_input_format_property(obs_properties_t *props, const config_helper &conf, + obs_property_t *p = nullptr) { - if (!p) - p = obs_properties_get(props, "input_format"); + if (!p) + p = obs_properties_get(props, "input_format"); - if (!p) - return false; + if (!p) + return false; - auto update_enabled = [&](bool enabled) { - bool was_enabled = obs_property_enabled(p); - obs_property_set_enabled(p, enabled); - return was_enabled != enabled; - }; + auto update_enabled = [&](bool enabled) { + bool was_enabled = obs_property_enabled(p); + obs_property_set_enabled(p, enabled); + return was_enabled != enabled; + }; - auto valid_dims = conf.dims(); - auto valid_fps = conf.fps(); - auto valid_if = conf.input_format(); + auto valid_dims = conf.dims(); + auto valid_fps = conf.fps(); + auto valid_if = conf.input_format(); - if (!valid_dims || !valid_fps) - return update_enabled(false); + if (!valid_dims || !valid_fps) + return update_enabled(false); - auto formats = enumerate_formats(conf.dev(), *valid_dims, *valid_fps); - if (!input_format_property_needs_update(p, formats, valid_if)) - return update_enabled(!formats.empty()); + auto formats = enumerate_formats(conf.dev(), *valid_dims, *valid_fps); + if (!input_format_property_needs_update(p, formats, valid_if)) + return update_enabled(!formats.empty()); - while (obs_property_list_item_count(p) > 1) - obs_property_list_item_remove(p, 1); + while (obs_property_list_item_count(p) > 1) + obs_property_list_item_remove(p, 1); - bool fourcc_found = !valid_if || *valid_if == INPUT_FORMAT_AUTO; - for (auto &format : formats) { - FourCharCode fourcc = 0; - const char *name = format_description_subtype_name( - format.formatDescription, &fourcc); - obs_property_list_add_int(p, name, fourcc); - fourcc_found = fourcc_found || fourcc == *valid_if; - } + bool fourcc_found = !valid_if || *valid_if == INPUT_FORMAT_AUTO; + for (auto &format : formats) { + FourCharCode fourcc = 0; + const char *name = format_description_subtype_name(format.formatDescription, &fourcc); + obs_property_list_add_int(p, name, fourcc); + fourcc_found = fourcc_found || fourcc == *valid_if; + } - if (!fourcc_found) { - const char *name = fourcc_subtype_name(*valid_if); - obs_property_list_add_int(p, name, *valid_if); - } + if (!fourcc_found) { + const char *name = fourcc_subtype_name(*valid_if); + obs_property_list_add_int(p, name, *valid_if); + } - return update_enabled(!formats.empty()); + return update_enabled(!formats.empty()); } -static bool update_int_list_property(obs_property_t *p, const int *val, - const size_t count, - const char *localization_name) +static bool update_int_list_property(obs_property_t *p, const int *val, const size_t count, + const char *localization_name) { - size_t num = obs_property_list_item_count(p); - if (num > count) { - if (!val || obs_property_list_item_int(p, count) != *val) { - obs_property_list_item_remove(p, count); + size_t num = obs_property_list_item_count(p); + if (num > count) { + if (!val || obs_property_list_item_int(p, count) != *val) { + obs_property_list_item_remove(p, count); - if (!val) - return true; - } else { - return false; - } - } + if (!val) + return true; + } else { + return false; + } + } - if (!val) - return false; + if (!val) + return false; - DStr buf, label; - dstr_printf(buf, "%d", *val); - dstr_init_copy(label, obs_module_text(localization_name)); - dstr_replace(label, "%1", buf->array); - size_t idx = obs_property_list_add_int(p, label->array, *val); - obs_property_list_item_disable(p, idx, true); + DStr buf, label; + dstr_printf(buf, "%d", *val); + dstr_init_copy(label, obs_module_text(localization_name)); + dstr_replace(label, "%1", buf->array); + size_t idx = obs_property_list_add_int(p, label->array, *val); + obs_property_list_item_disable(p, idx, true); - return true; + return true; } template -static bool -update_int_list_property(const char *prop_name, const char *localization_name, - size_t count, int auto_val, bool (*valid_func)(int), - obs_properties_t *props, const config_helper &conf, - obs_property_t *p, Func get_val) +static bool update_int_list_property(const char *prop_name, const char *localization_name, size_t count, int auto_val, + bool (*valid_func)(int), obs_properties_t *props, const config_helper &conf, + obs_property_t *p, Func get_val) { - auto ref = get_ref(props); - if (!p) - p = obs_properties_get(props, prop_name); + auto ref = get_ref(props); + if (!p) + p = obs_properties_get(props, prop_name); - int val = (int)obs_data_get_int(conf.settings, prop_name); + int val = (int) obs_data_get_int(conf.settings, prop_name); - av_video_info vi; - if (ref) - vi = ref->video_info.read(); + av_video_info vi; + if (ref) + vi = ref->video_info.read(); - bool params_valid = vi.video_params_valid; - bool enabled = obs_property_enabled(p); - bool should_enable = false; - bool has_autoselect = - obs_data_has_autoselect_value(conf.settings, prop_name); + bool params_valid = vi.video_params_valid; + bool enabled = obs_property_enabled(p); + bool should_enable = false; + bool has_autoselect = obs_data_has_autoselect_value(conf.settings, prop_name); - if ((params_valid && format_is_yuv(ref->frame.format)) || - !valid_func(val)) - should_enable = true; + if ((params_valid && format_is_yuv(ref->frame.format)) || !valid_func(val)) + should_enable = true; - obs_property_set_enabled(p, should_enable); - bool updated = enabled != should_enable; + obs_property_set_enabled(p, should_enable); + bool updated = enabled != should_enable; - updated = update_int_list_property(p, valid_func(val) ? nullptr : &val, - count, localization_name) || - updated; + updated = update_int_list_property(p, valid_func(val) ? nullptr : &val, count, localization_name) || updated; - if (!should_enable) { - if (has_autoselect) - obs_data_unset_autoselect_value(conf.settings, - prop_name); - return updated || has_autoselect; - } + if (!should_enable) { + if (has_autoselect) + obs_data_unset_autoselect_value(conf.settings, prop_name); + return updated || has_autoselect; + } - bool use_autoselect = ref && val == auto_val; - if (!use_autoselect) { - if (has_autoselect) - obs_data_unset_autoselect_value(conf.settings, - prop_name); - return updated || has_autoselect; - } + bool use_autoselect = ref && val == auto_val; + if (!use_autoselect) { + if (has_autoselect) + obs_data_unset_autoselect_value(conf.settings, prop_name); + return updated || has_autoselect; + } - if (params_valid && get_val(vi) != obs_data_get_autoselect_int( - conf.settings, prop_name)) { - obs_data_set_autoselect_int(conf.settings, prop_name, - get_val(vi)); - return true; - } + if (params_valid && get_val(vi) != obs_data_get_autoselect_int(conf.settings, prop_name)) { + obs_data_set_autoselect_int(conf.settings, prop_name, get_val(vi)); + return true; + } - return updated; + return updated; } -static bool update_color_space_property(obs_properties_t *props, - const config_helper &conf, - obs_property_t *p = nullptr) +static bool update_color_space_property(obs_properties_t *props, const config_helper &conf, obs_property_t *p = nullptr) { - return update_int_list_property("color_space", TEXT_COLOR_UNKNOWN_NAME, - 4, COLOR_SPACE_AUTO, color_space_valid, - props, conf, p, [](av_video_info vi) { - return vi.colorspace; - }); + return update_int_list_property("color_space", TEXT_COLOR_UNKNOWN_NAME, 4, COLOR_SPACE_AUTO, color_space_valid, + props, conf, p, [](av_video_info vi) { + return vi.colorspace; + }); } -static bool update_video_range_property(obs_properties_t *props, - const config_helper &conf, - obs_property_t *p = nullptr) +static bool update_video_range_property(obs_properties_t *props, const config_helper &conf, obs_property_t *p = nullptr) { - return update_int_list_property("video_range", TEXT_RANGE_UNKNOWN_NAME, - 5, VIDEO_RANGE_AUTO, video_range_valid, - props, conf, p, [](av_video_info vi) { - return vi.video_range; - }); + return update_int_list_property("video_range", TEXT_RANGE_UNKNOWN_NAME, 5, VIDEO_RANGE_AUTO, video_range_valid, + props, conf, p, [](av_video_info vi) { + return vi.video_range; + }); } -static bool properties_device_changed(obs_properties_t *props, - obs_property_t *p, obs_data_t *settings) +static bool properties_device_changed(obs_properties_t *props, obs_property_t *p, obs_data_t *settings) { - NSString *uid = get_string(settings, "device"); - AVCaptureDevice *dev = [AVCaptureDevice deviceWithUniqueID:uid]; + NSString *uid = get_string(settings, "device"); + AVCaptureDevice *dev = [AVCaptureDevice deviceWithUniqueID:uid]; - NSString *name = get_string(settings, "device_name"); - bool dev_list_updated = - update_device_list(p, uid, name, !dev && uid.length); + NSString *name = get_string(settings, "device_name"); + bool dev_list_updated = update_device_list(p, uid, name, !dev && uid.length); - p = obs_properties_get(props, "preset"); - bool preset_list_changed = check_preset(dev, p, settings); - bool autoselect_changed = autoselect_preset(dev, settings); + p = obs_properties_get(props, "preset"); + bool preset_list_changed = check_preset(dev, p, settings); + bool autoselect_changed = autoselect_preset(dev, settings); - config_helper conf{settings}; - bool res_changed = update_resolution_property(props, conf); - bool fps_changed = update_frame_rate_property(props, conf); - bool if_changed = update_input_format_property(props, conf); + config_helper conf {settings}; + bool res_changed = update_resolution_property(props, conf); + bool fps_changed = update_frame_rate_property(props, conf); + bool if_changed = update_input_format_property(props, conf); - return preset_list_changed || autoselect_changed || dev_list_updated || - res_changed || fps_changed || if_changed; + return preset_list_changed || autoselect_changed || dev_list_updated || res_changed || fps_changed || if_changed; } -static bool properties_use_preset_changed(obs_properties_t *props, - obs_property_t *, - obs_data_t *settings) +static bool properties_use_preset_changed(obs_properties_t *props, obs_property_t *, obs_data_t *settings) { - auto use_preset = obs_data_get_bool(settings, "use_preset"); + auto use_preset = obs_data_get_bool(settings, "use_preset"); - config_helper conf{settings}; + config_helper conf {settings}; - bool updated = false; - bool visible = false; - obs_property_t *p = nullptr; + bool updated = false; + bool visible = false; + obs_property_t *p = nullptr; - auto noop = [](obs_properties_t *, const config_helper &, - obs_property_t *) { return false; }; + auto noop = [](obs_properties_t *, const config_helper &, obs_property_t *) { + return false; + }; -#define UPDATE_PROPERTY(prop, uses_preset, func) \ - p = obs_properties_get(props, prop); \ - visible = use_preset == uses_preset; \ - updated = obs_property_visible(p) != visible || updated; \ - obs_property_set_visible(p, visible); \ - updated = func(props, conf, p) || updated; +#define UPDATE_PROPERTY(prop, uses_preset, func) \ + p = obs_properties_get(props, prop); \ + visible = use_preset == uses_preset; \ + updated = obs_property_visible(p) != visible || updated; \ + obs_property_set_visible(p, visible); \ + updated = func(props, conf, p) || updated; - UPDATE_PROPERTY("preset", true, noop); - UPDATE_PROPERTY("resolution", false, update_resolution_property); - UPDATE_PROPERTY("frame_rate", false, update_frame_rate_property); - UPDATE_PROPERTY("input_format", false, update_input_format_property); - UPDATE_PROPERTY("color_space", false, update_color_space_property); - UPDATE_PROPERTY("video_range", false, update_video_range_property); + UPDATE_PROPERTY("preset", true, noop); + UPDATE_PROPERTY("resolution", false, update_resolution_property); + UPDATE_PROPERTY("frame_rate", false, update_frame_rate_property); + UPDATE_PROPERTY("input_format", false, update_input_format_property); + UPDATE_PROPERTY("color_space", false, update_color_space_property); + UPDATE_PROPERTY("video_range", false, update_video_range_property); - return updated; + return updated; } -static bool properties_preset_changed(obs_properties_t *, obs_property_t *p, - obs_data_t *settings) +static bool properties_preset_changed(obs_properties_t *, obs_property_t *p, obs_data_t *settings) { - NSString *uid = get_string(settings, "device"); - AVCaptureDevice *dev = [AVCaptureDevice deviceWithUniqueID:uid]; + NSString *uid = get_string(settings, "device"); + AVCaptureDevice *dev = [AVCaptureDevice deviceWithUniqueID:uid]; - bool preset_list_changed = check_preset(dev, p, settings); - bool autoselect_changed = autoselect_preset(dev, settings); + bool preset_list_changed = check_preset(dev, p, settings); + bool autoselect_changed = autoselect_preset(dev, settings); - return preset_list_changed || autoselect_changed; + return preset_list_changed || autoselect_changed; } -static bool properties_resolution_changed(obs_properties_t *props, - obs_property_t *p, - obs_data_t *settings) +static bool properties_resolution_changed(obs_properties_t *props, obs_property_t *p, obs_data_t *settings) { - config_helper conf{settings}; + config_helper conf {settings}; - bool res_updated = update_resolution_property(props, conf, p); - bool fps_updated = update_frame_rate_property(props, conf); - bool if_updated = update_input_format_property(props, conf); - bool cs_updated = update_color_space_property(props, conf); - bool cr_updated = update_video_range_property(props, conf); + bool res_updated = update_resolution_property(props, conf, p); + bool fps_updated = update_frame_rate_property(props, conf); + bool if_updated = update_input_format_property(props, conf); + bool cs_updated = update_color_space_property(props, conf); + bool cr_updated = update_video_range_property(props, conf); - return res_updated || fps_updated || if_updated || cs_updated || - cr_updated; + return res_updated || fps_updated || if_updated || cs_updated || cr_updated; } -static bool properties_frame_rate_changed(obs_properties_t *props, - obs_property_t *p, - obs_data_t *settings) +static bool properties_frame_rate_changed(obs_properties_t *props, obs_property_t *p, obs_data_t *settings) { - config_helper conf{settings}; + config_helper conf {settings}; - bool fps_updated = update_frame_rate_property(props, conf, p); - bool if_updated = update_input_format_property(props, conf); - bool cs_updated = update_color_space_property(props, conf); - bool cr_updated = update_video_range_property(props, conf); + bool fps_updated = update_frame_rate_property(props, conf, p); + bool if_updated = update_input_format_property(props, conf); + bool cs_updated = update_color_space_property(props, conf); + bool cr_updated = update_video_range_property(props, conf); - return fps_updated || if_updated || cs_updated || cr_updated; + return fps_updated || if_updated || cs_updated || cr_updated; } -static bool properties_input_format_changed(obs_properties_t *props, - obs_property_t *p, - obs_data_t *settings) +static bool properties_input_format_changed(obs_properties_t *props, obs_property_t *p, obs_data_t *settings) { - config_helper conf{settings}; + config_helper conf {settings}; - bool if_updated = update_input_format_property(props, conf, p); - bool cs_updated = update_color_space_property(props, conf); - bool cr_updated = update_video_range_property(props, conf); + bool if_updated = update_input_format_property(props, conf, p); + bool cs_updated = update_color_space_property(props, conf); + bool cr_updated = update_video_range_property(props, conf); - return if_updated || cs_updated || cr_updated; + return if_updated || cs_updated || cr_updated; } -static bool properties_color_space_changed(obs_properties_t *props, - obs_property_t *p, - obs_data_t *settings) +static bool properties_color_space_changed(obs_properties_t *props, obs_property_t *p, obs_data_t *settings) { - config_helper conf{settings}; + config_helper conf {settings}; - return update_color_space_property(props, conf, p); + return update_color_space_property(props, conf, p); } -static bool properties_video_range_changed(obs_properties_t *props, - obs_property_t *p, - obs_data_t *settings) +static bool properties_video_range_changed(obs_properties_t *props, obs_property_t *p, obs_data_t *settings) { - config_helper conf{settings}; + config_helper conf {settings}; - return update_video_range_property(props, conf, p); + return update_video_range_property(props, conf, p); } static void add_properties_param(obs_properties_t *props, av_capture *capture) { - auto param = - unique_ptr(new properties_param(capture)); + auto param = unique_ptr(new properties_param(capture)); - obs_properties_set_param(props, param.release(), [](void *param) { - delete static_cast(param); - }); + obs_properties_set_param(props, param.release(), [](void *param) { + delete static_cast(param); + }); } static void add_preset_properties(obs_properties_t *props) { - obs_property_t *preset_list = obs_properties_add_list( - props, "preset", TEXT_PRESET, OBS_COMBO_TYPE_LIST, - OBS_COMBO_FORMAT_STRING); - for (NSString *preset in presets()) - obs_property_list_add_string(preset_list, - preset_names(preset).UTF8String, - preset.UTF8String); + obs_property_t *preset_list = + obs_properties_add_list(props, "preset", TEXT_PRESET, OBS_COMBO_TYPE_LIST, OBS_COMBO_FORMAT_STRING); + for (NSString *preset in presets()) + obs_property_list_add_string(preset_list, preset_names(preset).UTF8String, preset.UTF8String); - obs_property_set_modified_callback(preset_list, - properties_preset_changed); + obs_property_set_modified_callback(preset_list, properties_preset_changed); } static void add_manual_properties(obs_properties_t *props) { - obs_property_t *resolutions = obs_properties_add_list( - props, "resolution", TEXT_RESOLUTION, OBS_COMBO_TYPE_LIST, - OBS_COMBO_FORMAT_STRING); - obs_property_set_enabled(resolutions, false); - obs_property_set_modified_callback(resolutions, - properties_resolution_changed); + obs_property_t *resolutions = + obs_properties_add_list(props, "resolution", TEXT_RESOLUTION, OBS_COMBO_TYPE_LIST, OBS_COMBO_FORMAT_STRING); + obs_property_set_enabled(resolutions, false); + obs_property_set_modified_callback(resolutions, properties_resolution_changed); - obs_property_t *frame_rates = obs_properties_add_frame_rate( - props, "frame_rate", TEXT_FRAME_RATE); - /*obs_property_frame_rate_option_add(frame_rates, "match obs", + obs_property_t *frame_rates = obs_properties_add_frame_rate(props, "frame_rate", TEXT_FRAME_RATE); + /*obs_property_frame_rate_option_add(frame_rates, "match obs", TEXT_MATCH_OBS);*/ - obs_property_set_enabled(frame_rates, false); - obs_property_set_modified_callback(frame_rates, - properties_frame_rate_changed); + obs_property_set_enabled(frame_rates, false); + obs_property_set_modified_callback(frame_rates, properties_frame_rate_changed); - obs_property_t *input_format = obs_properties_add_list( - props, "input_format", TEXT_INPUT_FORMAT, OBS_COMBO_TYPE_LIST, - OBS_COMBO_FORMAT_INT); - obs_property_list_add_int(input_format, TEXT_AUTO, INPUT_FORMAT_AUTO); - obs_property_set_enabled(input_format, false); - obs_property_set_modified_callback(input_format, - properties_input_format_changed); + obs_property_t *input_format = + obs_properties_add_list(props, "input_format", TEXT_INPUT_FORMAT, OBS_COMBO_TYPE_LIST, OBS_COMBO_FORMAT_INT); + obs_property_list_add_int(input_format, TEXT_AUTO, INPUT_FORMAT_AUTO); + obs_property_set_enabled(input_format, false); + obs_property_set_modified_callback(input_format, properties_input_format_changed); - obs_property_t *color_space = obs_properties_add_list( - props, "color_space", TEXT_COLOR_SPACE, OBS_COMBO_TYPE_LIST, - OBS_COMBO_FORMAT_INT); - obs_property_list_add_int(color_space, TEXT_AUTO, COLOR_SPACE_AUTO); - obs_property_list_add_int(color_space, "Rec. 601", VIDEO_CS_601); - obs_property_list_add_int(color_space, "Rec. 709", VIDEO_CS_709); - obs_property_set_enabled(color_space, false); - obs_property_set_modified_callback(color_space, - properties_color_space_changed); + obs_property_t *color_space = + obs_properties_add_list(props, "color_space", TEXT_COLOR_SPACE, OBS_COMBO_TYPE_LIST, OBS_COMBO_FORMAT_INT); + obs_property_list_add_int(color_space, TEXT_AUTO, COLOR_SPACE_AUTO); + obs_property_list_add_int(color_space, "Rec. 601", VIDEO_CS_601); + obs_property_list_add_int(color_space, "Rec. 709", VIDEO_CS_709); + obs_property_set_enabled(color_space, false); + obs_property_set_modified_callback(color_space, properties_color_space_changed); #define ADD_RANGE(x) obs_property_list_add_int(video_range, TEXT_##x, VIDEO_##x) - obs_property_t *video_range = obs_properties_add_list( - props, "video_range", TEXT_VIDEO_RANGE, OBS_COMBO_TYPE_LIST, - OBS_COMBO_FORMAT_INT); - obs_property_list_add_int(video_range, TEXT_AUTO, VIDEO_RANGE_AUTO); - ADD_RANGE(RANGE_PARTIAL); - ADD_RANGE(RANGE_FULL); - obs_property_set_enabled(video_range, false); - obs_property_set_modified_callback(video_range, - properties_video_range_changed); + obs_property_t *video_range = + obs_properties_add_list(props, "video_range", TEXT_VIDEO_RANGE, OBS_COMBO_TYPE_LIST, OBS_COMBO_FORMAT_INT); + obs_property_list_add_int(video_range, TEXT_AUTO, VIDEO_RANGE_AUTO); + ADD_RANGE(RANGE_PARTIAL); + ADD_RANGE(RANGE_FULL); + obs_property_set_enabled(video_range, false); + obs_property_set_modified_callback(video_range, properties_video_range_changed); #undef ADD_RANGE } static obs_properties_t *av_capture_properties(void *data) { - obs_properties_t *props = obs_properties_create(); + obs_properties_t *props = obs_properties_create(); - obs_property_t *dev_list = obs_properties_add_list( - props, "device", TEXT_DEVICE, OBS_COMBO_TYPE_LIST, - OBS_COMBO_FORMAT_STRING); - obs_property_list_add_string(dev_list, "", ""); + obs_property_t *dev_list = + obs_properties_add_list(props, "device", TEXT_DEVICE, OBS_COMBO_TYPE_LIST, OBS_COMBO_FORMAT_STRING); + obs_property_list_add_string(dev_list, "", ""); - NSMutableArray *device_types = [NSMutableArray - arrayWithObjects:AVCaptureDeviceTypeBuiltInWideAngleCamera, - AVCaptureDeviceTypeExternalUnknown, nil]; + NSMutableArray *device_types = [NSMutableArray + arrayWithObjects:AVCaptureDeviceTypeBuiltInWideAngleCamera, AVCaptureDeviceTypeExternalUnknown, nil]; #if __MAC_OS_X_VERSION_MAX_ALLOWED >= 130000 - if (__builtin_available(macOS 13.0, *)) { - [device_types addObject:AVCaptureDeviceTypeDeskViewCamera]; - } + if (__builtin_available(macOS 13.0, *)) { + [device_types addObject:AVCaptureDeviceTypeDeskViewCamera]; + } #endif - AVCaptureDeviceDiscoverySession *video_discovery = [AVCaptureDeviceDiscoverySession - discoverySessionWithDeviceTypes:device_types - mediaType:AVMediaTypeVideo - position:AVCaptureDevicePositionUnspecified]; - for (AVCaptureDevice *dev in [video_discovery devices]) { - obs_property_list_add_string(dev_list, - dev.localizedName.UTF8String, - dev.uniqueID.UTF8String); - } + AVCaptureDeviceDiscoverySession *video_discovery = + [AVCaptureDeviceDiscoverySession discoverySessionWithDeviceTypes:device_types mediaType:AVMediaTypeVideo + position:AVCaptureDevicePositionUnspecified]; + for (AVCaptureDevice *dev in [video_discovery devices]) { + obs_property_list_add_string(dev_list, dev.localizedName.UTF8String, dev.uniqueID.UTF8String); + } - AVCaptureDeviceDiscoverySession *muxed_discovery = [AVCaptureDeviceDiscoverySession - discoverySessionWithDeviceTypes:device_types - mediaType:AVMediaTypeMuxed - position:AVCaptureDevicePositionUnspecified]; - for (AVCaptureDevice *dev in [muxed_discovery devices]) { - obs_property_list_add_string(dev_list, - dev.localizedName.UTF8String, - dev.uniqueID.UTF8String); - } + AVCaptureDeviceDiscoverySession *muxed_discovery = + [AVCaptureDeviceDiscoverySession discoverySessionWithDeviceTypes:device_types mediaType:AVMediaTypeMuxed + position:AVCaptureDevicePositionUnspecified]; + for (AVCaptureDevice *dev in [muxed_discovery devices]) { + obs_property_list_add_string(dev_list, dev.localizedName.UTF8String, dev.uniqueID.UTF8String); + } - obs_property_set_modified_callback(dev_list, properties_device_changed); + obs_property_set_modified_callback(dev_list, properties_device_changed); - obs_property_t *use_preset = - obs_properties_add_bool(props, "use_preset", TEXT_USE_PRESET); - obs_property_set_modified_callback(use_preset, - properties_use_preset_changed); + obs_property_t *use_preset = obs_properties_add_bool(props, "use_preset", TEXT_USE_PRESET); + obs_property_set_modified_callback(use_preset, properties_use_preset_changed); - add_preset_properties(props); + add_preset_properties(props); - add_manual_properties(props); + add_manual_properties(props); - obs_properties_add_bool(props, "buffering", - obs_module_text("Buffering")); + obs_properties_add_bool(props, "buffering", obs_module_text("Buffering")); - if (data) { - struct av_capture *capture = static_cast(data); + if (data) { + struct av_capture *capture = static_cast(data); - add_properties_param(props, capture); + add_properties_param(props, capture); - OBSDataAutoRelease current_settings = - obs_source_get_settings(capture->source); - if (!obs_data_get_bool(current_settings, "enable_audio")) { - auto cb = [](obs_properties_t *, obs_property_t *prop, - void *data) { - struct av_capture *capture = - static_cast(data); - OBSDataAutoRelease settings = obs_data_create(); - obs_data_set_bool(settings, "enable_audio", - true); - obs_source_update(capture->source, settings); + OBSDataAutoRelease current_settings = obs_source_get_settings(capture->source); + if (!obs_data_get_bool(current_settings, "enable_audio")) { + auto cb = [](obs_properties_t *, obs_property_t *prop, void *data) { + struct av_capture *capture = static_cast(data); + OBSDataAutoRelease settings = obs_data_create(); + obs_data_set_bool(settings, "enable_audio", true); + obs_source_update(capture->source, settings); - // Enable all audio tracks - obs_source_set_audio_mixers(capture->source, - 0x3F); - obs_property_set_visible(prop, false); - return true; - }; - obs_properties_add_button2( - props, "enable_audio_button", - obs_module_text("EnableAudio"), cb, capture); - } - } + // Enable all audio tracks + obs_source_set_audio_mixers(capture->source, 0x3F); + obs_property_set_visible(prop, false); + return true; + }; + obs_properties_add_button2(props, "enable_audio_button", obs_module_text("EnableAudio"), cb, capture); + } + } - return props; + return props; } -static void switch_device(av_capture *capture, NSString *uid, - obs_data_t *settings) +static void switch_device(av_capture *capture, NSString *uid, obs_data_t *settings) { - if (!uid) - return; + if (!uid) + return; - if (capture->device) - remove_device(capture); + if (capture->device) + remove_device(capture); - capture->uid = uid; + capture->uid = uid; - if (!uid.length) { - AVLOG(LOG_INFO, "No device selected, stopping capture"); - return; - } + if (!uid.length) { + AVLOG(LOG_INFO, "No device selected, stopping capture"); + return; + } - AVCaptureDevice *dev = [AVCaptureDevice deviceWithUniqueID:uid]; - if (!dev) { - AVLOG(LOG_WARNING, "Device with unique id '%s' not found", - uid.UTF8String); - return; - } + AVCaptureDevice *dev = [AVCaptureDevice deviceWithUniqueID:uid]; + if (!dev) { + AVLOG(LOG_WARNING, "Device with unique id '%s' not found", uid.UTF8String); + return; + } - capture_device(capture, dev, settings); + capture_device(capture, dev, settings); } static void update_preset(av_capture *capture, obs_data_t *settings) { - unlock_device(capture); + unlock_device(capture); - NSString *preset = get_string(settings, "preset"); - if (![capture->device supportsAVCaptureSessionPreset:preset]) { - AVLOG(LOG_WARNING, "Preset %s not available", - preset.UTF8String); - preset = select_preset(capture->device, preset); - } + NSString *preset = get_string(settings, "preset"); + if (![capture->device supportsAVCaptureSessionPreset:preset]) { + AVLOG(LOG_WARNING, "Preset %s not available", preset.UTF8String); + preset = select_preset(capture->device, preset); + } - capture->session.sessionPreset = preset; - AVLOG(LOG_INFO, "Selected preset %s", preset.UTF8String); + capture->session.sessionPreset = preset; + AVLOG(LOG_INFO, "Selected preset %s", preset.UTF8String); - start_capture(capture); + start_capture(capture); } static void update_manual(av_capture *capture, obs_data_t *settings) { - if (init_manual(capture, capture->device, settings)) - start_capture(capture); + if (init_manual(capture, capture->device, settings)) + start_capture(capture); } static void av_capture_update(void *data, obs_data_t *settings) { - auto capture = static_cast(data); + auto capture = static_cast(data); - NSString *uid = get_string(settings, "device"); + NSString *uid = get_string(settings, "device"); - if (!capture->device || ![capture->device.uniqueID isEqualToString:uid]) - return switch_device(capture, uid, settings); + if (!capture->device || ![capture->device.uniqueID isEqualToString:uid]) + return switch_device(capture, uid, settings); - if ((capture->use_preset = obs_data_get_bool(settings, "use_preset"))) { - update_preset(capture, settings); - } else { - update_manual(capture, settings); - } + if ((capture->use_preset = obs_data_get_bool(settings, "use_preset"))) { + update_preset(capture, settings); + } else { + update_manual(capture, settings); + } - av_capture_enable_buffering(capture, - obs_data_get_bool(settings, "buffering")); + av_capture_enable_buffering(capture, obs_data_get_bool(settings, "buffering")); - av_capture_set_audio_active( - capture, - obs_data_get_bool(settings, "enable_audio") && - ([capture->device hasMediaType:AVMediaTypeAudio] || - [capture->device hasMediaType:AVMediaTypeMuxed])); + av_capture_set_audio_active(capture, obs_data_get_bool(settings, "enable_audio") && + ([capture->device hasMediaType:AVMediaTypeAudio] || + [capture->device hasMediaType:AVMediaTypeMuxed])); } OBS_DECLARE_MODULE() OBS_MODULE_USE_DEFAULT_LOCALE("mac-avcapture", "en-US") MODULE_EXPORT const char *obs_module_description(void) { - return "MacOS AVFoundation Capture source"; + return "MacOS AVFoundation Capture source"; } bool obs_module_load(void) { - // Enable iOS device to show up as AVCapture devices - // From WWDC video 2014 #508 at 5:34 - // https://developer.apple.com/videos/wwdc/2014/#508 - CMIOObjectPropertyAddress prop = { - kCMIOHardwarePropertyAllowScreenCaptureDevices, - kCMIOObjectPropertyScopeGlobal, - kCMIOObjectPropertyElementMaster}; - UInt32 allow = 1; - CMIOObjectSetPropertyData(kCMIOObjectSystemObject, &prop, 0, NULL, - sizeof(allow), &allow); + // Enable iOS device to show up as AVCapture devices + // From WWDC video 2014 #508 at 5:34 + // https://developer.apple.com/videos/wwdc/2014/#508 + CMIOObjectPropertyAddress prop = {kCMIOHardwarePropertyAllowScreenCaptureDevices, kCMIOObjectPropertyScopeGlobal, + kCMIOObjectPropertyElementMaster}; + UInt32 allow = 1; + CMIOObjectSetPropertyData(kCMIOObjectSystemObject, &prop, 0, NULL, sizeof(allow), &allow); - obs_source_info av_capture_info = { - .id = "av_capture_input", - .type = OBS_SOURCE_TYPE_INPUT, - .output_flags = OBS_SOURCE_ASYNC_VIDEO | OBS_SOURCE_AUDIO | - OBS_SOURCE_DO_NOT_DUPLICATE | - OBS_SOURCE_CAP_OBSOLETE, - .get_name = av_capture_getname, - .create = av_capture_create, - .destroy = av_capture_destroy, - .get_defaults = av_capture_defaults_v1, - .get_properties = av_capture_properties, - .update = av_capture_update, - .icon_type = OBS_ICON_TYPE_CAMERA, - }; - obs_register_source(&av_capture_info); + obs_source_info av_capture_info = { + .id = "av_capture_input", + .type = OBS_SOURCE_TYPE_INPUT, + .output_flags = OBS_SOURCE_ASYNC_VIDEO | OBS_SOURCE_AUDIO | OBS_SOURCE_DO_NOT_DUPLICATE | + OBS_SOURCE_CAP_OBSOLETE, + .get_name = av_capture_getname, + .create = av_capture_create, + .destroy = av_capture_destroy, + .get_defaults = av_capture_defaults_v1, + .get_properties = av_capture_properties, + .update = av_capture_update, + .icon_type = OBS_ICON_TYPE_CAMERA, + }; + obs_register_source(&av_capture_info); - av_capture_info.version = 2; - av_capture_info.output_flags = OBS_SOURCE_ASYNC_VIDEO | - OBS_SOURCE_AUDIO | - OBS_SOURCE_DO_NOT_DUPLICATE; - av_capture_info.get_defaults = av_capture_defaults_v2; + av_capture_info.version = 2; + av_capture_info.output_flags = OBS_SOURCE_ASYNC_VIDEO | OBS_SOURCE_AUDIO | OBS_SOURCE_DO_NOT_DUPLICATE; + av_capture_info.get_defaults = av_capture_defaults_v2; - obs_register_source(&av_capture_info); - return true; + obs_register_source(&av_capture_info); + return true; } diff --git a/plugins/mac-capture/CGDisplayStream.h b/plugins/mac-capture/CGDisplayStream.h index cb50758e9..e894f68c5 100644 --- a/plugins/mac-capture/CGDisplayStream.h +++ b/plugins/mac-capture/CGDisplayStream.h @@ -35,8 +35,7 @@ typedef struct CF_BRIDGED_TYPE(id) CGDisplayStream *CGDisplayStreamRef; regions were merely copied from one place to another. A routine is provided to merge two update refs together in cases where apps need to coalesce the values because they decided to skip processing for one or more frames. */ -typedef const struct CF_BRIDGED_TYPE(id) - CGDisplayStreamUpdate *CGDisplayStreamUpdateRef; +typedef const struct CF_BRIDGED_TYPE(id) CGDisplayStreamUpdate *CGDisplayStreamUpdateRef; /*! @enum CGDisplayStreamUpdateRectType @@ -47,10 +46,10 @@ typedef const struct CF_BRIDGED_TYPE(id) @const kCGDisplayStreamUpdateReducedDirtyRects A possibly simplified (but overstated) array of dirty rectangles */ typedef CF_ENUM(int32_t, CGDisplayStreamUpdateRectType) { - kCGDisplayStreamUpdateRefreshedRects, - kCGDisplayStreamUpdateMovedRects, - kCGDisplayStreamUpdateDirtyRects, - kCGDisplayStreamUpdateReducedDirtyRects, + kCGDisplayStreamUpdateRefreshedRects, + kCGDisplayStreamUpdateMovedRects, + kCGDisplayStreamUpdateDirtyRects, + kCGDisplayStreamUpdateReducedDirtyRects, }; /*! @@ -62,10 +61,10 @@ typedef CF_ENUM(int32_t, CGDisplayStreamUpdateRectType) { @const kCGDisplayStreamFrameStatusStopped The display stream has stopped and no more calls will be made to the handler until the stream is started. */ typedef CF_ENUM(int32_t, CGDisplayStreamFrameStatus) { - kCGDisplayStreamFrameStatusFrameComplete, - kCGDisplayStreamFrameStatusFrameIdle, - kCGDisplayStreamFrameStatusFrameBlank, - kCGDisplayStreamFrameStatusStopped, + kCGDisplayStreamFrameStatusFrameComplete, + kCGDisplayStreamFrameStatusFrameIdle, + kCGDisplayStreamFrameStatusFrameBlank, + kCGDisplayStreamFrameStatusStopped, }; /* @@ -84,20 +83,18 @@ typedef CF_ENUM(int32_t, CGDisplayStreamFrameStatus) { of the handler, you must CFRetain() it, as it will be CFRelease()'d by the CGDisplayStream after the handler returns. The updateRef will be NULL in cases when status is not kCGDisplayStreamFrameStatusFrameComplete. */ -typedef void (^CGDisplayStreamFrameAvailableHandler)( - CGDisplayStreamFrameStatus status, uint64_t displayTime, - IOSurfaceRef __nullable frameSurface, - CGDisplayStreamUpdateRef __nullable updateRef); +typedef void (^CGDisplayStreamFrameAvailableHandler)(CGDisplayStreamFrameStatus status, uint64_t displayTime, + IOSurfaceRef __nullable frameSurface, + CGDisplayStreamUpdateRef __nullable updateRef); /*! @function CGDisplayStreamUpdateGetTypeID @abstract Returns the CF "class" ID for CGDisplayStreamUpdate @result The CFTypeID of the CGDisplayStreamUpdate class. */ -CG_EXTERN CFTypeID -CGDisplayStreamUpdateGetTypeID(void) CG_AVAILABLE_BUT_DEPRECATED( - 11.0, 14.0, - "There is no direct replacement for this function. Please use ScreenCaptureKit API's SCStreamOutputType instead"); +CG_EXTERN CFTypeID CGDisplayStreamUpdateGetTypeID(void) CG_AVAILABLE_BUT_DEPRECATED( + 11.0, 14.0, + "There is no direct replacement for this function. Please use ScreenCaptureKit API's SCStreamOutputType instead"); /*! @function CGDisplayStreamUpdateGetRects @@ -107,12 +104,11 @@ CGDisplayStreamUpdateGetTypeID(void) CG_AVAILABLE_BUT_DEPRECATED( @param rectCount A pointer to where the count of the number of rectangles in the array is to be returned. Must not be NULL. @result A pointer to the array of CGRectangles. This array should not be freed by the caller. */ -CG_EXTERN const CGRect *__nullable CGDisplayStreamUpdateGetRects( - CGDisplayStreamUpdateRef __nullable updateRef, - CGDisplayStreamUpdateRectType rectType, size_t *rectCount) - CG_AVAILABLE_BUT_DEPRECATED( - 11.0, 14.0, - "Please use ScreenCaptureKit API's SCStreamFrameInfo with SCStreamFrameInfoContentRect instead"); +CG_EXTERN const CGRect *__nullable CGDisplayStreamUpdateGetRects(CGDisplayStreamUpdateRef __nullable updateRef, + CGDisplayStreamUpdateRectType rectType, + size_t *rectCount) + CG_AVAILABLE_BUT_DEPRECATED( + 11.0, 14.0, "Please use ScreenCaptureKit API's SCStreamFrameInfo with SCStreamFrameInfoContentRect instead"); /*! @function CGDisplayStreamUpdateCreateMerged @@ -126,13 +122,11 @@ CG_EXTERN const CGRect *__nullable CGDisplayStreamUpdateGetRects( @param secondUpdate The second update (in a temporal sense) @result The new CGDisplayStreamUpdateRef */ -CG_EXTERN CGDisplayStreamUpdateRef __nullable -CGDisplayStreamUpdateCreateMergedUpdate( - CGDisplayStreamUpdateRef __nullable firstUpdate, - CGDisplayStreamUpdateRef __nullable secondUpdate) - CG_AVAILABLE_BUT_DEPRECATED( - 11.0, 14.0, - "There is no direct replacement for this function. Please use ScreenCaptureKit API's SCStreamFrameInfo to replace CGDisplayStreamUpdate"); +CG_EXTERN CGDisplayStreamUpdateRef __nullable CGDisplayStreamUpdateCreateMergedUpdate( + CGDisplayStreamUpdateRef __nullable firstUpdate, CGDisplayStreamUpdateRef __nullable secondUpdate) + CG_AVAILABLE_BUT_DEPRECATED( + 11.0, 14.0, + "There is no direct replacement for this function. Please use ScreenCaptureKit API's SCStreamFrameInfo to replace CGDisplayStreamUpdate"); /*! @function CGDisplayStreamUpdateGetMovedRectsDelta @@ -142,11 +136,10 @@ CGDisplayStreamUpdateCreateMergedUpdate( @param dy A pointer to a CGFloat to store the y component of the movement delta @discussion The delta values describe the offset from the moved rectangles back to the source location. */ -CG_EXTERN void CGDisplayStreamUpdateGetMovedRectsDelta( - CGDisplayStreamUpdateRef __nullable updateRef, CGFloat *dx, CGFloat *dy) - CG_AVAILABLE_BUT_DEPRECATED( - 11.0, 14.0, - "Please use ScreenCaptureKit API's SCStreamFrameInfo with SCStreamFrameInfoContentRect instead"); +CG_EXTERN void CGDisplayStreamUpdateGetMovedRectsDelta(CGDisplayStreamUpdateRef __nullable updateRef, CGFloat *dx, + CGFloat *dy) + CG_AVAILABLE_BUT_DEPRECATED( + 11.0, 14.0, "Please use ScreenCaptureKit API's SCStreamFrameInfo with SCStreamFrameInfoContentRect instead"); /*! @function CGDisplayStreamGetDropCount @@ -156,11 +149,9 @@ CG_EXTERN void CGDisplayStreamUpdateGetMovedRectsDelta( @discussion This call is primarily useful for performance measurement to determine if the client is keeping up with all WindowServer updates. */ -CG_EXTERN size_t -CGDisplayStreamUpdateGetDropCount(CGDisplayStreamUpdateRef __nullable updateRef) - CG_AVAILABLE_BUT_DEPRECATED( - 11.0, 14.0, - "There is no direct replacement for this function. Please use ScreenCaptureKit API's SCStreamFrameInfo to replace CGDisplayStreamUpdate"); +CG_EXTERN size_t CGDisplayStreamUpdateGetDropCount(CGDisplayStreamUpdateRef __nullable updateRef) CG_AVAILABLE_BUT_DEPRECATED( + 11.0, 14.0, + "There is no direct replacement for this function. Please use ScreenCaptureKit API's SCStreamFrameInfo to replace CGDisplayStreamUpdate"); /* Optional CGDisplayStream Properties */ @@ -172,8 +163,8 @@ CGDisplayStreamUpdateGetDropCount(CGDisplayStreamUpdateRef __nullable updateRef) HiDPI displays. */ CG_EXTERN const CFStringRef kCGDisplayStreamSourceRect CG_AVAILABLE_BUT_DEPRECATED( - 11.0, 14.0, - "Please use ScreenCaptureKit API's SCStreamConfiguration sourceRect property instead"); /* Source rectangle to capture - defaults to entire display */ + 11.0, 14.0, + "Please use ScreenCaptureKit API's SCStreamConfiguration sourceRect property instead"); /* Source rectangle to capture - defaults to entire display */ /*! @const kCGDisplayStreamDestinationRect @@ -183,8 +174,8 @@ CG_EXTERN const CFStringRef kCGDisplayStreamSourceRect CG_AVAILABLE_BUT_DEPRECAT specified in terms of pixels. */ CG_EXTERN const CFStringRef kCGDisplayStreamDestinationRect CG_AVAILABLE_BUT_DEPRECATED( - 11.0, 14.0, - "Please use ScreenCaptureKit API's SCStreamConfiguration destinationRect property instead"); /* Destination rectangle - defaults to entire buffer */ + 11.0, 14.0, + "Please use ScreenCaptureKit API's SCStreamConfiguration destinationRect property instead"); /* Destination rectangle - defaults to entire buffer */ /*! @const kCGDisplayStreamPreserveAspectRatio @@ -194,40 +185,40 @@ CG_EXTERN const CFStringRef kCGDisplayStreamDestinationRect CG_AVAILABLE_BUT_DEP in order to preserve the source aspect ratio. */ CG_EXTERN const CFStringRef kCGDisplayStreamPreserveAspectRatio CG_AVAILABLE_BUT_DEPRECATED( - 11.0, 14.0, - "Please use ScreenCaptureKit API's SCStreamConfiguration preserveAspectRatio property instead"); /* CFBoolean - defaults to true */ + 11.0, 14.0, + "Please use ScreenCaptureKit API's SCStreamConfiguration preserveAspectRatio property instead"); /* CFBoolean - defaults to true */ /*! @const kCGDisplayStreamColorSpace @discussion Set the desired CGColorSpace of the output frames. By default the color space will be that of the display. */ CG_EXTERN const CFStringRef kCGDisplayStreamColorSpace CG_AVAILABLE_BUT_DEPRECATED( - 11.0, 14.0, - "Please use ScreenCaptureKit API's SCStreamConfiguration colorSpaceName property instead"); /* Desired output color space (CGColorSpaceRef) - defaults to display color space */ + 11.0, 14.0, + "Please use ScreenCaptureKit API's SCStreamConfiguration colorSpaceName property instead"); /* Desired output color space (CGColorSpaceRef) - defaults to display color space */ /*! @const kCGDisplayStreamMinimumFrameTime @discussion Request that the delta between frame updates be at least as much specified by this value. */ CG_EXTERN const CFStringRef kCGDisplayStreamMinimumFrameTime CG_AVAILABLE_BUT_DEPRECATED( - 11.0, 14.0, - "Please use ScreenCaptureKit API's SCStreamConfiguration minimumFrameInterval property instead"); /* CFNumber in seconds, defaults to zero. */ + 11.0, 14.0, + "Please use ScreenCaptureKit API's SCStreamConfiguration minimumFrameInterval property instead"); /* CFNumber in seconds, defaults to zero. */ /*! @const kCGDisplayStreamShowCursor @discussion Controls whether the cursor is embedded within the provided buffers or not. */ CG_EXTERN const CFStringRef kCGDisplayStreamShowCursor CG_AVAILABLE_BUT_DEPRECATED( - 11.0, 14.0, - "Please use ScreenCaptureKit API's SCStreamConfiguration showsCursor property instead"); /* CFBoolean - defaults to false */ + 11.0, 14.0, + "Please use ScreenCaptureKit API's SCStreamConfiguration showsCursor property instead"); /* CFBoolean - defaults to false */ /*! @const kCGDisplayStreamQueueDepth @discussion Controls how many frames deep the frame queue will be. Defaults to N. */ CG_EXTERN const CFStringRef kCGDisplayStreamQueueDepth CG_AVAILABLE_BUT_DEPRECATED( - 11.0, 14.0, - "Please use ScreenCaptureKit API's SCStreamConfiguration queueDepth property instead"); /* Queue depth in frames. Defaults to 3. */ + 11.0, 14.0, + "Please use ScreenCaptureKit API's SCStreamConfiguration queueDepth property instead"); /* Queue depth in frames. Defaults to 3. */ /*! @const kCGDisplayStreamYCbCrMatrix @@ -235,8 +226,7 @@ CG_EXTERN const CFStringRef kCGDisplayStreamQueueDepth CG_AVAILABLE_BUT_DEPRECAT The value should be one of the three kCGDisplayStreamYCbCrMatrix values specified below. */ CG_EXTERN const CFStringRef kCGDisplayStreamYCbCrMatrix CG_AVAILABLE_BUT_DEPRECATED( - 11.0, 14.0, - "Please use ScreenCaptureKit API's SCStreamConfiguration colorMatrix property"); + 11.0, 14.0, "Please use ScreenCaptureKit API's SCStreamConfiguration colorMatrix property"); /* Supported YCbCr matrices. Note that these strings have identical values to the equivalent CoreVideo strings. */ CG_EXTERN const CFStringRef kCGDisplayStreamYCbCrMatrix_ITU_R_709_2; @@ -249,8 +239,8 @@ CG_EXTERN const CFStringRef kCGDisplayStreamYCbCrMatrix_SMPTE_240M_1995; @result The CFTypeID of the CGDisplayStream class. */ CG_EXTERN CFTypeID CGDisplayStreamGetTypeID(void) CG_AVAILABLE_BUT_DEPRECATED( - 11.0, 14.0, - "There is no direct replacement for this function. Please use ScreenCaptureKit API's SCStream to replace CGDisplayStream"); + 11.0, 14.0, + "There is no direct replacement for this function. Please use ScreenCaptureKit API's SCStream to replace CGDisplayStream"); /*! @function CGDisplayStreamCreate @@ -272,13 +262,12 @@ CG_EXTERN CFTypeID CGDisplayStreamGetTypeID(void) CG_AVAILABLE_BUT_DEPRECATED( @param handler A block that will be called for frame deliver. @result The new CGDisplayStream object. */ -CG_EXTERN CGDisplayStreamRef __nullable CGDisplayStreamCreate( - CGDirectDisplayID display, size_t outputWidth, size_t outputHeight, - int32_t pixelFormat, CFDictionaryRef __nullable properties, - CGDisplayStreamFrameAvailableHandler __nullable handler) - CG_AVAILABLE_BUT_DEPRECATED( - 11.0, 14.0, - "Please use ScreenCaptureKit API's initWithFilter:configuration:delegate: instead"); +CG_EXTERN CGDisplayStreamRef __nullable CGDisplayStreamCreate(CGDirectDisplayID display, size_t outputWidth, + size_t outputHeight, int32_t pixelFormat, + CFDictionaryRef __nullable properties, + CGDisplayStreamFrameAvailableHandler __nullable handler) + CG_AVAILABLE_BUT_DEPRECATED(11.0, 14.0, + "Please use ScreenCaptureKit API's initWithFilter:configuration:delegate: instead"); /*! @function CGDisplayStreamCreateWithDispatchQueue @@ -295,13 +284,11 @@ CG_EXTERN CGDisplayStreamRef __nullable CGDisplayStreamCreate( @result The new CGDisplayStream object. */ CG_EXTERN CGDisplayStreamRef __nullable CGDisplayStreamCreateWithDispatchQueue( - CGDirectDisplayID display, size_t outputWidth, size_t outputHeight, - int32_t pixelFormat, CFDictionaryRef __nullable properties, - dispatch_queue_t queue, - CGDisplayStreamFrameAvailableHandler __nullable handler) - CG_AVAILABLE_BUT_DEPRECATED( - 11.0, 14.0, - "Please use ScreenCaptureKit API's initWithFilter:configuration:delegate: instead"); + CGDirectDisplayID display, size_t outputWidth, size_t outputHeight, int32_t pixelFormat, + CFDictionaryRef __nullable properties, dispatch_queue_t queue, + CGDisplayStreamFrameAvailableHandler __nullable handler) + CG_AVAILABLE_BUT_DEPRECATED(11.0, 14.0, + "Please use ScreenCaptureKit API's initWithFilter:configuration:delegate: instead"); /*! @function CGDisplayStreamStart @@ -309,11 +296,8 @@ CG_EXTERN CGDisplayStreamRef __nullable CGDisplayStreamCreateWithDispatchQueue( @param displayStream to be started @result kCGErrorSuccess If the display stream was started, otherwise an error. */ -CG_EXTERN CGError -CGDisplayStreamStart(CGDisplayStreamRef cg_nullable displayStream) - CG_AVAILABLE_BUT_DEPRECATED( - 11.0, 14.0, - "Please use ScreenCaptureKit API's startCaptureWithCompletionHandler: to start a stream instead"); +CG_EXTERN CGError CGDisplayStreamStart(CGDisplayStreamRef cg_nullable displayStream) CG_AVAILABLE_BUT_DEPRECATED( + 11.0, 14.0, "Please use ScreenCaptureKit API's startCaptureWithCompletionHandler: to start a stream instead"); /*! @function CGDisplayStreamStop @@ -324,11 +308,8 @@ CGDisplayStreamStart(CGDisplayStreamRef cg_nullable displayStream) status of kCGDisplayStreamFrameStatusStopped. After that point it is safe to release the CGDisplayStream. It is safe to call this function from within the handler block, but the previous caveat still applies. */ -CG_EXTERN CGError -CGDisplayStreamStop(CGDisplayStreamRef cg_nullable displayStream) - CG_AVAILABLE_BUT_DEPRECATED( - 11.0, 14.0, - "Please use ScreenCaptureKit API's stopCaptureWithCompletionHandler: to stop a stream instead"); +CG_EXTERN CGError CGDisplayStreamStop(CGDisplayStreamRef cg_nullable displayStream) CG_AVAILABLE_BUT_DEPRECATED( + 11.0, 14.0, "Please use ScreenCaptureKit API's stopCaptureWithCompletionHandler: to stop a stream instead"); /*! @function CGDisplayStreamGetRunLoopSource @@ -337,11 +318,10 @@ CGDisplayStreamStop(CGDisplayStreamRef cg_nullable displayStream) @result The CFRunLoopSource for this displayStream. Note: This function will return NULL if the display stream was created via CGDisplayStreamCreateWithDispatchQueue(). */ -CG_EXTERN CFRunLoopSourceRef __nullable -CGDisplayStreamGetRunLoopSource(CGDisplayStreamRef cg_nullable displayStream) - CG_AVAILABLE_BUT_DEPRECATED( - 11.0, 14.0, - "There is no direct replacement for this function. Please use ScreenCaptureKit API's SCStream to replace CGDisplayStream"); +CG_EXTERN CFRunLoopSourceRef __nullable CGDisplayStreamGetRunLoopSource(CGDisplayStreamRef cg_nullable displayStream) + CG_AVAILABLE_BUT_DEPRECATED( + 11.0, 14.0, + "There is no direct replacement for this function. Please use ScreenCaptureKit API's SCStream to replace CGDisplayStream"); #endif /* __BLOCKS__ */ diff --git a/plugins/mac-capture/mac-display-capture.m b/plugins/mac-capture/mac-display-capture.m index 992a7cef3..0e8ea5dc3 100644 --- a/plugins/mac-capture/mac-display-capture.m +++ b/plugins/mac-capture/mac-display-capture.m @@ -16,759 +16,695 @@ #include "window-utils.h" enum crop_mode { - CROP_NONE, - CROP_MANUAL, - CROP_TO_WINDOW, - CROP_TO_WINDOW_AND_MANUAL, - CROP_INVALID + CROP_NONE, + CROP_MANUAL, + CROP_TO_WINDOW, + CROP_TO_WINDOW_AND_MANUAL, + CROP_INVALID }; static inline bool requires_window(enum crop_mode mode) { - return mode == CROP_TO_WINDOW || mode == CROP_TO_WINDOW_AND_MANUAL; + return mode == CROP_TO_WINDOW || mode == CROP_TO_WINDOW_AND_MANUAL; } struct display_capture { - obs_source_t *source; + obs_source_t *source; - gs_samplerstate_t *sampler; - gs_effect_t *effect; - gs_texture_t *tex; - gs_vertbuffer_t *vertbuf; + gs_samplerstate_t *sampler; + gs_effect_t *effect; + gs_texture_t *tex; + gs_vertbuffer_t *vertbuf; - NSScreen *screen; - unsigned display; - NSRect frame; - bool hide_cursor; + NSScreen *screen; + unsigned display; + NSRect frame; + bool hide_cursor; - enum crop_mode crop; - CGRect crop_rect; + enum crop_mode crop; + CGRect crop_rect; - struct cocoa_window window; - CGRect window_rect; - bool on_screen; - bool hide_when_minimized; + struct cocoa_window window; + CGRect window_rect; + bool on_screen; + bool hide_when_minimized; - os_event_t *disp_finished; - CGDisplayStreamRef disp; - IOSurfaceRef current, prev; + os_event_t *disp_finished; + CGDisplayStreamRef disp; + IOSurfaceRef current, prev; - pthread_mutex_t mutex; + pthread_mutex_t mutex; }; static inline bool crop_mode_valid(enum crop_mode mode) { - return CROP_NONE <= mode && mode < CROP_INVALID; + return CROP_NONE <= mode && mode < CROP_INVALID; } static void destroy_display_stream(struct display_capture *dc) { - if (dc->disp) { - CGDisplayStreamStop(dc->disp); - os_event_wait(dc->disp_finished); - } + if (dc->disp) { + CGDisplayStreamStop(dc->disp); + os_event_wait(dc->disp_finished); + } - if (dc->tex) { - gs_texture_destroy(dc->tex); - dc->tex = NULL; - } + if (dc->tex) { + gs_texture_destroy(dc->tex); + dc->tex = NULL; + } - if (dc->current) { - IOSurfaceDecrementUseCount(dc->current); - CFRelease(dc->current); - dc->current = NULL; - } + if (dc->current) { + IOSurfaceDecrementUseCount(dc->current); + CFRelease(dc->current); + dc->current = NULL; + } - if (dc->prev) { - IOSurfaceDecrementUseCount(dc->prev); - CFRelease(dc->prev); - dc->prev = NULL; - } + if (dc->prev) { + IOSurfaceDecrementUseCount(dc->prev); + CFRelease(dc->prev); + dc->prev = NULL; + } - if (dc->disp) { - CFRelease(dc->disp); - dc->disp = NULL; - } + if (dc->disp) { + CFRelease(dc->disp); + dc->disp = NULL; + } - if (dc->screen) { - [dc->screen release]; - dc->screen = nil; - } + if (dc->screen) { + [dc->screen release]; + dc->screen = nil; + } - os_event_destroy(dc->disp_finished); + os_event_destroy(dc->disp_finished); } static void display_capture_destroy(void *data) { - struct display_capture *dc = data; + struct display_capture *dc = data; - if (!dc) - return; + if (!dc) + return; - obs_enter_graphics(); + obs_enter_graphics(); - destroy_display_stream(dc); + destroy_display_stream(dc); - if (dc->sampler) - gs_samplerstate_destroy(dc->sampler); - if (dc->vertbuf) - gs_vertexbuffer_destroy(dc->vertbuf); + if (dc->sampler) + gs_samplerstate_destroy(dc->sampler); + if (dc->vertbuf) + gs_vertexbuffer_destroy(dc->vertbuf); - obs_leave_graphics(); + obs_leave_graphics(); - destroy_window(&dc->window); + destroy_window(&dc->window); - pthread_mutex_destroy(&dc->mutex); - bfree(dc); + pthread_mutex_destroy(&dc->mutex); + bfree(dc); } static inline void update_window_params(struct display_capture *dc) { - if (!requires_window(dc->crop)) - return; + if (!requires_window(dc->crop)) + return; - NSArray *arr = (NSArray *)CGWindowListCopyWindowInfo( - kCGWindowListOptionIncludingWindow, dc->window.window_id); + NSArray *arr = (NSArray *) CGWindowListCopyWindowInfo(kCGWindowListOptionIncludingWindow, dc->window.window_id); - if (arr.count) { - NSDictionary *dict = arr[0]; - NSDictionary *ref = dict[(NSString *)kCGWindowBounds]; - CGRectMakeWithDictionaryRepresentation((CFDictionaryRef)ref, - &dc->window_rect); - dc->on_screen = dict[(NSString *)kCGWindowIsOnscreen] != nil; - dc->window_rect = - [dc->screen convertRectToBacking:dc->window_rect]; + if (arr.count) { + NSDictionary *dict = arr[0]; + NSDictionary *ref = dict[(NSString *) kCGWindowBounds]; + CGRectMakeWithDictionaryRepresentation((CFDictionaryRef) ref, &dc->window_rect); + dc->on_screen = dict[(NSString *) kCGWindowIsOnscreen] != nil; + dc->window_rect = [dc->screen convertRectToBacking:dc->window_rect]; - } else { - if (find_window(&dc->window, NULL, false)) - update_window_params(dc); - else - dc->on_screen = false; - } + } else { + if (find_window(&dc->window, NULL, false)) + update_window_params(dc); + else + dc->on_screen = false; + } - [arr release]; + [arr release]; } -static inline void display_stream_update(struct display_capture *dc, - CGDisplayStreamFrameStatus status, - uint64_t display_time, - IOSurfaceRef frame_surface, - CGDisplayStreamUpdateRef update_ref) +static inline void display_stream_update(struct display_capture *dc, CGDisplayStreamFrameStatus status, + uint64_t display_time, IOSurfaceRef frame_surface, + CGDisplayStreamUpdateRef update_ref) { - UNUSED_PARAMETER(display_time); + UNUSED_PARAMETER(display_time); - if (status == kCGDisplayStreamFrameStatusStopped) { - os_event_signal(dc->disp_finished); - return; - } + if (status == kCGDisplayStreamFrameStatusStopped) { + os_event_signal(dc->disp_finished); + return; + } - IOSurfaceRef prev_current = NULL; + IOSurfaceRef prev_current = NULL; - if (frame_surface && !pthread_mutex_lock(&dc->mutex)) { - prev_current = dc->current; - dc->current = frame_surface; - CFRetain(dc->current); - IOSurfaceIncrementUseCount(dc->current); + if (frame_surface && !pthread_mutex_lock(&dc->mutex)) { + prev_current = dc->current; + dc->current = frame_surface; + CFRetain(dc->current); + IOSurfaceIncrementUseCount(dc->current); - update_window_params(dc); + update_window_params(dc); - pthread_mutex_unlock(&dc->mutex); - } + pthread_mutex_unlock(&dc->mutex); + } - if (prev_current) { - IOSurfaceDecrementUseCount(prev_current); - CFRelease(prev_current); - } + if (prev_current) { + IOSurfaceDecrementUseCount(prev_current); + CFRelease(prev_current); + } - size_t dropped_frames = CGDisplayStreamUpdateGetDropCount(update_ref); - if (dropped_frames > 0) - blog(LOG_INFO, "%s: Dropped %zu frames", - obs_source_get_name(dc->source), dropped_frames); + size_t dropped_frames = CGDisplayStreamUpdateGetDropCount(update_ref); + if (dropped_frames > 0) + blog(LOG_INFO, "%s: Dropped %zu frames", obs_source_get_name(dc->source), dropped_frames); } static bool init_display_stream(struct display_capture *dc) { - [[NSScreen screens] - enumerateObjectsUsingBlock:^(NSScreen *_Nonnull screen, - NSUInteger index __unused, - BOOL *_Nonnull stop __unused) { - NSNumber *screenNumber = - screen.deviceDescription[@"NSScreenNumber"]; - CGDirectDisplayID display_id = - (CGDirectDisplayID)screenNumber.intValue; + [[NSScreen screens] enumerateObjectsUsingBlock:^(NSScreen *_Nonnull screen, NSUInteger index __unused, + BOOL *_Nonnull stop __unused) { + NSNumber *screenNumber = screen.deviceDescription[@"NSScreenNumber"]; + CGDirectDisplayID display_id = (CGDirectDisplayID) screenNumber.intValue; - if (display_id == dc->display) { - dc->screen = [screen retain]; - *stop = YES; - } - }]; + if (display_id == dc->display) { + dc->screen = [screen retain]; + *stop = YES; + } + }]; - if (!dc->screen) { - return false; - } + if (!dc->screen) { + return false; + } - dc->frame = [dc->screen convertRectToBacking:dc->screen.frame]; + dc->frame = [dc->screen convertRectToBacking:dc->screen.frame]; - NSNumber *screen_num = dc->screen.deviceDescription[@"NSScreenNumber"]; - CGDirectDisplayID disp_id = screen_num.unsignedIntValue; + NSNumber *screen_num = dc->screen.deviceDescription[@"NSScreenNumber"]; + CGDirectDisplayID disp_id = screen_num.unsignedIntValue; - NSDictionary *rect_dict = - CFBridgingRelease(CGRectCreateDictionaryRepresentation( - CGRectMake(0, 0, dc->screen.frame.size.width, - dc->screen.frame.size.height))); + NSDictionary *rect_dict = CFBridgingRelease(CGRectCreateDictionaryRepresentation( + CGRectMake(0, 0, dc->screen.frame.size.width, dc->screen.frame.size.height))); - CFBooleanRef show_cursor_cf = dc->hide_cursor ? kCFBooleanFalse - : kCFBooleanTrue; + CFBooleanRef show_cursor_cf = dc->hide_cursor ? kCFBooleanFalse : kCFBooleanTrue; - NSDictionary *dict = @{ - (__bridge NSString *)kCGDisplayStreamSourceRect: rect_dict, - (__bridge NSString *)kCGDisplayStreamQueueDepth: @5, - (__bridge NSString *) - kCGDisplayStreamShowCursor: (id)show_cursor_cf, - }; + NSDictionary *dict = @{ + (__bridge NSString *) kCGDisplayStreamSourceRect: rect_dict, + (__bridge NSString *) kCGDisplayStreamQueueDepth: @5, + (__bridge NSString *) kCGDisplayStreamShowCursor: (id) show_cursor_cf, + }; - os_event_init(&dc->disp_finished, OS_EVENT_TYPE_MANUAL); + os_event_init(&dc->disp_finished, OS_EVENT_TYPE_MANUAL); - FourCharCode bgra_code = 0; - bgra_code = ('B' << 24) | ('G' << 16) | ('R' << 8) | 'A'; + FourCharCode bgra_code = 0; + bgra_code = ('B' << 24) | ('G' << 16) | ('R' << 8) | 'A'; - const CGSize *size = &dc->frame.size; - dc->disp = CGDisplayStreamCreateWithDispatchQueue( - disp_id, (size_t)size->width, (size_t)size->height, bgra_code, - (__bridge CFDictionaryRef)dict, - dispatch_queue_create(NULL, NULL), - ^(CGDisplayStreamFrameStatus status, uint64_t displayTime, - IOSurfaceRef frameSurface, - CGDisplayStreamUpdateRef updateRef) { - display_stream_update(dc, status, displayTime, - frameSurface, updateRef); - }); + const CGSize *size = &dc->frame.size; + dc->disp = CGDisplayStreamCreateWithDispatchQueue( + disp_id, (size_t) size->width, (size_t) size->height, bgra_code, (__bridge CFDictionaryRef) dict, + dispatch_queue_create(NULL, NULL), + ^(CGDisplayStreamFrameStatus status, uint64_t displayTime, IOSurfaceRef frameSurface, + CGDisplayStreamUpdateRef updateRef) { + display_stream_update(dc, status, displayTime, frameSurface, updateRef); + }); - return !CGDisplayStreamStart(dc->disp); + return !CGDisplayStreamStart(dc->disp); } bool init_vertbuf(struct display_capture *dc) { - struct gs_vb_data *vb_data = gs_vbdata_create(); - vb_data->num = 4; - vb_data->points = bzalloc(sizeof(struct vec3) * 4); - if (!vb_data->points) - return false; + struct gs_vb_data *vb_data = gs_vbdata_create(); + vb_data->num = 4; + vb_data->points = bzalloc(sizeof(struct vec3) * 4); + if (!vb_data->points) + return false; - vb_data->num_tex = 1; - vb_data->tvarray = bzalloc(sizeof(struct gs_tvertarray)); - if (!vb_data->tvarray) - return false; + vb_data->num_tex = 1; + vb_data->tvarray = bzalloc(sizeof(struct gs_tvertarray)); + if (!vb_data->tvarray) + return false; - vb_data->tvarray[0].width = 2; - vb_data->tvarray[0].array = bzalloc(sizeof(struct vec2) * 4); - if (!vb_data->tvarray[0].array) - return false; + vb_data->tvarray[0].width = 2; + vb_data->tvarray[0].array = bzalloc(sizeof(struct vec2) * 4); + if (!vb_data->tvarray[0].array) + return false; - dc->vertbuf = gs_vertexbuffer_create(vb_data, GS_DYNAMIC); - return dc->vertbuf != NULL; + dc->vertbuf = gs_vertexbuffer_create(vb_data, GS_DYNAMIC); + return dc->vertbuf != NULL; } void load_crop(struct display_capture *dc, obs_data_t *settings); static void *display_capture_create(obs_data_t *settings, obs_source_t *source) { - struct display_capture *dc = bzalloc(sizeof(struct display_capture)); + struct display_capture *dc = bzalloc(sizeof(struct display_capture)); - dc->source = source; - dc->hide_cursor = !obs_data_get_bool(settings, "show_cursor"); + dc->source = source; + dc->hide_cursor = !obs_data_get_bool(settings, "show_cursor"); - dc->effect = obs_get_base_effect(OBS_EFFECT_DEFAULT_RECT); - if (!dc->effect) - goto fail; + dc->effect = obs_get_base_effect(OBS_EFFECT_DEFAULT_RECT); + if (!dc->effect) + goto fail; - obs_enter_graphics(); + obs_enter_graphics(); - struct gs_sampler_info info = { - .filter = GS_FILTER_LINEAR, - .address_u = GS_ADDRESS_CLAMP, - .address_v = GS_ADDRESS_CLAMP, - .address_w = GS_ADDRESS_CLAMP, - .max_anisotropy = 1, - }; - dc->sampler = gs_samplerstate_create(&info); - if (!dc->sampler) - goto fail; + struct gs_sampler_info info = { + .filter = GS_FILTER_LINEAR, + .address_u = GS_ADDRESS_CLAMP, + .address_v = GS_ADDRESS_CLAMP, + .address_w = GS_ADDRESS_CLAMP, + .max_anisotropy = 1, + }; + dc->sampler = gs_samplerstate_create(&info); + if (!dc->sampler) + goto fail; - if (!init_vertbuf(dc)) - goto fail; + if (!init_vertbuf(dc)) + goto fail; - obs_leave_graphics(); + obs_leave_graphics(); - init_window(&dc->window, settings); - load_crop(dc, settings); + init_window(&dc->window, settings); + load_crop(dc, settings); - bool legacy_display_id = obs_data_has_user_value(settings, "display"); - if (legacy_display_id) { - CGDirectDisplayID display_id = - (CGDirectDisplayID)obs_data_get_int(settings, - "display"); - CFUUIDRef display_uuid = - CGDisplayCreateUUIDFromDisplayID(display_id); - CFStringRef uuid_string = - CFUUIDCreateString(kCFAllocatorDefault, display_uuid); - obs_data_set_string( - settings, "display_uuid", - CFStringGetCStringPtr(uuid_string, - kCFStringEncodingUTF8)); - obs_data_erase(settings, "display"); - CFRelease(uuid_string); - CFRelease(display_uuid); - } + bool legacy_display_id = obs_data_has_user_value(settings, "display"); + if (legacy_display_id) { + CGDirectDisplayID display_id = (CGDirectDisplayID) obs_data_get_int(settings, "display"); + CFUUIDRef display_uuid = CGDisplayCreateUUIDFromDisplayID(display_id); + CFStringRef uuid_string = CFUUIDCreateString(kCFAllocatorDefault, display_uuid); + obs_data_set_string(settings, "display_uuid", CFStringGetCStringPtr(uuid_string, kCFStringEncodingUTF8)); + obs_data_erase(settings, "display"); + CFRelease(uuid_string); + CFRelease(display_uuid); + } - const char *display_uuid = - obs_data_get_string(settings, "display_uuid"); - if (display_uuid) { - CFStringRef uuid_string = CFStringCreateWithCString( - kCFAllocatorDefault, display_uuid, - kCFStringEncodingUTF8); - CFUUIDRef uuid_ref = CFUUIDCreateFromString(kCFAllocatorDefault, - uuid_string); - dc->display = CGDisplayGetDisplayIDFromUUID(uuid_ref); - CFRelease(uuid_string); - CFRelease(uuid_ref); - } else { - dc->display = CGMainDisplayID(); - } + const char *display_uuid = obs_data_get_string(settings, "display_uuid"); + if (display_uuid) { + CFStringRef uuid_string = CFStringCreateWithCString(kCFAllocatorDefault, display_uuid, kCFStringEncodingUTF8); + CFUUIDRef uuid_ref = CFUUIDCreateFromString(kCFAllocatorDefault, uuid_string); + dc->display = CGDisplayGetDisplayIDFromUUID(uuid_ref); + CFRelease(uuid_string); + CFRelease(uuid_ref); + } else { + dc->display = CGMainDisplayID(); + } - pthread_mutex_init(&dc->mutex, NULL); + pthread_mutex_init(&dc->mutex, NULL); - if (!init_display_stream(dc)) - goto fail; + if (!init_display_stream(dc)) + goto fail; - return dc; + return dc; fail: - obs_leave_graphics(); - display_capture_destroy(dc); - return NULL; + obs_leave_graphics(); + display_capture_destroy(dc); + return NULL; } -static void build_sprite(struct gs_vb_data *data, float fcx, float fcy, - float start_u, float end_u, float start_v, float end_v) +static void build_sprite(struct gs_vb_data *data, float fcx, float fcy, float start_u, float end_u, float start_v, + float end_v) { - struct vec2 *tvarray = data->tvarray[0].array; + struct vec2 *tvarray = data->tvarray[0].array; - vec3_set(data->points + 1, fcx, 0.0f, 0.0f); - vec3_set(data->points + 2, 0.0f, fcy, 0.0f); - vec3_set(data->points + 3, fcx, fcy, 0.0f); - vec2_set(tvarray, start_u, start_v); - vec2_set(tvarray + 1, end_u, start_v); - vec2_set(tvarray + 2, start_u, end_v); - vec2_set(tvarray + 3, end_u, end_v); + vec3_set(data->points + 1, fcx, 0.0f, 0.0f); + vec3_set(data->points + 2, 0.0f, fcy, 0.0f); + vec3_set(data->points + 3, fcx, fcy, 0.0f); + vec2_set(tvarray, start_u, start_v); + vec2_set(tvarray + 1, end_u, start_v); + vec2_set(tvarray + 2, start_u, end_v); + vec2_set(tvarray + 3, end_u, end_v); } -static inline void build_sprite_rect(struct gs_vb_data *data, float origin_x, - float origin_y, float end_x, float end_y) +static inline void build_sprite_rect(struct gs_vb_data *data, float origin_x, float origin_y, float end_x, float end_y) { - build_sprite(data, fabsf(end_x - origin_x), fabsf(end_y - origin_y), - origin_x, end_x, origin_y, end_y); + build_sprite(data, fabsf(end_x - origin_x), fabsf(end_y - origin_y), origin_x, end_x, origin_y, end_y); } static void display_capture_video_tick(void *data, float seconds) { - UNUSED_PARAMETER(seconds); + UNUSED_PARAMETER(seconds); - struct display_capture *dc = data; + struct display_capture *dc = data; - if (!dc->current) - return; - if (!obs_source_showing(dc->source)) - return; + if (!dc->current) + return; + if (!obs_source_showing(dc->source)) + return; - IOSurfaceRef prev_prev = dc->prev; - if (pthread_mutex_lock(&dc->mutex)) - return; - dc->prev = dc->current; - dc->current = NULL; - pthread_mutex_unlock(&dc->mutex); + IOSurfaceRef prev_prev = dc->prev; + if (pthread_mutex_lock(&dc->mutex)) + return; + dc->prev = dc->current; + dc->current = NULL; + pthread_mutex_unlock(&dc->mutex); - if (prev_prev == dc->prev) - return; + if (prev_prev == dc->prev) + return; - if (requires_window(dc->crop) && !dc->on_screen) - goto cleanup; + if (requires_window(dc->crop) && !dc->on_screen) + goto cleanup; - CGPoint origin = {0.f}; - CGPoint end = {0.f}; + CGPoint origin = {0.f}; + CGPoint end = {0.f}; - switch (dc->crop) { - double x, y; - case CROP_INVALID: - break; + switch (dc->crop) { + double x, y; + case CROP_INVALID: + break; - case CROP_MANUAL: - origin.x += dc->crop_rect.origin.x; - origin.y += dc->crop_rect.origin.y; - end.y -= dc->crop_rect.size.height; - end.x -= dc->crop_rect.size.width; - case CROP_NONE: - end.y += dc->frame.size.height; - end.x += dc->frame.size.width; - break; + case CROP_MANUAL: + origin.x += dc->crop_rect.origin.x; + origin.y += dc->crop_rect.origin.y; + end.y -= dc->crop_rect.size.height; + end.x -= dc->crop_rect.size.width; + case CROP_NONE: + end.y += dc->frame.size.height; + end.x += dc->frame.size.width; + break; - case CROP_TO_WINDOW_AND_MANUAL: - origin.x += dc->crop_rect.origin.x; - origin.y += dc->crop_rect.origin.y; - end.y -= dc->crop_rect.size.height; - end.x -= dc->crop_rect.size.width; - case CROP_TO_WINDOW: - origin.x += x = dc->window_rect.origin.x - dc->frame.origin.x; - origin.y += y = dc->window_rect.origin.y - dc->frame.origin.y; - end.y += dc->window_rect.size.height + y; - end.x += dc->window_rect.size.width + x; - break; - } + case CROP_TO_WINDOW_AND_MANUAL: + origin.x += dc->crop_rect.origin.x; + origin.y += dc->crop_rect.origin.y; + end.y -= dc->crop_rect.size.height; + end.x -= dc->crop_rect.size.width; + case CROP_TO_WINDOW: + origin.x += x = dc->window_rect.origin.x - dc->frame.origin.x; + origin.y += y = dc->window_rect.origin.y - dc->frame.origin.y; + end.y += dc->window_rect.size.height + y; + end.x += dc->window_rect.size.width + x; + break; + } - obs_enter_graphics(); - build_sprite_rect(gs_vertexbuffer_get_data(dc->vertbuf), - (float)origin.x, (float)origin.y, (float)end.x, - (float)end.y); + obs_enter_graphics(); + build_sprite_rect(gs_vertexbuffer_get_data(dc->vertbuf), (float) origin.x, (float) origin.y, (float) end.x, + (float) end.y); - if (dc->tex) - gs_texture_rebind_iosurface(dc->tex, dc->prev); - else - dc->tex = gs_texture_create_from_iosurface(dc->prev); - obs_leave_graphics(); + if (dc->tex) + gs_texture_rebind_iosurface(dc->tex, dc->prev); + else + dc->tex = gs_texture_create_from_iosurface(dc->prev); + obs_leave_graphics(); cleanup: - if (prev_prev) { - IOSurfaceDecrementUseCount(prev_prev); - CFRelease(prev_prev); - } + if (prev_prev) { + IOSurfaceDecrementUseCount(prev_prev); + CFRelease(prev_prev); + } } static void display_capture_video_render(void *data, gs_effect_t *effect) { - UNUSED_PARAMETER(effect); + UNUSED_PARAMETER(effect); - struct display_capture *dc = data; + struct display_capture *dc = data; - if (!dc->tex || (requires_window(dc->crop) && !dc->on_screen)) - return; + if (!dc->tex || (requires_window(dc->crop) && !dc->on_screen)) + return; - const bool linear_srgb = gs_get_linear_srgb(); + const bool linear_srgb = gs_get_linear_srgb(); - const bool previous = gs_framebuffer_srgb_enabled(); - gs_enable_framebuffer_srgb(linear_srgb); + const bool previous = gs_framebuffer_srgb_enabled(); + gs_enable_framebuffer_srgb(linear_srgb); - gs_vertexbuffer_flush(dc->vertbuf); - gs_load_vertexbuffer(dc->vertbuf); - gs_load_indexbuffer(NULL); - gs_load_samplerstate(dc->sampler, 0); - gs_technique_t *tech = gs_effect_get_technique(dc->effect, "Draw"); - gs_eparam_t *param = gs_effect_get_param_by_name(dc->effect, "image"); - if (linear_srgb) - gs_effect_set_texture_srgb(param, dc->tex); - else - gs_effect_set_texture(param, dc->tex); - gs_technique_begin(tech); - gs_technique_begin_pass(tech, 0); + gs_vertexbuffer_flush(dc->vertbuf); + gs_load_vertexbuffer(dc->vertbuf); + gs_load_indexbuffer(NULL); + gs_load_samplerstate(dc->sampler, 0); + gs_technique_t *tech = gs_effect_get_technique(dc->effect, "Draw"); + gs_eparam_t *param = gs_effect_get_param_by_name(dc->effect, "image"); + if (linear_srgb) + gs_effect_set_texture_srgb(param, dc->tex); + else + gs_effect_set_texture(param, dc->tex); + gs_technique_begin(tech); + gs_technique_begin_pass(tech, 0); - gs_draw(GS_TRISTRIP, 0, 4); + gs_draw(GS_TRISTRIP, 0, 4); - gs_technique_end_pass(tech); - gs_technique_end(tech); + gs_technique_end_pass(tech); + gs_technique_end(tech); - gs_enable_framebuffer_srgb(previous); + gs_enable_framebuffer_srgb(previous); } static const char *display_capture_getname(void *unused) { - UNUSED_PARAMETER(unused); - return obs_module_text("DisplayCapture"); + UNUSED_PARAMETER(unused); + return obs_module_text("DisplayCapture"); } static uint32_t display_capture_getwidth(void *data) { - struct display_capture *dc = data; + struct display_capture *dc = data; - double crop = dc->crop_rect.origin.x + dc->crop_rect.size.width; - switch (dc->crop) { - case CROP_NONE: - return (uint32_t)dc->frame.size.width; + double crop = dc->crop_rect.origin.x + dc->crop_rect.size.width; + switch (dc->crop) { + case CROP_NONE: + return (uint32_t) dc->frame.size.width; - case CROP_MANUAL: - return (uint32_t)fabs(dc->frame.size.width - crop); + case CROP_MANUAL: + return (uint32_t) fabs(dc->frame.size.width - crop); - case CROP_TO_WINDOW: - return (uint32_t)dc->window_rect.size.width; + case CROP_TO_WINDOW: + return (uint32_t) dc->window_rect.size.width; - case CROP_TO_WINDOW_AND_MANUAL: - return (uint32_t)fabs(dc->window_rect.size.width - crop); + case CROP_TO_WINDOW_AND_MANUAL: + return (uint32_t) fabs(dc->window_rect.size.width - crop); - case CROP_INVALID: - break; - } - return 0; + case CROP_INVALID: + break; + } + return 0; } static uint32_t display_capture_getheight(void *data) { - struct display_capture *dc = data; + struct display_capture *dc = data; - double crop = dc->crop_rect.origin.y + dc->crop_rect.size.height; - switch (dc->crop) { - case CROP_NONE: - return (uint32_t)dc->frame.size.height; + double crop = dc->crop_rect.origin.y + dc->crop_rect.size.height; + switch (dc->crop) { + case CROP_NONE: + return (uint32_t) dc->frame.size.height; - case CROP_MANUAL: - return (uint32_t)fabs(dc->frame.size.height - crop); + case CROP_MANUAL: + return (uint32_t) fabs(dc->frame.size.height - crop); - case CROP_TO_WINDOW: - return (uint32_t)dc->window_rect.size.height; + case CROP_TO_WINDOW: + return (uint32_t) dc->window_rect.size.height; - case CROP_TO_WINDOW_AND_MANUAL: - return (uint32_t)fabs(dc->window_rect.size.height - crop); + case CROP_TO_WINDOW_AND_MANUAL: + return (uint32_t) fabs(dc->window_rect.size.height - crop); - case CROP_INVALID: - break; - } - return 0; + case CROP_INVALID: + break; + } + return 0; } static void display_capture_defaults(obs_data_t *settings) { - NSNumber *screen = - [[NSScreen mainScreen] deviceDescription][@"NSScreenNumber"]; + NSNumber *screen = [[NSScreen mainScreen] deviceDescription][@"NSScreenNumber"]; - CFUUIDRef display_uuid = CGDisplayCreateUUIDFromDisplayID( - (CGDirectDisplayID)screen.intValue); - CFStringRef uuid_string = - CFUUIDCreateString(kCFAllocatorDefault, display_uuid); - obs_data_set_default_string( - settings, "display_uuid", - CFStringGetCStringPtr(uuid_string, kCFStringEncodingUTF8)); - CFRelease(uuid_string); - CFRelease(display_uuid); - obs_data_set_default_bool(settings, "show_cursor", true); - obs_data_set_default_int(settings, "crop_mode", CROP_NONE); + CFUUIDRef display_uuid = CGDisplayCreateUUIDFromDisplayID((CGDirectDisplayID) screen.intValue); + CFStringRef uuid_string = CFUUIDCreateString(kCFAllocatorDefault, display_uuid); + obs_data_set_default_string(settings, "display_uuid", CFStringGetCStringPtr(uuid_string, kCFStringEncodingUTF8)); + CFRelease(uuid_string); + CFRelease(display_uuid); + obs_data_set_default_bool(settings, "show_cursor", true); + obs_data_set_default_int(settings, "crop_mode", CROP_NONE); - window_defaults(settings); + window_defaults(settings); } void load_crop_mode(enum crop_mode *mode, obs_data_t *settings) { - *mode = (int)obs_data_get_int(settings, "crop_mode"); - if (!crop_mode_valid(*mode)) - *mode = CROP_NONE; + *mode = (int) obs_data_get_int(settings, "crop_mode"); + if (!crop_mode_valid(*mode)) + *mode = CROP_NONE; } void load_crop(struct display_capture *dc, obs_data_t *settings) { - load_crop_mode(&dc->crop, settings); + load_crop_mode(&dc->crop, settings); #define CROP_VAR_NAME(var, mode) (mode "." #var) -#define LOAD_CROP_VAR(var, mode) \ - dc->crop_rect.var = \ - obs_data_get_double(settings, CROP_VAR_NAME(var, mode)); - switch (dc->crop) { - case CROP_MANUAL: - LOAD_CROP_VAR(origin.x, "manual"); - LOAD_CROP_VAR(origin.y, "manual"); - LOAD_CROP_VAR(size.width, "manual"); - LOAD_CROP_VAR(size.height, "manual"); - break; +#define LOAD_CROP_VAR(var, mode) dc->crop_rect.var = obs_data_get_double(settings, CROP_VAR_NAME(var, mode)); + switch (dc->crop) { + case CROP_MANUAL: + LOAD_CROP_VAR(origin.x, "manual"); + LOAD_CROP_VAR(origin.y, "manual"); + LOAD_CROP_VAR(size.width, "manual"); + LOAD_CROP_VAR(size.height, "manual"); + break; - case CROP_TO_WINDOW_AND_MANUAL: - LOAD_CROP_VAR(origin.x, "window"); - LOAD_CROP_VAR(origin.y, "window"); - LOAD_CROP_VAR(size.width, "window"); - LOAD_CROP_VAR(size.height, "window"); - break; + case CROP_TO_WINDOW_AND_MANUAL: + LOAD_CROP_VAR(origin.x, "window"); + LOAD_CROP_VAR(origin.y, "window"); + LOAD_CROP_VAR(size.width, "window"); + LOAD_CROP_VAR(size.height, "window"); + break; - case CROP_NONE: - case CROP_TO_WINDOW: - case CROP_INVALID: - break; - } + case CROP_NONE: + case CROP_TO_WINDOW: + case CROP_INVALID: + break; + } #undef LOAD_CROP_VAR } static void display_capture_update(void *data, obs_data_t *settings) { - struct display_capture *dc = data; + struct display_capture *dc = data; - load_crop(dc, settings); + load_crop(dc, settings); - if (requires_window(dc->crop)) - update_window(&dc->window, settings); + if (requires_window(dc->crop)) + update_window(&dc->window, settings); - CFStringRef uuid_string = CFStringCreateWithCString( - kCFAllocatorDefault, - obs_data_get_string(settings, "display_uuid"), - kCFStringEncodingUTF8); - CFUUIDRef display_uuid = - CFUUIDCreateFromString(kCFAllocatorDefault, uuid_string); - CGDirectDisplayID display = CGDisplayGetDisplayIDFromUUID(display_uuid); - CFRelease(uuid_string); - CFRelease(display_uuid); + CFStringRef uuid_string = CFStringCreateWithCString( + kCFAllocatorDefault, obs_data_get_string(settings, "display_uuid"), kCFStringEncodingUTF8); + CFUUIDRef display_uuid = CFUUIDCreateFromString(kCFAllocatorDefault, uuid_string); + CGDirectDisplayID display = CGDisplayGetDisplayIDFromUUID(display_uuid); + CFRelease(uuid_string); + CFRelease(display_uuid); - bool show_cursor = obs_data_get_bool(settings, "show_cursor"); - if (dc->display == display && dc->hide_cursor != show_cursor) - return; + bool show_cursor = obs_data_get_bool(settings, "show_cursor"); + if (dc->display == display && dc->hide_cursor != show_cursor) + return; - obs_enter_graphics(); + obs_enter_graphics(); - destroy_display_stream(dc); - dc->display = display; - dc->hide_cursor = !show_cursor; - init_display_stream(dc); + destroy_display_stream(dc); + dc->display = display; + dc->hide_cursor = !show_cursor; + init_display_stream(dc); - obs_leave_graphics(); + obs_leave_graphics(); } -static bool switch_crop_mode(obs_properties_t *props, obs_property_t *p, - obs_data_t *settings) +static bool switch_crop_mode(obs_properties_t *props, obs_property_t *p, obs_data_t *settings) { - UNUSED_PARAMETER(p); + UNUSED_PARAMETER(p); - enum crop_mode crop; - load_crop_mode(&crop, settings); + enum crop_mode crop; + load_crop_mode(&crop, settings); - const char *name; - bool visible; -#define LOAD_CROP_VAR(var, mode) \ - name = CROP_VAR_NAME(var, mode); \ - obs_property_set_visible(obs_properties_get(props, name), visible); + const char *name; + bool visible; +#define LOAD_CROP_VAR(var, mode) \ + name = CROP_VAR_NAME(var, mode); \ + obs_property_set_visible(obs_properties_get(props, name), visible); - visible = crop == CROP_MANUAL; - LOAD_CROP_VAR(origin.x, "manual"); - LOAD_CROP_VAR(origin.y, "manual"); - LOAD_CROP_VAR(size.width, "manual"); - LOAD_CROP_VAR(size.height, "manual"); + visible = crop == CROP_MANUAL; + LOAD_CROP_VAR(origin.x, "manual"); + LOAD_CROP_VAR(origin.y, "manual"); + LOAD_CROP_VAR(size.width, "manual"); + LOAD_CROP_VAR(size.height, "manual"); - visible = crop == CROP_TO_WINDOW_AND_MANUAL; - LOAD_CROP_VAR(origin.x, "window"); - LOAD_CROP_VAR(origin.y, "window"); - LOAD_CROP_VAR(size.width, "window"); - LOAD_CROP_VAR(size.height, "window"); + visible = crop == CROP_TO_WINDOW_AND_MANUAL; + LOAD_CROP_VAR(origin.x, "window"); + LOAD_CROP_VAR(origin.y, "window"); + LOAD_CROP_VAR(size.width, "window"); + LOAD_CROP_VAR(size.height, "window"); #undef LOAD_CROP_VAR - show_window_properties(props, visible || crop == CROP_TO_WINDOW); - return true; + show_window_properties(props, visible || crop == CROP_TO_WINDOW); + return true; } -static const char *crop_names[] = {"CropMode.None", "CropMode.Manual", - "CropMode.ToWindow", - "CropMode.ToWindowAndManual"}; +static const char *crop_names[] = {"CropMode.None", "CropMode.Manual", "CropMode.ToWindow", + "CropMode.ToWindowAndManual"}; #ifndef COUNTOF #define COUNTOF(x) (sizeof(x) / sizeof(x[0])) #endif static obs_properties_t *display_capture_properties(void *unused) { - UNUSED_PARAMETER(unused); + UNUSED_PARAMETER(unused); - obs_properties_t *props = obs_properties_create(); + obs_properties_t *props = obs_properties_create(); - obs_property_t *list = obs_properties_add_list( - props, "display_uuid", - obs_module_text("DisplayCapture.Display"), OBS_COMBO_TYPE_LIST, - OBS_COMBO_FORMAT_STRING); + obs_property_t *list = obs_properties_add_list(props, "display_uuid", obs_module_text("DisplayCapture.Display"), + OBS_COMBO_TYPE_LIST, OBS_COMBO_FORMAT_STRING); - [[NSScreen screens] enumerateObjectsUsingBlock:^( - NSScreen *_Nonnull screen, - NSUInteger index __unused, - BOOL *_Nonnull stop __unused) { - char dimension_buffer[4][12]; - char name_buffer[256]; - snprintf(dimension_buffer[0], sizeof(dimension_buffer[0]), "%u", - (uint32_t)[screen frame].size.width); - snprintf(dimension_buffer[1], sizeof(dimension_buffer[0]), "%u", - (uint32_t)[screen frame].size.height); - snprintf(dimension_buffer[2], sizeof(dimension_buffer[0]), "%d", - (int32_t)[screen frame].origin.x); - snprintf(dimension_buffer[3], sizeof(dimension_buffer[0]), "%d", - (int32_t)[screen frame].origin.y); + [[NSScreen screens] enumerateObjectsUsingBlock:^(NSScreen *_Nonnull screen, NSUInteger index __unused, + BOOL *_Nonnull stop __unused) { + char dimension_buffer[4][12]; + char name_buffer[256]; + snprintf(dimension_buffer[0], sizeof(dimension_buffer[0]), "%u", (uint32_t)[screen frame].size.width); + snprintf(dimension_buffer[1], sizeof(dimension_buffer[0]), "%u", (uint32_t)[screen frame].size.height); + snprintf(dimension_buffer[2], sizeof(dimension_buffer[0]), "%d", (int32_t)[screen frame].origin.x); + snprintf(dimension_buffer[3], sizeof(dimension_buffer[0]), "%d", (int32_t)[screen frame].origin.y); - snprintf(name_buffer, sizeof(name_buffer), - "%.200s: %.12sx%.12s @ %.12s,%.12s", - [[screen localizedName] UTF8String], - dimension_buffer[0], dimension_buffer[1], - dimension_buffer[2], dimension_buffer[3]); + snprintf(name_buffer, sizeof(name_buffer), "%.200s: %.12sx%.12s @ %.12s,%.12s", + [[screen localizedName] UTF8String], dimension_buffer[0], dimension_buffer[1], dimension_buffer[2], + dimension_buffer[3]); - NSNumber *screenNumber = - screen.deviceDescription[@"NSScreenNumber"]; + NSNumber *screenNumber = screen.deviceDescription[@"NSScreenNumber"]; - CGDirectDisplayID display_id = - (CGDirectDisplayID)screenNumber.intValue; - CFUUIDRef display_uuid = - CGDisplayCreateUUIDFromDisplayID(display_id); - CFStringRef uuid_string = - CFUUIDCreateString(kCFAllocatorDefault, display_uuid); - obs_property_list_add_string( - list, name_buffer, - CFStringGetCStringPtr(uuid_string, - kCFStringEncodingUTF8)); - CFRelease(uuid_string); - CFRelease(display_uuid); - }]; + CGDirectDisplayID display_id = (CGDirectDisplayID) screenNumber.intValue; + CFUUIDRef display_uuid = CGDisplayCreateUUIDFromDisplayID(display_id); + CFStringRef uuid_string = CFUUIDCreateString(kCFAllocatorDefault, display_uuid); + obs_property_list_add_string(list, name_buffer, CFStringGetCStringPtr(uuid_string, kCFStringEncodingUTF8)); + CFRelease(uuid_string); + CFRelease(display_uuid); + }]; - obs_properties_add_bool(props, "show_cursor", - obs_module_text("DisplayCapture.ShowCursor")); + obs_properties_add_bool(props, "show_cursor", obs_module_text("DisplayCapture.ShowCursor")); - obs_property_t *crop = obs_properties_add_list( - props, "crop_mode", obs_module_text("CropMode"), - OBS_COMBO_TYPE_LIST, OBS_COMBO_FORMAT_INT); - obs_property_set_modified_callback(crop, switch_crop_mode); + obs_property_t *crop = obs_properties_add_list(props, "crop_mode", obs_module_text("CropMode"), OBS_COMBO_TYPE_LIST, + OBS_COMBO_FORMAT_INT); + obs_property_set_modified_callback(crop, switch_crop_mode); - for (unsigned i = 0; i < COUNTOF(crop_names); i++) { - const char *name = obs_module_text(crop_names[i]); - obs_property_list_add_int(crop, name, i); - } + for (unsigned i = 0; i < COUNTOF(crop_names); i++) { + const char *name = obs_module_text(crop_names[i]); + obs_property_list_add_int(crop, name, i); + } - add_window_properties(props); - show_window_properties(props, false); + add_window_properties(props); + show_window_properties(props, false); - obs_property_t *p; - const char *name; - float min; -#define LOAD_CROP_VAR(var, mode) \ - name = CROP_VAR_NAME(var, mode); \ - p = obs_properties_add_float( \ - props, name, obs_module_text("Crop." #var), min, 4096.f, .5f); \ - obs_property_set_visible(p, false); + obs_property_t *p; + const char *name; + float min; +#define LOAD_CROP_VAR(var, mode) \ + name = CROP_VAR_NAME(var, mode); \ + p = obs_properties_add_float(props, name, obs_module_text("Crop." #var), min, 4096.f, .5f); \ + obs_property_set_visible(p, false); - min = 0.f; - LOAD_CROP_VAR(origin.x, "manual"); - LOAD_CROP_VAR(origin.y, "manual"); - LOAD_CROP_VAR(size.width, "manual"); - LOAD_CROP_VAR(size.height, "manual"); + min = 0.f; + LOAD_CROP_VAR(origin.x, "manual"); + LOAD_CROP_VAR(origin.y, "manual"); + LOAD_CROP_VAR(size.width, "manual"); + LOAD_CROP_VAR(size.height, "manual"); - min = -4096.f; - LOAD_CROP_VAR(origin.x, "window"); - LOAD_CROP_VAR(origin.y, "window"); - LOAD_CROP_VAR(size.width, "window"); - LOAD_CROP_VAR(size.height, "window"); + min = -4096.f; + LOAD_CROP_VAR(origin.x, "window"); + LOAD_CROP_VAR(origin.y, "window"); + LOAD_CROP_VAR(size.width, "window"); + LOAD_CROP_VAR(size.height, "window"); #undef LOAD_CROP_VAR - return props; + return props; } struct obs_source_info display_capture_info = { - .id = "display_capture", - .type = OBS_SOURCE_TYPE_INPUT, - .get_name = display_capture_getname, + .id = "display_capture", + .type = OBS_SOURCE_TYPE_INPUT, + .get_name = display_capture_getname, - .create = display_capture_create, - .destroy = display_capture_destroy, + .create = display_capture_create, + .destroy = display_capture_destroy, - .output_flags = OBS_SOURCE_VIDEO | OBS_SOURCE_CUSTOM_DRAW | - OBS_SOURCE_DO_NOT_DUPLICATE | OBS_SOURCE_SRGB, - .video_tick = display_capture_video_tick, - .video_render = display_capture_video_render, + .output_flags = OBS_SOURCE_VIDEO | OBS_SOURCE_CUSTOM_DRAW | OBS_SOURCE_DO_NOT_DUPLICATE | OBS_SOURCE_SRGB, + .video_tick = display_capture_video_tick, + .video_render = display_capture_video_render, - .get_width = display_capture_getwidth, - .get_height = display_capture_getheight, + .get_width = display_capture_getwidth, + .get_height = display_capture_getheight, - .get_defaults = display_capture_defaults, - .get_properties = display_capture_properties, - .update = display_capture_update, - .icon_type = OBS_ICON_TYPE_DESKTOP_CAPTURE, + .get_defaults = display_capture_defaults, + .get_properties = display_capture_properties, + .update = display_capture_update, + .icon_type = OBS_ICON_TYPE_DESKTOP_CAPTURE, }; diff --git a/plugins/mac-capture/mac-screen-capture.m b/plugins/mac-capture/mac-screen-capture.m index 458e275f9..1feac4be7 100644 --- a/plugins/mac-capture/mac-screen-capture.m +++ b/plugins/mac-capture/mac-screen-capture.m @@ -3,14 +3,14 @@ bool is_screen_capture_available(void) { - if (@available(macOS 12.5, *)) { - return true; - } else { - return false; - } + if (@available(macOS 12.5, *)) { + return true; + } else { + return false; + } } -#if __MAC_OS_X_VERSION_MAX_ALLOWED >= 120300 // __MAC_12_3 +#if __MAC_OS_X_VERSION_MAX_ALLOWED >= 120300 // __MAC_12_3 #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wunguarded-availability-new" @@ -24,14 +24,13 @@ bool is_screen_capture_available(void) #include #include -#define MACCAP_LOG(level, msg, ...) \ - blog(level, "[ mac-screencapture ]: " msg, ##__VA_ARGS__) -#define MACCAP_ERR(msg, ...) MACCAP_LOG(LOG_ERROR, msg, ##__VA_ARGS__) +#define MACCAP_LOG(level, msg, ...) blog(level, "[ mac-screencapture ]: " msg, ##__VA_ARGS__) +#define MACCAP_ERR(msg, ...) MACCAP_LOG(LOG_ERROR, msg, ##__VA_ARGS__) typedef enum { - ScreenCaptureDisplayStream = 0, - ScreenCaptureWindowStream = 1, - ScreenCaptureApplicationStream = 2, + ScreenCaptureDisplayStream = 0, + ScreenCaptureWindowStream = 1, + ScreenCaptureApplicationStream = 2, } ScreenCaptureStreamType; @interface ScreenCaptureDelegate : NSObject @@ -41,1297 +40,1053 @@ typedef enum { @end struct screen_capture { - obs_source_t *source; + obs_source_t *source; - gs_effect_t *effect; - gs_texture_t *tex; + gs_effect_t *effect; + gs_texture_t *tex; - NSRect frame; - bool hide_cursor; - bool hide_obs; - bool show_hidden_windows; - bool show_empty_names; + NSRect frame; + bool hide_cursor; + bool hide_obs; + bool show_hidden_windows; + bool show_empty_names; - SCStream *disp; - SCStreamConfiguration *stream_properties; - SCShareableContent *shareable_content; - ScreenCaptureDelegate *capture_delegate; + SCStream *disp; + SCStreamConfiguration *stream_properties; + SCShareableContent *shareable_content; + ScreenCaptureDelegate *capture_delegate; - os_event_t *disp_finished; - os_event_t *stream_start_completed; - os_sem_t *shareable_content_available; - IOSurfaceRef current, prev; + os_event_t *disp_finished; + os_event_t *stream_start_completed; + os_sem_t *shareable_content_available; + IOSurfaceRef current, prev; - pthread_mutex_t mutex; + pthread_mutex_t mutex; - ScreenCaptureStreamType capture_type; - CGDirectDisplayID display; - CGWindowID window; - NSString *application_id; + ScreenCaptureStreamType capture_type; + CGDirectDisplayID display; + CGWindowID window; + NSString *application_id; }; #pragma mark - static void destroy_screen_stream(struct screen_capture *sc) { - if (sc->disp) { - [sc->disp stopCaptureWithCompletionHandler:^( - NSError *_Nullable error) { - if (error && error.code != 3808) { - MACCAP_ERR( - "destroy_screen_stream: Failed to stop stream with error %s\n", - [[error localizedFailureReason] - cStringUsingEncoding: - NSUTF8StringEncoding]); - } - os_event_signal(sc->disp_finished); - }]; - os_event_wait(sc->disp_finished); - } + if (sc->disp) { + [sc->disp stopCaptureWithCompletionHandler:^(NSError *_Nullable error) { + if (error && error.code != 3808) { + MACCAP_ERR("destroy_screen_stream: Failed to stop stream with error %s\n", + [[error localizedFailureReason] cStringUsingEncoding:NSUTF8StringEncoding]); + } + os_event_signal(sc->disp_finished); + }]; + os_event_wait(sc->disp_finished); + } - if (sc->stream_properties) { - [sc->stream_properties release]; - sc->stream_properties = NULL; - } + if (sc->stream_properties) { + [sc->stream_properties release]; + sc->stream_properties = NULL; + } - if (sc->tex) { - gs_texture_destroy(sc->tex); - sc->tex = NULL; - } + if (sc->tex) { + gs_texture_destroy(sc->tex); + sc->tex = NULL; + } - if (sc->current) { - IOSurfaceDecrementUseCount(sc->current); - CFRelease(sc->current); - sc->current = NULL; - } + if (sc->current) { + IOSurfaceDecrementUseCount(sc->current); + CFRelease(sc->current); + sc->current = NULL; + } - if (sc->prev) { - IOSurfaceDecrementUseCount(sc->prev); - CFRelease(sc->prev); - sc->prev = NULL; - } + if (sc->prev) { + IOSurfaceDecrementUseCount(sc->prev); + CFRelease(sc->prev); + sc->prev = NULL; + } - if (sc->disp) { - [sc->disp release]; - sc->disp = NULL; - } + if (sc->disp) { + [sc->disp release]; + sc->disp = NULL; + } - os_event_destroy(sc->disp_finished); - os_event_destroy(sc->stream_start_completed); + os_event_destroy(sc->disp_finished); + os_event_destroy(sc->stream_start_completed); } static void screen_capture_destroy(void *data) { - struct screen_capture *sc = data; + struct screen_capture *sc = data; - if (!sc) - return; + if (!sc) + return; - obs_enter_graphics(); + obs_enter_graphics(); - destroy_screen_stream(sc); + destroy_screen_stream(sc); - obs_leave_graphics(); + obs_leave_graphics(); - if (sc->shareable_content) { - os_sem_wait(sc->shareable_content_available); - [sc->shareable_content release]; - os_sem_destroy(sc->shareable_content_available); - sc->shareable_content_available = NULL; - } + if (sc->shareable_content) { + os_sem_wait(sc->shareable_content_available); + [sc->shareable_content release]; + os_sem_destroy(sc->shareable_content_available); + sc->shareable_content_available = NULL; + } - if (sc->capture_delegate) { - [sc->capture_delegate release]; - } - [sc->application_id release]; + if (sc->capture_delegate) { + [sc->capture_delegate release]; + } + [sc->application_id release]; - pthread_mutex_destroy(&sc->mutex); - bfree(sc); + pthread_mutex_destroy(&sc->mutex); + bfree(sc); } -static inline void screen_stream_video_update(struct screen_capture *sc, - CMSampleBufferRef sample_buffer) +static inline void screen_stream_video_update(struct screen_capture *sc, CMSampleBufferRef sample_buffer) { - bool frame_detail_errored = false; - float scale_factor = 1.0f; - CGRect window_rect = {}; + bool frame_detail_errored = false; + float scale_factor = 1.0f; + CGRect window_rect = {}; - CFArrayRef attachments_array = - CMSampleBufferGetSampleAttachmentsArray(sample_buffer, false); - if (sc->capture_type == ScreenCaptureWindowStream && - attachments_array != NULL && - CFArrayGetCount(attachments_array) > 0) { - CFDictionaryRef attachments_dict = - CFArrayGetValueAtIndex(attachments_array, 0); - if (attachments_dict != NULL) { + CFArrayRef attachments_array = CMSampleBufferGetSampleAttachmentsArray(sample_buffer, false); + if (sc->capture_type == ScreenCaptureWindowStream && attachments_array != NULL && + CFArrayGetCount(attachments_array) > 0) { + CFDictionaryRef attachments_dict = CFArrayGetValueAtIndex(attachments_array, 0); + if (attachments_dict != NULL) { + CFTypeRef frame_scale_factor = CFDictionaryGetValue(attachments_dict, SCStreamFrameInfoScaleFactor); + if (frame_scale_factor != NULL) { + Boolean result = CFNumberGetValue((CFNumberRef) frame_scale_factor, kCFNumberFloatType, &scale_factor); + if (result == false) { + scale_factor = 1.0f; + frame_detail_errored = true; + } + } - CFTypeRef frame_scale_factor = CFDictionaryGetValue( - attachments_dict, SCStreamFrameInfoScaleFactor); - if (frame_scale_factor != NULL) { - Boolean result = CFNumberGetValue( - (CFNumberRef)frame_scale_factor, - kCFNumberFloatType, &scale_factor); - if (result == false) { - scale_factor = 1.0f; - frame_detail_errored = true; - } - } + CFTypeRef content_rect_dict = CFDictionaryGetValue(attachments_dict, SCStreamFrameInfoContentRect); + CFTypeRef content_scale_factor = CFDictionaryGetValue(attachments_dict, SCStreamFrameInfoContentScale); + if ((content_rect_dict != NULL) && (content_scale_factor != NULL)) { + CGRect content_rect = {}; + float points_to_pixels = 0.0f; - CFTypeRef content_rect_dict = CFDictionaryGetValue( - attachments_dict, SCStreamFrameInfoContentRect); - CFTypeRef content_scale_factor = CFDictionaryGetValue( - attachments_dict, - SCStreamFrameInfoContentScale); - if ((content_rect_dict != NULL) && - (content_scale_factor != NULL)) { - CGRect content_rect = {}; - float points_to_pixels = 0.0f; + Boolean result = + CGRectMakeWithDictionaryRepresentation((__bridge CFDictionaryRef) content_rect_dict, &content_rect); + if (result == false) { + content_rect = CGRectZero; + frame_detail_errored = true; + } + result = CFNumberGetValue((CFNumberRef) content_scale_factor, kCFNumberFloatType, &points_to_pixels); + if (result == false) { + points_to_pixels = 1.0f; + frame_detail_errored = true; + } - Boolean result = - CGRectMakeWithDictionaryRepresentation( - (__bridge CFDictionaryRef) - content_rect_dict, - &content_rect); - if (result == false) { - content_rect = CGRectZero; - frame_detail_errored = true; - } - result = CFNumberGetValue( - (CFNumberRef)content_scale_factor, - kCFNumberFloatType, &points_to_pixels); - if (result == false) { - points_to_pixels = 1.0f; - frame_detail_errored = true; - } + window_rect.origin = content_rect.origin; + window_rect.size.width = content_rect.size.width / points_to_pixels * scale_factor; + window_rect.size.height = content_rect.size.height / points_to_pixels * scale_factor; + } + } + } - window_rect.origin = content_rect.origin; - window_rect.size.width = - content_rect.size.width / - points_to_pixels * scale_factor; - window_rect.size.height = - content_rect.size.height / - points_to_pixels * scale_factor; - } - } - } + CVImageBufferRef image_buffer = CMSampleBufferGetImageBuffer(sample_buffer); - CVImageBufferRef image_buffer = - CMSampleBufferGetImageBuffer(sample_buffer); + CVPixelBufferLockBaseAddress(image_buffer, 0); + IOSurfaceRef frame_surface = CVPixelBufferGetIOSurface(image_buffer); + CVPixelBufferUnlockBaseAddress(image_buffer, 0); - CVPixelBufferLockBaseAddress(image_buffer, 0); - IOSurfaceRef frame_surface = CVPixelBufferGetIOSurface(image_buffer); - CVPixelBufferUnlockBaseAddress(image_buffer, 0); + IOSurfaceRef prev_current = NULL; - IOSurfaceRef prev_current = NULL; + if (frame_surface && !pthread_mutex_lock(&sc->mutex)) { + bool needs_to_update_properties = false; - if (frame_surface && !pthread_mutex_lock(&sc->mutex)) { + if (!frame_detail_errored) { + if (sc->capture_type == ScreenCaptureWindowStream) { + if ((sc->frame.size.width != window_rect.size.width) || + (sc->frame.size.height != window_rect.size.height)) { + sc->frame.size.width = window_rect.size.width; + sc->frame.size.height = window_rect.size.height; + needs_to_update_properties = true; + } + } else { + size_t width = CVPixelBufferGetWidth(image_buffer); + size_t height = CVPixelBufferGetHeight(image_buffer); - bool needs_to_update_properties = false; + if ((sc->frame.size.width != width) || (sc->frame.size.height != height)) { + sc->frame.size.width = width; + sc->frame.size.height = height; + needs_to_update_properties = true; + } + } + } - if (!frame_detail_errored) { - if (sc->capture_type == ScreenCaptureWindowStream) { - if ((sc->frame.size.width != - window_rect.size.width) || - (sc->frame.size.height != - window_rect.size.height)) { - sc->frame.size.width = - window_rect.size.width; - sc->frame.size.height = - window_rect.size.height; - needs_to_update_properties = true; - } - } else { - size_t width = - CVPixelBufferGetWidth(image_buffer); - size_t height = - CVPixelBufferGetHeight(image_buffer); + if (needs_to_update_properties) { + [sc->stream_properties setWidth:(size_t) sc->frame.size.width]; + [sc->stream_properties setHeight:(size_t) sc->frame.size.height]; - if ((sc->frame.size.width != width) || - (sc->frame.size.height != height)) { - sc->frame.size.width = width; - sc->frame.size.height = height; - needs_to_update_properties = true; - } - } - } + [sc->disp updateConfiguration:sc->stream_properties completionHandler:^(NSError *_Nullable error) { + if (error) { + MACCAP_ERR("screen_stream_video_update: Failed to update stream properties with error %s\n", + [[error localizedFailureReason] cStringUsingEncoding:NSUTF8StringEncoding]); + } + }]; + } - if (needs_to_update_properties) { - [sc->stream_properties - setWidth:(size_t)sc->frame.size.width]; - [sc->stream_properties - setHeight:(size_t)sc->frame.size.height]; + prev_current = sc->current; + sc->current = frame_surface; + CFRetain(sc->current); + IOSurfaceIncrementUseCount(sc->current); - [sc->disp - updateConfiguration:sc->stream_properties - completionHandler:^( - NSError *_Nullable error) { - if (error) { - MACCAP_ERR( - "screen_stream_video_update: Failed to update stream properties with error %s\n", - [[error localizedFailureReason] - cStringUsingEncoding: - NSUTF8StringEncoding]); - } - }]; - } + pthread_mutex_unlock(&sc->mutex); + } - prev_current = sc->current; - sc->current = frame_surface; - CFRetain(sc->current); - IOSurfaceIncrementUseCount(sc->current); - - pthread_mutex_unlock(&sc->mutex); - } - - if (prev_current) { - IOSurfaceDecrementUseCount(prev_current); - CFRelease(prev_current); - } + if (prev_current) { + IOSurfaceDecrementUseCount(prev_current); + CFRelease(prev_current); + } } -static inline void screen_stream_audio_update(struct screen_capture *sc, - CMSampleBufferRef sample_buffer) +static inline void screen_stream_audio_update(struct screen_capture *sc, CMSampleBufferRef sample_buffer) { - CMFormatDescriptionRef format_description = - CMSampleBufferGetFormatDescription(sample_buffer); - const AudioStreamBasicDescription *audio_description = - CMAudioFormatDescriptionGetStreamBasicDescription( - format_description); + CMFormatDescriptionRef format_description = CMSampleBufferGetFormatDescription(sample_buffer); + const AudioStreamBasicDescription *audio_description = + CMAudioFormatDescriptionGetStreamBasicDescription(format_description); - if (audio_description->mChannelsPerFrame < 1) { - MACCAP_ERR( - "screen_stream_audio_update: Received sample buffer has less than 1 channel per frame (mChannelsPerFrame set to '%d')\n", - audio_description->mChannelsPerFrame); - return; - } + if (audio_description->mChannelsPerFrame < 1) { + MACCAP_ERR( + "screen_stream_audio_update: Received sample buffer has less than 1 channel per frame (mChannelsPerFrame set to '%d')\n", + audio_description->mChannelsPerFrame); + return; + } - char *_Nullable bytes = NULL; - CMBlockBufferRef data_buffer = - CMSampleBufferGetDataBuffer(sample_buffer); - size_t data_buffer_length = CMBlockBufferGetDataLength(data_buffer); - CMBlockBufferGetDataPointer(data_buffer, 0, &data_buffer_length, NULL, - &bytes); + char *_Nullable bytes = NULL; + CMBlockBufferRef data_buffer = CMSampleBufferGetDataBuffer(sample_buffer); + size_t data_buffer_length = CMBlockBufferGetDataLength(data_buffer); + CMBlockBufferGetDataPointer(data_buffer, 0, &data_buffer_length, NULL, &bytes); - CMTime presentation_time = - CMSampleBufferGetOutputPresentationTimeStamp(sample_buffer); + CMTime presentation_time = CMSampleBufferGetOutputPresentationTimeStamp(sample_buffer); - struct obs_source_audio audio_data = {}; + struct obs_source_audio audio_data = {}; - for (uint32_t channel_idx = 0; - channel_idx < audio_description->mChannelsPerFrame; - ++channel_idx) { - uint32_t offset = - (uint32_t)(data_buffer_length / - audio_description->mChannelsPerFrame) * - channel_idx; - audio_data.data[channel_idx] = (uint8_t *)bytes + offset; - } + for (uint32_t channel_idx = 0; channel_idx < audio_description->mChannelsPerFrame; ++channel_idx) { + uint32_t offset = (uint32_t) (data_buffer_length / audio_description->mChannelsPerFrame) * channel_idx; + audio_data.data[channel_idx] = (uint8_t *) bytes + offset; + } - audio_data.frames = (uint32_t)(data_buffer_length / - audio_description->mBytesPerFrame / - audio_description->mChannelsPerFrame); - audio_data.speakers = audio_description->mChannelsPerFrame; - audio_data.samples_per_sec = (uint32_t)audio_description->mSampleRate; - audio_data.timestamp = - (uint64_t)(CMTimeGetSeconds(presentation_time) * NSEC_PER_SEC); - audio_data.format = AUDIO_FORMAT_FLOAT_PLANAR; - obs_source_output_audio(sc->source, &audio_data); + audio_data.frames = + (uint32_t) (data_buffer_length / audio_description->mBytesPerFrame / audio_description->mChannelsPerFrame); + audio_data.speakers = audio_description->mChannelsPerFrame; + audio_data.samples_per_sec = (uint32_t) audio_description->mSampleRate; + audio_data.timestamp = (uint64_t) (CMTimeGetSeconds(presentation_time) * NSEC_PER_SEC); + audio_data.format = AUDIO_FORMAT_FLOAT_PLANAR; + obs_source_output_audio(sc->source, &audio_data); } static bool init_screen_stream(struct screen_capture *sc) { - SCContentFilter *content_filter; + SCContentFilter *content_filter; - sc->frame = CGRectZero; - sc->stream_properties = [[SCStreamConfiguration alloc] init]; - os_sem_wait(sc->shareable_content_available); + sc->frame = CGRectZero; + sc->stream_properties = [[SCStreamConfiguration alloc] init]; + os_sem_wait(sc->shareable_content_available); - SCDisplay * (^get_target_display)() = ^SCDisplay *() - { - __block SCDisplay *target_display = nil; - [sc->shareable_content.displays - indexOfObjectPassingTest:^BOOL( - SCDisplay *_Nonnull display, NSUInteger idx, - BOOL *_Nonnull stop) { - if (display.displayID == sc->display) { - target_display = sc->shareable_content - .displays[idx]; - *stop = TRUE; - } - return *stop; - }]; - return target_display; - }; + SCDisplay * (^get_target_display)() = ^SCDisplay *() + { + __block SCDisplay *target_display = nil; + [sc->shareable_content.displays + indexOfObjectPassingTest:^BOOL(SCDisplay *_Nonnull display, NSUInteger idx, BOOL *_Nonnull stop) { + if (display.displayID == sc->display) { + target_display = sc->shareable_content.displays[idx]; + *stop = TRUE; + } + return *stop; + }]; + return target_display; + }; - void (^set_display_mode)(struct screen_capture *, SCDisplay *) = ^void( - struct screen_capture *capture_data, - SCDisplay *target_display) { - CGDisplayModeRef display_mode = - CGDisplayCopyDisplayMode(target_display.displayID); - [capture_data->stream_properties - setWidth:CGDisplayModeGetPixelWidth(display_mode)]; - [capture_data->stream_properties - setHeight:CGDisplayModeGetPixelHeight(display_mode)]; - CGDisplayModeRelease(display_mode); - }; + void (^set_display_mode)(struct screen_capture *, SCDisplay *) = + ^void(struct screen_capture *capture_data, SCDisplay *target_display) { + CGDisplayModeRef display_mode = CGDisplayCopyDisplayMode(target_display.displayID); + [capture_data->stream_properties setWidth:CGDisplayModeGetPixelWidth(display_mode)]; + [capture_data->stream_properties setHeight:CGDisplayModeGetPixelHeight(display_mode)]; + CGDisplayModeRelease(display_mode); + }; - switch (sc->capture_type) { - case ScreenCaptureDisplayStream: { - SCDisplay *target_display = get_target_display(); + switch (sc->capture_type) { + case ScreenCaptureDisplayStream: { + SCDisplay *target_display = get_target_display(); - if (sc->hide_obs) { - __block SCRunningApplication *obsApp = nil; - [sc->shareable_content - .applications indexOfObjectPassingTest:^BOOL( - SCRunningApplication - *_Nonnull app, - NSUInteger idx - __unused, - BOOL *_Nonnull stop) { - if ([app.bundleIdentifier - isEqualToString: - [[NSBundle mainBundle] - bundleIdentifier]]) { - obsApp = app; - *stop = TRUE; - } - return *stop; - }]; + if (sc->hide_obs) { + __block SCRunningApplication *obsApp = nil; + [sc->shareable_content.applications + indexOfObjectPassingTest:^BOOL(SCRunningApplication *_Nonnull app, NSUInteger idx __unused, + BOOL *_Nonnull stop) { + if ([app.bundleIdentifier isEqualToString:[[NSBundle mainBundle] bundleIdentifier]]) { + obsApp = app; + *stop = TRUE; + } + return *stop; + }]; - NSArray *exclusions = - [[NSArray alloc] initWithObjects:obsApp, nil]; + NSArray *exclusions = [[NSArray alloc] initWithObjects:obsApp, nil]; - NSArray *empty = [[NSArray alloc] init]; - content_filter = [[SCContentFilter alloc] - initWithDisplay:target_display - excludingApplications:exclusions - exceptingWindows:empty]; - [empty release]; - [exclusions release]; - } else { - NSArray *empty = [[NSArray alloc] init]; - content_filter = [[SCContentFilter alloc] - initWithDisplay:target_display - excludingWindows:empty]; - [empty release]; - } + NSArray *empty = [[NSArray alloc] init]; + content_filter = [[SCContentFilter alloc] initWithDisplay:target_display + excludingApplications:exclusions + exceptingWindows:empty]; + [empty release]; + [exclusions release]; + } else { + NSArray *empty = [[NSArray alloc] init]; + content_filter = [[SCContentFilter alloc] initWithDisplay:target_display excludingWindows:empty]; + [empty release]; + } - set_display_mode(sc, target_display); - } break; - case ScreenCaptureWindowStream: { - __block SCWindow *target_window = nil; - if (sc->window != 0) { - [sc->shareable_content.windows - indexOfObjectPassingTest:^BOOL( - SCWindow *_Nonnull window, - NSUInteger idx, BOOL *_Nonnull stop) { - if (window.windowID == sc->window) { - target_window = - sc->shareable_content - .windows[idx]; - *stop = TRUE; - } - return *stop; - }]; - } else { - target_window = - [sc->shareable_content.windows objectAtIndex:0]; - sc->window = target_window.windowID; - } - content_filter = [[SCContentFilter alloc] - initWithDesktopIndependentWindow:target_window]; + set_display_mode(sc, target_display); + } break; + case ScreenCaptureWindowStream: { + __block SCWindow *target_window = nil; + if (sc->window != 0) { + [sc->shareable_content.windows + indexOfObjectPassingTest:^BOOL(SCWindow *_Nonnull window, NSUInteger idx, BOOL *_Nonnull stop) { + if (window.windowID == sc->window) { + target_window = sc->shareable_content.windows[idx]; + *stop = TRUE; + } + return *stop; + }]; + } else { + target_window = [sc->shareable_content.windows objectAtIndex:0]; + sc->window = target_window.windowID; + } + content_filter = [[SCContentFilter alloc] initWithDesktopIndependentWindow:target_window]; - if (target_window) { - [sc->stream_properties - setWidth:(size_t)target_window.frame.size.width]; - [sc->stream_properties - setHeight:(size_t)target_window.frame.size - .height]; - } + if (target_window) { + [sc->stream_properties setWidth:(size_t) target_window.frame.size.width]; + [sc->stream_properties setHeight:(size_t) target_window.frame.size.height]; + } - } break; - case ScreenCaptureApplicationStream: { - SCDisplay *target_display = get_target_display(); - __block SCRunningApplication *target_application = nil; - { - [sc->shareable_content.applications - indexOfObjectPassingTest:^BOOL( - SCRunningApplication - *_Nonnull application, - NSUInteger idx, BOOL *_Nonnull stop) { - if ([application.bundleIdentifier - isEqualToString: - sc-> - application_id]) { - target_application = - sc->shareable_content - .applications - [idx]; - *stop = TRUE; - } - return *stop; - }]; - } - NSArray *target_application_array = [[NSArray alloc] - initWithObjects:target_application, nil]; + } break; + case ScreenCaptureApplicationStream: { + SCDisplay *target_display = get_target_display(); + __block SCRunningApplication *target_application = nil; + { + [sc->shareable_content.applications + indexOfObjectPassingTest:^BOOL(SCRunningApplication *_Nonnull application, NSUInteger idx, + BOOL *_Nonnull stop) { + if ([application.bundleIdentifier isEqualToString:sc->application_id]) { + target_application = sc->shareable_content.applications[idx]; + *stop = TRUE; + } + return *stop; + }]; + } + NSArray *target_application_array = [[NSArray alloc] initWithObjects:target_application, nil]; - NSArray *empty_array = [[NSArray alloc] init]; - content_filter = [[SCContentFilter alloc] - initWithDisplay:target_display - includingApplications:target_application_array - exceptingWindows:empty_array]; - [target_application_array release]; - [empty_array release]; + NSArray *empty_array = [[NSArray alloc] init]; + content_filter = [[SCContentFilter alloc] initWithDisplay:target_display + includingApplications:target_application_array + exceptingWindows:empty_array]; + [target_application_array release]; + [empty_array release]; - set_display_mode(sc, target_display); - } break; - } - os_sem_post(sc->shareable_content_available); + set_display_mode(sc, target_display); + } break; + } + os_sem_post(sc->shareable_content_available); - CGColorRef background = CGColorGetConstantColor(kCGColorClear); - [sc->stream_properties setQueueDepth:8]; - [sc->stream_properties setShowsCursor:!sc->hide_cursor]; - [sc->stream_properties setColorSpaceName:kCGColorSpaceDisplayP3]; - [sc->stream_properties setBackgroundColor:background]; - FourCharCode l10r_type = 0; - l10r_type = ('l' << 24) | ('1' << 16) | ('0' << 8) | 'r'; - [sc->stream_properties setPixelFormat:l10r_type]; + CGColorRef background = CGColorGetConstantColor(kCGColorClear); + [sc->stream_properties setQueueDepth:8]; + [sc->stream_properties setShowsCursor:!sc->hide_cursor]; + [sc->stream_properties setColorSpaceName:kCGColorSpaceDisplayP3]; + [sc->stream_properties setBackgroundColor:background]; + FourCharCode l10r_type = 0; + l10r_type = ('l' << 24) | ('1' << 16) | ('0' << 8) | 'r'; + [sc->stream_properties setPixelFormat:l10r_type]; - if (@available(macOS 13.0, *)) { + if (@available(macOS 13.0, *)) { #if __MAC_OS_X_VERSION_MAX_ALLOWED >= 130000 - [sc->stream_properties setCapturesAudio:TRUE]; - [sc->stream_properties setExcludesCurrentProcessAudio:TRUE]; - [sc->stream_properties setChannelCount:2]; + [sc->stream_properties setCapturesAudio:TRUE]; + [sc->stream_properties setExcludesCurrentProcessAudio:TRUE]; + [sc->stream_properties setChannelCount:2]; #endif - } else { - if (sc->capture_type != ScreenCaptureWindowStream) { - sc->disp = NULL; - [content_filter release]; - os_event_init(&sc->disp_finished, OS_EVENT_TYPE_MANUAL); - os_event_init(&sc->stream_start_completed, - OS_EVENT_TYPE_MANUAL); - return true; - } - } + } else { + if (sc->capture_type != ScreenCaptureWindowStream) { + sc->disp = NULL; + [content_filter release]; + os_event_init(&sc->disp_finished, OS_EVENT_TYPE_MANUAL); + os_event_init(&sc->stream_start_completed, OS_EVENT_TYPE_MANUAL); + return true; + } + } - sc->disp = [[SCStream alloc] initWithFilter:content_filter - configuration:sc->stream_properties - delegate:nil]; + sc->disp = [[SCStream alloc] initWithFilter:content_filter configuration:sc->stream_properties delegate:nil]; - [content_filter release]; + [content_filter release]; - NSError *addStreamOutputError = nil; - BOOL did_add_output = [sc->disp addStreamOutput:sc->capture_delegate - type:SCStreamOutputTypeScreen - sampleHandlerQueue:nil - error:&addStreamOutputError]; - if (!did_add_output) { - MACCAP_ERR( - "init_screen_stream: Failed to add stream output with error %s\n", - [[addStreamOutputError localizedFailureReason] - cStringUsingEncoding:NSUTF8StringEncoding]); - [addStreamOutputError release]; - return !did_add_output; - } + NSError *addStreamOutputError = nil; + BOOL did_add_output = [sc->disp addStreamOutput:sc->capture_delegate type:SCStreamOutputTypeScreen + sampleHandlerQueue:nil + error:&addStreamOutputError]; + if (!did_add_output) { + MACCAP_ERR("init_screen_stream: Failed to add stream output with error %s\n", + [[addStreamOutputError localizedFailureReason] cStringUsingEncoding:NSUTF8StringEncoding]); + [addStreamOutputError release]; + return !did_add_output; + } #if __MAC_OS_X_VERSION_MAX_ALLOWED >= 130000 - if (@available(macOS 13.0, *)) { - did_add_output = [sc->disp - addStreamOutput:sc->capture_delegate - type:SCStreamOutputTypeAudio - sampleHandlerQueue:nil - error:&addStreamOutputError]; - if (!did_add_output) { - MACCAP_ERR( - "init_screen_stream: Failed to add audio stream output with error %s\n", - [[addStreamOutputError localizedFailureReason] - cStringUsingEncoding: - NSUTF8StringEncoding]); - [addStreamOutputError release]; - return !did_add_output; - } - } + if (@available(macOS 13.0, *)) { + did_add_output = [sc->disp addStreamOutput:sc->capture_delegate type:SCStreamOutputTypeAudio + sampleHandlerQueue:nil + error:&addStreamOutputError]; + if (!did_add_output) { + MACCAP_ERR("init_screen_stream: Failed to add audio stream output with error %s\n", + [[addStreamOutputError localizedFailureReason] cStringUsingEncoding:NSUTF8StringEncoding]); + [addStreamOutputError release]; + return !did_add_output; + } + } #endif - os_event_init(&sc->disp_finished, OS_EVENT_TYPE_MANUAL); - os_event_init(&sc->stream_start_completed, OS_EVENT_TYPE_MANUAL); + os_event_init(&sc->disp_finished, OS_EVENT_TYPE_MANUAL); + os_event_init(&sc->stream_start_completed, OS_EVENT_TYPE_MANUAL); - __block BOOL did_stream_start = false; - [sc->disp startCaptureWithCompletionHandler:^( - NSError *_Nullable error) { - did_stream_start = (BOOL)(error == nil); - if (!did_stream_start) { - MACCAP_ERR( - "init_screen_stream: Failed to start capture with error %s\n", - [[error localizedFailureReason] - cStringUsingEncoding: - NSUTF8StringEncoding]); - // Clean up disp so it isn't stopped - [sc->disp release]; - sc->disp = NULL; - } - os_event_signal(sc->stream_start_completed); - }]; - os_event_wait(sc->stream_start_completed); + __block BOOL did_stream_start = false; + [sc->disp startCaptureWithCompletionHandler:^(NSError *_Nullable error) { + did_stream_start = (BOOL) (error == nil); + if (!did_stream_start) { + MACCAP_ERR("init_screen_stream: Failed to start capture with error %s\n", + [[error localizedFailureReason] cStringUsingEncoding:NSUTF8StringEncoding]); + // Clean up disp so it isn't stopped + [sc->disp release]; + sc->disp = NULL; + } + os_event_signal(sc->stream_start_completed); + }]; + os_event_wait(sc->stream_start_completed); - return did_stream_start; + return did_stream_start; } -static void screen_capture_build_content_list(struct screen_capture *sc, - bool display_capture) +static void screen_capture_build_content_list(struct screen_capture *sc, bool display_capture) { - typedef void (^shareable_content_callback)(SCShareableContent *, - NSError *); - shareable_content_callback new_content_received = ^void( - SCShareableContent *shareable_content, NSError *error) { - if (error == nil && sc->shareable_content_available != NULL) { - sc->shareable_content = [shareable_content retain]; - } else { + typedef void (^shareable_content_callback)(SCShareableContent *, NSError *); + shareable_content_callback new_content_received = ^void(SCShareableContent *shareable_content, NSError *error) { + if (error == nil && sc->shareable_content_available != NULL) { + sc->shareable_content = [shareable_content retain]; + } else { #ifdef DEBUG - MACCAP_ERR( - "screen_capture_properties: Failed to get shareable content with error %s\n", - [[error localizedFailureReason] - cStringUsingEncoding: - NSUTF8StringEncoding]); + MACCAP_ERR("screen_capture_properties: Failed to get shareable content with error %s\n", + [[error localizedFailureReason] cStringUsingEncoding:NSUTF8StringEncoding]); #endif - MACCAP_LOG( - LOG_WARNING, - "Unable to get list of available applications or windows. " - "Please check if OBS has necessary screen capture permissions."); - } - os_sem_post(sc->shareable_content_available); - }; + MACCAP_LOG(LOG_WARNING, "Unable to get list of available applications or windows. " + "Please check if OBS has necessary screen capture permissions."); + } + os_sem_post(sc->shareable_content_available); + }; - os_sem_wait(sc->shareable_content_available); - [sc->shareable_content release]; - [SCShareableContent - getShareableContentExcludingDesktopWindows:TRUE - onScreenWindowsOnly: - (display_capture - ? FALSE - : !sc->show_hidden_windows) - completionHandler:new_content_received]; + os_sem_wait(sc->shareable_content_available); + [sc->shareable_content release]; + [SCShareableContent getShareableContentExcludingDesktopWindows:TRUE + onScreenWindowsOnly:(display_capture ? FALSE : !sc->show_hidden_windows) + completionHandler:new_content_received]; } static void *screen_capture_create(obs_data_t *settings, obs_source_t *source) { - struct screen_capture *sc = bzalloc(sizeof(struct screen_capture)); + struct screen_capture *sc = bzalloc(sizeof(struct screen_capture)); - sc->source = source; - sc->hide_cursor = !obs_data_get_bool(settings, "show_cursor"); - sc->hide_obs = obs_data_get_bool(settings, "hide_obs"); - sc->show_empty_names = obs_data_get_bool(settings, "show_empty_names"); - sc->show_hidden_windows = - obs_data_get_bool(settings, "show_hidden_windows"); - sc->window = (CGWindowID)obs_data_get_int(settings, "window"); - sc->capture_type = (unsigned int)obs_data_get_int(settings, "type"); + sc->source = source; + sc->hide_cursor = !obs_data_get_bool(settings, "show_cursor"); + sc->hide_obs = obs_data_get_bool(settings, "hide_obs"); + sc->show_empty_names = obs_data_get_bool(settings, "show_empty_names"); + sc->show_hidden_windows = obs_data_get_bool(settings, "show_hidden_windows"); + sc->window = (CGWindowID) obs_data_get_int(settings, "window"); + sc->capture_type = (unsigned int) obs_data_get_int(settings, "type"); - os_sem_init(&sc->shareable_content_available, 1); - screen_capture_build_content_list( - sc, sc->capture_type == ScreenCaptureDisplayStream); + os_sem_init(&sc->shareable_content_available, 1); + screen_capture_build_content_list(sc, sc->capture_type == ScreenCaptureDisplayStream); - sc->capture_delegate = [[ScreenCaptureDelegate alloc] init]; - sc->capture_delegate.sc = sc; + sc->capture_delegate = [[ScreenCaptureDelegate alloc] init]; + sc->capture_delegate.sc = sc; - sc->effect = obs_get_base_effect(OBS_EFFECT_DEFAULT_RECT); - if (!sc->effect) - goto fail; + sc->effect = obs_get_base_effect(OBS_EFFECT_DEFAULT_RECT); + if (!sc->effect) + goto fail; - bool legacy_display_id = obs_data_has_user_value(settings, "display"); - if (legacy_display_id) { - CGDirectDisplayID display_id = - (CGDirectDisplayID)obs_data_get_int(settings, - "display"); - CFUUIDRef display_uuid = - CGDisplayCreateUUIDFromDisplayID(display_id); - CFStringRef uuid_string = - CFUUIDCreateString(kCFAllocatorDefault, display_uuid); - obs_data_set_string( - settings, "display_uuid", - CFStringGetCStringPtr(uuid_string, - kCFStringEncodingUTF8)); - obs_data_erase(settings, "display"); - CFRelease(uuid_string); - CFRelease(display_uuid); - } + bool legacy_display_id = obs_data_has_user_value(settings, "display"); + if (legacy_display_id) { + CGDirectDisplayID display_id = (CGDirectDisplayID) obs_data_get_int(settings, "display"); + CFUUIDRef display_uuid = CGDisplayCreateUUIDFromDisplayID(display_id); + CFStringRef uuid_string = CFUUIDCreateString(kCFAllocatorDefault, display_uuid); + obs_data_set_string(settings, "display_uuid", CFStringGetCStringPtr(uuid_string, kCFStringEncodingUTF8)); + obs_data_erase(settings, "display"); + CFRelease(uuid_string); + CFRelease(display_uuid); + } - const char *display_uuid = - obs_data_get_string(settings, "display_uuid"); - if (display_uuid) { - CFStringRef uuid_string = CFStringCreateWithCString( - kCFAllocatorDefault, display_uuid, - kCFStringEncodingUTF8); - CFUUIDRef uuid_ref = CFUUIDCreateFromString(kCFAllocatorDefault, - uuid_string); - sc->display = CGDisplayGetDisplayIDFromUUID(uuid_ref); - CFRelease(uuid_string); - CFRelease(uuid_ref); - } else { - sc->display = CGMainDisplayID(); - } + const char *display_uuid = obs_data_get_string(settings, "display_uuid"); + if (display_uuid) { + CFStringRef uuid_string = CFStringCreateWithCString(kCFAllocatorDefault, display_uuid, kCFStringEncodingUTF8); + CFUUIDRef uuid_ref = CFUUIDCreateFromString(kCFAllocatorDefault, uuid_string); + sc->display = CGDisplayGetDisplayIDFromUUID(uuid_ref); + CFRelease(uuid_string); + CFRelease(uuid_ref); + } else { + sc->display = CGMainDisplayID(); + } - sc->application_id = [[NSString alloc] - initWithUTF8String:obs_data_get_string(settings, - "application")]; - pthread_mutex_init(&sc->mutex, NULL); + sc->application_id = [[NSString alloc] initWithUTF8String:obs_data_get_string(settings, "application")]; + pthread_mutex_init(&sc->mutex, NULL); - if (!init_screen_stream(sc)) - goto fail; + if (!init_screen_stream(sc)) + goto fail; - return sc; + return sc; fail: - obs_leave_graphics(); - screen_capture_destroy(sc); - return NULL; + obs_leave_graphics(); + screen_capture_destroy(sc); + return NULL; } static void screen_capture_video_tick(void *data, float seconds __unused) { - struct screen_capture *sc = data; + struct screen_capture *sc = data; - if (!sc->current) - return; - if (!obs_source_showing(sc->source)) - return; + if (!sc->current) + return; + if (!obs_source_showing(sc->source)) + return; - IOSurfaceRef prev_prev = sc->prev; - if (pthread_mutex_lock(&sc->mutex)) - return; - sc->prev = sc->current; - sc->current = NULL; - pthread_mutex_unlock(&sc->mutex); + IOSurfaceRef prev_prev = sc->prev; + if (pthread_mutex_lock(&sc->mutex)) + return; + sc->prev = sc->current; + sc->current = NULL; + pthread_mutex_unlock(&sc->mutex); - if (prev_prev == sc->prev) - return; + if (prev_prev == sc->prev) + return; - obs_enter_graphics(); - if (sc->tex) - gs_texture_rebind_iosurface(sc->tex, sc->prev); - else - sc->tex = gs_texture_create_from_iosurface(sc->prev); - obs_leave_graphics(); + obs_enter_graphics(); + if (sc->tex) + gs_texture_rebind_iosurface(sc->tex, sc->prev); + else + sc->tex = gs_texture_create_from_iosurface(sc->prev); + obs_leave_graphics(); - if (prev_prev) { - IOSurfaceDecrementUseCount(prev_prev); - CFRelease(prev_prev); - } + if (prev_prev) { + IOSurfaceDecrementUseCount(prev_prev); + CFRelease(prev_prev); + } } -static void screen_capture_video_render(void *data, - gs_effect_t *effect __unused) +static void screen_capture_video_render(void *data, gs_effect_t *effect __unused) { - struct screen_capture *sc = data; + struct screen_capture *sc = data; - if (!sc->tex) - return; + if (!sc->tex) + return; - const bool previous = gs_framebuffer_srgb_enabled(); - gs_enable_framebuffer_srgb(true); + const bool previous = gs_framebuffer_srgb_enabled(); + gs_enable_framebuffer_srgb(true); - gs_eparam_t *param = gs_effect_get_param_by_name(sc->effect, "image"); - gs_effect_set_texture(param, sc->tex); + gs_eparam_t *param = gs_effect_get_param_by_name(sc->effect, "image"); + gs_effect_set_texture(param, sc->tex); - while (gs_effect_loop(sc->effect, "DrawD65P3")) - gs_draw_sprite(sc->tex, 0, 0, 0); + while (gs_effect_loop(sc->effect, "DrawD65P3")) + gs_draw_sprite(sc->tex, 0, 0, 0); - gs_enable_framebuffer_srgb(previous); + gs_enable_framebuffer_srgb(previous); } static const char *screen_capture_getname(void *unused __unused) { - if (@available(macOS 13.0, *)) - return obs_module_text("SCK.Name"); - else - return obs_module_text("SCK.Name.Beta"); + if (@available(macOS 13.0, *)) + return obs_module_text("SCK.Name"); + else + return obs_module_text("SCK.Name.Beta"); } static uint32_t screen_capture_getwidth(void *data) { - struct screen_capture *sc = data; + struct screen_capture *sc = data; - return (uint32_t)sc->frame.size.width; + return (uint32_t) sc->frame.size.width; } static uint32_t screen_capture_getheight(void *data) { - struct screen_capture *sc = data; + struct screen_capture *sc = data; - return (uint32_t)sc->frame.size.height; + return (uint32_t) sc->frame.size.height; } static void screen_capture_defaults(obs_data_t *settings) { - CGDirectDisplayID initial_display = 0; - { - NSScreen *mainScreen = [NSScreen mainScreen]; - if (mainScreen) { - NSNumber *screen_num = - mainScreen.deviceDescription[@"NSScreenNumber"]; - if (screen_num) { - initial_display = - (CGDirectDisplayID)(uintptr_t) - screen_num.pointerValue; - } - } - } + CGDirectDisplayID initial_display = 0; + { + NSScreen *mainScreen = [NSScreen mainScreen]; + if (mainScreen) { + NSNumber *screen_num = mainScreen.deviceDescription[@"NSScreenNumber"]; + if (screen_num) { + initial_display = (CGDirectDisplayID) (uintptr_t) screen_num.pointerValue; + } + } + } - CFUUIDRef display_uuid = - CGDisplayCreateUUIDFromDisplayID(initial_display); - CFStringRef uuid_string = - CFUUIDCreateString(kCFAllocatorDefault, display_uuid); - obs_data_set_default_string( - settings, "display_uuid", - CFStringGetCStringPtr(uuid_string, kCFStringEncodingUTF8)); - CFRelease(uuid_string); - CFRelease(display_uuid); + CFUUIDRef display_uuid = CGDisplayCreateUUIDFromDisplayID(initial_display); + CFStringRef uuid_string = CFUUIDCreateString(kCFAllocatorDefault, display_uuid); + obs_data_set_default_string(settings, "display_uuid", CFStringGetCStringPtr(uuid_string, kCFStringEncodingUTF8)); + CFRelease(uuid_string); + CFRelease(display_uuid); - obs_data_set_default_obj(settings, "application", NULL); - obs_data_set_default_int(settings, "type", ScreenCaptureDisplayStream); - obs_data_set_default_int(settings, "window", kCGNullWindowID); - obs_data_set_default_bool(settings, "show_cursor", true); - obs_data_set_default_bool(settings, "hide_obs", false); - obs_data_set_default_bool(settings, "show_empty_names", false); - obs_data_set_default_bool(settings, "show_hidden_windows", false); + obs_data_set_default_obj(settings, "application", NULL); + obs_data_set_default_int(settings, "type", ScreenCaptureDisplayStream); + obs_data_set_default_int(settings, "window", kCGNullWindowID); + obs_data_set_default_bool(settings, "show_cursor", true); + obs_data_set_default_bool(settings, "hide_obs", false); + obs_data_set_default_bool(settings, "show_empty_names", false); + obs_data_set_default_bool(settings, "show_hidden_windows", false); } static void screen_capture_update(void *data, obs_data_t *settings) { - struct screen_capture *sc = data; + struct screen_capture *sc = data; - CGWindowID old_window_id = sc->window; - CGWindowID new_window_id = - (CGWindowID)obs_data_get_int(settings, "window"); + CGWindowID old_window_id = sc->window; + CGWindowID new_window_id = (CGWindowID) obs_data_get_int(settings, "window"); - if (new_window_id > 0 && new_window_id != old_window_id) - sc->window = new_window_id; + if (new_window_id > 0 && new_window_id != old_window_id) + sc->window = new_window_id; - ScreenCaptureStreamType capture_type = - (ScreenCaptureStreamType)obs_data_get_int(settings, "type"); + ScreenCaptureStreamType capture_type = (ScreenCaptureStreamType) obs_data_get_int(settings, "type"); - CFStringRef uuid_string = CFStringCreateWithCString( - kCFAllocatorDefault, - obs_data_get_string(settings, "display_uuid"), - kCFStringEncodingUTF8); - CFUUIDRef display_uuid = - CFUUIDCreateFromString(kCFAllocatorDefault, uuid_string); - CGDirectDisplayID display = CGDisplayGetDisplayIDFromUUID(display_uuid); - CFRelease(uuid_string); - CFRelease(display_uuid); + CFStringRef uuid_string = CFStringCreateWithCString( + kCFAllocatorDefault, obs_data_get_string(settings, "display_uuid"), kCFStringEncodingUTF8); + CFUUIDRef display_uuid = CFUUIDCreateFromString(kCFAllocatorDefault, uuid_string); + CGDirectDisplayID display = CGDisplayGetDisplayIDFromUUID(display_uuid); + CFRelease(uuid_string); + CFRelease(display_uuid); - NSString *application_id = [[NSString alloc] - initWithUTF8String:obs_data_get_string(settings, - "application")]; - bool show_cursor = obs_data_get_bool(settings, "show_cursor"); - bool hide_obs = obs_data_get_bool(settings, "hide_obs"); - bool show_empty_names = obs_data_get_bool(settings, "show_empty_names"); - bool show_hidden_windows = - obs_data_get_bool(settings, "show_hidden_windows"); + NSString *application_id = [[NSString alloc] initWithUTF8String:obs_data_get_string(settings, "application")]; + bool show_cursor = obs_data_get_bool(settings, "show_cursor"); + bool hide_obs = obs_data_get_bool(settings, "hide_obs"); + bool show_empty_names = obs_data_get_bool(settings, "show_empty_names"); + bool show_hidden_windows = obs_data_get_bool(settings, "show_hidden_windows"); - if (capture_type == sc->capture_type) { - switch (sc->capture_type) { - case ScreenCaptureDisplayStream: { - if (sc->display == display && - sc->hide_cursor != show_cursor && - sc->hide_obs == hide_obs) { - [application_id release]; - return; - } - } break; - case ScreenCaptureWindowStream: { - if (old_window_id == sc->window && - sc->hide_cursor != show_cursor) { - [application_id release]; - return; - } - } break; - case ScreenCaptureApplicationStream: { - if (sc->display == display && - [application_id - isEqualToString:sc->application_id] && - sc->hide_cursor != show_cursor) { - [application_id release]; - return; - } - } break; - } - } + if (capture_type == sc->capture_type) { + switch (sc->capture_type) { + case ScreenCaptureDisplayStream: { + if (sc->display == display && sc->hide_cursor != show_cursor && sc->hide_obs == hide_obs) { + [application_id release]; + return; + } + } break; + case ScreenCaptureWindowStream: { + if (old_window_id == sc->window && sc->hide_cursor != show_cursor) { + [application_id release]; + return; + } + } break; + case ScreenCaptureApplicationStream: { + if (sc->display == display && [application_id isEqualToString:sc->application_id] && + sc->hide_cursor != show_cursor) { + [application_id release]; + return; + } + } break; + } + } - obs_enter_graphics(); + obs_enter_graphics(); - destroy_screen_stream(sc); - sc->capture_type = capture_type; - sc->display = display; - [sc->application_id release]; - sc->application_id = application_id; - sc->hide_cursor = !show_cursor; - sc->hide_obs = hide_obs; - sc->show_empty_names = show_empty_names; - sc->show_hidden_windows = show_hidden_windows; - init_screen_stream(sc); + destroy_screen_stream(sc); + sc->capture_type = capture_type; + sc->display = display; + [sc->application_id release]; + sc->application_id = application_id; + sc->hide_cursor = !show_cursor; + sc->hide_obs = hide_obs; + sc->show_empty_names = show_empty_names; + sc->show_hidden_windows = show_hidden_windows; + init_screen_stream(sc); - obs_leave_graphics(); + obs_leave_graphics(); } #pragma mark - obs_properties -static bool build_display_list(struct screen_capture *sc, - obs_properties_t *props) +static bool build_display_list(struct screen_capture *sc, obs_properties_t *props) { - os_sem_wait(sc->shareable_content_available); + os_sem_wait(sc->shareable_content_available); - obs_property_t *display_list = - obs_properties_get(props, "display_uuid"); - obs_property_list_clear(display_list); + obs_property_t *display_list = obs_properties_get(props, "display_uuid"); + obs_property_list_clear(display_list); - [sc->shareable_content.displays enumerateObjectsUsingBlock:^( - SCDisplay *_Nonnull display, - NSUInteger idx __unused, - BOOL *_Nonnull _stop __unused) { - NSUInteger screen_index = - [NSScreen.screens indexOfObjectPassingTest:^BOOL( - NSScreen *_Nonnull screen, - NSUInteger index __unused, - BOOL *_Nonnull stop) { - NSNumber *screen_num = - screen.deviceDescription - [@"NSScreenNumber"]; - CGDirectDisplayID screen_display_id = - (CGDirectDisplayID)screen_num.intValue; - *stop = (screen_display_id == - display.displayID); + [sc->shareable_content.displays enumerateObjectsUsingBlock:^(SCDisplay *_Nonnull display, NSUInteger idx __unused, + BOOL *_Nonnull _stop __unused) { + NSUInteger screen_index = [NSScreen.screens + indexOfObjectPassingTest:^BOOL(NSScreen *_Nonnull screen, NSUInteger index __unused, BOOL *_Nonnull stop) { + NSNumber *screen_num = screen.deviceDescription[@"NSScreenNumber"]; + CGDirectDisplayID screen_display_id = (CGDirectDisplayID) screen_num.intValue; + *stop = (screen_display_id == display.displayID); - return *stop; - }]; - NSScreen *screen = - [NSScreen.screens objectAtIndex:screen_index]; + return *stop; + }]; + NSScreen *screen = [NSScreen.screens objectAtIndex:screen_index]; - char dimension_buffer[4][12] = {}; - char name_buffer[256] = {}; - snprintf(dimension_buffer[0], sizeof(dimension_buffer[0]), "%u", - (uint32_t)screen.frame.size.width); - snprintf(dimension_buffer[1], sizeof(dimension_buffer[0]), "%u", - (uint32_t)screen.frame.size.height); - snprintf(dimension_buffer[2], sizeof(dimension_buffer[0]), "%d", - (int32_t)screen.frame.origin.x); - snprintf(dimension_buffer[3], sizeof(dimension_buffer[0]), "%d", - (int32_t)screen.frame.origin.y); + char dimension_buffer[4][12] = {}; + char name_buffer[256] = {}; + snprintf(dimension_buffer[0], sizeof(dimension_buffer[0]), "%u", (uint32_t) screen.frame.size.width); + snprintf(dimension_buffer[1], sizeof(dimension_buffer[0]), "%u", (uint32_t) screen.frame.size.height); + snprintf(dimension_buffer[2], sizeof(dimension_buffer[0]), "%d", (int32_t) screen.frame.origin.x); + snprintf(dimension_buffer[3], sizeof(dimension_buffer[0]), "%d", (int32_t) screen.frame.origin.y); - snprintf(name_buffer, sizeof(name_buffer), - "%.200s: %.12sx%.12s @ %.12s,%.12s", - screen.localizedName.UTF8String, dimension_buffer[0], - dimension_buffer[1], dimension_buffer[2], - dimension_buffer[3]); + snprintf(name_buffer, sizeof(name_buffer), "%.200s: %.12sx%.12s @ %.12s,%.12s", screen.localizedName.UTF8String, + dimension_buffer[0], dimension_buffer[1], dimension_buffer[2], dimension_buffer[3]); - CFUUIDRef display_uuid = - CGDisplayCreateUUIDFromDisplayID(display.displayID); - CFStringRef uuid_string = - CFUUIDCreateString(kCFAllocatorDefault, display_uuid); - obs_property_list_add_string( - display_list, name_buffer, - CFStringGetCStringPtr(uuid_string, - kCFStringEncodingUTF8)); - CFRelease(uuid_string); - CFRelease(display_uuid); - }]; + CFUUIDRef display_uuid = CGDisplayCreateUUIDFromDisplayID(display.displayID); + CFStringRef uuid_string = CFUUIDCreateString(kCFAllocatorDefault, display_uuid); + obs_property_list_add_string(display_list, name_buffer, + CFStringGetCStringPtr(uuid_string, kCFStringEncodingUTF8)); + CFRelease(uuid_string); + CFRelease(display_uuid); + }]; - os_sem_post(sc->shareable_content_available); - return true; + os_sem_post(sc->shareable_content_available); + return true; } -static bool build_window_list(struct screen_capture *sc, - obs_properties_t *props) +static bool build_window_list(struct screen_capture *sc, obs_properties_t *props) { - os_sem_wait(sc->shareable_content_available); + os_sem_wait(sc->shareable_content_available); - obs_property_t *window_list = obs_properties_get(props, "window"); - obs_property_list_clear(window_list); + obs_property_t *window_list = obs_properties_get(props, "window"); + obs_property_list_clear(window_list); - NSArray *filteredWindows; - filteredWindows = [sc->shareable_content.windows - filteredArrayUsingPredicate: - [NSPredicate predicateWithBlock:^BOOL( - SCWindow *window, - NSDictionary *bindings __unused) { - NSString *app_name = - window.owningApplication.applicationName; - NSString *title = window.title; - if (!sc->show_empty_names) { - if (app_name == NULL || title == NULL) { - return false; - } else if ([app_name - isEqualToString:@""] || - [title isEqualToString:@""]) { - return false; - } - } - return true; - }]]; + NSArray *filteredWindows; + filteredWindows = [sc->shareable_content.windows + filteredArrayUsingPredicate:[NSPredicate predicateWithBlock:^BOOL(SCWindow *window, + NSDictionary *bindings __unused) { + NSString *app_name = window.owningApplication.applicationName; + NSString *title = window.title; + if (!sc->show_empty_names) { + if (app_name == NULL || title == NULL) { + return false; + } else if ([app_name isEqualToString:@""] || [title isEqualToString:@""]) { + return false; + } + } + return true; + }]]; - NSArray *sortedWindows; - sortedWindows = - [filteredWindows sortedArrayUsingComparator:^NSComparisonResult( - SCWindow *window, SCWindow *other) { - NSComparisonResult appNameCmp = - [window.owningApplication.applicationName - compare:other.owningApplication - .applicationName - options:NSCaseInsensitiveSearch]; - if (appNameCmp == NSOrderedAscending) { - return NSOrderedAscending; - } else if (appNameCmp == NSOrderedSame) { - return [window.title - compare:other.title - options:NSCaseInsensitiveSearch]; - } else { - return NSOrderedDescending; - } - }]; + NSArray *sortedWindows; + sortedWindows = [filteredWindows sortedArrayUsingComparator:^NSComparisonResult(SCWindow *window, SCWindow *other) { + NSComparisonResult appNameCmp = [window.owningApplication.applicationName + compare:other.owningApplication.applicationName + options:NSCaseInsensitiveSearch]; + if (appNameCmp == NSOrderedAscending) { + return NSOrderedAscending; + } else if (appNameCmp == NSOrderedSame) { + return [window.title compare:other.title options:NSCaseInsensitiveSearch]; + } else { + return NSOrderedDescending; + } + }]; - [sortedWindows enumerateObjectsUsingBlock:^( - SCWindow *_Nonnull window, - NSUInteger idx __unused, - BOOL *_Nonnull stop __unused) { - NSString *app_name = window.owningApplication.applicationName; - NSString *title = window.title; + [sortedWindows + enumerateObjectsUsingBlock:^(SCWindow *_Nonnull window, NSUInteger idx __unused, BOOL *_Nonnull stop __unused) { + NSString *app_name = window.owningApplication.applicationName; + NSString *title = window.title; - const char *list_text = - [[NSString stringWithFormat:@"[%@] %@", app_name, title] - UTF8String]; - obs_property_list_add_int(window_list, list_text, - window.windowID); - }]; + const char *list_text = [[NSString stringWithFormat:@"[%@] %@", app_name, title] UTF8String]; + obs_property_list_add_int(window_list, list_text, window.windowID); + }]; - os_sem_post(sc->shareable_content_available); - return true; + os_sem_post(sc->shareable_content_available); + return true; } -static bool build_application_list(struct screen_capture *sc, - obs_properties_t *props) +static bool build_application_list(struct screen_capture *sc, obs_properties_t *props) { - os_sem_wait(sc->shareable_content_available); + os_sem_wait(sc->shareable_content_available); - obs_property_t *application_list = - obs_properties_get(props, "application"); - obs_property_list_clear(application_list); + obs_property_t *application_list = obs_properties_get(props, "application"); + obs_property_list_clear(application_list); - NSArray *filteredApplications; - filteredApplications = [sc->shareable_content.applications - filteredArrayUsingPredicate: - [NSPredicate predicateWithBlock:^BOOL( - SCRunningApplication *app, - NSDictionary *bindings __unused) { - const char *name = - [app.applicationName UTF8String]; - if (strcmp(name, "") == 0) { - return false; - } - return true; - }]]; + NSArray *filteredApplications; + filteredApplications = [sc->shareable_content.applications + filteredArrayUsingPredicate:[NSPredicate predicateWithBlock:^BOOL(SCRunningApplication *app, + NSDictionary *bindings __unused) { + const char *name = [app.applicationName UTF8String]; + if (strcmp(name, "") == 0) { + return false; + } + return true; + }]]; - NSArray *sortedApplications; - sortedApplications = [filteredApplications - sortedArrayUsingComparator:^NSComparisonResult( - SCRunningApplication *app, - SCRunningApplication *other) { - return [app.applicationName - compare:other.applicationName - options:NSCaseInsensitiveSearch]; - }]; + NSArray *sortedApplications; + sortedApplications = [filteredApplications + sortedArrayUsingComparator:^NSComparisonResult(SCRunningApplication *app, SCRunningApplication *other) { + return [app.applicationName compare:other.applicationName options:NSCaseInsensitiveSearch]; + }]; - [sortedApplications enumerateObjectsUsingBlock:^( - SCRunningApplication *_Nonnull application, - NSUInteger idx __unused, - BOOL *_Nonnull stop __unused) { - const char *name = [application.applicationName UTF8String]; - const char *bundle_id = - [application.bundleIdentifier UTF8String]; - obs_property_list_add_string(application_list, name, bundle_id); - }]; + [sortedApplications enumerateObjectsUsingBlock:^(SCRunningApplication *_Nonnull application, + NSUInteger idx __unused, BOOL *_Nonnull stop __unused) { + const char *name = [application.applicationName UTF8String]; + const char *bundle_id = [application.bundleIdentifier UTF8String]; + obs_property_list_add_string(application_list, name, bundle_id); + }]; - os_sem_post(sc->shareable_content_available); - return true; + os_sem_post(sc->shareable_content_available); + return true; } -static bool content_settings_changed(void *data, obs_properties_t *props, - obs_property_t *list __unused, - obs_data_t *settings) +static bool content_settings_changed(void *data, obs_properties_t *props, obs_property_t *list __unused, + obs_data_t *settings) { - struct screen_capture *sc = data; + struct screen_capture *sc = data; - unsigned int capture_type_id = - (unsigned int)obs_data_get_int(settings, "type"); - obs_property_t *display_list = - obs_properties_get(props, "display_uuid"); - obs_property_t *window_list = obs_properties_get(props, "window"); - obs_property_t *app_list = obs_properties_get(props, "application"); - obs_property_t *empty = obs_properties_get(props, "show_empty_names"); - obs_property_t *hidden = - obs_properties_get(props, "show_hidden_windows"); - obs_property_t *hide_obs = obs_properties_get(props, "hide_obs"); + unsigned int capture_type_id = (unsigned int) obs_data_get_int(settings, "type"); + obs_property_t *display_list = obs_properties_get(props, "display_uuid"); + obs_property_t *window_list = obs_properties_get(props, "window"); + obs_property_t *app_list = obs_properties_get(props, "application"); + obs_property_t *empty = obs_properties_get(props, "show_empty_names"); + obs_property_t *hidden = obs_properties_get(props, "show_hidden_windows"); + obs_property_t *hide_obs = obs_properties_get(props, "hide_obs"); - obs_property_t *capture_type_error = - obs_properties_get(props, "capture_type_info"); + obs_property_t *capture_type_error = obs_properties_get(props, "capture_type_info"); - if (sc->capture_type != capture_type_id) { - switch (capture_type_id) { - case 0: { - obs_property_set_visible(display_list, true); - obs_property_set_visible(window_list, false); - obs_property_set_visible(app_list, false); - obs_property_set_visible(empty, false); - obs_property_set_visible(hidden, false); - obs_property_set_visible(hide_obs, true); + if (sc->capture_type != capture_type_id) { + switch (capture_type_id) { + case 0: { + obs_property_set_visible(display_list, true); + obs_property_set_visible(window_list, false); + obs_property_set_visible(app_list, false); + obs_property_set_visible(empty, false); + obs_property_set_visible(hidden, false); + obs_property_set_visible(hide_obs, true); - if (capture_type_error) { - obs_property_set_visible(capture_type_error, - true); - } - break; - } - case 1: { - obs_property_set_visible(display_list, false); - obs_property_set_visible(window_list, true); - obs_property_set_visible(app_list, false); - obs_property_set_visible(empty, true); - obs_property_set_visible(hidden, true); - obs_property_set_visible(hide_obs, false); + if (capture_type_error) { + obs_property_set_visible(capture_type_error, true); + } + break; + } + case 1: { + obs_property_set_visible(display_list, false); + obs_property_set_visible(window_list, true); + obs_property_set_visible(app_list, false); + obs_property_set_visible(empty, true); + obs_property_set_visible(hidden, true); + obs_property_set_visible(hide_obs, false); - if (capture_type_error) { - obs_property_set_visible(capture_type_error, - false); - } - break; - } - case 2: { - obs_property_set_visible(display_list, true); - obs_property_set_visible(app_list, true); - obs_property_set_visible(window_list, false); - obs_property_set_visible(empty, false); - obs_property_set_visible(hidden, true); - obs_property_set_visible(hide_obs, false); + if (capture_type_error) { + obs_property_set_visible(capture_type_error, false); + } + break; + } + case 2: { + obs_property_set_visible(display_list, true); + obs_property_set_visible(app_list, true); + obs_property_set_visible(window_list, false); + obs_property_set_visible(empty, false); + obs_property_set_visible(hidden, true); + obs_property_set_visible(hide_obs, false); - if (capture_type_error) { - obs_property_set_visible(capture_type_error, - true); - } - break; - } - } - } + if (capture_type_error) { + obs_property_set_visible(capture_type_error, true); + } + break; + } + } + } - screen_capture_build_content_list( - sc, capture_type_id == ScreenCaptureDisplayStream); - build_display_list(sc, props); - build_window_list(sc, props); - build_application_list(sc, props); + screen_capture_build_content_list(sc, capture_type_id == ScreenCaptureDisplayStream); + build_display_list(sc, props); + build_window_list(sc, props); + build_application_list(sc, props); - sc->show_empty_names = obs_data_get_bool(settings, "show_empty_names"); - sc->show_hidden_windows = - obs_data_get_bool(settings, "show_hidden_windows"); + sc->show_empty_names = obs_data_get_bool(settings, "show_empty_names"); + sc->show_hidden_windows = obs_data_get_bool(settings, "show_hidden_windows"); - sc->hide_obs = obs_data_get_bool(settings, "hide_obs"); + sc->hide_obs = obs_data_get_bool(settings, "hide_obs"); - return true; + return true; } static obs_properties_t *screen_capture_properties(void *data) { - struct screen_capture *sc = data; + struct screen_capture *sc = data; - obs_properties_t *props = obs_properties_create(); + obs_properties_t *props = obs_properties_create(); - obs_property_t *capture_type = obs_properties_add_list( - props, "type", obs_module_text("SCK.Method"), - OBS_COMBO_TYPE_LIST, OBS_COMBO_FORMAT_INT); + obs_property_t *capture_type = obs_properties_add_list(props, "type", obs_module_text("SCK.Method"), + OBS_COMBO_TYPE_LIST, OBS_COMBO_FORMAT_INT); - obs_property_list_add_int(capture_type, - obs_module_text("DisplayCapture"), 0); - obs_property_list_add_int(capture_type, - obs_module_text("WindowCapture"), 1); - obs_property_list_add_int(capture_type, - obs_module_text("ApplicationCapture"), 2); + obs_property_list_add_int(capture_type, obs_module_text("DisplayCapture"), 0); + obs_property_list_add_int(capture_type, obs_module_text("WindowCapture"), 1); + obs_property_list_add_int(capture_type, obs_module_text("ApplicationCapture"), 2); - obs_property_t *display_list = obs_properties_add_list( - props, "display_uuid", - obs_module_text("DisplayCapture.Display"), OBS_COMBO_TYPE_LIST, - OBS_COMBO_FORMAT_STRING); + obs_property_t *display_list = obs_properties_add_list( + props, "display_uuid", obs_module_text("DisplayCapture.Display"), OBS_COMBO_TYPE_LIST, OBS_COMBO_FORMAT_STRING); - obs_property_t *app_list = obs_properties_add_list( - props, "application", obs_module_text("Application"), - OBS_COMBO_TYPE_LIST, OBS_COMBO_FORMAT_STRING); + obs_property_t *app_list = obs_properties_add_list(props, "application", obs_module_text("Application"), + OBS_COMBO_TYPE_LIST, OBS_COMBO_FORMAT_STRING); - obs_property_t *window_list = obs_properties_add_list( - props, "window", obs_module_text("WindowUtils.Window"), - OBS_COMBO_TYPE_LIST, OBS_COMBO_FORMAT_INT); + obs_property_t *window_list = obs_properties_add_list(props, "window", obs_module_text("WindowUtils.Window"), + OBS_COMBO_TYPE_LIST, OBS_COMBO_FORMAT_INT); - obs_property_t *empty = obs_properties_add_bool( - props, "show_empty_names", - obs_module_text("WindowUtils.ShowEmptyNames")); + obs_property_t *empty = + obs_properties_add_bool(props, "show_empty_names", obs_module_text("WindowUtils.ShowEmptyNames")); - obs_property_t *hidden = obs_properties_add_bool( - props, "show_hidden_windows", - obs_module_text("WindowUtils.ShowHidden")); + obs_property_t *hidden = + obs_properties_add_bool(props, "show_hidden_windows", obs_module_text("WindowUtils.ShowHidden")); - obs_properties_add_bool(props, "show_cursor", - obs_module_text("DisplayCapture.ShowCursor")); + obs_properties_add_bool(props, "show_cursor", obs_module_text("DisplayCapture.ShowCursor")); - obs_property_t *hide_obs = obs_properties_add_bool( - props, "hide_obs", obs_module_text("DisplayCapture.HideOBS")); + obs_property_t *hide_obs = obs_properties_add_bool(props, "hide_obs", obs_module_text("DisplayCapture.HideOBS")); - if (sc) { - obs_property_set_modified_callback2( - capture_type, content_settings_changed, sc); + if (sc) { + obs_property_set_modified_callback2(capture_type, content_settings_changed, sc); - obs_property_set_modified_callback2( - hidden, content_settings_changed, sc); + obs_property_set_modified_callback2(hidden, content_settings_changed, sc); - switch (sc->capture_type) { - case 0: { - obs_property_set_visible(display_list, true); - obs_property_set_visible(window_list, false); - obs_property_set_visible(app_list, false); - obs_property_set_visible(empty, false); - obs_property_set_visible(hidden, false); - obs_property_set_visible(hide_obs, true); - break; - } - case 1: { - obs_property_set_visible(display_list, false); - obs_property_set_visible(window_list, true); - obs_property_set_visible(app_list, false); - obs_property_set_visible(empty, true); - obs_property_set_visible(hidden, true); - obs_property_set_visible(hide_obs, false); - break; - } - case 2: { - obs_property_set_visible(display_list, true); - obs_property_set_visible(app_list, true); - obs_property_set_visible(window_list, false); - obs_property_set_visible(empty, false); - obs_property_set_visible(hidden, true); - obs_property_set_visible(hide_obs, false); - break; - } - } + switch (sc->capture_type) { + case 0: { + obs_property_set_visible(display_list, true); + obs_property_set_visible(window_list, false); + obs_property_set_visible(app_list, false); + obs_property_set_visible(empty, false); + obs_property_set_visible(hidden, false); + obs_property_set_visible(hide_obs, true); + break; + } + case 1: { + obs_property_set_visible(display_list, false); + obs_property_set_visible(window_list, true); + obs_property_set_visible(app_list, false); + obs_property_set_visible(empty, true); + obs_property_set_visible(hidden, true); + obs_property_set_visible(hide_obs, false); + break; + } + case 2: { + obs_property_set_visible(display_list, true); + obs_property_set_visible(app_list, true); + obs_property_set_visible(window_list, false); + obs_property_set_visible(empty, false); + obs_property_set_visible(hidden, true); + obs_property_set_visible(hide_obs, false); + break; + } + } - obs_property_set_modified_callback2( - empty, content_settings_changed, sc); - } + obs_property_set_modified_callback2(empty, content_settings_changed, sc); + } - if (@available(macOS 13.0, *)) - ; - else { - obs_property_t *audio_warning = obs_properties_add_text( - props, "audio_info", - obs_module_text("SCK.AudioUnavailable"), OBS_TEXT_INFO); - obs_property_text_set_info_type(audio_warning, - OBS_TEXT_INFO_WARNING); + if (@available(macOS 13.0, *)) + ; + else { + obs_property_t *audio_warning = + obs_properties_add_text(props, "audio_info", obs_module_text("SCK.AudioUnavailable"), OBS_TEXT_INFO); + obs_property_text_set_info_type(audio_warning, OBS_TEXT_INFO_WARNING); - obs_property_t *capture_type_error = obs_properties_add_text( - props, "capture_type_info", - obs_module_text("SCK.CaptureTypeUnavailable"), - OBS_TEXT_INFO); + obs_property_t *capture_type_error = obs_properties_add_text( + props, "capture_type_info", obs_module_text("SCK.CaptureTypeUnavailable"), OBS_TEXT_INFO); - obs_property_text_set_info_type(capture_type_error, - OBS_TEXT_INFO_ERROR); + obs_property_text_set_info_type(capture_type_error, OBS_TEXT_INFO_ERROR); - if (sc) { - switch (sc->capture_type) { - case ScreenCaptureDisplayStream: { - obs_property_set_visible(capture_type_error, - true); - break; - } - case ScreenCaptureWindowStream: { - obs_property_set_visible(capture_type_error, - false); - break; - } - case ScreenCaptureApplicationStream: { - obs_property_set_visible(capture_type_error, - true); - break; - } - } - } else { - obs_property_set_visible(capture_type_error, false); - } - } + if (sc) { + switch (sc->capture_type) { + case ScreenCaptureDisplayStream: { + obs_property_set_visible(capture_type_error, true); + break; + } + case ScreenCaptureWindowStream: { + obs_property_set_visible(capture_type_error, false); + break; + } + case ScreenCaptureApplicationStream: { + obs_property_set_visible(capture_type_error, true); + break; + } + } + } else { + obs_property_set_visible(capture_type_error, false); + } + } - return props; + return props; } -enum gs_color_space screen_capture_video_get_color_space( - void *data, size_t count, const enum gs_color_space *preferred_spaces) +enum gs_color_space screen_capture_video_get_color_space(void *data, size_t count, + const enum gs_color_space *preferred_spaces) { - UNUSED_PARAMETER(data); + UNUSED_PARAMETER(data); - for (size_t i = 0; i < count; ++i) { - if (preferred_spaces[i] == GS_CS_SRGB_16F) - return GS_CS_SRGB_16F; - } + for (size_t i = 0; i < count; ++i) { + if (preferred_spaces[i] == GS_CS_SRGB_16F) + return GS_CS_SRGB_16F; + } - for (size_t i = 0; i < count; ++i) { - if (preferred_spaces[i] == GS_CS_709_EXTENDED) - return GS_CS_709_EXTENDED; - } + for (size_t i = 0; i < count; ++i) { + if (preferred_spaces[i] == GS_CS_709_EXTENDED) + return GS_CS_709_EXTENDED; + } - for (size_t i = 0; i < count; ++i) { - if (preferred_spaces[i] == GS_CS_SRGB) - return GS_CS_SRGB; - } + for (size_t i = 0; i < count; ++i) { + if (preferred_spaces[i] == GS_CS_SRGB) + return GS_CS_SRGB; + } - return GS_CS_SRGB_16F; + return GS_CS_SRGB_16F; } #pragma mark - obs_source_info struct obs_source_info screen_capture_info = { - .id = "screen_capture", - .type = OBS_SOURCE_TYPE_INPUT, - .get_name = screen_capture_getname, + .id = "screen_capture", + .type = OBS_SOURCE_TYPE_INPUT, + .get_name = screen_capture_getname, - .create = screen_capture_create, - .destroy = screen_capture_destroy, + .create = screen_capture_create, + .destroy = screen_capture_destroy, - .output_flags = OBS_SOURCE_VIDEO | OBS_SOURCE_CUSTOM_DRAW | - OBS_SOURCE_DO_NOT_DUPLICATE | OBS_SOURCE_SRGB | - OBS_SOURCE_AUDIO, - .video_tick = screen_capture_video_tick, - .video_render = screen_capture_video_render, + .output_flags = OBS_SOURCE_VIDEO | OBS_SOURCE_CUSTOM_DRAW | OBS_SOURCE_DO_NOT_DUPLICATE | OBS_SOURCE_SRGB | + OBS_SOURCE_AUDIO, + .video_tick = screen_capture_video_tick, + .video_render = screen_capture_video_render, - .get_width = screen_capture_getwidth, - .get_height = screen_capture_getheight, + .get_width = screen_capture_getwidth, + .get_height = screen_capture_getheight, - .get_defaults = screen_capture_defaults, - .get_properties = screen_capture_properties, - .update = screen_capture_update, - .icon_type = OBS_ICON_TYPE_DESKTOP_CAPTURE, - .video_get_color_space = screen_capture_video_get_color_space, + .get_defaults = screen_capture_defaults, + .get_properties = screen_capture_properties, + .update = screen_capture_update, + .icon_type = OBS_ICON_TYPE_DESKTOP_CAPTURE, + .video_get_color_space = screen_capture_video_get_color_space, }; #pragma mark - ScreenCaptureDelegate @implementation ScreenCaptureDelegate -- (void)stream:(SCStream *)stream - didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer - ofType:(SCStreamOutputType)type +- (void)stream:(SCStream *)stream didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer ofType:(SCStreamOutputType)type { - if (self.sc != NULL) { - if (type == SCStreamOutputTypeScreen) { - screen_stream_video_update(self.sc, sampleBuffer); - } + if (self.sc != NULL) { + if (type == SCStreamOutputTypeScreen) { + screen_stream_video_update(self.sc, sampleBuffer); + } #if __MAC_OS_X_VERSION_MAX_ALLOWED >= 130000 - else if (@available(macOS 13.0, *)) { - if (type == SCStreamOutputTypeAudio) { - screen_stream_audio_update(self.sc, - sampleBuffer); - } - } + else if (@available(macOS 13.0, *)) { + if (type == SCStreamOutputTypeAudio) { + screen_stream_audio_update(self.sc, sampleBuffer); + } + } #endif - } + } } @end diff --git a/plugins/mac-capture/mac-window-capture.m b/plugins/mac-capture/mac-window-capture.m index e6a958186..ab227fb6a 100644 --- a/plugins/mac-capture/mac-window-capture.m +++ b/plugins/mac-capture/mac-window-capture.m @@ -9,226 +9,215 @@ #include "window-utils.h" struct window_capture { - obs_source_t *source; + obs_source_t *source; - struct cocoa_window window; + struct cocoa_window window; - //CGRect bounds; - //CGWindowListOption window_option; - CGWindowImageOption image_option; + //CGRect bounds; + //CGWindowListOption window_option; + CGWindowImageOption image_option; - CGColorSpaceRef color_space; + CGColorSpaceRef color_space; - DARRAY(uint8_t) buffer; + DARRAY(uint8_t) buffer; - pthread_t capture_thread; - os_event_t *capture_event; - os_event_t *stop_event; + pthread_t capture_thread; + os_event_t *capture_event; + os_event_t *stop_event; }; static CGImageRef get_image(struct window_capture *wc) { - NSArray *arr = (NSArray *)CGWindowListCreate( - kCGWindowListOptionIncludingWindow, wc->window.window_id); - [arr autorelease]; + NSArray *arr = (NSArray *) CGWindowListCreate(kCGWindowListOptionIncludingWindow, wc->window.window_id); + [arr autorelease]; - if (!arr.count && !find_window(&wc->window, NULL, false)) - return NULL; + if (!arr.count && !find_window(&wc->window, NULL, false)) + return NULL; - return CGWindowListCreateImage(CGRectNull, - kCGWindowListOptionIncludingWindow, - wc->window.window_id, wc->image_option); + return CGWindowListCreateImage(CGRectNull, kCGWindowListOptionIncludingWindow, wc->window.window_id, + wc->image_option); } static inline void capture_frame(struct window_capture *wc) { - uint64_t ts = os_gettime_ns(); - CGImageRef img = get_image(wc); - if (!img) - return; + uint64_t ts = os_gettime_ns(); + CGImageRef img = get_image(wc); + if (!img) + return; - size_t width = CGImageGetWidth(img); - size_t height = CGImageGetHeight(img); + size_t width = CGImageGetWidth(img); + size_t height = CGImageGetHeight(img); - if (!width || !height || CGImageGetBitsPerPixel(img) != 32 || - CGImageGetBitsPerComponent(img) != 8) { - CGImageRelease(img); - return; - } + if (!width || !height || CGImageGetBitsPerPixel(img) != 32 || CGImageGetBitsPerComponent(img) != 8) { + CGImageRelease(img); + return; + } - CGDataProviderRef provider = CGImageGetDataProvider(img); - CFDataRef data = CGDataProviderCopyData(provider); + CGDataProviderRef provider = CGImageGetDataProvider(img); + CFDataRef data = CGDataProviderCopyData(provider); - struct obs_source_frame frame = { - .format = VIDEO_FORMAT_BGRA, - .width = (uint32_t)width, - .height = (uint32_t)height, - .data[0] = (uint8_t *)CFDataGetBytePtr(data), - .linesize[0] = (uint32_t)CGImageGetBytesPerRow(img), - .timestamp = ts, - }; + struct obs_source_frame frame = { + .format = VIDEO_FORMAT_BGRA, + .width = (uint32_t) width, + .height = (uint32_t) height, + .data[0] = (uint8_t *) CFDataGetBytePtr(data), + .linesize[0] = (uint32_t) CGImageGetBytesPerRow(img), + .timestamp = ts, + }; - obs_source_output_video(wc->source, &frame); + obs_source_output_video(wc->source, &frame); - CGImageRelease(img); - CFRelease(data); + CGImageRelease(img); + CFRelease(data); } static void *capture_thread(void *data) { - struct window_capture *wc = data; + struct window_capture *wc = data; - for (;;) { - os_event_wait(wc->capture_event); - if (os_event_try(wc->stop_event) != EAGAIN) - break; + for (;;) { + os_event_wait(wc->capture_event); + if (os_event_try(wc->stop_event) != EAGAIN) + break; - @autoreleasepool { - capture_frame(wc); - } - } + @autoreleasepool { + capture_frame(wc); + } + } - return NULL; + return NULL; } -static inline void *window_capture_create_internal(obs_data_t *settings, - obs_source_t *source) +static inline void *window_capture_create_internal(obs_data_t *settings, obs_source_t *source) { - struct window_capture *wc = bzalloc(sizeof(struct window_capture)); + struct window_capture *wc = bzalloc(sizeof(struct window_capture)); - wc->source = source; + wc->source = source; - wc->color_space = CGColorSpaceCreateDeviceRGB(); + wc->color_space = CGColorSpaceCreateDeviceRGB(); - da_init(wc->buffer); + da_init(wc->buffer); - init_window(&wc->window, settings); + init_window(&wc->window, settings); - wc->image_option = obs_data_get_bool(settings, "show_shadow") - ? kCGWindowImageDefault - : kCGWindowImageBoundsIgnoreFraming; + wc->image_option = obs_data_get_bool(settings, "show_shadow") ? kCGWindowImageDefault + : kCGWindowImageBoundsIgnoreFraming; - os_event_init(&wc->capture_event, OS_EVENT_TYPE_AUTO); - os_event_init(&wc->stop_event, OS_EVENT_TYPE_MANUAL); + os_event_init(&wc->capture_event, OS_EVENT_TYPE_AUTO); + os_event_init(&wc->stop_event, OS_EVENT_TYPE_MANUAL); - pthread_create(&wc->capture_thread, NULL, capture_thread, wc); + pthread_create(&wc->capture_thread, NULL, capture_thread, wc); - return wc; + return wc; } static void *window_capture_create(obs_data_t *settings, obs_source_t *source) { - @autoreleasepool { - return window_capture_create_internal(settings, source); - } + @autoreleasepool { + return window_capture_create_internal(settings, source); + } } static void window_capture_destroy(void *data) { - struct window_capture *cap = data; + struct window_capture *cap = data; - os_event_signal(cap->stop_event); - os_event_signal(cap->capture_event); + os_event_signal(cap->stop_event); + os_event_signal(cap->capture_event); - pthread_join(cap->capture_thread, NULL); + pthread_join(cap->capture_thread, NULL); - CGColorSpaceRelease(cap->color_space); + CGColorSpaceRelease(cap->color_space); - da_free(cap->buffer); + da_free(cap->buffer); - os_event_destroy(cap->capture_event); - os_event_destroy(cap->stop_event); + os_event_destroy(cap->capture_event); + os_event_destroy(cap->stop_event); - destroy_window(&cap->window); + destroy_window(&cap->window); - bfree(cap); + bfree(cap); } static void window_capture_defaults(obs_data_t *settings) { - obs_data_set_default_bool(settings, "show_shadow", false); - window_defaults(settings); + obs_data_set_default_bool(settings, "show_shadow", false); + window_defaults(settings); } static obs_properties_t *window_capture_properties(void *unused) { - UNUSED_PARAMETER(unused); + UNUSED_PARAMETER(unused); - obs_properties_t *props = obs_properties_create(); + obs_properties_t *props = obs_properties_create(); - add_window_properties(props); + add_window_properties(props); - obs_properties_add_bool(props, "show_shadow", - obs_module_text("WindowCapture.ShowShadow")); + obs_properties_add_bool(props, "show_shadow", obs_module_text("WindowCapture.ShowShadow")); - return props; + return props; } -static inline void window_capture_update_internal(struct window_capture *wc, - obs_data_t *settings) +static inline void window_capture_update_internal(struct window_capture *wc, obs_data_t *settings) { - wc->image_option = obs_data_get_bool(settings, "show_shadow") - ? kCGWindowImageDefault - : kCGWindowImageBoundsIgnoreFraming; + wc->image_option = obs_data_get_bool(settings, "show_shadow") ? kCGWindowImageDefault + : kCGWindowImageBoundsIgnoreFraming; - update_window(&wc->window, settings); + update_window(&wc->window, settings); - if (wc->window.window_name.length) { - blog(LOG_INFO, - "[window-capture: '%s'] update settings:\n" - "\twindow: %s\n" - "\towner: %s", - obs_source_get_name(wc->source), - [wc->window.window_name UTF8String], - [wc->window.owner_name UTF8String]); - } + if (wc->window.window_name.length) { + blog(LOG_INFO, + "[window-capture: '%s'] update settings:\n" + "\twindow: %s\n" + "\towner: %s", + obs_source_get_name(wc->source), [wc->window.window_name UTF8String], [wc->window.owner_name UTF8String]); + } } static void window_capture_update(void *data, obs_data_t *settings) { - @autoreleasepool { - return window_capture_update_internal(data, settings); - } + @autoreleasepool { + return window_capture_update_internal(data, settings); + } } static const char *window_capture_getname(void *unused) { - UNUSED_PARAMETER(unused); - return obs_module_text("WindowCapture"); + UNUSED_PARAMETER(unused); + return obs_module_text("WindowCapture"); } -static inline void window_capture_tick_internal(struct window_capture *wc, - float seconds) +static inline void window_capture_tick_internal(struct window_capture *wc, float seconds) { - UNUSED_PARAMETER(seconds); - os_event_signal(wc->capture_event); + UNUSED_PARAMETER(seconds); + os_event_signal(wc->capture_event); } static void window_capture_tick(void *data, float seconds) { - struct window_capture *wc = data; + struct window_capture *wc = data; - if (!obs_source_showing(wc->source)) - return; + if (!obs_source_showing(wc->source)) + return; - @autoreleasepool { - return window_capture_tick_internal(data, seconds); - } + @autoreleasepool { + return window_capture_tick_internal(data, seconds); + } } struct obs_source_info window_capture_info = { - .id = "window_capture", - .type = OBS_SOURCE_TYPE_INPUT, - .get_name = window_capture_getname, + .id = "window_capture", + .type = OBS_SOURCE_TYPE_INPUT, + .get_name = window_capture_getname, - .create = window_capture_create, - .destroy = window_capture_destroy, + .create = window_capture_create, + .destroy = window_capture_destroy, - .output_flags = OBS_SOURCE_ASYNC_VIDEO, - .video_tick = window_capture_tick, + .output_flags = OBS_SOURCE_ASYNC_VIDEO, + .video_tick = window_capture_tick, - .get_defaults = window_capture_defaults, - .get_properties = window_capture_properties, - .update = window_capture_update, - .icon_type = OBS_ICON_TYPE_WINDOW_CAPTURE, + .get_defaults = window_capture_defaults, + .get_properties = window_capture_properties, + .update = window_capture_update, + .icon_type = OBS_ICON_TYPE_WINDOW_CAPTURE, }; diff --git a/plugins/mac-capture/window-utils.h b/plugins/mac-capture/window-utils.h index 588e9eda3..cdbd0965f 100644 --- a/plugins/mac-capture/window-utils.h +++ b/plugins/mac-capture/window-utils.h @@ -5,14 +5,14 @@ #include struct cocoa_window { - CGWindowID window_id; - int owner_pid; + CGWindowID window_id; + int owner_pid; - pthread_mutex_t name_lock; - NSString *owner_name; - NSString *window_name; + pthread_mutex_t name_lock; + NSString *owner_name; + NSString *window_name; - uint64_t next_search_time; + uint64_t next_search_time; }; typedef struct cocoa_window *cocoa_window_t; diff --git a/plugins/mac-capture/window-utils.m b/plugins/mac-capture/window-utils.m index 31bd32abe..ed1daefbe 100644 --- a/plugins/mac-capture/window-utils.m +++ b/plugins/mac-capture/window-utils.m @@ -2,35 +2,34 @@ #include -#define WINDOW_NAME ((NSString *)kCGWindowName) -#define WINDOW_NUMBER ((NSString *)kCGWindowNumber) -#define OWNER_NAME ((NSString *)kCGWindowOwnerName) -#define OWNER_PID ((NSNumber *)kCGWindowOwnerPID) +#define WINDOW_NAME ((NSString *) kCGWindowName) +#define WINDOW_NUMBER ((NSString *) kCGWindowNumber) +#define OWNER_NAME ((NSString *) kCGWindowOwnerName) +#define OWNER_PID ((NSNumber *) kCGWindowOwnerPID) static NSComparator win_info_cmp = ^(NSDictionary *o1, NSDictionary *o2) { - NSComparisonResult res = [o1[OWNER_NAME] compare:o2[OWNER_NAME]]; - if (res != NSOrderedSame) - return res; + NSComparisonResult res = [o1[OWNER_NAME] compare:o2[OWNER_NAME]]; + if (res != NSOrderedSame) + return res; - res = [o1[OWNER_PID] compare:o2[OWNER_PID]]; - if (res != NSOrderedSame) - return res; + res = [o1[OWNER_PID] compare:o2[OWNER_PID]]; + if (res != NSOrderedSame) + return res; - res = [o1[WINDOW_NAME] compare:o2[WINDOW_NAME]]; - if (res != NSOrderedSame) - return res; + res = [o1[WINDOW_NAME] compare:o2[WINDOW_NAME]]; + if (res != NSOrderedSame) + return res; - return [o1[WINDOW_NUMBER] compare:o2[WINDOW_NUMBER]]; + return [o1[WINDOW_NUMBER] compare:o2[WINDOW_NUMBER]]; }; NSArray *enumerate_windows(void) { - NSArray *arr = (NSArray *)CGWindowListCopyWindowInfo( - kCGWindowListOptionOnScreenOnly, kCGNullWindowID); + NSArray *arr = (NSArray *) CGWindowListCopyWindowInfo(kCGWindowListOptionOnScreenOnly, kCGNullWindowID); - [arr autorelease]; + [arr autorelease]; - return [arr sortedArrayUsingComparator:win_info_cmp]; + return [arr sortedArrayUsingComparator:win_info_cmp]; } #define WAIT_TIME_MS 500 @@ -39,227 +38,210 @@ NSArray *enumerate_windows(void) bool find_window(cocoa_window_t cw, obs_data_t *settings, bool force) { - if (!force && cw->next_search_time > os_gettime_ns()) - return false; + if (!force && cw->next_search_time > os_gettime_ns()) + return false; - cw->next_search_time = os_gettime_ns() + WAIT_TIME_NS; + cw->next_search_time = os_gettime_ns() + WAIT_TIME_NS; - pthread_mutex_lock(&cw->name_lock); + pthread_mutex_lock(&cw->name_lock); - if (!cw->window_name.length && !cw->owner_name.length) - goto invalid_name; + if (!cw->window_name.length && !cw->owner_name.length) + goto invalid_name; - for (NSDictionary *dict in enumerate_windows()) { - if (![cw->owner_name isEqualToString:dict[OWNER_NAME]]) - continue; + for (NSDictionary *dict in enumerate_windows()) { + if (![cw->owner_name isEqualToString:dict[OWNER_NAME]]) + continue; - if (![cw->window_name isEqualToString:dict[WINDOW_NAME]]) - continue; + if (![cw->window_name isEqualToString:dict[WINDOW_NAME]]) + continue; - pthread_mutex_unlock(&cw->name_lock); + pthread_mutex_unlock(&cw->name_lock); - NSNumber *window_id = (NSNumber *)dict[WINDOW_NUMBER]; - cw->window_id = window_id.intValue; - NSNumber *owner_pid = (NSNumber *)dict[OWNER_PID]; - cw->owner_pid = owner_pid.intValue; + NSNumber *window_id = (NSNumber *) dict[WINDOW_NUMBER]; + cw->window_id = window_id.intValue; + NSNumber *owner_pid = (NSNumber *) dict[OWNER_PID]; + cw->owner_pid = owner_pid.intValue; - obs_data_set_int(settings, "window", cw->window_id); - obs_data_set_int(settings, "owner_pid", cw->owner_pid); - return true; - } + obs_data_set_int(settings, "window", cw->window_id); + obs_data_set_int(settings, "owner_pid", cw->owner_pid); + return true; + } invalid_name: - pthread_mutex_unlock(&cw->name_lock); - return false; + pthread_mutex_unlock(&cw->name_lock); + return false; } void init_window(cocoa_window_t cw, obs_data_t *settings) { - pthread_mutex_init(&cw->name_lock, NULL); + pthread_mutex_init(&cw->name_lock, NULL); - cw->owner_name = @(obs_data_get_string(settings, "owner_name")); - cw->window_name = @(obs_data_get_string(settings, "window_name")); - [cw->owner_name retain]; - [cw->window_name retain]; + cw->owner_name = @(obs_data_get_string(settings, "owner_name")); + cw->window_name = @(obs_data_get_string(settings, "window_name")); + [cw->owner_name retain]; + [cw->window_name retain]; - // Find initial window. - pthread_mutex_lock(&cw->name_lock); + // Find initial window. + pthread_mutex_lock(&cw->name_lock); - if (!cw->window_name.length && !cw->owner_name.length) - goto invalid_name; + if (!cw->window_name.length && !cw->owner_name.length) + goto invalid_name; - NSNumber *owner_pid = @(obs_data_get_int(settings, "owner_pid")); - NSNumber *window_id = @(obs_data_get_int(settings, "window")); - for (NSDictionary *dict in enumerate_windows()) { - bool owner_names_match = - [cw->owner_name isEqualToString:dict[OWNER_NAME]]; - bool ids_match = - [owner_pid isEqualToNumber:dict[OWNER_PID]] && - [window_id isEqualToNumber:dict[WINDOW_NUMBER]]; - bool window_names_match = - [cw->window_name isEqualToString:dict[WINDOW_NAME]]; + NSNumber *owner_pid = @(obs_data_get_int(settings, "owner_pid")); + NSNumber *window_id = @(obs_data_get_int(settings, "window")); + for (NSDictionary *dict in enumerate_windows()) { + bool owner_names_match = [cw->owner_name isEqualToString:dict[OWNER_NAME]]; + bool ids_match = [owner_pid isEqualToNumber:dict[OWNER_PID]] && [window_id isEqualToNumber:dict[WINDOW_NUMBER]]; + bool window_names_match = [cw->window_name isEqualToString:dict[WINDOW_NAME]]; - if (owner_names_match && (ids_match || window_names_match)) { - pthread_mutex_unlock(&cw->name_lock); + if (owner_names_match && (ids_match || window_names_match)) { + pthread_mutex_unlock(&cw->name_lock); - cw->window_id = [dict[WINDOW_NUMBER] intValue]; - cw->owner_pid = [dict[OWNER_PID] intValue]; + cw->window_id = [dict[WINDOW_NUMBER] intValue]; + cw->owner_pid = [dict[OWNER_PID] intValue]; - obs_data_set_int(settings, "window", cw->window_id); - obs_data_set_int(settings, "owner_pid", cw->owner_pid); - return; - } - } + obs_data_set_int(settings, "window", cw->window_id); + obs_data_set_int(settings, "owner_pid", cw->owner_pid); + return; + } + } invalid_name: - pthread_mutex_unlock(&cw->name_lock); - return; + pthread_mutex_unlock(&cw->name_lock); + return; } void destroy_window(cocoa_window_t cw) { - pthread_mutex_destroy(&cw->name_lock); - [cw->owner_name release]; - [cw->window_name release]; + pthread_mutex_destroy(&cw->name_lock); + [cw->owner_name release]; + [cw->window_name release]; } void update_window(cocoa_window_t cw, obs_data_t *settings) { - pthread_mutex_lock(&cw->name_lock); - [cw->owner_name release]; - [cw->window_name release]; - cw->owner_name = @(obs_data_get_string(settings, "owner_name")); - cw->window_name = @(obs_data_get_string(settings, "window_name")); - [cw->owner_name retain]; - [cw->window_name retain]; - pthread_mutex_unlock(&cw->name_lock); + pthread_mutex_lock(&cw->name_lock); + [cw->owner_name release]; + [cw->window_name release]; + cw->owner_name = @(obs_data_get_string(settings, "owner_name")); + cw->window_name = @(obs_data_get_string(settings, "window_name")); + [cw->owner_name retain]; + [cw->window_name retain]; + pthread_mutex_unlock(&cw->name_lock); - cw->owner_pid = (int)obs_data_get_int(settings, "owner_pid"); - cw->window_id = (unsigned int)obs_data_get_int(settings, "window"); + cw->owner_pid = (int) obs_data_get_int(settings, "owner_pid"); + cw->window_id = (unsigned int) obs_data_get_int(settings, "window"); } static inline const char *make_name(NSString *owner, NSString *name) { - if (!owner.length) - return ""; + if (!owner.length) + return ""; - NSString *str = [NSString stringWithFormat:@"[%@] %@", owner, name]; - return str.UTF8String; + NSString *str = [NSString stringWithFormat:@"[%@] %@", owner, name]; + return str.UTF8String; } static inline NSDictionary *find_window_dict(NSArray *arr, int window_id) { - for (NSDictionary *dict in arr) { - NSNumber *wid = (NSNumber *)dict[WINDOW_NUMBER]; - if (wid.intValue == window_id) - return dict; - } + for (NSDictionary *dict in arr) { + NSNumber *wid = (NSNumber *) dict[WINDOW_NUMBER]; + if (wid.intValue == window_id) + return dict; + } - return nil; + return nil; } -static inline bool window_changed_internal(obs_property_t *p, - obs_data_t *settings) +static inline bool window_changed_internal(obs_property_t *p, obs_data_t *settings) { - int window_id = (int)obs_data_get_int(settings, "window"); - NSString *window_owner = @(obs_data_get_string(settings, "owner_name")); - NSString *window_name = @(obs_data_get_string(settings, "window_name")); + int window_id = (int) obs_data_get_int(settings, "window"); + NSString *window_owner = @(obs_data_get_string(settings, "owner_name")); + NSString *window_name = @(obs_data_get_string(settings, "window_name")); - NSDictionary *win_info = @{ - OWNER_NAME: window_owner, - WINDOW_NAME: window_name, - }; + NSDictionary *win_info = @ { + OWNER_NAME: window_owner, + WINDOW_NAME: window_name, + }; - NSArray *arr = enumerate_windows(); + NSArray *arr = enumerate_windows(); - bool show_empty_names = obs_data_get_bool(settings, "show_empty_names"); + bool show_empty_names = obs_data_get_bool(settings, "show_empty_names"); - NSDictionary *cur = find_window_dict(arr, window_id); - bool window_found = cur != nil; - bool window_added = window_found; + NSDictionary *cur = find_window_dict(arr, window_id); + bool window_found = cur != nil; + bool window_added = window_found; - obs_property_list_clear(p); - for (NSDictionary *dict in arr) { - NSString *owner = (NSString *)dict[OWNER_NAME]; - NSString *name = (NSString *)dict[WINDOW_NAME]; - NSNumber *wid = (NSNumber *)dict[WINDOW_NUMBER]; + obs_property_list_clear(p); + for (NSDictionary *dict in arr) { + NSString *owner = (NSString *) dict[OWNER_NAME]; + NSString *name = (NSString *) dict[WINDOW_NAME]; + NSNumber *wid = (NSNumber *) dict[WINDOW_NUMBER]; - if (!window_added && - win_info_cmp(win_info, dict) == NSOrderedAscending) { - window_added = true; - size_t idx = obs_property_list_add_int( - p, make_name(window_owner, window_name), - window_id); - obs_property_list_item_disable(p, idx, true); - } + if (!window_added && win_info_cmp(win_info, dict) == NSOrderedAscending) { + window_added = true; + size_t idx = obs_property_list_add_int(p, make_name(window_owner, window_name), window_id); + obs_property_list_item_disable(p, idx, true); + } - if (!show_empty_names && !name.length && - window_id != wid.intValue) - continue; + if (!show_empty_names && !name.length && window_id != wid.intValue) + continue; - obs_property_list_add_int(p, make_name(owner, name), - wid.intValue); - } + obs_property_list_add_int(p, make_name(owner, name), wid.intValue); + } - if (!window_added) { - size_t idx = obs_property_list_add_int( - p, make_name(window_owner, window_name), window_id); - obs_property_list_item_disable(p, idx, true); - } + if (!window_added) { + size_t idx = obs_property_list_add_int(p, make_name(window_owner, window_name), window_id); + obs_property_list_item_disable(p, idx, true); + } - if (!window_found) - return true; + if (!window_found) + return true; - NSString *owner = (NSString *)cur[OWNER_NAME]; - NSString *window = (NSString *)cur[WINDOW_NAME]; + NSString *owner = (NSString *) cur[OWNER_NAME]; + NSString *window = (NSString *) cur[WINDOW_NAME]; - obs_data_set_string(settings, "owner_name", owner.UTF8String); - obs_data_set_string(settings, "window_name", window.UTF8String); + obs_data_set_string(settings, "owner_name", owner.UTF8String); + obs_data_set_string(settings, "window_name", window.UTF8String); - return true; + return true; } -static bool window_changed(obs_properties_t *props, obs_property_t *p, - obs_data_t *settings) +static bool window_changed(obs_properties_t *props, obs_property_t *p, obs_data_t *settings) { - UNUSED_PARAMETER(props); + UNUSED_PARAMETER(props); - @autoreleasepool { - return window_changed_internal(p, settings); - } + @autoreleasepool { + return window_changed_internal(p, settings); + } } -static bool toggle_empty_names(obs_properties_t *props, obs_property_t *p, - obs_data_t *settings) +static bool toggle_empty_names(obs_properties_t *props, obs_property_t *p, obs_data_t *settings) { - UNUSED_PARAMETER(p); + UNUSED_PARAMETER(p); - return window_changed(props, obs_properties_get(props, "window"), - settings); + return window_changed(props, obs_properties_get(props, "window"), settings); } void window_defaults(obs_data_t *settings) { - obs_data_set_default_int(settings, "window", kCGNullWindowID); - obs_data_set_default_bool(settings, "show_empty_names", false); + obs_data_set_default_int(settings, "window", kCGNullWindowID); + obs_data_set_default_bool(settings, "show_empty_names", false); } void add_window_properties(obs_properties_t *props) { - obs_property_t *window_list = obs_properties_add_list( - props, "window", obs_module_text("WindowUtils.Window"), - OBS_COMBO_TYPE_LIST, OBS_COMBO_FORMAT_INT); - obs_property_set_modified_callback(window_list, window_changed); + obs_property_t *window_list = obs_properties_add_list(props, "window", obs_module_text("WindowUtils.Window"), + OBS_COMBO_TYPE_LIST, OBS_COMBO_FORMAT_INT); + obs_property_set_modified_callback(window_list, window_changed); - obs_property_t *empty = obs_properties_add_bool( - props, "show_empty_names", - obs_module_text("WindowUtils.ShowEmptyNames")); - obs_property_set_modified_callback(empty, toggle_empty_names); + obs_property_t *empty = + obs_properties_add_bool(props, "show_empty_names", obs_module_text("WindowUtils.ShowEmptyNames")); + obs_property_set_modified_callback(empty, toggle_empty_names); } void show_window_properties(obs_properties_t *props, bool show) { - obs_property_set_visible(obs_properties_get(props, "window"), show); - obs_property_set_visible(obs_properties_get(props, "show_empty_names"), - show); + obs_property_set_visible(obs_properties_get(props, "window"), show); + obs_property_set_visible(obs_properties_get(props, "show_empty_names"), show); } diff --git a/plugins/mac-syphon/syphon.m b/plugins/mac-syphon/syphon.m index 2a882f929..0561ca171 100644 --- a/plugins/mac-syphon/syphon.m +++ b/plugins/mac-syphon/syphon.m @@ -4,375 +4,360 @@ #include #include -#define LOG(level, message, ...) \ - blog(level, "%s: " message, obs_source_get_name(s->source), \ - ##__VA_ARGS__) +#define LOG(level, message, ...) blog(level, "%s: " message, obs_source_get_name(s->source), ##__VA_ARGS__) struct syphon { - SYPHON_CLIENT_UNIQUE_CLASS_NAME *client; - IOSurfaceRef ref; + SYPHON_CLIENT_UNIQUE_CLASS_NAME *client; + IOSurfaceRef ref; - gs_samplerstate_t *sampler; - gs_effect_t *effect; - gs_vertbuffer_t *vertbuffer; - gs_texture_t *tex; - uint32_t width, height; - bool crop; - CGRect crop_rect; - bool allow_transparency; + gs_samplerstate_t *sampler; + gs_effect_t *effect; + gs_vertbuffer_t *vertbuffer; + gs_texture_t *tex; + uint32_t width, height; + bool crop; + CGRect crop_rect; + bool allow_transparency; - obs_source_t *source; + obs_source_t *source; - bool active; - bool uuid_changed; - id new_server_listener; - id retire_listener; + bool active; + bool uuid_changed; + id new_server_listener; + id retire_listener; - NSString *app_name; - NSString *name; - NSString *uuid; + NSString *app_name; + NSString *name; + NSString *uuid; }; typedef struct syphon *syphon_t; static inline void update_properties(syphon_t s) { - obs_source_update_properties(s->source); + obs_source_update_properties(s->source); } @interface OBSSyphonKVObserver : NSObject - (void)observeValueForKeyPath:(NSString *)keyPath - ofObject:(id)object - change:(NSDictionary *)change - context:(void *)context; + ofObject:(id)object + change:(NSDictionary *)change + context:(void *)context; @end @implementation OBSSyphonKVObserver - (void)observeValueForKeyPath:(NSString *)keyPath - ofObject:(id)object - change:(NSDictionary *)change - context:(void *)context + ofObject:(id)object + change:(NSDictionary *)change + context:(void *)context { - syphon_t s = context; - if (!s) - return; + syphon_t s = context; + if (!s) + return; - if (!change[NSKeyValueChangeNewKey]) - return; + if (!change[NSKeyValueChangeNewKey]) + return; - update_properties(s); + update_properties(s); } @end static const char *syphon_get_name(void *unused __attribute((unused))) { - return obs_module_text("Syphon"); + return obs_module_text("Syphon"); } static void stop_client(syphon_t s) { - obs_enter_graphics(); + obs_enter_graphics(); - if (s->client) { - [s->client stop]; - } + if (s->client) { + [s->client stop]; + } - if (s->tex) { - gs_texture_destroy(s->tex); - s->tex = NULL; - } + if (s->tex) { + gs_texture_destroy(s->tex); + s->tex = NULL; + } - if (s->ref) { - IOSurfaceDecrementUseCount(s->ref); - CFRelease(s->ref); - s->ref = NULL; - } + if (s->ref) { + IOSurfaceDecrementUseCount(s->ref); + CFRelease(s->ref); + s->ref = NULL; + } - s->width = 0; - s->height = 0; + s->width = 0; + s->height = 0; - obs_leave_graphics(); + obs_leave_graphics(); } static inline NSDictionary *find_by_uuid(NSArray *arr, NSString *uuid) { - for (NSDictionary *dict in arr) { - if ([dict[SyphonServerDescriptionUUIDKey] isEqual:uuid]) - return dict; - } + for (NSDictionary *dict in arr) { + if ([dict[SyphonServerDescriptionUUIDKey] isEqual:uuid]) + return dict; + } - return nil; + return nil; } static inline void check_version(syphon_t s, NSDictionary *desc) { - extern const NSString *SyphonServerDescriptionDictionaryVersionKey; + extern const NSString *SyphonServerDescriptionDictionaryVersionKey; - NSNumber *version = desc[SyphonServerDescriptionDictionaryVersionKey]; - if (!version) - return LOG(LOG_WARNING, "Server description does not contain " - "VersionKey"); + NSNumber *version = desc[SyphonServerDescriptionDictionaryVersionKey]; + if (!version) + return LOG(LOG_WARNING, "Server description does not contain " + "VersionKey"); - if (version.unsignedIntValue > 0) - LOG(LOG_WARNING, - "Got server description version %d, " - "expected 0", - version.unsignedIntValue); + if (version.unsignedIntValue > 0) + LOG(LOG_WARNING, + "Got server description version %d, " + "expected 0", + version.unsignedIntValue); } static inline void check_description(syphon_t s, NSDictionary *desc) { - extern const NSString *SyphonSurfaceType; - extern const NSString *SyphonSurfaceTypeIOSurface; - extern const NSString *SyphonServerDescriptionSurfacesKey; + extern const NSString *SyphonSurfaceType; + extern const NSString *SyphonSurfaceTypeIOSurface; + extern const NSString *SyphonServerDescriptionSurfacesKey; - NSArray *surfaces = desc[SyphonServerDescriptionSurfacesKey]; - if (!surfaces) - return LOG(LOG_WARNING, "Server description does not contain " - "SyphonServerDescriptionSurfacesKey"); + NSArray *surfaces = desc[SyphonServerDescriptionSurfacesKey]; + if (!surfaces) + return LOG(LOG_WARNING, "Server description does not contain " + "SyphonServerDescriptionSurfacesKey"); - if (!surfaces.count) - return LOG(LOG_WARNING, "Server description contains empty " - "SyphonServerDescriptionSurfacesKey"); + if (!surfaces.count) + return LOG(LOG_WARNING, "Server description contains empty " + "SyphonServerDescriptionSurfacesKey"); - for (NSDictionary *surface in surfaces) { - NSString *type = surface[SyphonSurfaceType]; - if (type && [type isEqual:SyphonSurfaceTypeIOSurface]) - return; - } + for (NSDictionary *surface in surfaces) { + NSString *type = surface[SyphonSurfaceType]; + if (type && [type isEqual:SyphonSurfaceTypeIOSurface]) + return; + } - NSString *surfaces_string = [NSString stringWithFormat:@"%@", surfaces]; - LOG(LOG_WARNING, - "SyphonSurfaces does not contain" - "'SyphonSurfaceTypeIOSurface': %s", - surfaces_string.UTF8String); + NSString *surfaces_string = [NSString stringWithFormat:@"%@", surfaces]; + LOG(LOG_WARNING, + "SyphonSurfaces does not contain" + "'SyphonSurfaceTypeIOSurface': %s", + surfaces_string.UTF8String); } -static inline void handle_new_frame(syphon_t s, - SYPHON_CLIENT_UNIQUE_CLASS_NAME *client) +static inline void handle_new_frame(syphon_t s, SYPHON_CLIENT_UNIQUE_CLASS_NAME *client) { - IOSurfaceRef ref = [client IOSurface]; + IOSurfaceRef ref = [client IOSurface]; - if (!ref) - return; + if (!ref) + return; - if (ref == s->ref) { - CFRelease(ref); - return; - } + if (ref == s->ref) { + CFRelease(ref); + return; + } - IOSurfaceIncrementUseCount(ref); + IOSurfaceIncrementUseCount(ref); - obs_enter_graphics(); - if (s->ref) { - gs_texture_destroy(s->tex); - IOSurfaceDecrementUseCount(s->ref); - CFRelease(s->ref); - } + obs_enter_graphics(); + if (s->ref) { + gs_texture_destroy(s->tex); + IOSurfaceDecrementUseCount(s->ref); + CFRelease(s->ref); + } - s->ref = ref; - s->tex = gs_texture_create_from_iosurface(s->ref); - s->width = gs_texture_get_width(s->tex); - s->height = gs_texture_get_height(s->tex); - obs_leave_graphics(); + s->ref = ref; + s->tex = gs_texture_create_from_iosurface(s->ref); + s->width = gs_texture_get_width(s->tex); + s->height = gs_texture_get_height(s->tex); + obs_leave_graphics(); } static void create_client(syphon_t s) { - stop_client(s); + stop_client(s); - if (!s->app_name.length && !s->name.length && !s->uuid.length) - return; + if (!s->app_name.length && !s->name.length && !s->uuid.length) + return; - SyphonServerDirectory *ssd = [SyphonServerDirectory sharedDirectory]; - NSArray *servers = [ssd serversMatchingName:s->name - appName:s->app_name]; - if (!servers.count) - return; + SyphonServerDirectory *ssd = [SyphonServerDirectory sharedDirectory]; + NSArray *servers = [ssd serversMatchingName:s->name appName:s->app_name]; + if (!servers.count) + return; - NSDictionary *desc = find_by_uuid(servers, s->uuid); - if (!desc) { - desc = servers[0]; - if (![s->uuid isEqualToString: - desc[SyphonServerDescriptionUUIDKey]]) { - s->uuid_changed = true; - } - } + NSDictionary *desc = find_by_uuid(servers, s->uuid); + if (!desc) { + desc = servers[0]; + if (![s->uuid isEqualToString:desc[SyphonServerDescriptionUUIDKey]]) { + s->uuid_changed = true; + } + } - check_version(s, desc); - check_description(s, desc); + check_version(s, desc); + check_description(s, desc); - s->client = [[SYPHON_CLIENT_UNIQUE_CLASS_NAME alloc] - initWithServerDescription:desc - options:nil - newFrameHandler:^( - SYPHON_CLIENT_UNIQUE_CLASS_NAME *client) { - handle_new_frame(s, client); - }]; + s->client = + [[SYPHON_CLIENT_UNIQUE_CLASS_NAME alloc] initWithServerDescription:desc options:nil + newFrameHandler:^(SYPHON_CLIENT_UNIQUE_CLASS_NAME *client) { + handle_new_frame(s, client); + }]; - s->active = true; + s->active = true; } static inline bool load_syphon_settings(syphon_t s, obs_data_t *settings) { - NSString *app_name = @(obs_data_get_string(settings, "app_name")); - NSString *name = @(obs_data_get_string(settings, "name")); - bool equal_names = [app_name isEqual:s->app_name] && - [name isEqual:s->name]; - if (s->uuid_changed && equal_names) - return false; + NSString *app_name = @(obs_data_get_string(settings, "app_name")); + NSString *name = @(obs_data_get_string(settings, "name")); + bool equal_names = [app_name isEqual:s->app_name] && [name isEqual:s->name]; + if (s->uuid_changed && equal_names) + return false; - NSString *uuid = @(obs_data_get_string(settings, "uuid")); - if ([uuid isEqual:s->uuid] && equal_names) - return false; + NSString *uuid = @(obs_data_get_string(settings, "uuid")); + if ([uuid isEqual:s->uuid] && equal_names) + return false; - s->app_name = app_name; - s->name = name; - s->uuid = uuid; - s->uuid_changed = false; - return true; + s->app_name = app_name; + s->name = name; + s->uuid = uuid; + s->uuid_changed = false; + return true; } static inline void update_from_announce(syphon_t s, NSDictionary *info) { - if (s->active) - return; + if (s->active) + return; - if (!info) - return; + if (!info) + return; - NSString *app_name = info[SyphonServerDescriptionAppNameKey]; - NSString *name = info[SyphonServerDescriptionNameKey]; - NSString *uuid = info[SyphonServerDescriptionUUIDKey]; + NSString *app_name = info[SyphonServerDescriptionAppNameKey]; + NSString *name = info[SyphonServerDescriptionNameKey]; + NSString *uuid = info[SyphonServerDescriptionUUIDKey]; - if (![uuid isEqual:s->uuid] && - !([app_name isEqual:s->app_name] && [name isEqual:s->name])) - return; + if (![uuid isEqual:s->uuid] && !([app_name isEqual:s->app_name] && [name isEqual:s->name])) + return; - s->app_name = app_name; - s->name = name; - if (![s->uuid isEqualToString:uuid]) { - s->uuid = uuid; - s->uuid_changed = true; - } + s->app_name = app_name; + s->name = name; + if (![s->uuid isEqualToString:uuid]) { + s->uuid = uuid; + s->uuid_changed = true; + } - create_client(s); + create_client(s); } static inline void handle_announce(syphon_t s, NSNotification *note) { - if (!note) - return; + if (!note) + return; - update_from_announce(s, note.object); - update_properties(s); + update_from_announce(s, note.object); + update_properties(s); } static inline void update_from_retire(syphon_t s, NSDictionary *info) { - if (!info) - return; + if (!info) + return; - NSString *uuid = info[SyphonServerDescriptionUUIDKey]; - if (!uuid) - return; + NSString *uuid = info[SyphonServerDescriptionUUIDKey]; + if (!uuid) + return; - if (![uuid isEqual:s->uuid]) - return; + if (![uuid isEqual:s->uuid]) + return; - s->active = false; + s->active = false; } static inline void handle_retire(syphon_t s, NSNotification *note) { - if (!note) - return; + if (!note) + return; - update_from_retire(s, note.object); - update_properties(s); + update_from_retire(s, note.object); + update_properties(s); } static inline gs_vertbuffer_t *create_vertbuffer() { - struct gs_vb_data *vb_data = gs_vbdata_create(); - vb_data->num = 4; - vb_data->points = bzalloc(sizeof(struct vec3) * 4); - if (!vb_data->points) - return NULL; + struct gs_vb_data *vb_data = gs_vbdata_create(); + vb_data->num = 4; + vb_data->points = bzalloc(sizeof(struct vec3) * 4); + if (!vb_data->points) + return NULL; - vb_data->num_tex = 1; - vb_data->tvarray = bzalloc(sizeof(struct gs_tvertarray)); - if (!vb_data->tvarray) - goto fail_tvarray; + vb_data->num_tex = 1; + vb_data->tvarray = bzalloc(sizeof(struct gs_tvertarray)); + if (!vb_data->tvarray) + goto fail_tvarray; - vb_data->tvarray[0].width = 2; - vb_data->tvarray[0].array = bzalloc(sizeof(struct vec2) * 4); - if (!vb_data->tvarray[0].array) - goto fail_array; + vb_data->tvarray[0].width = 2; + vb_data->tvarray[0].array = bzalloc(sizeof(struct vec2) * 4); + if (!vb_data->tvarray[0].array) + goto fail_array; - gs_vertbuffer_t *vbuff = gs_vertexbuffer_create(vb_data, GS_DYNAMIC); - if (vbuff) - return vbuff; + gs_vertbuffer_t *vbuff = gs_vertexbuffer_create(vb_data, GS_DYNAMIC); + if (vbuff) + return vbuff; - bfree(vb_data->tvarray[0].array); + bfree(vb_data->tvarray[0].array); fail_array: - bfree(vb_data->tvarray); + bfree(vb_data->tvarray); fail_tvarray: - bfree(vb_data->points); + bfree(vb_data->points); - return NULL; + return NULL; } static inline bool init_obs_graphics_objects(syphon_t s) { - struct gs_sampler_info info = { - .filter = GS_FILTER_LINEAR, - .address_u = GS_ADDRESS_CLAMP, - .address_v = GS_ADDRESS_CLAMP, - .address_w = GS_ADDRESS_CLAMP, - .max_anisotropy = 1, - }; + struct gs_sampler_info info = { + .filter = GS_FILTER_LINEAR, + .address_u = GS_ADDRESS_CLAMP, + .address_v = GS_ADDRESS_CLAMP, + .address_w = GS_ADDRESS_CLAMP, + .max_anisotropy = 1, + }; - obs_enter_graphics(); - s->sampler = gs_samplerstate_create(&info); - s->vertbuffer = create_vertbuffer(); - obs_leave_graphics(); + obs_enter_graphics(); + s->sampler = gs_samplerstate_create(&info); + s->vertbuffer = create_vertbuffer(); + obs_leave_graphics(); - s->effect = obs_get_base_effect(OBS_EFFECT_DEFAULT_RECT); + s->effect = obs_get_base_effect(OBS_EFFECT_DEFAULT_RECT); - return s->sampler != NULL && s->vertbuffer != NULL && s->effect != NULL; + return s->sampler != NULL && s->vertbuffer != NULL && s->effect != NULL; } static inline bool create_syphon_listeners(syphon_t s) { - NSNotificationCenter *nc = [NSNotificationCenter defaultCenter]; - s->new_server_listener = [nc - addObserverForName:SyphonServerAnnounceNotification - object:nil - queue:[NSOperationQueue mainQueue] - usingBlock:^(NSNotification *note) { - handle_announce(s, note); - }]; + NSNotificationCenter *nc = [NSNotificationCenter defaultCenter]; + s->new_server_listener = [nc addObserverForName:SyphonServerAnnounceNotification object:nil + queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *note) { + handle_announce(s, note); + }]; - s->retire_listener = [nc - addObserverForName:SyphonServerRetireNotification - object:nil - queue:[NSOperationQueue mainQueue] - usingBlock:^(NSNotification *note) { - handle_retire(s, note); - }]; + s->retire_listener = [nc addObserverForName:SyphonServerRetireNotification object:nil + queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *note) { + handle_retire(s, note); + }]; - return s->new_server_listener != nil && s->retire_listener != nil; + return s->new_server_listener != nil && s->retire_listener != nil; } static inline void load_crop(syphon_t s, obs_data_t *settings) { - s->crop = obs_data_get_bool(settings, "crop"); + s->crop = obs_data_get_bool(settings, "crop"); #define LOAD_CROP(x) s->crop_rect.x = obs_data_get_double(settings, "crop." #x) - LOAD_CROP(origin.x); - LOAD_CROP(origin.y); - LOAD_CROP(size.width); - LOAD_CROP(size.height); + LOAD_CROP(origin.x); + LOAD_CROP(origin.y); + LOAD_CROP(size.width); + LOAD_CROP(size.height); #undef LOAD_CROP } @@ -380,416 +365,382 @@ static inline void syphon_destroy_internal(syphon_t s); static void *syphon_create_internal(obs_data_t *settings, obs_source_t *source) { - syphon_t s = bzalloc(sizeof(struct syphon)); - if (!s) - return s; + syphon_t s = bzalloc(sizeof(struct syphon)); + if (!s) + return s; - s->source = source; + s->source = source; - if (!init_obs_graphics_objects(s)) { - syphon_destroy_internal(s); - return NULL; - } + if (!init_obs_graphics_objects(s)) { + syphon_destroy_internal(s); + return NULL; + } - if (!load_syphon_settings(s, settings)) { - syphon_destroy_internal(s); - return NULL; - } + if (!load_syphon_settings(s, settings)) { + syphon_destroy_internal(s); + return NULL; + } - if (!create_syphon_listeners(s)) { - syphon_destroy_internal(s); - return NULL; - } + if (!create_syphon_listeners(s)) { + syphon_destroy_internal(s); + return NULL; + } - create_client(s); + create_client(s); - load_crop(s, settings); + load_crop(s, settings); - s->allow_transparency = - obs_data_get_bool(settings, "allow_transparency"); + s->allow_transparency = obs_data_get_bool(settings, "allow_transparency"); - return s; + return s; } static void *syphon_create(obs_data_t *settings, obs_source_t *source) { - @autoreleasepool { - return syphon_create_internal(settings, source); - } + @autoreleasepool { + return syphon_create_internal(settings, source); + } } static inline void stop_listener(id listener) { - if (!listener) - return; + if (!listener) + return; - NSNotificationCenter *nc = [NSNotificationCenter defaultCenter]; - [nc removeObserver:listener]; + NSNotificationCenter *nc = [NSNotificationCenter defaultCenter]; + [nc removeObserver:listener]; } static inline void syphon_destroy_internal(syphon_t s) { - stop_listener(s->new_server_listener); - stop_listener(s->retire_listener); + stop_listener(s->new_server_listener); + stop_listener(s->retire_listener); - obs_enter_graphics(); - stop_client(s); + obs_enter_graphics(); + stop_client(s); - if (s->sampler) - gs_samplerstate_destroy(s->sampler); - if (s->vertbuffer) - gs_vertexbuffer_destroy(s->vertbuffer); - obs_leave_graphics(); + if (s->sampler) + gs_samplerstate_destroy(s->sampler); + if (s->vertbuffer) + gs_vertexbuffer_destroy(s->vertbuffer); + obs_leave_graphics(); - bfree(s); + bfree(s); } static void syphon_destroy(void *data) { - @autoreleasepool { - syphon_destroy_internal(data); - } + @autoreleasepool { + syphon_destroy_internal(data); + } } static inline NSString *get_string(obs_data_t *settings, const char *name) { - if (!settings) - return nil; + if (!settings) + return nil; - return @(obs_data_get_string(settings, name)); + return @(obs_data_get_string(settings, name)); } -static inline void update_strings_from_context(syphon_t s, obs_data_t *settings, - NSString **app, NSString **name, - NSString **uuid) +static inline void update_strings_from_context(syphon_t s, obs_data_t *settings, NSString **app, NSString **name, + NSString **uuid) { - if (!s || !s->uuid_changed) - return; + if (!s || !s->uuid_changed) + return; - s->uuid_changed = false; - *app = s->app_name; - *name = s->name; - *uuid = s->uuid; + s->uuid_changed = false; + *app = s->app_name; + *name = s->name; + *uuid = s->uuid; - obs_data_set_string(settings, "app_name", s->app_name.UTF8String); - obs_data_set_string(settings, "name", s->name.UTF8String); - obs_data_set_string(settings, "uuid", s->uuid.UTF8String); + obs_data_set_string(settings, "app_name", s->app_name.UTF8String); + obs_data_set_string(settings, "name", s->name.UTF8String); + obs_data_set_string(settings, "uuid", s->uuid.UTF8String); } -static inline void add_servers(syphon_t s, obs_property_t *list, - obs_data_t *settings) +static inline void add_servers(syphon_t s, obs_property_t *list, obs_data_t *settings) { - bool found_current = settings == NULL; + bool found_current = settings == NULL; - NSString *set_app = get_string(settings, "app_name"); - NSString *set_name = get_string(settings, "name"); - NSString *set_uuid = get_string(settings, "uuid"); + NSString *set_app = get_string(settings, "app_name"); + NSString *set_name = get_string(settings, "name"); + NSString *set_uuid = get_string(settings, "uuid"); - update_strings_from_context(s, settings, &set_app, &set_name, - &set_uuid); + update_strings_from_context(s, settings, &set_app, &set_name, &set_uuid); - obs_property_list_add_string(list, "", ""); - NSArray *arr = [[SyphonServerDirectory sharedDirectory] servers]; - for (NSDictionary *server in arr) { - NSString *app = server[SyphonServerDescriptionAppNameKey]; - NSString *name = server[SyphonServerDescriptionNameKey]; - NSString *uuid = server[SyphonServerDescriptionUUIDKey]; - NSString *serv = - [NSString stringWithFormat:@"[%@] %@", app, name]; + obs_property_list_add_string(list, "", ""); + NSArray *arr = [[SyphonServerDirectory sharedDirectory] servers]; + for (NSDictionary *server in arr) { + NSString *app = server[SyphonServerDescriptionAppNameKey]; + NSString *name = server[SyphonServerDescriptionNameKey]; + NSString *uuid = server[SyphonServerDescriptionUUIDKey]; + NSString *serv = [NSString stringWithFormat:@"[%@] %@", app, name]; - obs_property_list_add_string(list, serv.UTF8String, - uuid.UTF8String); + obs_property_list_add_string(list, serv.UTF8String, uuid.UTF8String); - if (!found_current) - found_current = [uuid isEqual:set_uuid]; - } + if (!found_current) + found_current = [uuid isEqual:set_uuid]; + } - if (found_current || !set_uuid.length || !set_app.length) - return; + if (found_current || !set_uuid.length || !set_app.length) + return; - NSString *serv = - [NSString stringWithFormat:@"[%@] %@", set_app, set_name]; - size_t idx = obs_property_list_add_string(list, serv.UTF8String, - set_uuid.UTF8String); - obs_property_list_item_disable(list, idx, true); + NSString *serv = [NSString stringWithFormat:@"[%@] %@", set_app, set_name]; + size_t idx = obs_property_list_add_string(list, serv.UTF8String, set_uuid.UTF8String); + obs_property_list_item_disable(list, idx, true); } -static bool servers_changed(obs_properties_t *props, obs_property_t *list, - obs_data_t *settings) +static bool servers_changed(obs_properties_t *props, obs_property_t *list, obs_data_t *settings) { - @autoreleasepool { - obs_property_list_clear(list); - add_servers(obs_properties_get_param(props), list, settings); - return true; - } + @autoreleasepool { + obs_property_list_clear(list); + add_servers(obs_properties_get_param(props), list, settings); + return true; + } } -static bool update_crop(obs_properties_t *props, obs_property_t *prop, - obs_data_t *settings) +static bool update_crop(obs_properties_t *props, obs_property_t *prop, obs_data_t *settings) { - bool enabled = obs_data_get_bool(settings, "crop"); + bool enabled = obs_data_get_bool(settings, "crop"); -#define LOAD_CROP(x) \ - prop = obs_properties_get(props, "crop." #x); \ - obs_property_set_enabled(prop, enabled); - LOAD_CROP(origin.x); - LOAD_CROP(origin.y); - LOAD_CROP(size.width); - LOAD_CROP(size.height); +#define LOAD_CROP(x) \ + prop = obs_properties_get(props, "crop." #x); \ + obs_property_set_enabled(prop, enabled); + LOAD_CROP(origin.x); + LOAD_CROP(origin.y); + LOAD_CROP(size.width); + LOAD_CROP(size.height); #undef LOAD_CROP - return true; + return true; } static void show_syphon_license_internal(void) { - char *path = obs_module_file("syphon_license.txt"); - if (!path) - return; + char *path = obs_module_file("syphon_license.txt"); + if (!path) + return; - NSWorkspace *ws = [NSWorkspace sharedWorkspace]; + NSWorkspace *ws = [NSWorkspace sharedWorkspace]; - NSURL *url = [NSURL - URLWithString: - [@"file://" - stringByAppendingString: - [NSString - stringWithCString:path - encoding:NSUTF8StringEncoding]]]; - [ws openURL:url]; - bfree(path); + NSURL *url = + [NSURL URLWithString:[@"file://" stringByAppendingString:[NSString stringWithCString:path + encoding:NSUTF8StringEncoding]]]; + [ws openURL:url]; + bfree(path); } -static bool show_syphon_license(obs_properties_t *props, obs_property_t *prop, - void *data) +static bool show_syphon_license(obs_properties_t *props, obs_property_t *prop, void *data) { - UNUSED_PARAMETER(props); - UNUSED_PARAMETER(prop); - UNUSED_PARAMETER(data); + UNUSED_PARAMETER(props); + UNUSED_PARAMETER(prop); + UNUSED_PARAMETER(data); - @autoreleasepool { - show_syphon_license_internal(); - return false; - } + @autoreleasepool { + show_syphon_license_internal(); + return false; + } } static void syphon_release(void *param) { - if (!param) - return; + if (!param) + return; - obs_source_release(((syphon_t)param)->source); + obs_source_release(((syphon_t) param)->source); } static inline obs_properties_t *syphon_properties_internal(syphon_t s) { - if (s && obs_source_get_ref(s->source) == NULL) { - s = NULL; - } + if (s && obs_source_get_ref(s->source) == NULL) { + s = NULL; + } - obs_properties_t *props = - obs_properties_create_param(s, syphon_release); + obs_properties_t *props = obs_properties_create_param(s, syphon_release); - obs_property_t *list = obs_properties_add_list( - props, "uuid", obs_module_text("Source"), OBS_COMBO_TYPE_LIST, - OBS_COMBO_FORMAT_STRING); - obs_property_set_modified_callback(list, servers_changed); + obs_property_t *list = + obs_properties_add_list(props, "uuid", obs_module_text("Source"), OBS_COMBO_TYPE_LIST, OBS_COMBO_FORMAT_STRING); + obs_property_set_modified_callback(list, servers_changed); - obs_properties_add_bool(props, "allow_transparency", - obs_module_text("AllowTransparency")); + obs_properties_add_bool(props, "allow_transparency", obs_module_text("AllowTransparency")); - obs_property_t *crop = - obs_properties_add_bool(props, "crop", obs_module_text("Crop")); - obs_property_set_modified_callback(crop, update_crop); + obs_property_t *crop = obs_properties_add_bool(props, "crop", obs_module_text("Crop")); + obs_property_set_modified_callback(crop, update_crop); -#define LOAD_CROP(x) \ - obs_properties_add_float(props, "crop." #x, \ - obs_module_text("Crop." #x), 0., 4096.f, \ - .5f); - LOAD_CROP(origin.x); - LOAD_CROP(origin.y); - LOAD_CROP(size.width); - LOAD_CROP(size.height); +#define LOAD_CROP(x) obs_properties_add_float(props, "crop." #x, obs_module_text("Crop." #x), 0., 4096.f, .5f); + LOAD_CROP(origin.x); + LOAD_CROP(origin.y); + LOAD_CROP(size.width); + LOAD_CROP(size.height); #undef LOAD_CROP - obs_properties_add_button(props, "syphon license", - obs_module_text("SyphonLicense"), - show_syphon_license); + obs_properties_add_button(props, "syphon license", obs_module_text("SyphonLicense"), show_syphon_license); - return props; + return props; } static obs_properties_t *syphon_properties(void *data) { - @autoreleasepool { - return syphon_properties_internal(data); - } + @autoreleasepool { + return syphon_properties_internal(data); + } } static inline void syphon_save_internal(syphon_t s, obs_data_t *settings) { - if (!s->uuid_changed) - return; + if (!s->uuid_changed) + return; - obs_data_set_string(settings, "app_name", s->app_name.UTF8String); - obs_data_set_string(settings, "name", s->name.UTF8String); - obs_data_set_string(settings, "uuid", s->uuid.UTF8String); + obs_data_set_string(settings, "app_name", s->app_name.UTF8String); + obs_data_set_string(settings, "name", s->name.UTF8String); + obs_data_set_string(settings, "uuid", s->uuid.UTF8String); } static void syphon_save(void *data, obs_data_t *settings) { - @autoreleasepool { - syphon_save_internal(data, settings); - } + @autoreleasepool { + syphon_save_internal(data, settings); + } } -static inline void build_sprite(struct gs_vb_data *data, float fcx, float fcy, - float start_u, float end_u, float start_v, - float end_v) +static inline void build_sprite(struct gs_vb_data *data, float fcx, float fcy, float start_u, float end_u, + float start_v, float end_v) { - struct vec2 *tvarray = data->tvarray[0].array; + struct vec2 *tvarray = data->tvarray[0].array; - vec3_set(data->points + 1, fcx, 0.0f, 0.0f); - vec3_set(data->points + 2, 0.0f, fcy, 0.0f); - vec3_set(data->points + 3, fcx, fcy, 0.0f); - vec2_set(tvarray, start_u, start_v); - vec2_set(tvarray + 1, end_u, start_v); - vec2_set(tvarray + 2, start_u, end_v); - vec2_set(tvarray + 3, end_u, end_v); + vec3_set(data->points + 1, fcx, 0.0f, 0.0f); + vec3_set(data->points + 2, 0.0f, fcy, 0.0f); + vec3_set(data->points + 3, fcx, fcy, 0.0f); + vec2_set(tvarray, start_u, start_v); + vec2_set(tvarray + 1, end_u, start_v); + vec2_set(tvarray + 2, start_u, end_v); + vec2_set(tvarray + 3, end_u, end_v); } -static inline void build_sprite_rect(struct gs_vb_data *data, float origin_x, - float origin_y, float end_x, float end_y) +static inline void build_sprite_rect(struct gs_vb_data *data, float origin_x, float origin_y, float end_x, float end_y) { - build_sprite(data, fabsf(end_x - origin_x), fabsf(end_y - origin_y), - origin_x, end_x, origin_y, end_y); + build_sprite(data, fabsf(end_x - origin_x), fabsf(end_y - origin_y), origin_x, end_x, origin_y, end_y); } static void syphon_video_tick(void *data, float seconds) { - UNUSED_PARAMETER(seconds); + UNUSED_PARAMETER(seconds); - syphon_t s = data; + syphon_t s = data; - if (!s->tex) - return; + if (!s->tex) + return; - static const CGRect null_crop = {{0.f}}; - const CGRect *crop = &null_crop; - if (s->crop) - crop = &s->crop_rect; + static const CGRect null_crop = {{0.f}}; + const CGRect *crop = &null_crop; + if (s->crop) + crop = &s->crop_rect; - obs_enter_graphics(); - build_sprite_rect(gs_vertexbuffer_get_data(s->vertbuffer), - (float)crop->origin.x, - s->height - (float)crop->origin.y, - s->width - (float)crop->size.width, - (float)crop->size.height); - obs_leave_graphics(); + obs_enter_graphics(); + build_sprite_rect(gs_vertexbuffer_get_data(s->vertbuffer), (float) crop->origin.x, + s->height - (float) crop->origin.y, s->width - (float) crop->size.width, + (float) crop->size.height); + obs_leave_graphics(); } static void syphon_video_render(void *data, gs_effect_t *effect) { - UNUSED_PARAMETER(effect); + UNUSED_PARAMETER(effect); - syphon_t s = data; + syphon_t s = data; - if (!s->tex) - return; + if (!s->tex) + return; - gs_vertexbuffer_flush(s->vertbuffer); - gs_load_vertexbuffer(s->vertbuffer); - gs_load_indexbuffer(NULL); - gs_load_samplerstate(s->sampler, 0); - const char *tech_name = s->allow_transparency ? "Draw" : "DrawOpaque"; - gs_technique_t *tech = gs_effect_get_technique(s->effect, tech_name); - gs_effect_set_texture(gs_effect_get_param_by_name(s->effect, "image"), - s->tex); - gs_technique_begin(tech); - gs_technique_begin_pass(tech, 0); + gs_vertexbuffer_flush(s->vertbuffer); + gs_load_vertexbuffer(s->vertbuffer); + gs_load_indexbuffer(NULL); + gs_load_samplerstate(s->sampler, 0); + const char *tech_name = s->allow_transparency ? "Draw" : "DrawOpaque"; + gs_technique_t *tech = gs_effect_get_technique(s->effect, tech_name); + gs_effect_set_texture(gs_effect_get_param_by_name(s->effect, "image"), s->tex); + gs_technique_begin(tech); + gs_technique_begin_pass(tech, 0); - gs_draw(GS_TRISTRIP, 0, 4); + gs_draw(GS_TRISTRIP, 0, 4); - gs_technique_end_pass(tech); - gs_technique_end(tech); + gs_technique_end_pass(tech); + gs_technique_end(tech); } static uint32_t syphon_get_width(void *data) { - syphon_t s = (syphon_t)data; - if (!s->crop) - return s->width; - int32_t width = s->width - (int)s->crop_rect.origin.x - - (int)s->crop_rect.size.width; - return MAX(0, width); + syphon_t s = (syphon_t) data; + if (!s->crop) + return s->width; + int32_t width = s->width - (int) s->crop_rect.origin.x - (int) s->crop_rect.size.width; + return MAX(0, width); } static uint32_t syphon_get_height(void *data) { - syphon_t s = (syphon_t)data; - if (!s->crop) - return s->height; - int32_t height = s->height - (int)s->crop_rect.origin.y - - (int)s->crop_rect.size.height; - return MAX(0, height); + syphon_t s = (syphon_t) data; + if (!s->crop) + return s->height; + int32_t height = s->height - (int) s->crop_rect.origin.y - (int) s->crop_rect.size.height; + return MAX(0, height); } static inline bool update_syphon(syphon_t s, obs_data_t *settings) { - NSArray *arr = [[SyphonServerDirectory sharedDirectory] servers]; + NSArray *arr = [[SyphonServerDirectory sharedDirectory] servers]; - if (!load_syphon_settings(s, settings)) - return false; + if (!load_syphon_settings(s, settings)) + return false; - NSDictionary *dict = find_by_uuid(arr, s->uuid); - if (dict) { - NSString *app = dict[SyphonServerDescriptionAppNameKey]; - NSString *name = dict[SyphonServerDescriptionNameKey]; - obs_data_set_string(settings, "app_name", app.UTF8String); - obs_data_set_string(settings, "name", name.UTF8String); - load_syphon_settings(s, settings); + NSDictionary *dict = find_by_uuid(arr, s->uuid); + if (dict) { + NSString *app = dict[SyphonServerDescriptionAppNameKey]; + NSString *name = dict[SyphonServerDescriptionNameKey]; + obs_data_set_string(settings, "app_name", app.UTF8String); + obs_data_set_string(settings, "name", name.UTF8String); + load_syphon_settings(s, settings); - } else if (!dict && !s->uuid.length) { - obs_data_set_string(settings, "app_name", ""); - obs_data_set_string(settings, "name", ""); - load_syphon_settings(s, settings); - } + } else if (!dict && !s->uuid.length) { + obs_data_set_string(settings, "app_name", ""); + obs_data_set_string(settings, "name", ""); + load_syphon_settings(s, settings); + } - return true; + return true; } static void syphon_update_internal(syphon_t s, obs_data_t *settings) { - s->allow_transparency = - obs_data_get_bool(settings, "allow_transparency"); + s->allow_transparency = obs_data_get_bool(settings, "allow_transparency"); - load_crop(s, settings); + load_crop(s, settings); - if (update_syphon(s, settings)) - create_client(s); + if (update_syphon(s, settings)) + create_client(s); } static void syphon_update(void *data, obs_data_t *settings) { - @autoreleasepool { - syphon_update_internal(data, settings); - } + @autoreleasepool { + syphon_update_internal(data, settings); + } } struct obs_source_info syphon_info = { - .id = "syphon-input", - .type = OBS_SOURCE_TYPE_INPUT, - .output_flags = OBS_SOURCE_VIDEO | OBS_SOURCE_CUSTOM_DRAW | - OBS_SOURCE_DO_NOT_DUPLICATE, - .get_name = syphon_get_name, - .create = syphon_create, - .destroy = syphon_destroy, - .video_render = syphon_video_render, - .video_tick = syphon_video_tick, - .get_properties = syphon_properties, - .get_width = syphon_get_width, - .get_height = syphon_get_height, - .update = syphon_update, - .save = syphon_save, - .icon_type = OBS_ICON_TYPE_GAME_CAPTURE, + .id = "syphon-input", + .type = OBS_SOURCE_TYPE_INPUT, + .output_flags = OBS_SOURCE_VIDEO | OBS_SOURCE_CUSTOM_DRAW | OBS_SOURCE_DO_NOT_DUPLICATE, + .get_name = syphon_get_name, + .create = syphon_create, + .destroy = syphon_destroy, + .video_render = syphon_video_render, + .video_tick = syphon_video_tick, + .get_properties = syphon_properties, + .get_width = syphon_get_width, + .get_height = syphon_get_height, + .update = syphon_update, + .save = syphon_save, + .icon_type = OBS_ICON_TYPE_GAME_CAPTURE, }; diff --git a/plugins/mac-virtualcam/src/dal-plugin/CMSampleBufferUtils.mm b/plugins/mac-virtualcam/src/dal-plugin/CMSampleBufferUtils.mm index 7b106f281..2085b3f9a 100644 --- a/plugins/mac-virtualcam/src/dal-plugin/CMSampleBufferUtils.mm +++ b/plugins/mac-virtualcam/src/dal-plugin/CMSampleBufferUtils.mm @@ -7,22 +7,19 @@ #import "CMSampleBufferUtils.h" -CMSampleTimingInfo CMSampleTimingInfoForTimestamp(uint64_t timestampNanos, - uint32_t fpsNumerator, - uint32_t fpsDenominator) +CMSampleTimingInfo CMSampleTimingInfoForTimestamp(uint64_t timestampNanos, uint32_t fpsNumerator, + uint32_t fpsDenominator) { - // The timing here is quite important. For frames to be delivered correctly and successfully be recorded by apps - // like QuickTime Player, we need to be accurate in both our timestamps _and_ have a sensible scale. Using large - // timestamps and scales like clock_gettime_nsec_np() and NSEC_PER_SEC will work for display, but will error out - // when trying to record. - // - // 600 is a common default in Apple's docs https://developer.apple.com/documentation/avfoundation/avmutablemovie/1390622-timescale - CMTimeScale scale = 600; - CMSampleTimingInfo timing; - timing.duration = - CMTimeMake(fpsDenominator * scale, fpsNumerator * scale); - timing.presentationTimeStamp = CMTimeMakeWithSeconds( - timestampNanos / (double)NSEC_PER_SEC, scale); - timing.decodeTimeStamp = kCMTimeInvalid; - return timing; + // The timing here is quite important. For frames to be delivered correctly and successfully be recorded by apps + // like QuickTime Player, we need to be accurate in both our timestamps _and_ have a sensible scale. Using large + // timestamps and scales like clock_gettime_nsec_np() and NSEC_PER_SEC will work for display, but will error out + // when trying to record. + // + // 600 is a common default in Apple's docs https://developer.apple.com/documentation/avfoundation/avmutablemovie/1390622-timescale + CMTimeScale scale = 600; + CMSampleTimingInfo timing; + timing.duration = CMTimeMake(fpsDenominator * scale, fpsNumerator * scale); + timing.presentationTimeStamp = CMTimeMakeWithSeconds(timestampNanos / (double) NSEC_PER_SEC, scale); + timing.decodeTimeStamp = kCMTimeInvalid; + return timing; } diff --git a/plugins/mac-virtualcam/src/dal-plugin/Defines.h b/plugins/mac-virtualcam/src/dal-plugin/Defines.h index 1d1705aeb..a2a1c813b 100644 --- a/plugins/mac-virtualcam/src/dal-plugin/Defines.h +++ b/plugins/mac-virtualcam/src/dal-plugin/Defines.h @@ -17,5 +17,5 @@ // You should have received a copy of the GNU General Public License // along with obs-mac-virtualcam. If not, see . -#define PLUGIN_NAME @"mac-virtualcam" +#define PLUGIN_NAME @"mac-virtualcam" #define PLUGIN_VERSION @"1.3.0" diff --git a/plugins/mac-virtualcam/src/dal-plugin/Logging.h b/plugins/mac-virtualcam/src/dal-plugin/Logging.h index 49accffac..268cab40f 100644 --- a/plugins/mac-virtualcam/src/dal-plugin/Logging.h +++ b/plugins/mac-virtualcam/src/dal-plugin/Logging.h @@ -23,18 +23,17 @@ #include "Defines.h" #ifdef DEBUG -#define DLog(fmt, ...) NSLog((PLUGIN_NAME @"(DAL): " fmt), ##__VA_ARGS__) -#define DLogFunc(fmt, ...) \ - NSLog((PLUGIN_NAME @"(DAL): %s " fmt), __FUNCTION__, ##__VA_ARGS__) +#define DLog(fmt, ...) NSLog((PLUGIN_NAME @"(DAL): " fmt), ##__VA_ARGS__) +#define DLogFunc(fmt, ...) NSLog((PLUGIN_NAME @"(DAL): %s " fmt), __FUNCTION__, ##__VA_ARGS__) #else -#define DLog(...) (void)sizeof(__VA_ARGS__) -#define DLogFunc(...) (void)sizeof(__VA_ARGS__) +#define DLog(...) (void) sizeof(__VA_ARGS__) +#define DLogFunc(...) (void) sizeof(__VA_ARGS__) #endif #define VLog(fmt, ...) #define VLogFunc(fmt, ...) #define ELog(fmt, ...) DLog(fmt, ##__VA_ARGS__) -#define UNUSED_PARAMETER(param) (void)param +#define UNUSED_PARAMETER(param) (void) param #endif /* Logging_h */ diff --git a/plugins/mac-virtualcam/src/dal-plugin/OBSDALDevice.mm b/plugins/mac-virtualcam/src/dal-plugin/OBSDALDevice.mm index 3ff468024..fbf900a53 100644 --- a/plugins/mac-virtualcam/src/dal-plugin/OBSDALDevice.mm +++ b/plugins/mac-virtualcam/src/dal-plugin/OBSDALDevice.mm @@ -33,247 +33,240 @@ // Note that the DAL's API calls HasProperty before calling GetPropertyDataSize. This means that it can be assumed that address is valid for the property involved. - (UInt32)getPropertyDataSizeWithAddress:(CMIOObjectPropertyAddress)address - qualifierDataSize:(UInt32)qualifierDataSize - qualifierData:(nonnull const void *)qualifierData + qualifierDataSize:(UInt32)qualifierDataSize + qualifierData:(nonnull const void *)qualifierData { + switch (address.mSelector) { + case kCMIOObjectPropertyName: + return sizeof(CFStringRef); + case kCMIOObjectPropertyManufacturer: + return sizeof(CFStringRef); + case kCMIOObjectPropertyElementCategoryName: + return sizeof(CFStringRef); + case kCMIOObjectPropertyElementNumberName: + return sizeof(CFStringRef); + case kCMIODevicePropertyPlugIn: + return sizeof(CMIOObjectID); + case kCMIODevicePropertyDeviceUID: + return sizeof(CFStringRef); + case kCMIODevicePropertyModelUID: + return sizeof(CFStringRef); + case kCMIODevicePropertyTransportType: + return sizeof(UInt32); + case kCMIODevicePropertyDeviceIsAlive: + return sizeof(UInt32); + case kCMIODevicePropertyDeviceHasChanged: + return sizeof(UInt32); + case kCMIODevicePropertyDeviceIsRunning: + return sizeof(UInt32); + case kCMIODevicePropertyDeviceIsRunningSomewhere: + return sizeof(UInt32); + case kCMIODevicePropertyDeviceCanBeDefaultDevice: + return sizeof(UInt32); + case kCMIODevicePropertyHogMode: + return sizeof(pid_t); + case kCMIODevicePropertyLatency: + return sizeof(UInt32); + case kCMIODevicePropertyStreams: + // Only one stream + return sizeof(CMIOStreamID) * 1; + case kCMIODevicePropertyStreamConfiguration: + // Only one stream + return sizeof(UInt32) + (sizeof(UInt32) * 1); + case kCMIODevicePropertyExcludeNonDALAccess: + return sizeof(UInt32); + case kCMIODevicePropertyCanProcessAVCCommand: + return sizeof(Boolean); + case kCMIODevicePropertyCanProcessRS422Command: + return sizeof(Boolean); + case kCMIODevicePropertyLinkedCoreAudioDeviceUID: + return sizeof(CFStringRef); + case kCMIODevicePropertyDeviceMaster: + return sizeof(pid_t); + default: + break; + }; - switch (address.mSelector) { - case kCMIOObjectPropertyName: - return sizeof(CFStringRef); - case kCMIOObjectPropertyManufacturer: - return sizeof(CFStringRef); - case kCMIOObjectPropertyElementCategoryName: - return sizeof(CFStringRef); - case kCMIOObjectPropertyElementNumberName: - return sizeof(CFStringRef); - case kCMIODevicePropertyPlugIn: - return sizeof(CMIOObjectID); - case kCMIODevicePropertyDeviceUID: - return sizeof(CFStringRef); - case kCMIODevicePropertyModelUID: - return sizeof(CFStringRef); - case kCMIODevicePropertyTransportType: - return sizeof(UInt32); - case kCMIODevicePropertyDeviceIsAlive: - return sizeof(UInt32); - case kCMIODevicePropertyDeviceHasChanged: - return sizeof(UInt32); - case kCMIODevicePropertyDeviceIsRunning: - return sizeof(UInt32); - case kCMIODevicePropertyDeviceIsRunningSomewhere: - return sizeof(UInt32); - case kCMIODevicePropertyDeviceCanBeDefaultDevice: - return sizeof(UInt32); - case kCMIODevicePropertyHogMode: - return sizeof(pid_t); - case kCMIODevicePropertyLatency: - return sizeof(UInt32); - case kCMIODevicePropertyStreams: - // Only one stream - return sizeof(CMIOStreamID) * 1; - case kCMIODevicePropertyStreamConfiguration: - // Only one stream - return sizeof(UInt32) + (sizeof(UInt32) * 1); - case kCMIODevicePropertyExcludeNonDALAccess: - return sizeof(UInt32); - case kCMIODevicePropertyCanProcessAVCCommand: - return sizeof(Boolean); - case kCMIODevicePropertyCanProcessRS422Command: - return sizeof(Boolean); - case kCMIODevicePropertyLinkedCoreAudioDeviceUID: - return sizeof(CFStringRef); - case kCMIODevicePropertyDeviceMaster: - return sizeof(pid_t); - default: - break; - }; - - return 0; + return 0; } // Note that the DAL's API calls HasProperty before calling GetPropertyData. This means that it can be assumed that address is valid for the property involved. - (void)getPropertyDataWithAddress:(CMIOObjectPropertyAddress)address - qualifierDataSize:(UInt32)qualifierDataSize - qualifierData:(nonnull const void *)qualifierData - dataSize:(UInt32)dataSize - dataUsed:(nonnull UInt32 *)dataUsed - data:(nonnull void *)data + qualifierDataSize:(UInt32)qualifierDataSize + qualifierData:(nonnull const void *)qualifierData + dataSize:(UInt32)dataSize + dataUsed:(nonnull UInt32 *)dataUsed + data:(nonnull void *)data { - - switch (address.mSelector) { - case kCMIOObjectPropertyName: - *static_cast(data) = CFSTR("OBS Virtual Camera"); - *dataUsed = sizeof(CFStringRef); - break; - case kCMIOObjectPropertyManufacturer: - *static_cast(data) = CFSTR("John Boiles"); - *dataUsed = sizeof(CFStringRef); - break; - case kCMIOObjectPropertyElementCategoryName: - *static_cast(data) = CFSTR("Virtual Camera"); - *dataUsed = sizeof(CFStringRef); - break; - case kCMIOObjectPropertyElementNumberName: - *static_cast(data) = CFSTR("0001"); - *dataUsed = sizeof(CFStringRef); - break; - case kCMIODevicePropertyPlugIn: - *static_cast(data) = self.pluginId; - *dataUsed = sizeof(CMIOObjectID); - break; - case kCMIODevicePropertyDeviceUID: - *static_cast(data) = - CFSTR("obs-virtual-cam-device"); - *dataUsed = sizeof(CFStringRef); - break; - case kCMIODevicePropertyModelUID: - *static_cast(data) = - CFSTR("obs-virtual-cam-model"); - *dataUsed = sizeof(CFStringRef); - break; - case kCMIODevicePropertyTransportType: - *static_cast(data) = - kIOAudioDeviceTransportTypeBuiltIn; - *dataUsed = sizeof(UInt32); - break; - case kCMIODevicePropertyDeviceIsAlive: - *static_cast(data) = 1; - *dataUsed = sizeof(UInt32); - break; - case kCMIODevicePropertyDeviceHasChanged: - *static_cast(data) = 0; - *dataUsed = sizeof(UInt32); - break; - case kCMIODevicePropertyDeviceIsRunning: - *static_cast(data) = 1; - *dataUsed = sizeof(UInt32); - break; - case kCMIODevicePropertyDeviceIsRunningSomewhere: - *static_cast(data) = 1; - *dataUsed = sizeof(UInt32); - break; - case kCMIODevicePropertyDeviceCanBeDefaultDevice: - *static_cast(data) = 1; - *dataUsed = sizeof(UInt32); - break; - case kCMIODevicePropertyHogMode: - *static_cast(data) = -1; - *dataUsed = sizeof(pid_t); - break; - case kCMIODevicePropertyLatency: - *static_cast(data) = 0; - *dataUsed = sizeof(UInt32); - break; - case kCMIODevicePropertyStreams: - *static_cast(data) = self.streamId; - *dataUsed = sizeof(CMIOObjectID); - break; - case kCMIODevicePropertyStreamConfiguration: - DLog(@"TODO kCMIODevicePropertyStreamConfiguration"); - break; - case kCMIODevicePropertyExcludeNonDALAccess: - *static_cast(data) = self.excludeNonDALAccess ? 1 : 0; - *dataUsed = sizeof(UInt32); - break; - case kCMIODevicePropertyCanProcessAVCCommand: - *static_cast(data) = false; - *dataUsed = sizeof(Boolean); - break; - case kCMIODevicePropertyCanProcessRS422Command: - *static_cast(data) = false; - *dataUsed = sizeof(Boolean); - break; - case kCMIODevicePropertyDeviceMaster: - *static_cast(data) = self.masterPid; - *dataUsed = sizeof(pid_t); - break; - default: - break; - }; + switch (address.mSelector) { + case kCMIOObjectPropertyName: + *static_cast(data) = CFSTR("OBS Virtual Camera"); + *dataUsed = sizeof(CFStringRef); + break; + case kCMIOObjectPropertyManufacturer: + *static_cast(data) = CFSTR("John Boiles"); + *dataUsed = sizeof(CFStringRef); + break; + case kCMIOObjectPropertyElementCategoryName: + *static_cast(data) = CFSTR("Virtual Camera"); + *dataUsed = sizeof(CFStringRef); + break; + case kCMIOObjectPropertyElementNumberName: + *static_cast(data) = CFSTR("0001"); + *dataUsed = sizeof(CFStringRef); + break; + case kCMIODevicePropertyPlugIn: + *static_cast(data) = self.pluginId; + *dataUsed = sizeof(CMIOObjectID); + break; + case kCMIODevicePropertyDeviceUID: + *static_cast(data) = CFSTR("obs-virtual-cam-device"); + *dataUsed = sizeof(CFStringRef); + break; + case kCMIODevicePropertyModelUID: + *static_cast(data) = CFSTR("obs-virtual-cam-model"); + *dataUsed = sizeof(CFStringRef); + break; + case kCMIODevicePropertyTransportType: + *static_cast(data) = kIOAudioDeviceTransportTypeBuiltIn; + *dataUsed = sizeof(UInt32); + break; + case kCMIODevicePropertyDeviceIsAlive: + *static_cast(data) = 1; + *dataUsed = sizeof(UInt32); + break; + case kCMIODevicePropertyDeviceHasChanged: + *static_cast(data) = 0; + *dataUsed = sizeof(UInt32); + break; + case kCMIODevicePropertyDeviceIsRunning: + *static_cast(data) = 1; + *dataUsed = sizeof(UInt32); + break; + case kCMIODevicePropertyDeviceIsRunningSomewhere: + *static_cast(data) = 1; + *dataUsed = sizeof(UInt32); + break; + case kCMIODevicePropertyDeviceCanBeDefaultDevice: + *static_cast(data) = 1; + *dataUsed = sizeof(UInt32); + break; + case kCMIODevicePropertyHogMode: + *static_cast(data) = -1; + *dataUsed = sizeof(pid_t); + break; + case kCMIODevicePropertyLatency: + *static_cast(data) = 0; + *dataUsed = sizeof(UInt32); + break; + case kCMIODevicePropertyStreams: + *static_cast(data) = self.streamId; + *dataUsed = sizeof(CMIOObjectID); + break; + case kCMIODevicePropertyStreamConfiguration: + DLog(@"TODO kCMIODevicePropertyStreamConfiguration"); + break; + case kCMIODevicePropertyExcludeNonDALAccess: + *static_cast(data) = self.excludeNonDALAccess ? 1 : 0; + *dataUsed = sizeof(UInt32); + break; + case kCMIODevicePropertyCanProcessAVCCommand: + *static_cast(data) = false; + *dataUsed = sizeof(Boolean); + break; + case kCMIODevicePropertyCanProcessRS422Command: + *static_cast(data) = false; + *dataUsed = sizeof(Boolean); + break; + case kCMIODevicePropertyDeviceMaster: + *static_cast(data) = self.masterPid; + *dataUsed = sizeof(pid_t); + break; + default: + break; + }; } - (BOOL)hasPropertyWithAddress:(CMIOObjectPropertyAddress)address { - switch (address.mSelector) { - case kCMIOObjectPropertyName: - case kCMIOObjectPropertyManufacturer: - case kCMIOObjectPropertyElementCategoryName: - case kCMIOObjectPropertyElementNumberName: - case kCMIODevicePropertyPlugIn: - case kCMIODevicePropertyDeviceUID: - case kCMIODevicePropertyModelUID: - case kCMIODevicePropertyTransportType: - case kCMIODevicePropertyDeviceIsAlive: - case kCMIODevicePropertyDeviceHasChanged: - case kCMIODevicePropertyDeviceIsRunning: - case kCMIODevicePropertyDeviceIsRunningSomewhere: - case kCMIODevicePropertyDeviceCanBeDefaultDevice: - case kCMIODevicePropertyHogMode: - case kCMIODevicePropertyLatency: - case kCMIODevicePropertyStreams: - case kCMIODevicePropertyExcludeNonDALAccess: - case kCMIODevicePropertyCanProcessAVCCommand: - case kCMIODevicePropertyCanProcessRS422Command: - case kCMIODevicePropertyDeviceMaster: - return true; - case kCMIODevicePropertyStreamConfiguration: - case kCMIODevicePropertyLinkedCoreAudioDeviceUID: - return false; - default: - return false; - }; + switch (address.mSelector) { + case kCMIOObjectPropertyName: + case kCMIOObjectPropertyManufacturer: + case kCMIOObjectPropertyElementCategoryName: + case kCMIOObjectPropertyElementNumberName: + case kCMIODevicePropertyPlugIn: + case kCMIODevicePropertyDeviceUID: + case kCMIODevicePropertyModelUID: + case kCMIODevicePropertyTransportType: + case kCMIODevicePropertyDeviceIsAlive: + case kCMIODevicePropertyDeviceHasChanged: + case kCMIODevicePropertyDeviceIsRunning: + case kCMIODevicePropertyDeviceIsRunningSomewhere: + case kCMIODevicePropertyDeviceCanBeDefaultDevice: + case kCMIODevicePropertyHogMode: + case kCMIODevicePropertyLatency: + case kCMIODevicePropertyStreams: + case kCMIODevicePropertyExcludeNonDALAccess: + case kCMIODevicePropertyCanProcessAVCCommand: + case kCMIODevicePropertyCanProcessRS422Command: + case kCMIODevicePropertyDeviceMaster: + return true; + case kCMIODevicePropertyStreamConfiguration: + case kCMIODevicePropertyLinkedCoreAudioDeviceUID: + return false; + default: + return false; + }; } - (BOOL)isPropertySettableWithAddress:(CMIOObjectPropertyAddress)address { - switch (address.mSelector) { - case kCMIOObjectPropertyName: - case kCMIOObjectPropertyManufacturer: - case kCMIOObjectPropertyElementCategoryName: - case kCMIOObjectPropertyElementNumberName: - case kCMIODevicePropertyPlugIn: - case kCMIODevicePropertyDeviceUID: - case kCMIODevicePropertyModelUID: - case kCMIODevicePropertyTransportType: - case kCMIODevicePropertyDeviceIsAlive: - case kCMIODevicePropertyDeviceHasChanged: - case kCMIODevicePropertyDeviceIsRunning: - case kCMIODevicePropertyDeviceIsRunningSomewhere: - case kCMIODevicePropertyDeviceCanBeDefaultDevice: - case kCMIODevicePropertyHogMode: - case kCMIODevicePropertyLatency: - case kCMIODevicePropertyStreams: - case kCMIODevicePropertyStreamConfiguration: - case kCMIODevicePropertyCanProcessAVCCommand: - case kCMIODevicePropertyCanProcessRS422Command: - case kCMIODevicePropertyLinkedCoreAudioDeviceUID: - return false; - case kCMIODevicePropertyExcludeNonDALAccess: - case kCMIODevicePropertyDeviceMaster: - return true; - default: - return false; - }; + switch (address.mSelector) { + case kCMIOObjectPropertyName: + case kCMIOObjectPropertyManufacturer: + case kCMIOObjectPropertyElementCategoryName: + case kCMIOObjectPropertyElementNumberName: + case kCMIODevicePropertyPlugIn: + case kCMIODevicePropertyDeviceUID: + case kCMIODevicePropertyModelUID: + case kCMIODevicePropertyTransportType: + case kCMIODevicePropertyDeviceIsAlive: + case kCMIODevicePropertyDeviceHasChanged: + case kCMIODevicePropertyDeviceIsRunning: + case kCMIODevicePropertyDeviceIsRunningSomewhere: + case kCMIODevicePropertyDeviceCanBeDefaultDevice: + case kCMIODevicePropertyHogMode: + case kCMIODevicePropertyLatency: + case kCMIODevicePropertyStreams: + case kCMIODevicePropertyStreamConfiguration: + case kCMIODevicePropertyCanProcessAVCCommand: + case kCMIODevicePropertyCanProcessRS422Command: + case kCMIODevicePropertyLinkedCoreAudioDeviceUID: + return false; + case kCMIODevicePropertyExcludeNonDALAccess: + case kCMIODevicePropertyDeviceMaster: + return true; + default: + return false; + }; } - (void)setPropertyDataWithAddress:(CMIOObjectPropertyAddress)address - qualifierDataSize:(UInt32)qualifierDataSize - qualifierData:(nonnull const void *)qualifierData - dataSize:(UInt32)dataSize - data:(nonnull const void *)data + qualifierDataSize:(UInt32)qualifierDataSize + qualifierData:(nonnull const void *)qualifierData + dataSize:(UInt32)dataSize + data:(nonnull const void *)data { - - switch (address.mSelector) { - case kCMIODevicePropertyExcludeNonDALAccess: - self.excludeNonDALAccess = - (*static_cast(data) != 0); - break; - case kCMIODevicePropertyDeviceMaster: - self.masterPid = *static_cast(data); - break; - default: - break; - }; + switch (address.mSelector) { + case kCMIODevicePropertyExcludeNonDALAccess: + self.excludeNonDALAccess = (*static_cast(data) != 0); + break; + case kCMIODevicePropertyDeviceMaster: + self.masterPid = *static_cast(data); + break; + default: + break; + }; } @end diff --git a/plugins/mac-virtualcam/src/dal-plugin/OBSDALMachClient.h b/plugins/mac-virtualcam/src/dal-plugin/OBSDALMachClient.h index 3323432d4..176c3f7dd 100644 --- a/plugins/mac-virtualcam/src/dal-plugin/OBSDALMachClient.h +++ b/plugins/mac-virtualcam/src/dal-plugin/OBSDALMachClient.h @@ -13,9 +13,9 @@ NS_ASSUME_NONNULL_BEGIN @protocol MachClientDelegate - (void)receivedPixelBuffer:(CVPixelBufferRef)frame - timestamp:(uint64_t)timestamp - fpsNumerator:(uint32_t)fpsNumerator - fpsDenominator:(uint32_t)fpsDenominator; + timestamp:(uint64_t)timestamp + fpsNumerator:(uint32_t)fpsNumerator + fpsDenominator:(uint32_t)fpsDenominator; - (void)receivedStop; @end diff --git a/plugins/mac-virtualcam/src/dal-plugin/OBSDALMachClient.mm b/plugins/mac-virtualcam/src/dal-plugin/OBSDALMachClient.mm index 303a3a4dc..0bff701b3 100644 --- a/plugins/mac-virtualcam/src/dal-plugin/OBSDALMachClient.mm +++ b/plugins/mac-virtualcam/src/dal-plugin/OBSDALMachClient.mm @@ -10,7 +10,7 @@ #import "Logging.h" @interface OBSDALMachClient () { - NSPort *_receivePort; + NSPort *_receivePort; } @end @@ -18,8 +18,8 @@ - (void)dealloc { - DLogFunc(@""); - _receivePort.delegate = nil; + DLogFunc(@""); + _receivePort.delegate = nil; } - (NSPort *)serverPort @@ -27,154 +27,129 @@ // See note in MachServer.mm and don't judge me #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wdeprecated-declarations" - return [[NSMachBootstrapServer sharedInstance] - portForName:@MACH_SERVICE_NAME]; + return [[NSMachBootstrapServer sharedInstance] portForName:@MACH_SERVICE_NAME]; #pragma clang diagnostic pop } - (BOOL)isServerAvailable { - return [self serverPort] != nil; + return [self serverPort] != nil; } - (NSPort *)receivePort { - if (_receivePort == nil) { - NSPort *receivePort = [NSMachPort port]; - _receivePort = receivePort; - _receivePort.delegate = self; - __weak __typeof(self) weakSelf = self; - dispatch_async( - dispatch_get_global_queue( - DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), - ^{ - NSRunLoop *runLoop = [NSRunLoop currentRunLoop]; - [runLoop addPort:receivePort - forMode:NSDefaultRunLoopMode]; - // weakSelf should become nil when this object gets destroyed - while (weakSelf) { - [[NSRunLoop currentRunLoop] - runUntilDate: - [NSDate dateWithTimeIntervalSinceNow: - 0.1]]; - } - DLog(@"Shutting down receive run loop"); - }); - DLog(@"Initialized mach port %d for receiving", - ((NSMachPort *)_receivePort).machPort); - } - return _receivePort; + if (_receivePort == nil) { + NSPort *receivePort = [NSMachPort port]; + _receivePort = receivePort; + _receivePort.delegate = self; + __weak __typeof(self) weakSelf = self; + dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ + NSRunLoop *runLoop = [NSRunLoop currentRunLoop]; + [runLoop addPort:receivePort forMode:NSDefaultRunLoopMode]; + // weakSelf should become nil when this object gets destroyed + while (weakSelf) { + [[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:0.1]]; + } + DLog(@"Shutting down receive run loop"); + }); + DLog(@"Initialized mach port %d for receiving", ((NSMachPort *) _receivePort).machPort); + } + return _receivePort; } - (BOOL)connectToServer { - DLogFunc(@""); + DLogFunc(@""); - NSPort *sendPort = [self serverPort]; - if (sendPort == nil) { - ELog(@"Unable to connect to server port"); - return NO; - } + NSPort *sendPort = [self serverPort]; + if (sendPort == nil) { + ELog(@"Unable to connect to server port"); + return NO; + } - NSPortMessage *message = [[NSPortMessage alloc] - initWithSendPort:sendPort - receivePort:self.receivePort - components:nil]; - message.msgid = MachMsgIdConnect; + NSPortMessage *message = [[NSPortMessage alloc] initWithSendPort:sendPort receivePort:self.receivePort + components:nil]; + message.msgid = MachMsgIdConnect; - NSDate *timeout = [NSDate dateWithTimeIntervalSinceNow:5.0]; - if (![message sendBeforeDate:timeout]) { - ELog(@"sendBeforeDate failed"); - return NO; - } + NSDate *timeout = [NSDate dateWithTimeIntervalSinceNow:5.0]; + if (![message sendBeforeDate:timeout]) { + ELog(@"sendBeforeDate failed"); + return NO; + } - return YES; + return YES; } - (void)handlePortMessage:(NSPortMessage *)message { - __strong id strongDelegate = self.delegate; + __strong id strongDelegate = self.delegate; - VLogFunc(@""); - NSArray *components = message.components; - switch (message.msgid) { - case MachMsgIdConnect: - DLog(@"Received connect response"); - break; - case MachMsgIdFrame: - VLog(@"Received frame message"); + VLogFunc(@""); + NSArray *components = message.components; + switch (message.msgid) { + case MachMsgIdConnect: + DLog(@"Received connect response"); + break; + case MachMsgIdFrame: + VLog(@"Received frame message"); - if (components.count < 4) - return; + if (components.count < 4) + return; - @autoreleasepool { - NSMachPort *framePort = (NSMachPort *)components[0]; + @autoreleasepool { + NSMachPort *framePort = (NSMachPort *) components[0]; - if (!framePort) - return; + if (!framePort) + return; - IOSurfaceRef surface = IOSurfaceLookupFromMachPort( - [framePort machPort]); + IOSurfaceRef surface = IOSurfaceLookupFromMachPort([framePort machPort]); - if (surface) { - /* + if (surface) { + /* * IOSurfaceLocks are only necessary on non Apple Silicon devices, as those have * unified memory. On Intel machines, the lock ensures that the IOSurface is copied back * from GPU memory to CPU memory so we can process the pixel buffer. */ #ifndef __aarch64__ - IOSurfaceLock(surface, kIOSurfaceLockReadOnly, - NULL); + IOSurfaceLock(surface, kIOSurfaceLockReadOnly, NULL); #endif - CVPixelBufferRef frame; - CVPixelBufferCreateWithIOSurface( - kCFAllocatorDefault, surface, NULL, - &frame); + CVPixelBufferRef frame; + CVPixelBufferCreateWithIOSurface(kCFAllocatorDefault, surface, NULL, &frame); #ifndef __aarch64__ - IOSurfaceUnlock(surface, kIOSurfaceLockReadOnly, - NULL); + IOSurfaceUnlock(surface, kIOSurfaceLockReadOnly, NULL); #endif - CFRelease(surface); + CFRelease(surface); - uint64_t timestamp; - [components[1] getBytes:×tamp - length:sizeof(timestamp)]; + uint64_t timestamp; + [components[1] getBytes:×tamp length:sizeof(timestamp)]; - VLog(@"Received frame data: %zux%zu (%llu)", - CVPixelBufferGetWidth(frame), - CVPixelBufferGetHeight(frame), timestamp); + VLog(@"Received frame data: %zux%zu (%llu)", CVPixelBufferGetWidth(frame), + CVPixelBufferGetHeight(frame), timestamp); - uint32_t fpsNumerator; - [components[2] getBytes:&fpsNumerator - length:sizeof(fpsNumerator)]; - uint32_t fpsDenominator; - [components[3] getBytes:&fpsDenominator - length:sizeof(fpsDenominator)]; + uint32_t fpsNumerator; + [components[2] getBytes:&fpsNumerator length:sizeof(fpsNumerator)]; + uint32_t fpsDenominator; + [components[3] getBytes:&fpsDenominator length:sizeof(fpsDenominator)]; - [strongDelegate - receivedPixelBuffer:frame - timestamp:timestamp - fpsNumerator:fpsNumerator - fpsDenominator:fpsDenominator]; + [strongDelegate receivedPixelBuffer:frame timestamp:timestamp fpsNumerator:fpsNumerator + fpsDenominator:fpsDenominator]; - CVPixelBufferRelease(frame); - } else { - ELog(@"Failed to obtain IOSurface from Mach port"); - } - [framePort invalidate]; - mach_port_deallocate(mach_task_self(), - [framePort machPort]); - } - break; - case MachMsgIdStop: - DLog(@"Received stop message"); - [strongDelegate receivedStop]; - break; - default: - ELog(@"Received unexpected response msgid %u", - (unsigned)message.msgid); - break; - } + CVPixelBufferRelease(frame); + } else { + ELog(@"Failed to obtain IOSurface from Mach port"); + } + [framePort invalidate]; + mach_port_deallocate(mach_task_self(), [framePort machPort]); + } + break; + case MachMsgIdStop: + DLog(@"Received stop message"); + [strongDelegate receivedStop]; + break; + default: + ELog(@"Received unexpected response msgid %u", (unsigned) message.msgid); + break; + } } @end diff --git a/plugins/mac-virtualcam/src/dal-plugin/OBSDALObjectStore.h b/plugins/mac-virtualcam/src/dal-plugin/OBSDALObjectStore.h index 4c329d9fe..028c2e9d2 100644 --- a/plugins/mac-virtualcam/src/dal-plugin/OBSDALObjectStore.h +++ b/plugins/mac-virtualcam/src/dal-plugin/OBSDALObjectStore.h @@ -27,19 +27,19 @@ NS_ASSUME_NONNULL_BEGIN - (BOOL)hasPropertyWithAddress:(CMIOObjectPropertyAddress)address; - (BOOL)isPropertySettableWithAddress:(CMIOObjectPropertyAddress)address; - (UInt32)getPropertyDataSizeWithAddress:(CMIOObjectPropertyAddress)address - qualifierDataSize:(UInt32)qualifierDataSize - qualifierData:(const void *)qualifierData; + qualifierDataSize:(UInt32)qualifierDataSize + qualifierData:(const void *)qualifierData; - (void)getPropertyDataWithAddress:(CMIOObjectPropertyAddress)address - qualifierDataSize:(UInt32)qualifierDataSize - qualifierData:(const void *)qualifierData - dataSize:(UInt32)dataSize - dataUsed:(UInt32 *)dataUsed - data:(void *)data; + qualifierDataSize:(UInt32)qualifierDataSize + qualifierData:(const void *)qualifierData + dataSize:(UInt32)dataSize + dataUsed:(UInt32 *)dataUsed + data:(void *)data; - (void)setPropertyDataWithAddress:(CMIOObjectPropertyAddress)address - qualifierDataSize:(UInt32)qualifierDataSize - qualifierData:(const void *)qualifierData - dataSize:(UInt32)dataSize - data:(const void *)data; + qualifierDataSize:(UInt32)qualifierDataSize + qualifierData:(const void *)qualifierData + dataSize:(UInt32)dataSize + data:(const void *)data; @end diff --git a/plugins/mac-virtualcam/src/dal-plugin/OBSDALObjectStore.mm b/plugins/mac-virtualcam/src/dal-plugin/OBSDALObjectStore.mm index e6e58ed00..b478fba6d 100644 --- a/plugins/mac-virtualcam/src/dal-plugin/OBSDALObjectStore.mm +++ b/plugins/mac-virtualcam/src/dal-plugin/OBSDALObjectStore.mm @@ -28,254 +28,252 @@ // 4-byte selectors to string for easy debugging + (NSString *)StringFromPropertySelector:(CMIOObjectPropertySelector)selector { - switch (selector) { - case kCMIODevicePropertyPlugIn: - return @"kCMIODevicePropertyPlugIn"; - case kCMIODevicePropertyDeviceUID: - return @"kCMIODevicePropertyDeviceUID"; - case kCMIODevicePropertyModelUID: - return @"kCMIODevicePropertyModelUID"; - case kCMIODevicePropertyTransportType: - return @"kCMIODevicePropertyTransportType"; - case kCMIODevicePropertyDeviceIsAlive: - return @"kCMIODevicePropertyDeviceIsAlive"; - case kCMIODevicePropertyDeviceHasChanged: - return @"kCMIODevicePropertyDeviceHasChanged"; - case kCMIODevicePropertyDeviceIsRunning: - return @"kCMIODevicePropertyDeviceIsRunning"; - case kCMIODevicePropertyDeviceIsRunningSomewhere: - return @"kCMIODevicePropertyDeviceIsRunningSomewhere"; - case kCMIODevicePropertyDeviceCanBeDefaultDevice: - return @"kCMIODevicePropertyDeviceCanBeDefaultDevice"; - case kCMIODevicePropertyHogMode: - return @"kCMIODevicePropertyHogMode"; - case kCMIODevicePropertyLatency: - return @"kCMIODevicePropertyLatency"; - case kCMIODevicePropertyStreams: - return @"kCMIODevicePropertyStreams"; - case kCMIODevicePropertyStreamConfiguration: - return @"kCMIODevicePropertyStreamConfiguration"; - case kCMIODevicePropertyDeviceMaster: - return @"kCMIODevicePropertyDeviceMaster"; - case kCMIODevicePropertyExcludeNonDALAccess: - return @"kCMIODevicePropertyExcludeNonDALAccess"; - case kCMIODevicePropertyClientSyncDiscontinuity: - return @"kCMIODevicePropertyClientSyncDiscontinuity"; - case kCMIODevicePropertySMPTETimeCallback: - return @"kCMIODevicePropertySMPTETimeCallback"; - case kCMIODevicePropertyCanProcessAVCCommand: - return @"kCMIODevicePropertyCanProcessAVCCommand"; - case kCMIODevicePropertyAVCDeviceType: - return @"kCMIODevicePropertyAVCDeviceType"; - case kCMIODevicePropertyAVCDeviceSignalMode: - return @"kCMIODevicePropertyAVCDeviceSignalMode"; - case kCMIODevicePropertyCanProcessRS422Command: - return @"kCMIODevicePropertyCanProcessRS422Command"; - case kCMIODevicePropertyLinkedCoreAudioDeviceUID: - return @"kCMIODevicePropertyLinkedCoreAudioDeviceUID"; - case kCMIODevicePropertyVideoDigitizerComponents: - return @"kCMIODevicePropertyVideoDigitizerComponents"; - case kCMIODevicePropertySuspendedByUser: - return @"kCMIODevicePropertySuspendedByUser"; - case kCMIODevicePropertyLinkedAndSyncedCoreAudioDeviceUID: - return @"kCMIODevicePropertyLinkedAndSyncedCoreAudioDeviceUID"; - case kCMIODevicePropertyIIDCInitialUnitSpace: - return @"kCMIODevicePropertyIIDCInitialUnitSpace"; - case kCMIODevicePropertyIIDCCSRData: - return @"kCMIODevicePropertyIIDCCSRData"; - case kCMIODevicePropertyCanSwitchFrameRatesWithoutFrameDrops: - return @"kCMIODevicePropertyCanSwitchFrameRatesWithoutFrameDrops"; - case kCMIODevicePropertyLocation: - return @"kCMIODevicePropertyLocation"; - case kCMIODevicePropertyDeviceHasStreamingError: - return @"kCMIODevicePropertyDeviceHasStreamingError"; - case kCMIODevicePropertyScopeInput: - return @"kCMIODevicePropertyScopeInput"; - case kCMIODevicePropertyScopeOutput: - return @"kCMIODevicePropertyScopeOutput"; - case kCMIODevicePropertyScopePlayThrough: - return @"kCMIODevicePropertyScopePlayThrough"; - case kCMIOObjectPropertyClass: - return @"kCMIOObjectPropertyClass"; - case kCMIOObjectPropertyOwner: - return @"kCMIOObjectPropertyOwner"; - case kCMIOObjectPropertyCreator: - return @"kCMIOObjectPropertyCreator"; - case kCMIOObjectPropertyName: - return @"kCMIOObjectPropertyName"; - case kCMIOObjectPropertyManufacturer: - return @"kCMIOObjectPropertyManufacturer"; - case kCMIOObjectPropertyElementName: - return @"kCMIOObjectPropertyElementName"; - case kCMIOObjectPropertyElementCategoryName: - return @"kCMIOObjectPropertyElementCategoryName"; - case kCMIOObjectPropertyElementNumberName: - return @"kCMIOObjectPropertyElementNumberName"; - case kCMIOObjectPropertyOwnedObjects: - return @"kCMIOObjectPropertyOwnedObjects"; - case kCMIOObjectPropertyListenerAdded: - return @"kCMIOObjectPropertyListenerAdded"; - case kCMIOObjectPropertyListenerRemoved: - return @"kCMIOObjectPropertyListenerRemoved"; - case kCMIOStreamPropertyDirection: - return @"kCMIOStreamPropertyDirection"; - case kCMIOStreamPropertyTerminalType: - return @"kCMIOStreamPropertyTerminalType"; - case kCMIOStreamPropertyStartingChannel: - return @"kCMIOStreamPropertyStartingChannel"; - // Same value as kCMIODevicePropertyLatency - // case kCMIOStreamPropertyLatency: - // return @"kCMIOStreamPropertyLatency"; - case kCMIOStreamPropertyFormatDescription: - return @"kCMIOStreamPropertyFormatDescription"; - case kCMIOStreamPropertyFormatDescriptions: - return @"kCMIOStreamPropertyFormatDescriptions"; - case kCMIOStreamPropertyStillImage: - return @"kCMIOStreamPropertyStillImage"; - case kCMIOStreamPropertyStillImageFormatDescriptions: - return @"kCMIOStreamPropertyStillImageFormatDescriptions"; - case kCMIOStreamPropertyFrameRate: - return @"kCMIOStreamPropertyFrameRate"; - case kCMIOStreamPropertyMinimumFrameRate: - return @"kCMIOStreamPropertyMinimumFrameRate"; - case kCMIOStreamPropertyFrameRates: - return @"kCMIOStreamPropertyFrameRates"; - case kCMIOStreamPropertyFrameRateRanges: - return @"kCMIOStreamPropertyFrameRateRanges"; - case kCMIOStreamPropertyNoDataTimeoutInMSec: - return @"kCMIOStreamPropertyNoDataTimeoutInMSec"; - case kCMIOStreamPropertyDeviceSyncTimeoutInMSec: - return @"kCMIOStreamPropertyDeviceSyncTimeoutInMSec"; - case kCMIOStreamPropertyNoDataEventCount: - return @"kCMIOStreamPropertyNoDataEventCount"; - case kCMIOStreamPropertyOutputBufferUnderrunCount: - return @"kCMIOStreamPropertyOutputBufferUnderrunCount"; - case kCMIOStreamPropertyOutputBufferRepeatCount: - return @"kCMIOStreamPropertyOutputBufferRepeatCount"; - case kCMIOStreamPropertyOutputBufferQueueSize: - return @"kCMIOStreamPropertyOutputBufferQueueSize"; - case kCMIOStreamPropertyOutputBuffersRequiredForStartup: - return @"kCMIOStreamPropertyOutputBuffersRequiredForStartup"; - case kCMIOStreamPropertyOutputBuffersNeededForThrottledPlayback: - return @"kCMIOStreamPropertyOutputBuffersNeededForThrottledPlayback"; - case kCMIOStreamPropertyFirstOutputPresentationTimeStamp: - return @"kCMIOStreamPropertyFirstOutputPresentationTimeStamp"; - case kCMIOStreamPropertyEndOfData: - return @"kCMIOStreamPropertyEndOfData"; - case kCMIOStreamPropertyClock: - return @"kCMIOStreamPropertyClock"; - case kCMIOStreamPropertyCanProcessDeckCommand: - return @"kCMIOStreamPropertyCanProcessDeckCommand"; - case kCMIOStreamPropertyDeck: - return @"kCMIOStreamPropertyDeck"; - case kCMIOStreamPropertyDeckFrameNumber: - return @"kCMIOStreamPropertyDeckFrameNumber"; - case kCMIOStreamPropertyDeckDropness: - return @"kCMIOStreamPropertyDeckDropness"; - case kCMIOStreamPropertyDeckThreaded: - return @"kCMIOStreamPropertyDeckThreaded"; - case kCMIOStreamPropertyDeckLocal: - return @"kCMIOStreamPropertyDeckLocal"; - case kCMIOStreamPropertyDeckCueing: - return @"kCMIOStreamPropertyDeckCueing"; - case kCMIOStreamPropertyInitialPresentationTimeStampForLinkedAndSyncedAudio: - return @"kCMIOStreamPropertyInitialPresentationTimeStampForLinkedAndSyncedAudio"; - case kCMIOStreamPropertyScheduledOutputNotificationProc: - return @"kCMIOStreamPropertyScheduledOutputNotificationProc"; - case kCMIOStreamPropertyPreferredFormatDescription: - return @"kCMIOStreamPropertyPreferredFormatDescription"; - case kCMIOStreamPropertyPreferredFrameRate: - return @"kCMIOStreamPropertyPreferredFrameRate"; - case kCMIOControlPropertyScope: - return @"kCMIOControlPropertyScope"; - case kCMIOControlPropertyElement: - return @"kCMIOControlPropertyElement"; - case kCMIOControlPropertyVariant: - return @"kCMIOControlPropertyVariant"; - case kCMIOHardwarePropertyProcessIsMaster: - return @"kCMIOHardwarePropertyProcessIsMaster"; - case kCMIOHardwarePropertyIsInitingOrExiting: - return @"kCMIOHardwarePropertyIsInitingOrExiting"; - case kCMIOHardwarePropertyDevices: - return @"kCMIOHardwarePropertyDevices"; - case kCMIOHardwarePropertyDefaultInputDevice: - return @"kCMIOHardwarePropertyDefaultInputDevice"; - case kCMIOHardwarePropertyDefaultOutputDevice: - return @"kCMIOHardwarePropertyDefaultOutputDevice"; - case kCMIOHardwarePropertyDeviceForUID: - return @"kCMIOHardwarePropertyDeviceForUID"; - case kCMIOHardwarePropertySleepingIsAllowed: - return @"kCMIOHardwarePropertySleepingIsAllowed"; - case kCMIOHardwarePropertyUnloadingIsAllowed: - return @"kCMIOHardwarePropertyUnloadingIsAllowed"; - case kCMIOHardwarePropertyPlugInForBundleID: - return @"kCMIOHardwarePropertyPlugInForBundleID"; - case kCMIOHardwarePropertyUserSessionIsActiveOrHeadless: - return @"kCMIOHardwarePropertyUserSessionIsActiveOrHeadless"; - case kCMIOHardwarePropertySuspendedBySystem: - return @"kCMIOHardwarePropertySuspendedBySystem"; - case kCMIOHardwarePropertyAllowScreenCaptureDevices: - return @"kCMIOHardwarePropertyAllowScreenCaptureDevices"; - case kCMIOHardwarePropertyAllowWirelessScreenCaptureDevices: - return @"kCMIOHardwarePropertyAllowWirelessScreenCaptureDevices"; - default: - uint8_t *chars = (uint8_t *)&selector; - return [NSString stringWithFormat:@"Unknown selector: %c%c%c%c", - chars[0], chars[1], chars[2], - chars[3]]; - } + switch (selector) { + case kCMIODevicePropertyPlugIn: + return @"kCMIODevicePropertyPlugIn"; + case kCMIODevicePropertyDeviceUID: + return @"kCMIODevicePropertyDeviceUID"; + case kCMIODevicePropertyModelUID: + return @"kCMIODevicePropertyModelUID"; + case kCMIODevicePropertyTransportType: + return @"kCMIODevicePropertyTransportType"; + case kCMIODevicePropertyDeviceIsAlive: + return @"kCMIODevicePropertyDeviceIsAlive"; + case kCMIODevicePropertyDeviceHasChanged: + return @"kCMIODevicePropertyDeviceHasChanged"; + case kCMIODevicePropertyDeviceIsRunning: + return @"kCMIODevicePropertyDeviceIsRunning"; + case kCMIODevicePropertyDeviceIsRunningSomewhere: + return @"kCMIODevicePropertyDeviceIsRunningSomewhere"; + case kCMIODevicePropertyDeviceCanBeDefaultDevice: + return @"kCMIODevicePropertyDeviceCanBeDefaultDevice"; + case kCMIODevicePropertyHogMode: + return @"kCMIODevicePropertyHogMode"; + case kCMIODevicePropertyLatency: + return @"kCMIODevicePropertyLatency"; + case kCMIODevicePropertyStreams: + return @"kCMIODevicePropertyStreams"; + case kCMIODevicePropertyStreamConfiguration: + return @"kCMIODevicePropertyStreamConfiguration"; + case kCMIODevicePropertyDeviceMaster: + return @"kCMIODevicePropertyDeviceMaster"; + case kCMIODevicePropertyExcludeNonDALAccess: + return @"kCMIODevicePropertyExcludeNonDALAccess"; + case kCMIODevicePropertyClientSyncDiscontinuity: + return @"kCMIODevicePropertyClientSyncDiscontinuity"; + case kCMIODevicePropertySMPTETimeCallback: + return @"kCMIODevicePropertySMPTETimeCallback"; + case kCMIODevicePropertyCanProcessAVCCommand: + return @"kCMIODevicePropertyCanProcessAVCCommand"; + case kCMIODevicePropertyAVCDeviceType: + return @"kCMIODevicePropertyAVCDeviceType"; + case kCMIODevicePropertyAVCDeviceSignalMode: + return @"kCMIODevicePropertyAVCDeviceSignalMode"; + case kCMIODevicePropertyCanProcessRS422Command: + return @"kCMIODevicePropertyCanProcessRS422Command"; + case kCMIODevicePropertyLinkedCoreAudioDeviceUID: + return @"kCMIODevicePropertyLinkedCoreAudioDeviceUID"; + case kCMIODevicePropertyVideoDigitizerComponents: + return @"kCMIODevicePropertyVideoDigitizerComponents"; + case kCMIODevicePropertySuspendedByUser: + return @"kCMIODevicePropertySuspendedByUser"; + case kCMIODevicePropertyLinkedAndSyncedCoreAudioDeviceUID: + return @"kCMIODevicePropertyLinkedAndSyncedCoreAudioDeviceUID"; + case kCMIODevicePropertyIIDCInitialUnitSpace: + return @"kCMIODevicePropertyIIDCInitialUnitSpace"; + case kCMIODevicePropertyIIDCCSRData: + return @"kCMIODevicePropertyIIDCCSRData"; + case kCMIODevicePropertyCanSwitchFrameRatesWithoutFrameDrops: + return @"kCMIODevicePropertyCanSwitchFrameRatesWithoutFrameDrops"; + case kCMIODevicePropertyLocation: + return @"kCMIODevicePropertyLocation"; + case kCMIODevicePropertyDeviceHasStreamingError: + return @"kCMIODevicePropertyDeviceHasStreamingError"; + case kCMIODevicePropertyScopeInput: + return @"kCMIODevicePropertyScopeInput"; + case kCMIODevicePropertyScopeOutput: + return @"kCMIODevicePropertyScopeOutput"; + case kCMIODevicePropertyScopePlayThrough: + return @"kCMIODevicePropertyScopePlayThrough"; + case kCMIOObjectPropertyClass: + return @"kCMIOObjectPropertyClass"; + case kCMIOObjectPropertyOwner: + return @"kCMIOObjectPropertyOwner"; + case kCMIOObjectPropertyCreator: + return @"kCMIOObjectPropertyCreator"; + case kCMIOObjectPropertyName: + return @"kCMIOObjectPropertyName"; + case kCMIOObjectPropertyManufacturer: + return @"kCMIOObjectPropertyManufacturer"; + case kCMIOObjectPropertyElementName: + return @"kCMIOObjectPropertyElementName"; + case kCMIOObjectPropertyElementCategoryName: + return @"kCMIOObjectPropertyElementCategoryName"; + case kCMIOObjectPropertyElementNumberName: + return @"kCMIOObjectPropertyElementNumberName"; + case kCMIOObjectPropertyOwnedObjects: + return @"kCMIOObjectPropertyOwnedObjects"; + case kCMIOObjectPropertyListenerAdded: + return @"kCMIOObjectPropertyListenerAdded"; + case kCMIOObjectPropertyListenerRemoved: + return @"kCMIOObjectPropertyListenerRemoved"; + case kCMIOStreamPropertyDirection: + return @"kCMIOStreamPropertyDirection"; + case kCMIOStreamPropertyTerminalType: + return @"kCMIOStreamPropertyTerminalType"; + case kCMIOStreamPropertyStartingChannel: + return @"kCMIOStreamPropertyStartingChannel"; + // Same value as kCMIODevicePropertyLatency + // case kCMIOStreamPropertyLatency: + // return @"kCMIOStreamPropertyLatency"; + case kCMIOStreamPropertyFormatDescription: + return @"kCMIOStreamPropertyFormatDescription"; + case kCMIOStreamPropertyFormatDescriptions: + return @"kCMIOStreamPropertyFormatDescriptions"; + case kCMIOStreamPropertyStillImage: + return @"kCMIOStreamPropertyStillImage"; + case kCMIOStreamPropertyStillImageFormatDescriptions: + return @"kCMIOStreamPropertyStillImageFormatDescriptions"; + case kCMIOStreamPropertyFrameRate: + return @"kCMIOStreamPropertyFrameRate"; + case kCMIOStreamPropertyMinimumFrameRate: + return @"kCMIOStreamPropertyMinimumFrameRate"; + case kCMIOStreamPropertyFrameRates: + return @"kCMIOStreamPropertyFrameRates"; + case kCMIOStreamPropertyFrameRateRanges: + return @"kCMIOStreamPropertyFrameRateRanges"; + case kCMIOStreamPropertyNoDataTimeoutInMSec: + return @"kCMIOStreamPropertyNoDataTimeoutInMSec"; + case kCMIOStreamPropertyDeviceSyncTimeoutInMSec: + return @"kCMIOStreamPropertyDeviceSyncTimeoutInMSec"; + case kCMIOStreamPropertyNoDataEventCount: + return @"kCMIOStreamPropertyNoDataEventCount"; + case kCMIOStreamPropertyOutputBufferUnderrunCount: + return @"kCMIOStreamPropertyOutputBufferUnderrunCount"; + case kCMIOStreamPropertyOutputBufferRepeatCount: + return @"kCMIOStreamPropertyOutputBufferRepeatCount"; + case kCMIOStreamPropertyOutputBufferQueueSize: + return @"kCMIOStreamPropertyOutputBufferQueueSize"; + case kCMIOStreamPropertyOutputBuffersRequiredForStartup: + return @"kCMIOStreamPropertyOutputBuffersRequiredForStartup"; + case kCMIOStreamPropertyOutputBuffersNeededForThrottledPlayback: + return @"kCMIOStreamPropertyOutputBuffersNeededForThrottledPlayback"; + case kCMIOStreamPropertyFirstOutputPresentationTimeStamp: + return @"kCMIOStreamPropertyFirstOutputPresentationTimeStamp"; + case kCMIOStreamPropertyEndOfData: + return @"kCMIOStreamPropertyEndOfData"; + case kCMIOStreamPropertyClock: + return @"kCMIOStreamPropertyClock"; + case kCMIOStreamPropertyCanProcessDeckCommand: + return @"kCMIOStreamPropertyCanProcessDeckCommand"; + case kCMIOStreamPropertyDeck: + return @"kCMIOStreamPropertyDeck"; + case kCMIOStreamPropertyDeckFrameNumber: + return @"kCMIOStreamPropertyDeckFrameNumber"; + case kCMIOStreamPropertyDeckDropness: + return @"kCMIOStreamPropertyDeckDropness"; + case kCMIOStreamPropertyDeckThreaded: + return @"kCMIOStreamPropertyDeckThreaded"; + case kCMIOStreamPropertyDeckLocal: + return @"kCMIOStreamPropertyDeckLocal"; + case kCMIOStreamPropertyDeckCueing: + return @"kCMIOStreamPropertyDeckCueing"; + case kCMIOStreamPropertyInitialPresentationTimeStampForLinkedAndSyncedAudio: + return @"kCMIOStreamPropertyInitialPresentationTimeStampForLinkedAndSyncedAudio"; + case kCMIOStreamPropertyScheduledOutputNotificationProc: + return @"kCMIOStreamPropertyScheduledOutputNotificationProc"; + case kCMIOStreamPropertyPreferredFormatDescription: + return @"kCMIOStreamPropertyPreferredFormatDescription"; + case kCMIOStreamPropertyPreferredFrameRate: + return @"kCMIOStreamPropertyPreferredFrameRate"; + case kCMIOControlPropertyScope: + return @"kCMIOControlPropertyScope"; + case kCMIOControlPropertyElement: + return @"kCMIOControlPropertyElement"; + case kCMIOControlPropertyVariant: + return @"kCMIOControlPropertyVariant"; + case kCMIOHardwarePropertyProcessIsMaster: + return @"kCMIOHardwarePropertyProcessIsMaster"; + case kCMIOHardwarePropertyIsInitingOrExiting: + return @"kCMIOHardwarePropertyIsInitingOrExiting"; + case kCMIOHardwarePropertyDevices: + return @"kCMIOHardwarePropertyDevices"; + case kCMIOHardwarePropertyDefaultInputDevice: + return @"kCMIOHardwarePropertyDefaultInputDevice"; + case kCMIOHardwarePropertyDefaultOutputDevice: + return @"kCMIOHardwarePropertyDefaultOutputDevice"; + case kCMIOHardwarePropertyDeviceForUID: + return @"kCMIOHardwarePropertyDeviceForUID"; + case kCMIOHardwarePropertySleepingIsAllowed: + return @"kCMIOHardwarePropertySleepingIsAllowed"; + case kCMIOHardwarePropertyUnloadingIsAllowed: + return @"kCMIOHardwarePropertyUnloadingIsAllowed"; + case kCMIOHardwarePropertyPlugInForBundleID: + return @"kCMIOHardwarePropertyPlugInForBundleID"; + case kCMIOHardwarePropertyUserSessionIsActiveOrHeadless: + return @"kCMIOHardwarePropertyUserSessionIsActiveOrHeadless"; + case kCMIOHardwarePropertySuspendedBySystem: + return @"kCMIOHardwarePropertySuspendedBySystem"; + case kCMIOHardwarePropertyAllowScreenCaptureDevices: + return @"kCMIOHardwarePropertyAllowScreenCaptureDevices"; + case kCMIOHardwarePropertyAllowWirelessScreenCaptureDevices: + return @"kCMIOHardwarePropertyAllowWirelessScreenCaptureDevices"; + default: + uint8_t *chars = (uint8_t *) &selector; + return [NSString stringWithFormat:@"Unknown selector: %c%c%c%c", chars[0], chars[1], chars[2], chars[3]]; + } } + (BOOL)IsBridgedTypeForSelector:(CMIOObjectPropertySelector)selector { - switch (selector) { - case kCMIOObjectPropertyName: - case kCMIOObjectPropertyManufacturer: - case kCMIOObjectPropertyElementName: - case kCMIOObjectPropertyElementCategoryName: - case kCMIOObjectPropertyElementNumberName: - case kCMIODevicePropertyDeviceUID: - case kCMIODevicePropertyModelUID: - case kCMIOStreamPropertyFormatDescriptions: - case kCMIOStreamPropertyFormatDescription: - case kCMIOStreamPropertyClock: - return YES; - default: - return NO; - } + switch (selector) { + case kCMIOObjectPropertyName: + case kCMIOObjectPropertyManufacturer: + case kCMIOObjectPropertyElementName: + case kCMIOObjectPropertyElementCategoryName: + case kCMIOObjectPropertyElementNumberName: + case kCMIODevicePropertyDeviceUID: + case kCMIODevicePropertyModelUID: + case kCMIOStreamPropertyFormatDescriptions: + case kCMIOStreamPropertyFormatDescription: + case kCMIOStreamPropertyClock: + return YES; + default: + return NO; + } } + (OBSDALObjectStore *)SharedObjectStore { - static OBSDALObjectStore *sObjectStore = nil; - static dispatch_once_t sOnceToken; - dispatch_once(&sOnceToken, ^{ - sObjectStore = [[self alloc] init]; - }); - return sObjectStore; + static OBSDALObjectStore *sObjectStore = nil; + static dispatch_once_t sOnceToken; + dispatch_once(&sOnceToken, ^{ + sObjectStore = [[self alloc] init]; + }); + return sObjectStore; } + (NSObject *)GetObjectWithId:(CMIOObjectID)objectId { - return [[OBSDALObjectStore SharedObjectStore] getObject:objectId]; + return [[OBSDALObjectStore SharedObjectStore] getObject:objectId]; } - (id)init { - if (self = [super init]) { - self.objectMap = [[NSMutableDictionary alloc] init]; - } - return self; + if (self = [super init]) { + self.objectMap = [[NSMutableDictionary alloc] init]; + } + return self; } - (NSObject *)getObject:(CMIOObjectID)objectID { - return self.objectMap[@(objectID)]; + return self.objectMap[@(objectID)]; } - (void)setObject:(id)object forObjectId:(CMIOObjectID)objectId { - self.objectMap[@(objectId)] = object; + self.objectMap[@(objectId)] = object; } @end diff --git a/plugins/mac-virtualcam/src/dal-plugin/OBSDALPlugIn.h b/plugins/mac-virtualcam/src/dal-plugin/OBSDALPlugIn.h index 037dc06f7..8d85d50c0 100644 --- a/plugins/mac-virtualcam/src/dal-plugin/OBSDALPlugIn.h +++ b/plugins/mac-virtualcam/src/dal-plugin/OBSDALPlugIn.h @@ -21,9 +21,9 @@ #import "OBSDALMachClient.h" #import "OBSDALStream.h" -#define kTestCardWidthKey @"obs-mac-virtualcam-test-card-width" +#define kTestCardWidthKey @"obs-mac-virtualcam-test-card-width" #define kTestCardHeightKey @"obs-mac-virtualcam-test-card-height" -#define kTestCardFPSKey @"obs-mac-virtualcam-test-card-fps" +#define kTestCardFPSKey @"obs-mac-virtualcam-test-card-fps" NS_ASSUME_NONNULL_BEGIN diff --git a/plugins/mac-virtualcam/src/dal-plugin/OBSDALPlugIn.mm b/plugins/mac-virtualcam/src/dal-plugin/OBSDALPlugIn.mm index 691142f35..e9ecc1129 100644 --- a/plugins/mac-virtualcam/src/dal-plugin/OBSDALPlugIn.mm +++ b/plugins/mac-virtualcam/src/dal-plugin/OBSDALPlugIn.mm @@ -22,20 +22,20 @@ #import "Logging.h" typedef enum { - PlugInStateNotStarted = 0, - PlugInStateWaitingForServer, - PlugInStateReceivingFrames, + PlugInStateNotStarted = 0, + PlugInStateWaitingForServer, + PlugInStateReceivingFrames, } OBSDALPlugInState; @interface OBSDALPlugin () { - //! Serial queue for all state changes that need to be concerned with thread safety - dispatch_queue_t _stateQueue; + //! Serial queue for all state changes that need to be concerned with thread safety + dispatch_queue_t _stateQueue; - //! Repeated timer for driving the mach server re-connection - dispatch_source_t _machConnectTimer; + //! Repeated timer for driving the mach server re-connection + dispatch_source_t _machConnectTimer; - //! Timeout timer when we haven't received frames for 5s - dispatch_source_t _timeoutTimer; + //! Timeout timer when we haven't received frames for 5s + dispatch_source_t _timeoutTimer; } @property OBSDALPlugInState state; @property OBSDALMachClient *machClient; @@ -46,209 +46,186 @@ typedef enum { + (OBSDALPlugin *)SharedPlugIn { - static OBSDALPlugin *sPlugIn = nil; - static dispatch_once_t sOnceToken; - dispatch_once(&sOnceToken, ^{ - sPlugIn = [[self alloc] init]; - }); - return sPlugIn; + static OBSDALPlugin *sPlugIn = nil; + static dispatch_once_t sOnceToken; + dispatch_once(&sOnceToken, ^{ + sPlugIn = [[self alloc] init]; + }); + return sPlugIn; } - (instancetype)init { - if (self = [super init]) { - _stateQueue = dispatch_queue_create( - "com.obsproject.obs-mac-virtualcam.dal.state", - DISPATCH_QUEUE_SERIAL); + if (self = [super init]) { + _stateQueue = dispatch_queue_create("com.obsproject.obs-mac-virtualcam.dal.state", DISPATCH_QUEUE_SERIAL); - _timeoutTimer = dispatch_source_create( - DISPATCH_SOURCE_TYPE_TIMER, 0, 0, _stateQueue); - __weak __typeof(self) weakSelf = self; - dispatch_source_set_event_handler(_timeoutTimer, ^{ - if (weakSelf.state == PlugInStateReceivingFrames) { - DLog(@"No frames received for 5s, restarting connection"); - [self stopStream]; - [self startStream]; - } - }); + _timeoutTimer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, _stateQueue); + __weak __typeof(self) weakSelf = self; + dispatch_source_set_event_handler(_timeoutTimer, ^{ + if (weakSelf.state == PlugInStateReceivingFrames) { + DLog(@"No frames received for 5s, restarting connection"); + [self stopStream]; + [self startStream]; + } + }); - _machClient = [[OBSDALMachClient alloc] init]; - _machClient.delegate = self; + _machClient = [[OBSDALMachClient alloc] init]; + _machClient.delegate = self; - _machConnectTimer = dispatch_source_create( - DISPATCH_SOURCE_TYPE_TIMER, 0, 0, _stateQueue); - dispatch_time_t startTime = dispatch_time(DISPATCH_TIME_NOW, 0); - uint64_t intervalTime = (int64_t)(1 * NSEC_PER_SEC); - dispatch_source_set_timer(_machConnectTimer, startTime, - intervalTime, 0); + _machConnectTimer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, _stateQueue); + dispatch_time_t startTime = dispatch_time(DISPATCH_TIME_NOW, 0); + uint64_t intervalTime = (int64_t) (1 * NSEC_PER_SEC); + dispatch_source_set_timer(_machConnectTimer, startTime, intervalTime, 0); - dispatch_source_set_event_handler(_machConnectTimer, ^{ - __strong __typeof(weakSelf) strongSelf = weakSelf; - if (![[strongSelf machClient] isServerAvailable]) { - DLog(@"Server is not available"); - } else if (strongSelf.state == - PlugInStateWaitingForServer) { - DLog(@"Attempting connection"); - [[strongSelf machClient] connectToServer]; - } - }); - } - return self; + dispatch_source_set_event_handler(_machConnectTimer, ^{ + __strong __typeof(weakSelf) strongSelf = weakSelf; + if (![[strongSelf machClient] isServerAvailable]) { + DLog(@"Server is not available"); + } else if (strongSelf.state == PlugInStateWaitingForServer) { + DLog(@"Attempting connection"); + [[strongSelf machClient] connectToServer]; + } + }); + } + return self; } - (void)startStream { - dispatch_async(_stateQueue, ^{ - if (_state == PlugInStateNotStarted) { - dispatch_resume(_machConnectTimer); - [self.stream startServingDefaultFrames]; - _state = PlugInStateWaitingForServer; - } - }); + dispatch_async(_stateQueue, ^{ + if (_state == PlugInStateNotStarted) { + dispatch_resume(_machConnectTimer); + [self.stream startServingDefaultFrames]; + _state = PlugInStateWaitingForServer; + } + }); } - (void)stopStream { - dispatch_async(_stateQueue, ^{ - if (_state == PlugInStateWaitingForServer) { - dispatch_suspend(_machConnectTimer); - [self.stream stopServingDefaultFrames]; - } else if (_state == PlugInStateReceivingFrames) { - // TODO: Disconnect from the mach server? - dispatch_suspend(_timeoutTimer); - } - _state = PlugInStateNotStarted; - }); + dispatch_async(_stateQueue, ^{ + if (_state == PlugInStateWaitingForServer) { + dispatch_suspend(_machConnectTimer); + [self.stream stopServingDefaultFrames]; + } else if (_state == PlugInStateReceivingFrames) { + // TODO: Disconnect from the mach server? + dispatch_suspend(_timeoutTimer); + } + _state = PlugInStateNotStarted; + }); } - (void)initialize -{ -} +{} - (void)teardown -{ -} +{} #pragma mark - CMIOObject - (BOOL)hasPropertyWithAddress:(CMIOObjectPropertyAddress)address { - switch (address.mSelector) { - case kCMIOObjectPropertyName: - return true; - default: - DLog(@"PlugIn unhandled hasPropertyWithAddress for %@", - [OBSDALObjectStore - StringFromPropertySelector:address.mSelector]); - return false; - }; + switch (address.mSelector) { + case kCMIOObjectPropertyName: + return true; + default: + DLog(@"PlugIn unhandled hasPropertyWithAddress for %@", + [OBSDALObjectStore StringFromPropertySelector:address.mSelector]); + return false; + }; } - (BOOL)isPropertySettableWithAddress:(CMIOObjectPropertyAddress)address { - switch (address.mSelector) { - case kCMIOObjectPropertyName: - return false; - default: - DLog(@"PlugIn unhandled isPropertySettableWithAddress for %@", - [OBSDALObjectStore - StringFromPropertySelector:address.mSelector]); - return false; - }; + switch (address.mSelector) { + case kCMIOObjectPropertyName: + return false; + default: + DLog(@"PlugIn unhandled isPropertySettableWithAddress for %@", + [OBSDALObjectStore StringFromPropertySelector:address.mSelector]); + return false; + }; } - (UInt32)getPropertyDataSizeWithAddress:(CMIOObjectPropertyAddress)address - qualifierDataSize:(UInt32)qualifierDataSize - qualifierData:(const void *)qualifierData + qualifierDataSize:(UInt32)qualifierDataSize + qualifierData:(const void *)qualifierData { - switch (address.mSelector) { - case kCMIOObjectPropertyName: - return sizeof(CFStringRef); - default: - DLog(@"PlugIn unhandled getPropertyDataSizeWithAddress for %@", - [OBSDALObjectStore - StringFromPropertySelector:address.mSelector]); - return 0; - }; + switch (address.mSelector) { + case kCMIOObjectPropertyName: + return sizeof(CFStringRef); + default: + DLog(@"PlugIn unhandled getPropertyDataSizeWithAddress for %@", + [OBSDALObjectStore StringFromPropertySelector:address.mSelector]); + return 0; + }; } - (void)getPropertyDataWithAddress:(CMIOObjectPropertyAddress)address - qualifierDataSize:(UInt32)qualifierDataSize - qualifierData:(nonnull const void *)qualifierData - dataSize:(UInt32)dataSize - dataUsed:(nonnull UInt32 *)dataUsed - data:(nonnull void *)data + qualifierDataSize:(UInt32)qualifierDataSize + qualifierData:(nonnull const void *)qualifierData + dataSize:(UInt32)dataSize + dataUsed:(nonnull UInt32 *)dataUsed + data:(nonnull void *)data { - switch (address.mSelector) { - case kCMIOObjectPropertyName: - *static_cast(data) = - CFSTR("OBS Virtual Camera Plugin"); - *dataUsed = sizeof(CFStringRef); - return; - default: - DLog(@"PlugIn unhandled getPropertyDataWithAddress for %@", - [OBSDALObjectStore - StringFromPropertySelector:address.mSelector]); - return; - }; + switch (address.mSelector) { + case kCMIOObjectPropertyName: + *static_cast(data) = CFSTR("OBS Virtual Camera Plugin"); + *dataUsed = sizeof(CFStringRef); + return; + default: + DLog(@"PlugIn unhandled getPropertyDataWithAddress for %@", + [OBSDALObjectStore StringFromPropertySelector:address.mSelector]); + return; + }; } - (void)setPropertyDataWithAddress:(CMIOObjectPropertyAddress)address - qualifierDataSize:(UInt32)qualifierDataSize - qualifierData:(nonnull const void *)qualifierData - dataSize:(UInt32)dataSize - data:(nonnull const void *)data + qualifierDataSize:(UInt32)qualifierDataSize + qualifierData:(nonnull const void *)qualifierData + dataSize:(UInt32)dataSize + data:(nonnull const void *)data { - DLog(@"PlugIn unhandled setPropertyDataWithAddress for %@", - [OBSDALObjectStore StringFromPropertySelector:address.mSelector]); + DLog(@"PlugIn unhandled setPropertyDataWithAddress for %@", + [OBSDALObjectStore StringFromPropertySelector:address.mSelector]); } #pragma mark - MachClientDelegate - (void)receivedPixelBuffer:(CVPixelBufferRef)frame - timestamp:(uint64_t)timestamp - fpsNumerator:(uint32_t)fpsNumerator - fpsDenominator:(uint32_t)fpsDenominator + timestamp:(uint64_t)timestamp + fpsNumerator:(uint32_t)fpsNumerator + fpsDenominator:(uint32_t)fpsDenominator { - size_t width = CVPixelBufferGetWidth(frame); - size_t height = CVPixelBufferGetHeight(frame); + size_t width = CVPixelBufferGetWidth(frame); + size_t height = CVPixelBufferGetHeight(frame); - dispatch_sync(_stateQueue, ^{ - if (_state == PlugInStateWaitingForServer) { - NSUserDefaults *defaults = - [NSUserDefaults standardUserDefaults]; - [defaults setInteger:(long)width - forKey:kTestCardWidthKey]; - [defaults setInteger:(long)height - forKey:kTestCardHeightKey]; - [defaults setDouble:(double)fpsNumerator / - (double)fpsDenominator - forKey:kTestCardFPSKey]; + dispatch_sync(_stateQueue, ^{ + if (_state == PlugInStateWaitingForServer) { + NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; + [defaults setInteger:(long) width forKey:kTestCardWidthKey]; + [defaults setInteger:(long) height forKey:kTestCardHeightKey]; + [defaults setDouble:(double) fpsNumerator / (double) fpsDenominator forKey:kTestCardFPSKey]; - dispatch_suspend(_machConnectTimer); - [self.stream stopServingDefaultFrames]; - dispatch_resume(_timeoutTimer); - _state = PlugInStateReceivingFrames; - } - }); + dispatch_suspend(_machConnectTimer); + [self.stream stopServingDefaultFrames]; + dispatch_resume(_timeoutTimer); + _state = PlugInStateReceivingFrames; + } + }); - // Add 5 more seconds onto the timeout timer - dispatch_source_set_timer( - _timeoutTimer, - dispatch_time(DISPATCH_TIME_NOW, (int64_t)(5.0 * NSEC_PER_SEC)), - (uint64_t)(5.0 * NSEC_PER_SEC), (1ull * NSEC_PER_SEC) / 10); + // Add 5 more seconds onto the timeout timer + dispatch_source_set_timer(_timeoutTimer, dispatch_time(DISPATCH_TIME_NOW, (int64_t) (5.0 * NSEC_PER_SEC)), + (uint64_t) (5.0 * NSEC_PER_SEC), (1ull * NSEC_PER_SEC) / 10); - [self.stream queuePixelBuffer:frame - timestamp:timestamp - fpsNumerator:fpsNumerator - fpsDenominator:fpsDenominator]; + [self.stream queuePixelBuffer:frame timestamp:timestamp fpsNumerator:fpsNumerator fpsDenominator:fpsDenominator]; } - (void)receivedStop { - DLogFunc(@"Restarting connection"); - [self stopStream]; - [self startStream]; + DLogFunc(@"Restarting connection"); + [self stopStream]; + [self startStream]; } @end diff --git a/plugins/mac-virtualcam/src/dal-plugin/OBSDALPlugInInterface.mm b/plugins/mac-virtualcam/src/dal-plugin/OBSDALPlugInInterface.mm index c7a5b820f..344291036 100644 --- a/plugins/mac-virtualcam/src/dal-plugin/OBSDALPlugInInterface.mm +++ b/plugins/mac-virtualcam/src/dal-plugin/OBSDALPlugInInterface.mm @@ -32,399 +32,337 @@ static UInt32 sRefCount = 0; ULONG HardwarePlugIn_AddRef(CMIOHardwarePlugInRef) { - sRefCount += 1; - DLogFunc(@"sRefCount now = %d", sRefCount); - return sRefCount; + sRefCount += 1; + DLogFunc(@"sRefCount now = %d", sRefCount); + return sRefCount; } ULONG HardwarePlugIn_Release(CMIOHardwarePlugInRef) { - sRefCount -= 1; - DLogFunc(@"sRefCount now = %d", sRefCount); - return sRefCount; + sRefCount -= 1; + DLogFunc(@"sRefCount now = %d", sRefCount); + return sRefCount; } -HRESULT HardwarePlugIn_QueryInterface(CMIOHardwarePlugInRef, REFIID uuid, - LPVOID *interface) +HRESULT HardwarePlugIn_QueryInterface(CMIOHardwarePlugInRef, REFIID uuid, LPVOID *interface) { - if (!interface) { - DLogFunc(@"Received an empty interface"); - return E_POINTER; - } + if (!interface) { + DLogFunc(@"Received an empty interface"); + return E_POINTER; + } - // Set the returned interface to NULL in case the UUIDs don't match - *interface = NULL; + // Set the returned interface to NULL in case the UUIDs don't match + *interface = NULL; - // Create a CoreFoundation UUIDRef for the requested interface. - CFUUIDRef cfUuid = CFUUIDCreateFromUUIDBytes(kCFAllocatorDefault, uuid); - CFStringRef uuidString = CFUUIDCreateString(NULL, cfUuid); - CFStringRef hardwarePluginUuid = - CFUUIDCreateString(NULL, kCMIOHardwarePlugInInterfaceID); - CFRelease(cfUuid); + // Create a CoreFoundation UUIDRef for the requested interface. + CFUUIDRef cfUuid = CFUUIDCreateFromUUIDBytes(kCFAllocatorDefault, uuid); + CFStringRef uuidString = CFUUIDCreateString(NULL, cfUuid); + CFStringRef hardwarePluginUuid = CFUUIDCreateString(NULL, kCMIOHardwarePlugInInterfaceID); + CFRelease(cfUuid); - if (CFEqual(uuidString, hardwarePluginUuid)) { - // Return the interface; - sRefCount += 1; - *interface = OBSDALPlugInRef(); - CFRelease(hardwarePluginUuid); - CFRelease(uuidString); - return kCMIOHardwareNoError; - } else { - DLogFunc(@"ERR Queried for some weird UUID %@", uuidString); - } - CFRelease(hardwarePluginUuid); - CFRelease(uuidString); - return E_NOINTERFACE; + if (CFEqual(uuidString, hardwarePluginUuid)) { + // Return the interface; + sRefCount += 1; + *interface = OBSDALPlugInRef(); + CFRelease(hardwarePluginUuid); + CFRelease(uuidString); + return kCMIOHardwareNoError; + } else { + DLogFunc(@"ERR Queried for some weird UUID %@", uuidString); + } + CFRelease(hardwarePluginUuid); + CFRelease(uuidString); + return E_NOINTERFACE; } // I think this is deprecated, seems that HardwarePlugIn_InitializeWithObjectID gets called instead -OSStatus HardwarePlugIn_Initialize(CMIOHardwarePlugInRef self - __attribute__((unused))) +OSStatus HardwarePlugIn_Initialize(CMIOHardwarePlugInRef self __attribute__((unused))) { - DLogFunc(@"ERR self=%p", self); - return kCMIOHardwareUnspecifiedError; + DLogFunc(@"ERR self=%p", self); + return kCMIOHardwareUnspecifiedError; } -OSStatus HardwarePlugIn_InitializeWithObjectID(CMIOHardwarePlugInRef self, - CMIOObjectID objectID) +OSStatus HardwarePlugIn_InitializeWithObjectID(CMIOHardwarePlugInRef self, CMIOObjectID objectID) { - DLogFunc(@"self=%p", self); + DLogFunc(@"self=%p", self); - OSStatus error = kCMIOHardwareNoError; + OSStatus error = kCMIOHardwareNoError; - OBSDALPlugin *plugIn = [OBSDALPlugin SharedPlugIn]; - plugIn.objectId = objectID; - [[OBSDALObjectStore SharedObjectStore] setObject:plugIn - forObjectId:objectID]; + OBSDALPlugin *plugIn = [OBSDALPlugin SharedPlugIn]; + plugIn.objectId = objectID; + [[OBSDALObjectStore SharedObjectStore] setObject:plugIn forObjectId:objectID]; - OBSDALDevice *device = [[OBSDALDevice alloc] init]; - CMIOObjectID deviceId; - error = CMIOObjectCreate(OBSDALPlugInRef(), kCMIOObjectSystemObject, - kCMIODeviceClassID, &deviceId); - if (error != noErr) { - DLog(@"CMIOObjectCreate Error %d", error); - return error; - } - device.objectId = deviceId; - device.pluginId = objectID; - [[OBSDALObjectStore SharedObjectStore] setObject:device - forObjectId:deviceId]; + OBSDALDevice *device = [[OBSDALDevice alloc] init]; + CMIOObjectID deviceId; + error = CMIOObjectCreate(OBSDALPlugInRef(), kCMIOObjectSystemObject, kCMIODeviceClassID, &deviceId); + if (error != noErr) { + DLog(@"CMIOObjectCreate Error %d", error); + return error; + } + device.objectId = deviceId; + device.pluginId = objectID; + [[OBSDALObjectStore SharedObjectStore] setObject:device forObjectId:deviceId]; - OBSDALStream *stream = [[OBSDALStream alloc] init]; - CMIOObjectID streamId; - error = CMIOObjectCreate(OBSDALPlugInRef(), deviceId, - kCMIOStreamClassID, &streamId); - if (error != noErr) { - DLog(@"CMIOObjectCreate Error %d", error); - return error; - } - stream.objectId = streamId; - [[OBSDALObjectStore SharedObjectStore] setObject:stream - forObjectId:streamId]; - device.streamId = streamId; - plugIn.stream = stream; + OBSDALStream *stream = [[OBSDALStream alloc] init]; + CMIOObjectID streamId; + error = CMIOObjectCreate(OBSDALPlugInRef(), deviceId, kCMIOStreamClassID, &streamId); + if (error != noErr) { + DLog(@"CMIOObjectCreate Error %d", error); + return error; + } + stream.objectId = streamId; + [[OBSDALObjectStore SharedObjectStore] setObject:stream forObjectId:streamId]; + device.streamId = streamId; + plugIn.stream = stream; - // Tell the system about the Device - error = CMIOObjectsPublishedAndDied( - OBSDALPlugInRef(), kCMIOObjectSystemObject, 1, &deviceId, 0, 0); - if (error != kCMIOHardwareNoError) { - DLog(@"CMIOObjectsPublishedAndDied plugin/device Error %d", - error); - return error; - } + // Tell the system about the Device + error = CMIOObjectsPublishedAndDied(OBSDALPlugInRef(), kCMIOObjectSystemObject, 1, &deviceId, 0, 0); + if (error != kCMIOHardwareNoError) { + DLog(@"CMIOObjectsPublishedAndDied plugin/device Error %d", error); + return error; + } - // Tell the system about the Stream - error = CMIOObjectsPublishedAndDied(OBSDALPlugInRef(), deviceId, 1, - &streamId, 0, 0); - if (error != kCMIOHardwareNoError) { - DLog(@"CMIOObjectsPublishedAndDied device/stream Error %d", - error); - return error; - } + // Tell the system about the Stream + error = CMIOObjectsPublishedAndDied(OBSDALPlugInRef(), deviceId, 1, &streamId, 0, 0); + if (error != kCMIOHardwareNoError) { + DLog(@"CMIOObjectsPublishedAndDied device/stream Error %d", error); + return error; + } - return error; + return error; } OSStatus HardwarePlugIn_Teardown(CMIOHardwarePlugInRef self) { - DLogFunc(@"self=%p", self); + DLogFunc(@"self=%p", self); - OSStatus error = kCMIOHardwareNoError; + OSStatus error = kCMIOHardwareNoError; - OBSDALPlugin *plugIn = [OBSDALPlugin SharedPlugIn]; - [plugIn teardown]; + OBSDALPlugin *plugIn = [OBSDALPlugin SharedPlugIn]; + [plugIn teardown]; - return error; + return error; } #pragma mark CMIOObject Operations void HardwarePlugIn_ObjectShow(CMIOHardwarePlugInRef self, CMIOObjectID) { - DLogFunc(@"self=%p", self); + DLogFunc(@"self=%p", self); } -Boolean -HardwarePlugIn_ObjectHasProperty(CMIOHardwarePlugInRef, CMIOObjectID objectID, - const CMIOObjectPropertyAddress *address) +Boolean HardwarePlugIn_ObjectHasProperty(CMIOHardwarePlugInRef, CMIOObjectID objectID, + const CMIOObjectPropertyAddress *address) { - NSObject *object = - [OBSDALObjectStore GetObjectWithId:objectID]; + NSObject *object = [OBSDALObjectStore GetObjectWithId:objectID]; - if (object == nil) { - DLogFunc(@"ERR nil object"); - return false; - } + if (object == nil) { + DLogFunc(@"ERR nil object"); + return false; + } - Boolean answer = [object hasPropertyWithAddress:*address]; + Boolean answer = [object hasPropertyWithAddress:*address]; - return answer; + return answer; } -OSStatus HardwarePlugIn_ObjectIsPropertySettable( - CMIOHardwarePlugInRef self, CMIOObjectID objectID, - const CMIOObjectPropertyAddress *address, Boolean *isSettable) +OSStatus HardwarePlugIn_ObjectIsPropertySettable(CMIOHardwarePlugInRef self, CMIOObjectID objectID, + const CMIOObjectPropertyAddress *address, Boolean *isSettable) { + NSObject *object = [OBSDALObjectStore GetObjectWithId:objectID]; - NSObject *object = - [OBSDALObjectStore GetObjectWithId:objectID]; + if (object == nil) { + DLogFunc(@"ERR nil object"); + return kCMIOHardwareBadObjectError; + } - if (object == nil) { - DLogFunc(@"ERR nil object"); - return kCMIOHardwareBadObjectError; - } + *isSettable = [object isPropertySettableWithAddress:*address]; - *isSettable = [object isPropertySettableWithAddress:*address]; + DLogFunc(@"%@(%d) %@ self=%p settable=%d", NSStringFromClass([object class]), objectID, + [OBSDALObjectStore StringFromPropertySelector:address->mSelector], self, *isSettable); - DLogFunc(@"%@(%d) %@ self=%p settable=%d", - NSStringFromClass([object class]), objectID, - [OBSDALObjectStore - StringFromPropertySelector:address->mSelector], - self, *isSettable); - - return kCMIOHardwareNoError; + return kCMIOHardwareNoError; } -OSStatus HardwarePlugIn_ObjectGetPropertyDataSize( - CMIOHardwarePlugInRef, CMIOObjectID objectID, - const CMIOObjectPropertyAddress *address, UInt32 qualifierDataSize, - const void *qualifierData, UInt32 *dataSize) +OSStatus HardwarePlugIn_ObjectGetPropertyDataSize(CMIOHardwarePlugInRef, CMIOObjectID objectID, + const CMIOObjectPropertyAddress *address, UInt32 qualifierDataSize, + const void *qualifierData, UInt32 *dataSize) { - NSObject *object = - [OBSDALObjectStore GetObjectWithId:objectID]; + NSObject *object = [OBSDALObjectStore GetObjectWithId:objectID]; - if (object == nil) { - DLogFunc(@"ERR nil object"); - return kCMIOHardwareBadObjectError; - } + if (object == nil) { + DLogFunc(@"ERR nil object"); + return kCMIOHardwareBadObjectError; + } - *dataSize = [object getPropertyDataSizeWithAddress:*address - qualifierDataSize:qualifierDataSize - qualifierData:qualifierData]; + *dataSize = [object getPropertyDataSizeWithAddress:*address qualifierDataSize:qualifierDataSize + qualifierData:qualifierData]; - return kCMIOHardwareNoError; + return kCMIOHardwareNoError; } -OSStatus HardwarePlugIn_ObjectGetPropertyData( - CMIOHardwarePlugInRef, CMIOObjectID objectID, - const CMIOObjectPropertyAddress *address, UInt32 qualifierDataSize, - const void *qualifierData, UInt32 dataSize, UInt32 *dataUsed, - void *data) +OSStatus HardwarePlugIn_ObjectGetPropertyData(CMIOHardwarePlugInRef, CMIOObjectID objectID, + const CMIOObjectPropertyAddress *address, UInt32 qualifierDataSize, + const void *qualifierData, UInt32 dataSize, UInt32 *dataUsed, void *data) { - NSObject *object = - [OBSDALObjectStore GetObjectWithId:objectID]; + NSObject *object = [OBSDALObjectStore GetObjectWithId:objectID]; - if (object == nil) { - DLogFunc(@"ERR nil object"); - return kCMIOHardwareBadObjectError; - } + if (object == nil) { + DLogFunc(@"ERR nil object"); + return kCMIOHardwareBadObjectError; + } - [object getPropertyDataWithAddress:*address - qualifierDataSize:qualifierDataSize - qualifierData:qualifierData - dataSize:dataSize - dataUsed:dataUsed - data:data]; + [object getPropertyDataWithAddress:*address qualifierDataSize:qualifierDataSize qualifierData:qualifierData + dataSize:dataSize + dataUsed:dataUsed + data:data]; - return kCMIOHardwareNoError; + return kCMIOHardwareNoError; } -OSStatus HardwarePlugIn_ObjectSetPropertyData( - CMIOHardwarePlugInRef self, CMIOObjectID objectID, - const CMIOObjectPropertyAddress *address, UInt32 qualifierDataSize, - const void *qualifierData, UInt32 dataSize, const void *data) +OSStatus HardwarePlugIn_ObjectSetPropertyData(CMIOHardwarePlugInRef self, CMIOObjectID objectID, + const CMIOObjectPropertyAddress *address, UInt32 qualifierDataSize, + const void *qualifierData, UInt32 dataSize, const void *data) { + NSObject *object = [OBSDALObjectStore GetObjectWithId:objectID]; - NSObject *object = - [OBSDALObjectStore GetObjectWithId:objectID]; + if (object == nil) { + DLogFunc(@"ERR nil object"); + return kCMIOHardwareBadObjectError; + } - if (object == nil) { - DLogFunc(@"ERR nil object"); - return kCMIOHardwareBadObjectError; - } + UInt32 *dataInt = (UInt32 *) data; + DLogFunc(@"%@(%d) %@ self=%p data(int)=%d", NSStringFromClass([object class]), objectID, + [OBSDALObjectStore StringFromPropertySelector:address->mSelector], self, *dataInt); - UInt32 *dataInt = (UInt32 *)data; - DLogFunc(@"%@(%d) %@ self=%p data(int)=%d", - NSStringFromClass([object class]), objectID, - [OBSDALObjectStore - StringFromPropertySelector:address->mSelector], - self, *dataInt); + [object setPropertyDataWithAddress:*address qualifierDataSize:qualifierDataSize qualifierData:qualifierData + dataSize:dataSize + data:data]; - [object setPropertyDataWithAddress:*address - qualifierDataSize:qualifierDataSize - qualifierData:qualifierData - dataSize:dataSize - data:data]; - - return kCMIOHardwareNoError; + return kCMIOHardwareNoError; } #pragma mark CMIOStream Operations -OSStatus HardwarePlugIn_StreamCopyBufferQueue( - CMIOHardwarePlugInRef self, CMIOStreamID streamID, - CMIODeviceStreamQueueAlteredProc queueAlteredProc, - void *queueAlteredRefCon, CMSimpleQueueRef *queue) +OSStatus HardwarePlugIn_StreamCopyBufferQueue(CMIOHardwarePlugInRef self, CMIOStreamID streamID, + CMIODeviceStreamQueueAlteredProc queueAlteredProc, + void *queueAlteredRefCon, CMSimpleQueueRef *queue) { + OBSDALStream *stream = (OBSDALStream *) [OBSDALObjectStore GetObjectWithId:streamID]; - OBSDALStream *stream = - (OBSDALStream *)[OBSDALObjectStore GetObjectWithId:streamID]; + if (stream == nil) { + DLogFunc(@"ERR nil object"); + return kCMIOHardwareBadObjectError; + } - if (stream == nil) { - DLogFunc(@"ERR nil object"); - return kCMIOHardwareBadObjectError; - } + *queue = [stream copyBufferQueueWithAlteredProc:queueAlteredProc alteredRefCon:queueAlteredRefCon]; - *queue = [stream copyBufferQueueWithAlteredProc:queueAlteredProc - alteredRefCon:queueAlteredRefCon]; + DLogFunc(@"%@ (id=%d) self=%p queue=%@", stream, streamID, self, (__bridge NSObject *) *queue); - DLogFunc(@"%@ (id=%d) self=%p queue=%@", stream, streamID, self, - (__bridge NSObject *)*queue); - - return kCMIOHardwareNoError; + return kCMIOHardwareNoError; } #pragma mark CMIODevice Operations -OSStatus HardwarePlugIn_DeviceStartStream(CMIOHardwarePlugInRef self, - CMIODeviceID deviceID, - CMIOStreamID streamID) +OSStatus HardwarePlugIn_DeviceStartStream(CMIOHardwarePlugInRef self, CMIODeviceID deviceID, CMIOStreamID streamID) { - DLogFunc(@"self=%p device=%d stream=%d", self, deviceID, streamID); + DLogFunc(@"self=%p device=%d stream=%d", self, deviceID, streamID); - OBSDALStream *stream = - (OBSDALStream *)[OBSDALObjectStore GetObjectWithId:streamID]; + OBSDALStream *stream = (OBSDALStream *) [OBSDALObjectStore GetObjectWithId:streamID]; - if (stream == nil) { - DLogFunc(@"ERR nil object"); - return kCMIOHardwareBadObjectError; - } + if (stream == nil) { + DLogFunc(@"ERR nil object"); + return kCMIOHardwareBadObjectError; + } - [[OBSDALPlugin SharedPlugIn] startStream]; + [[OBSDALPlugin SharedPlugIn] startStream]; - return kCMIOHardwareNoError; + return kCMIOHardwareNoError; } OSStatus HardwarePlugIn_DeviceSuspend(CMIOHardwarePlugInRef self, CMIODeviceID) { - DLogFunc(@"self=%p", self); - return kCMIOHardwareNoError; + DLogFunc(@"self=%p", self); + return kCMIOHardwareNoError; } OSStatus HardwarePlugIn_DeviceResume(CMIOHardwarePlugInRef self, CMIODeviceID) { - DLogFunc(@"self=%p", self); - return kCMIOHardwareNoError; + DLogFunc(@"self=%p", self); + return kCMIOHardwareNoError; } -OSStatus HardwarePlugIn_DeviceStopStream(CMIOHardwarePlugInRef self, - CMIODeviceID deviceID, - CMIOStreamID streamID) +OSStatus HardwarePlugIn_DeviceStopStream(CMIOHardwarePlugInRef self, CMIODeviceID deviceID, CMIOStreamID streamID) { - DLogFunc(@"self=%p device=%d stream=%d", self, deviceID, streamID); + DLogFunc(@"self=%p device=%d stream=%d", self, deviceID, streamID); - OBSDALStream *stream = - (OBSDALStream *)[OBSDALObjectStore GetObjectWithId:streamID]; + OBSDALStream *stream = (OBSDALStream *) [OBSDALObjectStore GetObjectWithId:streamID]; - if (stream == nil) { - DLogFunc(@"ERR nil object"); - return kCMIOHardwareBadObjectError; - } + if (stream == nil) { + DLogFunc(@"ERR nil object"); + return kCMIOHardwareBadObjectError; + } - [[OBSDALPlugin SharedPlugIn] stopStream]; + [[OBSDALPlugin SharedPlugIn] stopStream]; - return kCMIOHardwareNoError; + return kCMIOHardwareNoError; } -OSStatus HardwarePlugIn_DeviceProcessAVCCommand(CMIOHardwarePlugInRef self, - CMIODeviceID, - CMIODeviceAVCCommand *) +OSStatus HardwarePlugIn_DeviceProcessAVCCommand(CMIOHardwarePlugInRef self, CMIODeviceID, CMIODeviceAVCCommand *) { - DLogFunc(@"self=%p", self); - return kCMIOHardwareNoError; + DLogFunc(@"self=%p", self); + return kCMIOHardwareNoError; } -OSStatus HardwarePlugIn_DeviceProcessRS422Command(CMIOHardwarePlugInRef self, - CMIODeviceID, - CMIODeviceRS422Command *) +OSStatus HardwarePlugIn_DeviceProcessRS422Command(CMIOHardwarePlugInRef self, CMIODeviceID, CMIODeviceRS422Command *) { - DLogFunc(@"self=%p", self); - return kCMIOHardwareNoError; + DLogFunc(@"self=%p", self); + return kCMIOHardwareNoError; } OSStatus HardwarePlugIn_StreamDeckPlay(CMIOHardwarePlugInRef self, CMIOStreamID) { - DLogFunc(@"self=%p", self); - return kCMIOHardwareIllegalOperationError; + DLogFunc(@"self=%p", self); + return kCMIOHardwareIllegalOperationError; } OSStatus HardwarePlugIn_StreamDeckStop(CMIOHardwarePlugInRef self, CMIOStreamID) { - DLogFunc(@"self=%p", self); - return kCMIOHardwareIllegalOperationError; + DLogFunc(@"self=%p", self); + return kCMIOHardwareIllegalOperationError; } -OSStatus HardwarePlugIn_StreamDeckJog(CMIOHardwarePlugInRef self, CMIOStreamID, - SInt32) +OSStatus HardwarePlugIn_StreamDeckJog(CMIOHardwarePlugInRef self, CMIOStreamID, SInt32) { - DLogFunc(@"self=%p", self); - return kCMIOHardwareIllegalOperationError; + DLogFunc(@"self=%p", self); + return kCMIOHardwareIllegalOperationError; } -OSStatus HardwarePlugIn_StreamDeckCueTo(CMIOHardwarePlugInRef self, - CMIOStreamID, Float64, Boolean) +OSStatus HardwarePlugIn_StreamDeckCueTo(CMIOHardwarePlugInRef self, CMIOStreamID, Float64, Boolean) { - DLogFunc(@"self=%p", self); - return kCMIOHardwareIllegalOperationError; + DLogFunc(@"self=%p", self); + return kCMIOHardwareIllegalOperationError; } static CMIOHardwarePlugInInterface sInterface = { - // Padding for COM - NULL, + // Padding for COM + NULL, - // IUnknown Routines - (HRESULT (*)(void *, CFUUIDBytes, - void **))HardwarePlugIn_QueryInterface, - (ULONG(*)(void *))HardwarePlugIn_AddRef, - (ULONG(*)(void *))HardwarePlugIn_Release, + // IUnknown Routines + (HRESULT (*)(void *, CFUUIDBytes, void **)) HardwarePlugIn_QueryInterface, (ULONG(*)(void *)) HardwarePlugIn_AddRef, + (ULONG(*)(void *)) HardwarePlugIn_Release, - // DAL Plug-In Routines - HardwarePlugIn_Initialize, HardwarePlugIn_InitializeWithObjectID, - HardwarePlugIn_Teardown, HardwarePlugIn_ObjectShow, - HardwarePlugIn_ObjectHasProperty, - HardwarePlugIn_ObjectIsPropertySettable, - HardwarePlugIn_ObjectGetPropertyDataSize, - HardwarePlugIn_ObjectGetPropertyData, - HardwarePlugIn_ObjectSetPropertyData, HardwarePlugIn_DeviceSuspend, - HardwarePlugIn_DeviceResume, HardwarePlugIn_DeviceStartStream, - HardwarePlugIn_DeviceStopStream, HardwarePlugIn_DeviceProcessAVCCommand, - HardwarePlugIn_DeviceProcessRS422Command, - HardwarePlugIn_StreamCopyBufferQueue, HardwarePlugIn_StreamDeckPlay, - HardwarePlugIn_StreamDeckStop, HardwarePlugIn_StreamDeckJog, - HardwarePlugIn_StreamDeckCueTo}; + // DAL Plug-In Routines + HardwarePlugIn_Initialize, HardwarePlugIn_InitializeWithObjectID, HardwarePlugIn_Teardown, + HardwarePlugIn_ObjectShow, HardwarePlugIn_ObjectHasProperty, HardwarePlugIn_ObjectIsPropertySettable, + HardwarePlugIn_ObjectGetPropertyDataSize, HardwarePlugIn_ObjectGetPropertyData, + HardwarePlugIn_ObjectSetPropertyData, HardwarePlugIn_DeviceSuspend, HardwarePlugIn_DeviceResume, + HardwarePlugIn_DeviceStartStream, HardwarePlugIn_DeviceStopStream, HardwarePlugIn_DeviceProcessAVCCommand, + HardwarePlugIn_DeviceProcessRS422Command, HardwarePlugIn_StreamCopyBufferQueue, HardwarePlugIn_StreamDeckPlay, + HardwarePlugIn_StreamDeckStop, HardwarePlugIn_StreamDeckJog, HardwarePlugIn_StreamDeckCueTo}; static CMIOHardwarePlugInInterface *sInterfacePtr = &sInterface; static CMIOHardwarePlugInRef sPlugInRef = &sInterfacePtr; CMIOHardwarePlugInRef OBSDALPlugInRef() { - return sPlugInRef; + return sPlugInRef; } diff --git a/plugins/mac-virtualcam/src/dal-plugin/OBSDALPlugInMain.mm b/plugins/mac-virtualcam/src/dal-plugin/OBSDALPlugInMain.mm index dde5e24c3..22c25c163 100644 --- a/plugins/mac-virtualcam/src/dal-plugin/OBSDALPlugInMain.mm +++ b/plugins/mac-virtualcam/src/dal-plugin/OBSDALPlugInMain.mm @@ -23,13 +23,13 @@ //! PlugInMain is the entrypoint for the plugin extern "C" { -__exported void *PlugInMain(CFAllocatorRef, CFUUIDRef requestedTypeUUID) -{ - DLogFunc(@"version=%@", PLUGIN_VERSION); - if (!CFEqual(requestedTypeUUID, kCMIOHardwarePlugInTypeID)) { - return 0; - } + __exported void *PlugInMain(CFAllocatorRef, CFUUIDRef requestedTypeUUID) + { + DLogFunc(@"version=%@", PLUGIN_VERSION); + if (!CFEqual(requestedTypeUUID, kCMIOHardwarePlugInTypeID)) { + return 0; + } - return OBSDALPlugInRef(); -} + return OBSDALPlugInRef(); + } } diff --git a/plugins/mac-virtualcam/src/dal-plugin/OBSDALStream.h b/plugins/mac-virtualcam/src/dal-plugin/OBSDALStream.h index 9d841ecea..f3526751e 100644 --- a/plugins/mac-virtualcam/src/dal-plugin/OBSDALStream.h +++ b/plugins/mac-virtualcam/src/dal-plugin/OBSDALStream.h @@ -28,18 +28,17 @@ NS_ASSUME_NONNULL_BEGIN - (instancetype _Nonnull)init; -- (CMSimpleQueueRef)copyBufferQueueWithAlteredProc: - (CMIODeviceStreamQueueAlteredProc)alteredProc - alteredRefCon:(void *)alteredRefCon; +- (CMSimpleQueueRef)copyBufferQueueWithAlteredProc:(CMIODeviceStreamQueueAlteredProc)alteredProc + alteredRefCon:(void *)alteredRefCon; - (void)startServingDefaultFrames; - (void)stopServingDefaultFrames; - (void)queuePixelBuffer:(CVPixelBufferRef)frame - timestamp:(uint64_t)timestamp - fpsNumerator:(uint32_t)fpsNumerator - fpsDenominator:(uint32_t)fpsDenominator; + timestamp:(uint64_t)timestamp + fpsNumerator:(uint32_t)fpsNumerator + fpsDenominator:(uint32_t)fpsDenominator; @end diff --git a/plugins/mac-virtualcam/src/dal-plugin/OBSDALStream.mm b/plugins/mac-virtualcam/src/dal-plugin/OBSDALStream.mm index 560b03657..18a55acd7 100644 --- a/plugins/mac-virtualcam/src/dal-plugin/OBSDALStream.mm +++ b/plugins/mac-virtualcam/src/dal-plugin/OBSDALStream.mm @@ -27,12 +27,12 @@ #import "OBSDALPlugIn.h" @interface OBSDALStream () { - CMSimpleQueueRef _queue; - CFTypeRef _clock; - NSImage *_testCardImage; - dispatch_source_t _frameDispatchSource; - NSSize _testCardSize; - Float64 _fps; + CMSimpleQueueRef _queue; + CFTypeRef _clock; + NSImage *_testCardImage; + dispatch_source_t _frameDispatchSource; + NSSize _testCardSize; + Float64 _fps; } @property CMIODeviceStreamQueueAlteredProc alteredProc; @@ -48,555 +48,489 @@ @implementation OBSDALStream -#define DEFAULT_FPS 30.0 -#define DEFAULT_WIDTH 1280 +#define DEFAULT_FPS 30.0 +#define DEFAULT_WIDTH 1280 #define DEFAULT_HEIGHT 720 - (instancetype _Nonnull)init { - self = [super init]; - if (self) { - _frameDispatchSource = dispatch_source_create( - DISPATCH_SOURCE_TYPE_TIMER, 0, 0, - dispatch_get_global_queue( - DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)); - __weak __typeof(self) wself = self; - dispatch_source_set_event_handler(_frameDispatchSource, ^{ - [wself fillFrame]; - }); - } - return self; + self = [super init]; + if (self) { + _frameDispatchSource = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, + dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)); + __weak __typeof(self) wself = self; + dispatch_source_set_event_handler(_frameDispatchSource, ^{ + [wself fillFrame]; + }); + } + return self; } - (void)dealloc { - DLog(@"Stream Dealloc"); - CMIOStreamClockInvalidate(_clock); - CFRelease(_clock); - _clock = NULL; - CFRelease(_queue); - _queue = NULL; - dispatch_suspend(_frameDispatchSource); + DLog(@"Stream Dealloc"); + CMIOStreamClockInvalidate(_clock); + CFRelease(_clock); + _clock = NULL; + CFRelease(_queue); + _queue = NULL; + dispatch_suspend(_frameDispatchSource); } - (void)startServingDefaultFrames { - DLogFunc(@""); - _testCardImage = nil; - _testCardSize = NSZeroSize; - _fps = 0; - dispatch_time_t startTime = dispatch_time(DISPATCH_TIME_NOW, 0); - uint64_t intervalTime = (int64_t)(NSEC_PER_SEC / self.fps); - dispatch_source_set_timer(_frameDispatchSource, startTime, intervalTime, - 0); - dispatch_resume(_frameDispatchSource); + DLogFunc(@""); + _testCardImage = nil; + _testCardSize = NSZeroSize; + _fps = 0; + dispatch_time_t startTime = dispatch_time(DISPATCH_TIME_NOW, 0); + uint64_t intervalTime = (int64_t) (NSEC_PER_SEC / self.fps); + dispatch_source_set_timer(_frameDispatchSource, startTime, intervalTime, 0); + dispatch_resume(_frameDispatchSource); } - (void)stopServingDefaultFrames { - DLogFunc(@""); - dispatch_suspend(_frameDispatchSource); + DLogFunc(@""); + dispatch_suspend(_frameDispatchSource); } - (CMSimpleQueueRef)queue { - if (_queue == NULL) { - // Allocate a one-second long queue, which we can use our FPS constant for. - OSStatus err = CMSimpleQueueCreate(kCFAllocatorDefault, - (int32_t)self.fps, &_queue); - if (err != noErr) { - DLog(@"Err %d in CMSimpleQueueCreate", err); - } - } - return _queue; + if (_queue == NULL) { + // Allocate a one-second long queue, which we can use our FPS constant for. + OSStatus err = CMSimpleQueueCreate(kCFAllocatorDefault, (int32_t) self.fps, &_queue); + if (err != noErr) { + DLog(@"Err %d in CMSimpleQueueCreate", err); + } + } + return _queue; } - (CFTypeRef)clock { - if (_clock == NULL) { - OSStatus err = CMIOStreamClockCreate( - kCFAllocatorDefault, - CFSTR("obs-mac-virtualcam::Stream::clock"), - (__bridge void *)self, CMTimeMake(1, 10), 100, 10, - &_clock); - if (err != noErr) { - DLog(@"Error %d from CMIOStreamClockCreate", err); - } - } - return _clock; + if (_clock == NULL) { + OSStatus err = CMIOStreamClockCreate(kCFAllocatorDefault, CFSTR("obs-mac-virtualcam::Stream::clock"), + (__bridge void *) self, CMTimeMake(1, 10), 100, 10, &_clock); + if (err != noErr) { + DLog(@"Error %d from CMIOStreamClockCreate", err); + } + } + return _clock; } - (NSSize)testCardSize { - if (NSEqualSizes(_testCardSize, NSZeroSize)) { - NSUserDefaults *defaults = - [NSUserDefaults standardUserDefaults]; - NSInteger width = [[defaults objectForKey:kTestCardWidthKey] - integerValue]; - NSInteger height = [[defaults objectForKey:kTestCardHeightKey] - integerValue]; - if (width == 0 || height == 0) { - _testCardSize = - NSMakeSize(DEFAULT_WIDTH, DEFAULT_HEIGHT); - } else { - _testCardSize = NSMakeSize(width, height); - } - } - return _testCardSize; + if (NSEqualSizes(_testCardSize, NSZeroSize)) { + NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; + NSInteger width = [[defaults objectForKey:kTestCardWidthKey] integerValue]; + NSInteger height = [[defaults objectForKey:kTestCardHeightKey] integerValue]; + if (width == 0 || height == 0) { + _testCardSize = NSMakeSize(DEFAULT_WIDTH, DEFAULT_HEIGHT); + } else { + _testCardSize = NSMakeSize(width, height); + } + } + return _testCardSize; } - (Float64)fps { - if (_fps == 0) { - NSUserDefaults *defaults = - [NSUserDefaults standardUserDefaults]; - double fps = - [[defaults objectForKey:kTestCardFPSKey] doubleValue]; - if (fps == 0) { - _fps = DEFAULT_FPS; - } else { - _fps = fps; - } - } - return _fps; + if (_fps == 0) { + NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; + double fps = [[defaults objectForKey:kTestCardFPSKey] doubleValue]; + if (fps == 0) { + _fps = DEFAULT_FPS; + } else { + _fps = fps; + } + } + return _fps; } - (NSImage *)testCardImage { - if (_testCardImage == nil) { - NSString *bundlePath = [[NSBundle - bundleForClass:[OBSDALStream class]] bundlePath]; - NSString *placeHolderPath = [bundlePath - stringByAppendingString: - @"/Contents/Resources/placeholder.png"]; - NSFileManager *fileManager = [NSFileManager defaultManager]; - NSURL *homeUrl = [fileManager homeDirectoryForCurrentUser]; - NSURL *customUrl = [homeUrl - URLByAppendingPathComponent: - @"Library/Application Support/obs-studio/plugin_config/mac-virtualcam/placeholder.png"]; - NSString *customPlaceHolder = customUrl.path; - if ([fileManager isReadableFileAtPath:customPlaceHolder]) - placeHolderPath = customPlaceHolder; - DLog(@"PlaceHolder:%@", placeHolderPath); - NSImage *placeholderImage = [[NSImage alloc] - initWithContentsOfFile:placeHolderPath]; + if (_testCardImage == nil) { + NSString *bundlePath = [[NSBundle bundleForClass:[OBSDALStream class]] bundlePath]; + NSString *placeHolderPath = [bundlePath stringByAppendingString:@"/Contents/Resources/placeholder.png"]; + NSFileManager *fileManager = [NSFileManager defaultManager]; + NSURL *homeUrl = [fileManager homeDirectoryForCurrentUser]; + NSURL *customUrl = + [homeUrl URLByAppendingPathComponent: + @"Library/Application Support/obs-studio/plugin_config/mac-virtualcam/placeholder.png"]; + NSString *customPlaceHolder = customUrl.path; + if ([fileManager isReadableFileAtPath:customPlaceHolder]) + placeHolderPath = customPlaceHolder; + DLog(@"PlaceHolder:%@", placeHolderPath); + NSImage *placeholderImage = [[NSImage alloc] initWithContentsOfFile:placeHolderPath]; - NSBitmapImageRep *rep = [[NSBitmapImageRep alloc] - initWithBitmapDataPlanes:NULL - pixelsWide:(NSInteger) - self.testCardSize.width - pixelsHigh:(NSInteger)self.testCardSize - .height - bitsPerSample:8 - samplesPerPixel:4 - hasAlpha:YES - isPlanar:NO - colorSpaceName:NSCalibratedRGBColorSpace - bytesPerRow:0 - bitsPerPixel:0]; - rep.size = self.testCardSize; + NSBitmapImageRep *rep = [[NSBitmapImageRep alloc] initWithBitmapDataPlanes:NULL + pixelsWide:(NSInteger) self.testCardSize.width + pixelsHigh:(NSInteger) self.testCardSize.height + bitsPerSample:8 + samplesPerPixel:4 + hasAlpha:YES + isPlanar:NO + colorSpaceName:NSCalibratedRGBColorSpace + bytesPerRow:0 + bitsPerPixel:0]; + rep.size = self.testCardSize; - double hScale = - placeholderImage.size.width / self.testCardSize.width; - double vScale = - placeholderImage.size.height / self.testCardSize.height; + double hScale = placeholderImage.size.width / self.testCardSize.width; + double vScale = placeholderImage.size.height / self.testCardSize.height; - double scaling = fmax(hScale, vScale); + double scaling = fmax(hScale, vScale); - double newWidth = placeholderImage.size.width / scaling; - double newHeight = placeholderImage.size.height / scaling; + double newWidth = placeholderImage.size.width / scaling; + double newHeight = placeholderImage.size.height / scaling; - double leftOffset = (self.testCardSize.width - newWidth) / 2; - double topOffset = (self.testCardSize.height - newHeight) / 2; + double leftOffset = (self.testCardSize.width - newWidth) / 2; + double topOffset = (self.testCardSize.height - newHeight) / 2; - [NSGraphicsContext saveGraphicsState]; - [NSGraphicsContext - setCurrentContext: - [NSGraphicsContext - graphicsContextWithBitmapImageRep:rep]]; + [NSGraphicsContext saveGraphicsState]; + [NSGraphicsContext setCurrentContext:[NSGraphicsContext graphicsContextWithBitmapImageRep:rep]]; - NSColor *backgroundColor = [NSColor blackColor]; - [backgroundColor set]; - NSRectFill(NSMakeRect(0, 0, self.testCardSize.width, - self.testCardSize.height)); + NSColor *backgroundColor = [NSColor blackColor]; + [backgroundColor set]; + NSRectFill(NSMakeRect(0, 0, self.testCardSize.width, self.testCardSize.height)); - [placeholderImage drawInRect:NSMakeRect(leftOffset, topOffset, - newWidth, newHeight) - fromRect:NSZeroRect - operation:NSCompositingOperationCopy - fraction:1.0]; - [NSGraphicsContext restoreGraphicsState]; + [placeholderImage drawInRect:NSMakeRect(leftOffset, topOffset, newWidth, newHeight) fromRect:NSZeroRect + operation:NSCompositingOperationCopy + fraction:1.0]; + [NSGraphicsContext restoreGraphicsState]; - NSImage *testCardImage = - [[NSImage alloc] initWithSize:self.testCardSize]; - [testCardImage addRepresentation:rep]; + NSImage *testCardImage = [[NSImage alloc] initWithSize:self.testCardSize]; + [testCardImage addRepresentation:rep]; - _testCardImage = testCardImage; - } - return _testCardImage; + _testCardImage = testCardImage; + } + return _testCardImage; } -- (CMSimpleQueueRef)copyBufferQueueWithAlteredProc: - (CMIODeviceStreamQueueAlteredProc)alteredProc - alteredRefCon:(void *)alteredRefCon +- (CMSimpleQueueRef)copyBufferQueueWithAlteredProc:(CMIODeviceStreamQueueAlteredProc)alteredProc + alteredRefCon:(void *)alteredRefCon { - self.alteredProc = alteredProc; - self.alteredRefCon = alteredRefCon; + self.alteredProc = alteredProc; + self.alteredRefCon = alteredRefCon; - // Retain this since it's a copy operation - CFRetain(self.queue); + // Retain this since it's a copy operation + CFRetain(self.queue); - return self.queue; + return self.queue; } - (CVPixelBufferRef)createPixelBufferWithTestAnimation { - int width = (int)self.testCardSize.width; - int height = (int)self.testCardSize.height; + int width = (int) self.testCardSize.width; + int height = (int) self.testCardSize.height; - NSDictionary *options = [NSDictionary - dictionaryWithObjectsAndKeys: - [NSNumber numberWithBool:YES], - kCVPixelBufferCGImageCompatibilityKey, - [NSNumber numberWithBool:YES], - kCVPixelBufferCGBitmapContextCompatibilityKey, nil]; - CVPixelBufferRef pxbuffer = NULL; - CVReturn status = CVPixelBufferCreate(kCFAllocatorDefault, width, - height, kCVPixelFormatType_32ARGB, - (__bridge CFDictionaryRef)options, - &pxbuffer); + NSDictionary *options = [NSDictionary + dictionaryWithObjectsAndKeys:[NSNumber numberWithBool:YES], kCVPixelBufferCGImageCompatibilityKey, + [NSNumber numberWithBool:YES], kCVPixelBufferCGBitmapContextCompatibilityKey, nil]; + CVPixelBufferRef pxbuffer = NULL; + CVReturn status = CVPixelBufferCreate(kCFAllocatorDefault, width, height, kCVPixelFormatType_32ARGB, + (__bridge CFDictionaryRef) options, &pxbuffer); - NSParameterAssert(status == kCVReturnSuccess && pxbuffer != NULL); + NSParameterAssert(status == kCVReturnSuccess && pxbuffer != NULL); - CVPixelBufferLockBaseAddress(pxbuffer, 0); - void *pxdata = CVPixelBufferGetBaseAddressOfPlane(pxbuffer, 0); - NSParameterAssert(pxdata != NULL); + CVPixelBufferLockBaseAddress(pxbuffer, 0); + void *pxdata = CVPixelBufferGetBaseAddressOfPlane(pxbuffer, 0); + NSParameterAssert(pxdata != NULL); - CGColorSpaceRef rgbColorSpace = CGColorSpaceCreateDeviceRGB(); - CGContextRef context = CGBitmapContextCreate( - pxdata, width, height, 8, - CVPixelBufferGetBytesPerRowOfPlane(pxbuffer, 0), rgbColorSpace, - kCGImageAlphaPremultipliedFirst | kCGImageByteOrder32Big); - CFRelease(rgbColorSpace); - NSParameterAssert(context); + CGColorSpaceRef rgbColorSpace = CGColorSpaceCreateDeviceRGB(); + CGContextRef context = CGBitmapContextCreate(pxdata, width, height, 8, + CVPixelBufferGetBytesPerRowOfPlane(pxbuffer, 0), rgbColorSpace, + kCGImageAlphaPremultipliedFirst | kCGImageByteOrder32Big); + CFRelease(rgbColorSpace); + NSParameterAssert(context); - NSGraphicsContext *nsContext = [NSGraphicsContext - graphicsContextWithCGContext:context - flipped:NO]; - [NSGraphicsContext setCurrentContext:nsContext]; + NSGraphicsContext *nsContext = [NSGraphicsContext graphicsContextWithCGContext:context flipped:NO]; + [NSGraphicsContext setCurrentContext:nsContext]; - NSRect rect = NSMakeRect(0, 0, self.testCardImage.size.width, - self.testCardImage.size.height); - CGImageRef image = [self.testCardImage CGImageForProposedRect:&rect - context:nsContext - hints:nil]; - CGContextDrawImage(context, - CGRectMake(0, 0, CGImageGetWidth(image), - CGImageGetHeight(image)), - image); + NSRect rect = NSMakeRect(0, 0, self.testCardImage.size.width, self.testCardImage.size.height); + CGImageRef image = [self.testCardImage CGImageForProposedRect:&rect context:nsContext hints:nil]; + CGContextDrawImage(context, CGRectMake(0, 0, CGImageGetWidth(image), CGImageGetHeight(image)), image); - // DrawDialWithFrame( - // NSMakeRect(0, 0, width, height), - // (int(self.fps) - self.sequenceNumber % int(self.fps)) * 360 / - // int(self.fps)); + // DrawDialWithFrame( + // NSMakeRect(0, 0, width, height), + // (int(self.fps) - self.sequenceNumber % int(self.fps)) * 360 / + // int(self.fps)); - CGContextRelease(context); + CGContextRelease(context); - CVPixelBufferUnlockBaseAddress(pxbuffer, 0); + CVPixelBufferUnlockBaseAddress(pxbuffer, 0); - return pxbuffer; + return pxbuffer; } - (void)fillFrame { - if (CMSimpleQueueGetFullness(self.queue) >= 1.0) { - return; - } + if (CMSimpleQueueGetFullness(self.queue) >= 1.0) { + return; + } - CVPixelBufferRef pixelBuffer = - [self createPixelBufferWithTestAnimation]; + CVPixelBufferRef pixelBuffer = [self createPixelBufferWithTestAnimation]; - uint64_t hostTime = clock_gettime_nsec_np(CLOCK_UPTIME_RAW); - CMSampleTimingInfo timingInfo = - CMSampleTimingInfoForTimestamp(hostTime, (uint32_t)self.fps, 1); + uint64_t hostTime = clock_gettime_nsec_np(CLOCK_UPTIME_RAW); + CMSampleTimingInfo timingInfo = CMSampleTimingInfoForTimestamp(hostTime, (uint32_t) self.fps, 1); - OSStatus err = CMIOStreamClockPostTimingEvent( - timingInfo.presentationTimeStamp, hostTime, true, self.clock); - if (err != noErr) { - DLog(@"CMIOStreamClockPostTimingEvent err %d", err); - } + OSStatus err = CMIOStreamClockPostTimingEvent(timingInfo.presentationTimeStamp, hostTime, true, self.clock); + if (err != noErr) { + DLog(@"CMIOStreamClockPostTimingEvent err %d", err); + } - CMFormatDescriptionRef format; - CMVideoFormatDescriptionCreateForImageBuffer(kCFAllocatorDefault, - pixelBuffer, &format); + CMFormatDescriptionRef format; + CMVideoFormatDescriptionCreateForImageBuffer(kCFAllocatorDefault, pixelBuffer, &format); - self.sequenceNumber = CMIOGetNextSequenceNumber(self.sequenceNumber); + self.sequenceNumber = CMIOGetNextSequenceNumber(self.sequenceNumber); - CMSampleBufferRef buffer; - err = CMIOSampleBufferCreateForImageBuffer( - kCFAllocatorDefault, pixelBuffer, format, &timingInfo, - self.sequenceNumber, kCMIOSampleBufferNoDiscontinuities, - &buffer); - CFRelease(pixelBuffer); - CFRelease(format); - if (err != noErr) { - DLog(@"CMIOSampleBufferCreateForImageBuffer err %d", err); - } + CMSampleBufferRef buffer; + err = CMIOSampleBufferCreateForImageBuffer(kCFAllocatorDefault, pixelBuffer, format, &timingInfo, + self.sequenceNumber, kCMIOSampleBufferNoDiscontinuities, &buffer); + CFRelease(pixelBuffer); + CFRelease(format); + if (err != noErr) { + DLog(@"CMIOSampleBufferCreateForImageBuffer err %d", err); + } - CMSimpleQueueEnqueue(self.queue, buffer); + CMSimpleQueueEnqueue(self.queue, buffer); - // Inform the clients that the queue has been altered - if (self.alteredProc != NULL) { - (self.alteredProc)(self.objectId, buffer, self.alteredRefCon); - } + // Inform the clients that the queue has been altered + if (self.alteredProc != NULL) { + (self.alteredProc)(self.objectId, buffer, self.alteredRefCon); + } } - (void)queuePixelBuffer:(CVPixelBufferRef)frame - timestamp:(uint64_t)timestamp - fpsNumerator:(uint32_t)fpsNumerator - fpsDenominator:(uint32_t)fpsDenominator + timestamp:(uint64_t)timestamp + fpsNumerator:(uint32_t)fpsNumerator + fpsDenominator:(uint32_t)fpsDenominator { - if (CMSimpleQueueGetFullness(self.queue) >= 1.0) { - DLog(@"Queue is full, bailing out"); - return; - } - OSStatus err = noErr; + if (CMSimpleQueueGetFullness(self.queue) >= 1.0) { + DLog(@"Queue is full, bailing out"); + return; + } + OSStatus err = noErr; - CMSampleTimingInfo timingInfo = CMSampleTimingInfoForTimestamp( - timestamp, fpsNumerator, fpsDenominator); + CMSampleTimingInfo timingInfo = CMSampleTimingInfoForTimestamp(timestamp, fpsNumerator, fpsDenominator); - err = CMIOStreamClockPostTimingEvent( - timingInfo.presentationTimeStamp, - clock_gettime_nsec_np(CLOCK_UPTIME_RAW), true, self.clock); - if (err != noErr) { - DLog(@"CMIOStreamClockPostTimingEvent err %d", err); - } + err = CMIOStreamClockPostTimingEvent(timingInfo.presentationTimeStamp, clock_gettime_nsec_np(CLOCK_UPTIME_RAW), + true, self.clock); + if (err != noErr) { + DLog(@"CMIOStreamClockPostTimingEvent err %d", err); + } - self.sequenceNumber = CMIOGetNextSequenceNumber(self.sequenceNumber); + self.sequenceNumber = CMIOGetNextSequenceNumber(self.sequenceNumber); - CMSampleBufferRef sampleBuffer; + CMSampleBufferRef sampleBuffer; - // Generate the video format description from that pixel buffer - CMVideoFormatDescriptionRef format; - err = CMVideoFormatDescriptionCreateForImageBuffer(kCFAllocatorDefault, - frame, &format); - if (err != noErr) { - DLog(@"CMVideoFormatDescriptionCreateForImageBuffer err %d", - err); - return; - } + // Generate the video format description from that pixel buffer + CMVideoFormatDescriptionRef format; + err = CMVideoFormatDescriptionCreateForImageBuffer(kCFAllocatorDefault, frame, &format); + if (err != noErr) { + DLog(@"CMVideoFormatDescriptionCreateForImageBuffer err %d", err); + return; + } - err = CMIOSampleBufferCreateForImageBuffer( - kCFAllocatorDefault, frame, format, &timingInfo, - self.sequenceNumber, kCMIOSampleBufferNoDiscontinuities, - &sampleBuffer); + err = CMIOSampleBufferCreateForImageBuffer(kCFAllocatorDefault, frame, format, &timingInfo, self.sequenceNumber, + kCMIOSampleBufferNoDiscontinuities, &sampleBuffer); - CFRelease(format); + CFRelease(format); - if (err != noErr) { - DLog(@"CMIOSampleBufferCreateForImageBuffer err %d", err); - return; - } + if (err != noErr) { + DLog(@"CMIOSampleBufferCreateForImageBuffer err %d", err); + return; + } - err = CMSimpleQueueEnqueue(self.queue, sampleBuffer); + err = CMSimpleQueueEnqueue(self.queue, sampleBuffer); - if (err != noErr) { - CFRelease(sampleBuffer); + if (err != noErr) { + CFRelease(sampleBuffer); - DLog(@"CMSimpleQueueEnqueue err %d", err); - return; - } + DLog(@"CMSimpleQueueEnqueue err %d", err); + return; + } - // Inform the clients that the queue has been altered - if (self.alteredProc != NULL) { - (self.alteredProc)(self.objectId, sampleBuffer, - self.alteredRefCon); - } + // Inform the clients that the queue has been altered + if (self.alteredProc != NULL) { + (self.alteredProc)(self.objectId, sampleBuffer, self.alteredRefCon); + } } - (CMVideoFormatDescriptionRef)getFormatDescription { - CMVideoFormatDescriptionRef formatDescription; - OSStatus err = CMVideoFormatDescriptionCreate( - kCFAllocatorDefault, - kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange, - (int32_t)self.testCardSize.width, - (int32_t)self.testCardSize.height, NULL, &formatDescription); - if (err != noErr) { - DLog(@"Error %d from CMVideoFormatDescriptionCreate", err); - } - return formatDescription; + CMVideoFormatDescriptionRef formatDescription; + OSStatus err = CMVideoFormatDescriptionCreate(kCFAllocatorDefault, kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange, + (int32_t) self.testCardSize.width, (int32_t) self.testCardSize.height, + NULL, &formatDescription); + if (err != noErr) { + DLog(@"Error %d from CMVideoFormatDescriptionCreate", err); + } + return formatDescription; } #pragma mark - CMIOObject - (UInt32)getPropertyDataSizeWithAddress:(CMIOObjectPropertyAddress)address - qualifierDataSize:(UInt32)qualifierDataSize - qualifierData:(nonnull const void *)qualifierData + qualifierDataSize:(UInt32)qualifierDataSize + qualifierData:(nonnull const void *)qualifierData { - switch (address.mSelector) { - case kCMIOStreamPropertyInitialPresentationTimeStampForLinkedAndSyncedAudio: - return sizeof(CMTime); - case kCMIOStreamPropertyOutputBuffersNeededForThrottledPlayback: - return sizeof(UInt32); - case kCMIOObjectPropertyName: - return sizeof(CFStringRef); - case kCMIOObjectPropertyManufacturer: - return sizeof(CFStringRef); - case kCMIOObjectPropertyElementName: - return sizeof(CFStringRef); - case kCMIOObjectPropertyElementCategoryName: - return sizeof(CFStringRef); - case kCMIOObjectPropertyElementNumberName: - return sizeof(CFStringRef); - case kCMIOStreamPropertyDirection: - return sizeof(UInt32); - case kCMIOStreamPropertyTerminalType: - return sizeof(UInt32); - case kCMIOStreamPropertyStartingChannel: - return sizeof(UInt32); - case kCMIOStreamPropertyLatency: - return sizeof(UInt32); - case kCMIOStreamPropertyFormatDescriptions: - return sizeof(CFArrayRef); - case kCMIOStreamPropertyFormatDescription: - return sizeof(CMFormatDescriptionRef); - case kCMIOStreamPropertyFrameRateRanges: - return sizeof(AudioValueRange); - case kCMIOStreamPropertyFrameRate: - case kCMIOStreamPropertyFrameRates: - return sizeof(Float64); - case kCMIOStreamPropertyMinimumFrameRate: - return sizeof(Float64); - case kCMIOStreamPropertyClock: - return sizeof(CFTypeRef); - default: - return 0; - }; + switch (address.mSelector) { + case kCMIOStreamPropertyInitialPresentationTimeStampForLinkedAndSyncedAudio: + return sizeof(CMTime); + case kCMIOStreamPropertyOutputBuffersNeededForThrottledPlayback: + return sizeof(UInt32); + case kCMIOObjectPropertyName: + return sizeof(CFStringRef); + case kCMIOObjectPropertyManufacturer: + return sizeof(CFStringRef); + case kCMIOObjectPropertyElementName: + return sizeof(CFStringRef); + case kCMIOObjectPropertyElementCategoryName: + return sizeof(CFStringRef); + case kCMIOObjectPropertyElementNumberName: + return sizeof(CFStringRef); + case kCMIOStreamPropertyDirection: + return sizeof(UInt32); + case kCMIOStreamPropertyTerminalType: + return sizeof(UInt32); + case kCMIOStreamPropertyStartingChannel: + return sizeof(UInt32); + case kCMIOStreamPropertyLatency: + return sizeof(UInt32); + case kCMIOStreamPropertyFormatDescriptions: + return sizeof(CFArrayRef); + case kCMIOStreamPropertyFormatDescription: + return sizeof(CMFormatDescriptionRef); + case kCMIOStreamPropertyFrameRateRanges: + return sizeof(AudioValueRange); + case kCMIOStreamPropertyFrameRate: + case kCMIOStreamPropertyFrameRates: + return sizeof(Float64); + case kCMIOStreamPropertyMinimumFrameRate: + return sizeof(Float64); + case kCMIOStreamPropertyClock: + return sizeof(CFTypeRef); + default: + return 0; + }; } - (void)getPropertyDataWithAddress:(CMIOObjectPropertyAddress)address - qualifierDataSize:(UInt32)qualifierDataSize - qualifierData:(nonnull const void *)qualifierData - dataSize:(UInt32)dataSize - dataUsed:(nonnull UInt32 *)dataUsed - data:(nonnull void *)data + qualifierDataSize:(UInt32)qualifierDataSize + qualifierData:(nonnull const void *)qualifierData + dataSize:(UInt32)dataSize + dataUsed:(nonnull UInt32 *)dataUsed + data:(nonnull void *)data { - switch (address.mSelector) { - case kCMIOObjectPropertyName: - *static_cast(data) = CFSTR("OBS Virtual Camera"); - *dataUsed = sizeof(CFStringRef); - break; - case kCMIOObjectPropertyElementName: - *static_cast(data) = - CFSTR("OBS Virtual Camera Stream Element"); - *dataUsed = sizeof(CFStringRef); - break; - case kCMIOObjectPropertyManufacturer: - case kCMIOObjectPropertyElementCategoryName: - case kCMIOObjectPropertyElementNumberName: - case kCMIOStreamPropertyTerminalType: - case kCMIOStreamPropertyStartingChannel: - case kCMIOStreamPropertyLatency: - case kCMIOStreamPropertyInitialPresentationTimeStampForLinkedAndSyncedAudio: - case kCMIOStreamPropertyOutputBuffersNeededForThrottledPlayback: - break; - case kCMIOStreamPropertyDirection: - *static_cast(data) = 1; - *dataUsed = sizeof(UInt32); - break; - case kCMIOStreamPropertyFormatDescriptions: - *static_cast( - data) = (__bridge_retained CFArrayRef)[NSArray - arrayWithObject:(__bridge_transfer NSObject *) - [self getFormatDescription]]; - *dataUsed = sizeof(CFArrayRef); - break; - case kCMIOStreamPropertyFormatDescription: - *static_cast(data) = - [self getFormatDescription]; - *dataUsed = sizeof(CMVideoFormatDescriptionRef); - break; - case kCMIOStreamPropertyFrameRateRanges: - AudioValueRange range; - range.mMinimum = self.fps; - range.mMaximum = self.fps; - *static_cast(data) = range; - *dataUsed = sizeof(AudioValueRange); - break; - case kCMIOStreamPropertyFrameRate: - case kCMIOStreamPropertyFrameRates: - *static_cast(data) = self.fps; - *dataUsed = sizeof(Float64); - break; - case kCMIOStreamPropertyMinimumFrameRate: - *static_cast(data) = self.fps; - *dataUsed = sizeof(Float64); - break; - case kCMIOStreamPropertyClock: - *static_cast(data) = self.clock; - // This one was incredibly tricky and cost me many hours to find. It seems that DAL expects - // the clock to be retained when returned. It's unclear why, and that seems inconsistent - // with other properties that don't have the same behavior. But this is what Apple's sample - // code does. - // https://github.com/lvsti/CoreMediaIO-DAL-Example/blob/0392cb/Sources/Extras/CoreMediaIO/DeviceAbstractionLayer/Devices/DP/Properties/CMIO_DP_Property_Clock.cpp#L75 - CFRetain(*static_cast(data)); - *dataUsed = sizeof(CFTypeRef); - break; - default: - *dataUsed = 0; - }; + switch (address.mSelector) { + case kCMIOObjectPropertyName: + *static_cast(data) = CFSTR("OBS Virtual Camera"); + *dataUsed = sizeof(CFStringRef); + break; + case kCMIOObjectPropertyElementName: + *static_cast(data) = CFSTR("OBS Virtual Camera Stream Element"); + *dataUsed = sizeof(CFStringRef); + break; + case kCMIOObjectPropertyManufacturer: + case kCMIOObjectPropertyElementCategoryName: + case kCMIOObjectPropertyElementNumberName: + case kCMIOStreamPropertyTerminalType: + case kCMIOStreamPropertyStartingChannel: + case kCMIOStreamPropertyLatency: + case kCMIOStreamPropertyInitialPresentationTimeStampForLinkedAndSyncedAudio: + case kCMIOStreamPropertyOutputBuffersNeededForThrottledPlayback: + break; + case kCMIOStreamPropertyDirection: + *static_cast(data) = 1; + *dataUsed = sizeof(UInt32); + break; + case kCMIOStreamPropertyFormatDescriptions: + *static_cast(data) = (__bridge_retained CFArrayRef) + [NSArray arrayWithObject:(__bridge_transfer NSObject *) [self getFormatDescription]]; + *dataUsed = sizeof(CFArrayRef); + break; + case kCMIOStreamPropertyFormatDescription: + *static_cast(data) = [self getFormatDescription]; + *dataUsed = sizeof(CMVideoFormatDescriptionRef); + break; + case kCMIOStreamPropertyFrameRateRanges: + AudioValueRange range; + range.mMinimum = self.fps; + range.mMaximum = self.fps; + *static_cast(data) = range; + *dataUsed = sizeof(AudioValueRange); + break; + case kCMIOStreamPropertyFrameRate: + case kCMIOStreamPropertyFrameRates: + *static_cast(data) = self.fps; + *dataUsed = sizeof(Float64); + break; + case kCMIOStreamPropertyMinimumFrameRate: + *static_cast(data) = self.fps; + *dataUsed = sizeof(Float64); + break; + case kCMIOStreamPropertyClock: + *static_cast(data) = self.clock; + // This one was incredibly tricky and cost me many hours to find. It seems that DAL expects + // the clock to be retained when returned. It's unclear why, and that seems inconsistent + // with other properties that don't have the same behavior. But this is what Apple's sample + // code does. + // https://github.com/lvsti/CoreMediaIO-DAL-Example/blob/0392cb/Sources/Extras/CoreMediaIO/DeviceAbstractionLayer/Devices/DP/Properties/CMIO_DP_Property_Clock.cpp#L75 + CFRetain(*static_cast(data)); + *dataUsed = sizeof(CFTypeRef); + break; + default: + *dataUsed = 0; + }; } - (BOOL)hasPropertyWithAddress:(CMIOObjectPropertyAddress)address { - switch (address.mSelector) { - case kCMIOObjectPropertyName: - case kCMIOObjectPropertyElementName: - case kCMIOStreamPropertyFormatDescriptions: - case kCMIOStreamPropertyFormatDescription: - case kCMIOStreamPropertyFrameRateRanges: - case kCMIOStreamPropertyFrameRate: - case kCMIOStreamPropertyFrameRates: - case kCMIOStreamPropertyMinimumFrameRate: - case kCMIOStreamPropertyClock: - return true; - case kCMIOObjectPropertyManufacturer: - case kCMIOObjectPropertyElementCategoryName: - case kCMIOObjectPropertyElementNumberName: - case kCMIOStreamPropertyDirection: - case kCMIOStreamPropertyTerminalType: - case kCMIOStreamPropertyStartingChannel: - case kCMIOStreamPropertyLatency: - case kCMIOStreamPropertyInitialPresentationTimeStampForLinkedAndSyncedAudio: - case kCMIOStreamPropertyOutputBuffersNeededForThrottledPlayback: - DLog(@"TODO: %@", - [OBSDALObjectStore - StringFromPropertySelector:address.mSelector]); - return false; - default: - return false; - }; + switch (address.mSelector) { + case kCMIOObjectPropertyName: + case kCMIOObjectPropertyElementName: + case kCMIOStreamPropertyFormatDescriptions: + case kCMIOStreamPropertyFormatDescription: + case kCMIOStreamPropertyFrameRateRanges: + case kCMIOStreamPropertyFrameRate: + case kCMIOStreamPropertyFrameRates: + case kCMIOStreamPropertyMinimumFrameRate: + case kCMIOStreamPropertyClock: + return true; + case kCMIOObjectPropertyManufacturer: + case kCMIOObjectPropertyElementCategoryName: + case kCMIOObjectPropertyElementNumberName: + case kCMIOStreamPropertyDirection: + case kCMIOStreamPropertyTerminalType: + case kCMIOStreamPropertyStartingChannel: + case kCMIOStreamPropertyLatency: + case kCMIOStreamPropertyInitialPresentationTimeStampForLinkedAndSyncedAudio: + case kCMIOStreamPropertyOutputBuffersNeededForThrottledPlayback: + DLog(@"TODO: %@", [OBSDALObjectStore StringFromPropertySelector:address.mSelector]); + return false; + default: + return false; + }; } - (BOOL)isPropertySettableWithAddress:(CMIOObjectPropertyAddress)address { - switch (address.mSelector) { - case kCMIOStreamPropertyFormatDescription: - case kCMIOStreamPropertyFrameRate: - // Suppress error logs complaining about the application not being able to set the desired format or frame rate. - return true; - default: - return false; - } + switch (address.mSelector) { + case kCMIOStreamPropertyFormatDescription: + case kCMIOStreamPropertyFrameRate: + // Suppress error logs complaining about the application not being able to set the desired format or frame rate. + return true; + default: + return false; + } } - (void)setPropertyDataWithAddress:(CMIOObjectPropertyAddress)address - qualifierDataSize:(UInt32)qualifierDataSize - qualifierData:(nonnull const void *)qualifierData - dataSize:(UInt32)dataSize - data:(nonnull const void *)data -{ -} + qualifierDataSize:(UInt32)qualifierDataSize + qualifierData:(nonnull const void *)qualifierData + dataSize:(UInt32)dataSize + data:(nonnull const void *)data +{} @end diff --git a/plugins/mac-virtualcam/src/obs-plugin/OBSDALMachServer.h b/plugins/mac-virtualcam/src/obs-plugin/OBSDALMachServer.h index 009999ef0..bc8fa5c36 100644 --- a/plugins/mac-virtualcam/src/obs-plugin/OBSDALMachServer.h +++ b/plugins/mac-virtualcam/src/obs-plugin/OBSDALMachServer.h @@ -18,9 +18,9 @@ NS_ASSUME_NONNULL_BEGIN Will eventually be used for sending frames to all connected clients */ - (void)sendPixelBuffer:(CVPixelBufferRef)frame - timestamp:(uint64_t)timestamp - fpsNumerator:(uint32_t)fpsNumerator - fpsDenominator:(uint32_t)fpsDenominator; + timestamp:(uint64_t)timestamp + fpsNumerator:(uint32_t)fpsNumerator + fpsDenominator:(uint32_t)fpsDenominator; - (void)stop; diff --git a/plugins/mac-virtualcam/src/obs-plugin/OBSDALMachServer.mm b/plugins/mac-virtualcam/src/obs-plugin/OBSDALMachServer.mm index b7352f2c9..31b750b0b 100644 --- a/plugins/mac-virtualcam/src/obs-plugin/OBSDALMachServer.mm +++ b/plugins/mac-virtualcam/src/obs-plugin/OBSDALMachServer.mm @@ -20,26 +20,26 @@ - (id)init { - if (self = [super init]) { - self.clientPorts = [[NSMutableSet alloc] init]; - } - return self; + if (self = [super init]) { + self.clientPorts = [[NSMutableSet alloc] init]; + } + return self; } - (void)dealloc { - blog(LOG_DEBUG, "tearing down MachServer"); - [self.runLoop removePort:self.port forMode:NSDefaultRunLoopMode]; - [self.port invalidate]; - self.port.delegate = nil; + blog(LOG_DEBUG, "tearing down MachServer"); + [self.runLoop removePort:self.port forMode:NSDefaultRunLoopMode]; + [self.port invalidate]; + self.port.delegate = nil; } - (void)run { - if (self.port != nil) { - blog(LOG_DEBUG, "mach server already running!"); - return; - } + if (self.port != nil) { + blog(LOG_DEBUG, "mach server already running!"); + return; + } // It's a bummer this is deprecated. The replacement, NSXPCConnection, seems to require // an assistant process that lives inside the .app bundle. This would be more modern, but adds @@ -49,145 +49,119 @@ // these APIs (which are, interestingly, not deprecated) #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wdeprecated-declarations" - self.port = [[NSMachBootstrapServer sharedInstance] - servicePortWithName:@MACH_SERVICE_NAME]; + self.port = [[NSMachBootstrapServer sharedInstance] servicePortWithName:@MACH_SERVICE_NAME]; #pragma clang diagnostic pop - if (self.port == nil) { - // This probably means another instance is running. - blog(LOG_ERROR, "Unable to open mach server port."); - return; - } + if (self.port == nil) { + // This probably means another instance is running. + blog(LOG_ERROR, "Unable to open mach server port."); + return; + } - self.port.delegate = self; + self.port.delegate = self; - self.runLoop = [NSRunLoop currentRunLoop]; - [self.runLoop addPort:self.port forMode:NSDefaultRunLoopMode]; + self.runLoop = [NSRunLoop currentRunLoop]; + [self.runLoop addPort:self.port forMode:NSDefaultRunLoopMode]; - blog(LOG_DEBUG, "mach server running!"); + blog(LOG_DEBUG, "mach server running!"); } - (void)handlePortMessage:(NSPortMessage *)message { - switch (message.msgid) { - case MachMsgIdConnect: - if (message.sendPort != nil) { - blog(LOG_DEBUG, - "mach server received connect message from port %d!", - ((NSMachPort *)message.sendPort).machPort); - [self.clientPorts addObject:message.sendPort]; - } - break; - default: - blog(LOG_ERROR, "Unexpected mach message ID %u", - (unsigned)message.msgid); - break; - } + switch (message.msgid) { + case MachMsgIdConnect: + if (message.sendPort != nil) { + blog(LOG_DEBUG, "mach server received connect message from port %d!", + ((NSMachPort *) message.sendPort).machPort); + [self.clientPorts addObject:message.sendPort]; + } + break; + default: + blog(LOG_ERROR, "Unexpected mach message ID %u", (unsigned) message.msgid); + break; + } } -- (void)sendMessageToClientsWithMsgId:(uint32_t)msgId - components:(nullable NSArray *)components +- (void)sendMessageToClientsWithMsgId:(uint32_t)msgId components:(nullable NSArray *)components { - if ([self.clientPorts count] <= 0) { - return; - } + if ([self.clientPorts count] <= 0) { + return; + } - NSMutableSet *removedPorts = [NSMutableSet set]; + NSMutableSet *removedPorts = [NSMutableSet set]; - for (NSPort *port in self.clientPorts) { - @try { - NSPortMessage *message = [[NSPortMessage alloc] - initWithSendPort:port - receivePort:nil - components:components]; - message.msgid = msgId; - if (![port isValid] || - ![message - sendBeforeDate: - [NSDate dateWithTimeIntervalSinceNow: - 1.0]]) { - blog(LOG_DEBUG, - "failed to send message to %d, removing it from the clients!", - ((NSMachPort *)port).machPort); + for (NSPort *port in self.clientPorts) { + @try { + NSPortMessage *message = [[NSPortMessage alloc] initWithSendPort:port receivePort:nil + components:components]; + message.msgid = msgId; + if (![port isValid] || ![message sendBeforeDate:[NSDate dateWithTimeIntervalSinceNow:1.0]]) { + blog(LOG_DEBUG, "failed to send message to %d, removing it from the clients!", + ((NSMachPort *) port).machPort); - [port invalidate]; - [removedPorts addObject:port]; - } - } @catch (NSException *exception) { - blog(LOG_DEBUG, - "failed to send message (exception) to %d, removing it from the clients!", - ((NSMachPort *)port).machPort); + [port invalidate]; + [removedPorts addObject:port]; + } + } @catch (NSException *exception) { + blog(LOG_DEBUG, "failed to send message (exception) to %d, removing it from the clients!", + ((NSMachPort *) port).machPort); - [port invalidate]; - [removedPorts addObject:port]; - } - } + [port invalidate]; + [removedPorts addObject:port]; + } + } - // Remove dead ports if necessary - [self.clientPorts minusSet:removedPorts]; + // Remove dead ports if necessary + [self.clientPorts minusSet:removedPorts]; } - (void)sendPixelBuffer:(CVPixelBufferRef)frame - timestamp:(uint64_t)timestamp - fpsNumerator:(uint32_t)fpsNumerator - fpsDenominator:(uint32_t)fpsDenominator + timestamp:(uint64_t)timestamp + fpsNumerator:(uint32_t)fpsNumerator + fpsDenominator:(uint32_t)fpsDenominator { - if ([self.clientPorts count] <= 0) { - return; - } + if ([self.clientPorts count] <= 0) { + return; + } - @autoreleasepool { - NSData *timestampData = [NSData - dataWithBytes:×tamp - length:sizeof(timestamp)]; - NSData *fpsNumeratorData = [NSData - dataWithBytes:&fpsNumerator - length:sizeof(fpsNumerator)]; - NSData *fpsDenominatorData = [NSData - dataWithBytes:&fpsDenominator - length:sizeof(fpsDenominator)]; + @autoreleasepool { + NSData *timestampData = [NSData dataWithBytes:×tamp length:sizeof(timestamp)]; + NSData *fpsNumeratorData = [NSData dataWithBytes:&fpsNumerator length:sizeof(fpsNumerator)]; + NSData *fpsDenominatorData = [NSData dataWithBytes:&fpsDenominator length:sizeof(fpsDenominator)]; - IOSurfaceRef surface = CVPixelBufferGetIOSurface(frame); + IOSurfaceRef surface = CVPixelBufferGetIOSurface(frame); #ifndef __aarch64__ - IOSurfaceLock(surface, 0, NULL); + IOSurfaceLock(surface, 0, NULL); #endif - if (!surface) { - blog(LOG_ERROR, - "unable to access IOSurface associated with CVPixelBuffer"); - return; - } + if (!surface) { + blog(LOG_ERROR, "unable to access IOSurface associated with CVPixelBuffer"); + return; + } - mach_port_t framePort = IOSurfaceCreateMachPort(surface); + mach_port_t framePort = IOSurfaceCreateMachPort(surface); - if (!framePort) { - blog(LOG_ERROR, - "unable to allocate mach port for IOSurface"); - return; - } + if (!framePort) { + blog(LOG_ERROR, "unable to allocate mach port for IOSurface"); + return; + } - [self sendMessageToClientsWithMsgId:MachMsgIdFrame - components:@[ - [NSMachPort - portWithMachPort:framePort - options:NSMachPortDeallocateNone], - timestampData, - fpsNumeratorData, - fpsDenominatorData - ]]; + [self sendMessageToClientsWithMsgId:MachMsgIdFrame components:@[ + [NSMachPort portWithMachPort:framePort options:NSMachPortDeallocateNone], timestampData, fpsNumeratorData, + fpsDenominatorData + ]]; - mach_port_deallocate(mach_task_self(), framePort); + mach_port_deallocate(mach_task_self(), framePort); #ifndef __aarch64__ - IOSurfaceUnlock(surface, 0, NULL); + IOSurfaceUnlock(surface, 0, NULL); #endif - } + } } - (void)stop { - blog(LOG_DEBUG, "sending stop message to %lu clients", - self.clientPorts.count); - [self sendMessageToClientsWithMsgId:MachMsgIdStop components:nil]; + blog(LOG_DEBUG, "sending stop message to %lu clients", self.clientPorts.count); + [self sendMessageToClientsWithMsgId:MachMsgIdStop components:nil]; } @end diff --git a/plugins/mac-virtualcam/src/obs-plugin/plugin-main.mm b/plugins/mac-virtualcam/src/obs-plugin/plugin-main.mm index 281620fa4..b015d0e10 100644 --- a/plugins/mac-virtualcam/src/obs-plugin/plugin-main.mm +++ b/plugins/mac-virtualcam/src/obs-plugin/plugin-main.mm @@ -9,40 +9,39 @@ OBS_DECLARE_MODULE() OBS_MODULE_USE_DEFAULT_LOCALE("mac-virtualcam", "en-US") MODULE_EXPORT const char *obs_module_description(void) { - return "macOS virtual webcam output"; + return "macOS virtual webcam output"; } NSString *const OBSDalDestination = @"/Library/CoreMediaIO/Plug-Ins/DAL"; static bool cmio_extension_supported() { - if (@available(macOS 13.0, *)) { - return true; - } else { - return false; - } + if (@available(macOS 13.0, *)) { + return true; + } else { + return false; + } } struct virtualcam_data { - obs_output_t *output; - obs_video_info videoInfo; - CVPixelBufferPoolRef pool; + obs_output_t *output; + obs_video_info videoInfo; + CVPixelBufferPoolRef pool; - // CMIO Extension (available with macOS 13) - CMSimpleQueueRef queue; - CMIODeviceID deviceID; - CMIOStreamID streamID; - CMFormatDescriptionRef formatDescription; - id extensionDelegate; + // CMIO Extension (available with macOS 13) + CMSimpleQueueRef queue; + CMIODeviceID deviceID; + CMIOStreamID streamID; + CMFormatDescriptionRef formatDescription; + id extensionDelegate; - // Legacy DAL (deprecated since macOS 12.3) - OBSDALMachServer *machServer; + // Legacy DAL (deprecated since macOS 12.3) + OBSDALMachServer *machServer; }; -@interface SystemExtensionActivationDelegate - : NSObject { -@private - struct virtualcam_data *_vcam; +@interface SystemExtensionActivationDelegate : NSObject { + @private + struct virtualcam_data *_vcam; } @property (getter=isInstalled) BOOL installed; @@ -54,613 +53,502 @@ struct virtualcam_data { - (id)initWithVcam:(virtualcam_data *)vcam { - self = [super init]; + self = [super init]; - if (self) { - _vcam = vcam; - _installed = NO; - } + if (self) { + _vcam = vcam; + _installed = NO; + } - return self; + return self; } -- (OSSystemExtensionReplacementAction) - request:(nonnull OSSystemExtensionRequest *)request - actionForReplacingExtension: - (nonnull OSSystemExtensionProperties *)existing - withExtension:(nonnull OSSystemExtensionProperties *)ext +- (OSSystemExtensionReplacementAction)request:(nonnull OSSystemExtensionRequest *)request + actionForReplacingExtension:(nonnull OSSystemExtensionProperties *)existing + withExtension:(nonnull OSSystemExtensionProperties *)ext { - NSString *extVersion = - [NSString stringWithFormat:@"%@.%@", [ext bundleShortVersion], - [ext bundleVersion]]; - NSString *existingVersion = [NSString - stringWithFormat:@"%@.%@", [existing bundleShortVersion], - [existing bundleVersion]]; + NSString *extVersion = [NSString stringWithFormat:@"%@.%@", [ext bundleShortVersion], [ext bundleVersion]]; + NSString *existingVersion = + [NSString stringWithFormat:@"%@.%@", [existing bundleShortVersion], [existing bundleVersion]]; - if ([extVersion compare:existingVersion - options:NSNumericSearch] == NSOrderedDescending) { - return OSSystemExtensionReplacementActionReplace; - } else { - return OSSystemExtensionReplacementActionCancel; - } + if ([extVersion compare:existingVersion options:NSNumericSearch] == NSOrderedDescending) { + return OSSystemExtensionReplacementActionReplace; + } else { + return OSSystemExtensionReplacementActionCancel; + } } -- (void)request:(nonnull OSSystemExtensionRequest *)request - didFailWithError:(nonnull NSError *)error +- (void)request:(nonnull OSSystemExtensionRequest *)request didFailWithError:(nonnull NSError *)error { - NSString *errorMessage; - int severity; + NSString *errorMessage; + int severity; - switch (error.code) { - case OSSystemExtensionErrorRequestCanceled: - errorMessage = - @"macOS Camera Extension installation request cancelled."; - severity = LOG_INFO; - break; - case OSSystemExtensionErrorUnsupportedParentBundleLocation: - self.lastErrorMessage = [NSString - stringWithUTF8String: - obs_module_text( - "Error.SystemExtension.WrongLocation")]; - errorMessage = self.lastErrorMessage; - severity = LOG_WARNING; - break; - default: - self.lastErrorMessage = error.localizedDescription; - errorMessage = [NSString - stringWithFormat: - @"OSSystemExtensionErrorCode %ld (\"%s\")", - error.code, - error.localizedDescription.UTF8String]; - severity = LOG_ERROR; - break; - } + switch (error.code) { + case OSSystemExtensionErrorRequestCanceled: + errorMessage = @"macOS Camera Extension installation request cancelled."; + severity = LOG_INFO; + break; + case OSSystemExtensionErrorUnsupportedParentBundleLocation: + self.lastErrorMessage = + [NSString stringWithUTF8String:obs_module_text("Error.SystemExtension.WrongLocation")]; + errorMessage = self.lastErrorMessage; + severity = LOG_WARNING; + break; + default: + self.lastErrorMessage = error.localizedDescription; + errorMessage = [NSString stringWithFormat:@"OSSystemExtensionErrorCode %ld (\"%s\")", error.code, + error.localizedDescription.UTF8String]; + severity = LOG_ERROR; + break; + } - blog(severity, "mac-camera-extension error: %s", - errorMessage.UTF8String); + blog(severity, "mac-camera-extension error: %s", errorMessage.UTF8String); } -- (void)request:(nonnull OSSystemExtensionRequest *)request - didFinishWithResult:(OSSystemExtensionRequestResult)result +- (void)request:(nonnull OSSystemExtensionRequest *)request didFinishWithResult:(OSSystemExtensionRequestResult)result { - self.installed = YES; - blog(LOG_INFO, "macOS Camera Extension activated successfully."); + self.installed = YES; + blog(LOG_INFO, "macOS Camera Extension activated successfully."); } - (void)requestNeedsUserApproval:(nonnull OSSystemExtensionRequest *)request { - self.installed = NO; - blog(LOG_INFO, "macOS Camera Extension user approval required."); + self.installed = NO; + blog(LOG_INFO, "macOS Camera Extension user approval required."); } @end static void install_cmio_system_extension(struct virtualcam_data *vcam) { - OSSystemExtensionRequest *request = [OSSystemExtensionRequest - activationRequestForExtension: - @"com.obsproject.obs-studio.mac-camera-extension" - queue:dispatch_get_main_queue()]; - request.delegate = vcam->extensionDelegate; + OSSystemExtensionRequest *request = [OSSystemExtensionRequest + activationRequestForExtension:@"com.obsproject.obs-studio.mac-camera-extension" + queue:dispatch_get_main_queue()]; + request.delegate = vcam->extensionDelegate; - [[OSSystemExtensionManager sharedManager] submitRequest:request]; + [[OSSystemExtensionManager sharedManager] submitRequest:request]; } typedef enum { - OBSDalPluginNotInstalled, - OBSDalPluginInstalled, - OBSDalPluginNeedsUpdate + OBSDalPluginNotInstalled, + OBSDalPluginInstalled, + OBSDalPluginNeedsUpdate } dal_plugin_status; static dal_plugin_status check_dal_plugin() { - NSFileManager *fileManager = [NSFileManager defaultManager]; + NSFileManager *fileManager = [NSFileManager defaultManager]; - NSString *dalPluginFileName = [OBSDalDestination - stringByAppendingString:@"/obs-mac-virtualcam.plugin"]; + NSString *dalPluginFileName = [OBSDalDestination stringByAppendingString:@"/obs-mac-virtualcam.plugin"]; - BOOL dalPluginInstalled = - [fileManager fileExistsAtPath:dalPluginFileName]; + BOOL dalPluginInstalled = [fileManager fileExistsAtPath:dalPluginFileName]; - if (dalPluginInstalled) { - NSDictionary *dalPluginInfoPlist = [NSDictionary - dictionaryWithContentsOfURL: - [NSURL fileURLWithPath: - [OBSDalDestination - stringByAppendingString: - @"/obs-mac-virtualcam.plugin/Contents/Info.plist"]]]; + if (dalPluginInstalled) { + NSDictionary *dalPluginInfoPlist = [NSDictionary + dictionaryWithContentsOfURL: + [NSURL fileURLWithPath:[OBSDalDestination + stringByAppendingString:@"/obs-mac-virtualcam.plugin/Contents/Info.plist"]]]; - NSString *dalPluginVersion = [dalPluginInfoPlist - valueForKey:@"CFBundleShortVersionString"]; - NSString *dalPluginBuild = - [dalPluginInfoPlist valueForKey:@"CFBundleVersion"]; + NSString *dalPluginVersion = [dalPluginInfoPlist valueForKey:@"CFBundleShortVersionString"]; + NSString *dalPluginBuild = [dalPluginInfoPlist valueForKey:@"CFBundleVersion"]; - NSString *obsVersion = [[[NSBundle mainBundle] infoDictionary] - objectForKey:@"CFBundleShortVersionString"]; - NSString *obsBuild = [[[NSBundle mainBundle] infoDictionary] - objectForKey:(NSString *)kCFBundleVersionKey]; - BOOL dalPluginUpdateNeeded = - !([dalPluginVersion isEqualToString:obsVersion] && - [dalPluginBuild isEqualToString:obsBuild]); + NSString *obsVersion = [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleShortVersionString"]; + NSString *obsBuild = [[[NSBundle mainBundle] infoDictionary] objectForKey:(NSString *) kCFBundleVersionKey]; + BOOL dalPluginUpdateNeeded = + !([dalPluginVersion isEqualToString:obsVersion] && [dalPluginBuild isEqualToString:obsBuild]); - return dalPluginUpdateNeeded ? OBSDalPluginNeedsUpdate - : OBSDalPluginInstalled; - } + return dalPluginUpdateNeeded ? OBSDalPluginNeedsUpdate : OBSDalPluginInstalled; + } - return OBSDalPluginNotInstalled; + return OBSDalPluginNotInstalled; } static bool install_dal_plugin(bool update) { - NSFileManager *fileManager = [NSFileManager defaultManager]; - BOOL dalPluginDirExists = - [fileManager fileExistsAtPath:OBSDalDestination]; + NSFileManager *fileManager = [NSFileManager defaultManager]; + BOOL dalPluginDirExists = [fileManager fileExistsAtPath:OBSDalDestination]; - NSURL *bundleURL = [[NSBundle mainBundle] bundleURL]; - NSString *pluginPath = @"Contents/Resources/obs-mac-virtualcam.plugin"; + NSURL *bundleURL = [[NSBundle mainBundle] bundleURL]; + NSString *pluginPath = @"Contents/Resources/obs-mac-virtualcam.plugin"; - NSURL *pluginUrl = [bundleURL URLByAppendingPathComponent:pluginPath]; - NSString *dalPluginSourcePath = [pluginUrl path]; + NSURL *pluginUrl = [bundleURL URLByAppendingPathComponent:pluginPath]; + NSString *dalPluginSourcePath = [pluginUrl path]; - NSString *createPluginDirCmd = - (!dalPluginDirExists) - ? [NSString stringWithFormat:@"mkdir -p '%@' && ", - OBSDalDestination] - : @""; - NSString *deleteOldPluginCmd = - (update) ? [NSString stringWithFormat:@"rm -rf '%@' && ", - OBSDalDestination] - : @""; - NSString *copyPluginCmd = [NSString - stringWithFormat:@"cp -R '%@' '%@'", dalPluginSourcePath, - OBSDalDestination]; + NSString *createPluginDirCmd = + (!dalPluginDirExists) ? [NSString stringWithFormat:@"mkdir -p '%@' && ", OBSDalDestination] : @""; + NSString *deleteOldPluginCmd = (update) ? [NSString stringWithFormat:@"rm -rf '%@' && ", OBSDalDestination] : @""; + NSString *copyPluginCmd = [NSString stringWithFormat:@"cp -R '%@' '%@'", dalPluginSourcePath, OBSDalDestination]; - if ([fileManager fileExistsAtPath:dalPluginSourcePath]) { - NSString *copyCmd = [NSString - stringWithFormat: - @"do shell script \"%@%@%@\" with administrator privileges", - createPluginDirCmd, deleteOldPluginCmd, - copyPluginCmd]; + if ([fileManager fileExistsAtPath:dalPluginSourcePath]) { + NSString *copyCmd = [NSString stringWithFormat:@"do shell script \"%@%@%@\" with administrator privileges", + createPluginDirCmd, deleteOldPluginCmd, copyPluginCmd]; - NSDictionary *errorDict; - NSAppleScript *scriptObject = - [[NSAppleScript alloc] initWithSource:copyCmd]; - [scriptObject executeAndReturnError:&errorDict]; - if (errorDict != nil) { - const char *errorMessage = [[errorDict - objectForKey:@"NSAppleScriptErrorMessage"] - UTF8String]; + NSDictionary *errorDict; + NSAppleScript *scriptObject = [[NSAppleScript alloc] initWithSource:copyCmd]; + [scriptObject executeAndReturnError:&errorDict]; + if (errorDict != nil) { + const char *errorMessage = [[errorDict objectForKey:@"NSAppleScriptErrorMessage"] UTF8String]; - blog(LOG_INFO, - "[macOS] VirtualCam DAL Plugin Installation status: %s", - errorMessage); - return false; - } else { - return true; - } - } else { - blog(LOG_INFO, - "[macOS] VirtualCam DAL Plugin not shipped with OBS"); - return false; - } + blog(LOG_INFO, "[macOS] VirtualCam DAL Plugin Installation status: %s", errorMessage); + return false; + } else { + return true; + } + } else { + blog(LOG_INFO, "[macOS] VirtualCam DAL Plugin not shipped with OBS"); + return false; + } } static bool uninstall_dal_plugin() { - NSAppleScript *scriptObject = [[NSAppleScript alloc] - initWithSource: - [NSString - stringWithFormat: - @"do shell script \"rm -rf %@/obs-mac-virtualcam.plugin\" with administrator privileges", - OBSDalDestination]]; + NSAppleScript *scriptObject = [[NSAppleScript alloc] + initWithSource:[NSString + stringWithFormat: + @"do shell script \"rm -rf %@/obs-mac-virtualcam.plugin\" with administrator privileges", + OBSDalDestination]]; - NSDictionary *errorDict; + NSDictionary *errorDict; - [scriptObject executeAndReturnError:&errorDict]; - if (errorDict) { - blog(LOG_INFO, - "[macOS] VirtualCam DAL Plugin could not be uninstalled: %s", - [[errorDict objectForKey:NSAppleScriptErrorMessage] - UTF8String]); - return false; - } else { - return true; - } + [scriptObject executeAndReturnError:&errorDict]; + if (errorDict) { + blog(LOG_INFO, "[macOS] VirtualCam DAL Plugin could not be uninstalled: %s", + [[errorDict objectForKey:NSAppleScriptErrorMessage] UTF8String]); + return false; + } else { + return true; + } } -FourCharCode convert_video_format_to_mac(enum video_format format, - enum video_range_type range) +FourCharCode convert_video_format_to_mac(enum video_format format, enum video_range_type range) { - switch (format) { - case VIDEO_FORMAT_I420: - return (range == VIDEO_RANGE_FULL) - ? kCVPixelFormatType_420YpCbCr8PlanarFullRange - : kCVPixelFormatType_420YpCbCr8Planar; - case VIDEO_FORMAT_NV12: - return (range == VIDEO_RANGE_FULL) - ? kCVPixelFormatType_420YpCbCr8BiPlanarFullRange - : kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange; - case VIDEO_FORMAT_UYVY: - return (range == VIDEO_RANGE_FULL) - ? kCVPixelFormatType_422YpCbCr8FullRange - : kCVPixelFormatType_422YpCbCr8; - case VIDEO_FORMAT_P010: - return (range == VIDEO_RANGE_FULL) - ? kCVPixelFormatType_420YpCbCr10BiPlanarFullRange - : kCVPixelFormatType_420YpCbCr10BiPlanarVideoRange; - default: - // Zero indicates that the format is not supported on macOS - // Note that some formats do have an associated constant, but - // constructing such formats fails with kCVReturnInvalidPixelFormat. - return 0; - } + switch (format) { + case VIDEO_FORMAT_I420: + return (range == VIDEO_RANGE_FULL) ? kCVPixelFormatType_420YpCbCr8PlanarFullRange + : kCVPixelFormatType_420YpCbCr8Planar; + case VIDEO_FORMAT_NV12: + return (range == VIDEO_RANGE_FULL) ? kCVPixelFormatType_420YpCbCr8BiPlanarFullRange + : kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange; + case VIDEO_FORMAT_UYVY: + return (range == VIDEO_RANGE_FULL) ? kCVPixelFormatType_422YpCbCr8FullRange : kCVPixelFormatType_422YpCbCr8; + case VIDEO_FORMAT_P010: + return (range == VIDEO_RANGE_FULL) ? kCVPixelFormatType_420YpCbCr10BiPlanarFullRange + : kCVPixelFormatType_420YpCbCr10BiPlanarVideoRange; + default: + // Zero indicates that the format is not supported on macOS + // Note that some formats do have an associated constant, but + // constructing such formats fails with kCVReturnInvalidPixelFormat. + return 0; + } } static const char *virtualcam_output_get_name(void *type_data) { - (void)type_data; - return obs_module_text("Plugin_Name"); + (void) type_data; + return obs_module_text("Plugin_Name"); } -static void *virtualcam_output_create(obs_data_t *settings, - obs_output_t *output) +static void *virtualcam_output_create(obs_data_t *settings, obs_output_t *output) { - UNUSED_PARAMETER(settings); + UNUSED_PARAMETER(settings); - struct virtualcam_data *vcam = - (struct virtualcam_data *)bzalloc(sizeof(*vcam)); + struct virtualcam_data *vcam = (struct virtualcam_data *) bzalloc(sizeof(*vcam)); - vcam->output = output; + vcam->output = output; - if (cmio_extension_supported()) { - vcam->extensionDelegate = - [[SystemExtensionActivationDelegate alloc] - initWithVcam:vcam]; - install_cmio_system_extension(vcam); - } else { - vcam->machServer = [[OBSDALMachServer alloc] init]; - } + if (cmio_extension_supported()) { + vcam->extensionDelegate = [[SystemExtensionActivationDelegate alloc] initWithVcam:vcam]; + install_cmio_system_extension(vcam); + } else { + vcam->machServer = [[OBSDALMachServer alloc] init]; + } - return vcam; + return vcam; } static void virtualcam_output_destroy(void *data) { - struct virtualcam_data *vcam = (struct virtualcam_data *)data; + struct virtualcam_data *vcam = (struct virtualcam_data *) data; - if (cmio_extension_supported()) { - vcam->extensionDelegate = nil; - } else { - vcam->machServer = nil; - } + if (cmio_extension_supported()) { + vcam->extensionDelegate = nil; + } else { + vcam->machServer = nil; + } - bfree(vcam); + bfree(vcam); } static bool virtualcam_output_start(void *data) { - struct virtualcam_data *vcam = (struct virtualcam_data *)data; + struct virtualcam_data *vcam = (struct virtualcam_data *) data; - dal_plugin_status dal_status = check_dal_plugin(); + dal_plugin_status dal_status = check_dal_plugin(); - if (cmio_extension_supported()) { - if (dal_status != OBSDalPluginNotInstalled) { - if (!uninstall_dal_plugin()) { - obs_output_set_last_error( - vcam->output, - obs_module_text( - "Error.DAL.NotUninstalled")); - return false; - } - } + if (cmio_extension_supported()) { + if (dal_status != OBSDalPluginNotInstalled) { + if (!uninstall_dal_plugin()) { + obs_output_set_last_error(vcam->output, obs_module_text("Error.DAL.NotUninstalled")); + return false; + } + } - SystemExtensionActivationDelegate *delegate = - vcam->extensionDelegate; + SystemExtensionActivationDelegate *delegate = vcam->extensionDelegate; - if (!delegate.installed) { - if (delegate.lastErrorMessage) { - obs_output_set_last_error( - vcam->output, - [NSString - stringWithFormat: - @"%s\n\n%@", - obs_module_text( - "Error.SystemExtension.InstallationError"), - delegate.lastErrorMessage] - .UTF8String); - } else { - obs_output_set_last_error( - vcam->output, - obs_module_text( - "Error.SystemExtension.NotInstalled")); - } + if (!delegate.installed) { + if (delegate.lastErrorMessage) { + obs_output_set_last_error( + vcam->output, + [NSString stringWithFormat:@"%s\n\n%@", obs_module_text("Error.SystemExtension.InstallationError"), + delegate.lastErrorMessage] + .UTF8String); + } else { + obs_output_set_last_error(vcam->output, obs_module_text("Error.SystemExtension.NotInstalled")); + } - return false; - } - } else { - bool success = false; - if (dal_status == OBSDalPluginNotInstalled) { - success = install_dal_plugin(false); - } else if (dal_status == OBSDalPluginNeedsUpdate) { - success = install_dal_plugin(true); - } else { - success = true; - } + return false; + } + } else { + bool success = false; + if (dal_status == OBSDalPluginNotInstalled) { + success = install_dal_plugin(false); + } else if (dal_status == OBSDalPluginNeedsUpdate) { + success = install_dal_plugin(true); + } else { + success = true; + } - if (!success) { - obs_output_set_last_error(vcam->output, - "Error.DAL.NotInstalled"); - return false; - } - } + if (!success) { + obs_output_set_last_error(vcam->output, "Error.DAL.NotInstalled"); + return false; + } + } - obs_get_video_info(&vcam->videoInfo); + obs_get_video_info(&vcam->videoInfo); - FourCharCode video_format = convert_video_format_to_mac( - vcam->videoInfo.output_format, vcam->videoInfo.range); + FourCharCode video_format = convert_video_format_to_mac(vcam->videoInfo.output_format, vcam->videoInfo.range); - struct video_scale_info conversion = {}; - conversion.width = vcam->videoInfo.output_width; - conversion.height = vcam->videoInfo.output_height; - conversion.colorspace = vcam->videoInfo.colorspace; - conversion.range = vcam->videoInfo.range; + struct video_scale_info conversion = {}; + conversion.width = vcam->videoInfo.output_width; + conversion.height = vcam->videoInfo.output_height; + conversion.colorspace = vcam->videoInfo.colorspace; + conversion.range = vcam->videoInfo.range; - if (!video_format) { - // Selected output format is not supported natively by CoreVideo, CPU conversion necessary - blog(LOG_WARNING, - "Selected output format (%s) not supported by CoreVideo, enabling CPU transcoding...", - get_video_format_name(vcam->videoInfo.output_format)); + if (!video_format) { + // Selected output format is not supported natively by CoreVideo, CPU conversion necessary + blog(LOG_WARNING, "Selected output format (%s) not supported by CoreVideo, enabling CPU transcoding...", + get_video_format_name(vcam->videoInfo.output_format)); - conversion.format = VIDEO_FORMAT_NV12; - video_format = convert_video_format_to_mac(conversion.format, - conversion.range); - } else { - conversion.format = vcam->videoInfo.output_format; - } - obs_output_set_video_conversion(vcam->output, &conversion); + conversion.format = VIDEO_FORMAT_NV12; + video_format = convert_video_format_to_mac(conversion.format, conversion.range); + } else { + conversion.format = vcam->videoInfo.output_format; + } + obs_output_set_video_conversion(vcam->output, &conversion); - NSDictionary *pAttr = @{}; - NSDictionary *pbAttr = @{ - (id)kCVPixelBufferPixelFormatTypeKey: @(video_format), - (id)kCVPixelBufferWidthKey: @(vcam->videoInfo.output_width), - (id)kCVPixelBufferHeightKey: @(vcam->videoInfo.output_height), - (id)kCVPixelBufferIOSurfacePropertiesKey: @{} - }; - CVReturn status = CVPixelBufferPoolCreate( - kCFAllocatorDefault, (__bridge CFDictionaryRef)pAttr, - (__bridge CFDictionaryRef)pbAttr, &vcam->pool); + NSDictionary *pAttr = @ {}; + NSDictionary *pbAttr = @{ + (id) kCVPixelBufferPixelFormatTypeKey: @(video_format), + (id) kCVPixelBufferWidthKey: @(vcam->videoInfo.output_width), + (id) kCVPixelBufferHeightKey: @(vcam->videoInfo.output_height), + (id) kCVPixelBufferIOSurfacePropertiesKey: @ {} + }; + CVReturn status = CVPixelBufferPoolCreate(kCFAllocatorDefault, (__bridge CFDictionaryRef) pAttr, + (__bridge CFDictionaryRef) pbAttr, &vcam->pool); - if (status != kCVReturnSuccess) { - blog(LOG_ERROR, - "unable to allocate pixel buffer pool (error %d)", status); - return false; - } + if (status != kCVReturnSuccess) { + blog(LOG_ERROR, "unable to allocate pixel buffer pool (error %d)", status); + return false; + } - if (cmio_extension_supported()) { - UInt32 size; - UInt32 used; + if (cmio_extension_supported()) { + UInt32 size; + UInt32 used; - CMIOObjectPropertyAddress address{ - .mSelector = kCMIOHardwarePropertyDevices, - .mScope = kCMIOObjectPropertyScopeGlobal, - .mElement = kCMIOObjectPropertyElementMain}; - CMIOObjectGetPropertyDataSize(kCMIOObjectSystemObject, &address, - 0, NULL, &size); - size_t num_devices = size / sizeof(CMIOObjectID); - CMIOObjectID cmio_devices[num_devices]; - CMIOObjectGetPropertyData(kCMIOObjectSystemObject, &address, 0, - NULL, size, &used, &cmio_devices); + CMIOObjectPropertyAddress address {.mSelector = kCMIOHardwarePropertyDevices, + .mScope = kCMIOObjectPropertyScopeGlobal, + .mElement = kCMIOObjectPropertyElementMain}; + CMIOObjectGetPropertyDataSize(kCMIOObjectSystemObject, &address, 0, NULL, &size); + size_t num_devices = size / sizeof(CMIOObjectID); + CMIOObjectID cmio_devices[num_devices]; + CMIOObjectGetPropertyData(kCMIOObjectSystemObject, &address, 0, NULL, size, &used, &cmio_devices); - vcam->deviceID = 0; + vcam->deviceID = 0; - NSString *OBSVirtualCamUUID = [[NSBundle - bundleWithIdentifier:@"com.obsproject.mac-virtualcam"] - objectForInfoDictionaryKey:@"OBSCameraDeviceUUID"]; - for (size_t i = 0; i < num_devices; i++) { - CMIOObjectID cmio_device = cmio_devices[i]; - address.mSelector = kCMIODevicePropertyDeviceUID; + NSString *OBSVirtualCamUUID = [[NSBundle bundleWithIdentifier:@"com.obsproject.mac-virtualcam"] + objectForInfoDictionaryKey:@"OBSCameraDeviceUUID"]; + for (size_t i = 0; i < num_devices; i++) { + CMIOObjectID cmio_device = cmio_devices[i]; + address.mSelector = kCMIODevicePropertyDeviceUID; - UInt32 device_name_size; - CMIOObjectGetPropertyDataSize(cmio_device, &address, 0, - NULL, &device_name_size); + UInt32 device_name_size; + CMIOObjectGetPropertyDataSize(cmio_device, &address, 0, NULL, &device_name_size); - CFStringRef uid; - CMIOObjectGetPropertyData(cmio_device, &address, 0, - NULL, device_name_size, &used, - &uid); + CFStringRef uid; + CMIOObjectGetPropertyData(cmio_device, &address, 0, NULL, device_name_size, &used, &uid); - const char *uid_string = CFStringGetCStringPtr( - uid, kCFStringEncodingUTF8); - if (uid_string && - strcmp(uid_string, OBSVirtualCamUUID.UTF8String) == - 0) { - vcam->deviceID = cmio_device; - CFRelease(uid); - break; - } else { - CFRelease(uid); - } - } + const char *uid_string = CFStringGetCStringPtr(uid, kCFStringEncodingUTF8); + if (uid_string && strcmp(uid_string, OBSVirtualCamUUID.UTF8String) == 0) { + vcam->deviceID = cmio_device; + CFRelease(uid); + break; + } else { + CFRelease(uid); + } + } - if (!vcam->deviceID) { - obs_output_set_last_error( - vcam->output, - obs_module_text( - "Error.SystemExtension.CameraUnavailable")); - return false; - } + if (!vcam->deviceID) { + obs_output_set_last_error(vcam->output, obs_module_text("Error.SystemExtension.CameraUnavailable")); + return false; + } - address.mSelector = kCMIODevicePropertyStreams; - CMIOObjectGetPropertyDataSize(vcam->deviceID, &address, 0, NULL, - &size); - CMIOStreamID stream_ids[(size / sizeof(CMIOStreamID))]; + address.mSelector = kCMIODevicePropertyStreams; + CMIOObjectGetPropertyDataSize(vcam->deviceID, &address, 0, NULL, &size); + CMIOStreamID stream_ids[(size / sizeof(CMIOStreamID))]; - CMIOObjectGetPropertyData(vcam->deviceID, &address, 0, NULL, - size, &used, &stream_ids); + CMIOObjectGetPropertyData(vcam->deviceID, &address, 0, NULL, size, &used, &stream_ids); - vcam->streamID = stream_ids[1]; + vcam->streamID = stream_ids[1]; - CMIOStreamCopyBufferQueue( - vcam->streamID, [](CMIOStreamID, void *, void *) {}, - NULL, &vcam->queue); - CMVideoFormatDescriptionCreate(kCFAllocatorDefault, - video_format, - vcam->videoInfo.output_width, - vcam->videoInfo.output_height, - NULL, &vcam->formatDescription); + CMIOStreamCopyBufferQueue( + vcam->streamID, [](CMIOStreamID, void *, void *) { + }, NULL, &vcam->queue); + CMVideoFormatDescriptionCreate(kCFAllocatorDefault, video_format, vcam->videoInfo.output_width, + vcam->videoInfo.output_height, NULL, &vcam->formatDescription); - OSStatus result = - CMIODeviceStartStream(vcam->deviceID, vcam->streamID); + OSStatus result = CMIODeviceStartStream(vcam->deviceID, vcam->streamID); - if (result != noErr) { - obs_output_set_last_error( - vcam->output, - obs_module_text( - "Error.SystemExtension.CameraNotStarted")); - return false; - } - } else { - [vcam->machServer run]; - } + if (result != noErr) { + obs_output_set_last_error(vcam->output, obs_module_text("Error.SystemExtension.CameraNotStarted")); + return false; + } + } else { + [vcam->machServer run]; + } - if (!obs_output_begin_data_capture(vcam->output, 0)) { - return false; - } + if (!obs_output_begin_data_capture(vcam->output, 0)) { + return false; + } - return true; + return true; } static void virtualcam_output_stop(void *data, uint64_t ts) { - UNUSED_PARAMETER(ts); + UNUSED_PARAMETER(ts); - struct virtualcam_data *vcam = (struct virtualcam_data *)data; + struct virtualcam_data *vcam = (struct virtualcam_data *) data; - obs_output_end_data_capture(vcam->output); - if (cmio_extension_supported()) { - CMIODeviceStopStream(vcam->deviceID, vcam->streamID); - CFRelease(vcam->formatDescription); - } else { - [vcam->machServer stop]; - } - CVPixelBufferPoolRelease(vcam->pool); + obs_output_end_data_capture(vcam->output); + if (cmio_extension_supported()) { + CMIODeviceStopStream(vcam->deviceID, vcam->streamID); + CFRelease(vcam->formatDescription); + } else { + [vcam->machServer stop]; + } + CVPixelBufferPoolRelease(vcam->pool); } static void virtualcam_output_raw_video(void *data, struct video_data *frame) { - struct virtualcam_data *vcam = (struct virtualcam_data *)data; + struct virtualcam_data *vcam = (struct virtualcam_data *) data; - CVPixelBufferRef frameRef = nil; - CVReturn status = CVPixelBufferPoolCreatePixelBuffer( - kCFAllocatorDefault, vcam->pool, &frameRef); + CVPixelBufferRef frameRef = nil; + CVReturn status = CVPixelBufferPoolCreatePixelBuffer(kCFAllocatorDefault, vcam->pool, &frameRef); - if (status != kCVReturnSuccess) { - blog(LOG_ERROR, "unable to allocate pixel buffer (error %d)", - status); - return; - } + if (status != kCVReturnSuccess) { + blog(LOG_ERROR, "unable to allocate pixel buffer (error %d)", status); + return; + } - // Copy all planes into pixel buffer - size_t planeCount = CVPixelBufferGetPlaneCount(frameRef); - CVPixelBufferLockBaseAddress(frameRef, 0); + // Copy all planes into pixel buffer + size_t planeCount = CVPixelBufferGetPlaneCount(frameRef); + CVPixelBufferLockBaseAddress(frameRef, 0); - if (planeCount == 0) { - uint8_t *src = frame->data[0]; - uint8_t *dst = (uint8_t *)CVPixelBufferGetBaseAddress(frameRef); + if (planeCount == 0) { + uint8_t *src = frame->data[0]; + uint8_t *dst = (uint8_t *) CVPixelBufferGetBaseAddress(frameRef); - size_t destBytesPerRow = CVPixelBufferGetBytesPerRow(frameRef); - size_t srcBytesPerRow = frame->linesize[0]; - size_t height = CVPixelBufferGetHeight(frameRef); + size_t destBytesPerRow = CVPixelBufferGetBytesPerRow(frameRef); + size_t srcBytesPerRow = frame->linesize[0]; + size_t height = CVPixelBufferGetHeight(frameRef); - // Sometimes CVPixelBufferCreate will create a pixel buffer that's a different - // size than necessary to hold the frame (probably for some optimization reason). - // If that is the case this will do a row-by-row copy into the buffer. - if (destBytesPerRow == srcBytesPerRow) { - memcpy(dst, src, destBytesPerRow * height); - } else { - for (int line = 0; (size_t)line < height; line++) { - memcpy(dst, src, srcBytesPerRow); - src += srcBytesPerRow; - dst += destBytesPerRow; - } - } - } else { - for (size_t plane = 0; plane < planeCount; plane++) { - uint8_t *src = frame->data[plane]; + // Sometimes CVPixelBufferCreate will create a pixel buffer that's a different + // size than necessary to hold the frame (probably for some optimization reason). + // If that is the case this will do a row-by-row copy into the buffer. + if (destBytesPerRow == srcBytesPerRow) { + memcpy(dst, src, destBytesPerRow * height); + } else { + for (int line = 0; (size_t) line < height; line++) { + memcpy(dst, src, srcBytesPerRow); + src += srcBytesPerRow; + dst += destBytesPerRow; + } + } + } else { + for (size_t plane = 0; plane < planeCount; plane++) { + uint8_t *src = frame->data[plane]; - if (!src) { - blog(LOG_WARNING, - "Video data from OBS contains less planes than CVPixelBuffer"); - break; - } + if (!src) { + blog(LOG_WARNING, "Video data from OBS contains less planes than CVPixelBuffer"); + break; + } - uint8_t *dst = - (uint8_t *)CVPixelBufferGetBaseAddressOfPlane( - frameRef, plane); + uint8_t *dst = (uint8_t *) CVPixelBufferGetBaseAddressOfPlane(frameRef, plane); - size_t destBytesPerRow = - CVPixelBufferGetBytesPerRowOfPlane(frameRef, - plane); - size_t srcBytesPerRow = frame->linesize[plane]; - size_t height = - CVPixelBufferGetHeightOfPlane(frameRef, plane); + size_t destBytesPerRow = CVPixelBufferGetBytesPerRowOfPlane(frameRef, plane); + size_t srcBytesPerRow = frame->linesize[plane]; + size_t height = CVPixelBufferGetHeightOfPlane(frameRef, plane); - if (destBytesPerRow == srcBytesPerRow) { - memcpy(dst, src, destBytesPerRow * height); - } else { - for (int line = 0; (size_t)line < height; - line++) { - memcpy(dst, src, srcBytesPerRow); - src += srcBytesPerRow; - dst += destBytesPerRow; - } - } - } - } + if (destBytesPerRow == srcBytesPerRow) { + memcpy(dst, src, destBytesPerRow * height); + } else { + for (int line = 0; (size_t) line < height; line++) { + memcpy(dst, src, srcBytesPerRow); + src += srcBytesPerRow; + dst += destBytesPerRow; + } + } + } + } - CVPixelBufferUnlockBaseAddress(frameRef, 0); + CVPixelBufferUnlockBaseAddress(frameRef, 0); - if (cmio_extension_supported()) { - CMSampleBufferRef sampleBuffer; - CMSampleTimingInfo timingInfo{ - .presentationTimeStamp = - CMTimeMake(frame->timestamp, NSEC_PER_SEC)}; + if (cmio_extension_supported()) { + CMSampleBufferRef sampleBuffer; + CMSampleTimingInfo timingInfo {.presentationTimeStamp = CMTimeMake(frame->timestamp, NSEC_PER_SEC)}; - CMSampleBufferCreateForImageBuffer(kCFAllocatorDefault, - frameRef, true, NULL, NULL, - vcam->formatDescription, - &timingInfo, &sampleBuffer); - CMSimpleQueueEnqueue(vcam->queue, sampleBuffer); - } else { - // Share pixel buffer with clients - [vcam->machServer sendPixelBuffer:frameRef - timestamp:frame->timestamp - fpsNumerator:vcam->videoInfo.fps_num - fpsDenominator:vcam->videoInfo.fps_den]; - } + CMSampleBufferCreateForImageBuffer(kCFAllocatorDefault, frameRef, true, NULL, NULL, vcam->formatDescription, + &timingInfo, &sampleBuffer); + CMSimpleQueueEnqueue(vcam->queue, sampleBuffer); + } else { + // Share pixel buffer with clients + [vcam->machServer sendPixelBuffer:frameRef timestamp:frame->timestamp fpsNumerator:vcam->videoInfo.fps_num + fpsDenominator:vcam->videoInfo.fps_den]; + } - CVPixelBufferRelease(frameRef); + CVPixelBufferRelease(frameRef); } struct obs_output_info virtualcam_output_info = { - .id = "virtualcam_output", - .flags = OBS_OUTPUT_VIDEO, - .get_name = virtualcam_output_get_name, - .create = virtualcam_output_create, - .destroy = virtualcam_output_destroy, - .start = virtualcam_output_start, - .stop = virtualcam_output_stop, - .raw_video = virtualcam_output_raw_video, + .id = "virtualcam_output", + .flags = OBS_OUTPUT_VIDEO, + .get_name = virtualcam_output_get_name, + .create = virtualcam_output_create, + .destroy = virtualcam_output_destroy, + .start = virtualcam_output_start, + .stop = virtualcam_output_stop, + .raw_video = virtualcam_output_raw_video, }; bool obs_module_load(void) { - obs_register_output(&virtualcam_output_info); + obs_register_output(&virtualcam_output_info); - obs_data_t *obs_settings = obs_data_create(); - obs_data_set_bool(obs_settings, "vcamEnabled", true); - obs_apply_private_data(obs_settings); - obs_data_release(obs_settings); + obs_data_t *obs_settings = obs_data_create(); + obs_data_set_bool(obs_settings, "vcamEnabled", true); + obs_apply_private_data(obs_settings); + obs_data_release(obs_settings); - return true; + return true; } diff --git a/plugins/obs-vst/mac/EditorWidget-osx.mm b/plugins/obs-vst/mac/EditorWidget-osx.mm index 9ed0eb121..dd356749e 100644 --- a/plugins/obs-vst/mac/EditorWidget-osx.mm +++ b/plugins/obs-vst/mac/EditorWidget-osx.mm @@ -23,40 +23,35 @@ along with this program. If not, see . void EditorWidget::buildEffectContainer(AEffect *effect) { - NSView *view = - [[NSView alloc] initWithFrame:NSMakeRect(0, 0, 300, 300)]; - cocoaViewContainer = - QWidget::createWindowContainer(QWindow::fromWinId(WId(view))); - cocoaViewContainer->move(0, 0); - cocoaViewContainer->resize(300, 300); - cocoaViewContainer->show(); + NSView *view = [[NSView alloc] initWithFrame:NSMakeRect(0, 0, 300, 300)]; + cocoaViewContainer = QWidget::createWindowContainer(QWindow::fromWinId(WId(view))); + cocoaViewContainer->move(0, 0); + cocoaViewContainer->resize(300, 300); + cocoaViewContainer->show(); - QGridLayout *hblParams = new QGridLayout(); - hblParams->setContentsMargins(0, 0, 0, 0); - hblParams->setSpacing(0); - hblParams->addWidget(cocoaViewContainer); + QGridLayout *hblParams = new QGridLayout(); + hblParams->setContentsMargins(0, 0, 0, 0); + hblParams->setSpacing(0); + hblParams->addWidget(cocoaViewContainer); - VstRect *vstRect = nullptr; - effect->dispatcher(effect, effEditGetRect, 0, 0, &vstRect, 0); - if (vstRect) { - NSRect frame = NSMakeRect(vstRect->left, vstRect->top, - vstRect->right, vstRect->bottom); + VstRect *vstRect = nullptr; + effect->dispatcher(effect, effEditGetRect, 0, 0, &vstRect, 0); + if (vstRect) { + NSRect frame = NSMakeRect(vstRect->left, vstRect->top, vstRect->right, vstRect->bottom); - [view setFrame:frame]; + [view setFrame:frame]; - cocoaViewContainer->resize(vstRect->right - vstRect->left, - vstRect->bottom - vstRect->top); + cocoaViewContainer->resize(vstRect->right - vstRect->left, vstRect->bottom - vstRect->top); - setFixedSize(vstRect->right - vstRect->left, - vstRect->bottom - vstRect->top); - } + setFixedSize(vstRect->right - vstRect->left, vstRect->bottom - vstRect->top); + } - effect->dispatcher(effect, effEditOpen, 0, 0, view, 0); + effect->dispatcher(effect, effEditOpen, 0, 0, view, 0); - setLayout(hblParams); + setLayout(hblParams); } void EditorWidget::handleResizeRequest(int width, int height) { - setFixedSize(width, height); + setFixedSize(width, height); } diff --git a/plugins/obs-vst/mac/VSTPlugin-osx.mm b/plugins/obs-vst/mac/VSTPlugin-osx.mm index 0a9e5399b..17f942323 100644 --- a/plugins/obs-vst/mac/VSTPlugin-osx.mm +++ b/plugins/obs-vst/mac/VSTPlugin-osx.mm @@ -19,81 +19,74 @@ along with this program. If not, see . AEffect *VSTPlugin::loadEffect() { - AEffect *newEffect = NULL; + AEffect *newEffect = NULL; - // Create a path to the bundle - CFStringRef pluginPathStringRef = CFStringCreateWithCString( - NULL, pluginPath.c_str(), kCFStringEncodingUTF8); - CFURLRef bundleUrl = CFURLCreateWithFileSystemPath(kCFAllocatorDefault, - pluginPathStringRef, - kCFURLPOSIXPathStyle, - true); + // Create a path to the bundle + CFStringRef pluginPathStringRef = CFStringCreateWithCString(NULL, pluginPath.c_str(), kCFStringEncodingUTF8); + CFURLRef bundleUrl = + CFURLCreateWithFileSystemPath(kCFAllocatorDefault, pluginPathStringRef, kCFURLPOSIXPathStyle, true); - if (bundleUrl == NULL) { - CFRelease(pluginPathStringRef); - blog(LOG_WARNING, - "Couldn't make URL reference for VST plug-in"); - return NULL; - } + if (bundleUrl == NULL) { + CFRelease(pluginPathStringRef); + blog(LOG_WARNING, "Couldn't make URL reference for VST plug-in"); + return NULL; + } - // Open the bundle - bundle = CFBundleCreate(kCFAllocatorDefault, bundleUrl); - if (bundle == NULL) { - blog(LOG_WARNING, "Couldn't create VST bundle reference."); - CFRelease(pluginPathStringRef); - CFRelease(bundleUrl); - return NULL; - } + // Open the bundle + bundle = CFBundleCreate(kCFAllocatorDefault, bundleUrl); + if (bundle == NULL) { + blog(LOG_WARNING, "Couldn't create VST bundle reference."); + CFRelease(pluginPathStringRef); + CFRelease(bundleUrl); + return NULL; + } - vstPluginMain mainEntryPoint = NULL; - mainEntryPoint = (vstPluginMain)CFBundleGetFunctionPointerForName( - bundle, CFSTR("VSTPluginMain")); + vstPluginMain mainEntryPoint = NULL; + mainEntryPoint = (vstPluginMain) CFBundleGetFunctionPointerForName(bundle, CFSTR("VSTPluginMain")); - // VST plugins previous to the 2.4 SDK used main_macho for the - // entry point name. - if (mainEntryPoint == NULL) { - mainEntryPoint = - (vstPluginMain)CFBundleGetFunctionPointerForName( - bundle, CFSTR("main_macho")); - } + // VST plugins previous to the 2.4 SDK used main_macho for the + // entry point name. + if (mainEntryPoint == NULL) { + mainEntryPoint = (vstPluginMain) CFBundleGetFunctionPointerForName(bundle, CFSTR("main_macho")); + } - if (mainEntryPoint == NULL) { - blog(LOG_WARNING, "Couldn't get a pointer to plug-in's main()"); - CFRelease(pluginPathStringRef); - CFRelease(bundleUrl); - CFRelease(bundle); - bundle = NULL; - return NULL; - } + if (mainEntryPoint == NULL) { + blog(LOG_WARNING, "Couldn't get a pointer to plug-in's main()"); + CFRelease(pluginPathStringRef); + CFRelease(bundleUrl); + CFRelease(bundle); + bundle = NULL; + return NULL; + } - newEffect = mainEntryPoint(hostCallback_static); - if (newEffect == NULL) { - blog(LOG_WARNING, "VST Plug-in's main() returns null."); - CFRelease(pluginPathStringRef); - CFRelease(bundleUrl); - CFRelease(bundle); - bundle = NULL; - return NULL; - } + newEffect = mainEntryPoint(hostCallback_static); + if (newEffect == NULL) { + blog(LOG_WARNING, "VST Plug-in's main() returns null."); + CFRelease(pluginPathStringRef); + CFRelease(bundleUrl); + CFRelease(bundle); + bundle = NULL; + return NULL; + } - newEffect->user = this; + newEffect->user = this; - // Clean up - CFRelease(pluginPathStringRef); - CFRelease(bundleUrl); + // Clean up + CFRelease(pluginPathStringRef); + CFRelease(bundleUrl); - return newEffect; + return newEffect; } void VSTPlugin::unloadLibrary() { - if (bundle) { - CFRelease(bundle); - bundle = NULL; - } + if (bundle) { + CFRelease(bundle); + bundle = NULL; + } } bool VSTPlugin::vstLoaded() { - return (bundle != NULL); + return (bundle != NULL); } diff --git a/plugins/text-freetype2/find-font-cocoa.m b/plugins/text-freetype2/find-font-cocoa.m index 22b379266..bf4ed2c3c 100644 --- a/plugins/text-freetype2/find-font-cocoa.m +++ b/plugins/text-freetype2/find-font-cocoa.m @@ -9,117 +9,100 @@ extern void save_font_list(void); static inline void add_path_font(const char *path) { - FT_Face face; - FT_Long idx = 0; - FT_Long max_faces = 1; + FT_Face face; + FT_Long idx = 0; + FT_Long max_faces = 1; - while (idx < max_faces) { - if (FT_New_Face(ft2_lib, path, idx, &face) != 0) - break; + while (idx < max_faces) { + if (FT_New_Face(ft2_lib, path, idx, &face) != 0) + break; - build_font_path_info(face, idx++, path); - max_faces = face->num_faces; - FT_Done_Face(face); - } + build_font_path_info(face, idx++, path); + max_faces = face->num_faces; + FT_Done_Face(face); + } } static void add_path_fonts(NSFileManager *file_manager, NSString *path) { - NSArray *files = NULL; + NSArray *files = NULL; - files = [file_manager contentsOfDirectoryAtPath:path error:nil]; + files = [file_manager contentsOfDirectoryAtPath:path error:nil]; - for (NSString *file in files) { - NSString *full_path = - [path stringByAppendingPathComponent:file]; + for (NSString *file in files) { + NSString *full_path = [path stringByAppendingPathComponent:file]; - BOOL is_dir = FALSE; - bool folder_exists = [file_manager fileExistsAtPath:full_path - isDirectory:&is_dir]; + BOOL is_dir = FALSE; + bool folder_exists = [file_manager fileExistsAtPath:full_path isDirectory:&is_dir]; - if (folder_exists && is_dir) { - add_path_fonts(file_manager, full_path); - } else { - add_path_font(full_path.fileSystemRepresentation); - } - } + if (folder_exists && is_dir) { + add_path_fonts(file_manager, full_path); + } else { + add_path_font(full_path.fileSystemRepresentation); + } + } } void load_os_font_list(void) { - @autoreleasepool { - BOOL is_dir; - NSArray *paths = NSSearchPathForDirectoriesInDomains( - NSLibraryDirectory, NSAllDomainsMask, true); + @autoreleasepool { + BOOL is_dir; + NSArray *paths = NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSAllDomainsMask, true); - for (NSString *path in paths) { - NSFileManager *file_manager = - [NSFileManager defaultManager]; - NSString *font_path = - [path stringByAppendingPathComponent:@"Fonts"]; + for (NSString *path in paths) { + NSFileManager *file_manager = [NSFileManager defaultManager]; + NSString *font_path = [path stringByAppendingPathComponent:@"Fonts"]; - bool folder_exists = [file_manager - fileExistsAtPath:font_path - isDirectory:&is_dir]; + bool folder_exists = [file_manager fileExistsAtPath:font_path isDirectory:&is_dir]; - if (folder_exists && is_dir) - add_path_fonts(file_manager, font_path); - } + if (folder_exists && is_dir) + add_path_fonts(file_manager, font_path); + } - save_font_list(); - } + save_font_list(); + } } static uint32_t add_font_checksum(uint32_t checksum, const char *path) { - if (path && *path) - checksum = calc_crc32(checksum, path, strlen(path)); - return checksum; + if (path && *path) + checksum = calc_crc32(checksum, path, strlen(path)); + return checksum; } -static uint32_t add_font_checksum_path(uint32_t checksum, - NSFileManager *file_manager, - NSString *path) +static uint32_t add_font_checksum_path(uint32_t checksum, NSFileManager *file_manager, NSString *path) { - NSArray *files = NULL; + NSArray *files = NULL; - files = [file_manager contentsOfDirectoryAtPath:path error:nil]; + files = [file_manager contentsOfDirectoryAtPath:path error:nil]; - for (NSString *file in files) { - NSString *full_path = - [path stringByAppendingPathComponent:file]; + for (NSString *file in files) { + NSString *full_path = [path stringByAppendingPathComponent:file]; - checksum = add_font_checksum( - checksum, full_path.fileSystemRepresentation); - } + checksum = add_font_checksum(checksum, full_path.fileSystemRepresentation); + } - return checksum; + return checksum; } uint32_t get_font_checksum(void) { - uint32_t checksum = 0; + uint32_t checksum = 0; - @autoreleasepool { - BOOL is_dir; - NSArray *paths = NSSearchPathForDirectoriesInDomains( - NSLibraryDirectory, NSAllDomainsMask, true); + @autoreleasepool { + BOOL is_dir; + NSArray *paths = NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSAllDomainsMask, true); - for (NSString *path in paths) { - NSFileManager *file_manager = - [NSFileManager defaultManager]; - NSString *font_path = - [path stringByAppendingPathComponent:@"Fonts"]; + for (NSString *path in paths) { + NSFileManager *file_manager = [NSFileManager defaultManager]; + NSString *font_path = [path stringByAppendingPathComponent:@"Fonts"]; - bool folder_exists = [file_manager - fileExistsAtPath:font_path - isDirectory:&is_dir]; + bool folder_exists = [file_manager fileExistsAtPath:font_path isDirectory:&is_dir]; - if (folder_exists && is_dir) - checksum = add_font_checksum_path( - checksum, file_manager, font_path); - } - } + if (folder_exists && is_dir) + checksum = add_font_checksum_path(checksum, file_manager, font_path); + } + } - return checksum; + return checksum; } diff --git a/test/osx/test.mm b/test/osx/test.mm index 9b1ff45b3..f65f99e37 100644 --- a/test/osx/test.mm +++ b/test/osx/test.mm @@ -16,23 +16,23 @@ static const int cy = 600; /* --------------------------------------------------- */ -template -struct OBSUniqueHandle : std::unique_ptr> { - using base = std::unique_ptr>; - explicit OBSUniqueHandle(T *obj = nullptr) : base(obj, D) {} - operator T *() { return base::get(); } +template struct OBSUniqueHandle : std::unique_ptr> { + using base = std::unique_ptr>; + explicit OBSUniqueHandle(T *obj = nullptr) : base(obj, D) + {} + operator T *() + { + return base::get(); + } }; #define DECLARE_DELETER(x) decltype(x), x -using SourceContext = - OBSUniqueHandle; +using SourceContext = OBSUniqueHandle; -using SceneContext = - OBSUniqueHandle; +using SceneContext = OBSUniqueHandle; -using DisplayContext = - OBSUniqueHandle; +using DisplayContext = OBSUniqueHandle; #undef DECLARE_DELETER @@ -40,69 +40,68 @@ using DisplayContext = static void CreateOBS() { - if (!obs_startup("en", nullptr, nullptr)) - throw "Couldn't create OBS"; + if (!obs_startup("en", nullptr, nullptr)) + throw "Couldn't create OBS"; - struct obs_video_info ovi; - ovi.adapter = 0; - ovi.fps_num = 30000; - ovi.fps_den = 1001; - ovi.graphics_module = DL_OPENGL; - ovi.output_format = VIDEO_FORMAT_RGBA; - ovi.base_width = cx; - ovi.base_height = cy; - ovi.output_width = cx; - ovi.output_height = cy; + struct obs_video_info ovi; + ovi.adapter = 0; + ovi.fps_num = 30000; + ovi.fps_den = 1001; + ovi.graphics_module = DL_OPENGL; + ovi.output_format = VIDEO_FORMAT_RGBA; + ovi.base_width = cx; + ovi.base_height = cy; + ovi.output_width = cx; + ovi.output_height = cy; - if (obs_reset_video(&ovi) != 0) - throw "Couldn't initialize video"; + if (obs_reset_video(&ovi) != 0) + throw "Couldn't initialize video"; } static DisplayContext CreateDisplay(NSView *view) { - gs_init_data info = {}; - info.cx = cx; - info.cy = cy; - info.format = GS_RGBA; - info.zsformat = GS_ZS_NONE; - info.window.view = view; + gs_init_data info = {}; + info.cx = cx; + info.cy = cy; + info.format = GS_RGBA; + info.zsformat = GS_ZS_NONE; + info.window.view = view; - return DisplayContext{obs_display_create(&info, 0)}; + return DisplayContext {obs_display_create(&info, 0)}; } static SceneContext SetupScene() { - /* ------------------------------------------------------ */ - /* load modules */ - obs_load_all_modules(); + /* ------------------------------------------------------ */ + /* load modules */ + obs_load_all_modules(); - /* ------------------------------------------------------ */ - /* create source */ - SourceContext source{ - obs_source_create("random", "a test source", nullptr, nullptr)}; - if (!source) - throw "Couldn't create random test source"; + /* ------------------------------------------------------ */ + /* create source */ + SourceContext source {obs_source_create("random", "a test source", nullptr, nullptr)}; + if (!source) + throw "Couldn't create random test source"; - /* ------------------------------------------------------ */ - /* create scene and add source to scene */ - SceneContext scene{obs_scene_create("test scene")}; - if (!scene) - throw "Couldn't create scene"; + /* ------------------------------------------------------ */ + /* create scene and add source to scene */ + SceneContext scene {obs_scene_create("test scene")}; + if (!scene) + throw "Couldn't create scene"; - obs_scene_add(scene, source); + obs_scene_add(scene, source); - /* ------------------------------------------------------ */ - /* set the scene as the primary draw source and go */ - obs_set_output_source(0, obs_scene_get_source(scene)); + /* ------------------------------------------------------ */ + /* set the scene as the primary draw source and go */ + obs_set_output_source(0, obs_scene_get_source(scene)); - return scene; + return scene; } @interface OBSTest : NSObject { - NSWindow *win; - NSView *view; - DisplayContext display; - SceneContext scene; + NSWindow *win; + NSView *view; + DisplayContext display; + SceneContext scene; } - (void)applicationDidFinishLaunching:(NSNotification *)notification; - (BOOL)applicationShouldTerminateAfterLastWindowClosed:(NSApplication *)app; @@ -112,68 +111,63 @@ static SceneContext SetupScene() @implementation OBSTest - (void)applicationDidFinishLaunching:(NSNotification *)notification { - UNUSED_PARAMETER(notification); + UNUSED_PARAMETER(notification); - try { - NSRect content_rect = NSMakeRect(0, 0, cx, cy); - win = [[NSWindow alloc] - initWithContentRect:content_rect - styleMask:NSTitledWindowMask | - NSClosableWindowMask - backing:NSBackingStoreBuffered - defer:NO]; - if (!win) - throw "Could not create window"; + try { + NSRect content_rect = NSMakeRect(0, 0, cx, cy); + win = [[NSWindow alloc] initWithContentRect:content_rect styleMask:NSTitledWindowMask | NSClosableWindowMask + backing:NSBackingStoreBuffered + defer:NO]; + if (!win) + throw "Could not create window"; - view = [[NSView alloc] initWithFrame:content_rect]; - if (!view) - throw "Could not create view"; + view = [[NSView alloc] initWithFrame:content_rect]; + if (!view) + throw "Could not create view"; - CreateOBS(); + CreateOBS(); - win.title = @"foo"; - win.delegate = self; - win.contentView = view; + win.title = @"foo"; + win.delegate = self; + win.contentView = view; - [win orderFrontRegardless]; - [win center]; - [win makeMainWindow]; + [win orderFrontRegardless]; + [win center]; + [win makeMainWindow]; - display = CreateDisplay(view); + display = CreateDisplay(view); - scene = SetupScene(); + scene = SetupScene(); - obs_display_add_draw_callback( - display.get(), - [](void *, uint32_t, uint32_t) { - obs_render_main_texture(); - }, - nullptr); + obs_display_add_draw_callback( + display.get(), [](void *, uint32_t, uint32_t) { + obs_render_main_texture(); + }, nullptr); - } catch (char const *error) { - NSLog(@"%s\n", error); + } catch (char const *error) { + NSLog(@"%s\n", error); - [NSApp terminate:nil]; - } + [NSApp terminate:nil]; + } } - (BOOL)applicationShouldTerminateAfterLastWindowClosed:(NSApplication *)app { - UNUSED_PARAMETER(app); + UNUSED_PARAMETER(app); - return YES; + return YES; } - (void)windowWillClose:(NSNotification *)notification { - UNUSED_PARAMETER(notification); + UNUSED_PARAMETER(notification); - obs_set_output_source(0, nullptr); - scene.reset(); - display.reset(); + obs_set_output_source(0, nullptr); + scene.reset(); + display.reset(); - obs_shutdown(); - NSLog(@"Number of memory leaks: %lu", bnum_allocs()); + obs_shutdown(); + NSLog(@"Number of memory leaks: %lu", bnum_allocs()); } @end @@ -181,13 +175,13 @@ static SceneContext SetupScene() int main() { - @autoreleasepool { - NSApplication *app = [NSApplication sharedApplication]; - OBSTest *test = [[OBSTest alloc] init]; - app.delegate = test; + @autoreleasepool { + NSApplication *app = [NSApplication sharedApplication]; + OBSTest *test = [[OBSTest alloc] init]; + app.delegate = test; - [app run]; - } + [app run]; + } - return 0; + return 0; }