1 module iota.audio.midi;
2
3 public import iota.audio.types;
4 public import iota.audio.midiin;
5 public import iota.audio.midiout;
6
7 version (Windows) {
8 package import iota.audio.midiwin;
9 import core.sys.windows.windows;
10 import core.sys.windows.wtypes;
11 /**
12 * Te last error code that occured on the OS side.
13 */
14 MMRESULT lastErrorCode;
15 }
16
17 /**
18 * The last error code that occured on middleware side.
19 */
20 public int lastStatusCode;
21 package string[] inDevs;
22 package string[] outDevs;
23 /**
24 * Initializes MIDI subsystem.
25 * Returns: Zero on success, or a specific error code.
26 */
27 public int initMIDI() {
28 version (Windows) {
29 import std.string : fromStringz;
30 import std.utf : toUTF8;
31
32 uint nOutDevices = midiOutGetNumDevs();
33 uint nInDevices = midiInGetNumDevs();
34 if (!(nInDevices | nOutDevices)) return lastStatusCode = MIDIInitializationStatus.DevicesNotFound;
35 inDevs.length = nInDevices;
36 for (int i ; i < inDevs.length ; i++) {
37 MIDIINCAPS caps;
38 size_t u = i;
39 lastErrorCode = midiInGetDevCaps(u, &caps, cast(UINT)MIDIINCAPS.sizeof);
40 if (lastErrorCode == MMSYSERR_NOERROR)
41 inDevs[i] = toUTF8(fromStringz(caps.szPname.ptr).idup);
42 else
43 return lastStatusCode = MIDIInitializationStatus.InitError;
44 }
45 outDevs.length = nOutDevices;
46 for (int i ; i < outDevs.length ; i++) {
47 MIDIOUTCAPS caps;
48 size_t u = i;
49 lastErrorCode = midiOutGetDevCaps(u, &caps, cast(UINT)MIDIOUTCAPS.sizeof);
50 if (lastErrorCode == MMSYSERR_NOERROR)
51 outDevs[i] = toUTF8(fromStringz(caps.szPname.ptr).idup);
52 else
53 return lastStatusCode = MIDIInitializationStatus.InitError;
54 }
55 return 0;
56 } else return lastStatusCode = MIDIInitializationStatus.OSNotSupported;
57 }
58 ///Returns the name of all MIDI input devices.
59 public string[] getMIDIInputDevs() @safe nothrow {
60 return inDevs.dup;
61 }
62 ///Returns the name of all MIDI output devices.
63 public string[] getMIDIOutputDevs() @safe nothrow {
64 return outDevs.dup;
65 }
66 /**
67 * Opens an input for a MIDI stream.
68 * Params:
69 * input = Stream returned here.
70 * num = The ID of the device.
71 * bufSize = The input buffer size if applicable (1024 by default).
72 * Returns: 0 if the operation is successful, or an error code.
73 */
74 public int openMIDIInput(ref MIDIInput input, uint num, size_t bufSize = 1024) {
75 version (Windows) {
76 WindowsMIDIInput wmi = new WindowsMIDIInput(num, bufSize);
77 switch (wmi.lastErrorCode) {
78 case MMSYSERR_NOMEM:
79 return MIDIDeviceInitStatus.OutOfMemory;
80 case MMSYSERR_BADDEVICEID:
81 return MIDIDeviceInitStatus.InvalidDeviceID;
82 case MMSYSERR_NOERROR:
83 input = wmi;
84 return MIDIDeviceInitStatus.AllOk;
85 default:
86 return MIDIDeviceInitStatus.InitError;
87 }
88 } else return lastStatusCode = MIDIDeviceInitStatus.OSNotSupported;
89 }
90 /**
91 * Opens an output for a MIDI stream.
92 * Params:
93 * output = Stream returned here.
94 * num = The ID of the device.
95 * Returns:
96 */
97 public int openMIDIOutput(ref MIDIOutput output, uint num) {
98 version (Windows) {
99 WindowsMIDIOutput wmi = new WindowsMIDIOutput(num);
100 switch (wmi.lastErrorCode) {
101 case MMSYSERR_NOMEM:
102 return MIDIDeviceInitStatus.OutOfMemory;
103 case MMSYSERR_BADDEVICEID:
104 return MIDIDeviceInitStatus.InvalidDeviceID;
105 case MMSYSERR_NOERROR:
106 output = wmi;
107 return MIDIDeviceInitStatus.AllOk;
108 default:
109 return MIDIDeviceInitStatus.InitError;
110 }
111 } else return lastStatusCode = MIDIDeviceInitStatus.OSNotSupported;
112 }