@@ -14,16 +14,16 @@ use std::collections::HashMap;
1414use std:: sync:: Arc ;
1515use crate :: bluetooth:: discovery:: { find_connected_airpods, find_other_managed_devices} ;
1616use devices:: airpods:: AirPodsDevice ;
17- use bluer:: Address ;
17+ use bluer:: { Address , InternalErrorKind } ;
1818use ksni:: TrayMethods ;
1919use crate :: ui:: tray:: MyTray ;
2020use clap:: Parser ;
2121use crate :: bluetooth:: le:: start_le_monitor;
2222use tokio:: sync:: mpsc:: unbounded_channel;
23- use crate :: bluetooth :: att :: ATTHandles ;
24- use crate :: bluetooth:: managers:: BluetoothManager ;
23+ use tokio :: sync :: RwLock ;
24+ use crate :: bluetooth:: managers:: DeviceManagers ;
2525use crate :: devices:: enums:: DeviceData ;
26- use crate :: ui:: messages:: { AirPodsCommand , BluetoothUIMessage , NothingCommand , UICommand } ;
26+ use crate :: ui:: messages:: BluetoothUIMessage ;
2727use crate :: utils:: get_devices_path;
2828
2929#[ derive( Parser ) ]
@@ -40,28 +40,29 @@ fn main() -> iced::Result {
4040 let args = Args :: parse ( ) ;
4141 let log_level = if args. debug { "debug" } else { "info" } ;
4242 if env:: var ( "RUST_LOG" ) . is_err ( ) {
43- unsafe { env:: set_var ( "RUST_LOG" , log_level. to_owned ( ) + ",iced_wgpu=off ,wgpu_hal=off ,wgpu_core=off ,librepods_rust::bluetooth::le=off ,cosmic_text=off ,naga=off ,iced_winit=off " ) } ;
43+ unsafe { env:: set_var ( "RUST_LOG" , log_level. to_owned ( ) + ",winit=warn,tracing=warn,, iced_wgpu=warn ,wgpu_hal=warn ,wgpu_core=warn ,librepods_rust::bluetooth::le=warn ,cosmic_text=warn ,naga=warn ,iced_winit=warn " ) } ;
4444 }
4545 env_logger:: init ( ) ;
4646
4747 let ( ui_tx, ui_rx) = unbounded_channel :: < BluetoothUIMessage > ( ) ;
48- let ( ui_command_tx, ui_command_rx) = unbounded_channel :: < UICommand > ( ) ;
4948
49+ let device_managers: Arc < RwLock < HashMap < String , DeviceManagers > > > = Arc :: new ( RwLock :: new ( HashMap :: new ( ) ) ) ;
50+ let device_managers_clone = device_managers. clone ( ) ;
5051 std:: thread:: spawn ( || {
5152 let rt = tokio:: runtime:: Runtime :: new ( ) . unwrap ( ) ;
52- rt. block_on ( async_main ( ui_tx, ui_command_rx ) ) . unwrap ( ) ;
53+ rt. block_on ( async_main ( ui_tx, device_managers_clone ) ) . unwrap ( ) ;
5354 } ) ;
5455
55- ui:: window:: start_ui ( ui_rx, args. start_minimized , ui_command_tx )
56+ ui:: window:: start_ui ( ui_rx, args. start_minimized , device_managers )
5657}
5758
5859
59- async fn async_main ( ui_tx : tokio:: sync:: mpsc:: UnboundedSender < BluetoothUIMessage > , mut ui_command_rx : tokio:: sync:: mpsc:: UnboundedReceiver < UICommand > ) -> bluer:: Result < ( ) > {
60+ async fn async_main (
61+ ui_tx : tokio:: sync:: mpsc:: UnboundedSender < BluetoothUIMessage > ,
62+ device_managers : Arc < RwLock < HashMap < String , DeviceManagers > > > ,
63+ ) -> bluer:: Result < ( ) > {
6064 let args = Args :: parse ( ) ;
6165
62- // let mut device_command_txs: HashMap<String, tokio::sync::mpsc::UnboundedSender<(ControlCommandIdentifiers, Vec<u8>)>> = HashMap::new();
63- let mut device_managers: HashMap < String , Arc < BluetoothManager > > = HashMap :: new ( ) ;
64-
6566 let mut managed_devices_mac: Vec < String > = Vec :: new ( ) ; // includes ony non-AirPods. AirPods handled separately.
6667
6768 let devices_path = get_devices_path ( ) ;
@@ -125,12 +126,15 @@ async fn async_main(ui_tx: tokio::sync::mpsc::UnboundedSender<BluetoothUIMessage
125126 let ui_tx_clone = ui_tx. clone ( ) ;
126127 ui_tx_clone. send ( BluetoothUIMessage :: DeviceConnected ( device. address ( ) . to_string ( ) ) ) . unwrap ( ) ;
127128 let airpods_device = AirPodsDevice :: new ( device. address ( ) , tray_handle. clone ( ) , ui_tx_clone) . await ;
128- // device_command_txs.insert(device.address().to_string(), airpods_device.command_tx.unwrap());
129- // device_managers.insert(device.address().to_string(), Arc::new(airpods_device.aacp_manager));
130- device_managers. insert (
131- device. address ( ) . to_string ( ) ,
132- Arc :: from ( BluetoothManager :: AACP ( Arc :: new ( airpods_device. aacp_manager ) ) ) ,
133- ) ;
129+
130+ let mut managers = device_managers. write ( ) . await ;
131+ let dev_managers = DeviceManagers :: with_aacp ( airpods_device. aacp_manager . clone ( ) ) ;
132+ managers
133+ . entry ( device. address ( ) . to_string ( ) )
134+ . or_insert ( dev_managers)
135+ . set_aacp ( airpods_device. aacp_manager )
136+ ;
137+ drop ( managers)
134138 }
135139 Err ( _) => {
136140 info ! ( "No connected AirPods found." ) ;
@@ -144,30 +148,37 @@ async fn async_main(ui_tx: tokio::sync::mpsc::UnboundedSender<BluetoothUIMessage
144148 info ! ( "Found connected managed device: {}, initializing." , addr_str) ;
145149 let type_ = devices_list. get ( & addr_str) . unwrap ( ) . type_ . clone ( ) ;
146150 let ui_tx_clone = ui_tx. clone ( ) ;
147- let mut device_managers = device_managers. clone ( ) ;
151+ let device_managers = device_managers. clone ( ) ;
148152 tokio:: spawn ( async move {
149153 ui_tx_clone. send ( BluetoothUIMessage :: DeviceConnected ( addr_str. clone ( ) ) ) . unwrap ( ) ;
154+ let mut managers = device_managers. write ( ) . await ;
150155 match type_ {
151156 devices:: enums:: DeviceType :: Nothing => {
152157 let dev = devices:: nothing:: NothingDevice :: new ( device. address ( ) , ui_tx_clone) . await ;
153- device_managers. insert (
154- addr_str,
155- Arc :: from ( BluetoothManager :: ATT ( Arc :: new ( dev. att_manager ) ) ) ,
156- ) ;
158+ let dev_managers = DeviceManagers :: with_att ( dev. att_manager . clone ( ) ) ;
159+ managers
160+ . entry ( addr_str)
161+ . or_insert ( dev_managers)
162+ . set_att ( dev. att_manager ) ;
157163 }
158164 _ => { }
159165 }
166+ drop ( managers)
160167 } ) ;
161168 }
162169 }
163170 Err ( e) => {
164- log:: error!( "Error finding connected managed devices: {}" , e) ;
171+ log:: debug!( "type of error: {:?}" , e. kind) ;
172+ if e. kind != bluer:: ErrorKind :: Internal ( InternalErrorKind :: Io ( std:: io:: ErrorKind :: NotFound ) ) {
173+ log:: error!( "Error finding other managed devices: {}" , e) ;
174+ } else {
175+ info ! ( "No other managed devices found." ) ;
176+ }
165177 }
166178 }
167179
168180 let conn = Connection :: new_system ( ) ?;
169181 let rule = MatchRule :: new_signal ( "org.freedesktop.DBus.Properties" , "PropertiesChanged" ) ;
170- let device_managers_clone = device_managers. clone ( ) ;
171182 conn. add_match ( rule, move |_: ( ) , conn, msg| {
172183 let Some ( path) = msg. path ( ) else { return true ; } ;
173184 if !path. contains ( "/org/bluez/hci" ) || !path. contains ( "/dev_" ) {
@@ -198,14 +209,17 @@ async fn async_main(ui_tx: tokio::sync::mpsc::UnboundedSender<BluetoothUIMessage
198209 match type_ {
199210 devices:: enums:: DeviceType :: Nothing => {
200211 let ui_tx_clone = ui_tx. clone ( ) ;
201- let mut device_managers = device_managers. clone ( ) ;
212+ let device_managers = device_managers. clone ( ) ;
202213 tokio:: spawn ( async move {
214+ let mut managers = device_managers. write ( ) . await ;
203215 ui_tx_clone. send ( BluetoothUIMessage :: DeviceConnected ( addr_str. clone ( ) ) ) . unwrap ( ) ;
204216 let dev = devices:: nothing:: NothingDevice :: new ( addr, ui_tx_clone) . await ;
205- device_managers. insert (
206- addr_str,
207- Arc :: from ( BluetoothManager :: ATT ( Arc :: new ( dev. att_manager ) ) ) ,
208- ) ;
217+ let dev_managers = DeviceManagers :: with_att ( dev. att_manager . clone ( ) ) ;
218+ managers
219+ . entry ( addr_str)
220+ . or_insert ( dev_managers)
221+ . set_att ( dev. att_manager ) ;
222+ drop ( managers) ;
209223 } ) ;
210224 }
211225 _ => { }
@@ -220,85 +234,20 @@ async fn async_main(ui_tx: tokio::sync::mpsc::UnboundedSender<BluetoothUIMessage
220234 info ! ( "AirPods connected: {}, initializing" , name) ;
221235 let handle_clone = tray_handle. clone ( ) ;
222236 let ui_tx_clone = ui_tx. clone ( ) ;
223- let mut device_managers = device_managers. clone ( ) ;
237+ let device_managers = device_managers. clone ( ) ;
224238 tokio:: spawn ( async move {
225239 ui_tx_clone. send ( BluetoothUIMessage :: DeviceConnected ( addr_str. clone ( ) ) ) . unwrap ( ) ;
226240 let airpods_device = AirPodsDevice :: new ( addr, handle_clone, ui_tx_clone) . await ;
227- device_managers. insert (
228- addr_str,
229- Arc :: from ( BluetoothManager :: AACP ( Arc :: new ( airpods_device. aacp_manager ) ) ) ,
230- ) ;
241+ let mut managers = device_managers. write ( ) . await ;
242+ let dev_managers = DeviceManagers :: with_aacp ( airpods_device. aacp_manager . clone ( ) ) ;
243+ managers
244+ . entry ( addr_str)
245+ . or_insert ( dev_managers)
246+ . set_aacp ( airpods_device. aacp_manager ) ;
247+ drop ( managers) ;
231248 } ) ;
232249 true
233250 } ) ?;
234- tokio:: spawn ( async move {
235- while let Some ( command) = ui_command_rx. recv ( ) . await {
236- match command {
237- UICommand :: AirPods ( AirPodsCommand :: SetControlCommandStatus ( mac, identifier, value) ) => {
238- if let Some ( manager) = device_managers_clone. get ( & mac) {
239- match manager. as_ref ( ) {
240- BluetoothManager :: AACP ( manager) => {
241- log:: debug!( "Sending control command to device {}: {:?} = {:?}" , mac, identifier, value) ;
242- if let Err ( e) = manager. send_control_command ( identifier, value. as_ref ( ) ) . await {
243- log:: error!( "Failed to send control command to device {}: {}" , mac, e) ;
244- }
245- }
246- _ => {
247- log:: warn!( "AACP not available for {}" , mac) ;
248- }
249- }
250- } else {
251- log:: warn!( "No manager for device {}" , mac) ;
252- }
253- }
254- UICommand :: AirPods ( AirPodsCommand :: RenameDevice ( mac, new_name) ) => {
255- if let Some ( manager) = device_managers_clone. get ( & mac) {
256- match manager. as_ref ( ) {
257- BluetoothManager :: AACP ( manager) => {
258- log:: debug!( "Renaming device {} to {}" , mac, new_name) ;
259- if let Err ( e) = manager. send_rename_packet ( & new_name) . await {
260- log:: error!( "Failed to rename device {}: {}" , mac, e) ;
261- }
262- }
263- _ => {
264- log:: warn!( "AACP not available for {}" , mac) ;
265- }
266- }
267- } else {
268- log:: warn!( "No manager for device {}" , mac) ;
269- }
270- }
271- UICommand :: Nothing ( NothingCommand :: SetNoiseCancellationMode ( mac, mode) ) => {
272- if let Some ( manager) = device_managers_clone. get ( & mac) {
273- match manager. as_ref ( ) {
274- BluetoothManager :: ATT ( manager) => {
275- log:: debug!( "Setting noise cancellation mode for device {}: {:?}" , mac, mode) ;
276- if let Err ( e) = manager. write (
277- ATTHandles :: NothingEverything ,
278- & [
279- 0x55 ,
280- 0x60 , 0x01 ,
281- 0x0F , 0xF0 ,
282- 0x03 , 0x00 ,
283- 0x00 , 0x01 , // the 0x00 is an incremental counter, but it works without it
284- mode. to_byte ( ) , 0x00 ,
285- 0x00 , 0x00 // these both bytes were something random, 0 works too
286- ]
287- ) . await {
288- log:: error!( "Failed to set noise cancellation mode for device {}: {}" , mac, e) ;
289- }
290- }
291- _ => {
292- log:: warn!( "Nothing manager not available for {}" , mac) ;
293- }
294- }
295- } else {
296- log:: warn!( "No manager for device {}" , mac) ;
297- }
298- }
299- }
300- }
301- } ) ;
302251
303252 info ! ( "Listening for Bluetooth connections via D-Bus..." ) ;
304253 loop {
0 commit comments