diff --git a/VoiceInk/Recorder.swift b/VoiceInk/Recorder.swift index 21faebf..2092082 100644 --- a/VoiceInk/Recorder.swift +++ b/VoiceInk/Recorder.swift @@ -34,7 +34,8 @@ class Recorder: ObservableObject { private func handleDeviceChange() async { guard !isReconfiguring else { return } isReconfiguring = true - + logger.notice("🔄 Handling device change...") + if engine != nil { let currentURL = file?.url stopRecording() @@ -43,30 +44,46 @@ class Recorder: ObservableObject { if let url = currentURL { do { try await startRecording(toOutputFile: url) - } catch {} + logger.notice("✅ Successfully restarted recording after device change.") + } catch { + logger.error("❌ Failed to restart recording after device change: \(error.localizedDescription)") + } + } else { + logger.warning("âš ī¸ No file URL available to restart recording after device change.") } } isReconfiguring = false + logger.notice("✅ Device change handled.") } private func configureAudioSession(with deviceID: AudioDeviceID) async throws { + logger.info("🔊 Configuring audio session for device ID: \(deviceID)...") try? await Task.sleep(nanoseconds: 50_000_000) do { - let format = try AudioDeviceConfiguration.configureAudioSession(with: deviceID) + _ = try AudioDeviceConfiguration.configureAudioSession(with: deviceID) try AudioDeviceConfiguration.setDefaultInputDevice(deviceID) + logger.info("✅ Audio session configured successfully.") } catch { + logger.error("❌ Failed to configure audio session: \(error.localizedDescription)") throw error } try? await Task.sleep(nanoseconds: 50_000_000) } func startRecording(toOutputFile url: URL) async throws { + deviceManager.isRecordingActive = true + logger.notice("â–ļī¸ Attempting to start recording to: \(url.lastPathComponent)") + let wasMuted = await mediaController.muteSystemAudio() let deviceID = deviceManager.getCurrentDevice() if deviceID != 0 { do { try await configureAudioSession(with: deviceID) - } catch {} + } catch { + logger.warning("âš ī¸ Failed to configure audio session for device \(deviceID), attempting to continue: \(error.localizedDescription)") + } + } else { + logger.warning("âš ī¸ No input device found (deviceID is 0). Attempting to record with default.") } engine = AVAudioEngine() @@ -160,7 +177,9 @@ class Recorder: ObservableObject { do { try engine!.start() + logger.notice("✅ Recording started successfully.") } catch { + logger.error("❌ Failed to start audio engine: \(error.localizedDescription)") await mediaController.unmuteSystemAudio() stopRecording() throw RecorderError.couldNotStartRecording @@ -168,10 +187,21 @@ class Recorder: ObservableObject { } func stopRecording() { + let wasRunning = engine != nil + defer { + deviceManager.isRecordingActive = false + engine?.stop() + engine = nil + } + + if wasRunning { + logger.notice("âšī¸ Recording stopped.") + } else { + logger.info("â„šī¸ stopRecording called, but engine was not running.") + } + audioMeter = AudioMeter(averagePower: 0, peakPower: 0) engine?.inputNode.removeTap(onBus: 0) - engine?.stop() - engine = nil file = nil NotificationCenter.default.post(name: NSNotification.Name("AudioDeviceChanged"), object: nil) Task { diff --git a/VoiceInk/Services/AudioDeviceManager.swift b/VoiceInk/Services/AudioDeviceManager.swift index 58c7d3c..f6f3828 100644 --- a/VoiceInk/Services/AudioDeviceManager.swift +++ b/VoiceInk/Services/AudioDeviceManager.swift @@ -23,6 +23,8 @@ class AudioDeviceManager: ObservableObject { @Published var prioritizedDevices: [PrioritizedDevice] = [] private var fallbackDeviceID: AudioDeviceID? + var isRecordingActive: Bool = false + static let shared = AudioDeviceManager() init() { @@ -385,7 +387,9 @@ class AudioDeviceManager: ObservableObject { } // Notify UI of changes - NotificationCenter.default.post(name: NSNotification.Name("AudioDeviceChanged"), object: nil) + if !self.isRecordingActive { + NotificationCenter.default.post(name: NSNotification.Name("AudioDeviceChanged"), object: nil) + } } } @@ -452,6 +456,9 @@ class AudioDeviceManager: ObservableObject { } private func notifyDeviceChange() { - NotificationCenter.default.post(name: NSNotification.Name("AudioDeviceChanged"), object: nil) + // Only notify if recording is not active + if !isRecordingActive { + NotificationCenter.default.post(name: NSNotification.Name("AudioDeviceChanged"), object: nil) + } } }