Files
WorkIndicator/AudioWatcher.cs
T
ckaczor d28f421ea3
Deploy to Gitea Releases / deploy-to-gitea-releases (push) Successful in 34s
Try hooking up talking state to mute state
2026-08-18 15:36:01 -04:00

121 lines
3.6 KiB
C#

using NAudio.CoreAudioApi;
using NAudio.CoreAudioApi.Interfaces;
using Serilog;
using System.Collections.Generic;
namespace WorkIndicator;
internal enum MicrophoneStatus
{
NotUsed,
UsedMuted,
UsedNotMuted
}
internal class AudioWatcher : IMMNotificationClient
{
private readonly ILogger _logger = Log.ForContext<AudioWatcher>();
private readonly MMDeviceEnumerator _deviceEnumerator = new();
private readonly Dictionary<string, AudioDevice> _inputDevices = new();
public delegate void MicrophoneStatusChangedDelegate(MicrophoneStatus microphoneStatus);
public event MicrophoneStatusChangedDelegate MicrophoneStatusChanged;
public void Start()
{
_logger.Information("Start");
_deviceEnumerator.RegisterEndpointNotificationCallback(this);
_logger.Information("Getting capture devices");
var captureDevices = _deviceEnumerator.EnumerateAudioEndPoints(DataFlow.Capture, DeviceState.Active);
foreach (var captureDevice in captureDevices)
{
_logger.Information("Capture device: {name}", captureDevice.DeviceFriendlyName);
HandleAddedDevice(captureDevice);
}
}
private void HandleAddedDevice(MMDevice captureDevice)
{
_logger.Information("Device added: {name}", captureDevice.DeviceFriendlyName);
var audioDevice = new AudioDevice(captureDevice);
audioDevice.AudioSessionsChanged += AudioDevice_AudioSessionsChanged;
_inputDevices[captureDevice.ID] = audioDevice;
MicrophoneStatusChanged?.Invoke(GetMicrophoneStatus());
}
private void AudioDevice_AudioSessionsChanged()
{
MicrophoneStatusChanged?.Invoke(GetMicrophoneStatus());
}
private void HandleRemovedDevice(string deviceId)
{
_logger.Information("Device removed: {id}", deviceId);
_inputDevices.Remove(deviceId);
MicrophoneStatusChanged?.Invoke(GetMicrophoneStatus());
}
public void Stop()
{
_logger.Information("Stop");
_deviceEnumerator.UnregisterEndpointNotificationCallback(this);
_deviceEnumerator.Dispose();
}
public MicrophoneStatus GetMicrophoneStatus()
{
foreach (var inputDevice in _inputDevices.Values)
{
if (inputDevice.ActiveSessionCount > 0)
return inputDevice.IsMuted ? MicrophoneStatus.UsedMuted : MicrophoneStatus.UsedNotMuted;
}
return MicrophoneStatus.NotUsed;
}
void IMMNotificationClient.OnDeviceStateChanged(string deviceId, DeviceState newState)
{
_logger.Information("OnDeviceStateChanged: {deviceId} {newState}", deviceId, newState);
}
void IMMNotificationClient.OnDeviceAdded(string deviceId)
{
_logger.Information("OnDeviceAdded: {deviceId}", deviceId);
var device = _deviceEnumerator.GetDevice(deviceId);
if (device.DataFlow is DataFlow.Capture or DataFlow.All)
{
HandleAddedDevice(device);
}
}
void IMMNotificationClient.OnDeviceRemoved(string deviceId)
{
_logger.Information("OnDeviceRemoved: {deviceId}", deviceId);
HandleRemovedDevice(deviceId);
}
void IMMNotificationClient.OnDefaultDeviceChanged(DataFlow flow, Role role, string defaultDeviceId)
{
_logger.Information("OnDefaultDeviceChanged: {defaultDeviceId} {flow} {role}", defaultDeviceId, flow, role);
}
void IMMNotificationClient.OnPropertyValueChanged(string pwstrDeviceId, PropertyKey key)
{
_logger.Debug("OnPropertyValueChanged: {deviceId} {propertyId}", pwstrDeviceId, key.propertyId);
}
}