using System.Diagnostics; using Toak.Core; using Toak.IO; namespace Toak.Audio; public static class AudioRecorder { private static readonly string WavPath = Path.Combine(Path.GetTempPath(), "toak_recording.wav"); public static string GetWavPath() => WavPath; public static void StartRecording() { if (File.Exists(WavPath)) { Logger.LogDebug($"Deleting old audio file: {WavPath}"); File.Delete(WavPath); } Logger.LogDebug("Starting pw-record to record audio..."); var pInfo = new ProcessStartInfo { FileName = "pw-record", Arguments = $"--rate=16000 --channels=1 --format=s16 \"{WavPath}\"", UseShellExecute = false, CreateNoWindow = true, RedirectStandardOutput = true, RedirectStandardError = true }; var process = Process.Start(pInfo); if (process != null) { StateTracker.SetRecording(process.Id); Notifications.Notify("Recording Started"); } } public static void StopRecording() { var pid = StateTracker.GetRecordingPid(); if (pid.HasValue) { Logger.LogDebug($"Found active recording process with PID {pid.Value}. Attempting to stop..."); try { var process = Process.GetProcessById(pid.Value); if (!process.HasExited) { // Gracefully stop pw-record using SIGINT to ensure WAV headers are finalizing cleanly Process.Start(new ProcessStartInfo { FileName = "kill", Arguments = $"-INT {pid.Value}", CreateNoWindow = true, UseShellExecute = false })?.WaitForExit(); process.WaitForExit(2000); // give it a moment to flush } } catch (Exception ex) { // Process might already be dead Console.WriteLine($"[AudioRecorder] Error stopping pw-record: {ex.Message}"); } finally { StateTracker.ClearRecording(); } } } }