- start implementing process handling

master
Simon G 5 years ago
parent 83a7cb32b3
commit f4901660f2
  1. 37
      Lib.Audio/Channel.cs
  2. 6
      Lib.Audio/Controllable.cs
  3. 31
      Lib.Audio/ControllableCollector.cs
  4. 8
      Lib.Audio/Device.cs
  5. 3
      Lib.Audio/Factories/IChannelFactory.cs
  6. 3
      Lib.Audio/Factories/IControllableFactory.cs
  7. 2
      Lib.Audio/Factories/IDeviceFactory.cs
  8. 5
      Lib.Audio/Interfaces/IControllable.cs
  9. 3
      Lib.Audio/Interfaces/IControllableCollector.cs
  10. 1
      Lib.Audio/Lib.Audio.csproj
  11. 3
      Lib.Audio/MasterControllable.cs
  12. 2
      Mystify/MainModel.cs

@ -14,22 +14,31 @@ using Lib.Driver.Xml;
using Lib.Midi.Interfaces; using Lib.Midi.Interfaces;
using Lib.Midi.Messages; using Lib.Midi.Messages;
using Lib.Midi.Messages.Interfaces; using Lib.Midi.Messages.Interfaces;
using Lib.ProcessManaging.Interfaces;
namespace Lib.Audio namespace Lib.Audio
{ {
public class Channel : IChannel public class Channel : IChannel
{ {
private readonly IControllableCollector _controllableCollector;
private readonly IMidiCommunication _midiCommunication; private readonly IMidiCommunication _midiCommunication;
private readonly IProcessManager _processManager;
private readonly int _channelNumber; private readonly int _channelNumber;
private IMidiMessage? _acknowledgeMessage; private IMidiMessage? _acknowledgeMessage;
public Channel(XmlChannel xmlChannel, public Channel(XmlChannel xmlChannel,
IControllableCollector controllableCollector,
IMidiCommunication midiCommunication, IMidiCommunication midiCommunication,
IProcessManager processManager,
IFaderFactory faderFactory, IFaderFactory faderFactory,
IKnobFactory knobFactory, IKnobFactory knobFactory,
IButtonFactory buttonFactory) IButtonFactory buttonFactory)
{ {
_controllableCollector = controllableCollector;
_midiCommunication = midiCommunication; _midiCommunication = midiCommunication;
_processManager = processManager;
_channelNumber = xmlChannel.ChannelNumber; _channelNumber = xmlChannel.ChannelNumber;
if (xmlChannel.Fader != null) if (xmlChannel.Fader != null)
@ -47,6 +56,9 @@ namespace Lib.Audio
foreach (var button in xmlChannel.Buttons) foreach (var button in xmlChannel.Buttons)
Buttons.Add(buttonFactory.Create(button, _channelNumber)); Buttons.Add(buttonFactory.Create(button, _channelNumber));
} }
_processManager.ProcessStarted += OnProcessManagerProcessStarted;
_processManager.ProcessExited += OnProcessManagerProcessExited;
} }
public IFader? Fader { get; } public IFader? Fader { get; }
@ -137,11 +149,36 @@ namespace Lib.Audio
Controllable?.SetVolume(fader.RelativePosition); Controllable?.SetVolume(fader.RelativePosition);
} }
private void OnProcessManagerProcessStarted(object? sender, IObservedProcess process)
{
if (Controllable?.Process == null)
return;
if (!Controllable.Process.IsSameExecutable(process))
return;
Controllable = _controllableCollector.GetControllableForProcess(process);
}
private void OnProcessManagerProcessExited(object? sender, IObservedProcess process)
{
if (Controllable?.Process == null)
return;
if (!Controllable.Process.IsSameExecutable(process))
return;
Controllable.IsValid = false; //TODO: Toggle Record button led
}
public override string ToString() => $"Channel {_channelNumber}"; public override string ToString() => $"Channel {_channelNumber}";
public void Dispose() public void Dispose()
{ {
_processManager.ProcessStarted -= OnProcessManagerProcessStarted;
_processManager.ProcessExited -= OnProcessManagerProcessExited;
UnMapControllable(); UnMapControllable();
_midiCommunication.Send(new PitchWheelChangeMessage(0, _channelNumber, 0)); _midiCommunication.Send(new PitchWheelChangeMessage(0, _channelNumber, 0));
} }

@ -5,6 +5,7 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using Lib.Audio.Interfaces; using Lib.Audio.Interfaces;
using Lib.ProcessManaging.Interfaces;
using NAudio.CoreAudioApi; using NAudio.CoreAudioApi;
namespace Lib.Audio namespace Lib.Audio
@ -13,12 +14,15 @@ namespace Lib.Audio
{ {
private readonly List<AudioSessionControl> _audioSessionControls; private readonly List<AudioSessionControl> _audioSessionControls;
public Controllable(List<AudioSessionControl> audioSessionControls, string name) public Controllable(List<AudioSessionControl> audioSessionControls, IObservedProcess? process, string name)
{ {
_audioSessionControls = audioSessionControls; _audioSessionControls = audioSessionControls;
Process = process;
Name = name; Name = name;
} }
public bool IsValid { get; set; } = true;
public IObservedProcess? Process { get; }
public string Name { get; } public string Name { get; }
public string? IconPath => _audioSessionControls.FirstOrDefault(c => !string.IsNullOrEmpty(c.IconPath))?.IconPath; public string? IconPath => _audioSessionControls.FirstOrDefault(c => !string.IsNullOrEmpty(c.IconPath))?.IconPath;

@ -4,10 +4,10 @@
using System; 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 Lib.ProcessManaging.Interfaces;
using NAudio.CoreAudioApi; using NAudio.CoreAudioApi;
using NAudio.CoreAudioApi.Interfaces; using NAudio.CoreAudioApi.Interfaces;
@ -15,11 +15,20 @@ namespace Lib.Audio
{ {
public class ControllableCollector : IControllableCollector public class ControllableCollector : IControllableCollector
{ {
private readonly IProcessManager _processManager;
private readonly IControllableFactory _controllableFactory; private readonly IControllableFactory _controllableFactory;
public ControllableCollector(IControllableFactory controllableFactory) => _controllableFactory = controllableFactory; public ControllableCollector(IProcessManager processManager, IControllableFactory controllableFactory)
{
_processManager = processManager;
_controllableFactory = controllableFactory;
}
public List<IControllable> Controllables => CreateControllables(); public List<IControllable> Controllables => CreateControllables();
public IControllable? GetControllableForProcess(IObservedProcess process) =>
Controllables.FirstOrDefault(c => c.Process != null && c.Process.IsSameExecutable(process));
private List<IControllable> CreateControllables() private List<IControllable> CreateControllables()
{ {
MMDeviceEnumerator deviceEnumerator = new(); MMDeviceEnumerator deviceEnumerator = new();
@ -54,7 +63,7 @@ namespace Lib.Audio
{ {
List<AudioSessionControl> idSessions = sessionsById[id]; List<AudioSessionControl> idSessions = sessionsById[id];
(Process? process, AudioSessionControl? audioSessionControl) = FindProcess(idSessions); (IObservedProcess? process, AudioSessionControl? audioSessionControl) = FindProcess(idSessions);
if (audioSessionControl == null || process == default && !idSessions.Any(s => s.IsSystemSoundsSession)) if (audioSessionControl == null || process == default && !idSessions.Any(s => s.IsSystemSoundsSession))
continue; continue;
@ -62,25 +71,23 @@ namespace Lib.Audio
if (idSessions.Any(s => s.IsSystemSoundsSession)) if (idSessions.Any(s => s.IsSystemSoundsSession))
name = "System Sounds"; name = "System Sounds";
else if (process != null) else if (process != null)
name = process.ProcessName; name = process.Name;
else else
name = id; name = id;
controllables.Add(_controllableFactory.Create(idSessions, name)); controllables.Add(_controllableFactory.Create(idSessions, process, name));
} }
return controllables; return controllables;
} }
private (Process? process, AudioSessionControl? session) FindProcess(List<AudioSessionControl> sessions) private (IObservedProcess? process, AudioSessionControl? session) FindProcess(List<AudioSessionControl> sessions)
{ {
try foreach (var session in sessions)
{
foreach (var session in sessions)
return (Process.GetProcessById((int) session.GetProcessID), session);
}
catch (ArgumentException)
{ {
IObservedProcess? process = _processManager.GetProcessById((int) session.GetProcessID);
if (process != null)
return (process, session);
} }
return (null, null); return (null, null);

@ -20,13 +20,13 @@ namespace Lib.Audio
private readonly IMidiCommunication _midiCommunication; private readonly IMidiCommunication _midiCommunication;
private readonly IChannelFactory _channelFactory; private readonly IChannelFactory _channelFactory;
public Device(IDriver driver, IMidiCommunicationFactory midiCommunicationFactory, IChannelFactory channelFactory) public Device(IDriver driver, IControllableCollector controllableCollector, IMidiCommunicationFactory midiCommunicationFactory, IChannelFactory channelFactory)
{ {
_driver = driver; _driver = driver;
_midiCommunication = midiCommunicationFactory.Create(driver); _midiCommunication = midiCommunicationFactory.Create(driver);
_channelFactory = channelFactory; _channelFactory = channelFactory;
Channels = InitializeChannels(); Channels = InitializeChannels(controllableCollector);
_midiCommunication.MessageReceived += OnMidiCommunicationMessageReceived; _midiCommunication.MessageReceived += OnMidiCommunicationMessageReceived;
_midiCommunication.ErrorReceived += OnMidiCommunicationErrorReceived; _midiCommunication.ErrorReceived += OnMidiCommunicationErrorReceived;
@ -36,8 +36,8 @@ namespace Lib.Audio
public List<IChannel> Channels { get; } public List<IChannel> Channels { get; }
public void StartCommunication(bool useMidiView) => _midiCommunication.Open(useMidiView); public void StartCommunication(bool useMidiView) => _midiCommunication.Open(useMidiView);
private List<IChannel> InitializeChannels() => _driver.Channels == null ? new List<IChannel>() private List<IChannel> InitializeChannels(IControllableCollector controllableCollector) => _driver.Channels == null ? new List<IChannel>()
: _driver.Channels.Select(c => _channelFactory.Create(c, _midiCommunication)).ToList(); : _driver.Channels.Select(c => _channelFactory.Create(c, controllableCollector, _midiCommunication)).ToList();
private void OnMidiCommunicationMessageReceived(object? sender, IMidiMessage message) private void OnMidiCommunicationMessageReceived(object? sender, IMidiMessage message)
{ {

@ -10,6 +10,7 @@ namespace Lib.Audio.Factories
{ {
public interface IChannelFactory public interface IChannelFactory
{ {
IChannel Create(XmlChannel xmlChannel, IMidiCommunication midiCommunication); IChannel Create(XmlChannel xmlChannel, IControllableCollector controllableCollector,
IMidiCommunication midiCommunication);
} }
} }

@ -4,13 +4,14 @@
using System.Collections.Generic; using System.Collections.Generic;
using Lib.Audio.Interfaces; using Lib.Audio.Interfaces;
using Lib.ProcessManaging.Interfaces;
using NAudio.CoreAudioApi; using NAudio.CoreAudioApi;
namespace Lib.Audio.Factories namespace Lib.Audio.Factories
{ {
public interface IControllableFactory public interface IControllableFactory
{ {
IControllable Create(List<AudioSessionControl> audioSessionControls, string name); IControllable Create(List<AudioSessionControl> audioSessionControls, IObservedProcess? process, string name);
IMasterControllable Create(AudioEndpointVolume audioEndpointVolume, string name); IMasterControllable Create(AudioEndpointVolume audioEndpointVolume, string name);
} }
} }

@ -9,6 +9,6 @@ namespace Lib.Audio.Factories
{ {
public interface IDeviceFactory public interface IDeviceFactory
{ {
IDevice Create(IDriver driver); IDevice Create(IDriver driver, IControllableCollector controllableCollector);
} }
} }

@ -2,10 +2,15 @@
// Created: 2021-04-07 // Created: 2021-04-07
// Copyright(c) 2021 SimonG. All Rights Reserved. // Copyright(c) 2021 SimonG. All Rights Reserved.
using Lib.ProcessManaging.Interfaces;
namespace Lib.Audio.Interfaces namespace Lib.Audio.Interfaces
{ {
public interface IControllable public interface IControllable
{ {
bool IsValid { get; set; }
IObservedProcess? Process { get; }
string Name { get; } string Name { get; }
string? IconPath { get; } string? IconPath { get; }

@ -3,11 +3,14 @@
// Copyright(c) 2021 SimonG. All Rights Reserved. // Copyright(c) 2021 SimonG. All Rights Reserved.
using System.Collections.Generic; using System.Collections.Generic;
using Lib.ProcessManaging.Interfaces;
namespace Lib.Audio.Interfaces namespace Lib.Audio.Interfaces
{ {
public interface IControllableCollector public interface IControllableCollector
{ {
List<IControllable> Controllables { get; } List<IControllable> Controllables { get; }
IControllable? GetControllableForProcess(IObservedProcess process);
} }
} }

@ -13,6 +13,7 @@
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\Lib.Driver\Lib.Driver.csproj" /> <ProjectReference Include="..\Lib.Driver\Lib.Driver.csproj" />
<ProjectReference Include="..\Lib.Midi\Lib.Midi.csproj" /> <ProjectReference Include="..\Lib.Midi\Lib.Midi.csproj" />
<ProjectReference Include="..\Lib.ProcessManaging\Lib.ProcessManaging.csproj" />
</ItemGroup> </ItemGroup>
</Project> </Project>

@ -3,6 +3,7 @@
// Copyright(c) 2021 SimonG. All Rights Reserved. // Copyright(c) 2021 SimonG. All Rights Reserved.
using Lib.Audio.Interfaces; using Lib.Audio.Interfaces;
using Lib.ProcessManaging.Interfaces;
using NAudio.CoreAudioApi; using NAudio.CoreAudioApi;
namespace Lib.Audio namespace Lib.Audio
@ -19,6 +20,8 @@ namespace Lib.Audio
_controllableCollector = controllableCollector; _controllableCollector = controllableCollector;
} }
public bool IsValid { get; set; }
public IObservedProcess? Process { get; }
public string Name { get; } public string Name { get; }
public string? IconPath => null; public string? IconPath => null;

@ -40,8 +40,8 @@ namespace Mystify
if (driver == null) if (driver == null)
throw new Exception("Driver could not be loaded."); throw new Exception("Driver could not be loaded.");
_device = _deviceFactory.Create(driver);
_controllableCollector = _controllableCollectorFactory.Create(); _controllableCollector = _controllableCollectorFactory.Create();
_device = _deviceFactory.Create(driver, _controllableCollector);
_device.StartCommunication(UseMidiView); _device.StartCommunication(UseMidiView);
} }

Loading…
Cancel
Save