use std::{fs, os::raw::c_char};
extern "C" {
pub(crate) fn XOpenDisplay(display_name: *const c_char) -> *mut std::os::raw::c_void;
pub(crate) fn XCloseDisplay(display: *mut std::os::raw::c_void) -> i32;
pub(crate) fn wl_display_connect(name: *const c_char) -> *mut std::os::raw::c_void;
pub(crate) fn wl_display_disconnect(display: *mut std::os::raw::c_void);
}
#[derive(Debug)]
pub struct LinuxGlibLoop {
glib_loop: glib::MainLoop,
handle: Option<std::thread::JoinHandle<()>>,
}
impl LinuxGlibLoop {
pub fn new() -> Self {
let g_loop = glib::MainLoop::new(None, false);
let g_loop_clone = g_loop.clone();
let handle = std::thread::spawn(move || {
g_loop_clone.run();
});
Self {
glib_loop: g_loop,
handle: Some(handle),
}
}
}
impl Default for LinuxGlibLoop {
fn default() -> Self {
Self::new()
}
}
impl Drop for LinuxGlibLoop {
fn drop(&mut self) {
if self.glib_loop.is_running() {
self.glib_loop.quit();
}
if let Some(handle) = self.handle.take() {
let r = handle.join();
if std::thread::panicking() {
if let Err(e) = r {
log::error!(
"[libobs-wrapper]: Thread panicked while dropping LinuxGlibLoop: {:?}",
e
);
}
} else {
r.unwrap();
}
}
}
}
pub(crate) unsafe fn wl_proxy_get_display(
proxy: *mut std::os::raw::c_void,
) -> Result<*mut std::os::raw::c_void, libloading::Error> {
let lib = unsafe {
libloading::Library::new("libwayland-client.so")
.or_else(|_e| libloading::Library::new("libwayland-client.so.0"))?
};
let sym: Result<
libloading::Symbol<
unsafe extern "C" fn(*mut ::std::os::raw::c_void) -> *mut ::std::os::raw::c_void,
>,
libloading::Error,
> = unsafe {
lib.get(b"wl_proxy_get_display\0")
};
match sym {
Ok(f) => Ok(unsafe {
f(proxy)
}),
Err(e) => Err(e),
}
}
pub(crate) fn get_linux_opengl_lib_name() -> String {
let obs_bin = "/usr/bin/obs"; if !std::path::Path::new(obs_bin).exists() {
log::debug!("Couldn't find /usr/bin/obs, using fallback OpenGL lib name.");
return "libobs-opengl.so".to_string(); }
let raw_strings = fs::read(obs_bin).unwrap_or_default();
let search_str = "libobs-opengl";
let search_bytes = search_str.as_bytes();
let found_lib_name = "libobs-opengl.so".to_string();
let mut idx = 0usize;
while idx < raw_strings.len() {
let rel = raw_strings[idx..]
.windows(search_bytes.len())
.position(|w| w == search_bytes);
let start = match rel {
Some(r) => idx + r,
None => break,
};
let end = match raw_strings[start..].iter().position(|&b| b == 0) {
Some(p) => start + p,
None => raw_strings.len(),
};
if end > start {
if let Ok(s) = std::str::from_utf8(&raw_strings[start..end]) {
if s.contains(".so") {
return s.to_string();
}
}
}
idx = start + search_bytes.len();
}
log::debug!("Extracted OpenGL lib name: {}", found_lib_name);
found_lib_name
}