Path: blob/master/drivers/alsamidi/midi_driver_alsamidi.cpp
9973 views
/**************************************************************************/1/* midi_driver_alsamidi.cpp */2/**************************************************************************/3/* This file is part of: */4/* GODOT ENGINE */5/* https://godotengine.org */6/**************************************************************************/7/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */8/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */9/* */10/* Permission is hereby granted, free of charge, to any person obtaining */11/* a copy of this software and associated documentation files (the */12/* "Software"), to deal in the Software without restriction, including */13/* without limitation the rights to use, copy, modify, merge, publish, */14/* distribute, sublicense, and/or sell copies of the Software, and to */15/* permit persons to whom the Software is furnished to do so, subject to */16/* the following conditions: */17/* */18/* The above copyright notice and this permission notice shall be */19/* included in all copies or substantial portions of the Software. */20/* */21/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */22/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */23/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */24/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */25/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */26/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */27/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */28/**************************************************************************/2930#ifdef ALSAMIDI_ENABLED3132#include "midi_driver_alsamidi.h"3334#include "core/os/os.h"3536#include <cerrno>3738MIDIDriverALSAMidi::InputConnection::InputConnection(int p_device_index,39snd_rawmidi_t *p_rawmidi) :40parser(p_device_index), rawmidi_ptr(p_rawmidi) {}4142void MIDIDriverALSAMidi::InputConnection::read() {43int read_count;44do {45uint8_t buffer[32];46read_count = snd_rawmidi_read(rawmidi_ptr, buffer, sizeof(buffer));4748if (read_count < 0) {49if (read_count != -EAGAIN) {50ERR_PRINT("snd_rawmidi_read error: " + String(snd_strerror(read_count)));51}52} else {53for (int i = 0; i < read_count; i++) {54parser.parse_fragment(buffer[i]);55}56}57} while (read_count > 0);58}5960void MIDIDriverALSAMidi::thread_func(void *p_udata) {61MIDIDriverALSAMidi *md = static_cast<MIDIDriverALSAMidi *>(p_udata);6263while (!md->exit_thread.is_set()) {64md->lock();65for (InputConnection &conn : md->connected_inputs) {66conn.read();67}68md->unlock();6970OS::get_singleton()->delay_usec(1000);71}72}7374Error MIDIDriverALSAMidi::open() {75void **hints;7677if (snd_device_name_hint(-1, "rawmidi", &hints) < 0) {78return ERR_CANT_OPEN;79}8081lock();82int device_index = 0;83for (void **h = hints; *h != nullptr; h++) {84char *name = snd_device_name_get_hint(*h, "NAME");8586if (name != nullptr) {87snd_rawmidi_t *midi_in;88int ret = snd_rawmidi_open(&midi_in, nullptr, name, SND_RAWMIDI_NONBLOCK);89if (ret >= 0) {90// Get display name.91snd_rawmidi_info_t *info;92snd_rawmidi_info_malloc(&info);93snd_rawmidi_info(midi_in, info);94connected_input_names.push_back(snd_rawmidi_info_get_name(info));95snd_rawmidi_info_free(info);9697connected_inputs.push_back(InputConnection(device_index, midi_in));98// Only increment device_index for successfully connected devices.99device_index++;100}101}102103if (name != nullptr) {104free(name);105}106}107snd_device_name_free_hint(hints);108unlock();109110exit_thread.clear();111thread.start(MIDIDriverALSAMidi::thread_func, this);112113return OK;114}115116void MIDIDriverALSAMidi::close() {117exit_thread.set();118if (thread.is_started()) {119thread.wait_to_finish();120}121122for (const InputConnection &conn : connected_inputs) {123snd_rawmidi_close(conn.rawmidi_ptr);124}125126connected_inputs.clear();127connected_input_names.clear();128}129130void MIDIDriverALSAMidi::lock() const {131mutex.lock();132}133134void MIDIDriverALSAMidi::unlock() const {135mutex.unlock();136}137138MIDIDriverALSAMidi::MIDIDriverALSAMidi() {139exit_thread.clear();140}141142MIDIDriverALSAMidi::~MIDIDriverALSAMidi() {143close();144}145146#endif // ALSAMIDI_ENABLED147148149