#[cfg(feature = "XPLM400")]
use crate::avionics::AvionicsApi;
use crate::camera::CameraApi;
use crate::command::CommandApi;
use crate::data::DataApi;
use crate::feature::FeatureApi;
use crate::flight_loop::{FlightLoop, FlightLoopCallback, FlightLoopPhase};
use crate::menu::MenuApi;
use crate::navigation::{Fms, NavApi};
use crate::paths::PathApi;
use crate::player::PlayerApi;
use crate::plugin::management::PluginApi;
use crate::scenery::SceneryApi;
#[cfg(all(feature = "XPLM400", feature = "fmod"))]
use crate::sound::SoundApi;
#[cfg(feature = "XPLM400")]
use crate::weather::WeatherApi;
use std::ffi::c_void;
use std::{
ffi::{CStr, CString, NulError},
marker::PhantomData,
ptr,
};
use tailcall::tailcall;
use xplane_sys::{
XPLMDebugString, XPLMGetLanguage, XPLMGetVersions, XPLMGetVirtualKeyDescription,
XPLMHostApplicationID, XPLMLanguageCode, XPLMSpeakString,
};
mod ffi;
mod plugin_macro;
mod internal;
#[cfg(feature = "XPLM400")]
pub mod avionics;
pub mod camera;
pub mod command;
pub mod data;
pub mod error;
pub mod feature;
pub mod flight_loop;
pub mod geometry;
pub mod menu;
pub mod message;
pub mod navigation;
#[cfg(feature = "XPLM303")]
pub mod obj_instance;
pub mod paths;
pub mod player;
pub mod plugin;
pub mod scenery;
#[cfg(all(feature = "XPLM400", feature = "fmod"))]
pub mod sound;
#[cfg(feature = "XPLM400")]
pub mod weather;
pub mod window;
type NoSendSync = PhantomData<*mut ()>;
#[tailcall]
fn xp_major_ver(input: i32, full_version: i32) -> (i32, i32) {
if !(-99..=99).contains(&input) {
xp_major_ver(input, full_version)
}
(input, full_version)
}
#[allow(missing_docs)]
pub struct XPAPI {
#[cfg(feature = "XPLM400")]
pub avionics: AvionicsApi,
pub camera: CameraApi,
pub command: CommandApi,
pub data: DataApi,
pub features: FeatureApi,
pub menu: MenuApi,
pub nav: NavApi,
pub paths: PathApi,
pub player: PlayerApi,
pub plugins: PluginApi,
pub scenery: SceneryApi,
#[cfg(all(feature = "XPLM400", feature = "fmod"))]
pub sound: SoundApi,
#[cfg(feature = "XPLM400")]
pub weather: WeatherApi,
_phantom: NoSendSync, }
impl XPAPI {
pub fn debug_string<S: Into<Vec<u8>>>(&mut self, s: S) -> Result<(), NulError> {
let s = CString::new(s)?;
unsafe {
XPLMDebugString(s.as_ptr());
}
Ok(())
}
pub fn speak_string<S: Into<Vec<u8>>>(&mut self, s: S) -> Result<(), NulError> {
let s = CString::new(s)?;
unsafe {
XPLMSpeakString(s.as_ptr());
}
Ok(())
}
pub fn new_flight_loop<T: 'static>(
&mut self,
phase: FlightLoopPhase,
callback: impl FlightLoopCallback<T>,
base_state: T,
) -> FlightLoop<T> {
FlightLoop::new(phase, callback, base_state)
}
pub fn find_symbol<S: Into<String>>(&mut self, name: S) -> *mut c_void {
match std::ffi::CString::new(name.into()) {
Ok(name_c) => unsafe { xplane_sys::XPLMFindSymbol(name_c.as_ptr()) },
Err(_) => ptr::null_mut(),
}
}
pub fn get_versions(&mut self) -> ((i32, i32), i32) {
let mut xp = 0i32;
let mut xplm = 0i32;
let mut host_id = XPLMHostApplicationID::XPlane;
unsafe {
XPLMGetVersions(&mut xp, &mut xplm, &mut host_id);
}
(xp_major_ver(xp, xp), xplm)
}
#[allow(clippy::cast_sign_loss, clippy::cast_possible_truncation)]
pub fn get_vkey_desc(&mut self, key: window::Key) -> &str {
let desc = unsafe { XPLMGetVirtualKeyDescription(u32::from(key) as i8) };
unsafe {
CStr::from_ptr(desc).to_str().unwrap() }
}
pub fn get_language(&mut self) -> Option<&'static str> {
let lang = unsafe { XPLMGetLanguage() };
match lang {
XPLMLanguageCode::English => Some("en"),
XPLMLanguageCode::French => Some("fr"),
XPLMLanguageCode::German => Some("de"),
XPLMLanguageCode::Italian => Some("it"),
XPLMLanguageCode::Spanish => Some("es"),
XPLMLanguageCode::Korean => Some("ko"),
XPLMLanguageCode::Russian => Some("ru"),
XPLMLanguageCode::Greek => Some("el"),
XPLMLanguageCode::Japanese => Some("ja"),
#[cfg(feature = "XPLM300")]
XPLMLanguageCode::Chinese => Some("zh"),
_ => None,
}
}
}
#[inline]
fn make_x() -> XPAPI {
XPAPI {
#[cfg(feature = "XPLM400")]
avionics: AvionicsApi {
_phantom: PhantomData,
},
camera: CameraApi {
_phantom: PhantomData,
},
command: CommandApi {
_phantom: PhantomData,
},
data: DataApi {
_phantom: PhantomData,
},
features: FeatureApi {
_phantom: PhantomData,
},
menu: MenuApi {
_phantom: PhantomData,
},
nav: NavApi {
fms: Fms {
_phantom: PhantomData,
},
_phantom: PhantomData,
},
paths: PathApi {
_phantom: PhantomData,
},
player: PlayerApi {
_phantom: PhantomData,
},
plugins: PluginApi {
_phantom: PhantomData,
},
scenery: SceneryApi {
_phantom: PhantomData,
},
#[cfg(all(feature = "XPLM400", feature = "fmod"))]
sound: SoundApi {
_phantom: PhantomData,
},
#[cfg(feature = "XPLM400")]
weather: WeatherApi {
_phantom: PhantomData,
},
_phantom: PhantomData,
}
}
#[macro_export]
macro_rules! debug {
($x:ident, $($arg:tt)*) => ({
let formatted_string: String = std::fmt::format(std::format_args!($($arg)*));
$x.debug_string(formatted_string)
});
}
#[macro_export]
#[allow(unused_unsafe)]
macro_rules! debugln {
($x:ident) => ($crate::debug!($x, "\n"));
($x:ident, $($arg:tt)*) => ({
let mut formatted_string: String = std::fmt::format(std::format_args!($($arg)*));
formatted_string.push_str("\n");
$x.debug_string(formatted_string)
});
}