146 lines
4.4 KiB
Rust
146 lines
4.4 KiB
Rust
pub mod config;
|
|
pub mod context;
|
|
pub mod state;
|
|
pub mod handler;
|
|
|
|
use gtk::glib;
|
|
use gstreamer as gst;
|
|
use std::ffi::c_void;
|
|
use std::os::raw::{c_char, c_int, c_uint};
|
|
use std::ptr;
|
|
|
|
// Re-export types for external use (e.g. integration tests)
|
|
pub use config::{ModuleConfig, DEADZONE_ARG, DEADZONE_LONG, DEADZONE_DESC, DEADZONE_ARG_DESC};
|
|
pub use context::{Window, GtkLock, WindowContext, __IncompleteArrayField};
|
|
pub use state::{MODULE_STATE, WindowData, ModuleState};
|
|
pub use handler::WindowHandler;
|
|
|
|
#[no_mangle]
|
|
pub static module_name: [c_char; 7] = [
|
|
b'a' as c_char,
|
|
b'h' as c_char,
|
|
b'f' as c_char,
|
|
b'a' as c_char,
|
|
b'i' as c_char,
|
|
b'l' as c_char,
|
|
0,
|
|
];
|
|
|
|
#[no_mangle]
|
|
pub static module_major_version: c_uint = 4;
|
|
|
|
#[no_mangle]
|
|
pub static module_minor_version: c_uint = 0;
|
|
|
|
#[no_mangle]
|
|
pub static mut module_entries: [glib::ffi::GOptionEntry; 3] = [
|
|
glib::ffi::GOptionEntry {
|
|
long_name: DEADZONE_LONG.as_ptr() as *const c_char,
|
|
short_name: 0,
|
|
flags: 0,
|
|
arg: glib::ffi::G_OPTION_ARG_STRING,
|
|
arg_data: &raw mut DEADZONE_ARG as *mut _,
|
|
description: DEADZONE_DESC.as_ptr() as *const c_char,
|
|
arg_description: DEADZONE_ARG_DESC.as_ptr() as *const c_char
|
|
},
|
|
glib::ffi::GOptionEntry { long_name: ptr::null(), short_name: 0, flags: 0, arg: 0, arg_data: ptr::null_mut(), description: ptr::null(), arg_description: ptr::null() },
|
|
glib::ffi::GOptionEntry { long_name: ptr::null(), short_name: 0, flags: 0, arg: 0, arg_data: ptr::null_mut(), description: ptr::null(), arg_description: ptr::null() },
|
|
];
|
|
|
|
// Helper for tests to inspect window data
|
|
/// # Safety
|
|
/// `ctx` must be a valid Window pointer.
|
|
pub unsafe fn get_window_data_ref(ctx: *mut Window) -> Option<&'static state::WindowData> {
|
|
let ptr = *(*ctx).module_data.as_ptr();
|
|
if ptr.is_null() {
|
|
None
|
|
} else {
|
|
Some(&*(ptr as *mut state::WindowData))
|
|
}
|
|
}
|
|
|
|
/// # Safety
|
|
/// This function is called by the C host.
|
|
#[no_mangle]
|
|
pub unsafe extern "C" fn on_activation(_gtklock: *mut GtkLock, _id: c_int) {
|
|
println!("[ahfail] on_activation called");
|
|
if let Err(e) = gtk::init() {
|
|
eprintln!("Failed to initialize GTK bindings: {}", e);
|
|
return;
|
|
}
|
|
if let Err(e) = gst::init() {
|
|
eprintln!("Failed to initialize GStreamer: {}", e);
|
|
return;
|
|
}
|
|
|
|
let anim_opt = unsafe { ahfail_ui::animation::load_animation() };
|
|
|
|
let config = ModuleConfig::from_args();
|
|
|
|
MODULE_STATE.with(|state| {
|
|
let mut state = state.borrow_mut();
|
|
state.animation = anim_opt;
|
|
state.audio_uri = Some("resource:///ahfail/audio/magic-word.mp3".to_string());
|
|
state.config = config;
|
|
});
|
|
}
|
|
|
|
/// # Safety
|
|
/// This function is called by the C host.
|
|
#[no_mangle]
|
|
pub unsafe extern "C" fn on_window_create(_gtklock: *mut GtkLock, ctx: *mut Window) {
|
|
if let Some(win_ctx) = WindowContext::new(ctx) {
|
|
WindowHandler::create(&win_ctx);
|
|
}
|
|
}
|
|
|
|
/// # Safety
|
|
/// This function is called by the C host.
|
|
#[no_mangle]
|
|
pub unsafe extern "C" fn on_window_destroy(_gtklock: *mut GtkLock, ctx: *mut Window) {
|
|
if let Some(win_ctx) = WindowContext::new(ctx) {
|
|
WindowHandler::destroy(&win_ctx);
|
|
}
|
|
}
|
|
|
|
/// # Safety
|
|
/// This function is called by the C host.
|
|
#[no_mangle]
|
|
pub unsafe extern "C" fn on_idle_hide(gtklock: *mut GtkLock) {
|
|
if gtklock.is_null() { return; }
|
|
let garray = (*gtklock).windows;
|
|
if !garray.is_null() {
|
|
let len = (*garray).len;
|
|
let data_ptr = (*garray).data as *mut *mut Window;
|
|
let windows = std::slice::from_raw_parts(data_ptr, len as usize);
|
|
|
|
for &window_ptr in windows {
|
|
on_window_destroy(ptr::null_mut(), window_ptr);
|
|
}
|
|
}
|
|
}
|
|
|
|
/// # Safety
|
|
/// This function is called by the C host.
|
|
#[no_mangle]
|
|
pub unsafe extern "C" fn on_focus_change(_gtklock: *mut GtkLock, _win: *mut Window, _old: *mut Window) {}
|
|
|
|
/// # Safety
|
|
/// This function is called by the C host.
|
|
#[no_mangle]
|
|
pub unsafe extern "C" fn on_idle_show(_gtklock: *mut GtkLock) {}
|
|
|
|
/// # Safety
|
|
/// This function is called by the C host.
|
|
#[no_mangle]
|
|
pub unsafe extern "C" fn g_module_unload(_module: *mut c_void) {
|
|
MODULE_STATE.with(|state| {
|
|
let mut state = state.borrow_mut();
|
|
if let Some(vs) = state.volume_state.take() {
|
|
ahfail_ui::volume::restore(vs);
|
|
}
|
|
state.animation = None;
|
|
state.audio_uri = None;
|
|
state.config.deadzone = None;
|
|
});
|
|
} |