Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
88 changes: 65 additions & 23 deletions Sources/Fluid/ContentView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -2949,12 +2949,14 @@ struct ContentView: View {
self.menuBarManager.showRecordingOverlayImmediately()
}

if !self.isRecordingForCommand, !self.isRecordingForRewrite {
TranscriptionSoundPlayer.shared.playStartSound()
}
let shouldPlayStartSound = !self.isRecordingForCommand && !self.isRecordingForRewrite

Task {
await self.asr.start()
await self.asr.start(beforeCaptureEnabled: {
if shouldPlayStartSound {
await self.playTranscriptionStartSoundBeforeCapture()
}
})
if !self.asr.isRunning {
self.menuBarManager.hideRecordingOverlayImmediately(reason: "asr_start_failed")
}
Expand Down Expand Up @@ -3167,7 +3169,7 @@ struct ContentView: View {
"ContentView: selected model for dictate hotkey=\(SettingsStore.shared.selectedSpeechModel.displayName)",
source: "ContentView"
)
self.beginDictationRecording(for: .primary, mode: .dictate)
await self.beginDictationRecording(for: .primary, mode: .dictate)
},
stopAndProcessCallback: {
let route = self.currentDictationOutputRouteForHotkeyStop()
Expand All @@ -3176,11 +3178,11 @@ struct ContentView: View {
},
promptModeCallback: {
DebugLogger.shared.info("Prompt mode triggered", source: "ContentView")
self.beginDictationRecording(for: .secondary, mode: .promptMode)
await self.beginDictationRecording(for: .secondary, mode: .promptMode)
},
promptSelectionCallback: { selection in
DebugLogger.shared.info("Prompt selection shortcut triggered", source: "ContentView")
self.beginDictationRecording(for: selection, mode: .promptMode)
await self.beginDictationRecording(for: selection, mode: .promptMode)
},
commandModeCallback: {
DebugLogger.shared.info("Command mode triggered", source: "ContentView")
Expand All @@ -3199,9 +3201,10 @@ struct ContentView: View {
"Starting voice recording for command",
source: "ContentView"
)
TranscriptionSoundPlayer.shared.playStartSound()
Task {
await self.asr.start()
await self.asr.start(beforeCaptureEnabled: {
await self.playTranscriptionStartSoundBeforeCapture()
})
}
},
rewriteModeCallback: {
Expand Down Expand Up @@ -3234,9 +3237,10 @@ struct ContentView: View {

// Start recording immediately for the edit instruction
DebugLogger.shared.info("Starting voice recording for edit mode", source: "ContentView")
TranscriptionSoundPlayer.shared.playStartSound()
Task {
await self.asr.start()
await self.asr.start(beforeCaptureEnabled: {
await self.playTranscriptionStartSoundBeforeCapture()
})
}
},
isDictateRecordingProvider: {
Expand Down Expand Up @@ -3532,7 +3536,7 @@ extension ContentView {
}
}

private func beginDictationRecording(for slot: SettingsStore.DictationShortcutSlot, mode: ActiveRecordingMode) {
private func beginDictationRecording(for slot: SettingsStore.DictationShortcutSlot, mode: ActiveRecordingMode) async {
DebugLogger.shared.debug("Begin dictation recording for slot \(slot.rawValue)", source: "ContentView")
self.appBench("begin_recording slot=\(slot.rawValue) mode=\(mode.rawValue)")
if self.isOnboardingVoicePlaygroundStepActive {
Expand All @@ -3542,44 +3546,82 @@ extension ContentView {
self.settings.playgroundUsed = false
self.playgroundUsed = false
}
self.appBench("capture_context_start")
self.captureRecordingContext()
self.applyDictationPromptConfiguration(for: SettingsStore.shared.dictationPromptSelection(for: slot))
self.appBench("capture_context_end")
self.appBench("pre_asr_state_start")
self.applyDictationShortcutSelectionContext(for: slot)
self.setActiveRecordingMode(mode)
self.rewriteModeService.clearState()
self.appBench("pre_asr_state_end")

self.appBench("prompt_config_start")
self.applyDictationPromptConfiguration(for: SettingsStore.shared.dictationPromptSelection(for: slot))
self.appBench("prompt_config_end")
self.appBench("overlay_mode_request mode=Dictation")
self.menuBarManager.setOverlayMode(.dictation)
self.menuBarManager.showRecordingOverlayImmediately()
self.appBench("overlay_mode_requested mode=Dictation")
self.prewarmPrivateAIDictationIfNeeded(for: slot)

guard !self.asr.isRunning else {
let wasAlreadyRunning = self.asr.isRunning
if wasAlreadyRunning {
self.appBench("asr_start_skipped reason=already_running")
return
}
if SettingsStore.shared.enableTranscriptionSounds {
TranscriptionSoundPlayer.shared.playStartSound()
}
Task {

if !wasAlreadyRunning {
let asrStartStartedAt = ProcessInfo.processInfo.systemUptime
DebugLogger.shared.benchmark("APP_BENCH", message: "asr_start_call", source: "AppBenchmark")
await self.asr.start()
await self.asr.start(beforeCaptureEnabled: {
await self.playTranscriptionStartSoundBeforeCapture(logBenchmarks: true)
})
if !self.asr.isRunning {
self.appBench("asr_start_failed")
self.menuBarManager.hideRecordingOverlayImmediately(reason: "asr_start_failed")
return
}
DebugLogger.shared.benchmark(
"APP_BENCH",
message: "asr_start_return elapsedMs=\(Int(((ProcessInfo.processInfo.systemUptime - asrStartStartedAt) * 1000).rounded()))",
source: "AppBenchmark"
)
}

self.appBench("prewarm_private_ai_start")
self.prewarmPrivateAIDictationIfNeeded(for: slot)
self.appBench("prewarm_private_ai_end")
}

private func beginDictationRecording(for selection: SettingsStore.DictationPromptSelection, mode: ActiveRecordingMode) {
private func beginDictationRecording(for selection: SettingsStore.DictationPromptSelection, mode: ActiveRecordingMode) async {
let settings = SettingsStore.shared
settings.setDictationPromptSelection(selection, for: .secondary)
self.applyDictationPromptConfiguration(for: selection)
self.beginDictationRecording(for: .secondary, mode: mode)
await self.beginDictationRecording(for: .secondary, mode: mode)
}

private func playTranscriptionStartSoundBeforeCapture(logBenchmarks: Bool = false) async {
guard SettingsStore.shared.enableTranscriptionSounds else { return }

if logBenchmarks {
self.appBench("start_sound_start")
}

let duration = TranscriptionSoundPlayer.shared.playStartSound()
let gateSeconds = min(max(duration + 0.04, 0), 1.0)
if logBenchmarks {
DebugLogger.shared.benchmark(
"APP_BENCH",
message: "start_sound_played durationMs=\(Int((duration * 1000).rounded())) gateMs=\(Int((gateSeconds * 1000).rounded()))",
source: "AppBenchmark"
)
}

if gateSeconds > 0 {
try? await Task.sleep(nanoseconds: UInt64(gateSeconds * 1_000_000_000))
}

if logBenchmarks {
self.appBench("start_sound_gate_done")
}
}

private func applyDictationPromptConfiguration(for selection: SettingsStore.DictationPromptSelection) {
Expand Down
Loading
Loading