linux-rust: add tray icon
This commit is contained in:
@@ -1,10 +1,13 @@
|
||||
use crate::bluetooth::aacp::{AACPManager, ProximityKeyType, AACPEvent};
|
||||
use crate::bluetooth::aacp::ControlCommandIdentifiers;
|
||||
use crate::media_controller::MediaController;
|
||||
use bluer::Address;
|
||||
use log::{debug, info};
|
||||
use std::sync::Arc;
|
||||
use ksni::Handle;
|
||||
use tokio::sync::Mutex;
|
||||
use tokio::time::{sleep, Duration};
|
||||
use crate::ui::tray::MyTray;
|
||||
|
||||
pub struct AirPodsDevice {
|
||||
pub mac_address: Address,
|
||||
@@ -13,11 +16,13 @@ pub struct AirPodsDevice {
|
||||
}
|
||||
|
||||
impl AirPodsDevice {
|
||||
pub async fn new(mac_address: Address) -> Self {
|
||||
pub async fn new(mac_address: Address, tray_handle: Handle<MyTray>) -> Self {
|
||||
info!("Creating new AirPodsDevice for {}", mac_address);
|
||||
let mut aacp_manager = AACPManager::new();
|
||||
aacp_manager.connect(mac_address).await;
|
||||
|
||||
tray_handle.update(|tray: &mut MyTray| tray.connected = true).await;
|
||||
|
||||
info!("Sending handshake");
|
||||
aacp_manager.send_handshake().await.expect(
|
||||
"Failed to send handshake to AirPods device",
|
||||
@@ -46,8 +51,52 @@ impl AirPodsDevice {
|
||||
let media_controller = Arc::new(Mutex::new(MediaController::new(mac_address.to_string())));
|
||||
let mc_clone = media_controller.clone();
|
||||
let (tx, mut rx) = tokio::sync::mpsc::unbounded_channel();
|
||||
let (command_tx, mut command_rx) = tokio::sync::mpsc::unbounded_channel();
|
||||
|
||||
aacp_manager.set_event_channel(tx).await;
|
||||
tray_handle.update(|tray: &mut MyTray| tray.command_tx = Some(command_tx)).await;
|
||||
|
||||
let aacp_manager_clone = aacp_manager.clone();
|
||||
tokio::spawn(async move {
|
||||
while let Some((id, value)) = command_rx.recv().await {
|
||||
if let Err(e) = aacp_manager_clone.send_control_command(id, &value).await {
|
||||
log::error!("Failed to send control command: {}", e);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
let (listening_mode_tx, mut listening_mode_rx) = tokio::sync::mpsc::unbounded_channel();
|
||||
aacp_manager.subscribe_to_control_command(ControlCommandIdentifiers::ListeningMode, listening_mode_tx).await;
|
||||
let tray_handle_clone = tray_handle.clone();
|
||||
tokio::spawn(async move {
|
||||
while let Some(value) = listening_mode_rx.recv().await {
|
||||
tray_handle_clone.update(|tray: &mut MyTray| {
|
||||
tray.listening_mode = Some(value[0]);
|
||||
}).await;
|
||||
}
|
||||
});
|
||||
|
||||
let (allow_off_tx, mut allow_off_rx) = tokio::sync::mpsc::unbounded_channel();
|
||||
aacp_manager.subscribe_to_control_command(ControlCommandIdentifiers::AllowOffOption, allow_off_tx).await;
|
||||
let tray_handle_clone = tray_handle.clone();
|
||||
tokio::spawn(async move {
|
||||
while let Some(value) = allow_off_rx.recv().await {
|
||||
tray_handle_clone.update(|tray: &mut MyTray| {
|
||||
tray.allow_off_option = Some(value[0]);
|
||||
}).await;
|
||||
}
|
||||
});
|
||||
|
||||
let (conversation_detect_tx, mut conversation_detect_rx) = tokio::sync::mpsc::unbounded_channel();
|
||||
aacp_manager.subscribe_to_control_command(ControlCommandIdentifiers::ConversationDetectConfig, conversation_detect_tx).await;
|
||||
let tray_handle_clone = tray_handle.clone();
|
||||
tokio::spawn(async move {
|
||||
while let Some(value) = conversation_detect_rx.recv().await {
|
||||
tray_handle_clone.update(|tray: &mut MyTray| {
|
||||
tray.conversation_detect_enabled = Some(value[0] == 0x01);
|
||||
}).await;
|
||||
}
|
||||
});
|
||||
|
||||
tokio::spawn(async move {
|
||||
while let Some(event) = rx.recv().await {
|
||||
@@ -58,9 +107,33 @@ impl AirPodsDevice {
|
||||
debug!("Calling handle_ear_detection with old_status: {:?}, new_status: {:?}", old_status, new_status);
|
||||
controller.handle_ear_detection(old_status, new_status).await;
|
||||
}
|
||||
_ => {
|
||||
debug!("Received unhandled AACP event: {:?}", event);
|
||||
AACPEvent::BatteryInfo(battery_info) => {
|
||||
debug!("Received BatteryInfo event: {:?}", battery_info);
|
||||
tray_handle.update(|tray: &mut MyTray| {
|
||||
for b in &battery_info {
|
||||
match b.component as u8 {
|
||||
0x02 => {
|
||||
tray.battery_l = Some(b.level);
|
||||
tray.battery_l_status = Some(b.status);
|
||||
}
|
||||
0x04 => {
|
||||
tray.battery_r = Some(b.level);
|
||||
tray.battery_r_status = Some(b.status);
|
||||
}
|
||||
0x08 => {
|
||||
tray.battery_c = Some(b.level);
|
||||
tray.battery_c_status = Some(b.status);
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
}).await;
|
||||
debug!("Updated tray with new battery info");
|
||||
}
|
||||
AACPEvent::ControlCommand(status) => {
|
||||
debug!("Received ControlCommand event: {:?}", status);
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user