From d28f421ea3c2bb6512a5ef030cc62c96a3a327d6 Mon Sep 17 00:00:00 2001 From: Chris Kaczor Date: Tue, 18 Aug 2026 15:36:01 -0400 Subject: [PATCH] Try hooking up talking state to mute state --- AudioDevice.cs | 10 +++++----- AudioWatcher.cs | 30 ++++++++++++++++++++---------- LightController.cs | 10 ++++++---- 3 files changed, 31 insertions(+), 19 deletions(-) diff --git a/AudioDevice.cs b/AudioDevice.cs index d782a18..106a33b 100644 --- a/AudioDevice.cs +++ b/AudioDevice.cs @@ -13,8 +13,6 @@ internal class AudioDevice : IAudioSessionEventsHandler private readonly string _friendlyName; private readonly Dictionary _sessions = new(); - private bool _muted; - public delegate void AudioSessionsChangedDelegate(); public event AudioSessionsChangedDelegate AudioSessionsChanged; @@ -24,9 +22,9 @@ internal class AudioDevice : IAudioSessionEventsHandler _logger = Log.ForContext(); _friendlyName = device.DeviceFriendlyName; - _muted = device.AudioEndpointVolume.Mute; + IsMuted = device.AudioEndpointVolume.Mute; - _logger.Information("AudioDevice: {name} {muted}", _friendlyName, _muted); + _logger.Information("AudioDevice: {name} {muted}", _friendlyName, IsMuted); device.AudioEndpointVolume.OnVolumeNotification += AudioEndpointVolume_OnVolumeNotification; device.AudioSessionManager.AudioSessionControl.RegisterEventClient(this); @@ -45,7 +43,7 @@ internal class AudioDevice : IAudioSessionEventsHandler { _logger.Information("AudioEndpointVolume_OnVolumeNotification: {name} {muted}", _friendlyName, data.Muted); - _muted = data.Muted; + IsMuted = data.Muted; } private void AudioSessionManager_OnSessionCreated(object sender, IAudioSessionControl newSession) @@ -69,6 +67,8 @@ internal class AudioDevice : IAudioSessionEventsHandler public int ActiveSessionCount => _sessions.Values.Count(s => s.State == AudioSessionState.AudioSessionStateActive); + public bool IsMuted { get; private set; } + void IAudioSessionEventsHandler.OnVolumeChanged(float volume, bool isMuted) { _logger.Information("OnVolumeChanged: {name} {volume} {isMuted}", _friendlyName, volume, isMuted); diff --git a/AudioWatcher.cs b/AudioWatcher.cs index 68eaac7..907aa0d 100644 --- a/AudioWatcher.cs +++ b/AudioWatcher.cs @@ -1,20 +1,26 @@ using NAudio.CoreAudioApi; using NAudio.CoreAudioApi.Interfaces; -using System.Collections.Generic; -using System.Linq; using Serilog; +using System.Collections.Generic; namespace WorkIndicator; +internal enum MicrophoneStatus +{ + NotUsed, + UsedMuted, + UsedNotMuted +} + internal class AudioWatcher : IMMNotificationClient { private readonly ILogger _logger = Log.ForContext(); private readonly MMDeviceEnumerator _deviceEnumerator = new(); private readonly Dictionary _inputDevices = new(); - public delegate void MicrophoneInUseChangedDelegate(bool microphoneInUse); + public delegate void MicrophoneStatusChangedDelegate(MicrophoneStatus microphoneStatus); - public event MicrophoneInUseChangedDelegate MicrophoneInUseChanged; + public event MicrophoneStatusChangedDelegate MicrophoneStatusChanged; public void Start() { @@ -43,12 +49,12 @@ internal class AudioWatcher : IMMNotificationClient _inputDevices[captureDevice.ID] = audioDevice; - MicrophoneInUseChanged?.Invoke(MicrophoneInUse()); + MicrophoneStatusChanged?.Invoke(GetMicrophoneStatus()); } private void AudioDevice_AudioSessionsChanged() { - MicrophoneInUseChanged?.Invoke(MicrophoneInUse()); + MicrophoneStatusChanged?.Invoke(GetMicrophoneStatus()); } private void HandleRemovedDevice(string deviceId) @@ -57,7 +63,7 @@ internal class AudioWatcher : IMMNotificationClient _inputDevices.Remove(deviceId); - MicrophoneInUseChanged?.Invoke(MicrophoneInUse()); + MicrophoneStatusChanged?.Invoke(GetMicrophoneStatus()); } public void Stop() @@ -68,11 +74,15 @@ internal class AudioWatcher : IMMNotificationClient _deviceEnumerator.Dispose(); } - public bool MicrophoneInUse() + public MicrophoneStatus GetMicrophoneStatus() { - var totalActiveSessionCount = _inputDevices.Sum(i => i.Value.ActiveSessionCount); + foreach (var inputDevice in _inputDevices.Values) + { + if (inputDevice.ActiveSessionCount > 0) + return inputDevice.IsMuted ? MicrophoneStatus.UsedMuted : MicrophoneStatus.UsedNotMuted; + } - return totalActiveSessionCount > 0; + return MicrophoneStatus.NotUsed; } void IMMNotificationClient.OnDeviceStateChanged(string deviceId, DeviceState newState) diff --git a/LightController.cs b/LightController.cs index d3ff445..4954c99 100644 --- a/LightController.cs +++ b/LightController.cs @@ -30,7 +30,7 @@ namespace WorkIndicator Properties.Settings.Default.PropertyChanged += HandleSettingChange; - AudioWatcher.MicrophoneInUseChanged += AudioWatcher_MicrophoneInUseChanged; + AudioWatcher.MicrophoneStatusChanged += AudioWatcher_MicrophoneStatusChanged; AudioWatcher.Start(); _initialized = true; @@ -50,7 +50,7 @@ namespace WorkIndicator UpdateLights(); } - private static void AudioWatcher_MicrophoneInUseChanged(bool microphoneInUse) + private static void AudioWatcher_MicrophoneStatusChanged(MicrophoneStatus microphoneStatus) { UpdateLights(); } @@ -90,9 +90,11 @@ namespace WorkIndicator if (status == Status.Auto) { - if (AudioWatcher.MicrophoneInUse()) + var microphoneStatus = AudioWatcher.GetMicrophoneStatus(); + + if (microphoneStatus != MicrophoneStatus.NotUsed) { - status = Status.OnPhone; + status = microphoneStatus == MicrophoneStatus.UsedMuted ? Status.OnPhone : Status.Talking; } else {