@@ -40,6 +40,8 @@ struct Cache {
4040
4141 recorder_stop_sig : Option < Arc < AtomicBool > > ,
4242 merge_stop_sig : Option < Arc < AtomicBool > > ,
43+
44+ speaker_device_info : Option < ( u32 , String ) > ,
4345}
4446
4547static CACHE : Lazy < Mutex < Cache > > = Lazy :: new ( || Mutex :: new ( Cache :: default ( ) ) ) ;
@@ -85,7 +87,7 @@ pub fn init(ui: &AppWindow) {
8587 logic_cb ! ( choose_save_dir, ui) ;
8688 logic_cb ! ( input_audio_amplification_changed, ui, v) ;
8789 logic_cb ! ( desktop_speaker_amplification_changed, ui, v) ;
88- logic_cb ! ( refresh_desktop_speaker, ui) ;
90+ logic_cb ! ( refresh_desktop_speaker, ui, show_toast ) ;
8991 logic_cb ! ( input_audio_changed, ui, name, show_toast) ;
9092 logic_cb ! ( start_recording, ui) ;
9193 logic_cb ! ( stop_recording, ui) ;
@@ -104,9 +106,7 @@ fn inner_init(ui: &AppWindow) {
104106 toast_warn ! ( ui, format!( "{e}" ) ) ;
105107 }
106108
107- if let Err ( e) = init_desktop_speaker ( & ui) {
108- toast_warn ! ( ui, format!( "{e}" ) ) ;
109- }
109+ init_desktop_speaker ( & ui) ;
110110
111111 if let Err ( e) = init_video ( & ui) {
112112 toast_warn ! ( ui, format!( "{e}" ) ) ;
@@ -173,7 +173,38 @@ fn init_input_audio(ui: &AppWindow) -> Result<()> {
173173 Ok ( ( ) )
174174}
175175
176- fn init_desktop_speaker ( ui : & AppWindow ) -> Result < ( ) > {
176+ fn init_desktop_speaker ( ui : & AppWindow ) {
177+ let ui_weak = ui. as_weak ( ) ;
178+
179+ if let Err ( e) = create_desktop_speaker ( ui) {
180+ log:: warn!( "{e}" ) ;
181+ }
182+
183+ thread:: spawn ( move || {
184+ let Ok ( recorder) =
185+ SpeakerRecorder :: new ( PathBuf :: new ( ) , Arc :: new ( AtomicBool :: new ( false ) ) , None , true )
186+ else {
187+ log:: warn!( "init desktop speaker recorder failed" ) ;
188+ return ;
189+ } ;
190+
191+ loop {
192+ thread:: sleep ( std:: time:: Duration :: from_secs ( 5 ) ) ;
193+
194+ let device_info = CACHE . lock ( ) . unwrap ( ) . speaker_device_info . clone ( ) ;
195+
196+ if speaker_device_changed ( & recorder, & device_info) {
197+ log:: info!( "speaker device changed: current speaker deivce info: {device_info:?}" ) ;
198+
199+ _ = ui_weak. clone ( ) . upgrade_in_event_loop ( move |ui| {
200+ refresh_desktop_speaker ( & ui, false ) ;
201+ } ) ;
202+ }
203+ }
204+ } ) ;
205+ }
206+
207+ fn create_desktop_speaker ( ui : & AppWindow ) -> Result < ( ) > {
177208 let ui_weak = ui. as_weak ( ) ;
178209
179210 thread:: spawn ( move || {
@@ -212,12 +243,13 @@ fn init_desktop_speaker(ui: &AppWindow) -> Result<()> {
212243 let amplification = Arc :: new ( AtomicI32 :: new (
213244 config:: all ( ) . control . desktop_speaker_gain as i32 ,
214245 ) ) ;
215- let recorder = recorder. with_amplification ( amplification. clone ( ) ) ;
246+ let mut recorder = recorder. with_amplification ( amplification. clone ( ) ) ;
216247
217248 {
218249 let mut cache = CACHE . lock ( ) . unwrap ( ) ;
219250 cache. desktop_speaker_stop_sig = Some ( stop_sig) ;
220251 cache. desktop_speaker_amplification = Some ( amplification) ;
252+ cache. speaker_device_info = recorder. get_device_info ( ) ;
221253 }
222254
223255 if let Err ( e) = recorder. start_recording ( ) {
@@ -378,18 +410,37 @@ fn desktop_speaker_amplification_changed(_ui: &AppWindow, v: f32) {
378410 }
379411}
380412
381- fn refresh_desktop_speaker ( ui : & AppWindow ) {
413+ fn refresh_desktop_speaker ( ui : & AppWindow , show_toast : bool ) {
382414 {
383415 if let Some ( stop_sig) = CACHE . lock ( ) . unwrap ( ) . desktop_speaker_stop_sig . take ( ) {
384416 stop_sig. store ( true , Ordering :: Relaxed ) ;
385417 }
386418 }
387419
388- if let Err ( e) = init_desktop_speaker ( ui) {
389- toast_warn ! ( ui, format!( "{e}" ) ) ;
420+ if let Err ( e) = create_desktop_speaker ( ui) {
421+ if show_toast {
422+ toast_warn ! ( ui, format!( "{e}" ) ) ;
423+ } else {
424+ log:: warn!( "{e}" ) ;
425+ }
390426 } else {
391- toast_success ! ( ui, "refresh successfully" ) ;
427+ if show_toast {
428+ toast_success ! ( ui, "refresh successfully" ) ;
429+ }
430+ }
431+ }
432+
433+ fn speaker_device_changed ( recorder : & SpeakerRecorder , device_info : & Option < ( u32 , String ) > ) -> bool {
434+ let Ok ( Some ( ( node_id, node_name) ) ) = recorder. find_default_output ( ) else {
435+ log:: warn!( "find default speaker device failed" ) ;
436+ return false ;
437+ } ;
438+
439+ if let Some ( ( old_node_id, old_node_name) ) = device_info {
440+ return node_id != * old_node_id || node_name. as_str ( ) != old_node_name. as_str ( ) ;
392441 }
442+
443+ true
393444}
394445
395446fn input_audio_changed ( ui : & AppWindow , name : SharedString , show_toast : bool ) {
0 commit comments