initial commit, 4.5 stable
Some checks failed
🔗 GHA / 📊 Static checks (push) Has been cancelled
🔗 GHA / 🤖 Android (push) Has been cancelled
🔗 GHA / 🍏 iOS (push) Has been cancelled
🔗 GHA / 🐧 Linux (push) Has been cancelled
🔗 GHA / 🍎 macOS (push) Has been cancelled
🔗 GHA / 🏁 Windows (push) Has been cancelled
🔗 GHA / 🌐 Web (push) Has been cancelled

This commit is contained in:
2025-09-16 20:46:46 -04:00
commit 9d30169a8d
13378 changed files with 7050105 additions and 0 deletions

7
drivers/alsamidi/SCsub Normal file
View File

@@ -0,0 +1,7 @@
#!/usr/bin/env python
from misc.utility.scons_hints import *
Import("env")
# Driver source files
env.add_source_files(env.drivers_sources, "*.cpp")

View File

@@ -0,0 +1,147 @@
/**************************************************************************/
/* midi_driver_alsamidi.cpp */
/**************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/**************************************************************************/
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
/* */
/* 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 "midi_driver_alsamidi.h"
#include "core/os/os.h"
#include <cerrno>
MIDIDriverALSAMidi::InputConnection::InputConnection(int p_device_index,
snd_rawmidi_t *p_rawmidi) :
parser(p_device_index), rawmidi_ptr(p_rawmidi) {}
void MIDIDriverALSAMidi::InputConnection::read() {
int read_count;
do {
uint8_t buffer[32];
read_count = snd_rawmidi_read(rawmidi_ptr, buffer, sizeof(buffer));
if (read_count < 0) {
if (read_count != -EAGAIN) {
ERR_PRINT("snd_rawmidi_read error: " + String(snd_strerror(read_count)));
}
} else {
for (int i = 0; i < read_count; i++) {
parser.parse_fragment(buffer[i]);
}
}
} while (read_count > 0);
}
void MIDIDriverALSAMidi::thread_func(void *p_udata) {
MIDIDriverALSAMidi *md = static_cast<MIDIDriverALSAMidi *>(p_udata);
while (!md->exit_thread.is_set()) {
md->lock();
for (InputConnection &conn : md->connected_inputs) {
conn.read();
}
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;
}
lock();
int device_index = 0;
for (void **h = hints; *h != nullptr; h++) {
char *name = snd_device_name_get_hint(*h, "NAME");
if (name != nullptr) {
snd_rawmidi_t *midi_in;
int ret = snd_rawmidi_open(&midi_in, nullptr, name, SND_RAWMIDI_NONBLOCK);
if (ret >= 0) {
// Get display name.
snd_rawmidi_info_t *info;
snd_rawmidi_info_malloc(&info);
snd_rawmidi_info(midi_in, info);
connected_input_names.push_back(snd_rawmidi_info_get_name(info));
snd_rawmidi_info_free(info);
connected_inputs.push_back(InputConnection(device_index, midi_in));
// Only increment device_index for successfully connected devices.
device_index++;
}
}
if (name != nullptr) {
free(name);
}
}
snd_device_name_free_hint(hints);
unlock();
exit_thread.clear();
thread.start(MIDIDriverALSAMidi::thread_func, this);
return OK;
}
void MIDIDriverALSAMidi::close() {
exit_thread.set();
if (thread.is_started()) {
thread.wait_to_finish();
}
for (const InputConnection &conn : connected_inputs) {
snd_rawmidi_close(conn.rawmidi_ptr);
}
connected_inputs.clear();
connected_input_names.clear();
}
void MIDIDriverALSAMidi::lock() const {
mutex.lock();
}
void MIDIDriverALSAMidi::unlock() const {
mutex.unlock();
}
MIDIDriverALSAMidi::MIDIDriverALSAMidi() {
exit_thread.clear();
}
MIDIDriverALSAMidi::~MIDIDriverALSAMidi() {
close();
}
#endif // ALSAMIDI_ENABLED

View File

@@ -0,0 +1,79 @@
/**************************************************************************/
/* midi_driver_alsamidi.h */
/**************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/**************************************************************************/
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
/* */
/* 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. */
/**************************************************************************/
#pragma once
#ifdef ALSAMIDI_ENABLED
#include "core/os/midi_driver.h"
#include "core/os/mutex.h"
#include "core/os/thread.h"
#include "core/templates/safe_refcount.h"
#include "core/templates/vector.h"
#ifdef SOWRAP_ENABLED
#include "../alsa/asound-so_wrap.h"
#else
#include <alsa/asoundlib.h>
#endif
class MIDIDriverALSAMidi : public MIDIDriver {
Thread thread;
Mutex mutex;
struct InputConnection {
InputConnection() = default;
InputConnection(int p_device_index, snd_rawmidi_t *p_rawmidi);
Parser parser;
snd_rawmidi_t *rawmidi_ptr = nullptr;
// Read in and parse available data, forwarding complete events to Input.
void read();
};
Vector<InputConnection> connected_inputs;
SafeFlag exit_thread;
static void thread_func(void *p_udata);
void lock() const;
void unlock() const;
public:
virtual Error open() override;
virtual void close() override;
MIDIDriverALSAMidi();
virtual ~MIDIDriverALSAMidi();
};
#endif // ALSAMIDI_ENABLED