mirror of
https://github.com/WarmUpTill/SceneSwitcher.git
synced 2026-08-22 01:05:53 -05:00
Adapt to new libremidi version
This commit is contained in:
@@ -13,21 +13,45 @@ if(NOT EXISTS "${LIBREMIDI_DIR}/CMakeLists.txt")
|
||||
endif()
|
||||
add_subdirectory("${LIBREMIDI_DIR}" "${LIBREMIDI_DIR}/build" EXCLUDE_FROM_ALL)
|
||||
|
||||
# --- End of section ---
|
||||
|
||||
add_library(${PROJECT_NAME} MODULE)
|
||||
|
||||
if(OS_WINDOWS)
|
||||
if(MSVC)
|
||||
target_compile_options(libremidi PUBLIC /wd4251 /wd4267 /wd4275)
|
||||
target_compile_options(libremidi PRIVATE /wd4251 /wd4267 /wd4275 /wd4101
|
||||
/wd4244 /wd4018)
|
||||
target_compile_options(${PROJECT_NAME} PRIVATE /wd4101 /wd4244 /wd4018)
|
||||
endif()
|
||||
else()
|
||||
target_compile_options(
|
||||
libremidi
|
||||
PUBLIC -Wno-error=conversion -Wno-error=unused-result -Wno-error=shadow
|
||||
-Wno-error=unused-parameter -Wno-error=deprecated-declarations
|
||||
PUBLIC -Wno-error=conversion
|
||||
-Wno-error=unused-result
|
||||
-Wno-error=shadow
|
||||
-Wno-error=unused-parameter
|
||||
-Wno-error=unused-variable
|
||||
-Wno-error=deprecated-declarations
|
||||
-Wno-error=sign-compare)
|
||||
if(OS_MACOS)
|
||||
target_compile_options(libremidi PUBLIC -Wno-error=vla-extension)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# --- End of section ---
|
||||
|
||||
add_library(${PROJECT_NAME} MODULE)
|
||||
if(OS_MACOS)
|
||||
set(PATCH_FILE
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/remove-bit-cast-for-macos-build.patch")
|
||||
execute_process(
|
||||
COMMAND git apply ${PATCH_FILE}
|
||||
WORKING_DIRECTORY ${LIBREMIDI_DIR}
|
||||
RESULT_VARIABLE PATCH_RESULT)
|
||||
if(PATCH_RESULT EQUAL 0)
|
||||
message("Libremidi patch \"${PATCH_FILE}\" applied successfully!")
|
||||
else()
|
||||
message(
|
||||
WARNING "Libremidi patch \"${PATCH_FILE}\" did NOT apply successfully!")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
target_sources(
|
||||
${PROJECT_NAME}
|
||||
|
||||
@@ -12,16 +12,18 @@
|
||||
|
||||
namespace advss {
|
||||
|
||||
static std::map<std::pair<MidiDeviceType, int>, MidiDeviceInstance *>
|
||||
SetupMidiMessageVector()
|
||||
std::map<std::pair<MidiDeviceType, std::string>, MidiDeviceInstance *>
|
||||
MidiDeviceInstance::devices = {};
|
||||
|
||||
static bool registerClearMessageBufferStep()
|
||||
{
|
||||
AddIntervalResetStep(
|
||||
MidiDeviceInstance::ClearMessageBuffersOfAllDevices);
|
||||
return {};
|
||||
return true;
|
||||
}
|
||||
|
||||
std::map<std::pair<MidiDeviceType, int>, MidiDeviceInstance *>
|
||||
MidiDeviceInstance::devices = SetupMidiMessageVector();
|
||||
static bool registerClearMessageBufferStepDone =
|
||||
registerClearMessageBufferStep();
|
||||
|
||||
void MidiDeviceInstance::ClearMessageBuffersOfAllDevices()
|
||||
{
|
||||
@@ -61,26 +63,24 @@ MidiMessage::MidiMessage(const libremidi::message &message)
|
||||
|
||||
void MidiMessage::Save(obs_data_t *obj) const
|
||||
{
|
||||
auto data = obs_data_create();
|
||||
OBSDataAutoRelease data = obs_data_create();
|
||||
obs_data_set_bool(data, "typeIsOptional", _typeIsOptional);
|
||||
obs_data_set_int(data, "type", static_cast<int>(_type));
|
||||
_channel.Save(data, "channel");
|
||||
_note.Save(data, "note");
|
||||
_value.Save(data, "value");
|
||||
obs_data_set_obj(obj, "midiMessage", data);
|
||||
obs_data_release(data);
|
||||
}
|
||||
|
||||
void MidiMessage::Load(obs_data_t *obj)
|
||||
{
|
||||
auto data = obs_data_get_obj(obj, "midiMessage");
|
||||
OBSDataAutoRelease data = obs_data_get_obj(obj, "midiMessage");
|
||||
_typeIsOptional = obs_data_get_bool(data, "typeIsOptional");
|
||||
_type = static_cast<libremidi::message_type>(
|
||||
obs_data_get_int(data, "type"));
|
||||
_channel.Load(data, "channel");
|
||||
_note.Load(data, "note");
|
||||
_value.Load(data, "value");
|
||||
obs_data_release(data);
|
||||
}
|
||||
|
||||
int MidiMessage::GetMidiNote(const libremidi::message &msg)
|
||||
@@ -232,13 +232,14 @@ bool MidiMessage::Matches(const MidiMessage &m) const
|
||||
return channelMatch && noteMatch && valueMatch && typeMatch;
|
||||
}
|
||||
|
||||
MidiDeviceInstance *MidiDeviceInstance::GetDevice(MidiDeviceType type, int port)
|
||||
MidiDeviceInstance *MidiDeviceInstance::GetDevice(MidiDeviceType type,
|
||||
const std::string &name)
|
||||
{
|
||||
if (port < 0) {
|
||||
if (name.empty()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
auto key = std::make_pair(type, port);
|
||||
auto key = std::make_pair(type, name);
|
||||
auto it = devices.find(key);
|
||||
if (it != devices.end()) {
|
||||
it->second->OpenPort();
|
||||
@@ -248,47 +249,147 @@ MidiDeviceInstance *MidiDeviceInstance::GetDevice(MidiDeviceType type, int port)
|
||||
try {
|
||||
auto device = new MidiDeviceInstance();
|
||||
device->_type = type;
|
||||
device->_port = port;
|
||||
device->_name = name;
|
||||
devices[key] = device;
|
||||
device->OpenPort();
|
||||
return device;
|
||||
} catch (const libremidi::driver_error &error) {
|
||||
blog(LOG_WARNING,
|
||||
"Failed to create midi %s device instance for port #%d: %s",
|
||||
type == MidiDeviceType::INPUT ? "input" : "output", port,
|
||||
error.what());
|
||||
"Failed to create midi %s device instance for port '%s': %s",
|
||||
type == MidiDeviceType::INPUT ? "input" : "output",
|
||||
name.c_str(), error.what());
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
static std::string
|
||||
getNameFromPortInformation(const libremidi::port_information &info)
|
||||
{
|
||||
std::string name = info.manufacturer + " " + info.device_name + " " +
|
||||
info.port_name + "] " + info.display_name;
|
||||
name.erase(name.begin(), std::find_if(name.begin(), name.end(),
|
||||
[](char c) { return c != ' '; }));
|
||||
return "[" + name;
|
||||
}
|
||||
|
||||
static inline QStringList getInputDeviceNames()
|
||||
{
|
||||
QStringList devices;
|
||||
try {
|
||||
libremidi::observer obs;
|
||||
for (const libremidi::input_port &port :
|
||||
obs.get_input_ports()) {
|
||||
devices << QString::fromStdString(
|
||||
getNameFromPortInformation(port));
|
||||
}
|
||||
} catch (const libremidi::driver_error &error) {
|
||||
blog(LOG_WARNING, "Failed to get midi input devices: %s",
|
||||
error.what());
|
||||
}
|
||||
return devices;
|
||||
}
|
||||
|
||||
static inline QStringList getOutputDeviceNames()
|
||||
{
|
||||
QStringList devices;
|
||||
try {
|
||||
libremidi::observer obs;
|
||||
for (const libremidi::output_port &port :
|
||||
obs.get_output_ports()) {
|
||||
devices << QString::fromStdString(
|
||||
getNameFromPortInformation(port));
|
||||
}
|
||||
} catch (const libremidi::driver_error &error) {
|
||||
blog(LOG_WARNING, "Failed to get midi output devices: %s",
|
||||
error.what());
|
||||
}
|
||||
return devices;
|
||||
}
|
||||
|
||||
static std::string getPortNameFromNumber(MidiDeviceType type, int port)
|
||||
{
|
||||
if (port < 0) {
|
||||
return "";
|
||||
}
|
||||
|
||||
QStringList devices;
|
||||
if (type == MidiDeviceType::INPUT) {
|
||||
devices = getInputDeviceNames();
|
||||
} else {
|
||||
devices = getOutputDeviceNames();
|
||||
}
|
||||
|
||||
if (port >= devices.size()) {
|
||||
return "";
|
||||
}
|
||||
return devices.at(port).toStdString();
|
||||
}
|
||||
|
||||
MidiDeviceInstance *MidiDeviceInstance::GetDevice(MidiDeviceType type, int port)
|
||||
{
|
||||
std::string name = getPortNameFromNumber(type, port);
|
||||
return GetDevice(type, name);
|
||||
}
|
||||
|
||||
void MidiDevice::Save(obs_data_t *obj) const
|
||||
{
|
||||
auto data = obs_data_create();
|
||||
OBSDataAutoRelease data = obs_data_create();
|
||||
obs_data_set_int(data, "type", static_cast<int>(_type));
|
||||
obs_data_set_int(data, "port", _dev ? _dev->_port : -1);
|
||||
obs_data_set_string(data, "portName", _dev ? _dev->_name.c_str() : "");
|
||||
obs_data_set_obj(obj, "midiDevice", data);
|
||||
obs_data_release(data);
|
||||
}
|
||||
|
||||
void MidiDevice::Load(obs_data_t *obj)
|
||||
{
|
||||
auto data = obs_data_get_obj(obj, "midiDevice");
|
||||
OBSDataAutoRelease data = obs_data_get_obj(obj, "midiDevice");
|
||||
_type = static_cast<MidiDeviceType>(obs_data_get_int(data, "type"));
|
||||
obs_data_set_default_int(data, "port", -1);
|
||||
_port = obs_data_get_int(data, "port");
|
||||
_dev = MidiDeviceInstance::GetDevice(_type, _port);
|
||||
obs_data_release(data);
|
||||
// TODO: Remove this fallback at some point
|
||||
if (obs_data_has_user_value(data, "port")) {
|
||||
auto port = obs_data_get_int(data, "port");
|
||||
_dev = MidiDeviceInstance::GetDevice(_type, port);
|
||||
if (_dev) {
|
||||
_name = _dev->_name;
|
||||
}
|
||||
} else {
|
||||
_name = obs_data_get_string(data, "portName");
|
||||
_dev = MidiDeviceInstance::GetDevice(_type, _name);
|
||||
}
|
||||
}
|
||||
|
||||
bool MidiDevice::SendMessge(const MidiMessage &m)
|
||||
{
|
||||
if (_type == MidiDeviceType::INPUT || _port == -1 || !_dev) {
|
||||
if (_type == MidiDeviceType::INPUT || _name.empty() || !_dev) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return _dev->SendMessge(m);
|
||||
}
|
||||
|
||||
static std::optional<libremidi::output_port>
|
||||
getOutPortFromName(const std::string &name)
|
||||
{
|
||||
libremidi::observer obs;
|
||||
for (const libremidi::output_port &port : obs.get_output_ports()) {
|
||||
if (getNameFromPortInformation(port) == name) {
|
||||
return port;
|
||||
}
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
static std::optional<libremidi::input_port>
|
||||
getInPortFromName(const std::string &name)
|
||||
{
|
||||
libremidi::observer obs;
|
||||
for (const libremidi::input_port &port : obs.get_input_ports()) {
|
||||
if (getNameFromPortInformation(port) == name) {
|
||||
return port;
|
||||
}
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
bool MidiDeviceInstance::OpenPort()
|
||||
{
|
||||
if ((_type == MidiDeviceType::INPUT && in.is_port_open()) ||
|
||||
@@ -297,44 +398,61 @@ bool MidiDeviceInstance::OpenPort()
|
||||
}
|
||||
|
||||
if (_type == MidiDeviceType::OUTPUT) {
|
||||
auto port = getOutPortFromName(_name);
|
||||
if (!port) {
|
||||
blog(LOG_INFO,
|
||||
"Could not find output port with name '%s'",
|
||||
_name.c_str());
|
||||
return false;
|
||||
}
|
||||
try {
|
||||
out.open_port(_port);
|
||||
blog(LOG_INFO, "Opened output midi port #%d", _port);
|
||||
out.open_port(*port);
|
||||
blog(LOG_INFO, "Opened output midi port '%s'",
|
||||
_name.c_str());
|
||||
return true;
|
||||
} catch (const libremidi::driver_error &error) {
|
||||
blog(LOG_WARNING,
|
||||
"Failed to open output midi port #%d: %s", _port,
|
||||
error.what());
|
||||
"Failed to open output midi port '%s': %s",
|
||||
_name.c_str(), error.what());
|
||||
} catch (const libremidi::system_error &error) {
|
||||
blog(LOG_WARNING,
|
||||
"Failed to open output midi port #%d: %s", _port,
|
||||
error.what());
|
||||
"Failed to open output midi port '%s': %s",
|
||||
_name.c_str(), error.what());
|
||||
} catch (const libremidi::midi_exception &error) {
|
||||
blog(LOG_WARNING,
|
||||
"Failed to open output midi port #%d: %s", _port,
|
||||
error.what());
|
||||
"Failed to open output midi port '%s': %s",
|
||||
_name.c_str(), error.what());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
auto cb = [this](const libremidi::message &m) {
|
||||
this->ReceiveMidiMessage(m);
|
||||
auto cb = [this](libremidi::message &&m) {
|
||||
ReceiveMidiMessage(std::move(m));
|
||||
};
|
||||
|
||||
in.set_callback(cb);
|
||||
in = libremidi::midi_in{
|
||||
libremidi::input_configuration{.on_message = cb}};
|
||||
|
||||
auto port = getInPortFromName(_name);
|
||||
if (!port) {
|
||||
blog(LOG_INFO, "Could not find input port with name '%s'",
|
||||
_name.c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
in.open_port(_port);
|
||||
blog(LOG_INFO, "Opened input midi port #%d", _port);
|
||||
in.open_port(*port);
|
||||
blog(LOG_INFO, "Opened input midi port '%s'", _name.c_str());
|
||||
return true;
|
||||
} catch (const libremidi::driver_error &error) {
|
||||
blog(LOG_WARNING, "Failed to open input midi port #%d: %s",
|
||||
_port, error.what());
|
||||
blog(LOG_WARNING, "Failed to open input midi port '%s': %s",
|
||||
_name.c_str(), error.what());
|
||||
} catch (const libremidi::system_error &error) {
|
||||
blog(LOG_WARNING, "Failed to open input midi port #%d: %s",
|
||||
_port, error.what());
|
||||
blog(LOG_WARNING, "Failed to open input midi port '%s': %s",
|
||||
_name.c_str(), error.what());
|
||||
} catch (const libremidi::midi_exception &error) {
|
||||
blog(LOG_WARNING, "Failed to open input midi port #%d: %s",
|
||||
_port, error.what());
|
||||
blog(LOG_WARNING, "Failed to open input midi port '%s': %s",
|
||||
_name.c_str(), error.what());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@@ -349,40 +467,36 @@ void MidiDeviceInstance::ClosePort()
|
||||
if (_type == MidiDeviceType::OUTPUT) {
|
||||
try {
|
||||
out.close_port();
|
||||
blog(LOG_INFO, "Closed output midi port #%d", _port);
|
||||
blog(LOG_INFO, "Closed output midi port '%s'",
|
||||
_name.c_str());
|
||||
} catch (const libremidi::driver_error &error) {
|
||||
blog(LOG_WARNING,
|
||||
"Failed to close output midi port #%d: %s", _port,
|
||||
error.what());
|
||||
"Failed to close output midi port '%s': %s",
|
||||
_name.c_str(), error.what());
|
||||
} catch (const libremidi::system_error &error) {
|
||||
blog(LOG_WARNING,
|
||||
"Failed to close output midi port #%d: %s", _port,
|
||||
error.what());
|
||||
"Failed to close output midi port '%s': %s",
|
||||
_name.c_str(), error.what());
|
||||
} catch (const libremidi::midi_exception &error) {
|
||||
blog(LOG_WARNING,
|
||||
"Failed to close output midi port #%d: %s", _port,
|
||||
error.what());
|
||||
"Failed to close output midi port '%s': %s",
|
||||
_name.c_str(), error.what());
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
auto cb = [this](const libremidi::message &m) {
|
||||
this->ReceiveMidiMessage(m);
|
||||
};
|
||||
|
||||
in.set_callback(cb);
|
||||
try {
|
||||
in.close_port();
|
||||
blog(LOG_INFO, "Closed input midi port #%d", _port);
|
||||
blog(LOG_INFO, "Closed input midi port '%s'", _name.c_str());
|
||||
} catch (const libremidi::driver_error &error) {
|
||||
blog(LOG_WARNING, "Failed to close input midi port #%d: %s",
|
||||
_port, error.what());
|
||||
blog(LOG_WARNING, "Failed to close input midi port '%s': %s",
|
||||
_name.c_str(), error.what());
|
||||
} catch (const libremidi::system_error &error) {
|
||||
blog(LOG_WARNING, "Failed to close input midi port #%d: %s",
|
||||
_port, error.what());
|
||||
blog(LOG_WARNING, "Failed to close input midi port '%s': %s",
|
||||
_name.c_str(), error.what());
|
||||
} catch (const libremidi::midi_exception &error) {
|
||||
blog(LOG_WARNING, "Failed to close input midi port #%d: %s",
|
||||
_port, error.what());
|
||||
blog(LOG_WARNING, "Failed to close input midi port '%s': %s",
|
||||
_name.c_str(), error.what());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -395,31 +509,35 @@ bool MidiDeviceInstance::SendMessge(const MidiMessage &m)
|
||||
|
||||
switch (m.Type()) {
|
||||
case libremidi::message_type::NOTE_OFF:
|
||||
message = libremidi::message::note_off(channel, note, value);
|
||||
message = libremidi::channel_events::note_off(channel, note,
|
||||
value);
|
||||
break;
|
||||
case libremidi::message_type::NOTE_ON:
|
||||
message = libremidi::message::note_on(channel, note, value);
|
||||
break;
|
||||
case libremidi::message_type::CONTROL_CHANGE:
|
||||
message = libremidi::message::control_change(channel, note,
|
||||
message = libremidi::channel_events::note_on(channel, note,
|
||||
value);
|
||||
break;
|
||||
case libremidi::message_type::CONTROL_CHANGE:
|
||||
message = libremidi::channel_events::control_change(
|
||||
channel, note, value);
|
||||
break;
|
||||
case libremidi::message_type::PROGRAM_CHANGE:
|
||||
message = libremidi::message::program_change(channel, value);
|
||||
message = libremidi::channel_events::program_change(channel,
|
||||
value);
|
||||
break;
|
||||
case libremidi::message_type::PITCH_BEND:
|
||||
message = libremidi::message::pitch_bend(
|
||||
message = libremidi::channel_events::pitch_bend(
|
||||
channel, (value <= 64 ? 0 : value - 64) * 2, value);
|
||||
break;
|
||||
case libremidi::message_type::POLY_PRESSURE:
|
||||
message =
|
||||
libremidi::message::poly_pressure(channel, note, value);
|
||||
message = libremidi::channel_events::poly_pressure(channel,
|
||||
note, value);
|
||||
break;
|
||||
case libremidi::message_type::AFTERTOUCH:
|
||||
message = libremidi::message::aftertouch(channel, value);
|
||||
message = libremidi::channel_events::aftertouch(channel, value);
|
||||
break;
|
||||
default:
|
||||
message = {libremidi::message::make_command(m.Type(), channel),
|
||||
message = {libremidi::channel_events::make_command(m.Type(),
|
||||
channel),
|
||||
(unsigned char)note, (unsigned char)value};
|
||||
blog(LOG_WARNING,
|
||||
"sending midi message of non-default type \"%s\"",
|
||||
@@ -442,7 +560,7 @@ const std::vector<MidiMessage> &MidiDeviceInstance::GetMessages()
|
||||
return _messages;
|
||||
}
|
||||
|
||||
void MidiDeviceInstance::ReceiveMidiMessage(const libremidi::message &msg)
|
||||
void MidiDeviceInstance::ReceiveMidiMessage(libremidi::message &&msg)
|
||||
{
|
||||
auto lock = LockContext();
|
||||
_messages.emplace_back(msg);
|
||||
@@ -479,7 +597,7 @@ void MidiDevice::ClearMessageBuffer()
|
||||
|
||||
const std::vector<MidiMessage> *MidiDevice::GetMessages(bool ignoreSkip)
|
||||
{
|
||||
if (_type == MidiDeviceType::OUTPUT || _port == -1 || !_dev ||
|
||||
if (_type == MidiDeviceType::OUTPUT || _name.empty() || !_dev ||
|
||||
(_dev->_skipBufferClear && !ignoreSkip)) {
|
||||
return nullptr;
|
||||
}
|
||||
@@ -487,81 +605,9 @@ const std::vector<MidiMessage> *MidiDevice::GetMessages(bool ignoreSkip)
|
||||
return &_dev->GetMessages();
|
||||
}
|
||||
|
||||
static QString portToName(bool input, int port)
|
||||
{
|
||||
std::string name;
|
||||
try {
|
||||
if (input) {
|
||||
auto midiin = libremidi::midi_in();
|
||||
name = midiin.get_port_name(port);
|
||||
} else {
|
||||
auto midiout = libremidi::midi_out();
|
||||
name = midiout.get_port_name(port);
|
||||
}
|
||||
} catch (const libremidi::driver_error &error) {
|
||||
blog(LOG_WARNING,
|
||||
"Failed to get midi %s device name of port #%d: %s",
|
||||
input ? "input" : "output", port, error.what());
|
||||
}
|
||||
|
||||
const QString deviceNamePattern =
|
||||
obs_module_text("AdvSceneSwitcher.midi.deviceNamePattern");
|
||||
return deviceNamePattern.arg(QString::number(port),
|
||||
QString::fromStdString(name));
|
||||
}
|
||||
|
||||
std::string MidiDevice::GetInputName() const
|
||||
{
|
||||
return portToName(true, _port).toStdString();
|
||||
}
|
||||
|
||||
std::string MidiDevice::GetOutputName() const
|
||||
{
|
||||
return portToName(false, _port).toStdString();
|
||||
}
|
||||
|
||||
std::string MidiDevice::Name() const
|
||||
{
|
||||
if (_port < 0) {
|
||||
return "";
|
||||
}
|
||||
|
||||
if (_type == MidiDeviceType::INPUT) {
|
||||
return GetInputName();
|
||||
}
|
||||
return GetOutputName();
|
||||
}
|
||||
|
||||
static inline QStringList getInputDeviceNames()
|
||||
{
|
||||
QStringList devices;
|
||||
try {
|
||||
auto midiin = libremidi::midi_in();
|
||||
auto nPorts = midiin.get_port_count();
|
||||
for (unsigned i = 0; i < nPorts; i++) {
|
||||
devices << portToName(true, i);
|
||||
}
|
||||
} catch (const libremidi::driver_error &error) {
|
||||
blog(LOG_WARNING, "Failed to get midi input devices: %s",
|
||||
error.what());
|
||||
}
|
||||
return devices;
|
||||
}
|
||||
|
||||
static inline QStringList getOutputDeviceNames()
|
||||
{
|
||||
QStringList devices;
|
||||
try {
|
||||
auto midiout = libremidi::midi_out();
|
||||
auto nPorts = midiout.get_port_count();
|
||||
for (unsigned i = 0; i < nPorts; i++) {
|
||||
devices << portToName(false, i);
|
||||
}
|
||||
} catch (const libremidi::driver_error &error) {
|
||||
blog(LOG_WARNING, "Failed to get midi output devices: %s",
|
||||
error.what());
|
||||
}
|
||||
return devices;
|
||||
return _name;
|
||||
}
|
||||
|
||||
MidiDeviceSelection::MidiDeviceSelection(QWidget *parent, MidiDeviceType t)
|
||||
@@ -591,7 +637,8 @@ void MidiDeviceSelection::IdxChangedHelper(int idx)
|
||||
emit DeviceSelectionChanged(MidiDevice());
|
||||
}
|
||||
|
||||
auto devInstance = MidiDeviceInstance::GetDevice(_type, idx - 1);
|
||||
auto name = currentText().toStdString();
|
||||
auto devInstance = MidiDeviceInstance::GetDevice(_type, name);
|
||||
if (!devInstance) {
|
||||
DisplayMessage(obs_module_text(
|
||||
"AdvSceneSwitcher.midi.deviceOpenFail"));
|
||||
@@ -602,7 +649,7 @@ void MidiDeviceSelection::IdxChangedHelper(int idx)
|
||||
|
||||
MidiDevice dev;
|
||||
dev._type = _type;
|
||||
dev._port = idx - 1;
|
||||
dev._name = name;
|
||||
dev._dev = devInstance;
|
||||
emit DeviceSelectionChanged(dev);
|
||||
}
|
||||
@@ -922,13 +969,18 @@ void MidiMessageSelection::ValueChanged(const NumberVariable<int> &v)
|
||||
|
||||
QStringList GetAllNotes()
|
||||
{
|
||||
QStringList result;
|
||||
QStringList notes = {"C", "C#", "D", "D#", "E", "F",
|
||||
"F#", "G", "G#", "A", "A#", "B"};
|
||||
for (int octave = -1; octave <= 9; octave++) {
|
||||
for (int noteIndex = 0; noteIndex < 12; noteIndex++) {
|
||||
result << notes[noteIndex] + QString::number(octave);
|
||||
static bool done = false;
|
||||
static QStringList result;
|
||||
static const QStringList notes = {"C", "C#", "D", "D#", "E", "F",
|
||||
"F#", "G", "G#", "A", "A#", "B"};
|
||||
if (!done) {
|
||||
for (int octave = -1; octave <= 9; octave++) {
|
||||
for (int noteIndex = 0; noteIndex < 12; noteIndex++) {
|
||||
result << notes[noteIndex] +
|
||||
QString::number(octave);
|
||||
}
|
||||
}
|
||||
done = true;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -5,11 +5,8 @@
|
||||
#include <QComboBox>
|
||||
#include <obs-data.h>
|
||||
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable : 4005)
|
||||
#define LIBREMIDI_HEADER_ONLY 1
|
||||
#include <libremidi/libremidi.hpp>
|
||||
#pragma warning(pop)
|
||||
|
||||
namespace advss {
|
||||
|
||||
@@ -60,6 +57,8 @@ enum class MidiDeviceType {
|
||||
|
||||
class MidiDeviceInstance {
|
||||
public:
|
||||
static MidiDeviceInstance *GetDevice(MidiDeviceType type,
|
||||
const std::string &);
|
||||
static MidiDeviceInstance *GetDevice(MidiDeviceType type, int port);
|
||||
static void ClearMessageBuffersOfAllDevices();
|
||||
static void ResetAllDevices();
|
||||
@@ -71,18 +70,24 @@ private:
|
||||
void ClosePort();
|
||||
bool SendMessge(const MidiMessage &);
|
||||
const std::vector<MidiMessage> &GetMessages();
|
||||
void ReceiveMidiMessage(const libremidi::message &);
|
||||
void ReceiveMidiMessage(libremidi::message &&);
|
||||
void ClearMessageBuffer();
|
||||
|
||||
static std::map<std::pair<MidiDeviceType, int>, MidiDeviceInstance *>
|
||||
static std::map<std::pair<MidiDeviceType, std::string>,
|
||||
MidiDeviceInstance *>
|
||||
devices;
|
||||
|
||||
bool _skipBufferClear = false;
|
||||
|
||||
MidiDeviceType _type = MidiDeviceType::INPUT;
|
||||
int _port = -1;
|
||||
libremidi::midi_in in;
|
||||
libremidi::midi_out out;
|
||||
std::string _name;
|
||||
libremidi::midi_in in =
|
||||
libremidi::midi_in(libremidi::input_configuration{
|
||||
[this](libremidi::message &&message) {
|
||||
ReceiveMidiMessage(std::move(message));
|
||||
}});
|
||||
libremidi::midi_out out =
|
||||
libremidi::midi_out(libremidi::output_configuration());
|
||||
std::vector<MidiMessage> _messages;
|
||||
|
||||
friend class MidiDevice;
|
||||
@@ -110,11 +115,8 @@ public:
|
||||
bool DeviceSelected() { return !!_dev; }
|
||||
|
||||
private:
|
||||
std::string GetInputName() const;
|
||||
std::string GetOutputName() const;
|
||||
|
||||
MidiDeviceType _type = MidiDeviceType::INPUT;
|
||||
int _port = -1;
|
||||
std::string _name;
|
||||
MidiDeviceInstance *_dev = nullptr;
|
||||
|
||||
friend class MidiDeviceSelection;
|
||||
|
||||
42
plugins/midi/remove-bit-cast-for-macos-build.patch
Normal file
42
plugins/midi/remove-bit-cast-for-macos-build.patch
Normal file
@@ -0,0 +1,42 @@
|
||||
diff --git a/include/libremidi/backends/coremidi/helpers.hpp b/include/libremidi/backends/coremidi/helpers.hpp
|
||||
index 08e62ff..ba35ec7 100644
|
||||
--- a/include/libremidi/backends/coremidi/helpers.hpp
|
||||
+++ b/include/libremidi/backends/coremidi/helpers.hpp
|
||||
@@ -207,7 +207,8 @@ inline CFStringRef ConnectedEndpointName(MIDIEndpointRef endpoint)
|
||||
inline MIDIObjectRef
|
||||
locate_object(auto& self, const port_information& info, MIDIObjectType requested_type)
|
||||
{
|
||||
- auto uid = std::bit_cast<std::int32_t>((uint32_t)info.port);
|
||||
+ std::int32_t uid;
|
||||
+ std::memcpy(&uid, &(info.port), sizeof(uint32_t));
|
||||
MIDIObjectRef object{};
|
||||
MIDIObjectType type{};
|
||||
auto ret = MIDIObjectFindByUniqueID(uid, &object, &type);
|
||||
diff --git a/include/libremidi/backends/coremidi/observer.hpp b/include/libremidi/backends/coremidi/observer.hpp
|
||||
index defe623..12a936a 100644
|
||||
--- a/include/libremidi/backends/coremidi/observer.hpp
|
||||
+++ b/include/libremidi/backends/coremidi/observer.hpp
|
||||
@@ -78,13 +78,16 @@ public:
|
||||
if (!ok)
|
||||
return {};
|
||||
|
||||
- return std::conditional_t<Input, input_port, output_port>{
|
||||
- {.client = (std::uintptr_t)this->client,
|
||||
- .port = std::bit_cast<uint32_t>(get_int_property(obj, kMIDIPropertyUniqueID)),
|
||||
- .manufacturer = get_string_property(obj, kMIDIPropertyManufacturer),
|
||||
- .device_name = get_string_property(obj, kMIDIPropertyModel),
|
||||
- .port_name = get_string_property(obj, kMIDIPropertyName),
|
||||
- .display_name = get_string_property(obj, kMIDIPropertyDisplayName)}};
|
||||
+ std::conditional_t<Input, input_port, output_port> ret{
|
||||
+ {.client = (std::uintptr_t)this->client,
|
||||
+ .port = 0,
|
||||
+ .manufacturer = get_string_property(obj, kMIDIPropertyManufacturer),
|
||||
+ .device_name = get_string_property(obj, kMIDIPropertyModel),
|
||||
+ .port_name = get_string_property(obj, kMIDIPropertyName),
|
||||
+ .display_name = get_string_property(obj, kMIDIPropertyDisplayName)}};
|
||||
+ auto prop = get_int_property(obj, kMIDIPropertyUniqueID);
|
||||
+ std::memcpy(&ret.port, &(prop), sizeof(prop));
|
||||
+ return ret;
|
||||
}
|
||||
|
||||
std::vector<libremidi::input_port> get_input_ports() const noexcept override
|
||||
Reference in New Issue
Block a user