Added - Client events are now implemented through `SimConnect::subscribe_to_client_event`, `SimConnect::unsubscribe_from_client_event` and `SimConnect::unsubscribe_from_all_client_events`. - `subscribe_to_client_events.rs` example has been added. - `SimConnectError::EventAlreadySubscribedTo` and `SimConnectError::EventNotSubscribedTo` error variants have been added. Changed - A second call to `SimConnect::subscribe_to_system_event` for the same event will now return an error of type `SimConnectError::EventAlreadySubscribedTo` instead of `SimConnectError::SimConnectException`. - The call to `SimConnect::unsubscribe_from_system_event` is now a NOOP when the system event is not subscribed to. - `SimConnectError::UnimplementedMessageType` has been renamed to `SimConnectError::UnimplementedNotification`. Removed - `SimConnect::register_event` has been replaced by the new client event functions. - `NotificationGroup` has been removed in favor of an internally managed notification group.
271 lines
13 KiB
Rust
271 lines
13 KiB
Rust
use std::os::raw::c_char;
|
|
|
|
use crate::{bindings, fixed_c_str_to_string, SimConnectError};
|
|
|
|
/// SimConnect System Event Request.
|
|
#[derive(Debug, Copy, Clone, PartialEq, Eq, num_enum::TryFromPrimitive)]
|
|
#[repr(u32)]
|
|
#[non_exhaustive]
|
|
pub enum SystemEventRequest {
|
|
/// Request a notification every second.
|
|
OneSecond = 0,
|
|
/// Request a notification every four seconds.
|
|
FourSeconds,
|
|
/// Request notifications six times per second. This is the same rate that joystick movement events are transmitted.
|
|
SixTimesPerSecond,
|
|
/// Request a notification when the aircraft flight dynamics file is changed. These files have a .AIR extension. The filename is returned.
|
|
AircraftLoaded,
|
|
/// Request a notification if the user aircraft crashes.
|
|
Crashed,
|
|
/// Request a notification when the crash cut-scene has completed.
|
|
CrashReset,
|
|
/// Request a notification when a flight is loaded. Note that when a flight is ended, a default flight is typically loaded, so these events will occur when flights and missions are started and finished. The filename of the flight loaded is returned.
|
|
FlightLoaded,
|
|
/// Request a notification when a flight is saved correctly. The filename of the flight saved is returned.
|
|
FlightSaved,
|
|
/// Request a notification when a new flight plan is activated. The filename of the activated flight plan is returned.
|
|
FlightPlanActivated,
|
|
/// Request a notification when the active flight plan is de-activated.
|
|
FlightPlanDeactivated,
|
|
/// Request notifications every visual frame.
|
|
Frame,
|
|
/// Request notifications when the scenario is paused or unpaused, and also immediately returns the current pause state.
|
|
Pause,
|
|
/// Request a notification when the scenario is paused.
|
|
Paused,
|
|
/// Request notifications for every visual frame that the simulation is paused.
|
|
PauseFrame,
|
|
/// Request a notification when the user changes the position of their aircraft through a dialog.
|
|
PositionChanged,
|
|
/// Request notifications when the scenario is running or not, and also immediately returns the current state.
|
|
Sim,
|
|
/// The simulator is running. Typically the user is actively controlling the vehicle which is on the ground, underwater or in the air.
|
|
SimStart,
|
|
/// The simulator is not running. Typically the user is loading a scenario, navigating the user interface or in a dialog.
|
|
SimStop,
|
|
/// Requests a notification when the master sound switch is changed. This request will also return the current state of the master sound switch immediately.
|
|
Sound,
|
|
/// Request a notification when the flight is un-paused.
|
|
Unpaused,
|
|
/// Requests a notification when the user aircraft view is changed. This request will also return the current view immediately.
|
|
View,
|
|
}
|
|
|
|
impl SystemEventRequest {
|
|
pub(crate) fn into_c_char(self) -> *const c_char {
|
|
match self {
|
|
SystemEventRequest::OneSecond => "1sec\0".as_ptr() as *const c_char,
|
|
SystemEventRequest::FourSeconds => "4sec\0".as_ptr() as *const c_char,
|
|
SystemEventRequest::SixTimesPerSecond => "6Hz\0".as_ptr() as *const c_char,
|
|
SystemEventRequest::AircraftLoaded => "AircraftLoaded\0".as_ptr() as *const c_char,
|
|
SystemEventRequest::Crashed => "Crashed\0".as_ptr() as *const c_char,
|
|
SystemEventRequest::CrashReset => "CrashReset\0".as_ptr() as *const c_char,
|
|
SystemEventRequest::FlightLoaded => "FlightLoaded\0".as_ptr() as *const c_char,
|
|
SystemEventRequest::FlightSaved => "FlightSaved\0".as_ptr() as *const c_char,
|
|
SystemEventRequest::FlightPlanActivated => {
|
|
"FlightPlanActivated\0".as_ptr() as *const c_char
|
|
}
|
|
SystemEventRequest::FlightPlanDeactivated => {
|
|
"FlightPlanDeactivated\0".as_ptr() as *const c_char
|
|
}
|
|
SystemEventRequest::Frame => "Frame\0".as_ptr() as *const c_char,
|
|
SystemEventRequest::Pause => "Pause\0".as_ptr() as *const c_char,
|
|
SystemEventRequest::Paused => "Paused\0".as_ptr() as *const c_char,
|
|
SystemEventRequest::PauseFrame => "PauseFrame\0".as_ptr() as *const c_char,
|
|
SystemEventRequest::PositionChanged => "PositionChanged\0".as_ptr() as *const c_char,
|
|
SystemEventRequest::Sim => "Sim\0".as_ptr() as *const c_char,
|
|
SystemEventRequest::SimStart => "SimStart\0".as_ptr() as *const c_char,
|
|
SystemEventRequest::SimStop => "SimStop\0".as_ptr() as *const c_char,
|
|
SystemEventRequest::Sound => "Sound\0".as_ptr() as *const c_char,
|
|
SystemEventRequest::Unpaused => "Unpaused\0".as_ptr() as *const c_char,
|
|
SystemEventRequest::View => "View\0".as_ptr() as *const c_char,
|
|
}
|
|
}
|
|
}
|
|
|
|
/// Cockpit view type.
|
|
#[derive(Debug, Copy, Clone, PartialEq, Eq, num_enum::TryFromPrimitive)]
|
|
#[repr(u32)]
|
|
pub enum ViewType {
|
|
/// No cockpit view.
|
|
None = 0,
|
|
/// 2D Panels in cockpit view.
|
|
Cockpit2D = bindings::SIMCONNECT_VIEW_SYSTEM_EVENT_DATA_COCKPIT_2D,
|
|
/// Virtual (3D) panels in cockpit view.
|
|
CockpitVirtual = bindings::SIMCONNECT_VIEW_SYSTEM_EVENT_DATA_COCKPIT_VIRTUAL,
|
|
/// Orthogonal (map) view.
|
|
Orthogonal = bindings::SIMCONNECT_VIEW_SYSTEM_EVENT_DATA_ORTHOGONAL,
|
|
}
|
|
|
|
/// SimConnect System Event Notification.
|
|
#[derive(Debug, Clone, PartialEq)]
|
|
#[non_exhaustive]
|
|
pub enum SystemEvent {
|
|
/// A notification every second.
|
|
OneSecond,
|
|
/// A notification every four seconds.
|
|
FourSeconds,
|
|
/// A notification six times per second. This is the same rate that joystick movement events are transmitted.
|
|
SixTimesPerSecond,
|
|
/// A notification when the aircraft flight dynamics file is changed. These files have a .AIR extension. The filename is returned.
|
|
AircraftLoaded {
|
|
/// The returned filename.
|
|
file_name: String,
|
|
},
|
|
/// A notification if the user aircraft crashes.
|
|
Crashed,
|
|
/// A notification when the crash cut-scene has completed.
|
|
CrashReset,
|
|
/// A notification when a flight is loaded. Note that when a flight is ended, a default flight is typically loaded, so these events will occur when flights and missions are started and finished. The filename of the flight loaded is returned.
|
|
FlightLoaded {
|
|
/// The returned filename.
|
|
file_name: String,
|
|
},
|
|
/// A notification when a flight is saved correctly. The filename of the flight saved is returned.
|
|
FlightSaved {
|
|
/// The returned filename.
|
|
file_name: String,
|
|
},
|
|
/// A notification when a new flight plan is activated. The filename of the activated flight plan is returned.
|
|
FlightPlanActivated {
|
|
/// The returned filename.
|
|
file_name: String,
|
|
},
|
|
/// A notification when the active flight plan is de-activated.
|
|
FlightPlanDeactivated,
|
|
/// Notifications every visual frame.
|
|
Frame {
|
|
/// The visual frame rate in frames per second.
|
|
frame_rate: f32,
|
|
/// The simulation rate. For example if the simulation is running at four times normal speed -- 4X -- then `4.0` will be returned.
|
|
sim_speed: f32,
|
|
},
|
|
/// Notifications when the scenario is paused or unpaused, and also immediately returns the current pause state.
|
|
Pause {
|
|
/// The current pause state (`true` = paused or `false` = unpaused).
|
|
state: bool,
|
|
},
|
|
/// A notification when the scenario is paused.
|
|
Paused,
|
|
/// Notifications for every visual frame that the simulation is paused.
|
|
PauseFrame {
|
|
/// The visual frame rate in frames per second.
|
|
frame_rate: f32,
|
|
/// The simulation rate. For example if the simulation is running at four times normal speed -- 4X -- then 4.0 will be returned.
|
|
sim_speed: f32,
|
|
},
|
|
/// A notification when the user changes the position of their aircraft through a dialog.
|
|
PositionChanged,
|
|
/// Notifications when the scenario is running or not, and also immediately returns the current state.
|
|
Sim {
|
|
/// The current state (`true` = running or `false` = not running).
|
|
state: bool,
|
|
},
|
|
/// The simulator is running. Typically the user is actively controlling the vehicle which is on the ground, underwater or in the air.
|
|
SimStart,
|
|
/// The simulator is not running. Typically the user is loading a scenario, navigating the user interface or in a dialog.
|
|
SimStop,
|
|
/// A notification when the master sound switch is changed. This request will also return the current state of the master sound switch immediately.
|
|
Sound {
|
|
/// The current state of the master sound switch. `false` if the switch is off, `true` if the switch is on.
|
|
state: bool,
|
|
},
|
|
/// A notification when the flight is un-paused.
|
|
Unpaused,
|
|
/// A notification when the user aircraft view is changed. This request will also return the current view immediately.
|
|
View {
|
|
/// The current cockpit view type.
|
|
view: ViewType,
|
|
},
|
|
}
|
|
|
|
impl TryFrom<&bindings::SIMCONNECT_RECV_EVENT> for SystemEvent {
|
|
type Error = SimConnectError;
|
|
|
|
fn try_from(event: &bindings::SIMCONNECT_RECV_EVENT) -> Result<Self, Self::Error> {
|
|
let request = SystemEventRequest::try_from(event.uEventID)
|
|
.map_err(|_| SimConnectError::UnimplementedEventType(event.uEventID))?;
|
|
|
|
match request {
|
|
SystemEventRequest::OneSecond => Ok(SystemEvent::OneSecond),
|
|
SystemEventRequest::FourSeconds => Ok(SystemEvent::FourSeconds),
|
|
SystemEventRequest::SixTimesPerSecond => Ok(SystemEvent::SixTimesPerSecond),
|
|
SystemEventRequest::Crashed => Ok(SystemEvent::Crashed),
|
|
SystemEventRequest::CrashReset => Ok(SystemEvent::CrashReset),
|
|
SystemEventRequest::FlightPlanDeactivated => Ok(SystemEvent::FlightPlanDeactivated),
|
|
SystemEventRequest::Pause => Ok(SystemEvent::Pause {
|
|
state: event.dwData == 1,
|
|
}),
|
|
SystemEventRequest::Paused => Ok(SystemEvent::Paused),
|
|
SystemEventRequest::PositionChanged => Ok(SystemEvent::PositionChanged),
|
|
SystemEventRequest::Sim => Ok(SystemEvent::Sim {
|
|
state: event.dwData == 1,
|
|
}),
|
|
SystemEventRequest::SimStart => Ok(SystemEvent::SimStart),
|
|
SystemEventRequest::SimStop => Ok(SystemEvent::SimStop),
|
|
SystemEventRequest::Sound => Ok(SystemEvent::Sound {
|
|
state: event.dwData == bindings::SIMCONNECT_SOUND_SYSTEM_EVENT_DATA_MASTER,
|
|
}),
|
|
SystemEventRequest::Unpaused => Ok(SystemEvent::Unpaused),
|
|
SystemEventRequest::View => Ok(SystemEvent::View {
|
|
view: ViewType::try_from(event.dwData).unwrap_or(ViewType::None),
|
|
}),
|
|
_ => Err(SimConnectError::UnimplementedEventType(event.uEventID)),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl TryFrom<&bindings::SIMCONNECT_RECV_EVENT_FILENAME> for SystemEvent {
|
|
type Error = SimConnectError;
|
|
|
|
fn try_from(event: &bindings::SIMCONNECT_RECV_EVENT_FILENAME) -> Result<Self, Self::Error> {
|
|
let request = SystemEventRequest::try_from(event._base.uEventID)
|
|
.map_err(|_| SimConnectError::UnimplementedEventType(event._base.uEventID))?;
|
|
|
|
match request {
|
|
SystemEventRequest::AircraftLoaded => {
|
|
let file_name = fixed_c_str_to_string(&event.szFileName);
|
|
Ok(SystemEvent::AircraftLoaded { file_name })
|
|
}
|
|
SystemEventRequest::FlightLoaded => {
|
|
let file_name = fixed_c_str_to_string(&event.szFileName);
|
|
Ok(SystemEvent::FlightLoaded { file_name })
|
|
}
|
|
SystemEventRequest::FlightSaved => {
|
|
let file_name = fixed_c_str_to_string(&event.szFileName);
|
|
Ok(SystemEvent::FlightSaved { file_name })
|
|
}
|
|
SystemEventRequest::FlightPlanActivated => {
|
|
let file_name = fixed_c_str_to_string(&event.szFileName);
|
|
Ok(SystemEvent::FlightPlanActivated { file_name })
|
|
}
|
|
_ => Err(SimConnectError::UnimplementedEventType(
|
|
event._base.uEventID,
|
|
)),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl TryFrom<&bindings::SIMCONNECT_RECV_EVENT_FRAME> for SystemEvent {
|
|
type Error = SimConnectError;
|
|
|
|
fn try_from(event: &bindings::SIMCONNECT_RECV_EVENT_FRAME) -> Result<Self, Self::Error> {
|
|
let request = SystemEventRequest::try_from(event._base.uEventID)
|
|
.map_err(|_| SimConnectError::UnimplementedEventType(event._base.uEventID))?;
|
|
|
|
match request {
|
|
SystemEventRequest::Frame => Ok(SystemEvent::Frame {
|
|
frame_rate: event.fFrameRate,
|
|
sim_speed: event.fSimSpeed,
|
|
}),
|
|
SystemEventRequest::PauseFrame => Ok(SystemEvent::PauseFrame {
|
|
frame_rate: event.fFrameRate,
|
|
sim_speed: event.fSimSpeed,
|
|
}),
|
|
_ => Err(SimConnectError::UnimplementedEventType(
|
|
event._base.uEventID,
|
|
)),
|
|
}
|
|
}
|
|
}
|