|
|
|
@ -2,18 +2,21 @@ |
|
|
|
// Created: 2021-04-08 |
|
|
|
// Created: 2021-04-08 |
|
|
|
// Copyright(c) 2021 SimonG. All Rights Reserved. |
|
|
|
// Copyright(c) 2021 SimonG. All Rights Reserved. |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
using System; |
|
|
|
using System.Collections.Generic; |
|
|
|
using System.Collections.Generic; |
|
|
|
|
|
|
|
using System.Diagnostics; |
|
|
|
using System.Linq; |
|
|
|
using System.Linq; |
|
|
|
using Lib.Audio.Factories; |
|
|
|
using Lib.Audio.Factories; |
|
|
|
using Lib.Audio.Interfaces; |
|
|
|
using Lib.Audio.Interfaces; |
|
|
|
using NAudio.CoreAudioApi; |
|
|
|
using NAudio.CoreAudioApi; |
|
|
|
|
|
|
|
using NAudio.CoreAudioApi.Interfaces; |
|
|
|
|
|
|
|
|
|
|
|
namespace Lib.Audio |
|
|
|
namespace Lib.Audio |
|
|
|
{ |
|
|
|
{ |
|
|
|
public class ControllableCollector : IControllableCollector |
|
|
|
public class ControllableCollector : IControllableCollector |
|
|
|
{ |
|
|
|
{ |
|
|
|
private readonly IControllableFactory _controllableFactory; |
|
|
|
private readonly IControllableFactory _controllableFactory; |
|
|
|
|
|
|
|
|
|
|
|
public ControllableCollector(IControllableFactory controllableFactory) => _controllableFactory = controllableFactory; |
|
|
|
public ControllableCollector(IControllableFactory controllableFactory) => _controllableFactory = controllableFactory; |
|
|
|
|
|
|
|
|
|
|
|
public List<IControllable> Controllables => CreateControllables(); |
|
|
|
public List<IControllable> Controllables => CreateControllables(); |
|
|
|
@ -22,7 +25,62 @@ namespace Lib.Audio |
|
|
|
MMDeviceEnumerator deviceEnumerator = new(); |
|
|
|
MMDeviceEnumerator deviceEnumerator = new(); |
|
|
|
MMDeviceCollection? audioDevices = deviceEnumerator.EnumerateAudioEndPoints(DataFlow.All, DeviceState.Active); |
|
|
|
MMDeviceCollection? audioDevices = deviceEnumerator.EnumerateAudioEndPoints(DataFlow.All, DeviceState.Active); |
|
|
|
|
|
|
|
|
|
|
|
return audioDevices.Select(a => _controllableFactory.Create(a.AudioSessionManager.AudioSessionControl)).ToList(); |
|
|
|
List<IControllable> controllables = new(); |
|
|
|
|
|
|
|
controllables.AddRange(audioDevices.Select(a => _controllableFactory.Create(a.AudioSessionManager.AudioSessionControl, a.FriendlyName))); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Dictionary<string, List<AudioSessionControl>> 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<AudioSessionControl>(); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
sessionsById[searchIdentifier].Add(session); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
foreach (var id in sessionsById.Keys.ToList()) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
List<AudioSessionControl> 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<AudioSessionControl> sessions) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
try |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
foreach (var session in sessions) |
|
|
|
|
|
|
|
return (Process.GetProcessById((int) session.GetProcessID), session); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
catch (ArgumentException) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return (null, null); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |