Cross Platform Application to allow control with a MIDI controller
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

86 lines
3.3 KiB

// 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<IControllable> Controllables => CreateControllables();
private List<IControllable> CreateControllables()
{
MMDeviceEnumerator deviceEnumerator = new();
MMDeviceCollection? audioDevices = deviceEnumerator.EnumerateAudioEndPoints(DataFlow.All, DeviceState.Active);
List<IControllable> controllables = new();
controllables.AddRange(audioDevices.Select(a => _controllableFactory.Create(a.AudioEndpointVolume, 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(idSessions, 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);
}
}
}