Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Linux/BSD] Add dynamically loaded library version checks. #74978

Merged
merged 1 commit into from
Apr 18, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions drivers/alsa/audio_driver_alsa.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,18 @@ Error AudioDriverALSA::init() {
return ERR_CANT_OPEN;
}
#endif
bool ver_ok = false;
String version = String::utf8(snd_asoundlib_version());
Vector<String> ver_parts = version.split(".");
if (ver_parts.size() >= 2) {
ver_ok = ((ver_parts[0].to_int() == 1 && ver_parts[1].to_int() >= 1)) || (ver_parts[0].to_int() > 1); // 1.1.0
}
print_verbose(vformat("ALSA %s detected.", version));
if (!ver_ok) {
print_verbose("Unsupported ALSA library version!");
return ERR_CANT_OPEN;
}

active.clear();
exit_thread.clear();

Expand Down
12 changes: 12 additions & 0 deletions drivers/pulseaudio/audio_driver_pulseaudio.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -290,6 +290,18 @@ Error AudioDriverPulseAudio::init() {
return ERR_CANT_OPEN;
}
#endif
bool ver_ok = false;
String version = String::utf8(pa_get_library_version());
Vector<String> ver_parts = version.split(".");
if (ver_parts.size() >= 2) {
ver_ok = (ver_parts[0].to_int() >= 8); // 8.0.0
}
print_verbose(vformat("PulseAudio %s detected.", version));
if (!ver_ok) {
print_verbose("Unsupported PulseAudio library version!");
return ERR_CANT_OPEN;
}

active.clear();
exit_thread.clear();

Expand Down
11 changes: 11 additions & 0 deletions platform/linuxbsd/freedesktop_portal_desktop.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,17 @@ FreeDesktopPortalDesktop::FreeDesktopPortalDesktop() {
#else
unsupported = false;
#endif
bool ver_ok = false;
int version_major = 0;
int version_minor = 0;
int version_rev = 0;
dbus_get_version(&version_major, &version_minor, &version_rev);
ver_ok = (version_major == 1 && version_minor >= 10) || (version_major > 1); // 1.10.0
print_verbose(vformat("PortalDesktop: DBus %d.%d.%d detected.", version_major, version_minor, version_rev));
if (!ver_ok) {
print_verbose("PortalDesktop: Unsupported DBus library version!");
unsupported = true;
}
}

#endif // DBUS_ENABLED
11 changes: 11 additions & 0 deletions platform/linuxbsd/freedesktop_screensaver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,17 @@ FreeDesktopScreenSaver::FreeDesktopScreenSaver() {
#else
unsupported = false;
#endif
bool ver_ok = false;
int version_major = 0;
int version_minor = 0;
int version_rev = 0;
dbus_get_version(&version_major, &version_minor, &version_rev);
ver_ok = (version_major == 1 && version_minor >= 10) || (version_major > 1); // 1.10.0
print_verbose(vformat("ScreenSaver: DBus %d.%d.%d detected.", version_major, version_minor, version_rev));
if (!ver_ok) {
print_verbose("ScreenSaver:: Unsupported DBus library version!");
unsupported = true;
}
}

#endif // DBUS_ENABLED
8 changes: 7 additions & 1 deletion platform/linuxbsd/joypad_linux.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,13 @@ JoypadLinux::JoypadLinux(Input *in) {
#endif
use_udev = initialize_libudev(dylibloader_verbose) == 0;
if (use_udev) {
print_verbose("JoypadLinux: udev enabled and loaded successfully.");
if (!udev_new || !udev_unref || !udev_enumerate_new || !udev_enumerate_add_match_subsystem || !udev_enumerate_scan_devices || !udev_enumerate_get_list_entry || !udev_list_entry_get_next || !udev_list_entry_get_name || !udev_device_new_from_syspath || !udev_device_get_devnode || !udev_device_get_action || !udev_device_unref || !udev_enumerate_unref || !udev_monitor_new_from_netlink || !udev_monitor_filter_add_match_subsystem_devtype || !udev_monitor_enable_receiving || !udev_monitor_get_fd || !udev_monitor_receive_device || !udev_monitor_unref) {
// There's no API to check version, check if functions are available instead.
use_udev = false;
print_verbose("JoypadLinux: Unsupported udev library version!");
} else {
print_verbose("JoypadLinux: udev enabled and loaded successfully.");
}
} else {
print_verbose("JoypadLinux: udev enabled, but couldn't be loaded. Falling back to /dev/input to detect joypads.");
}
Expand Down
10 changes: 10 additions & 0 deletions platform/linuxbsd/os_linuxbsd.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1102,6 +1102,16 @@ OS_LinuxBSD::OS_LinuxBSD() {
#else
font_config_initialized = true;
#endif
if (font_config_initialized) {
bool ver_ok = false;
int version = FcGetVersion();
ver_ok = ((version / 100 / 100) == 2 && (version / 100 % 100) >= 11) || ((version / 100 / 100) > 2); // 2.11.0
print_verbose(vformat("FontConfig %d.%d.%d detected.", version / 100 / 100, version / 100 % 100, version % 100));
if (!ver_ok) {
font_config_initialized = false;
}
}

if (font_config_initialized) {
config = FcInitLoadConfigAndFonts();
if (!config) {
Expand Down
5 changes: 5 additions & 0 deletions platform/linuxbsd/tts_linux.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,11 @@ void TTS_Linux::speech_init_thread_func(void *p_userdata) {
if (initialize_speechd(dylibloader_verbose) != 0) {
print_verbose("Text-to-Speech: Cannot load Speech Dispatcher library!");
} else {
if (!spd_open || !spd_set_notification_on || !spd_list_synthesis_voices || !free_spd_voices || !spd_set_synthesis_voice || !spd_set_volume || !spd_set_voice_pitch || !spd_set_voice_rate || !spd_set_data_mode || !spd_say || !spd_pause || !spd_resume || !spd_cancel) {
// There's no API to check version, check if functions are available instead.
print_verbose("Text-to-Speech: Unsupported Speech Dispatcher library version!");
return;
}
#else
{
#endif
Expand Down
99 changes: 90 additions & 9 deletions platform/linuxbsd/x11/display_server_x11.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1354,7 +1354,7 @@ void DisplayServerX11::delete_sub_window(WindowID p_id) {
}
XDestroyWindow(x11_display, wd.x11_xim_window);
#ifdef XKB_ENABLED
if (xkb_loaded) {
if (xkb_loaded_v05p) {
if (wd.xkb_state) {
xkb_compose_state_unref(wd.xkb_state);
wd.xkb_state = nullptr;
Expand Down Expand Up @@ -2987,7 +2987,7 @@ void DisplayServerX11::_handle_key_event(WindowID p_window, XKeyEvent *p_event,

String keysym;
#ifdef XKB_ENABLED
if (xkb_loaded) {
if (xkb_loaded_v08p) {
KeySym keysym_unicode_nm = 0; // keysym used to find unicode
XLookupString(&xkeyevent_no_mod, nullptr, 0, &keysym_unicode_nm, nullptr);
keysym = String::chr(xkb_keysym_to_utf32(xkb_keysym_to_upper(keysym_unicode_nm)));
Expand Down Expand Up @@ -3082,7 +3082,7 @@ void DisplayServerX11::_handle_key_event(WindowID p_window, XKeyEvent *p_event,
} while (status == XBufferOverflow);
#endif
#ifdef XKB_ENABLED
} else if (xkeyevent->type == KeyPress && wd.xkb_state && xkb_loaded) {
} else if (xkeyevent->type == KeyPress && wd.xkb_state && xkb_loaded_v05p) {
xkb_compose_feed_result res = xkb_compose_state_feed(wd.xkb_state, keysym_unicode);
if (res == XKB_COMPOSE_FEED_ACCEPTED) {
if (xkb_compose_state_get_status(wd.xkb_state) == XKB_COMPOSE_COMPOSED) {
Expand Down Expand Up @@ -4999,7 +4999,7 @@ DisplayServerX11::WindowID DisplayServerX11::_create_window(WindowMode p_mode, V

wd.x11_xim_window = XCreateWindow(x11_display, wd.x11_window, 0, 0, 1, 1, 0, CopyFromParent, InputOnly, CopyFromParent, CWEventMask, &window_attributes_ime);
#ifdef XKB_ENABLED
if (dead_tbl && xkb_loaded) {
if (dead_tbl && xkb_loaded_v05p) {
wd.xkb_state = xkb_compose_state_new(dead_tbl, XKB_COMPOSE_STATE_NO_FLAGS);
}
#endif
Expand Down Expand Up @@ -5283,9 +5283,16 @@ DisplayServerX11::DisplayServerX11(const String &p_rendering_driver, WindowMode
ERR_FAIL_MSG("Can't load XCursor dynamically.");
}
#ifdef XKB_ENABLED
xkb_loaded = (initialize_xkbcommon(dylibloader_verbose) == 0);
if (!xkb_context_new || !xkb_compose_table_new_from_locale || !xkb_compose_table_unref || !xkb_context_unref || !xkb_compose_state_feed || !xkb_compose_state_unref || !xkb_compose_state_new || !xkb_compose_state_get_status || !xkb_compose_state_get_utf8 || !xkb_keysym_to_utf32 || !xkb_keysym_to_upper) {
xkb_loaded = false;
bool xkb_loaded = (initialize_xkbcommon(dylibloader_verbose) == 0);
xkb_loaded_v05p = xkb_loaded;
if (!xkb_context_new || !xkb_compose_table_new_from_locale || !xkb_compose_table_unref || !xkb_context_unref || !xkb_compose_state_feed || !xkb_compose_state_unref || !xkb_compose_state_new || !xkb_compose_state_get_status || !xkb_compose_state_get_utf8) {
xkb_loaded_v05p = false;
print_verbose("Detected XKBcommon library version older than 0.5, dead key composition and Unicode key labels disabled.");
}
xkb_loaded_v08p = xkb_loaded;
if (!xkb_keysym_to_utf32 || !xkb_keysym_to_upper) {
xkb_loaded_v08p = false;
print_verbose("Detected XKBcommon library version older than 0.8, Unicode key labels disabled.");
}
#endif
if (initialize_xext(dylibloader_verbose) != 0) {
Expand Down Expand Up @@ -5341,6 +5348,15 @@ DisplayServerX11::DisplayServerX11(const String &p_rendering_driver, WindowMode

r_error = OK;

{
if (!XcursorImageCreate || !XcursorImageLoadCursor || !XcursorImageDestroy || !XcursorGetDefaultSize || !XcursorGetTheme || !XcursorLibraryLoadImage) {
// There's no API to check version, check if functions are available instead.
ERR_PRINT("Unsupported Xcursor library version.");
r_error = ERR_UNAVAILABLE;
return;
}
}

for (int i = 0; i < CURSOR_MAX; i++) {
cursors[i] = None;
img[i] = nullptr;
Expand All @@ -5357,6 +5373,71 @@ DisplayServerX11::DisplayServerX11(const String &p_rendering_driver, WindowMode
return;
}

{
int version_major = 0;
int version_minor = 0;
int rc = XShapeQueryVersion(x11_display, &version_major, &version_minor);
print_verbose(vformat("Xshape %d.%d detected.", version_major, version_minor));
if (rc != 1 || version_major < 1) {
ERR_PRINT("Unsupported Xshape library version.");
r_error = ERR_UNAVAILABLE;
XCloseDisplay(x11_display);
return;
}
}

{
int version_major = 0;
int version_minor = 0;
int rc = XineramaQueryVersion(x11_display, &version_major, &version_minor);
print_verbose(vformat("Xinerama %d.%d detected.", version_major, version_minor));
if (rc != 1 || version_major < 1) {
ERR_PRINT("Unsupported Xinerama library version.");
r_error = ERR_UNAVAILABLE;
XCloseDisplay(x11_display);
return;
}
}

{
int version_major = 0;
int version_minor = 0;
int rc = XRRQueryVersion(x11_display, &version_major, &version_minor);
print_verbose(vformat("Xrandr %d.%d detected.", version_major, version_minor));
if (rc != 1 || (version_major == 1 && version_minor < 3) || (version_major < 1)) {
ERR_PRINT("Unsupported Xrandr library version.");
r_error = ERR_UNAVAILABLE;
XCloseDisplay(x11_display);
return;
}
}

{
int version_major = 0;
int version_minor = 0;
int rc = XRenderQueryVersion(x11_display, &version_major, &version_minor);
print_verbose(vformat("Xrender %d.%d detected.", version_major, version_minor));
if (rc != 1 || (version_major == 0 && version_minor < 11)) {
ERR_PRINT("Unsupported Xrender library version.");
r_error = ERR_UNAVAILABLE;
XCloseDisplay(x11_display);
return;
}
}

{
int version_major = 2; // Report 2.2 as supported by engine, but should work with 2.1 or 2.0 library as well.
int version_minor = 2;
int rc = XIQueryVersion(x11_display, &version_major, &version_minor);
print_verbose(vformat("Xinput %d.%d detected.", version_major, version_minor));
if (rc != Success || (version_major < 2)) {
ERR_PRINT("Unsupported Xinput2 library version.");
r_error = ERR_UNAVAILABLE;
XCloseDisplay(x11_display);
return;
}
}

char *modifiers = nullptr;
Bool xkb_dar = False;
XAutoRepeatOn(x11_display);
Expand Down Expand Up @@ -5779,7 +5860,7 @@ DisplayServerX11::~DisplayServerX11() {
}
XDestroyWindow(x11_display, wd.x11_xim_window);
#ifdef XKB_ENABLED
if (xkb_loaded) {
if (xkb_loaded_v05p) {
if (wd.xkb_state) {
xkb_compose_state_unref(wd.xkb_state);
wd.xkb_state = nullptr;
Expand All @@ -5791,7 +5872,7 @@ DisplayServerX11::~DisplayServerX11() {
}

#ifdef XKB_ENABLED
if (xkb_loaded) {
if (xkb_loaded_v05p) {
if (dead_tbl) {
xkb_compose_table_unref(dead_tbl);
}
Expand Down
3 changes: 2 additions & 1 deletion platform/linuxbsd/x11/display_server_x11.h
Original file line number Diff line number Diff line change
Expand Up @@ -211,7 +211,8 @@ class DisplayServerX11 : public DisplayServer {
String im_text;

#ifdef XKB_ENABLED
bool xkb_loaded = false;
bool xkb_loaded_v05p = false;
bool xkb_loaded_v08p = false;
xkb_context *xkb_ctx = nullptr;
xkb_compose_table *dead_tbl = nullptr;
#endif
Expand Down