Skip to content

Commit

Permalink
feat(winloc): add ability to watch location status
Browse files Browse the repository at this point in the history
  • Loading branch information
spmadden committed Sep 18, 2023
1 parent 0ca8619 commit 9e06dc9
Show file tree
Hide file tree
Showing 3 changed files with 84 additions and 2 deletions.
12 changes: 12 additions & 0 deletions interfaces/win-location-api/doc/winloc.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,4 +56,16 @@ Geoposition {
}
```

```
PositionStatus {
Ready: 0,
Initializing: 1,
NoData: 2,
Disabled: 3,
NotInitialized: 4,
NotAvailable: 5,
Other/Unknown
}
```
27 changes: 26 additions & 1 deletion interfaces/win-location-api/src/data.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,31 @@ pub enum PositionSource {
Obfuscated,
}

#[derive(Debug, Copy, Clone, Eq, PartialEq)]
pub enum PositionStatus {
Ready,
Initializing,
NoData,
Disabled,
NotInitialized,
NotAvailable,
OtherUnknown(i32),
}

impl From<i32> for PositionStatus {
fn from(value: i32) -> Self {
match value {
0 => PositionStatus::Ready,
1 => PositionStatus::Initializing,
2 => PositionStatus::NoData,
3 => PositionStatus::Disabled,
4 => PositionStatus::NotInitialized,
5 => PositionStatus::NotAvailable,
u => PositionStatus::OtherUnknown(u),
}
}
}

#[derive(Default, Debug, Copy, Clone, PartialEq)]
pub struct WindowsCoordinate {
coordinate: Option<EllipticalCoordinate>,
Expand Down Expand Up @@ -74,7 +99,7 @@ impl WindowsCoordinate {
impl From<&Geocoordinate> for WindowsCoordinate {
fn from(value: &Geocoordinate) -> Self {
let coord = TryFrom::<&Geocoordinate>::try_from(value);
let coordinate: Option<EllipticalCoordinate> = coord.ok();
let mut coordinate: Option<EllipticalCoordinate> = coord.ok();

let mut heading = None;
if let Ok(hdg) = value.Heading() {
Expand Down
47 changes: 46 additions & 1 deletion interfaces/win-location-api/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ pub use crate::windows::*;
mod windows {
use log::{error, info, trace, warn};
use windows::Devices::Geolocation::{
GeolocationAccessStatus, Geolocator, PositionChangedEventArgs,
GeolocationAccessStatus, Geolocator, PositionChangedEventArgs, StatusChangedEventArgs,
};
use windows::Foundation::{EventRegistrationToken, TypedEventHandler};

Expand Down Expand Up @@ -54,6 +54,16 @@ mod windows {
Ok(out)
}

///
/// Returns the current status of the connection
pub fn get_status(&self) -> Result<PositionStatus, Error> {
Ok(self.locator.LocationStatus()?.0.into())
}

///
/// Registers a callback handler to receive updates when the location changes.
/// When the [`LocationHandler`] object gets dropped or goes out of scope, the callback
/// function is deregistered.
pub fn on_location_changed<T: FnMut(WindowsCoordinate) + Send + 'static>(
&self,
mut cb: T,
Expand Down Expand Up @@ -81,6 +91,29 @@ mod windows {
token: res,
})
}
pub fn on_status_changed<T: FnMut(PositionStatus) + Send + 'static>(
&self,
mut cb: T,
) -> Result<StatusHandler, Error> {
let handler = TypedEventHandler::new(
move |_sender: &Option<Geolocator>, result: &Option<StatusChangedEventArgs>| {
let Some(args) = result else {
error!("No status changed args received.");
return Ok(());
};
if let Ok(status) = args.Status() {
let out: PositionStatus = status.0.into();
cb(out);
}
Ok(())
},
);
let res = self.locator.StatusChanged(&handler)?;
Ok(StatusHandler {
locator: &self.locator,
token: res,
})
}
}

pub struct LocationHandler<'a> {
Expand All @@ -94,6 +127,18 @@ mod windows {
trace!("Dropped location handler.");
}
}

pub struct StatusHandler<'a> {
locator: &'a Geolocator,
token: EventRegistrationToken,
}

impl<'a> Drop for StatusHandler<'a> {
fn drop(&mut self) {
let _res = self.locator.RemoveStatusChanged(self.token);
trace!("Dropped location handler.");
}
}
}

#[cfg(target_os = "windows")]
Expand Down

0 comments on commit 9e06dc9

Please sign in to comment.