Skip to content

Commit

Permalink
mac-capture: Don't crash when migrating unknown display IDs
Browse files Browse the repository at this point in the history
The current code assumes that a display UUID can be created with the
stored ID, but that's not always the case, e.g. when the user doesn't
have the display connected. As such, we need to null check this, and
fall back to the invalid ID (0) when the ID cannot be migrated.

The current code also only migrates on source creation, which yields
weird behaviour where if the user opens properties and then cancels it
would still show the first display, but only for the session. This is
why the code was factored out of the creation function and now is always
used when an ID needs to be acquired from OBS Data settings, including
when the source is updated.
  • Loading branch information
gxalpha authored and RytoEX committed Sep 28, 2023
1 parent 857c42a commit 23bfb62
Show file tree
Hide file tree
Showing 4 changed files with 43 additions and 54 deletions.
29 changes: 2 additions & 27 deletions plugins/mac-capture/mac-display-capture.m
Original file line number Diff line number Diff line change
Expand Up @@ -286,27 +286,7 @@ bool init_vertbuf(struct display_capture *dc)
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);
}

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();
}
dc->display = get_display_migrate_settings(settings);

pthread_mutex_init(&dc->mutex, NULL);

Expand Down Expand Up @@ -561,12 +541,7 @@ static void display_capture_update(void *data, obs_data_t *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);
CGDirectDisplayID display = get_display_migrate_settings(settings);

bool show_cursor = obs_data_get_bool(settings, "show_cursor");
if (dc->display == display && dc->hide_cursor != show_cursor)
Expand Down
30 changes: 3 additions & 27 deletions plugins/mac-capture/mac-sck-video-capture.m
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#include "mac-sck-common.h"
#include "window-utils.h"

static void destroy_screen_stream(struct screen_capture *sc)
{
Expand Down Expand Up @@ -271,27 +272,7 @@ static bool init_screen_stream(struct screen_capture *sc)
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);
}

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->display = get_display_migrate_settings(settings);

sc->application_id = [[NSString alloc] initWithUTF8String:obs_data_get_string(settings, "application")];
pthread_mutex_init(&sc->mutex, NULL);
Expand Down Expand Up @@ -420,12 +401,7 @@ static void sck_video_capture_update(void *data, obs_data_t *settings)

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);
CGDirectDisplayID display = get_display_migrate_settings(settings);

NSString *application_id = [[NSString alloc] initWithUTF8String:obs_data_get_string(settings, "application")];
bool show_cursor = obs_data_get_bool(settings, "show_cursor");
Expand Down
5 changes: 5 additions & 0 deletions plugins/mac-capture/window-utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,3 +31,8 @@ void window_defaults(obs_data_t *settings);
void add_window_properties(obs_properties_t *props);

void show_window_properties(obs_properties_t *props, bool show);

/** Get the display ID of a display and simultaneously migrate pre-30.0 display IDs to 30.0 UUIDs.
- Parameter settings: Pointer to `obs_data_t` object containing `display` int and/or `display_uuid` string
- Returns: `CGDirectDisplayID` of the display the user selected. May be 0 if the display cannot be found. */
CGDirectDisplayID get_display_migrate_settings(obs_data_t *settings);
33 changes: 33 additions & 0 deletions plugins/mac-capture/window-utils.m
Original file line number Diff line number Diff line change
Expand Up @@ -245,3 +245,36 @@ 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);
}

CGDirectDisplayID get_display_migrate_settings(obs_data_t *settings)
{
bool legacy_display_id = obs_data_has_user_value(settings, "display");
bool new_display_id = obs_data_has_user_value(settings, "display_uuid");
if (legacy_display_id && !new_display_id) {
CGDirectDisplayID display_id = (CGDirectDisplayID) obs_data_get_int(settings, "display");
CFUUIDRef display_uuid = CGDisplayCreateUUIDFromDisplayID(display_id);
if (display_uuid) {
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);
} else {
return 0;
}
} else if (legacy_display_id && new_display_id) {
obs_data_erase(settings, "display");
}

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);
CGDirectDisplayID display = CGDisplayGetDisplayIDFromUUID(uuid_ref);
CFRelease(uuid_string);
CFRelease(uuid_ref);
return display;
} else {
return 0;
}
}

0 comments on commit 23bfb62

Please sign in to comment.