feat(clients): event sound effects + optional text-to-speech
Add audible cues and optional spoken announcements for session events (join/leave, channel + PM sent/recv, login, logout/connection-lost, mic on/off, voice-activity, PTT) across all three clients, driven off the shared C ABI vc_event stream so the mapping stays consistent. TTS is off by default; when enabled it announces events and reads message/PM bodies aloud. Master toggles + a sound-volume slider; the per-utterance voice-activity and PTT cues default off. WAVs ship from assets/sounds/. Windows (built + verified): new VoiceCat.App/Notifications/ layer (FeedbackSettings -> %AppData%\VoiceCat\feedback.json, SoundPlayerPool via System.Media.SoundPlayer, SpeechAnnouncer via Prismatoid 0.3.0, EventFeedback dispatcher); MainForm hooks; NotificationSettingsForm under Settings > Notifications; csproj adds the Prismatoid PackageRef and copies the WAVs into sounds\. macOS + iOS (written, not yet built -- needs a Mac): shared VoiceCatCore/Feedback/ (SoundEvent, EventFeedback = AVAudioPlayer pool + native AVSpeechSynthesizer, FeedbackSettings over UserDefaults); WAVs bundled via Package.swift resources (.process). Hooks in SessionState/ AppState (iOS) and MainWindowController (macOS); settings UI in SettingsView (iOS) and SettingsWindowController (macOS). No core/server code touched; ctest --preset dev unaffected. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
47
clients/windows/VoiceCat.App/Notifications/SoundEvent.cs
Normal file
47
clients/windows/VoiceCat.App/Notifications/SoundEvent.cs
Normal file
@@ -0,0 +1,47 @@
|
||||
namespace VoiceCat.App.Notifications;
|
||||
|
||||
/// <summary>
|
||||
/// The set of audible event cues. Each maps to a WAV in the app's <c>sounds\</c> folder
|
||||
/// (copied from <c>assets/sounds/</c> at build time). The same logical set is mirrored in the
|
||||
/// macOS/iOS clients so feedback stays consistent across platforms.
|
||||
/// </summary>
|
||||
public enum SoundEvent
|
||||
{
|
||||
ChannelJoin, // another user joined my channel
|
||||
ChannelLeave, // another user left my channel
|
||||
ChannelRecv, // channel text message from someone else
|
||||
ChannelSent, // channel text message I sent
|
||||
PmRecv, // private message received
|
||||
PmSent, // private message I sent
|
||||
Login, // connected / authenticated
|
||||
Logout, // clean disconnect
|
||||
ConnectionLost, // unexpected disconnect
|
||||
VoiceOn, // my microphone stream started
|
||||
VoiceOff, // my microphone stream stopped
|
||||
VaStart, // my voice-activity began (off by default)
|
||||
VaStop, // my voice-activity ended (off by default)
|
||||
Ptt, // push-to-talk engaged (off by default)
|
||||
}
|
||||
|
||||
internal static class SoundEventExtensions
|
||||
{
|
||||
/// <summary>WAV file name (without directory) for each event, matching assets/sounds/.</summary>
|
||||
public static string FileName(this SoundEvent ev) => ev switch
|
||||
{
|
||||
SoundEvent.ChannelJoin => "channel_join.wav",
|
||||
SoundEvent.ChannelLeave => "channel_leave.wav",
|
||||
SoundEvent.ChannelRecv => "channel_recv.wav",
|
||||
SoundEvent.ChannelSent => "channel_sent.wav",
|
||||
SoundEvent.PmRecv => "pm_recv.wav",
|
||||
SoundEvent.PmSent => "pm_sent.wav",
|
||||
SoundEvent.Login => "login.wav",
|
||||
SoundEvent.Logout => "logout.wav",
|
||||
SoundEvent.ConnectionLost => "connection_lost.wav",
|
||||
SoundEvent.VoiceOn => "voice_on.wav",
|
||||
SoundEvent.VoiceOff => "voice_off.wav",
|
||||
SoundEvent.VaStart => "va_start.wav",
|
||||
SoundEvent.VaStop => "va_stop.wav",
|
||||
SoundEvent.Ptt => "ptt.wav",
|
||||
_ => throw new ArgumentOutOfRangeException(nameof(ev), ev, null),
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user