use serde::{Deserialize, Serialize, Serializer};
use std::{fmt, str::FromStr};
use zbus::zvariant::{DeserializeDict, SerializeDict, Signature, Type};
use super::{HandleToken, DESTINATION, PATH};
use crate::{helpers::call_basic_response_method, Error};
#[derive(SerializeDict, DeserializeDict, Type, Clone, Debug, Default)]
#[zvariant(signature = "dict")]
struct AccessDeviceOptions {
handle_token: HandleToken,
}
#[derive(Debug, Clone, Copy, Deserialize, PartialEq, Eq)]
pub enum Device {
Microphone,
Speakers,
Camera,
}
impl fmt::Display for Device {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::Microphone => write!(f, "Microphone"),
Self::Speakers => write!(f, "Speakers"),
Self::Camera => write!(f, "Camera"),
}
}
}
impl AsRef<str> for Device {
fn as_ref(&self) -> &str {
match self {
Self::Microphone => "Microphone",
Self::Speakers => "Speakers",
Self::Camera => "Camera",
}
}
}
impl From<Device> for &'static str {
fn from(d: Device) -> Self {
match d {
Device::Microphone => "Microphone",
Device::Speakers => "Speakers",
Device::Camera => "Camera",
}
}
}
impl FromStr for Device {
type Err = Error;
fn from_str(s: &str) -> Result<Self, Self::Err> {
match s {
"Microphone" | "microphone" => Ok(Device::Microphone),
"Speakers" | "speakers" => Ok(Device::Speakers),
"Camera" | "camera" => Ok(Device::Camera),
_ => Err(Error::ParseError(
"Failed to parse device, invalid value".to_string(),
)),
}
}
}
impl Serialize for Device {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
serializer.serialize_str(&self.to_string().to_lowercase())
}
}
impl Type for Device {
fn signature() -> Signature<'static> {
String::signature()
}
}
#[derive(Debug)]
#[doc(alias = "org.freedesktop.portal.Device")]
pub struct DeviceProxy<'a>(zbus::Proxy<'a>);
impl<'a> DeviceProxy<'a> {
pub async fn new(connection: &zbus::Connection) -> Result<DeviceProxy<'a>, Error> {
let proxy = zbus::ProxyBuilder::new_bare(connection)
.interface("org.freedesktop.portal.Device")?
.path(PATH)?
.destination(DESTINATION)?
.build()
.await?;
Ok(Self(proxy))
}
pub fn inner(&self) -> &zbus::Proxy<'_> {
&self.0
}
#[doc(alias = "AccessDevice")]
pub async fn access_device(&self, pid: u32, devices: &[Device]) -> Result<(), Error> {
let options = AccessDeviceOptions::default();
call_basic_response_method(
self.inner(),
&options.handle_token,
"AccessDevice",
&(pid, devices, &options),
)
.await
}
}