1 /*************************************************************************/
2 /*  midi_driver_winmidi.cpp                                              */
3 /*************************************************************************/
4 /*                       This file is part of:                           */
5 /*                           GODOT ENGINE                                */
6 /*                      https://godotengine.org                          */
7 /*************************************************************************/
8 /* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur.                 */
9 /* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md).   */
10 /*                                                                       */
11 /* Permission is hereby granted, free of charge, to any person obtaining */
12 /* a copy of this software and associated documentation files (the       */
13 /* "Software"), to deal in the Software without restriction, including   */
14 /* without limitation the rights to use, copy, modify, merge, publish,   */
15 /* distribute, sublicense, and/or sell copies of the Software, and to    */
16 /* permit persons to whom the Software is furnished to do so, subject to */
17 /* the following conditions:                                             */
18 /*                                                                       */
19 /* The above copyright notice and this permission notice shall be        */
20 /* included in all copies or substantial portions of the Software.       */
21 /*                                                                       */
22 /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,       */
23 /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF    */
24 /* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
25 /* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY  */
26 /* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,  */
27 /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE     */
28 /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */
29 /*************************************************************************/
30 
31 #ifdef WINMIDI_ENABLED
32 
33 #include "midi_driver_winmidi.h"
34 
35 #include "core/print_string.h"
36 
read(HMIDIIN hMidiIn,UINT wMsg,DWORD_PTR dwInstance,DWORD_PTR dwParam1,DWORD_PTR dwParam2)37 void MIDIDriverWinMidi::read(HMIDIIN hMidiIn, UINT wMsg, DWORD_PTR dwInstance, DWORD_PTR dwParam1, DWORD_PTR dwParam2) {
38 
39 	if (wMsg == MIM_DATA) {
40 		receive_input_packet((uint64_t)dwParam2, (uint8_t *)&dwParam1, 3);
41 	}
42 }
43 
open()44 Error MIDIDriverWinMidi::open() {
45 
46 	for (UINT i = 0; i < midiInGetNumDevs(); i++) {
47 		HMIDIIN midi_in;
48 
49 		MMRESULT res = midiInOpen(&midi_in, i, (DWORD_PTR)read, (DWORD_PTR)this, CALLBACK_FUNCTION);
50 		if (res == MMSYSERR_NOERROR) {
51 			midiInStart(midi_in);
52 			connected_sources.insert(i, midi_in);
53 		} else {
54 			char err[256];
55 			midiInGetErrorText(res, err, 256);
56 			ERR_PRINTS("midiInOpen error: " + String(err));
57 
58 			MIDIINCAPS caps;
59 			res = midiInGetDevCaps(i, &caps, sizeof(MIDIINCAPS));
60 			if (res == MMSYSERR_NOERROR) {
61 				ERR_PRINTS("Can't open MIDI device \"" + String(caps.szPname) + "\", is it being used by another application?");
62 			}
63 		}
64 	}
65 
66 	return OK;
67 }
68 
get_connected_inputs()69 PoolStringArray MIDIDriverWinMidi::get_connected_inputs() {
70 
71 	PoolStringArray list;
72 
73 	for (int i = 0; i < connected_sources.size(); i++) {
74 		HMIDIIN midi_in = connected_sources[i];
75 		UINT id = 0;
76 		MMRESULT res = midiInGetID(midi_in, &id);
77 		if (res == MMSYSERR_NOERROR) {
78 			MIDIINCAPS caps;
79 			res = midiInGetDevCaps(i, &caps, sizeof(MIDIINCAPS));
80 			if (res == MMSYSERR_NOERROR) {
81 				list.push_back(caps.szPname);
82 			}
83 		}
84 	}
85 
86 	return list;
87 }
88 
close()89 void MIDIDriverWinMidi::close() {
90 
91 	for (int i = 0; i < connected_sources.size(); i++) {
92 		HMIDIIN midi_in = connected_sources[i];
93 		midiInStop(midi_in);
94 		midiInClose(midi_in);
95 	}
96 	connected_sources.clear();
97 }
98 
MIDIDriverWinMidi()99 MIDIDriverWinMidi::MIDIDriverWinMidi() {
100 }
101 
~MIDIDriverWinMidi()102 MIDIDriverWinMidi::~MIDIDriverWinMidi() {
103 
104 	close();
105 }
106 
107 #endif // WINMIDI_ENABLED
108