Added a new MIDIDriver class
This commit is contained in:
parent
cfcb6e11f2
commit
7a5f9fc08e
|
@ -221,6 +221,10 @@ String _OS::get_audio_driver_name(int p_driver) const {
|
||||||
return OS::get_singleton()->get_audio_driver_name(p_driver);
|
return OS::get_singleton()->get_audio_driver_name(p_driver);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PoolStringArray _OS::get_connected_midi_inputs() {
|
||||||
|
return OS::get_singleton()->get_connected_midi_inputs();
|
||||||
|
}
|
||||||
|
|
||||||
void _OS::set_video_mode(const Size2 &p_size, bool p_fullscreen, bool p_resizeable, int p_screen) {
|
void _OS::set_video_mode(const Size2 &p_size, bool p_fullscreen, bool p_resizeable, int p_screen) {
|
||||||
|
|
||||||
OS::VideoMode vm;
|
OS::VideoMode vm;
|
||||||
|
@ -1058,6 +1062,7 @@ void _OS::_bind_methods() {
|
||||||
ClassDB::bind_method(D_METHOD("get_video_driver_name", "driver"), &_OS::get_video_driver_name);
|
ClassDB::bind_method(D_METHOD("get_video_driver_name", "driver"), &_OS::get_video_driver_name);
|
||||||
ClassDB::bind_method(D_METHOD("get_audio_driver_count"), &_OS::get_audio_driver_count);
|
ClassDB::bind_method(D_METHOD("get_audio_driver_count"), &_OS::get_audio_driver_count);
|
||||||
ClassDB::bind_method(D_METHOD("get_audio_driver_name", "driver"), &_OS::get_audio_driver_name);
|
ClassDB::bind_method(D_METHOD("get_audio_driver_name", "driver"), &_OS::get_audio_driver_name);
|
||||||
|
ClassDB::bind_method(D_METHOD("get_connected_midi_inputs"), &_OS::get_connected_midi_inputs);
|
||||||
|
|
||||||
ClassDB::bind_method(D_METHOD("get_screen_count"), &_OS::get_screen_count);
|
ClassDB::bind_method(D_METHOD("get_screen_count"), &_OS::get_screen_count);
|
||||||
ClassDB::bind_method(D_METHOD("get_current_screen"), &_OS::get_current_screen);
|
ClassDB::bind_method(D_METHOD("get_current_screen"), &_OS::get_current_screen);
|
||||||
|
|
|
@ -152,6 +152,8 @@ public:
|
||||||
virtual int get_audio_driver_count() const;
|
virtual int get_audio_driver_count() const;
|
||||||
virtual String get_audio_driver_name(int p_driver) const;
|
virtual String get_audio_driver_name(int p_driver) const;
|
||||||
|
|
||||||
|
virtual PoolStringArray get_connected_midi_inputs();
|
||||||
|
|
||||||
virtual int get_screen_count() const;
|
virtual int get_screen_count() const;
|
||||||
virtual int get_current_screen() const;
|
virtual int get_current_screen() const;
|
||||||
virtual void set_current_screen(int p_screen);
|
virtual void set_current_screen(int p_screen);
|
||||||
|
|
|
@ -89,6 +89,7 @@ VARIANT_ENUM_CAST(KeyList);
|
||||||
VARIANT_ENUM_CAST(KeyModifierMask);
|
VARIANT_ENUM_CAST(KeyModifierMask);
|
||||||
VARIANT_ENUM_CAST(ButtonList);
|
VARIANT_ENUM_CAST(ButtonList);
|
||||||
VARIANT_ENUM_CAST(JoystickList);
|
VARIANT_ENUM_CAST(JoystickList);
|
||||||
|
VARIANT_ENUM_CAST(MidiMessageList);
|
||||||
|
|
||||||
void register_global_constants() {
|
void register_global_constants() {
|
||||||
|
|
||||||
|
@ -458,6 +459,15 @@ void register_global_constants() {
|
||||||
BIND_GLOBAL_ENUM_CONSTANT(JOY_ANALOG_L2);
|
BIND_GLOBAL_ENUM_CONSTANT(JOY_ANALOG_L2);
|
||||||
BIND_GLOBAL_ENUM_CONSTANT(JOY_ANALOG_R2);
|
BIND_GLOBAL_ENUM_CONSTANT(JOY_ANALOG_R2);
|
||||||
|
|
||||||
|
// midi
|
||||||
|
BIND_GLOBAL_ENUM_CONSTANT(MIDI_MESSAGE_NOTE_OFF);
|
||||||
|
BIND_GLOBAL_ENUM_CONSTANT(MIDI_MESSAGE_NOTE_ON);
|
||||||
|
BIND_GLOBAL_ENUM_CONSTANT(MIDI_MESSAGE_AFTERTOUCH);
|
||||||
|
BIND_GLOBAL_ENUM_CONSTANT(MIDI_MESSAGE_CONTROL_CHANGE);
|
||||||
|
BIND_GLOBAL_ENUM_CONSTANT(MIDI_MESSAGE_PROGRAM_CHANGE);
|
||||||
|
BIND_GLOBAL_ENUM_CONSTANT(MIDI_MESSAGE_CHANNEL_PRESSURE);
|
||||||
|
BIND_GLOBAL_ENUM_CONSTANT(MIDI_MESSAGE_PITCH_BEND);
|
||||||
|
|
||||||
// error list
|
// error list
|
||||||
|
|
||||||
BIND_GLOBAL_ENUM_CONSTANT(OK);
|
BIND_GLOBAL_ENUM_CONSTANT(OK);
|
||||||
|
|
|
@ -1080,3 +1080,122 @@ InputEventPanGesture::InputEventPanGesture() {
|
||||||
|
|
||||||
delta = Vector2(0, 0);
|
delta = Vector2(0, 0);
|
||||||
}
|
}
|
||||||
|
/////////////////////////////
|
||||||
|
|
||||||
|
void InputEventMIDI::set_channel(const int p_channel) {
|
||||||
|
|
||||||
|
channel = p_channel;
|
||||||
|
}
|
||||||
|
|
||||||
|
int InputEventMIDI::get_channel() const {
|
||||||
|
return channel;
|
||||||
|
}
|
||||||
|
|
||||||
|
void InputEventMIDI::set_message(const int p_message) {
|
||||||
|
|
||||||
|
message = p_message;
|
||||||
|
}
|
||||||
|
|
||||||
|
int InputEventMIDI::get_message() const {
|
||||||
|
return message;
|
||||||
|
}
|
||||||
|
|
||||||
|
void InputEventMIDI::set_pitch(const int p_pitch) {
|
||||||
|
|
||||||
|
pitch = p_pitch;
|
||||||
|
}
|
||||||
|
|
||||||
|
int InputEventMIDI::get_pitch() const {
|
||||||
|
return pitch;
|
||||||
|
}
|
||||||
|
|
||||||
|
void InputEventMIDI::set_velocity(const int p_velocity) {
|
||||||
|
|
||||||
|
velocity = p_velocity;
|
||||||
|
}
|
||||||
|
|
||||||
|
int InputEventMIDI::get_velocity() const {
|
||||||
|
return velocity;
|
||||||
|
}
|
||||||
|
|
||||||
|
void InputEventMIDI::set_instrument(const int p_instrument) {
|
||||||
|
|
||||||
|
instrument = p_instrument;
|
||||||
|
}
|
||||||
|
|
||||||
|
int InputEventMIDI::get_instrument() const {
|
||||||
|
return instrument;
|
||||||
|
}
|
||||||
|
|
||||||
|
void InputEventMIDI::set_pressure(const int p_pressure) {
|
||||||
|
|
||||||
|
pressure = p_pressure;
|
||||||
|
}
|
||||||
|
|
||||||
|
int InputEventMIDI::get_pressure() const {
|
||||||
|
return pressure;
|
||||||
|
}
|
||||||
|
|
||||||
|
void InputEventMIDI::set_controller_number(const int p_controller_number) {
|
||||||
|
|
||||||
|
controller_number = p_controller_number;
|
||||||
|
}
|
||||||
|
|
||||||
|
int InputEventMIDI::get_controller_number() const {
|
||||||
|
return controller_number;
|
||||||
|
}
|
||||||
|
|
||||||
|
void InputEventMIDI::set_controller_value(const int p_controller_value) {
|
||||||
|
|
||||||
|
controller_value = p_controller_value;
|
||||||
|
}
|
||||||
|
|
||||||
|
int InputEventMIDI::get_controller_value() const {
|
||||||
|
return controller_value;
|
||||||
|
}
|
||||||
|
|
||||||
|
String InputEventMIDI::as_text() const {
|
||||||
|
|
||||||
|
return "InputEventMIDI : channel=(" + itos(get_channel()) + "), message=(" + itos(get_message()) + ")";
|
||||||
|
}
|
||||||
|
|
||||||
|
void InputEventMIDI::_bind_methods() {
|
||||||
|
|
||||||
|
ClassDB::bind_method(D_METHOD("set_channel", "channel"), &InputEventMIDI::set_channel);
|
||||||
|
ClassDB::bind_method(D_METHOD("get_channel"), &InputEventMIDI::get_channel);
|
||||||
|
ClassDB::bind_method(D_METHOD("set_message", "message"), &InputEventMIDI::set_message);
|
||||||
|
ClassDB::bind_method(D_METHOD("get_message"), &InputEventMIDI::get_message);
|
||||||
|
ClassDB::bind_method(D_METHOD("set_pitch", "pitch"), &InputEventMIDI::set_pitch);
|
||||||
|
ClassDB::bind_method(D_METHOD("get_pitch"), &InputEventMIDI::get_pitch);
|
||||||
|
ClassDB::bind_method(D_METHOD("set_velocity", "velocity"), &InputEventMIDI::set_velocity);
|
||||||
|
ClassDB::bind_method(D_METHOD("get_velocity"), &InputEventMIDI::get_velocity);
|
||||||
|
ClassDB::bind_method(D_METHOD("set_instrument", "instrument"), &InputEventMIDI::set_instrument);
|
||||||
|
ClassDB::bind_method(D_METHOD("get_instrument"), &InputEventMIDI::get_instrument);
|
||||||
|
ClassDB::bind_method(D_METHOD("set_pressure", "pressure"), &InputEventMIDI::set_pressure);
|
||||||
|
ClassDB::bind_method(D_METHOD("get_pressure"), &InputEventMIDI::get_pressure);
|
||||||
|
ClassDB::bind_method(D_METHOD("set_controller_number", "controller_number"), &InputEventMIDI::set_controller_number);
|
||||||
|
ClassDB::bind_method(D_METHOD("get_controller_number"), &InputEventMIDI::get_controller_number);
|
||||||
|
ClassDB::bind_method(D_METHOD("set_controller_value", "controller_value"), &InputEventMIDI::set_controller_value);
|
||||||
|
ClassDB::bind_method(D_METHOD("get_controller_value"), &InputEventMIDI::get_controller_value);
|
||||||
|
|
||||||
|
ADD_PROPERTY(PropertyInfo(Variant::INT, "channel"), "set_channel", "get_channel");
|
||||||
|
ADD_PROPERTY(PropertyInfo(Variant::INT, "message"), "set_message", "get_message");
|
||||||
|
ADD_PROPERTY(PropertyInfo(Variant::INT, "pitch"), "set_pitch", "get_pitch");
|
||||||
|
ADD_PROPERTY(PropertyInfo(Variant::INT, "velocity"), "set_velocity", "get_velocity");
|
||||||
|
ADD_PROPERTY(PropertyInfo(Variant::INT, "instrument"), "set_instrument", "get_instrument");
|
||||||
|
ADD_PROPERTY(PropertyInfo(Variant::INT, "pressure"), "set_pressure", "get_pressure");
|
||||||
|
ADD_PROPERTY(PropertyInfo(Variant::INT, "controller_number"), "set_controller_number", "get_controller_number");
|
||||||
|
ADD_PROPERTY(PropertyInfo(Variant::INT, "controller_value"), "set_controller_value", "get_controller_value");
|
||||||
|
}
|
||||||
|
|
||||||
|
InputEventMIDI::InputEventMIDI() {
|
||||||
|
|
||||||
|
channel = 0;
|
||||||
|
message = 0;
|
||||||
|
pitch = 0;
|
||||||
|
velocity = 0;
|
||||||
|
instrument = 0;
|
||||||
|
pressure = 0;
|
||||||
|
controller_number = 0;
|
||||||
|
controller_value = 0;
|
||||||
|
}
|
||||||
|
|
|
@ -140,6 +140,16 @@ enum JoystickList {
|
||||||
JOY_ANALOG_R2 = JOY_AXIS_7,
|
JOY_ANALOG_R2 = JOY_AXIS_7,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum MidiMessageList {
|
||||||
|
MIDI_MESSAGE_NOTE_OFF = 0x8,
|
||||||
|
MIDI_MESSAGE_NOTE_ON = 0x9,
|
||||||
|
MIDI_MESSAGE_AFTERTOUCH = 0xA,
|
||||||
|
MIDI_MESSAGE_CONTROL_CHANGE = 0xB,
|
||||||
|
MIDI_MESSAGE_PROGRAM_CHANGE = 0xC,
|
||||||
|
MIDI_MESSAGE_CHANNEL_PRESSURE = 0xD,
|
||||||
|
MIDI_MESSAGE_PITCH_BEND = 0xE,
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Input Modifier Status
|
* Input Modifier Status
|
||||||
* for keyboard/mouse events.
|
* for keyboard/mouse events.
|
||||||
|
@ -525,4 +535,50 @@ public:
|
||||||
|
|
||||||
InputEventPanGesture();
|
InputEventPanGesture();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class InputEventMIDI : public InputEvent {
|
||||||
|
GDCLASS(InputEventMIDI, InputEvent)
|
||||||
|
|
||||||
|
int channel;
|
||||||
|
int message;
|
||||||
|
int pitch;
|
||||||
|
int velocity;
|
||||||
|
int instrument;
|
||||||
|
int pressure;
|
||||||
|
int controller_number;
|
||||||
|
int controller_value;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
static void _bind_methods();
|
||||||
|
|
||||||
|
public:
|
||||||
|
void set_channel(const int p_channel);
|
||||||
|
int get_channel() const;
|
||||||
|
|
||||||
|
void set_message(const int p_message);
|
||||||
|
int get_message() const;
|
||||||
|
|
||||||
|
void set_pitch(const int p_pitch);
|
||||||
|
int get_pitch() const;
|
||||||
|
|
||||||
|
void set_velocity(const int p_velocity);
|
||||||
|
int get_velocity() const;
|
||||||
|
|
||||||
|
void set_instrument(const int p_instrument);
|
||||||
|
int get_instrument() const;
|
||||||
|
|
||||||
|
void set_pressure(const int p_pressure);
|
||||||
|
int get_pressure() const;
|
||||||
|
|
||||||
|
void set_controller_number(const int p_controller_number);
|
||||||
|
int get_controller_number() const;
|
||||||
|
|
||||||
|
void set_controller_value(const int p_controller_value);
|
||||||
|
int get_controller_value() const;
|
||||||
|
|
||||||
|
virtual String as_text() const;
|
||||||
|
|
||||||
|
InputEventMIDI();
|
||||||
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -0,0 +1,107 @@
|
||||||
|
/*************************************************************************/
|
||||||
|
/* midi_driver.cpp */
|
||||||
|
/*************************************************************************/
|
||||||
|
/* This file is part of: */
|
||||||
|
/* GODOT ENGINE */
|
||||||
|
/* https://godotengine.org */
|
||||||
|
/*************************************************************************/
|
||||||
|
/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
|
||||||
|
/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */
|
||||||
|
/* */
|
||||||
|
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||||
|
/* a copy of this software and associated documentation files (the */
|
||||||
|
/* "Software"), to deal in the Software without restriction, including */
|
||||||
|
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||||
|
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||||
|
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||||
|
/* the following conditions: */
|
||||||
|
/* */
|
||||||
|
/* The above copyright notice and this permission notice shall be */
|
||||||
|
/* included in all copies or substantial portions of the Software. */
|
||||||
|
/* */
|
||||||
|
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||||
|
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||||
|
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||||
|
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||||
|
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||||
|
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||||
|
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||||
|
/*************************************************************************/
|
||||||
|
|
||||||
|
#include "midi_driver.h"
|
||||||
|
|
||||||
|
#include "main/input_default.h"
|
||||||
|
#include "os/os.h"
|
||||||
|
|
||||||
|
MIDIDriver *MIDIDriver::singleton = NULL;
|
||||||
|
MIDIDriver *MIDIDriver::get_singleton() {
|
||||||
|
|
||||||
|
return singleton;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MIDIDriver::set_singleton() {
|
||||||
|
|
||||||
|
singleton = this;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MIDIDriver::receive_input_packet(uint64_t timestamp, uint8_t *data, uint32_t length) {
|
||||||
|
|
||||||
|
Ref<InputEventMIDI> event;
|
||||||
|
event.instance();
|
||||||
|
|
||||||
|
if (length >= 1) {
|
||||||
|
event->set_channel(data[0] & 0xF);
|
||||||
|
event->set_message(data[0] >> 4);
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (event->get_message()) {
|
||||||
|
case MIDI_MESSAGE_AFTERTOUCH:
|
||||||
|
if (length >= 3) {
|
||||||
|
event->set_pitch(data[1]);
|
||||||
|
event->set_pressure(data[2]);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case MIDI_MESSAGE_CONTROL_CHANGE:
|
||||||
|
if (length >= 3) {
|
||||||
|
event->set_controller_number(data[1]);
|
||||||
|
event->set_controller_value(data[2]);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case MIDI_MESSAGE_NOTE_ON:
|
||||||
|
case MIDI_MESSAGE_NOTE_OFF:
|
||||||
|
case MIDI_MESSAGE_PITCH_BEND:
|
||||||
|
if (length >= 3) {
|
||||||
|
event->set_pitch(data[1]);
|
||||||
|
event->set_velocity(data[2]);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case MIDI_MESSAGE_PROGRAM_CHANGE:
|
||||||
|
if (length >= 2) {
|
||||||
|
event->set_instrument(data[1]);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case MIDI_MESSAGE_CHANNEL_PRESSURE:
|
||||||
|
if (length >= 2) {
|
||||||
|
event->set_pressure(data[1]);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
InputDefault *id = Object::cast_to<InputDefault>(Input::get_singleton());
|
||||||
|
id->parse_input_event(event);
|
||||||
|
}
|
||||||
|
|
||||||
|
PoolStringArray MIDIDriver::get_connected_inputs() {
|
||||||
|
|
||||||
|
PoolStringArray list;
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
MIDIDriver::MIDIDriver() {
|
||||||
|
|
||||||
|
set_singleton();
|
||||||
|
}
|
|
@ -0,0 +1,59 @@
|
||||||
|
/*************************************************************************/
|
||||||
|
/* midi_driver.h */
|
||||||
|
/*************************************************************************/
|
||||||
|
/* This file is part of: */
|
||||||
|
/* GODOT ENGINE */
|
||||||
|
/* https://godotengine.org */
|
||||||
|
/*************************************************************************/
|
||||||
|
/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
|
||||||
|
/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */
|
||||||
|
/* */
|
||||||
|
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||||
|
/* a copy of this software and associated documentation files (the */
|
||||||
|
/* "Software"), to deal in the Software without restriction, including */
|
||||||
|
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||||
|
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||||
|
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||||
|
/* the following conditions: */
|
||||||
|
/* */
|
||||||
|
/* The above copyright notice and this permission notice shall be */
|
||||||
|
/* included in all copies or substantial portions of the Software. */
|
||||||
|
/* */
|
||||||
|
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||||
|
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||||
|
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||||
|
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||||
|
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||||
|
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||||
|
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||||
|
/*************************************************************************/
|
||||||
|
|
||||||
|
#ifndef MIDI_DRIVER_H
|
||||||
|
#define MIDI_DRIVER_H
|
||||||
|
|
||||||
|
#include "core/variant.h"
|
||||||
|
#include "typedefs.h"
|
||||||
|
/**
|
||||||
|
* Multi-Platform abstraction for accessing to MIDI.
|
||||||
|
*/
|
||||||
|
|
||||||
|
class MIDIDriver {
|
||||||
|
|
||||||
|
static MIDIDriver *singleton;
|
||||||
|
|
||||||
|
public:
|
||||||
|
static MIDIDriver *get_singleton();
|
||||||
|
void set_singleton();
|
||||||
|
|
||||||
|
virtual Error open() = 0;
|
||||||
|
virtual void close() = 0;
|
||||||
|
|
||||||
|
virtual PoolStringArray get_connected_inputs();
|
||||||
|
|
||||||
|
static void receive_input_packet(uint64_t timestamp, uint8_t *data, uint32_t length);
|
||||||
|
|
||||||
|
MIDIDriver();
|
||||||
|
virtual ~MIDIDriver() {}
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
|
@ -33,6 +33,7 @@
|
||||||
#include "dir_access.h"
|
#include "dir_access.h"
|
||||||
#include "input.h"
|
#include "input.h"
|
||||||
#include "os/file_access.h"
|
#include "os/file_access.h"
|
||||||
|
#include "os/midi_driver.h"
|
||||||
#include "project_settings.h"
|
#include "project_settings.h"
|
||||||
#include "servers/audio_server.h"
|
#include "servers/audio_server.h"
|
||||||
#include "version_generated.gen.h"
|
#include "version_generated.gen.h"
|
||||||
|
@ -672,6 +673,15 @@ List<String> OS::get_restart_on_exit_arguments() const {
|
||||||
return restart_commandline;
|
return restart_commandline;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PoolStringArray OS::get_connected_midi_inputs() {
|
||||||
|
|
||||||
|
if (MIDIDriver::get_singleton())
|
||||||
|
return MIDIDriver::get_singleton()->get_connected_inputs();
|
||||||
|
|
||||||
|
PoolStringArray list;
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
OS::OS() {
|
OS::OS() {
|
||||||
void *volatile stack_bottom;
|
void *volatile stack_bottom;
|
||||||
|
|
||||||
|
|
|
@ -189,6 +189,8 @@ public:
|
||||||
virtual int get_audio_driver_count() const;
|
virtual int get_audio_driver_count() const;
|
||||||
virtual const char *get_audio_driver_name(int p_driver) const;
|
virtual const char *get_audio_driver_name(int p_driver) const;
|
||||||
|
|
||||||
|
virtual PoolStringArray get_connected_midi_inputs();
|
||||||
|
|
||||||
virtual int get_screen_count() const { return 1; }
|
virtual int get_screen_count() const { return 1; }
|
||||||
virtual int get_current_screen() const { return 0; }
|
virtual int get_current_screen() const { return 0; }
|
||||||
virtual void set_current_screen(int p_screen) {}
|
virtual void set_current_screen(int p_screen) {}
|
||||||
|
|
|
@ -21,6 +21,11 @@ if (env["platform"] == "windows"):
|
||||||
if env['xaudio2']:
|
if env['xaudio2']:
|
||||||
SConscript("xaudio2/SCsub")
|
SConscript("xaudio2/SCsub")
|
||||||
|
|
||||||
|
# Midi drivers
|
||||||
|
SConscript('alsamidi/SCsub')
|
||||||
|
SConscript('coremidi/SCsub')
|
||||||
|
SConscript('winmidi/SCsub')
|
||||||
|
|
||||||
# Graphics drivers
|
# Graphics drivers
|
||||||
if (env["platform"] != "server"):
|
if (env["platform"] != "server"):
|
||||||
SConscript('gles3/SCsub')
|
SConscript('gles3/SCsub')
|
||||||
|
|
|
@ -0,0 +1,8 @@
|
||||||
|
#!/usr/bin/env python
|
||||||
|
|
||||||
|
Import('env')
|
||||||
|
|
||||||
|
# Driver source files
|
||||||
|
env.add_source_files(env.drivers_sources, "*.cpp")
|
||||||
|
|
||||||
|
Export('env')
|
|
@ -0,0 +1,201 @@
|
||||||
|
/*************************************************************************/
|
||||||
|
/* alsa_midi.cpp */
|
||||||
|
/*************************************************************************/
|
||||||
|
/* This file is part of: */
|
||||||
|
/* GODOT ENGINE */
|
||||||
|
/* https://godotengine.org */
|
||||||
|
/*************************************************************************/
|
||||||
|
/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
|
||||||
|
/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */
|
||||||
|
/* */
|
||||||
|
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||||
|
/* a copy of this software and associated documentation files (the */
|
||||||
|
/* "Software"), to deal in the Software without restriction, including */
|
||||||
|
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||||
|
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||||
|
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||||
|
/* the following conditions: */
|
||||||
|
/* */
|
||||||
|
/* The above copyright notice and this permission notice shall be */
|
||||||
|
/* included in all copies or substantial portions of the Software. */
|
||||||
|
/* */
|
||||||
|
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||||
|
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||||
|
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||||
|
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||||
|
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||||
|
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||||
|
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||||
|
/*************************************************************************/
|
||||||
|
|
||||||
|
#ifdef ALSAMIDI_ENABLED
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
|
#include "alsa_midi.h"
|
||||||
|
#include "os/os.h"
|
||||||
|
#include "print_string.h"
|
||||||
|
|
||||||
|
static int get_message_size(uint8_t message) {
|
||||||
|
switch (message & 0xF0) {
|
||||||
|
case 0x80: // note off
|
||||||
|
case 0x90: // note on
|
||||||
|
case 0xA0: // aftertouch
|
||||||
|
case 0xB0: // continuous controller
|
||||||
|
return 3;
|
||||||
|
|
||||||
|
case 0xC0: // patch change
|
||||||
|
case 0xD0: // channel pressure
|
||||||
|
case 0xE0: // pitch bend
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 256;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MIDIDriverALSAMidi::thread_func(void *p_udata) {
|
||||||
|
MIDIDriverALSAMidi *md = (MIDIDriverALSAMidi *)p_udata;
|
||||||
|
uint64_t timestamp = 0;
|
||||||
|
uint8_t buffer[256];
|
||||||
|
int expected_size = 255;
|
||||||
|
int bytes = 0;
|
||||||
|
|
||||||
|
while (!md->exit_thread) {
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
md->lock();
|
||||||
|
|
||||||
|
for (int i = 0; i < md->connected_inputs.size(); i++) {
|
||||||
|
snd_rawmidi_t *midi_in = md->connected_inputs[i];
|
||||||
|
do {
|
||||||
|
uint8_t byte = 0;
|
||||||
|
ret = snd_rawmidi_read(midi_in, &byte, 1);
|
||||||
|
if (ret < 0) {
|
||||||
|
if (ret != -EAGAIN) {
|
||||||
|
ERR_PRINTS("snd_rawmidi_read error: " + String(snd_strerror(ret)));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (byte & 0x80) {
|
||||||
|
// Flush previous packet if there is any
|
||||||
|
if (bytes) {
|
||||||
|
md->receive_input_packet(timestamp, buffer, bytes);
|
||||||
|
bytes = 0;
|
||||||
|
}
|
||||||
|
expected_size = get_message_size(byte);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bytes < 256) {
|
||||||
|
buffer[bytes++] = byte;
|
||||||
|
// If we know the size of the current packet receive it if it reached the expected size
|
||||||
|
if (bytes >= expected_size) {
|
||||||
|
md->receive_input_packet(timestamp, buffer, bytes);
|
||||||
|
bytes = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} while (ret > 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
md->unlock();
|
||||||
|
|
||||||
|
OS::get_singleton()->delay_usec(1000);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Error MIDIDriverALSAMidi::open() {
|
||||||
|
|
||||||
|
void **hints;
|
||||||
|
|
||||||
|
if (snd_device_name_hint(-1, "rawmidi", &hints) < 0)
|
||||||
|
return ERR_CANT_OPEN;
|
||||||
|
|
||||||
|
int i = 0;
|
||||||
|
for (void **n = hints; *n != NULL; n++) {
|
||||||
|
char *name = snd_device_name_get_hint(*n, "NAME");
|
||||||
|
|
||||||
|
if (name != NULL) {
|
||||||
|
snd_rawmidi_t *midi_in;
|
||||||
|
int ret = snd_rawmidi_open(&midi_in, NULL, name, SND_RAWMIDI_NONBLOCK);
|
||||||
|
if (ret >= 0) {
|
||||||
|
connected_inputs.insert(i++, midi_in);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (name != NULL)
|
||||||
|
free(name);
|
||||||
|
}
|
||||||
|
snd_device_name_free_hint(hints);
|
||||||
|
|
||||||
|
mutex = Mutex::create();
|
||||||
|
thread = Thread::create(MIDIDriverALSAMidi::thread_func, this);
|
||||||
|
|
||||||
|
return OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MIDIDriverALSAMidi::close() {
|
||||||
|
|
||||||
|
if (thread) {
|
||||||
|
exit_thread = true;
|
||||||
|
Thread::wait_to_finish(thread);
|
||||||
|
|
||||||
|
memdelete(thread);
|
||||||
|
thread = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mutex) {
|
||||||
|
memdelete(mutex);
|
||||||
|
mutex = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < connected_inputs.size(); i++) {
|
||||||
|
snd_rawmidi_t *midi_in = connected_inputs[i];
|
||||||
|
snd_rawmidi_close(midi_in);
|
||||||
|
}
|
||||||
|
connected_inputs.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
void MIDIDriverALSAMidi::lock() const {
|
||||||
|
|
||||||
|
if (mutex)
|
||||||
|
mutex->lock();
|
||||||
|
}
|
||||||
|
|
||||||
|
void MIDIDriverALSAMidi::unlock() const {
|
||||||
|
|
||||||
|
if (mutex)
|
||||||
|
mutex->unlock();
|
||||||
|
}
|
||||||
|
|
||||||
|
PoolStringArray MIDIDriverALSAMidi::get_connected_inputs() {
|
||||||
|
|
||||||
|
PoolStringArray list;
|
||||||
|
|
||||||
|
lock();
|
||||||
|
for (int i = 0; i < connected_inputs.size(); i++) {
|
||||||
|
snd_rawmidi_t *midi_in = connected_inputs[i];
|
||||||
|
snd_rawmidi_info_t *info;
|
||||||
|
|
||||||
|
snd_rawmidi_info_malloc(&info);
|
||||||
|
snd_rawmidi_info(midi_in, info);
|
||||||
|
list.push_back(snd_rawmidi_info_get_name(info));
|
||||||
|
snd_rawmidi_info_free(info);
|
||||||
|
}
|
||||||
|
unlock();
|
||||||
|
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
MIDIDriverALSAMidi::MIDIDriverALSAMidi() {
|
||||||
|
|
||||||
|
mutex = NULL;
|
||||||
|
thread = NULL;
|
||||||
|
|
||||||
|
exit_thread = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
MIDIDriverALSAMidi::~MIDIDriverALSAMidi() {
|
||||||
|
|
||||||
|
close();
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,69 @@
|
||||||
|
/*************************************************************************/
|
||||||
|
/* alsa_midi.h */
|
||||||
|
/*************************************************************************/
|
||||||
|
/* This file is part of: */
|
||||||
|
/* GODOT ENGINE */
|
||||||
|
/* https://godotengine.org */
|
||||||
|
/*************************************************************************/
|
||||||
|
/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
|
||||||
|
/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */
|
||||||
|
/* */
|
||||||
|
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||||
|
/* a copy of this software and associated documentation files (the */
|
||||||
|
/* "Software"), to deal in the Software without restriction, including */
|
||||||
|
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||||
|
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||||
|
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||||
|
/* the following conditions: */
|
||||||
|
/* */
|
||||||
|
/* The above copyright notice and this permission notice shall be */
|
||||||
|
/* included in all copies or substantial portions of the Software. */
|
||||||
|
/* */
|
||||||
|
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||||
|
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||||
|
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||||
|
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||||
|
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||||
|
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||||
|
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||||
|
/*************************************************************************/
|
||||||
|
|
||||||
|
#ifdef ALSAMIDI_ENABLED
|
||||||
|
|
||||||
|
#ifndef ALSA_MIDI_H
|
||||||
|
#define ALSA_MIDI_H
|
||||||
|
|
||||||
|
#include <alsa/asoundlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include "core/os/mutex.h"
|
||||||
|
#include "core/os/thread.h"
|
||||||
|
#include "core/vector.h"
|
||||||
|
#include "os/midi_driver.h"
|
||||||
|
|
||||||
|
class MIDIDriverALSAMidi : public MIDIDriver {
|
||||||
|
|
||||||
|
Thread *thread;
|
||||||
|
Mutex *mutex;
|
||||||
|
|
||||||
|
Vector<snd_rawmidi_t *> connected_inputs;
|
||||||
|
|
||||||
|
bool exit_thread;
|
||||||
|
|
||||||
|
static void thread_func(void *p_udata);
|
||||||
|
|
||||||
|
void lock() const;
|
||||||
|
void unlock() const;
|
||||||
|
|
||||||
|
public:
|
||||||
|
virtual Error open();
|
||||||
|
virtual void close();
|
||||||
|
|
||||||
|
virtual PoolStringArray get_connected_inputs();
|
||||||
|
|
||||||
|
MIDIDriverALSAMidi();
|
||||||
|
virtual ~MIDIDriverALSAMidi();
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
|
#endif
|
|
@ -0,0 +1,8 @@
|
||||||
|
#!/usr/bin/env python
|
||||||
|
|
||||||
|
Import('env')
|
||||||
|
|
||||||
|
# Driver source files
|
||||||
|
env.add_source_files(env.drivers_sources, "*.cpp")
|
||||||
|
|
||||||
|
Export('env')
|
|
@ -0,0 +1,105 @@
|
||||||
|
/*************************************************************************/
|
||||||
|
/* core_midi.cpp */
|
||||||
|
/*************************************************************************/
|
||||||
|
/* This file is part of: */
|
||||||
|
/* GODOT ENGINE */
|
||||||
|
/* https://godotengine.org */
|
||||||
|
/*************************************************************************/
|
||||||
|
/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
|
||||||
|
/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */
|
||||||
|
/* */
|
||||||
|
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||||
|
/* a copy of this software and associated documentation files (the */
|
||||||
|
/* "Software"), to deal in the Software without restriction, including */
|
||||||
|
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||||
|
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||||
|
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||||
|
/* the following conditions: */
|
||||||
|
/* */
|
||||||
|
/* The above copyright notice and this permission notice shall be */
|
||||||
|
/* included in all copies or substantial portions of the Software. */
|
||||||
|
/* */
|
||||||
|
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||||
|
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||||
|
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||||
|
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||||
|
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||||
|
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||||
|
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||||
|
/*************************************************************************/
|
||||||
|
|
||||||
|
#ifdef COREMIDI_ENABLED
|
||||||
|
|
||||||
|
#include "core_midi.h"
|
||||||
|
#include "print_string.h"
|
||||||
|
|
||||||
|
#include <CoreAudio/HostTime.h>
|
||||||
|
#include <CoreServices/CoreServices.h>
|
||||||
|
|
||||||
|
void MIDIDriverCoreMidi::read(const MIDIPacketList *packet_list, void *read_proc_ref_con, void *src_conn_ref_con) {
|
||||||
|
MIDIPacket *packet = const_cast<MIDIPacket *>(packet_list->packet);
|
||||||
|
for (int i = 0; i < packet_list->numPackets; i++) {
|
||||||
|
receive_input_packet(packet->timeStamp, packet->data, packet->length);
|
||||||
|
packet = MIDIPacketNext(packet);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Error MIDIDriverCoreMidi::open() {
|
||||||
|
|
||||||
|
CFStringRef name = CFStringCreateWithCString(NULL, "Godot", kCFStringEncodingASCII);
|
||||||
|
OSStatus result = MIDIClientCreate(name, NULL, NULL, &client);
|
||||||
|
CFRelease(name);
|
||||||
|
if (result != noErr) {
|
||||||
|
ERR_PRINTS("MIDIClientCreate failed: " + String(GetMacOSStatusErrorString(result)));
|
||||||
|
return ERR_CANT_OPEN;
|
||||||
|
}
|
||||||
|
|
||||||
|
result = MIDIInputPortCreate(client, CFSTR("Godot Input"), MIDIDriverCoreMidi::read, (void *)this, &port_in);
|
||||||
|
if (result != noErr) {
|
||||||
|
ERR_PRINTS("MIDIInputPortCreate failed: " + String(GetMacOSStatusErrorString(result)));
|
||||||
|
return ERR_CANT_OPEN;
|
||||||
|
}
|
||||||
|
|
||||||
|
int sources = MIDIGetNumberOfSources();
|
||||||
|
for (int i = 0; i < sources; i++) {
|
||||||
|
|
||||||
|
MIDIEndpointRef source = MIDIGetSource(i);
|
||||||
|
if (source != NULL) {
|
||||||
|
MIDIPortConnectSource(port_in, source, (void *)this);
|
||||||
|
connected_sources.insert(i, source);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MIDIDriverCoreMidi::close() {
|
||||||
|
|
||||||
|
for (int i = 0; i < connected_sources.size(); i++) {
|
||||||
|
MIDIEndpointRef source = connected_sources[i];
|
||||||
|
MIDIPortDisconnectSource(port_in, source);
|
||||||
|
}
|
||||||
|
connected_sources.clear();
|
||||||
|
|
||||||
|
if (port_in != 0) {
|
||||||
|
MIDIPortDispose(port_in);
|
||||||
|
port_in = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (client != 0) {
|
||||||
|
MIDIClientDispose(client);
|
||||||
|
client = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
MIDIDriverCoreMidi::MIDIDriverCoreMidi() {
|
||||||
|
|
||||||
|
client = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
MIDIDriverCoreMidi::~MIDIDriverCoreMidi() {
|
||||||
|
|
||||||
|
close();
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,61 @@
|
||||||
|
/*************************************************************************/
|
||||||
|
/* core_midi.h */
|
||||||
|
/*************************************************************************/
|
||||||
|
/* This file is part of: */
|
||||||
|
/* GODOT ENGINE */
|
||||||
|
/* https://godotengine.org */
|
||||||
|
/*************************************************************************/
|
||||||
|
/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
|
||||||
|
/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */
|
||||||
|
/* */
|
||||||
|
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||||
|
/* a copy of this software and associated documentation files (the */
|
||||||
|
/* "Software"), to deal in the Software without restriction, including */
|
||||||
|
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||||
|
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||||
|
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||||
|
/* the following conditions: */
|
||||||
|
/* */
|
||||||
|
/* The above copyright notice and this permission notice shall be */
|
||||||
|
/* included in all copies or substantial portions of the Software. */
|
||||||
|
/* */
|
||||||
|
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||||
|
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||||
|
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||||
|
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||||
|
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||||
|
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||||
|
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||||
|
/*************************************************************************/
|
||||||
|
|
||||||
|
#ifdef COREMIDI_ENABLED
|
||||||
|
|
||||||
|
#ifndef CORE_MIDI_H
|
||||||
|
#define CORE_MIDI_H
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include <CoreMIDI/CoreMIDI.h>
|
||||||
|
|
||||||
|
#include "core/vector.h"
|
||||||
|
#include "os/midi_driver.h"
|
||||||
|
|
||||||
|
class MIDIDriverCoreMidi : public MIDIDriver {
|
||||||
|
|
||||||
|
MIDIClientRef client;
|
||||||
|
MIDIPortRef port_in;
|
||||||
|
|
||||||
|
Vector<MIDIEndpointRef> connected_sources;
|
||||||
|
|
||||||
|
static void read(const MIDIPacketList *packet_list, void *read_proc_ref_con, void *src_conn_ref_con);
|
||||||
|
|
||||||
|
public:
|
||||||
|
virtual Error open();
|
||||||
|
virtual void close();
|
||||||
|
|
||||||
|
MIDIDriverCoreMidi();
|
||||||
|
virtual ~MIDIDriverCoreMidi();
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
|
#endif
|
|
@ -0,0 +1,8 @@
|
||||||
|
#!/usr/bin/env python
|
||||||
|
|
||||||
|
Import('env')
|
||||||
|
|
||||||
|
# Driver source files
|
||||||
|
env.add_source_files(env.drivers_sources, "*.cpp")
|
||||||
|
|
||||||
|
Export('env')
|
|
@ -0,0 +1,100 @@
|
||||||
|
/*************************************************************************/
|
||||||
|
/* win_midi.cpp */
|
||||||
|
/*************************************************************************/
|
||||||
|
/* This file is part of: */
|
||||||
|
/* GODOT ENGINE */
|
||||||
|
/* https://godotengine.org */
|
||||||
|
/*************************************************************************/
|
||||||
|
/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
|
||||||
|
/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */
|
||||||
|
/* */
|
||||||
|
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||||
|
/* a copy of this software and associated documentation files (the */
|
||||||
|
/* "Software"), to deal in the Software without restriction, including */
|
||||||
|
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||||
|
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||||
|
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||||
|
/* the following conditions: */
|
||||||
|
/* */
|
||||||
|
/* The above copyright notice and this permission notice shall be */
|
||||||
|
/* included in all copies or substantial portions of the Software. */
|
||||||
|
/* */
|
||||||
|
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||||
|
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||||
|
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||||
|
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||||
|
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||||
|
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||||
|
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||||
|
/*************************************************************************/
|
||||||
|
|
||||||
|
#ifdef WINMIDI_ENABLED
|
||||||
|
|
||||||
|
#include "win_midi.h"
|
||||||
|
#include "print_string.h"
|
||||||
|
|
||||||
|
void MIDIDriverWinMidi::read(HMIDIIN hMidiIn, UINT wMsg, DWORD_PTR dwInstance, DWORD_PTR dwParam1, DWORD_PTR dwParam2) {
|
||||||
|
|
||||||
|
if (wMsg == MIM_DATA) {
|
||||||
|
receive_input_packet((uint64_t)dwParam2, (uint8_t *)&dwParam1, 3);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Error MIDIDriverWinMidi::open() {
|
||||||
|
|
||||||
|
for (UINT i = 0; i < midiInGetNumDevs(); i++) {
|
||||||
|
HMIDIIN midi_in;
|
||||||
|
|
||||||
|
MMRESULT res = midiInOpen(&midi_in, i, (DWORD_PTR)read, (DWORD_PTR)this, CALLBACK_FUNCTION);
|
||||||
|
if (res == MMSYSERR_NOERROR) {
|
||||||
|
midiInStart(midi_in);
|
||||||
|
connected_sources.insert(i, midi_in);
|
||||||
|
} else {
|
||||||
|
char err[256];
|
||||||
|
midiInGetErrorText(res, err, 256);
|
||||||
|
ERR_PRINTS("midiInOpen error: " + String(err));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
PoolStringArray MIDIDriverWinMidi::get_connected_inputs() {
|
||||||
|
|
||||||
|
PoolStringArray list;
|
||||||
|
|
||||||
|
for (int i = 0; i < connected_sources.size(); i++) {
|
||||||
|
HMIDIIN midi_in = connected_sources[i];
|
||||||
|
UINT id = 0;
|
||||||
|
MMRESULT res = midiInGetID(midi_in, &id);
|
||||||
|
if (res == MMSYSERR_NOERROR) {
|
||||||
|
MIDIINCAPS caps;
|
||||||
|
res = midiInGetDevCaps(i, &caps, sizeof(MIDIINCAPS));
|
||||||
|
if (res == MMSYSERR_NOERROR) {
|
||||||
|
list.push_back(caps.szPname);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MIDIDriverWinMidi::close() {
|
||||||
|
|
||||||
|
for (int i = 0; i < connected_sources.size(); i++) {
|
||||||
|
HMIDIIN midi_in = connected_sources[i];
|
||||||
|
midiInStop(midi_in);
|
||||||
|
midiInClose(midi_in);
|
||||||
|
}
|
||||||
|
connected_sources.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
MIDIDriverWinMidi::MIDIDriverWinMidi() {
|
||||||
|
}
|
||||||
|
|
||||||
|
MIDIDriverWinMidi::~MIDIDriverWinMidi() {
|
||||||
|
|
||||||
|
close();
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,61 @@
|
||||||
|
/*************************************************************************/
|
||||||
|
/* win_midi.h */
|
||||||
|
/*************************************************************************/
|
||||||
|
/* This file is part of: */
|
||||||
|
/* GODOT ENGINE */
|
||||||
|
/* https://godotengine.org */
|
||||||
|
/*************************************************************************/
|
||||||
|
/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */
|
||||||
|
/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */
|
||||||
|
/* */
|
||||||
|
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||||
|
/* a copy of this software and associated documentation files (the */
|
||||||
|
/* "Software"), to deal in the Software without restriction, including */
|
||||||
|
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||||
|
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||||
|
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||||
|
/* the following conditions: */
|
||||||
|
/* */
|
||||||
|
/* The above copyright notice and this permission notice shall be */
|
||||||
|
/* included in all copies or substantial portions of the Software. */
|
||||||
|
/* */
|
||||||
|
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||||
|
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||||
|
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||||
|
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||||
|
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||||
|
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||||
|
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||||
|
/*************************************************************************/
|
||||||
|
|
||||||
|
#ifdef WINMIDI_ENABLED
|
||||||
|
|
||||||
|
#ifndef WIN_MIDI_H
|
||||||
|
#define WIN_MIDI_H
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <windows.h>
|
||||||
|
|
||||||
|
#include <mmsystem.h>
|
||||||
|
|
||||||
|
#include "core/vector.h"
|
||||||
|
#include "os/midi_driver.h"
|
||||||
|
|
||||||
|
class MIDIDriverWinMidi : public MIDIDriver {
|
||||||
|
|
||||||
|
Vector<HMIDIIN> connected_sources;
|
||||||
|
|
||||||
|
static void CALLBACK read(HMIDIIN hMidiIn, UINT wMsg, DWORD_PTR dwInstance, DWORD_PTR dwParam1, DWORD_PTR dwParam2);
|
||||||
|
|
||||||
|
public:
|
||||||
|
virtual Error open();
|
||||||
|
virtual void close();
|
||||||
|
|
||||||
|
virtual PoolStringArray get_connected_inputs();
|
||||||
|
|
||||||
|
MIDIDriverWinMidi();
|
||||||
|
virtual ~MIDIDriverWinMidi();
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
|
#endif
|
|
@ -108,8 +108,8 @@ def configure(env):
|
||||||
## Flags
|
## Flags
|
||||||
|
|
||||||
env.Append(CPPPATH=['#platform/osx'])
|
env.Append(CPPPATH=['#platform/osx'])
|
||||||
env.Append(CPPFLAGS=['-DOSX_ENABLED', '-DUNIX_ENABLED', '-DGLES_ENABLED', '-DAPPLE_STYLE_KEYS', '-DCOREAUDIO_ENABLED'])
|
env.Append(CPPFLAGS=['-DOSX_ENABLED', '-DUNIX_ENABLED', '-DGLES_ENABLED', '-DAPPLE_STYLE_KEYS', '-DCOREAUDIO_ENABLED', '-DCOREMIDI_ENABLED'])
|
||||||
env.Append(LINKFLAGS=['-framework', 'Cocoa', '-framework', 'Carbon', '-framework', 'OpenGL', '-framework', 'AGL', '-framework', 'AudioUnit', '-framework', 'CoreAudio', '-lz', '-framework', 'IOKit', '-framework', 'ForceFeedback'])
|
env.Append(LINKFLAGS=['-framework', 'Cocoa', '-framework', 'Carbon', '-framework', 'OpenGL', '-framework', 'AGL', '-framework', 'AudioUnit', '-framework', 'CoreAudio', '-framework', 'CoreMidi', '-lz', '-framework', 'IOKit', '-framework', 'ForceFeedback'])
|
||||||
env.Append(LIBS=['pthread'])
|
env.Append(LIBS=['pthread'])
|
||||||
|
|
||||||
env.Append(CPPFLAGS=['-mmacosx-version-min=10.9'])
|
env.Append(CPPFLAGS=['-mmacosx-version-min=10.9'])
|
||||||
|
|
|
@ -33,6 +33,7 @@
|
||||||
|
|
||||||
#include "crash_handler_osx.h"
|
#include "crash_handler_osx.h"
|
||||||
#include "drivers/coreaudio/audio_driver_coreaudio.h"
|
#include "drivers/coreaudio/audio_driver_coreaudio.h"
|
||||||
|
#include "drivers/coremidi/core_midi.h"
|
||||||
#include "drivers/unix/os_unix.h"
|
#include "drivers/unix/os_unix.h"
|
||||||
#include "joypad_osx.h"
|
#include "joypad_osx.h"
|
||||||
#include "main/input_default.h"
|
#include "main/input_default.h"
|
||||||
|
@ -74,6 +75,7 @@ public:
|
||||||
IP_Unix *ip_unix;
|
IP_Unix *ip_unix;
|
||||||
|
|
||||||
AudioDriverCoreAudio audio_driver;
|
AudioDriverCoreAudio audio_driver;
|
||||||
|
MIDIDriverCoreMidi midi_driver;
|
||||||
|
|
||||||
InputDefault *input;
|
InputDefault *input;
|
||||||
JoypadOSX *joypad_osx;
|
JoypadOSX *joypad_osx;
|
||||||
|
|
|
@ -1351,6 +1351,8 @@ Error OS_OSX::initialize(const VideoMode &p_desired, int p_video_driver, int p_a
|
||||||
|
|
||||||
AudioDriverManager::initialize(p_audio_driver);
|
AudioDriverManager::initialize(p_audio_driver);
|
||||||
|
|
||||||
|
midi_driver.open();
|
||||||
|
|
||||||
input = memnew(InputDefault);
|
input = memnew(InputDefault);
|
||||||
joypad_osx = memnew(JoypadOSX);
|
joypad_osx = memnew(JoypadOSX);
|
||||||
|
|
||||||
|
|
|
@ -200,7 +200,8 @@ def configure_msvc(env, manual_msvc_config):
|
||||||
|
|
||||||
env.AppendUnique(CPPDEFINES = ['WINDOWS_ENABLED', 'OPENGL_ENABLED',
|
env.AppendUnique(CPPDEFINES = ['WINDOWS_ENABLED', 'OPENGL_ENABLED',
|
||||||
'RTAUDIO_ENABLED', 'WASAPI_ENABLED',
|
'RTAUDIO_ENABLED', 'WASAPI_ENABLED',
|
||||||
'TYPED_METHOD_BIND', 'WIN32', 'MSVC',
|
'WINMIDI_ENABLED', 'TYPED_METHOD_BIND',
|
||||||
|
'WIN32', 'MSVC',
|
||||||
{'WINVER' : '$target_win_version',
|
{'WINVER' : '$target_win_version',
|
||||||
'_WIN32_WINNT': '$target_win_version'}])
|
'_WIN32_WINNT': '$target_win_version'}])
|
||||||
if env["bits"] == "64":
|
if env["bits"] == "64":
|
||||||
|
|
|
@ -1219,6 +1219,10 @@ Error OS_Windows::initialize(const VideoMode &p_desired, int p_video_driver, int
|
||||||
|
|
||||||
AudioDriverManager::initialize(p_audio_driver);
|
AudioDriverManager::initialize(p_audio_driver);
|
||||||
|
|
||||||
|
#ifdef WINMIDI_ENABLED
|
||||||
|
driver_midi.open();
|
||||||
|
#endif
|
||||||
|
|
||||||
TRACKMOUSEEVENT tme;
|
TRACKMOUSEEVENT tme;
|
||||||
tme.cbSize = sizeof(TRACKMOUSEEVENT);
|
tme.cbSize = sizeof(TRACKMOUSEEVENT);
|
||||||
tme.dwFlags = TME_LEAVE;
|
tme.dwFlags = TME_LEAVE;
|
||||||
|
@ -1347,6 +1351,10 @@ void OS_Windows::set_main_loop(MainLoop *p_main_loop) {
|
||||||
|
|
||||||
void OS_Windows::finalize() {
|
void OS_Windows::finalize() {
|
||||||
|
|
||||||
|
#ifdef WINMIDI_ENABLED
|
||||||
|
driver_midi.close();
|
||||||
|
#endif
|
||||||
|
|
||||||
if (main_loop)
|
if (main_loop)
|
||||||
memdelete(main_loop);
|
memdelete(main_loop);
|
||||||
|
|
||||||
|
|
|
@ -35,6 +35,7 @@
|
||||||
#include "crash_handler_win.h"
|
#include "crash_handler_win.h"
|
||||||
#include "drivers/rtaudio/audio_driver_rtaudio.h"
|
#include "drivers/rtaudio/audio_driver_rtaudio.h"
|
||||||
#include "drivers/wasapi/audio_driver_wasapi.h"
|
#include "drivers/wasapi/audio_driver_wasapi.h"
|
||||||
|
#include "drivers/winmidi/win_midi.h"
|
||||||
#include "os/input.h"
|
#include "os/input.h"
|
||||||
#include "os/os.h"
|
#include "os/os.h"
|
||||||
#include "power_windows.h"
|
#include "power_windows.h"
|
||||||
|
@ -144,6 +145,9 @@ class OS_Windows : public OS {
|
||||||
#ifdef XAUDIO2_ENABLED
|
#ifdef XAUDIO2_ENABLED
|
||||||
AudioDriverXAudio2 driver_xaudio2;
|
AudioDriverXAudio2 driver_xaudio2;
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef WINMIDI_ENABLED
|
||||||
|
MIDIDriverWinMidi driver_midi;
|
||||||
|
#endif
|
||||||
|
|
||||||
CrashHandler crash_handler;
|
CrashHandler crash_handler;
|
||||||
|
|
||||||
|
|
|
@ -240,7 +240,7 @@ def configure(env):
|
||||||
|
|
||||||
if (os.system("pkg-config --exists alsa") == 0): # 0 means found
|
if (os.system("pkg-config --exists alsa") == 0): # 0 means found
|
||||||
print("Enabling ALSA")
|
print("Enabling ALSA")
|
||||||
env.Append(CPPFLAGS=["-DALSA_ENABLED"])
|
env.Append(CPPFLAGS=["-DALSA_ENABLED", "-DALSAMIDI_ENABLED"])
|
||||||
env.ParseConfig('pkg-config alsa --cflags --libs')
|
env.ParseConfig('pkg-config alsa --cflags --libs')
|
||||||
else:
|
else:
|
||||||
print("ALSA libraries not found, disabling driver")
|
print("ALSA libraries not found, disabling driver")
|
||||||
|
|
|
@ -342,6 +342,10 @@ Error OS_X11::initialize(const VideoMode &p_desired, int p_video_driver, int p_a
|
||||||
|
|
||||||
AudioDriverManager::initialize(p_audio_driver);
|
AudioDriverManager::initialize(p_audio_driver);
|
||||||
|
|
||||||
|
#ifdef ALSAMIDI_ENABLED
|
||||||
|
driver_alsamidi.open();
|
||||||
|
#endif
|
||||||
|
|
||||||
ERR_FAIL_COND_V(!visual_server, ERR_UNAVAILABLE);
|
ERR_FAIL_COND_V(!visual_server, ERR_UNAVAILABLE);
|
||||||
ERR_FAIL_COND_V(x11_window == 0, ERR_UNAVAILABLE);
|
ERR_FAIL_COND_V(x11_window == 0, ERR_UNAVAILABLE);
|
||||||
|
|
||||||
|
@ -606,6 +610,9 @@ void OS_X11::finalize() {
|
||||||
memdelete(debugger_connection_console);
|
memdelete(debugger_connection_console);
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
#ifdef ALSAMIDI_ENABLED
|
||||||
|
driver_alsamidi.close();
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef JOYDEV_ENABLED
|
#ifdef JOYDEV_ENABLED
|
||||||
memdelete(joypad);
|
memdelete(joypad);
|
||||||
|
|
|
@ -38,6 +38,7 @@
|
||||||
#include "servers/visual_server.h"
|
#include "servers/visual_server.h"
|
||||||
//#include "servers/visual/visual_server_wrap_mt.h"
|
//#include "servers/visual/visual_server_wrap_mt.h"
|
||||||
#include "drivers/alsa/audio_driver_alsa.h"
|
#include "drivers/alsa/audio_driver_alsa.h"
|
||||||
|
#include "drivers/alsamidi/alsa_midi.h"
|
||||||
#include "drivers/pulseaudio/audio_driver_pulseaudio.h"
|
#include "drivers/pulseaudio/audio_driver_pulseaudio.h"
|
||||||
#include "joypad_linux.h"
|
#include "joypad_linux.h"
|
||||||
#include "main/input_default.h"
|
#include "main/input_default.h"
|
||||||
|
@ -168,6 +169,10 @@ class OS_X11 : public OS_Unix {
|
||||||
AudioDriverALSA driver_alsa;
|
AudioDriverALSA driver_alsa;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef ALSAMIDI_ENABLED
|
||||||
|
MIDIDriverALSAMidi driver_alsamidi;
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef PULSEAUDIO_ENABLED
|
#ifdef PULSEAUDIO_ENABLED
|
||||||
AudioDriverPulseAudio driver_pulseaudio;
|
AudioDriverPulseAudio driver_pulseaudio;
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Reference in New Issue