use std::ffi::{CStr, CString};
use std::os::raw::*;
use std::path::PathBuf;
use std::ptr;
use xplm_sys;
pub fn plugin_with_signature(signature: &str) -> Option<Plugin> {
match CString::new(signature) {
Ok(signature) => {
let plugin_id = unsafe { xplm_sys::XPLMFindPluginBySignature(signature.as_ptr()) };
if plugin_id != xplm_sys::XPLM_NO_PLUGIN_ID {
Some(Plugin(plugin_id))
} else {
None
}
}
Err(_) => None,
}
}
pub fn this_plugin() -> Plugin {
let plugin_id = unsafe { xplm_sys::XPLMGetMyID() };
assert_ne!(
plugin_id,
xplm_sys::XPLM_NO_PLUGIN_ID,
"XPLMGetMyId() returned no plugin ID"
);
Plugin(plugin_id)
}
pub fn all_plugins() -> Plugins {
Plugins {
next: 0,
count: unsafe { xplm_sys::XPLMCountPlugins() - 1 },
}
}
pub struct Plugins {
next: c_int,
count: c_int,
}
impl Iterator for Plugins {
type Item = Plugin;
fn next(&mut self) -> Option<Self::Item> {
if self.next < self.count {
let plugin = Plugin(unsafe { xplm_sys::XPLMGetNthPlugin(self.next) });
self.next += 1;
if plugin.0 == xplm_sys::XPLM_PLUGIN_XPLANE as xplm_sys::XPLMPluginID {
self.next()
} else {
Some(plugin)
}
} else {
None
}
}
fn size_hint(&self) -> (usize, Option<usize>) {
let remaining = (self.count - self.next) as usize;
(remaining, Some(remaining))
}
}
impl ExactSizeIterator for Plugins {}
pub struct Plugin(xplm_sys::XPLMPluginID);
impl Plugin {
pub fn name(&self) -> String {
read_to_buffer(|buffer| unsafe {
xplm_sys::XPLMGetPluginInfo(
self.0,
buffer,
ptr::null_mut(),
ptr::null_mut(),
ptr::null_mut(),
)
})
}
pub fn signature(&self) -> String {
read_to_buffer(|buffer| unsafe {
xplm_sys::XPLMGetPluginInfo(
self.0,
ptr::null_mut(),
ptr::null_mut(),
buffer,
ptr::null_mut(),
)
})
}
pub fn description(&self) -> String {
read_to_buffer(|buffer| unsafe {
xplm_sys::XPLMGetPluginInfo(
self.0,
ptr::null_mut(),
ptr::null_mut(),
ptr::null_mut(),
buffer,
)
})
}
pub fn path(&self) -> PathBuf {
let os_path = read_to_buffer(|buffer| unsafe {
xplm_sys::XPLMGetPluginInfo(
self.0,
ptr::null_mut(),
buffer,
ptr::null_mut(),
ptr::null_mut(),
)
});
PathBuf::from(os_path)
}
pub fn enabled(&self) -> bool {
unsafe { xplm_sys::XPLMIsPluginEnabled(self.0) == 1 }
}
pub fn set_enabled(&self, enabled: bool) {
if enabled {
unsafe {
xplm_sys::XPLMEnablePlugin(self.0);
}
} else {
unsafe {
xplm_sys::XPLMDisablePlugin(self.0);
}
}
}
}
fn read_to_buffer<F: Fn(*mut c_char)>(read_callback: F) -> String {
let mut buffer: [c_char; 256] = [b'\0' as c_char; 256];
read_callback(buffer.as_mut_ptr());
let cstr = unsafe { CStr::from_ptr(buffer.as_ptr()) };
cstr.to_string_lossy().into_owned()
}