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 }