// Author: Gockner, Simon // Created: 2021-04-08 // Copyright(c) 2021 SimonG. All Rights Reserved. using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using Lib.Audio.Factories; using Lib.Audio.Interfaces; using NAudio.CoreAudioApi; using NAudio.CoreAudioApi.Interfaces; namespace Lib.Audio { public class ControllableCollector : IControllableCollector { private readonly IControllableFactory _controllableFactory; public ControllableCollector(IControllableFactory controllableFactory) => _controllableFactory = controllableFactory; public List Controllables => CreateControllables(); private List CreateControllables() { MMDeviceEnumerator deviceEnumerator = new(); MMDeviceCollection? audioDevices = deviceEnumerator.EnumerateAudioEndPoints(DataFlow.All, DeviceState.Active); List controllables = new(); controllables.AddRange(audioDevices.Select(a => _controllableFactory.Create(a.AudioSessionManager.AudioSessionControl, a.FriendlyName))); Dictionary> sessionsById = new(); foreach (var audioDevice in audioDevices) { SessionCollection sessions = audioDevice.AudioSessionManager.Sessions; for (int i = 0; i < sessions.Count; i++) { AudioSessionControl session = sessions[i]; if (session.State == AudioSessionState.AudioSessionStateExpired) continue; string searchIdentifier = session.GetSessionIdentifier[(session.GetSessionIdentifier.IndexOf("|", StringComparison.Ordinal) + 1)..]; if (!sessionsById.ContainsKey(searchIdentifier)) sessionsById[searchIdentifier] = new List(); sessionsById[searchIdentifier].Add(session); } } foreach (var id in sessionsById.Keys.ToList()) { List idSessions = sessionsById[id]; (Process? process, AudioSessionControl? audioSessionControl) = FindProcess(idSessions); if (audioSessionControl == null || process == default && !idSessions.Any(s => s.IsSystemSoundsSession)) continue; string name; if (idSessions.Any(s => s.IsSystemSoundsSession)) name = "System Sounds"; else if (process != null) name = process.ProcessName; else name = id; controllables.Add(_controllableFactory.Create(audioSessionControl, name)); } return controllables; } private (Process? process, AudioSessionControl? session) FindProcess(List sessions) { try { foreach (var session in sessions) return (Process.GetProcessById((int) session.GetProcessID), session); } catch (ArgumentException) { } return (null, null); } } }