Skip to content

Commit fdad15c

Browse files
committed
Add camera preview timeout and improve camera cleanup
1 parent 1506972 commit fdad15c

File tree

2 files changed

+46
-8
lines changed

2 files changed

+46
-8
lines changed

apps/desktop/src-tauri/src/camera.rs

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,9 @@ use tokio::{
1717
runtime::Runtime,
1818
sync::{broadcast, oneshot},
1919
task::LocalSet,
20+
time::{Duration, Instant},
2021
};
21-
use tracing::{error, info, trace};
22+
use tracing::{error, info, trace, warn};
2223
use wgpu::{CompositeAlphaMode, SurfaceTexture};
2324

2425
static TOOLBAR_HEIGHT: f32 = 56.0; // also defined in Typescript
@@ -496,8 +497,23 @@ impl Renderer {
496497
return;
497498
};
498499

500+
let start_time = Instant::now();
501+
let startup_timeout = Duration::from_secs(5);
502+
let mut received_first_frame = false;
503+
499504
let mut state = default_state;
500505
while let Some(event) = loop {
506+
let timeout_remaining = if received_first_frame {
507+
Duration::MAX
508+
} else {
509+
startup_timeout.saturating_sub(start_time.elapsed())
510+
};
511+
512+
if timeout_remaining.is_zero() {
513+
warn!("Camera preview timed out waiting for first frame, closing window");
514+
break None;
515+
}
516+
501517
tokio::select! {
502518
frame = camera_rx.recv_async() => break frame.ok().map(Ok),
503519
result = reconfigure.recv() => {
@@ -507,10 +523,15 @@ impl Renderer {
507523
continue;
508524
}
509525
},
526+
_ = tokio::time::sleep(timeout_remaining) => {
527+
warn!("Camera preview timed out waiting for first frame, closing window");
528+
break None;
529+
}
510530
}
511531
} {
512532
match event {
513533
Ok(frame) => {
534+
received_first_frame = true;
514535
let aspect_ratio = frame.inner.width() as f32 / frame.inner.height() as f32;
515536
self.sync_ratio_uniform_and_resize_window_to_it(&window, &state, aspect_ratio);
516537

apps/desktop/src-tauri/src/lib.rs

Lines changed: 24 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -456,12 +456,17 @@ async fn set_camera_input(
456456
.map_err(|e| e.to_string())?;
457457
}
458458
Some(id) => {
459+
{
460+
let app = &mut *state.write().await;
461+
app.selected_camera_id = Some(id.clone());
462+
app.camera_in_use = true;
463+
app.camera_cleanup_done = false;
464+
}
465+
459466
let mut attempts = 0;
460-
loop {
467+
let init_result: Result<(), String> = loop {
461468
attempts += 1;
462469

463-
// We first ask the actor to set the input
464-
// This returns a future that resolves when the camera is actually ready
465470
let request = camera_feed
466471
.ask(feeds::camera::SetInput { id: id.clone() })
467472
.await
@@ -473,10 +478,10 @@ async fn set_camera_input(
473478
};
474479

475480
match result {
476-
Ok(_) => break,
481+
Ok(_) => break Ok(()),
477482
Err(e) => {
478483
if attempts >= 3 {
479-
return Err(format!(
484+
break Err(format!(
480485
"Failed to initialize camera after {} attempts: {}",
481486
attempts, e
482487
));
@@ -488,6 +493,13 @@ async fn set_camera_input(
488493
tokio::time::sleep(Duration::from_millis(500)).await;
489494
}
490495
}
496+
};
497+
498+
if let Err(e) = init_result {
499+
let app = &mut *state.write().await;
500+
app.selected_camera_id = None;
501+
app.camera_in_use = false;
502+
return Err(e);
491503
}
492504

493505
ShowCapWindow::Camera
@@ -2758,7 +2770,13 @@ pub async fn run(recording_logging_handle: LoggingHandle, logs_dir: PathBuf) {
27582770
let state = app.state::<ArcLock<App>>();
27592771
let app_state = &mut *state.write().await;
27602772

2761-
if !app_state.is_recording_active_or_pending() {
2773+
let camera_window_open =
2774+
CapWindowId::Camera.get(&app).is_some();
2775+
2776+
if !app_state.is_recording_active_or_pending()
2777+
&& !camera_window_open
2778+
&& !app_state.camera_in_use
2779+
{
27622780
let _ =
27632781
app_state.mic_feed.ask(microphone::RemoveInput).await;
27642782
let _ = app_state
@@ -2768,7 +2786,6 @@ pub async fn run(recording_logging_handle: LoggingHandle, logs_dir: PathBuf) {
27682786

27692787
app_state.selected_mic_label = None;
27702788
app_state.selected_camera_id = None;
2771-
app_state.camera_in_use = false;
27722789
}
27732790
});
27742791
}

0 commit comments

Comments
 (0)