1 module wasapi.midi; 2 3 version(Windows): 4 5 import core.sys.windows.mmsystem; 6 import wasapi.comutils; 7 8 class MidiOutDeviceDesc { 9 uint index; 10 string name; 11 uint technology; 12 ushort channelMask; 13 14 MidiOutDevice open() { 15 MidiOutDevice res = new MidiOutDevice(this); 16 if (!res.open()) 17 return null; 18 return res; 19 } 20 } 21 22 class MidiOutDevice { 23 private HMIDIOUT handle; 24 private MIDIHDR hdr; 25 protected MidiOutDeviceDesc desc; 26 protected bool closed = true; 27 protected bool hdrPrepared; 28 protected this(MidiOutDeviceDesc desc) { 29 this.desc = desc; 30 } 31 void sendEvent(ubyte b1) { 32 midiOutShortMsg(handle, b1); 33 } 34 void sendEvent(ubyte b1, ubyte b2) { 35 midiOutShortMsg(handle, b1 | (cast(uint)b2 << 8)); 36 } 37 void sendEvent(ubyte b1, ubyte b2, ubyte b3) { 38 midiOutShortMsg(handle, b1 | (cast(uint)b2 << 8) | (cast(uint)b3 << 16)); 39 } 40 void sendEvent(ubyte b1, ubyte b2, ubyte b3, ubyte b4) { 41 midiOutShortMsg(handle, b1 | (cast(uint)b2 << 8) | (cast(uint)b3 << 16) | (cast(uint)b4 << 24)); 42 } 43 protected bool open() { 44 if (midiOutOpen(&handle, desc.index, 0, 0, CALLBACK_NULL) != MMSYSERR_NOERROR) 45 return false; 46 closed = false; 47 if (midiOutPrepareHeader(handle, &hdr, MIDIHDR.sizeof) != MMSYSERR_NOERROR) { 48 close(); 49 return false; 50 } 51 hdrPrepared = true; 52 return true; 53 } 54 void close() { 55 if (closed) 56 return; 57 if (handle) { 58 if (hdrPrepared) { 59 midiOutUnprepareHeader(handle, &hdr, MIDIHDR.sizeof); 60 hdrPrepared = false; 61 } 62 midiOutReset(handle); 63 midiOutClose(handle); 64 handle = null; 65 } 66 closed = true; 67 } 68 ~this() { 69 close(); 70 } 71 } 72 73 immutable uint DEFAULT_MIDI_DEVICE = uint.max; 74 75 class MidiProvider { 76 @property uint inputDevCount() { 77 return midiInGetNumDevs(); 78 } 79 @property uint outDevCount() { 80 return midiOutGetNumDevs(); 81 } 82 83 MidiOutDeviceDesc getOutputDevice(uint index = DEFAULT_MIDI_DEVICE) { 84 import std.utf; 85 if (index == DEFAULT_MIDI_DEVICE) 86 index = MIDI_MAPPER; 87 MIDIOUTCAPS caps; 88 if (midiOutGetDevCaps(index, &caps, MIDIOUTCAPS.sizeof) != MMSYSERR_NOERROR) 89 return null; 90 MidiOutDeviceDesc res = new MidiOutDeviceDesc(); 91 res.index = index; 92 res.name = fromWstringz(caps.szPname.ptr).toUTF8; 93 res.technology = caps.wTechnology; 94 res.channelMask = caps.wChannelMask; 95 return res; 96 } 97 } 98