Skip to content

Commit 19b1e06

Browse files
committed
[*] update normally
1 parent 2c18318 commit 19b1e06

File tree

6 files changed

+89
-29
lines changed

6 files changed

+89
-29
lines changed

lib/recorder/examples/speaker_recording_demo.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ fn main() -> Result<(), Box<dyn Error>> {
2727
stop_sig_clone.store(true, Ordering::Relaxed);
2828
});
2929

30-
let recorder = SpeakerRecorder::new(save_path.clone(), stop_sig, None, false)?;
30+
let mut recorder = SpeakerRecorder::new(save_path.clone(), stop_sig, None, false)?;
3131
recorder.start_recording()?;
3232
log::info!("Successfully save: {}", save_path.display());
3333
Ok(())

lib/recorder/src/record_speaker.rs

Lines changed: 24 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,8 @@ pub struct SpeakerRecorder {
120120
disable_save_file: bool,
121121
// [0, infinity]
122122
amplification: Option<Arc<AtomicI32>>,
123+
124+
device_info: Option<(u32, String)>,
123125
}
124126

125127
impl SpeakerRecorder {
@@ -165,15 +167,20 @@ impl SpeakerRecorder {
165167
.connect_rc(None)
166168
.map_err(|e| SpeakerError::PipewireError(format!("context connect failed: {e}")))?;
167169

168-
Ok(Self {
170+
let mut recoder = Self {
169171
mainloop,
170172
core,
171173
save_path,
172174
stop_sig,
173175
level_sender,
174176
disable_save_file,
175177
amplification: None,
176-
})
178+
device_info: None,
179+
};
180+
181+
let output_device = recoder.find_default_output()?;
182+
recoder.device_info = output_device.clone();
183+
Ok(recoder)
177184
}
178185

179186
pub fn with_amplification(mut self, v: Arc<AtomicI32>) -> Self {
@@ -204,10 +211,8 @@ impl SpeakerRecorder {
204211
/// // Start recording (this will block until stop_sig is set)
205212
/// // recorder.start_recording().unwrap();
206213
/// ```
207-
pub fn start_recording(&self) -> Result<(), SpeakerError> {
208-
let output_device = self.find_default_output()?;
209-
210-
let Some((node_id, node_name)) = output_device else {
214+
pub fn start_recording(&mut self) -> Result<(), SpeakerError> {
215+
let Some((node_id, ref node_name)) = self.device_info else {
211216
return Err(SpeakerError::PipewireError(format!(
212217
"No found output speaker device (None)"
213218
)));
@@ -264,6 +269,10 @@ impl SpeakerRecorder {
264269
Ok(())
265270
}
266271

272+
pub fn get_device_info(&self) -> Option<(u32, String)> {
273+
self.device_info.clone()
274+
}
275+
267276
/// Stop the speaker recording session.
268277
///
269278
/// This method signals the recording thread to stop and clean up resources.
@@ -292,7 +301,7 @@ impl SpeakerRecorder {
292301
self.stop_sig.store(true, Ordering::Relaxed);
293302
}
294303

295-
fn find_default_output(&self) -> Result<Option<(u32, String)>, SpeakerError> {
304+
pub fn find_default_output(&self) -> Result<Option<(u32, String)>, SpeakerError> {
296305
log::info!("Start search output audio devices...");
297306

298307
let registry = self
@@ -318,13 +327,13 @@ impl SpeakerRecorder {
318327
(props.get("media.class"), props.get("node.name"))
319328
&& (media_class == "Audio/Sink" || media_class.starts_with("Audio/Sink"))
320329
{
321-
log::debug!(
322-
"Find audio output device : {} (ID: {}), type={:?}, attr: {:?}",
323-
node_name,
324-
global.id,
325-
global.type_,
326-
global.props
327-
);
330+
// log::debug!(
331+
// "Find audio output device : {} (ID: {}), type={:?}, attr: {:?}",
332+
// node_name,
333+
// global.id,
334+
// global.type_,
335+
// global.props
336+
// );
328337

329338
if let Some(priority) = props.get("priority.session")
330339
&& let Ok(priority) = priority.parse::<i32>()
@@ -347,7 +356,7 @@ impl SpeakerRecorder {
347356
self.mainloop.loop_().iterate(Duration::from_millis(100));
348357
}
349358

350-
log::info!("Use default device: {:?}", output_info);
359+
log::info!("Find default device: {:?}", output_info);
351360

352361
let result = output_info
353362
.lock()

lib/recorder/src/recorder.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -466,7 +466,7 @@ impl RecordingSession {
466466
let recorder = SpeakerRecorder::new(save_path, stop_sig, sender, disable_save_file)
467467
.map_err(|e| RecorderError::SpeakerError(e.to_string()))?;
468468

469-
let recorder = if amplification.is_some() {
469+
let mut recorder = if amplification.is_some() {
470470
recorder.with_amplification(amplification.unwrap())
471471
} else {
472472
recorder

wayshot/src/logic/recorder.rs

Lines changed: 61 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -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

4547
static 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

395446
fn input_audio_changed(ui: &AppWindow, name: SharedString, show_toast: bool) {

wayshot/ui/logic.slint

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ export global Logic {
8080
callback input-audio-changed(name: string, show-toast: bool);
8181
callback input-audio-amplification-changed(value: float);
8282
callback desktop-speaker-amplification-changed(value: float);
83-
callback refresh-desktop-speaker();
83+
callback refresh-desktop-speaker(show-toast: bool);
8484
callback start-recording();
8585
callback stop-recording();
8686
callback stop-merge-tracks();

wayshot/ui/panel/desktop/home.slint

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -257,7 +257,7 @@ component ControlPanel inherits HorizontalLayout {
257257
colorize: desktop-speaker-slider.enabled ? Theme.icon-color : Theme.disabled-color;
258258

259259
clicked => {
260-
Logic.refresh-desktop-speaker();
260+
Logic.refresh-desktop-speaker(true);
261261
}
262262
}
263263
}

0 commit comments

Comments
 (0)