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.lib.midi.input; 8 9 import core.sys.windows.windef : LOBYTE, LOWORD, HIBYTE, HIWORD; 10 import core.sys.windows.mmsystem; 11 import std.conv : to; 12 13 import midigamepad.lib.util; 14 15 public import dplug.client.midi : MidiMessage; 16 public import midigamepad.lib.midi.device : MIDIDeviceInfo, MIDIDeviceType; 17 public import core.sys.windows.mmsystem : MIDIINCAPS, MMRESULT; 18 19 /++ 20 Opens a handle for the specified MIDI input device and starts it 21 22 Returns: 23 true on success 24 +/ 25 bool bootstrapMIDIInputDevice(uint deviceID, MidiInProc callback, 26 out HMIDIIN handle, size_t callbackData = 0) @nogc nothrow 27 { 28 if (openMIDIInputDevice(deviceID, callback, handle, callbackData) != MMSYSERR_NOERROR) 29 return false; 30 31 return startMIDIInputDevice(handle); 32 } 33 34 /++ ditto +/ 35 bool bootstrapMIDIInputDevice(MIDIDeviceInfo di, MidiInProc callback, 36 out HMIDIIN handle, size_t callbackData = 0) @nogc nothrow 37 { 38 return bootstrapMIDIInputDevice(di.id, callback, handle, callbackData); 39 } 40 41 /++ 42 Disposes the specified MIDI input device 43 44 Returns: 45 MMSYSERR_NOERROR on success 46 +/ 47 MMRESULT closeMIDIInputDevice(HMIDIIN handle) 48 { 49 return midiInClose(handle); 50 } 51 52 53 /++ 54 Returns: All connected MIDI input devices 55 +/ 56 MIDIDeviceInfo[] getAllMIDIInputDevices() 57 { 58 const uint count = getMIDIInputDevicesCount(); 59 MIDIDeviceInfo[] output = new MIDIDeviceInfo[count]; 60 61 for (uint i = 0; i < count; i++) 62 { 63 output[i] = getMIDIInputDeviceInfo(i); 64 } 65 66 return output; 67 } 68 69 /++ 70 Returns: the count of connected MIDI input devices 71 +/ 72 uint getMIDIInputDevicesCount() @nogc nothrow 73 { 74 return midiInGetNumDevs(); 75 } 76 77 /++ 78 Returns: the name of the given MIDI input device 79 +/ 80 string getMIDIInputDeviceName(MIDIINCAPS caps) pure @safe 81 { 82 return caps.szPname.trimEndNull.to!string; 83 } 84 85 /++ 86 Returns: the device info of the specified MIDI input device 87 +/ 88 MIDIDeviceInfo getMIDIInputDeviceInfo(uint deviceID) 89 { 90 MIDIINCAPS caps = getWinDeviceInfo(deviceID); 91 auto output = MIDIDeviceInfo(caps.getMIDIInputDeviceName(), deviceID, MIDIDeviceType.input); 92 93 return output; 94 } 95 96 /++ 97 Returns: the capabilities of the specified MIDI input device 98 +/ 99 MIDIINCAPS getWinDeviceInfo(uint deviceID) @nogc nothrow 100 { 101 MIDIINCAPS capabilities = MIDIINCAPS(); 102 103 MMRESULT rslt; 104 if ((rslt = midiInGetDevCaps(deviceID, &capabilities, MIDIINCAPS.sizeof)) == MMSYSERR_NOERROR) 105 { 106 return capabilities; 107 } 108 else 109 { 110 switch (rslt) 111 { 112 case MMSYSERR_BADDEVICEID: 113 assert(0, MMSYSERR_BADDEVICEID.stringof); 114 115 case MMSYSERR_INVALPARAM: 116 assert(0, MMSYSERR_INVALPARAM.stringof); 117 118 case MMSYSERR_NODRIVER: 119 assert(0, MMSYSERR_NODRIVER.stringof); 120 121 case MMSYSERR_NOMEM: 122 assert(0, MMSYSERR_NOMEM.stringof); 123 124 default: 125 assert(0); 126 } 127 } 128 } 129 130 extern (Windows) alias MidiInProc = void function(HMIDIIN, uint, size_t, size_t, size_t); 131 132 /++ 133 Opens a handle for the specified MIDI input device 134 135 Returns: 136 MMSYSERR_NOERROR on success 137 +/ 138 MMRESULT openMIDIInputDevice(uint deviceID, MidiInProc callback, 139 out HMIDIIN handle, size_t callbackData = 0) @nogc nothrow 140 { 141 // BUG: THIS RETURNS 1 (MMSYSERR_ERROR) WHEN COMPILED IN x86 MODE 142 return midiInOpen(&handle, deviceID, cast(size_t)(callback), callbackData, CALLBACK_FUNCTION); 143 } 144 145 /++ ditto ++/ 146 MMRESULT openMIDIInputDevice(MIDIDeviceInfo di, MidiInProc callback, 147 out HMIDIIN handle, size_t callbackData = 0) @nogc nothrow 148 { 149 return openMIDIInputDevice(di.id, callback, handle, callbackData); 150 } 151 152 /++ 153 Starts the MIDI input device which is represented by the passed handle 154 155 Returns: 156 true on success 157 false if the passed handle was invalid 158 +/ 159 bool startMIDIInputDevice(HMIDIIN handle) @nogc nothrow 160 { 161 return (midiInStart(handle) == MMSYSERR_NOERROR); 162 } 163 164 /++ 165 Parses param1 of a MIM_DATA message 166 167 See_Also: 168 https://msdn.microsoft.com/en-us/library/vs/alm/dd757284(v=vs.85).aspx, 169 https://users.cs.cf.ac.uk/Dave.Marshall/Multimedia/node158.html 170 +/ 171 MidiMessage parseMIMDATA(size_t param1) @nogc nothrow pure 172 { 173 immutable ubyte status = param1.LOWORD.LOBYTE; 174 immutable ubyte data1 = param1.LOWORD.HIBYTE; 175 immutable ubyte data2 = param1.HIWORD.LOBYTE; 176 177 return MidiMessage(0, status, data1, data2); 178 }