diff --git a/app/src/lib/hooks/useSystemAudioCapture.ts b/app/src/lib/hooks/useSystemAudioCapture.ts index 10b7a468..fb4ddeba 100644 --- a/app/src/lib/hooks/useSystemAudioCapture.ts +++ b/app/src/lib/hooks/useSystemAudioCapture.ts @@ -41,7 +41,6 @@ export function useSystemAudioCapture({ }, []); const startRecording = useCallback(async () => { - console.log('[useSystemAudioCapture] startRecording called'); if (!isTauri()) { const errorMsg = 'System audio capture is only available in the desktop app.'; setError(errorMsg); @@ -55,16 +54,13 @@ export function useSystemAudioCapture({ } try { - console.log('[useSystemAudioCapture] Starting capture...'); setError(null); setDuration(0); // Start native capture - console.log('[useSystemAudioCapture] Calling invoke...'); await invoke('start_system_audio_capture', { maxDurationSecs: maxDurationSeconds, }); - console.log('[useSystemAudioCapture] Invoke completed, starting timer'); setIsRecording(true); isRecordingRef.current = true; @@ -78,14 +74,11 @@ export function useSystemAudioCapture({ // Auto-stop at max duration if (elapsed >= maxDurationSeconds && stopRecordingRef.current) { - console.log('[useSystemAudioCapture] Max duration reached, auto-stopping'); void stopRecordingRef.current(); } } }, 100); - console.log('[useSystemAudioCapture] Timer started'); } catch (err) { - console.error('[useSystemAudioCapture] Error starting recording:', err); const errorMessage = err instanceof Error ? err.message @@ -157,17 +150,15 @@ export function useSystemAudioCapture({ // Cleanup on unmount only useEffect(() => { return () => { - console.log('[useSystemAudioCapture] Component unmounting, cleaning up'); if (timerRef.current !== null) { clearInterval(timerRef.current); timerRef.current = null; } // Cancel recording on unmount if still recording if (isRecordingRef.current && isTauri()) { - console.log('[useSystemAudioCapture] Canceling recording on unmount'); // Call stop directly without the callback to avoid stale closure invoke('stop_system_audio_capture').catch((err) => { - console.error('[useSystemAudioCapture] Error stopping on unmount:', err); + console.error('Error stopping audio capture on unmount:', err); }); } }; diff --git a/tauri/src-tauri/gen/Assets.car b/tauri/src-tauri/gen/Assets.car index 7b81cf77..269230ac 100644 Binary files a/tauri/src-tauri/gen/Assets.car and b/tauri/src-tauri/gen/Assets.car differ diff --git a/tauri/src-tauri/src/audio_capture/mod.rs b/tauri/src-tauri/src/audio_capture/mod.rs index 54f47856..7a55c334 100644 --- a/tauri/src-tauri/src/audio_capture/mod.rs +++ b/tauri/src-tauri/src/audio_capture/mod.rs @@ -18,6 +18,7 @@ pub struct AudioCaptureState { pub sample_rate: Arc>, pub channels: Arc>, pub stop_tx: Arc>>>, + pub error: Arc>>, #[cfg(target_os = "macos")] pub stream: Arc>>, } @@ -29,6 +30,7 @@ impl AudioCaptureState { sample_rate: Arc::new(Mutex::new(44100)), channels: Arc::new(Mutex::new(2)), stop_tx: Arc::new(Mutex::new(None)), + error: Arc::new(Mutex::new(None)), #[cfg(target_os = "macos")] stream: Arc::new(Mutex::new(None)), } @@ -36,5 +38,6 @@ impl AudioCaptureState { pub fn reset(&self) { *self.samples.lock().unwrap() = Vec::new(); + *self.error.lock().unwrap() = None; } } diff --git a/tauri/src-tauri/src/audio_capture/windows.rs b/tauri/src-tauri/src/audio_capture/windows.rs index 33739a25..1f5fd40e 100644 --- a/tauri/src-tauri/src/audio_capture/windows.rs +++ b/tauri/src-tauri/src/audio_capture/windows.rs @@ -19,6 +19,7 @@ pub async fn start_capture( let sample_rate_arc = state.sample_rate.clone(); let channels_arc = state.channels.clone(); let stop_tx = state.stop_tx.clone(); + let error_arc = state.error.clone(); // Use AtomicBool for stop signal (works with non-Send types) let stop_flag = Arc::new(AtomicBool::new(false)); @@ -42,7 +43,9 @@ pub async fn start_capture( { Ok(d) => d, Err(e) => { - eprintln!("Failed to get audio device: {}", e); + let error_msg = format!("Failed to get audio device: {}", e); + eprintln!("{}", error_msg); + *error_arc.lock().unwrap() = Some(error_msg); return; } }; @@ -50,7 +53,9 @@ pub async fn start_capture( let mut audio_client = match device.get_iaudioclient() { Ok(client) => client, Err(e) => { - eprintln!("Failed to get audio client: {}", e); + let error_msg = format!("Failed to get audio client: {}", e); + eprintln!("{}", error_msg); + *error_arc.lock().unwrap() = Some(error_msg); return; } }; @@ -58,7 +63,9 @@ pub async fn start_capture( let mix_format = match audio_client.get_mixformat() { Ok(format) => format, Err(e) => { - eprintln!("Failed to get mix format: {}", e); + let error_msg = format!("Failed to get mix format: {}", e); + eprintln!("{}", error_msg); + *error_arc.lock().unwrap() = Some(error_msg); return; } }; @@ -76,20 +83,26 @@ pub async fn start_capture( }; if let Err(e) = audio_client.initialize_client(&mix_format, &Direction::Capture, &stream_mode) { - eprintln!("Failed to initialize audio client: {}", e); + let error_msg = format!("Failed to initialize audio client: {}", e); + eprintln!("{}", error_msg); + *error_arc.lock().unwrap() = Some(error_msg); return; } let capture_client = match audio_client.get_audiocaptureclient() { Ok(client) => client, Err(e) => { - eprintln!("Failed to get capture client: {}", e); + let error_msg = format!("Failed to get capture client: {}", e); + eprintln!("{}", error_msg); + *error_arc.lock().unwrap() = Some(error_msg); return; } }; if let Err(e) = audio_client.start_stream() { - eprintln!("Failed to start stream: {}", e); + let error_msg = format!("Failed to start stream: {}", e); + eprintln!("{}", error_msg); + *error_arc.lock().unwrap() = Some(error_msg); return; } @@ -176,13 +189,18 @@ pub async fn stop_capture(state: &AudioCaptureState) -> Result { // Wait a bit for capture to stop tokio::time::sleep(tokio::time::Duration::from_millis(500)).await; + // Check if there was an error during capture + if let Some(error) = state.error.lock().unwrap().as_ref() { + return Err(error.clone()); + } + // Get samples let samples = state.samples.lock().unwrap().clone(); let sample_rate = *state.sample_rate.lock().unwrap(); let channels = *state.channels.lock().unwrap(); if samples.is_empty() { - return Err("No audio samples captured".to_string()); + return Err("No audio samples captured. Make sure audio is playing on your system during recording.".to_string()); } // Convert to WAV