use super::{HandleToken, SessionProxy, DESTINATION, PATH};
use crate::{
helpers::{call_basic_response_method, call_method, receive_signal},
Error, WindowIdentifier,
};
use futures::TryFutureExt;
use serde::{Deserialize, Serialize};
use serde_repr::{Deserialize_repr, Serialize_repr};
use zvariant::OwnedObjectPath;
use zvariant_derive::{DeserializeDict, SerializeDict, Type, TypeDict};
#[derive(Serialize_repr, Deserialize_repr, PartialEq, Debug, Type)]
#[repr(u32)]
pub enum Accuracy {
None = 0,
Country = 1,
City = 2,
Neighborhood = 3,
Street = 4,
Exact = 5,
}
#[derive(SerializeDict, DeserializeDict, TypeDict, Debug, Default)]
struct CreateSessionOptions {
session_handle_token: HandleToken,
distance_threshold: Option<u32>,
time_threshold: Option<u32>,
accuracy: Option<Accuracy>,
}
impl CreateSessionOptions {
pub fn distance_threshold(mut self, distance_threshold: u32) -> Self {
self.distance_threshold = Some(distance_threshold);
self
}
pub fn time_threshold(mut self, time_threshold: u32) -> Self {
self.time_threshold = Some(time_threshold);
self
}
pub fn accuracy(mut self, accuracy: Accuracy) -> Self {
self.accuracy = Some(accuracy);
self
}
}
#[derive(SerializeDict, DeserializeDict, TypeDict, Debug, Default)]
struct SessionStartOptions {
handle_token: HandleToken,
}
#[derive(Debug, Serialize, Deserialize, Type)]
pub struct Location(OwnedObjectPath, LocationInner);
impl Location {
pub fn accuracy(&self) -> f64 {
self.1.accuracy
}
pub fn altitude(&self) -> f64 {
self.1.altitude
}
pub fn speed(&self) -> f64 {
self.1.speed
}
pub fn heading(&self) -> f64 {
self.1.heading
}
pub fn description(&self) -> &str {
&self.1.description
}
pub fn latitude(&self) -> f64 {
self.1.latitude
}
pub fn longitude(&self) -> f64 {
self.1.longitude
}
pub fn timestamp(&self) -> u64 {
self.1.timestamp.0
}
}
#[derive(Debug, SerializeDict, DeserializeDict, TypeDict)]
struct LocationInner {
#[zvariant(rename = "Accuracy")]
accuracy: f64,
#[zvariant(rename = "Altitude")]
altitude: f64,
#[zvariant(rename = "Speed")]
speed: f64,
#[zvariant(rename = "Heading")]
heading: f64,
#[zvariant(rename = "Description")]
description: String,
#[zvariant(rename = "Latitude")]
latitude: f64,
#[zvariant(rename = "Longitude")]
longitude: f64,
#[zvariant(rename = "Timestamp")]
timestamp: (u64, u64),
}
#[derive(Debug)]
#[doc(alias = "org.freedesktop.portal.Location")]
pub struct LocationProxy<'a>(zbus::azync::Proxy<'a>);
impl<'a> LocationProxy<'a> {
pub async fn new(connection: &zbus::azync::Connection) -> Result<LocationProxy<'a>, Error> {
let proxy = zbus::ProxyBuilder::new_bare(connection)
.interface("org.freedesktop.portal.Location")
.path(PATH)?
.destination(DESTINATION)
.build_async()
.await?;
Ok(Self(proxy))
}
pub fn inner(&self) -> &zbus::azync::Proxy<'_> {
&self.0
}
#[doc(alias = "LocationUpdated")]
pub async fn receive_location_updated(&self) -> Result<Location, Error> {
receive_signal(&self.0, "LocationUpdated").await
}
#[doc(alias = "CreateSession")]
pub async fn create_session(
&self,
distance_threshold: Option<u32>,
time_threshold: Option<u32>,
accuracy: Option<Accuracy>,
) -> Result<SessionProxy<'a>, Error> {
let options = CreateSessionOptions::default()
.distance_threshold(distance_threshold.unwrap_or(0))
.time_threshold(time_threshold.unwrap_or(0))
.accuracy(accuracy.unwrap_or(Accuracy::Exact));
let (path, proxy) = futures::try_join!(
call_method::<zvariant::OwnedObjectPath, CreateSessionOptions>(
&self.0,
"CreateSession",
&(options)
)
.into_future(),
SessionProxy::from_unique_name(self.0.connection(), &options.session_handle_token)
.into_future(),
)?;
assert_eq!(proxy.inner().path(), &path.into_inner());
Ok(proxy)
}
#[doc(alias = "Start")]
pub async fn start(
&self,
session: &SessionProxy<'_>,
identifier: WindowIdentifier,
) -> Result<(), Error> {
let options = SessionStartOptions::default();
call_basic_response_method(
&self.0,
&options.handle_token,
"Start",
&(session, identifier, &options),
)
.await
}
}