Files
WorkIndicator/AudioWatcher.cs
T
2026-08-18 12:18:31 -04:00

111 lines
3.3 KiB
C#

using NAudio.CoreAudioApi;
using NAudio.CoreAudioApi.Interfaces;
using System.Collections.Generic;
using System.Linq;
using Serilog;
namespace WorkIndicator;
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 MicrophoneInUseChangedDelegate(bool microphoneInUse);
public event MicrophoneInUseChangedDelegate MicrophoneInUseChanged;
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;
MicrophoneInUseChanged?.Invoke(MicrophoneInUse());
}
private void AudioDevice_AudioSessionsChanged()
{
MicrophoneInUseChanged?.Invoke(MicrophoneInUse());
}
private void HandleRemovedDevice(string deviceId)
{
_logger.Information("Device removed: {id}", deviceId);
_inputDevices.Remove(deviceId);
MicrophoneInUseChanged?.Invoke(MicrophoneInUse());
}
public void Stop()
{
_logger.Information("Stop");
_deviceEnumerator.UnregisterEndpointNotificationCallback(this);
_deviceEnumerator.Dispose();
}
public bool MicrophoneInUse()
{
var totalActiveSessionCount = _inputDevices.Sum(i => i.Value.ActiveSessionCount);
return totalActiveSessionCount > 0;
}
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);
}
}