Skip to content

Commit

Permalink
fixes issue with charging icon, code refactor
Browse files Browse the repository at this point in the history
  • Loading branch information
kondinskis committed Oct 30, 2021
1 parent 88490d2 commit 502308e
Show file tree
Hide file tree
Showing 5 changed files with 101 additions and 78 deletions.
2 changes: 1 addition & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "cloud-flight"
version = "0.1.0"
version = "0.1.1"
edition = "2018"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
Expand Down
60 changes: 43 additions & 17 deletions src/cloud_flight.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use hidapi::{HidApi, HidDevice};
use log::debug;
use log::{debug, info};
use std::cell::Cell;

const VENDOR_ID: u16 = 0x0951;
const PRODUCT_ID: u16 = 0x16c4;
Expand Down Expand Up @@ -41,7 +42,7 @@ fn battery_percent(charge_state: u8, value: u8) -> u8 {
}
}

pub enum EventType {
pub enum Event {
Battery { value: u8 },
BatteryCharging,
VolumeUp,
Expand All @@ -54,16 +55,24 @@ pub enum EventType {
}
pub struct CloudFlight {
device: HidDevice,
pub powered: Cell<bool>,
pub muted: Cell<bool>,
pub charging: Cell<bool>,
pub battery: Cell<u8>,
}
impl CloudFlight {
pub fn new() -> Self {
let api = HidApi::new().unwrap();

CloudFlight {
device: api.open(VENDOR_ID, PRODUCT_ID).unwrap(),
powered: Cell::new(true),
muted: Cell::new(false),
charging: Cell::new(false),
battery: Cell::new(100),
}
}
pub fn read(&self) -> EventType {
pub fn read(&self) -> Event {
let mut buf = [0u8; 32];
let bytes = self.device.read_timeout(&mut buf, 500).unwrap();
debug!("Read: {}, {:02x?}", bytes, buf);
Expand All @@ -72,37 +81,54 @@ impl CloudFlight {
if buf[0] == 0x64 {
if buf[1] == 0x01 {
self.battery();
return EventType::PowerOn;
self.powered.set(true);
info!("Power on");
return Event::PowerOn;
} else if buf[1] == 0x03 {
return EventType::PowerOff;
self.powered.set(false);
info!("Power off");
return Event::PowerOff;
}
}
if buf[0] == 0x65 {
if buf[1] == 0x04 {
return EventType::Muted;
self.muted.set(true);
info!("Muted");
return Event::Muted;
} else {
return EventType::Unmuted;
self.muted.set(false);
info!("Unmuted");
return Event::Unmuted;
}
}
return EventType::Ignored;
return Event::Ignored;
}
5 => {
if buf[1] == 0x01 {
return EventType::VolumeUp;
info!("Volume up");
return Event::VolumeUp;
} else if buf[1] == 0x02 {
return EventType::VolumeDown;
info!("Volume down");
return Event::VolumeDown;
}
return EventType::Ignored;
return Event::Ignored;
}
20 => {
if (buf[3] == 0x10 || buf[3] == 0x11) && buf[4] >= 20 {
return EventType::BatteryCharging;
if buf[3] == 0x10 || buf[3] == 0x11 {
info!("Battery charging");
self.charging.set(true);
if buf[4] >= 20 {
return Event::BatteryCharging;
}
return Event::Battery { value: 100 };
}
return EventType::Battery {
value: battery_percent(buf[3], buf[4]),
};
let b_percent = battery_percent(buf[3], buf[4]);
info!("Battery {}", b_percent);
self.charging.set(false);
self.battery.set(b_percent);
return Event::Battery { value: b_percent };
}
_ => return EventType::Ignored,
_ => return Event::Ignored,
}
}
pub fn battery(&self) {
Expand Down
48 changes: 17 additions & 31 deletions src/main.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
use clokwerk::{Scheduler, TimeUnits};
use log::info;
use simple_logger::SimpleLogger;
use std::sync::Arc;
use std::thread;
Expand Down Expand Up @@ -28,37 +27,24 @@ fn main() {
loop {
scheduler.run_pending();
let event = cf.read();
svc.update(|tray: &mut tray::Tray| {
match event {
cloud_flight::EventType::BatteryCharging => {
info!("Battery charging")
match event {
cloud_flight::Event::BatteryCharging => (),
cloud_flight::Event::Battery { value: _ } => (),
cloud_flight::Event::VolumeUp => (),
cloud_flight::Event::VolumeDown => (),
cloud_flight::Event::Muted => {
if BATTERY_REFRESH_ON_MUTE {
cf.battery();
}
cloud_flight::EventType::Battery { value } => {
tray.battery = value;
info!("Battery {}", value)
}
cloud_flight::EventType::VolumeUp => {
info!("Volume up")
}
cloud_flight::EventType::VolumeDown => {
info!("Volume down")
}
cloud_flight::EventType::Muted => {
tray.muted = true;
if BATTERY_REFRESH_ON_MUTE {
cf.battery();
}
info!("Muted")
}
cloud_flight::EventType::Unmuted => {
tray.muted = false;
info!("Unmuted")
}
cloud_flight::EventType::PowerOff => info!("Power off"),
cloud_flight::EventType::PowerOn => info!("Power on"),
cloud_flight::EventType::Ignored => (),
};
});
}
cloud_flight::Event::Unmuted => (),
cloud_flight::Event::PowerOff => (),
cloud_flight::Event::PowerOn => (),
cloud_flight::Event::Ignored => (),
};
if !matches!(event, cloud_flight::Event::Ignored) {
svc.update();
}
}
});
handle.join().unwrap();
Expand Down
67 changes: 39 additions & 28 deletions src/tray.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use ksni::menu::StandardItem;
use ksni::ToolTip;
use std::sync::Arc;
use std::vec::Vec;
Expand All @@ -14,42 +15,69 @@ const HEADPHONES_BATTERY_CAUTION: &str = "battery-010";
const HEADPHONES_BATTERY_EMPTY: &str = "battery-empty.svg";

pub struct Tray {
pub muted: bool,
pub battery: u8,
cf: Arc<cloud_flight::CloudFlight>,
}

impl ksni::Tray for Tray {
fn icon_name(&self) -> String {
if self.muted {
if self.cf.muted.get() {
HEADPHONES_MUTED.to_string()
} else if self.cf.charging.get() {
HEADPHONES_BATTERY_CHARGING.to_string()
} else {
battery_icon(self.battery).into()
match self.cf.battery.get() {
0..=19 => HEADPHONES_BATTERY_CAUTION,
20..=39 => HEADPHONES_BATTERY_LOW,
40..=59 => HEADPHONES_BATTERY_MEDIUM,
60..=89 => HEADPHONES_BATTERY_GOOD,
90..=100 => HEADPHONES_BATTERY_FULL,
_ => HEADPHONES_BATTERY_EMPTY,
}
.to_string()
}
}
fn tool_tip(&self) -> ToolTip {
let description: String;
if self.cf.charging.get() {
description = format!("Charging battery");
} else {
description = format!("Battery: {}%", self.cf.battery.get());
}
ToolTip {
title: "HyperX Cloud Flight".into(),
description: format!("Battery: {}%", self.battery),
description: description,
icon_name: "".into(),
icon_pixmap: Vec::new(),
}
}
fn menu(&self) -> Vec<ksni::MenuItem<Self>> {
use ksni::menu::*;
let muted_text: String;
if self.cf.muted.get() {
muted_text = "Yes".into();
} else {
muted_text = "No".into();
}

let battery_text: String;
if self.cf.charging.get() {
battery_text = "Battery charging".into();
} else {
battery_text = format!("Battery level: {}", self.cf.battery.get());
}

vec![
StandardItem {
label: "HyperX Cloud Flight".into(),
..Default::default()
}
.into(),
StandardItem {
label: format!("Muted: {}", self.muted),
label: format!("Muted: {}", muted_text),
..Default::default()
}
.into(),
StandardItem {
label: format!("Battery level: {}", self.battery),
label: battery_text,
activate: {
let cf = self.cf.clone();
Box::new(move |_| cf.clone().battery())
Expand All @@ -73,29 +101,12 @@ pub struct TrayService {

impl TrayService {
pub fn new(cf: Arc<cloud_flight::CloudFlight>) -> Self {
let svc = ksni::TrayService::new(Tray {
muted: false,
battery: 100,
cf: cf,
});
let svc = ksni::TrayService::new(Tray { cf: cf });
let handle = svc.handle();
svc.spawn();
TrayService { handle: handle }
}
pub fn update<F: Fn(&mut Tray)>(&self, f: F) {
self.handle.update(f);
}
}

fn battery_icon(battery: u8) -> String {
match battery {
0..=19 => HEADPHONES_BATTERY_CAUTION,
20..=39 => HEADPHONES_BATTERY_LOW,
40..=59 => HEADPHONES_BATTERY_MEDIUM,
60..=89 => HEADPHONES_BATTERY_GOOD,
90..=100 => HEADPHONES_BATTERY_FULL,
101 => HEADPHONES_BATTERY_CHARGING,
_ => HEADPHONES_BATTERY_EMPTY,
pub fn update(&self) {
self.handle.update(|_: &mut Tray| {});
}
.to_string()
}

0 comments on commit 502308e

Please sign in to comment.