1/**************************************************************************/
2/* midi_driver.cpp */
3/**************************************************************************/
4/* This file is part of: */
5/* GODOT ENGINE */
6/* https://godotengine.org */
7/**************************************************************************/
8/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
9/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
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#include "midi_driver.h"
32
33#include "core/input/input.h"
34
35uint8_t MIDIDriver::last_received_message = 0x00;
36MIDIDriver *MIDIDriver::singleton = nullptr;
37MIDIDriver *MIDIDriver::get_singleton() {
38 return singleton;
39}
40
41void MIDIDriver::set_singleton() {
42 singleton = this;
43}
44
45void MIDIDriver::receive_input_packet(uint64_t timestamp, uint8_t *data, uint32_t length) {
46 Ref<InputEventMIDI> event;
47 event.instantiate();
48 uint32_t param_position = 1;
49
50 if (length >= 1) {
51 if (data[0] >= 0xF0) {
52 // channel does not apply to system common messages
53 event->set_channel(0);
54 event->set_message(MIDIMessage(data[0]));
55 last_received_message = data[0];
56 } else if ((data[0] & 0x80) == 0x00) {
57 // running status
58 event->set_channel(last_received_message & 0xF);
59 event->set_message(MIDIMessage(last_received_message >> 4));
60 param_position = 0;
61 } else {
62 event->set_channel(data[0] & 0xF);
63 event->set_message(MIDIMessage(data[0] >> 4));
64 param_position = 1;
65 last_received_message = data[0];
66 }
67 }
68
69 switch (event->get_message()) {
70 case MIDIMessage::AFTERTOUCH:
71 if (length >= 2 + param_position) {
72 event->set_pitch(data[param_position]);
73 event->set_pressure(data[param_position + 1]);
74 }
75 break;
76
77 case MIDIMessage::CONTROL_CHANGE:
78 if (length >= 2 + param_position) {
79 event->set_controller_number(data[param_position]);
80 event->set_controller_value(data[param_position + 1]);
81 }
82 break;
83
84 case MIDIMessage::NOTE_ON:
85 case MIDIMessage::NOTE_OFF:
86 if (length >= 2 + param_position) {
87 event->set_pitch(data[param_position]);
88 event->set_velocity(data[param_position + 1]);
89 }
90 break;
91
92 case MIDIMessage::PITCH_BEND:
93 if (length >= 2 + param_position) {
94 event->set_pitch((data[param_position + 1] << 7) | data[param_position]);
95 }
96 break;
97
98 case MIDIMessage::PROGRAM_CHANGE:
99 if (length >= 1 + param_position) {
100 event->set_instrument(data[param_position]);
101 }
102 break;
103
104 case MIDIMessage::CHANNEL_PRESSURE:
105 if (length >= 1 + param_position) {
106 event->set_pressure(data[param_position]);
107 }
108 break;
109 default:
110 break;
111 }
112
113 Input *id = Input::get_singleton();
114 id->parse_input_event(event);
115}
116
117PackedStringArray MIDIDriver::get_connected_inputs() {
118 PackedStringArray list;
119 return list;
120}
121
122MIDIDriver::MIDIDriver() {
123 set_singleton();
124}
125