1 /+ 2 Copyright Elias Batek 2017 - 2018. 3 Distributed under the Boost Software License, Version 1.0. 4 (See accompanying file LICENSE_1_0.txt or copy at 5 https://www.boost.org/LICENSE_1_0.txt) 6 +/ 7 module midigamepad.shell.tui; 8 9 import core.thread; 10 import core.sys.windows.mmsystem : HMIDIIN, midiInStart, MIM_OPEN, MMRESULT, 11 MMSYSERR_NOERROR; 12 13 //import core.sys.windows.winuser; 14 import std.conv : ConvException, to; 15 import std.file : exists; 16 import std.json : JSONException; 17 import std.stdio; 18 import std.string : chomp; 19 20 import midigamepad.lib.keyboard; 21 import midigamepad.lib.midi.input; 22 import midigamepad.lib.translation; 23 import midigamepad.shell.program : runMIDIGamePad; 24 import midigamepad.shell.texts; 25 26 /++ 27 Launches MIDI GamePad's text-based user interface (TUI) 28 29 NOTE: At the moment it's not a real TUI 30 +/ 31 int launchTUI() 32 { 33 printHeader(); 34 35 MIDIDeviceInfo selectedDevice = void; 36 MappingsCollection mappings = void; 37 38 while (true) 39 { 40 const uint devicesCount = getMIDIInputDevicesCount(); 41 42 if (devicesCount == 0) 43 { 44 // No suitable devices connected 45 writeln("E:\tNo MIDI Input Devices connected.\n\tExiting... :("); 46 return 1; 47 } 48 49 write("MIDI Input Devices connected: "); 50 writeln(devicesCount); 51 52 if (devicesCount == 1) 53 { 54 // Only 1 suitable devices connected, skipping selection 55 selectedDevice = getMIDIInputDeviceInfo(0); 56 break; 57 } 58 59 // Retrieving all suitable devices 60 // Repeat this every iteration because the user might have (dis-)connected a device 61 MIDIDeviceInfo[] devices = getAllMIDIInputDevices(); 62 63 foreach (dev; devices) 64 { 65 write(dev.id); 66 write(" ... "); 67 writeln(dev.name); 68 } 69 70 write("Select the input device to use [0]: "); 71 write(" $> "); 72 73 uint selection = 0; 74 75 const string userInput = readln().chomp; 76 77 if (userInput.length == 0) 78 { 79 // Empty selection, use default 80 selectedDevice = devices[0]; 81 } 82 else 83 { 84 try 85 { 86 selection = userInput.to!uint(); 87 } 88 catch (ConvException) 89 { 90 writeln("\nE:\tInvalid device selection :(\n"); 91 } 92 93 if (selection >= devicesCount) 94 { 95 // invalid number (no such device) 96 writeln("\nE:\tUnknown device :(\n"); 97 } 98 } 99 100 selectedDevice = devices[selection]; 101 break; 102 } 103 104 // Show the selection 105 write("\nSelected device:\t("); 106 write(selectedDevice.id); 107 write(") "); 108 writeln(selectedDevice.name); 109 110 while (true) 111 { 112 writeln("\nWhich mappings file should be loaded: "); 113 write(" $> "); 114 immutable string selectedMappingsFile = readln().chomp; 115 116 if (!selectedMappingsFile.exists) 117 { 118 writeln("\nE:\tCannot find the specified path :(\n"); 119 continue; 120 } 121 122 try 123 { 124 mappings = parseFile(selectedMappingsFile); 125 writeln("Mappings file successfully loaded :D\n"); 126 break; 127 } 128 catch (MappingsParserException ex) 129 { 130 writeln(); 131 printMappingsParserException(ex); 132 writeln("\n"); 133 continue; 134 } 135 } 136 137 writeln("Bootstrapping ..."); 138 return runMIDIGamePad(selectedDevice, mappings, true); 139 }