mirror of
https://github.com/obsproject/obs-studio.git
synced 2024-07-19 09:39:15 +00:00
mac-capture: Switch to UUID-based display management
Using UUIDs to store display references in obs-studio's settings file allows us to "rediscover" devices even between restarts (as CGDirectDisplayID changes between those) and select the same device.
This commit is contained in:
parent
ad9fd6c6f0
commit
fb9b5c829a
|
@ -182,10 +182,24 @@ static inline void display_stream_update(struct display_capture *dc,
|
||||||
|
|
||||||
static bool init_display_stream(struct display_capture *dc)
|
static bool init_display_stream(struct display_capture *dc)
|
||||||
{
|
{
|
||||||
if (dc->display >= [NSScreen screens].count)
|
[[NSScreen screens]
|
||||||
return false;
|
enumerateObjectsUsingBlock:^(NSScreen *_Nonnull screen,
|
||||||
|
NSUInteger index __unused,
|
||||||
|
BOOL *_Nonnull stop __unused) {
|
||||||
|
NSNumber *screenNumber =
|
||||||
|
screen.deviceDescription[@"NSScreenNumber"];
|
||||||
|
CGDirectDisplayID display_id =
|
||||||
|
(CGDirectDisplayID)screenNumber.intValue;
|
||||||
|
|
||||||
dc->screen = [[NSScreen screens][dc->display] retain];
|
if (display_id == dc->display) {
|
||||||
|
dc->screen = [screen retain];
|
||||||
|
*stop = YES;
|
||||||
|
}
|
||||||
|
}];
|
||||||
|
|
||||||
|
if (!dc->screen) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
dc->frame = [dc->screen convertRectToBacking:dc->screen.frame];
|
dc->frame = [dc->screen convertRectToBacking:dc->screen.frame];
|
||||||
|
|
||||||
|
@ -283,7 +297,39 @@ static void *display_capture_create(obs_data_t *settings, obs_source_t *source)
|
||||||
init_window(&dc->window, settings);
|
init_window(&dc->window, settings);
|
||||||
load_crop(dc, settings);
|
load_crop(dc, settings);
|
||||||
|
|
||||||
dc->display = (unsigned int)obs_data_get_int(settings, "display");
|
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();
|
||||||
|
}
|
||||||
|
|
||||||
pthread_mutex_init(&dc->mutex, NULL);
|
pthread_mutex_init(&dc->mutex, NULL);
|
||||||
|
|
||||||
if (!init_display_stream(dc))
|
if (!init_display_stream(dc))
|
||||||
|
@ -482,7 +528,18 @@ static uint32_t display_capture_getheight(void *data)
|
||||||
|
|
||||||
static void display_capture_defaults(obs_data_t *settings)
|
static void display_capture_defaults(obs_data_t *settings)
|
||||||
{
|
{
|
||||||
obs_data_set_default_int(settings, "display", 0);
|
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_bool(settings, "show_cursor", true);
|
||||||
obs_data_set_default_int(settings, "crop_mode", CROP_NONE);
|
obs_data_set_default_int(settings, "crop_mode", CROP_NONE);
|
||||||
|
|
||||||
|
@ -536,7 +593,16 @@ static void display_capture_update(void *data, obs_data_t *settings)
|
||||||
if (requires_window(dc->crop))
|
if (requires_window(dc->crop))
|
||||||
update_window(&dc->window, settings);
|
update_window(&dc->window, settings);
|
||||||
|
|
||||||
unsigned display = (unsigned int)obs_data_get_int(settings, "display");
|
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");
|
bool show_cursor = obs_data_get_bool(settings, "show_cursor");
|
||||||
if (dc->display == display && dc->hide_cursor != show_cursor)
|
if (dc->display == display && dc->hide_cursor != show_cursor)
|
||||||
return;
|
return;
|
||||||
|
@ -596,13 +662,14 @@ static obs_properties_t *display_capture_properties(void *unused)
|
||||||
obs_properties_t *props = obs_properties_create();
|
obs_properties_t *props = obs_properties_create();
|
||||||
|
|
||||||
obs_property_t *list = obs_properties_add_list(
|
obs_property_t *list = obs_properties_add_list(
|
||||||
props, "display", obs_module_text("DisplayCapture.Display"),
|
props, "display_uuid",
|
||||||
OBS_COMBO_TYPE_LIST, OBS_COMBO_FORMAT_INT);
|
obs_module_text("DisplayCapture.Display"), OBS_COMBO_TYPE_LIST,
|
||||||
|
OBS_COMBO_FORMAT_STRING);
|
||||||
|
|
||||||
[[NSScreen screens] enumerateObjectsUsingBlock:^(
|
[[NSScreen screens] enumerateObjectsUsingBlock:^(
|
||||||
NSScreen *_Nonnull screen, NSUInteger index,
|
NSScreen *_Nonnull screen,
|
||||||
BOOL *_Nonnull stop
|
NSUInteger index __unused,
|
||||||
__attribute__((unused))) {
|
BOOL *_Nonnull stop __unused) {
|
||||||
char dimension_buffer[4][12];
|
char dimension_buffer[4][12];
|
||||||
char name_buffer[256];
|
char name_buffer[256];
|
||||||
snprintf(dimension_buffer[0], sizeof(dimension_buffer[0]), "%u",
|
snprintf(dimension_buffer[0], sizeof(dimension_buffer[0]), "%u",
|
||||||
|
@ -620,7 +687,21 @@ static obs_properties_t *display_capture_properties(void *unused)
|
||||||
dimension_buffer[0], dimension_buffer[1],
|
dimension_buffer[0], dimension_buffer[1],
|
||||||
dimension_buffer[2], dimension_buffer[3]);
|
dimension_buffer[2], dimension_buffer[3]);
|
||||||
|
|
||||||
obs_property_list_add_int(list, name_buffer, index);
|
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);
|
||||||
}];
|
}];
|
||||||
|
|
||||||
obs_properties_add_bool(props, "show_cursor",
|
obs_properties_add_bool(props, "show_cursor",
|
||||||
|
|
|
@ -633,7 +633,39 @@ static void *screen_capture_create(obs_data_t *settings, obs_source_t *source)
|
||||||
if (!sc->effect)
|
if (!sc->effect)
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
||||||
sc->display = (CGDirectDisplayID)obs_data_get_int(settings, "display");
|
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->application_id = [[NSString alloc]
|
sc->application_id = [[NSString alloc]
|
||||||
initWithUTF8String:obs_data_get_string(settings,
|
initWithUTF8String:obs_data_get_string(settings,
|
||||||
"application")];
|
"application")];
|
||||||
|
@ -740,7 +772,15 @@ static void screen_capture_defaults(obs_data_t *settings)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
obs_data_set_default_int(settings, "display", initial_display);
|
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_obj(settings, "application", NULL);
|
||||||
obs_data_set_default_int(settings, "type", ScreenCaptureDisplayStream);
|
obs_data_set_default_int(settings, "type", ScreenCaptureDisplayStream);
|
||||||
|
@ -764,8 +804,17 @@ static void screen_capture_update(void *data, obs_data_t *settings)
|
||||||
|
|
||||||
ScreenCaptureStreamType capture_type =
|
ScreenCaptureStreamType capture_type =
|
||||||
(ScreenCaptureStreamType)obs_data_get_int(settings, "type");
|
(ScreenCaptureStreamType)obs_data_get_int(settings, "type");
|
||||||
CGDirectDisplayID display =
|
|
||||||
(CGDirectDisplayID)obs_data_get_int(settings, "display");
|
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]
|
NSString *application_id = [[NSString alloc]
|
||||||
initWithUTF8String:obs_data_get_string(settings,
|
initWithUTF8String:obs_data_get_string(settings,
|
||||||
"application")];
|
"application")];
|
||||||
|
@ -827,7 +876,8 @@ static bool build_display_list(struct screen_capture *sc,
|
||||||
{
|
{
|
||||||
os_sem_wait(sc->shareable_content_available);
|
os_sem_wait(sc->shareable_content_available);
|
||||||
|
|
||||||
obs_property_t *display_list = obs_properties_get(props, "display");
|
obs_property_t *display_list =
|
||||||
|
obs_properties_get(props, "display_uuid");
|
||||||
obs_property_list_clear(display_list);
|
obs_property_list_clear(display_list);
|
||||||
|
|
||||||
[sc->shareable_content.displays enumerateObjectsUsingBlock:^(
|
[sc->shareable_content.displays enumerateObjectsUsingBlock:^(
|
||||||
|
@ -869,8 +919,16 @@ static bool build_display_list(struct screen_capture *sc,
|
||||||
dimension_buffer[1], dimension_buffer[2],
|
dimension_buffer[1], dimension_buffer[2],
|
||||||
dimension_buffer[3]);
|
dimension_buffer[3]);
|
||||||
|
|
||||||
obs_property_list_add_int(display_list, name_buffer,
|
CFUUIDRef display_uuid =
|
||||||
display.displayID);
|
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);
|
os_sem_post(sc->shareable_content_available);
|
||||||
|
@ -946,7 +1004,8 @@ static bool content_settings_changed(void *data, obs_properties_t *props,
|
||||||
|
|
||||||
unsigned int capture_type_id =
|
unsigned int capture_type_id =
|
||||||
(unsigned int)obs_data_get_int(settings, "type");
|
(unsigned int)obs_data_get_int(settings, "type");
|
||||||
obs_property_t *display_list = obs_properties_get(props, "display");
|
obs_property_t *display_list =
|
||||||
|
obs_properties_get(props, "display_uuid");
|
||||||
obs_property_t *window_list = obs_properties_get(props, "window");
|
obs_property_t *window_list = obs_properties_get(props, "window");
|
||||||
obs_property_t *app_list = obs_properties_get(props, "application");
|
obs_property_t *app_list = obs_properties_get(props, "application");
|
||||||
obs_property_t *empty = obs_properties_get(props, "show_empty_names");
|
obs_property_t *empty = obs_properties_get(props, "show_empty_names");
|
||||||
|
@ -1037,8 +1096,9 @@ static obs_properties_t *screen_capture_properties(void *data)
|
||||||
obs_module_text("ApplicationCapture"), 2);
|
obs_module_text("ApplicationCapture"), 2);
|
||||||
|
|
||||||
obs_property_t *display_list = obs_properties_add_list(
|
obs_property_t *display_list = obs_properties_add_list(
|
||||||
props, "display", obs_module_text("DisplayCapture.Display"),
|
props, "display_uuid",
|
||||||
OBS_COMBO_TYPE_LIST, OBS_COMBO_FORMAT_INT);
|
obs_module_text("DisplayCapture.Display"), OBS_COMBO_TYPE_LIST,
|
||||||
|
OBS_COMBO_FORMAT_STRING);
|
||||||
|
|
||||||
obs_property_t *app_list = obs_properties_add_list(
|
obs_property_t *app_list = obs_properties_add_list(
|
||||||
props, "application", obs_module_text("Application"),
|
props, "application", obs_module_text("Application"),
|
||||||
|
|
Loading…
Reference in a new issue