From db2363697abc2ddc76ed81ba23a4423460481c29 Mon Sep 17 00:00:00 2001 From: Vladimir Sumarov Date: Mon, 28 Oct 2024 15:44:58 -0700 Subject: [PATCH] more logging for capture error --- plugins/mac-capture/mac-screen-capture.m | 238 ++++++++++++----------- 1 file changed, 125 insertions(+), 113 deletions(-) diff --git a/plugins/mac-capture/mac-screen-capture.m b/plugins/mac-capture/mac-screen-capture.m index 0c81add31d5fb9..4c6323e59f156a 100644 --- a/plugins/mac-capture/mac-screen-capture.m +++ b/plugins/mac-capture/mac-screen-capture.m @@ -359,16 +359,17 @@ static void requestScreenRecordingPermission() static bool init_screen_stream(struct screen_capture *sc) { MACCAP_LOG("Entering init_screen_stream"); - + if (!hasScreenRecordingPermission()) { MACCAP_ERR("Screen recording permission not granted"); dispatch_async(dispatch_get_main_queue(), ^{ NSAlert *alert = [[NSAlert alloc] init]; - [alert setMessageText:@"Screen Recording Permission Required"]; + [alert setMessageText: + @"Screen Recording Permission Required"]; [alert setInformativeText: - @"Please grant Screen Recording permission in System " - @"Preferences > Security & Privacy > Privacy > Screen " - @"Recording, then restart the application."]; + @"Please grant Screen Recording permission in System " + @"Preferences > Security & Privacy > Privacy > Screen " + @"Recording, then restart the application."]; [alert addButtonWithTitle:@"OK"]; [alert runModal]; [alert release]; @@ -389,23 +390,23 @@ static bool init_screen_stream(struct screen_capture *sc) MACCAP_LOG("Waiting for shareable content"); os_sem_wait(sc->shareable_content_available); - SCDisplay *(^get_target_display)() = ^SCDisplay *() { + SCDisplay * (^get_target_display)() = ^SCDisplay *() + { __block SCDisplay *target_display = nil; [sc->shareable_content.displays indexOfObjectPassingTest:^BOOL( - SCDisplay *_Nonnull display, - NSUInteger idx, + SCDisplay *_Nonnull display, NSUInteger idx, BOOL *_Nonnull stop) { if (display.displayID == sc->display) { - target_display = - sc->shareable_content - .displays[idx]; + target_display = sc->shareable_content + .displays[idx]; *stop = TRUE; } return *stop; }]; if (!target_display) { - MACCAP_LOG("Target display not found. Display ID: %d", sc->display); + MACCAP_LOG("Target display not found. Display ID: %d", + sc->display); } return target_display; }; @@ -420,12 +421,13 @@ static bool init_screen_stream(struct screen_capture *sc) os_sem_post(sc->shareable_content_available); return false; } - - MACCAP_LOG("Creating content filter for display ID: %d", target_display.displayID); + + MACCAP_LOG("Creating content filter for display ID: %d", + target_display.displayID); NSArray *empty = [[NSArray alloc] init]; - content_filter = - [[SCContentFilter alloc] initWithDisplay:target_display - excludingWindows:empty]; + content_filter = [[SCContentFilter alloc] + initWithDisplay:target_display + excludingWindows:empty]; [empty release]; set_display_mode(sc, target_display); @@ -434,35 +436,39 @@ static bool init_screen_stream(struct screen_capture *sc) case ScreenCaptureWindowStream: { MACCAP_LOG("Initializing window stream capture"); __block SCWindow *target_window = nil; - [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; - }]; + [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; + }]; - MACCAP_LOG("Window count: %lu", (unsigned long)[sc->shareable_content.windows count]); - if (!target_window && [sc->shareable_content.windows count] > 0) { + MACCAP_LOG( + "Window count: %lu", + (unsigned long)[sc->shareable_content.windows count]); + if (!target_window && + [sc->shareable_content.windows count] > 0) { target_window = [sc->shareable_content.windows objectAtIndex:0]; sc->window = target_window.windowID; - MACCAP_LOG("Using fallback window. Window ID: %d", sc->window); + MACCAP_LOG("Using fallback window. Window ID: %d", + sc->window); } if (!target_window) { - MACCAP_ERR("Target window not found. Window ID: %d", sc->window); + MACCAP_ERR("Target window not found. Window ID: %d", + sc->window); os_sem_post(sc->shareable_content_available); return false; } - MACCAP_LOG("Creating content filter for window ID: %d", target_window.windowID); + MACCAP_LOG("Creating content filter for window ID: %d", + target_window.windowID); content_filter = [[SCContentFilter alloc] initWithDesktopIndependentWindow:target_window]; @@ -470,30 +476,31 @@ static bool init_screen_stream(struct screen_capture *sc) setWidth:(size_t)target_window.frame.size.width]; [sc->stream_properties setHeight:(size_t)target_window.frame.size.height]; - MACCAP_LOG("Window dimensions set to: %zux%zu", - (size_t)target_window.frame.size.width, - (size_t)target_window.frame.size.height); + MACCAP_LOG("Window dimensions set to: %zux%zu", + (size_t)target_window.frame.size.width, + (size_t)target_window.frame.size.height); } break; case ScreenCaptureApplicationStream: { MACCAP_LOG("Initializing application stream capture"); SCDisplay *target_display = get_target_display(); if (!target_display) { - MACCAP_ERR("Target display not found for application capture"); + MACCAP_ERR( + "Target display not found for application capture"); os_sem_post(sc->shareable_content_available); return false; } - MACCAP_LOG("Searching for application with bundle ID: %s", - [sc->application_id UTF8String]); + MACCAP_LOG("Searching for application with bundle ID: %s", + [sc->application_id UTF8String]); __block SCRunningApplication *target_application = nil; [sc->shareable_content.applications indexOfObjectPassingTest:^BOOL( SCRunningApplication *_Nonnull application, - NSUInteger idx, - BOOL *_Nonnull stop) { + NSUInteger idx, BOOL *_Nonnull stop) { if ([application.bundleIdentifier - isEqualToString:sc->application_id]) { + isEqualToString:sc-> + application_id]) { target_application = sc->shareable_content .applications[idx]; @@ -503,21 +510,22 @@ static bool init_screen_stream(struct screen_capture *sc) }]; if (!target_application) { - MACCAP_ERR("Target application not found with bundle ID: %s", + MACCAP_ERR( + "Target application not found with bundle ID: %s", [sc->application_id UTF8String]); os_sem_post(sc->shareable_content_available); return false; } MACCAP_LOG("Creating content filter for application"); - NSArray *target_application_array = - [[NSArray alloc] initWithObjects:target_application, nil]; + NSArray *target_application_array = [[NSArray alloc] + initWithObjects:target_application, nil]; NSArray *empty_array = [[NSArray alloc] init]; content_filter = [[SCContentFilter alloc] - initWithDisplay:target_display + initWithDisplay:target_display includingApplications:target_application_array - exceptingWindows:empty_array]; + exceptingWindows:empty_array]; [target_application_array release]; [empty_array release]; @@ -551,23 +559,22 @@ static bool init_screen_stream(struct screen_capture *sc) [content_filter release]; os_event_init(&sc->disp_finished, OS_EVENT_TYPE_MANUAL); os_event_init(&sc->stream_start_completed, - OS_EVENT_TYPE_MANUAL); + OS_EVENT_TYPE_MANUAL); return true; } MACCAP_LOG("Initializing SCStream"); sc->disp = [[SCStream alloc] initWithFilter:content_filter - configuration:sc->stream_properties - delegate:nil]; + configuration:sc->stream_properties + delegate:nil]; [content_filter release]; NSError *addStreamOutputError = nil; MACCAP_LOG("Adding stream output"); - BOOL did_add_output = [sc->disp - addStreamOutput:sc->capture_delegate - type:SCStreamOutputTypeScreen - sampleHandlerQueue:nil - error:&addStreamOutputError]; + BOOL did_add_output = [sc->disp addStreamOutput:sc->capture_delegate + type:SCStreamOutputTypeScreen + sampleHandlerQueue:nil + error:&addStreamOutputError]; if (!did_add_output) { NSString *errorDescription = @@ -575,8 +582,8 @@ static bool init_screen_stream(struct screen_capture *sc) ? [addStreamOutputError localizedDescription] : @"Unknown error"; MACCAP_ERR("Failed to add stream output with error: %s", - [errorDescription - cStringUsingEncoding:NSUTF8StringEncoding]); + [errorDescription + cStringUsingEncoding:NSUTF8StringEncoding]); [addStreamOutputError release]; return false; } @@ -585,21 +592,22 @@ static bool init_screen_stream(struct screen_capture *sc) if (@available(macOS 13.0, *)) { MACCAP_LOG("Adding audio stream output"); did_add_output = [sc->disp - addStreamOutput:sc->capture_delegate - type:SCStreamOutputTypeAudio + addStreamOutput:sc->capture_delegate + type:SCStreamOutputTypeAudio sampleHandlerQueue:nil - error:&addStreamOutputError]; + error:&addStreamOutputError]; if (!did_add_output) { NSString *errorDescription = addStreamOutputError ? [addStreamOutputError - localizedDescription] + localizedDescription] : @"Unknown error"; MACCAP_ERR( "Failed to add audio stream output with error: %s", [errorDescription - cStringUsingEncoding:NSUTF8StringEncoding]); + cStringUsingEncoding: + NSUTF8StringEncoding]); [addStreamOutputError release]; return false; } @@ -611,60 +619,64 @@ static bool init_screen_stream(struct screen_capture *sc) MACCAP_LOG("Starting capture"); __block BOOL did_stream_start = false; - [sc->disp - startCaptureWithCompletionHandler:^(NSError *_Nullable error) { - did_stream_start = (error == nil); - if (!did_stream_start) { - NSString *errorDescription = - error ? [error localizedDescription] - : @"Unknown error"; - MACCAP_ERR("Failed to start capture with error: %s", - [errorDescription - cStringUsingEncoding: - NSUTF8StringEncoding]); - - if ([error.domain - isEqualToString: - @"com.apple.ScreenCaptureKit.ErrorDomain"]) { - MACCAP_LOG("ScreenCaptureKit error domain detected, code: %ld", (long)error.code); - NSInteger permissionDeniedErrorCode = -3801; - if (error.code == permissionDeniedErrorCode) { - MACCAP_ERR("Permission denied error detected"); - dispatch_async( - dispatch_get_main_queue(), - ^{ - NSAlert *alert = [[NSAlert alloc] init]; - [alert setMessageText:@"Screen Recording Permission Denied"]; - [alert setInformativeText: - @"Please grant Screen Recording permission in " - @"System Preferences > Security & Privacy > " - @"Privacy > Screen Recording, then restart " - @"the application."]; - [alert addButtonWithTitle:@"OK"]; - [alert runModal]; - [alert release]; - - NSURL *url = [NSURL - fileURLWithPath:@"/System/Library/PreferencePanes/" - @"Security.prefPane"]; - [[NSWorkspace - sharedWorkspace] - openURL:url]; - }); - } + [sc->disp startCaptureWithCompletionHandler:^( + NSError *_Nullable error) { + did_stream_start = (error == nil); + if (!did_stream_start) { + NSString *errorDescription = + error ? [error localizedDescription] + : @"Unknown error"; + MACCAP_ERR("Failed to start capture with error: %s", + [errorDescription + cStringUsingEncoding: + NSUTF8StringEncoding]); + + if ([error.domain + isEqualToString: + @"com.apple.ScreenCaptureKit.ErrorDomain"]) { + MACCAP_LOG( + "ScreenCaptureKit error domain detected, code: %ld", + (long)error.code); + NSInteger permissionDeniedErrorCode = -3801; + if (error.code == permissionDeniedErrorCode) { + MACCAP_ERR( + "Permission denied error detected"); + dispatch_async(dispatch_get_main_queue(), ^{ + NSAlert *alert = + [[NSAlert alloc] init]; + [alert setMessageText: + @"Screen Recording Permission Denied"]; + [alert setInformativeText: + @"Please grant Screen Recording permission in " + @"System Preferences > Security & Privacy > " + @"Privacy > Screen Recording, then restart " + @"the application."]; + [alert addButtonWithTitle:@"OK"]; + [alert runModal]; + [alert release]; + + NSURL *url = [NSURL + fileURLWithPath: + @"/System/Library/PreferencePanes/" + @"Security.prefPane"]; + [[NSWorkspace sharedWorkspace] + openURL:url]; + }); } - - [sc->disp release]; - sc->disp = NULL; - } else { - MACCAP_LOG("Capture started successfully"); } - os_event_signal(sc->stream_start_completed); - }]; + + [sc->disp release]; + sc->disp = NULL; + } else { + MACCAP_LOG("Capture started successfully"); + } + os_event_signal(sc->stream_start_completed); + }]; MACCAP_LOG("Waiting for stream start completion"); os_event_wait(sc->stream_start_completed); - MACCAP_LOG("Stream initialization %s", did_stream_start ? "succeeded" : "failed"); + MACCAP_LOG("Stream initialization %s", + did_stream_start ? "succeeded" : "failed"); return did_stream_start; }