// Author: Gockner, Simon // Created: 2021-04-07 // Copyright(c) 2021 SimonG. All Rights Reserved. using System.Collections.Generic; using System.Linq; using Lib.Audio.Controls; using Lib.Audio.Controls.Buttons.Factories; using Lib.Audio.Controls.Buttons.Interfaces; using Lib.Audio.Controls.Factories; using Lib.Audio.Controls.Interfaces; using Lib.Audio.Interfaces; using Lib.Driver.Xml; using Lib.Midi.Interfaces; using Lib.Midi.Messages; using Lib.Midi.Messages.Interfaces; using Lib.ProcessManaging.Interfaces; namespace Lib.Audio { public class Channel : IChannel { private readonly IControllableCollector _controllableCollector; private readonly IMidiCommunication _midiCommunication; private readonly IProcessManager _processManager; private readonly int _channelNumber; private IMidiMessage? _acknowledgeMessage; public Channel(XmlChannel xmlChannel, IControllableCollector controllableCollector, IMidiCommunication midiCommunication, IProcessManager processManager, IFaderFactory faderFactory, IKnobFactory knobFactory, IButtonFactory buttonFactory) { _controllableCollector = controllableCollector; _midiCommunication = midiCommunication; _processManager = processManager; _channelNumber = xmlChannel.ChannelNumber; if (xmlChannel.Fader != null) { Fader = faderFactory.Create(xmlChannel.Fader); Fader.PositionChanged += OnFaderPositionChanged; } if (xmlChannel.Knob != null) Knob = knobFactory.Create(); if (xmlChannel.Buttons != null) { Buttons = new List(); foreach (var button in xmlChannel.Buttons) Buttons.Add(buttonFactory.Create(button, _channelNumber)); } _processManager.ProcessStarted += OnProcessManagerProcessStarted; _processManager.ProcessExited += OnProcessManagerProcessExited; } public IFader? Fader { get; } public IKnob? Knob { get; } public List? Buttons { get; } public IControllable? Controllable { get; private set; } public void MapControllable(IControllable controllable) { Controllable = controllable; ToggleSelectButtonLed(); if (Controllable.IsValid) InitializeFader(); } private void UnMapControllable() { if (Controllable == null) return; ToggleSelectButtonLed(); } public void HandleMessage(IMidiMessage message) { if (message is NoteOnMessage noteOnMessage) { if (Fader?.NoteNumber == noteOnMessage.NoteNumber) Fader.IsTouched = true; else { IButton? button = Buttons?.FirstOrDefault(b => b.NoteNumber == noteOnMessage.NoteNumber); _acknowledgeMessage = button?.Handle(Controllable, (Velocity) noteOnMessage.Velocity); } } else if (message is NoteMessage noteMessage) { if (Fader?.NoteNumber == noteMessage.NoteNumber) { Fader.IsTouched = false; _acknowledgeMessage = new PitchWheelChangeMessage(0, _channelNumber, Fader.Position); } else { IButton? button = Buttons?.FirstOrDefault(b => b.NoteNumber == noteMessage.NoteNumber); _acknowledgeMessage = button?.Handle(Controllable, (Velocity) noteMessage.Velocity); } } else if (message is PitchWheelChangeMessage pitchWheelChangeMessage) { if (Fader != null) Fader.Position = pitchWheelChangeMessage.Pitch; } } public void SendAcknowledge() { if (_acknowledgeMessage == null) return; _midiCommunication.Send(_acknowledgeMessage); _acknowledgeMessage = null; } private void InitializeFader() { if (Fader == null || Controllable == null) return; float volume = Controllable.GetVolume(); Fader.RelativePosition = volume; _midiCommunication.Send(new PitchWheelChangeMessage(0, _channelNumber, Fader.Position)); } private void ToggleSelectButtonLed() { ISelectButton? selectButton = Buttons?.OfType().FirstOrDefault(); IMidiMessage? selectMessage = selectButton?.Select(); if (selectMessage != null) _midiCommunication.Send(selectMessage); } private void OnFaderPositionChanged(object? sender, int position) { if (sender is not IFader fader) return; Controllable?.SetVolume(fader.RelativePosition); } private void OnProcessManagerProcessStarted(object? sender, IObservedProcess process) { if (Controllable == null) return; if (!Controllable.ExecutablePath.Equals(process.FileName)) return; Controllable = _controllableCollector.GetControllableForExecutable(Controllable.ExecutablePath); if (Controllable != null) InitializeFader(); } private void OnProcessManagerProcessExited(object? sender, IObservedProcess process) { if (Controllable == null) return; if (!Controllable.ExecutablePath.Equals(process.FileName)) return; Controllable.IsValid = false; //TODO: Toggle Record button led } public override string ToString() => $"Channel {_channelNumber}"; public void Dispose() { _processManager.ProcessStarted -= OnProcessManagerProcessStarted; _processManager.ProcessExited -= OnProcessManagerProcessExited; UnMapControllable(); _midiCommunication.Send(new PitchWheelChangeMessage(0, _channelNumber, 0)); } } }