using Midi; using Midi.Devices; using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Net; using System.Net.Sockets; using System.Text; using System.Text.Encodings.Web; using System.Text.Json; using System.Text.Unicode; using System.Threading; namespace VirtualDJ_MidiDeviceBridge { internal static class Globals { public static string ConfigPath = ""; public static MidiConfig Config = MidiConfig.GetDefaultConfig(); public static bool ShiftKeyHeld = false; public static IInputDevice MidiInDevice = null; public static IOutputDevice MidiOutDevice = null; public static object UdpLock = new object(); public static UdpClient UdpClient = new UdpClient(); public static FileSystemWatcher configWatcher = null; static Globals() { UdpClient.Client.SendTimeout = 100; UdpClient.Client.ReceiveTimeout = 100; } public static void UserReadConfig() { try { if (File.Exists(ConfigPath)) { string json = File.ReadAllText(ConfigPath); Config = JsonSerializer.Deserialize(json); } else { Console.WriteLine($"Path doesn't point to a file. Press enter to create a default config file at '{ConfigPath}'"); Console.ReadKey(); File.WriteAllBytes(ConfigPath, JsonSerializer.SerializeToUtf8Bytes(Config, new JsonSerializerOptions { WriteIndented = true, Encoder = JavaScriptEncoder.Create(UnicodeRanges.All) })); Console.WriteLine("Wrote default config!"); } } catch { Console.WriteLine("Failed to read config file!"); } } public static void StartConfigWatcher() { configWatcher = new FileSystemWatcher { Path = Path.GetDirectoryName(Path.GetFullPath(ConfigPath)), Filter = Path.GetFileName(Path.GetFullPath(ConfigPath)), NotifyFilter = NotifyFilters.LastWrite }; configWatcher.Changed += ConfigWatcher_Changed; configWatcher.EnableRaisingEvents = true; } private static void ConfigWatcher_Changed(object sender, FileSystemEventArgs e) { if (e.ChangeType != WatcherChangeTypes.Changed) return; Thread.Sleep(100); UserReadConfig(); Console.WriteLine("Config reloaded!"); } public static string SendCommand(string cmd) { lock (UdpLock) { IPEndPoint remote = new IPEndPoint(IPAddress.Loopback, 54000); //Console.WriteLine($"Sending message: {message}"); byte[] data = Encoding.ASCII.GetBytes(cmd); UdpClient.Send(data, data.Length, remote); data = UdpClient.Receive(ref remote); string result = Encoding.ASCII.GetString(data); //Console.WriteLine($"Received message: {result}"); if (result.Contains("Error")) { Console.WriteLine($"Command resulted in error!"); Console.WriteLine($"Command: {cmd}"); Console.WriteLine($"Error: {result}"); } return result; } } public static void UserSelectDevice() { DeviceManager.UpdateInputDevices(); DeviceManager.UpdateOutputDevices(); Console.WriteLine("Devices: "); int index = 0; foreach(var device in DeviceManager.InputDevices) { Console.WriteLine($"\t{device.Name} [{index}]"); index++; } Console.WriteLine(); while (true) { Console.Write("Please select a device: "); int selectedIndex; if (!Int32.TryParse(Console.ReadLine(), out selectedIndex)) { Console.WriteLine("Not a number"); continue; } if (selectedIndex < 0 || selectedIndex > DeviceManager.InputDevices.Count - 1) { Console.WriteLine($"Invalid index {selectedIndex}"); continue; } MidiInDevice = DeviceManager.InputDevices[selectedIndex]; MidiOutDevice = DeviceManager.OutputDevices.Where(dev => dev.Name == MidiInDevice.Name).FirstOrDefault(); Console.Write($"Trying to claim device {MidiInDevice.Name}... "); try { MidiInDevice.Open(); MidiOutDevice.Open(); } catch { Console.WriteLine("Failed! Is the device busy?"); continue; } MidiOutDevice.SendSysEx(new byte[] { 0x90, 0x20, 0x00 }); Console.WriteLine("Success!"); break; } } } }