diff --git a/UI24RBridgeTest/Program.cs b/UI24RBridgeTest/Program.cs index d0b9e9c..a0ef1df 100644 --- a/UI24RBridgeTest/Program.cs +++ b/UI24RBridgeTest/Program.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; using System.IO; +using System.Linq; using UI24RController; using UI24RController.MIDIController; @@ -26,7 +27,7 @@ static void Main(string[] args) var controllersSetting = new List(); configuration.GetSection("MidiControllers").Bind(controllersSetting); - + var address = configuration["UI24R-Url"]; var midiInputDevice = configuration["MIDI-Input-Name"]; var midiOutputDevice = configuration["MIDI-Output-Name"]; @@ -55,7 +56,7 @@ static void Main(string[] args) { controllerSecond = MIDIControllerFactory.GetMidiController(protocol); } - + if (args.Length > 0) WriteMIDIDeviceNames(controller); else @@ -156,7 +157,7 @@ static void Main(string[] args) Console.WriteLine("Start bridge..."); BridgeSettings settings = new BridgeSettings(address, messageWriter); - + if (syncID != null) { settings.SyncID = syncID; @@ -251,27 +252,42 @@ static void Main(string[] args) } } } - + } } } + private static string PromptDeviceChoice(string promptText, IEnumerable deviceNames) + { + var nameList = deviceNames.ToList(); + + AnsiConsole.WriteLine(promptText); + for (int i = 0; i < nameList.Count; i++) + AnsiConsole.MarkupLine($" [blue][[{i + 1}]][/]: {nameList[i]}"); + + int chosen = AnsiConsole.Prompt( + new TextPrompt("Enter number:") + .DefaultValue(1) + .Validate(n => n >= 1 && n <= nameList.Count + ? ValidationResult.Success() + : ValidationResult.Error($"Please enter a number between 1 and {nameList.Count}"))); + + return nameList[chosen - 1]; + } private static void CreateAppsettings(string fileName) { var controller = MIDIControllerFactory.GetMidiController("MC"); var inputDevicenames = controller.GetInputDeviceNames(); var outputDevicenames = controller.GetOutputDeviceNames(); - + AnsiConsole.WriteLine("appsettings.json is not found."); AnsiConsole.WriteLine("Creating of the configuration file is starting."); var address = AnsiConsole.Ask(@"Please write the mixer address (eg: ws:\\192.168.3.12): "); //"UI24R-Url" - var midiInputDevice = AnsiConsole.Prompt( - new TextPrompt("Choose primary input device. (It is case sensitive.)") - .AddChoices(inputDevicenames)); //configuration["MIDI-Input-Name"]; + var midiInputDevice = PromptDeviceChoice( + "Choose primary input device:", inputDevicenames); //configuration["MIDI-Input-Name"]; - var midiOutputDevice = AnsiConsole.Prompt( - new TextPrompt("Choose primary output device. (It is case sensitive.)") - .AddChoices(outputDevicenames)); //configuration["MIDI-Output-Name"]; + var midiOutputDevice = PromptDeviceChoice( + "Choose primary output device:", outputDevicenames); //configuration["MIDI-Output-Name"]; //var primaryIsExtender = configuration["PrimaryIsExtender"] == "true"; string primaryIsExtender = "false"; @@ -290,7 +306,7 @@ private static void CreateAppsettings(string fileName) new TextPrompt("Primary controller offset (show 1-8ch: 0 9-16ch: 1") .AddChoices(["0", "1"]) .DefaultValue("0")); - + var isAddSecondaryDevice = AnsiConsole.Prompt( new TextPrompt("Do you want to add secondary device?") .AddChoice(true) @@ -304,17 +320,15 @@ private static void CreateAppsettings(string fileName) string secondaryIsExtender = "false"; string secondaryChannelStart = "1"; //var secondaryMidiInputDevice = configuration["MIDI-Input-Name-Second"]; - //var secondaryMidiOutputDevice = configuration["MIDI-Output-Name-Second"]; + //var secondaryMidiOutputDevice = configuration["MIDI-Output-Name-Second"]; //var secondaryIsExtender = configuration["SecondaryIsExtender"] == "true"; if (isAddSecondaryDevice) { - secondaryMidiInputDevice = AnsiConsole.Prompt( - new TextPrompt("Choose secondary input device. (It is case sensitive.)") - .AddChoices(inputDevicenames)); //configuration["MIDI-Input-Name"]; + secondaryMidiInputDevice = PromptDeviceChoice( + "Choose secondary input device:", inputDevicenames); //configuration["MIDI-Input-Name"]; - secondaryMidiOutputDevice = AnsiConsole.Prompt( - new TextPrompt("Choose secondary output device. (It is case sensitive.)") - .AddChoices(outputDevicenames)); //configuration["MIDI-Output-Name"]; + secondaryMidiOutputDevice = PromptDeviceChoice( + "Choose secondary output device:", outputDevicenames); //configuration["MIDI-Output-Name"]; if (AnsiConsole.Prompt( new TextPrompt("Is secondary device an extender?") @@ -370,7 +384,7 @@ private static void CreateAppsettings(string fileName) "; File.WriteAllText(fileName, settingsContent); - + } diff --git a/UI24RBridgeTest/UI24RBridgeTest.csproj b/UI24RBridgeTest/UI24RBridgeTest.csproj index a71edb6..51d84d9 100644 --- a/UI24RBridgeTest/UI24RBridgeTest.csproj +++ b/UI24RBridgeTest/UI24RBridgeTest.csproj @@ -2,7 +2,7 @@ Exe - net8.0 + net10.0 win-x64;win-x86;linux-x64 false diff --git a/UI24RController/MIDIController/BehringerUniversalMIDI.cs b/UI24RController/MIDIController/BehringerUniversalMIDI.cs index f42edc6..4e68dfa 100644 --- a/UI24RController/MIDIController/BehringerUniversalMIDI.cs +++ b/UI24RController/MIDIController/BehringerUniversalMIDI.cs @@ -86,13 +86,13 @@ public void Dispose() } } - public bool ConnectInputDevice(string deviceName) + public async Task ConnectInputDevice(string deviceName) { var access = MidiAccessManager.Default; var deviceNumber = access.Inputs.Where(i => i.Name == deviceName).FirstOrDefault(); if (deviceNumber != null) { - _input = access.OpenInputAsync(deviceNumber.Id).Result; + _input = await access.OpenInputAsync(deviceNumber.Id); _input.MessageReceived += (obj, e) => { if (e.Data.Length>2) @@ -104,7 +104,7 @@ public bool ConnectInputDevice(string deviceName) return true; } else - return false; + return false; } private void ProcessMidiMessage(MidiReceivedEventArgs e) @@ -122,13 +122,13 @@ private void ProcessMidiMessage(MidiReceivedEventArgs e) } } - public bool ConnectOutputDevice(string deviceName) + public async Task ConnectOutputDevice(string deviceName) { var access = MidiAccessManager.Default; var deviceNumber = access.Outputs.Where(i => i.Name == deviceName).FirstOrDefault(); if (deviceNumber != null) { - _output = access.OpenOutputAsync(deviceNumber.Id).Result; + _output = await access.OpenOutputAsync(deviceNumber.Id); return true; } return false; @@ -207,7 +207,7 @@ public void WriteTextToLCD(string text, int delay) throw new NotImplementedException(); } - public bool ReConnectDevice() + public async Task ReConnectDevice() { throw new NotImplementedException(); } diff --git a/UI24RController/MIDIController/IMIDIController.cs b/UI24RController/MIDIController/IMIDIController.cs index 7a67a7b..83face1 100644 --- a/UI24RController/MIDIController/IMIDIController.cs +++ b/UI24RController/MIDIController/IMIDIController.cs @@ -2,16 +2,17 @@ using System.Collections.Generic; using UI24RController; using UI24RController.MIDIController; +using System.Threading.Tasks; public interface IMIDIController { #region Connection string[] GetInputDeviceNames(); string[] GetOutputDeviceNames(); - bool ConnectInputDevice(string deviceName); - bool ConnectOutputDevice(string deviceName); + Task ConnectInputDevice(string deviceName); + Task ConnectOutputDevice(string deviceName); - bool ReConnectDevice(); + Task ReConnectDevice(); bool IsConnectionErrorOccured { get; } bool IsConnected { get; } diff --git a/UI24RController/MIDIController/MC.cs b/UI24RController/MIDIController/MC.cs index 9c2f06f..963eff7 100644 --- a/UI24RController/MIDIController/MC.cs +++ b/UI24RController/MIDIController/MC.cs @@ -4,7 +4,6 @@ using Commons.Music.Midi; using System.Linq; using System.Threading.Tasks; -using Commons.Music.Midi.RtMidi; using System.Threading; using System.Collections.Concurrent; using System.Text.RegularExpressions; @@ -38,7 +37,7 @@ public FaderState(double value) /// Store every fader setted value of the faders, key is the channel number (z in the message) /// protected ConcurrentDictionary faderValues = new ConcurrentDictionary(); - + IMidiInput _input = null; protected string _inputDeviceNumber; protected string _inputDeviceName; @@ -421,10 +420,10 @@ public void Dispose() _output.Dispose(); _output = null; } - + } - public bool ConnectInputDevice(string deviceName) + public async Task ConnectInputDevice(string deviceName) { try { @@ -433,8 +432,8 @@ public bool ConnectInputDevice(string deviceName) var deviceNumber = access.Inputs.Where(i => i.Name.ToUpper() == deviceName.ToUpper()).FirstOrDefault(); if (deviceNumber != null) { - - var input = access.OpenInputAsync(deviceNumber.Id).Result; + var input = await access.OpenInputAsync(deviceNumber.Id); + _input = input; _inputDeviceNumber = deviceNumber.Id; _input.MessageReceived += (obj, e) => @@ -459,7 +458,7 @@ public bool ConnectInputDevice(string deviceName) } return false; } - public bool ConnectOutputDevice(string deviceName) + public async Task ConnectOutputDevice(string deviceName) { try { @@ -468,7 +467,7 @@ public bool ConnectOutputDevice(string deviceName) var deviceNumber = access.Outputs.Where(i => i.Name.ToUpper() == deviceName.ToUpper()).FirstOrDefault(); if (deviceNumber != null) { - var output = access.OpenOutputAsync(deviceNumber.Id).Result; + var output = await access.OpenOutputAsync(deviceNumber.Id); _outputDeviceNumber = deviceNumber.Id; _output = output; _isConnected = true; @@ -504,10 +503,11 @@ private void StartPingThread() _pingThread.Start(); } - public bool ReConnectDevice() + public async Task ReConnectDevice() { - return ConnectInputDevice(_inputDeviceName) && - ConnectOutputDevice(_outputDeviceName); + var inputOk = await ConnectInputDevice(_inputDeviceName); + var outputOk = await ConnectOutputDevice(_outputDeviceName); + return inputOk && outputOk; } public string[] GetInputDeviceNames() @@ -531,7 +531,7 @@ protected void Send(byte[] mevent, int offset, int length, long timestamp) } } - catch + catch { OnConnectionErrorEvent(); } @@ -540,7 +540,7 @@ private void ProcessMidiMessage(MidiReceivedEventArgs e) { var message = e.Data; - if (message[0] == 0x90) //button pressed, released, fader released + if (message[0] == 0x90) //button pressed, released, fader released { if (message.MIDIEqual(0x90, 0x00, 0x00, 0xff, 0x00, 0xff) && (message[1] >= 0x68) && (message[1] <= 0x70)) //release fader (0x90 [0x68-0x70] 0x00) { @@ -795,7 +795,7 @@ private void ProcessMidiMessage(MidiReceivedEventArgs e) int lower = message[1]; // lower 7 bit var faderValue = (upper + lower) / 16383.0; - + faderValues[channelNumber].Value = faderValue; OnFaderEvent(channelNumber, faderValue); if (!faderValues[channelNumber].IsTouched) diff --git a/UI24RController/MIDIController/MackieHUI.cs b/UI24RController/MIDIController/MackieHUI.cs index 27f3b74..98411b4 100644 --- a/UI24RController/MIDIController/MackieHUI.cs +++ b/UI24RController/MIDIController/MackieHUI.cs @@ -14,7 +14,7 @@ public class MackieHUI : IMIDIController, IDisposable /// Store every fader setted value of the faders, key is the channel number (z in the message) /// protected Dictionary faderValues = new Dictionary(); - + IMidiInput _input = null; IMidiOutput _output = null; @@ -94,13 +94,13 @@ public void Dispose() } } - public bool ConnectInputDevice(string deviceName) + public async Task ConnectInputDevice(string deviceName) { var access = MidiAccessManager.Default; var deviceNumber = access.Inputs.Where(i => i.Name == deviceName).FirstOrDefault(); if (deviceNumber != null) { - _input = access.OpenInputAsync(deviceNumber.Id).Result; + _input = await access.OpenInputAsync(deviceNumber.Id); _input.MessageReceived += (obj, e) => { if (e.Data.Length>2) @@ -113,7 +113,7 @@ public bool ConnectInputDevice(string deviceName) return true; } else - return false; + return false; } private void ProcessMidiMessage() @@ -127,13 +127,13 @@ private void ProcessMidiMessage() if (firstMessage.MIDIEqual(0x90, 0x00, 0x7f)) //ping answer -> do nothing { } - else if(firstMessage.MIDIEqual(0xb0, 0x0f)&& (firstMessage[2] < 8)) //first message of: release fader + else if(firstMessage.MIDIEqual(0xb0, 0x0f)&& (firstMessage[2] < 8)) //first message of: release fader { var channelNumber = firstMessage[2]; var secondMessage = _messageQueue.Dequeue(); if (secondMessage.MIDIEqual(0xb0, 0x2f, 0x00)) //release fader { - //TODO: Send back the last fader value to the controller + //TODO: Send back the last fader value to the controller if (faderValues.ContainsKey(channelNumber)) { SetFader(channelNumber, faderValues[channelNumber]); @@ -154,7 +154,7 @@ private void ProcessMidiMessage() faderValues.AddOrSet(channelNumber, faderValue); OnFaderEvent(channelNumber, faderValue); } - } + } else if (firstMessage.MIDIEqual(0xb0, 0x0f, 0x0a)) //preset up, preset down { var secondMessage = _messageQueue.Dequeue(); @@ -171,13 +171,13 @@ private void ProcessMidiMessage() } } - public bool ConnectOutputDevice(string deviceName) + public async Task ConnectOutputDevice(string deviceName) { var access = MidiAccessManager.Default; var deviceNumber = access.Outputs.Where(i => i.Name == deviceName).FirstOrDefault(); if (deviceNumber != null) { - _output = access.OpenOutputAsync(deviceNumber.Id).Result; + _output = await access.OpenOutputAsync(deviceNumber.Id); return true; } return false; @@ -201,11 +201,11 @@ public bool SetFader(int channelNumber, double faderValue) { if (_output != null && channelNumber<8) { - //'touch fader': b0 0f 0z + //'touch fader': b0 0f 0z // b0 2f 40 - //'release fader': b0 0f 0z - // b0 2f 00 - //'move fader': b0 0z hi + //'release fader': b0 0f 0z + // b0 2f 00 + //'move fader': b0 0z hi // b0 2z lo //where z is the channel number 1-8 //hi is between 0x00-0x7f @@ -220,7 +220,7 @@ public bool SetFader(int channelNumber, double faderValue) //touch fader on channel //_output.Send(new byte[] {data0, 0x0f, z }, 0, 3, 0); //_output.Send(new byte[] { data0, 0x2f, 0x40 }, 0, 3, 0); - //move fader + //move fader _output.Send(new byte[] { data0, (byte)(0x00 + z), upper }, 0, 3, 0); _output.Send(new byte[] { data0, (byte)(0x20 + z), lower }, 0, 3, 0); faderValues.AddOrSet(z, faderValue); @@ -278,7 +278,7 @@ public void WriteTextToLCD(string text, int delay) throw new NotImplementedException(); } - public bool ReConnectDevice() + public async Task ReConnectDevice() { throw new NotImplementedException(); } diff --git a/UI24RController/UI24RBridge.cs b/UI24RController/UI24RBridge.cs index e8a0c28..379ab4b 100644 --- a/UI24RController/UI24RBridge.cs +++ b/UI24RController/UI24RBridge.cs @@ -34,10 +34,10 @@ public class UI24RBridge : IDisposable protected SelectedLayoutEnum _selectedLayout = SelectedLayoutEnum.Channels; protected bool _isReconnecting = false; - + /// /// Represent the UI24R mixer state - /// TODO: need to move every global variable that store any mixer specific state to the Mixer class (viewGroups, selectedChannel etc.) + /// TODO: need to move every global variable that store any mixer specific state to the Mixer class (viewGroups, selectedChannel etc.) /// protected Mixer _mixer = new Mixer(); @@ -107,7 +107,7 @@ public UI24RBridge(BridgeSettings settings, List controllers) } this.KnobsFunction = KnobsFunctionEnum.Gain; - + //if (!_settings.Controller.IsConnected) //{ // _midiController_ConnectionErrorEvent(this, null); @@ -137,10 +137,10 @@ private void _midiController_ConnectionErrorEvent(IMIDIController controller, Ev SendMessage("Try to reconnect....", false); if (!_isReconnecting) { - new Thread(() => + new Thread(async () => { _isReconnecting = true; - while (_isReconnecting && !controller.ReConnectDevice()) + while (_isReconnecting && !await controller.ReConnectDevice()) { Thread.Sleep(100); } @@ -179,7 +179,7 @@ private void InitializeViewGroupsFromConfig() private void Controller_TrackEvent(IMIDIController controller, EventArgs e) { - + } private void Controller_PanEvent(IMIDIController controller, EventArgs e) @@ -361,7 +361,7 @@ private void _midiController_MuteChannelEvent(IMIDIController controller, MIDICo SetControllerMuteButtonsForCurrentLayer(); } } - + private void _midiController_SelectChannelEvent(IMIDIController controller, MIDIController.ChannelEventArgs e) { var ch = _mixer.getChannelNumberInCurrentLayer(e.ChannelNumber, controller.ChannelOffset); @@ -758,8 +758,8 @@ private void _midiController_RecEvent(IMIDIController controller, EventArgs e) //these envent are public and provided to the secondary controller //if the selected channel is on the secondary controller the modified value has to be send back to the primary controller - public bool SelectedChannelIsOnCurrentLayer(int channelOffset) - { + public bool SelectedChannelIsOnCurrentLayer(int channelOffset) + { return _mixer.getCurrentLayer(channelOffset).Where(x => x == SelectedChannel).Count() > 0; } public int UserLayerEditNewChannel @@ -833,7 +833,7 @@ public void UpdateChannelOnUserLayer() _mixer.setNewUserChannelInCurrentBank(controllerPos); controller.WriteTextToChannelLCDSecondLine(controllerPos, ""); SetControllerChannelToCurrentLayerAndSend(controller, _mixer.UserLayerEditNewChannel, controllerPos); - + } } @@ -849,7 +849,7 @@ public void _midiController_WheelEvent(IMIDIController controller, MIDIControlle _mixer.findNextAvailableChannelForUserLayer(controllerPos, e.WheelDirection, otherController.ChannelOffset); controller.WriteTextToChannelLCDSecondLine(controllerPos, _mixerChannels[_mixer.UserLayerEditNewChannel].Name); } - + } //if (_secondaryBridge != null) _secondaryBridge._midiController_WheelEvent(sender, e); } @@ -871,11 +871,11 @@ private void _midiController_TapTempoEvent(IMIDIController controller, EventArgs } } - + #endregion private void InitializeChannels() - { + { _mixerChannels = new List(); for (int i=0; i<24; i++) { @@ -966,7 +966,7 @@ private void SetControllerChannelToCurrentLayerAndSend(IMIDIController controlle controller.SetSelectLed(controllerChannelNumber, false); controller.SetKnobLed(controllerChannelNumber, 0); - + controller.WriteTextToChannelLCDFirstLine(controllerChannelNumber, ""); controller.SetMuteLed(controllerChannelNumber, false); controller.SetSoloLed(controllerChannelNumber, false); @@ -1031,7 +1031,7 @@ private void SetStateLedsOnController() { controller.SetLed(_selectedLayout.ToButtonsEnum(), true); controller.WriteTextToBarsDisplay("AX" + (_selectedLayout.AuxToInt() + 1).ToString()); - } + } else if (_selectedLayout.IsFx()) { controller.SetLed(_selectedLayout.ToButtonsEnum(), true); @@ -1039,7 +1039,7 @@ private void SetStateLedsOnController() } }); - + } private void SetKnobsFunctionLedOnController() @@ -1091,7 +1091,7 @@ private void ProcessUI24Message(string text) chOnLayer.controller.SetFader(chOnLayer.controllerChannelNumber, ui24Message.FaderValue); }); } - + } break; case MessageTypeEnum.name: @@ -1359,7 +1359,7 @@ private void ProcessUI24Message(string text) private void SetMuteGroupsLeds() { UInt32 mask = _mixer.MuteMask; - _controllers.ForEach(controller => { + _controllers.ForEach(controller => { for (int i = 0; i < 6; ++i) { controller.SetLed(ButtonsEnum.MuteGroup1 + i, ((mask >> i) & 1) == 1); diff --git a/UI24RController/UI24RChannels/mixer.cs b/UI24RController/UI24RChannels/mixer.cs index bcf8d5c..32f0f74 100644 --- a/UI24RController/UI24RChannels/mixer.cs +++ b/UI24RController/UI24RChannels/mixer.cs @@ -42,7 +42,7 @@ public Mixer() private void initLayers(int startBank = 0) { - + UserLayerEdit = false; UserLayerEditNewChannel = -1; @@ -149,7 +149,7 @@ public void setChannelsToViewLayerAndPosition(int[] channels, int viewGroupNumbe _banks[2][viewGroupNumber] = channels; } - public void setChannelInLayerAndPosition(int bank, int layerNumber, int position, int channel) + public void setChannelInLayerAndPosition(int bank, int layerNumber, int position, int channel) { _banks[bank][layerNumber][position] = channel; } @@ -213,7 +213,7 @@ public int[] getCurrentLayer(int channelOffset) { if (_selectedLayer < _banks[_selectedBank].Count) { - + if (_selectedBank<2) { var selectedLayer = (_selectedLayer + channelOffset) % _numLayersPerBank; @@ -224,7 +224,7 @@ public int[] getCurrentLayer(int channelOffset) var offset = channelOffset*8; var result = _banks[_selectedBank][_selectedLayer].Skip(offset).Take(8).ToFixedLength(8,-1).Append(54); return result.ToArray(); - + } } return new int[] { 0, 1, 2, 3, 4, 5, 6, 7, 54 }; @@ -241,7 +241,7 @@ public int getChannelNumberInCurrentLayer(int ch, int channelOffset) #region Mute Group private UInt32 _muteMask; - public UInt32 MuteMask { + public UInt32 MuteMask { get { return _muteMask; @@ -300,7 +300,7 @@ public void SetMuteAll(bool value) #region Tap Tempo - private DateTime _lastTick; + private DateTime? _lastTick; private List _tempo; @@ -322,7 +322,7 @@ public int TapTempo() return -1; } - double timeDiff = (newTick - _lastTick).TotalSeconds; + double timeDiff = (newTick - _lastTick.Value).TotalSeconds; //if tick after more than 5s, clear ticks if (timeDiff > 5) diff --git a/UI24RController/UI24RController.csproj b/UI24RController/UI24RController.csproj index 7f9ad83..adea337 100644 --- a/UI24RController/UI24RController.csproj +++ b/UI24RController/UI24RController.csproj @@ -1,7 +1,7 @@  - net8.0 + net10.0