Connect tray to new code base
This commit is contained in:
@@ -1,5 +1,6 @@
|
|||||||
use hyper_x_cloud_ii_wireless::Device;
|
use hyper_x_cloud_ii_wireless::devices::{Device, DeviceState};
|
||||||
use ksni::{Tray, MenuItem, menu::{StandardItem}, ToolTip, TrayService, Handle};
|
use ksni::{menu::StandardItem, Handle, MenuItem, ToolTip, Tray, TrayService};
|
||||||
|
use std::sync::{Arc, RwLock, RwLockReadGuard};
|
||||||
|
|
||||||
pub struct TrayHandler {
|
pub struct TrayHandler {
|
||||||
handle: Handle<BatteryTray>,
|
handle: Handle<BatteryTray>,
|
||||||
@@ -10,58 +11,35 @@ impl TrayHandler {
|
|||||||
let tray_service = TrayService::new(tray);
|
let tray_service = TrayService::new(tray);
|
||||||
let handle = tray_service.handle();
|
let handle = tray_service.handle();
|
||||||
tray_service.spawn();
|
tray_service.spawn();
|
||||||
TrayHandler {
|
TrayHandler { handle }
|
||||||
handle,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn update(&self, device: &Device) {
|
pub fn update(&self, device_state: &DeviceState) {
|
||||||
self.handle.update(|tray: &mut BatteryTray| { tray.update(device); })
|
let message = if device_state.connected.unwrap_or(false) {
|
||||||
}
|
Some(device_state.to_string())
|
||||||
|
} else {
|
||||||
pub fn set_status(&mut self, message: &str) {
|
None
|
||||||
self.handle.update(|tray: &mut BatteryTray| { tray.set_status(message); })
|
};
|
||||||
}
|
let name = device_state.device_name.clone();
|
||||||
|
self.handle.update(|tray| {
|
||||||
pub fn clear_status(&mut self) {
|
tray.message = message;
|
||||||
self.handle.update(|tray: &mut BatteryTray| { tray.clear_status(); })
|
tray.device_name = name;
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
pub struct BatteryTray {
|
pub struct BatteryTray {
|
||||||
battery_level: u8,
|
device_name: Option<String>,
|
||||||
charging: Option<bool>,
|
message: Option<String>,
|
||||||
muted: Option<bool>,
|
|
||||||
mic_connected: Option<bool>,
|
|
||||||
status_message: Option<String>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl BatteryTray {
|
impl BatteryTray {
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
BatteryTray {
|
BatteryTray {
|
||||||
battery_level: 0,
|
device_name: None,
|
||||||
charging: None,
|
message: None,
|
||||||
muted: None,
|
|
||||||
mic_connected: None,
|
|
||||||
status_message: Some("No device found".to_string()),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn update(&mut self, device: &Device) {
|
|
||||||
self.battery_level = device.battery_level;
|
|
||||||
self.charging = device.charging;
|
|
||||||
self.muted = device.muted;
|
|
||||||
self.mic_connected = device.mic_connected;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn set_status(&mut self, message: &str) {
|
|
||||||
self.status_message = Some(message.to_string());
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn clear_status(&mut self) {
|
|
||||||
self.status_message = None;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Tray for BatteryTray {
|
impl Tray for BatteryTray {
|
||||||
@@ -72,71 +50,45 @@ impl Tray for BatteryTray {
|
|||||||
"audio-headset".into()
|
"audio-headset".into()
|
||||||
}
|
}
|
||||||
fn tool_tip(&self) -> ToolTip {
|
fn tool_tip(&self) -> ToolTip {
|
||||||
let description = match &self.status_message {
|
println!("tool_tip");
|
||||||
Some(m) => m.clone(),
|
let description = if let Some(message) = self.message.clone() {
|
||||||
None => {
|
message
|
||||||
let mut description = format!("Battery level: {}%", self.battery_level);
|
} else {
|
||||||
if let Some(charging) = self.charging {
|
"Headset is not connected".to_string()
|
||||||
if charging {
|
|
||||||
description += "\nCharging";
|
|
||||||
} else {
|
|
||||||
description += "\nNot charging";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if let Some(muted) = self.muted {
|
|
||||||
if muted {
|
|
||||||
description += "\nMuted";
|
|
||||||
} else {
|
|
||||||
description += "\nNot muted";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if let Some(mic_connected) = self.mic_connected {
|
|
||||||
if mic_connected {
|
|
||||||
description += "\nMicrophone connected";
|
|
||||||
} else {
|
|
||||||
description += "\nMicrophone not connected";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
description
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
ToolTip {
|
ToolTip {
|
||||||
title: "HyperX Cloud II".to_string(),
|
title: self.device_name.clone().unwrap_or("Unknown".to_string()),
|
||||||
description,
|
description,
|
||||||
icon_name: "audio-headset".into(),
|
icon_name: "audio-headset".into(),
|
||||||
icon_pixmap: Vec::new(),
|
icon_pixmap: Vec::new(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fn menu(&self) -> Vec<MenuItem<Self>> {
|
fn menu(&self) -> Vec<MenuItem<Self>> {
|
||||||
let mut items = vec![
|
println!("menu");
|
||||||
StandardItem {
|
let message = if let Some(message) = &self.message {
|
||||||
label: format!("Battery level: {bat}% ({crg})", bat = self.battery_level,crg = (if self.charging.is_some() { "Charging" } else {"Discharging"})),
|
message
|
||||||
enabled: false,
|
} else {
|
||||||
..Default::default()
|
&"Headset is not connected".to_string()
|
||||||
}
|
};
|
||||||
.into(),
|
|
||||||
StandardItem {
|
let mut state_items: Vec<MenuItem<Self>> = message
|
||||||
label: "Exit".into(),
|
.lines()
|
||||||
icon_name: "application-exit".into(),
|
.map(|line| {
|
||||||
activate: Box::new(|_| std::process::exit(0)),
|
StandardItem {
|
||||||
..Default::default()
|
label: line.to_string(),
|
||||||
}
|
enabled: false,
|
||||||
.into(),
|
..Default::default()
|
||||||
];
|
}
|
||||||
if let Some(muted) = self.muted {
|
.into()
|
||||||
items.insert(1, StandardItem {
|
})
|
||||||
label: if muted { "Muted" } else { "Not muted" }.into(),
|
.collect();
|
||||||
enabled: false,
|
let exit = StandardItem {
|
||||||
..Default::default()
|
label: "Exit".into(),
|
||||||
}.into());
|
icon_name: "application-exit".into(),
|
||||||
}
|
activate: Box::new(|_| std::process::exit(0)),
|
||||||
if let Some(mic_connected) = self.mic_connected {
|
..Default::default()
|
||||||
items.insert(2, StandardItem {
|
};
|
||||||
label: if mic_connected { "Microphone connected" } else { "Microphone not connected" }.into(),
|
state_items.push(exit.into());
|
||||||
enabled: false,
|
state_items
|
||||||
..Default::default()
|
|
||||||
}.into());
|
|
||||||
}
|
|
||||||
items
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
74
src/main.rs
74
src/main.rs
@@ -1,78 +1,48 @@
|
|||||||
|
use std::sync::{Arc, RwLock};
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
|
||||||
use hyper_x_cloud_ii_wireless::{Device, DeviceError};
|
|
||||||
mod battery_tray;
|
mod battery_tray;
|
||||||
use battery_tray::{TrayHandler, BatteryTray};
|
use battery_tray::{BatteryTray, TrayHandler};
|
||||||
|
use hyper_x_cloud_ii_wireless::devices::{connect_compatible_device, Device, DeviceError};
|
||||||
|
|
||||||
fn pair_device() -> Device {
|
fn handle_error(error: DeviceError) -> String {
|
||||||
loop {
|
|
||||||
match Device::new() {
|
|
||||||
Ok(device) => break device,
|
|
||||||
Err(error) => {
|
|
||||||
eprintln!("{error}");
|
|
||||||
}
|
|
||||||
};
|
|
||||||
std::thread::sleep(std::time::Duration::from_secs(1));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn handle_error(error: DeviceError, device: &mut Device, tray_handler: &mut TrayHandler) {
|
|
||||||
match error {
|
match error {
|
||||||
DeviceError::HidError(hidapi::HidError::HidApiError { message }) => {
|
DeviceError::HidError(hidapi::HidError::HidApiError { message }) => {
|
||||||
if message == "No such device" {
|
if message == "No such device" {
|
||||||
eprintln!("No device found.");
|
eprintln!("No device found.");
|
||||||
tray_handler.set_status("No device found.");
|
"No such device".to_string()
|
||||||
*device = pair_device();
|
|
||||||
} else {
|
} else {
|
||||||
eprintln!("{message}");
|
eprintln!("{message}");
|
||||||
|
message
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
DeviceError::NoDeviceFound() => {
|
|
||||||
eprintln!("{}", DeviceError::NoDeviceFound());
|
|
||||||
device.clear_state();
|
|
||||||
tray_handler.update(device);
|
|
||||||
tray_handler.set_status( &DeviceError::NoDeviceFound().to_string());
|
|
||||||
}
|
|
||||||
DeviceError::HeadSetOff() => {
|
|
||||||
eprintln!("{}", DeviceError::HeadSetOff());
|
|
||||||
device.clear_state();
|
|
||||||
tray_handler.update(device);
|
|
||||||
tray_handler.set_status(&DeviceError::HeadSetOff().to_string());
|
|
||||||
}
|
|
||||||
error => {
|
error => {
|
||||||
eprintln!("{error}");
|
eprintln!("{error}");
|
||||||
|
error.to_string()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let mut tray_handler = TrayHandler::new(BatteryTray::new());
|
let mut device = loop {
|
||||||
let mut device = pair_device();
|
match connect_compatible_device() {
|
||||||
tray_handler.update(&device);
|
Ok(d) => break d,
|
||||||
|
Err(e) => println!("Connecting failed with error: {e}"),
|
||||||
|
}
|
||||||
|
std::thread::sleep(Duration::from_secs(1));
|
||||||
|
};
|
||||||
|
|
||||||
|
let tray_handler = TrayHandler::new(BatteryTray::new());
|
||||||
|
|
||||||
// Run loop
|
// Run loop
|
||||||
loop {
|
loop {
|
||||||
std::thread::sleep(std::time::Duration::from_secs(1));
|
std::thread::sleep(Duration::from_secs(1));
|
||||||
match device.update_battery_level() {
|
match device.refresh_state() {
|
||||||
Ok(_) => {
|
Ok(()) => (),
|
||||||
tray_handler.clear_status();
|
|
||||||
tray_handler.update(&device);
|
|
||||||
},
|
|
||||||
Err(error) => {
|
Err(error) => {
|
||||||
handle_error(error, &mut device, &mut tray_handler);
|
eprintln!("{}", error);
|
||||||
continue;
|
|
||||||
},
|
|
||||||
};
|
|
||||||
match device.wait_for_updates(Duration::from_secs(60)) {
|
|
||||||
Ok(_) => {
|
|
||||||
tray_handler.clear_status();
|
|
||||||
tray_handler.update(&device)
|
|
||||||
},
|
|
||||||
Err(DeviceError::NoResponse()) => (),
|
|
||||||
Err(error) => {
|
|
||||||
handle_error(error, &mut device, &mut tray_handler);
|
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
tray_handler.update(device.get_device_state())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user