/** * Create the capture */ static void *xshm_create(obs_data_t settings, obs_source_t source) { UNUSED_PARAMETER(source); struct xshm_data *data = bzalloc(sizeof(struct xshm_data)); data->dpy = XOpenDisplay(NULL); if (!data->dpy) { blog(LOG_ERROR, "xshm-input: Unable to open X display !"); goto fail; } if (!XShmQueryExtension(data->dpy)) { blog(LOG_ERROR, "xshm-input: XShm extension not found !"); goto fail; } data->use_xinerama = xinerama_is_active(data->dpy) ? true : false; obs_enter_graphics(); data->cursor = xcursor_init(data->dpy); obs_leave_graphics(); xshm_update(data, settings); return data; fail: xshm_destroy(data); return NULL; }
/** * The x server was changed */ static bool xshm_server_changed(obs_properties_t *props, obs_property_t *p, obs_data_t *settings) { UNUSED_PARAMETER(p); bool advanced = obs_data_get_bool(settings, "advanced"); int_fast32_t old_screen = obs_data_get_int(settings, "screen"); const char *server = obs_data_get_string(settings, "server"); obs_property_t *screens = obs_properties_get(props, "screen"); /* we want a real NULL here in case there is no string here */ server = (advanced && *server) ? server : NULL; obs_property_list_clear(screens); Display *dpy = XOpenDisplay(server); if (!dpy) { obs_property_set_enabled(screens, false); return true; } struct dstr screen_info; dstr_init(&screen_info); bool xinerama = xinerama_is_active(dpy); int_fast32_t count = (xinerama) ? xinerama_screen_count(dpy) : XScreenCount(dpy); for (int_fast32_t i = 0; i < count; ++i) { int_fast32_t x, y, w, h; x = y = w = h = 0; if (xinerama) xinerama_screen_geo(dpy, i, &x, &y, &w, &h); else x11_screen_geo(dpy, i, &w, &h); dstr_printf(&screen_info, "Screen %"PRIuFAST32" (%"PRIuFAST32 "x%"PRIuFAST32" @ %"PRIuFAST32 ",%"PRIuFAST32")", i, w, h, x, y); obs_property_list_add_int(screens, screen_info.array, i); } /* handle missing screen */ if (old_screen + 1 > count) { dstr_printf(&screen_info, "Screen %"PRIuFAST32" (not found)", old_screen); size_t index = obs_property_list_add_int(screens, screen_info.array, old_screen); obs_property_list_item_disable(screens, index, true); } dstr_free(&screen_info); XCloseDisplay(dpy); obs_property_set_enabled(screens, true); return true; }
/** * Get the properties for the capture */ static obs_properties_t xshm_properties(void) { obs_properties_t props = obs_properties_create(); int_fast32_t screen_max; Display *dpy = XOpenDisplay(NULL); screen_max = xinerama_is_active(dpy) ? xinerama_screen_count(dpy) : XScreenCount(dpy); screen_max = (screen_max) ? screen_max - 1 : 0; XCloseDisplay(dpy); obs_properties_add_int(props, "screen", obs_module_text("Screen"), 0, screen_max, 1); obs_properties_add_bool(props, "show_cursor", obs_module_text("CaptureCursor")); return props; }
/** * Start the capture */ static void xshm_capture_start(struct xshm_data *data) { const char *server = (data->advanced && *data->server) ? data->server : NULL; data->dpy = XOpenDisplay(server); if (!data->dpy) { blog(LOG_ERROR, "Unable to open X display !"); goto fail; } if (!XShmQueryExtension(data->dpy)) { blog(LOG_ERROR, "XShm extension not found !"); goto fail; } data->use_xinerama = xinerama_is_active(data->dpy) ? true : false; if (xshm_update_geometry(data) < 0) { blog(LOG_ERROR, "failed to update geometry !"); goto fail; } data->xshm = xshm_attach(data->dpy, data->screen, data->width, data->height); if (!data->xshm) { blog(LOG_ERROR, "failed to attach shm !"); goto fail; } obs_enter_graphics(); data->cursor = xcursor_init(data->dpy); xcursor_offset(data->cursor, data->x_org, data->y_org); xshm_resize_texture(data); obs_leave_graphics(); return; fail: xshm_capture_stop(data); }
/** * Start the capture */ static void xshm_capture_start(struct xshm_data *data) { const char *server = (data->advanced && *data->server) ? data->server : NULL; data->xcb = xcb_connect(server, NULL); if (!data->xcb || xcb_connection_has_error(data->xcb)) { blog(LOG_ERROR, "Unable to open X display !"); goto fail; } if (!xshm_check_extensions(data->xcb)) goto fail; data->use_xinerama = xinerama_is_active(data->xcb) ? true : false; if (xshm_update_geometry(data) < 0) { blog(LOG_ERROR, "failed to update geometry !"); goto fail; } data->xshm = xshm_xcb_attach(data->xcb, data->width, data->height); if (!data->xshm) { blog(LOG_ERROR, "failed to attach shm !"); goto fail; } data->cursor = xcb_xcursor_init(data->xcb); xcb_xcursor_offset(data->cursor, data->x_org, data->y_org); obs_enter_graphics(); xshm_resize_texture(data); obs_leave_graphics(); return; fail: xshm_capture_stop(data); }