Initialize rtmidi async

On my system this opening the settings takes 10 seconds on a cold boot.
Letting it initialize async during boot reduces this delay drastically.
This commit is contained in:
Megamouse
2026-06-04 23:17:08 +02:00
committed by Ani
parent bf85a3fdd9
commit 8112c7cc19
9 changed files with 82 additions and 25 deletions
+3
View File
@@ -412,7 +412,10 @@ usb_device_rb3_midi_drums::usb_device_rb3_midi_drums(const std::array<u8, 7>& lo
usb_device_rb3_midi_drums::~usb_device_rb3_midi_drums() usb_device_rb3_midi_drums::~usb_device_rb3_midi_drums()
{ {
if (midi_in)
{
rtmidi_in_free(midi_in); rtmidi_in_free(midi_in);
}
} }
static const std::array<u8, 40> disabled_response = { static const std::array<u8, 40> disabled_response = {
+3
View File
@@ -100,7 +100,10 @@ usb_device_rb3_midi_guitar::usb_device_rb3_midi_guitar(const std::array<u8, 7>&
usb_device_rb3_midi_guitar::~usb_device_rb3_midi_guitar() usb_device_rb3_midi_guitar::~usb_device_rb3_midi_guitar()
{ {
if (midi_in)
{
rtmidi_in_free(midi_in); rtmidi_in_free(midi_in);
}
} }
static const std::array<u8, 40> disabled_response = { static const std::array<u8, 40> disabled_response = {
+3
View File
@@ -86,7 +86,10 @@ usb_device_rb3_midi_keyboard::usb_device_rb3_midi_keyboard(const std::array<u8,
usb_device_rb3_midi_keyboard::~usb_device_rb3_midi_keyboard() usb_device_rb3_midi_keyboard::~usb_device_rb3_midi_keyboard()
{ {
if (midi_in)
{
rtmidi_in_free(midi_in); rtmidi_in_free(midi_in);
}
} }
static const std::array<u8, 40> disabled_response = { static const std::array<u8, 40> disabled_response = {
+2 -2
View File
@@ -302,7 +302,7 @@ bool config_checker::check_config(cfg_mode mode, QString content_or_serial, QStr
const std::array<midi_device, max_midi_devices> def_devices = mc.get_selection_list(); const std::array<midi_device, max_midi_devices> def_devices = mc.get_selection_list();
mc.parse_devices(val); mc.parse_devices(val);
const std::array<midi_device, max_midi_devices> devices = mc.get_selection_list(); const std::array<midi_device, max_midi_devices>& devices = mc.get_selection_list();
for (usz i = 0; i < devices.size(); i++) for (usz i = 0; i < devices.size(); i++)
{ {
@@ -327,7 +327,7 @@ bool config_checker::check_config(cfg_mode mode, QString content_or_serial, QStr
const std::array<std::string, 4> def_devices = mc.get_selection_list(); const std::array<std::string, 4> def_devices = mc.get_selection_list();
mc.parse_devices(val); mc.parse_devices(val);
const std::array<std::string, 4> devices = mc.get_selection_list(); const std::array<std::string, 4>& devices = mc.get_selection_list();
for (usz i = 0; i < devices.size(); i++) for (usz i = 0; i < devices.size(); i++)
{ {
+3 -3
View File
@@ -14,7 +14,7 @@ microphone_creator::microphone_creator()
} }
// We need to recreate the localized string because the microphone creator is currently only created once. // We need to recreate the localized string because the microphone creator is currently only created once.
QString microphone_creator::get_none() QString microphone_creator::get_none() const
{ {
return tr("None", "Microphone device"); return tr("None", "Microphone device");
} }
@@ -49,12 +49,12 @@ void microphone_creator::refresh_list()
} }
} }
QStringList microphone_creator::get_microphone_list() const const QStringList& microphone_creator::get_microphone_list() const
{ {
return m_microphone_list; return m_microphone_list;
} }
std::array<std::string, 4> microphone_creator::get_selection_list() const const std::array<std::string, 4>& microphone_creator::get_selection_list() const
{ {
return m_sel_list; return m_sel_list;
} }
+3 -3
View File
@@ -15,12 +15,12 @@ class microphone_creator : public QObject
public: public:
microphone_creator(); microphone_creator();
QString get_none(); QString get_none() const;
std::string set_device(u32 num, const QString& text); std::string set_device(u32 num, const QString& text);
void parse_devices(std::string_view list); void parse_devices(std::string_view list);
void refresh_list(); void refresh_list();
QStringList get_microphone_list() const; const QStringList& get_microphone_list() const;
std::array<std::string, 4> get_selection_list() const; const std::array<std::string, 4>& get_selection_list() const;
private: private:
QStringList m_microphone_list; QStringList m_microphone_list;
+38 -5
View File
@@ -8,24 +8,57 @@
LOG_CHANNEL(cfg_log, "CFG"); LOG_CHANNEL(cfg_log, "CFG");
const auto midi_deleter = [](RtMidiWrapper* ptr) { if (ptr) rtmidi_in_free(ptr); };
using midi_ptr = std::unique_ptr<RtMidiWrapper, decltype(midi_deleter)>;
std::mutex midi_creator::m_midi_init_mutex = {};
std::unique_ptr<std::thread> midi_creator::m_midi_init_thread = {};
midi_creator::midi_creator() midi_creator::midi_creator()
{ {
setObjectName("midi_creator"); setObjectName("midi_creator");
// Initialize rtmidi async. This can take 10+ seconds on a cold start.
std::lock_guard lock(m_midi_init_mutex);
if (!m_midi_init_thread)
{
m_midi_init_thread = std::make_unique<std::thread>([]
{
[[maybe_unused]] midi_ptr midi_in(rtmidi_in_create_default());
});
}
}
midi_creator::~midi_creator()
{
std::lock_guard lock(m_midi_init_mutex);
if (m_midi_init_thread && m_midi_init_thread->joinable())
{
m_midi_init_thread->join();
}
} }
// We need to recreate the localized string because the midi creator is currently only created once. // We need to recreate the localized string because the midi creator is currently only created once.
QString midi_creator::get_none() QString midi_creator::get_none() const
{ {
return tr("None", "MIDI device"); return tr("None", "MIDI device");
} }
void midi_creator::refresh_list() void midi_creator::refresh_list()
{ {
// Wait for initial initialization
{
std::lock_guard lock(m_midi_init_mutex);
if (m_midi_init_thread && m_midi_init_thread->joinable())
{
m_midi_init_thread->join();
}
}
m_midi_list.clear(); m_midi_list.clear();
m_midi_list.append(get_none()); m_midi_list.append(get_none());
const auto deleter = [](RtMidiWrapper* ptr) { if (ptr) rtmidi_in_free(ptr); }; midi_ptr midi_in(rtmidi_in_create_default());
std::unique_ptr<RtMidiWrapper, decltype(deleter)> midi_in(rtmidi_in_create_default());
ensure(midi_in); ensure(midi_in);
if (!midi_in->ok) if (!midi_in->ok)
@@ -74,12 +107,12 @@ void midi_creator::refresh_list()
} }
} }
QStringList midi_creator::get_midi_list() const const QStringList& midi_creator::get_midi_list() const
{ {
return m_midi_list; return m_midi_list;
} }
std::array<midi_device, max_midi_devices> midi_creator::get_selection_list() const const std::array<midi_device, max_midi_devices>& midi_creator::get_selection_list() const
{ {
return m_sel_list; return m_sel_list;
} }
+10 -3
View File
@@ -3,6 +3,9 @@
#include "util/types.hpp" #include "util/types.hpp"
#include "Emu/Io/midi_config_types.h" #include "Emu/Io/midi_config_types.h"
#include <mutex>
#include <thread>
#include <QObject> #include <QObject>
#include <QStringList> #include <QStringList>
@@ -12,14 +15,18 @@ class midi_creator : public QObject
public: public:
midi_creator(); midi_creator();
QString get_none(); virtual ~midi_creator();
QString get_none() const;
std::string set_device(u32 num, const midi_device& device); std::string set_device(u32 num, const midi_device& device);
void parse_devices(std::string_view list); void parse_devices(std::string_view list);
void refresh_list(); void refresh_list();
QStringList get_midi_list() const; const QStringList& get_midi_list() const;
std::array<midi_device, max_midi_devices> get_selection_list() const; const std::array<midi_device, max_midi_devices>& get_selection_list() const;
private: private:
static std::mutex m_midi_init_mutex;
static std::unique_ptr<std::thread> m_midi_init_thread;
QStringList m_midi_list; QStringList m_midi_list;
std::array<midi_device, max_midi_devices> m_sel_list; std::array<midi_device, max_midi_devices> m_sel_list;
}; };
+14 -6
View File
@@ -933,8 +933,11 @@ settings_dialog::settings_dialog(std::shared_ptr<gui_settings> gui_settings, std
QStringList cur_list = m_emu_settings->m_microphone_creator.get_microphone_list(); QStringList cur_list = m_emu_settings->m_microphone_creator.get_microphone_list();
for (u32 subindex = 0; subindex < m_mics_combo.size(); subindex++) for (u32 subindex = 0; subindex < m_mics_combo.size(); subindex++)
{ {
if (subindex != index && m_mics_combo[subindex]->currentText() != mic_none) if (subindex == index) continue;
cur_list.removeOne(m_mics_combo[subindex]->currentText()); if (const QString text = m_mics_combo[subindex]->currentText(); text != mic_none)
{
cur_list.removeOne(text);
}
} }
m_mics_combo[index]->blockSignals(true); m_mics_combo[index]->blockSignals(true);
m_mics_combo[index]->clear(); m_mics_combo[index]->clear();
@@ -949,7 +952,9 @@ settings_dialog::settings_dialog(std::shared_ptr<gui_settings> gui_settings, std
{ {
m_emu_settings->SetSetting(emu_settings_type::MicrophoneDevices, m_emu_settings->m_microphone_creator.set_device(index, text)); m_emu_settings->SetSetting(emu_settings_type::MicrophoneDevices, m_emu_settings->m_microphone_creator.set_device(index, text));
if (const u32 next_index = index + 1; next_index < m_mics_combo.size() && text == mic_none) if (const u32 next_index = index + 1; next_index < m_mics_combo.size() && text == mic_none)
{
m_mics_combo[next_index]->setCurrentText(mic_none); m_mics_combo[next_index]->setCurrentText(mic_none);
}
propagate_used_devices(); propagate_used_devices();
}; };
@@ -1102,7 +1107,7 @@ settings_dialog::settings_dialog(std::shared_ptr<gui_settings> gui_settings, std
m_emu_settings->m_microphone_creator.parse_devices(m_emu_settings->GetSetting(emu_settings_type::MicrophoneDevices)); m_emu_settings->m_microphone_creator.parse_devices(m_emu_settings->GetSetting(emu_settings_type::MicrophoneDevices));
const std::array<std::string, 4> mic_sel_list = m_emu_settings->m_microphone_creator.get_selection_list(); const std::array<std::string, 4>& mic_sel_list = m_emu_settings->m_microphone_creator.get_selection_list();
for (s32 index = static_cast<int>(mic_sel_list.size()) - 1; index >= 0; index--) for (s32 index = static_cast<int>(mic_sel_list.size()) - 1; index >= 0; index--)
{ {
@@ -1276,8 +1281,11 @@ settings_dialog::settings_dialog(std::shared_ptr<gui_settings> gui_settings, std
QStringList cur_list = m_emu_settings->m_midi_creator.get_midi_list(); QStringList cur_list = m_emu_settings->m_midi_creator.get_midi_list();
for (u32 subindex = 0; subindex < m_midi_device_combo.size(); subindex++) for (u32 subindex = 0; subindex < m_midi_device_combo.size(); subindex++)
{ {
if (subindex != index && m_midi_device_combo[subindex]->currentText() != midi_none) if (subindex == index) continue;
cur_list.removeOne(m_midi_device_combo[subindex]->currentText()); if (const QString text = m_midi_device_combo[subindex]->currentText(); text != midi_none)
{
cur_list.removeOne(text);
}
} }
m_midi_device_combo[index]->blockSignals(true); m_midi_device_combo[index]->blockSignals(true);
m_midi_device_combo[index]->clear(); m_midi_device_combo[index]->clear();
@@ -1326,7 +1334,7 @@ settings_dialog::settings_dialog(std::shared_ptr<gui_settings> gui_settings, std
m_emu_settings->m_midi_creator.parse_devices(m_emu_settings->GetSetting(emu_settings_type::MidiDevices)); m_emu_settings->m_midi_creator.parse_devices(m_emu_settings->GetSetting(emu_settings_type::MidiDevices));
const std::array<midi_device, max_midi_devices> midi_sel_list = m_emu_settings->m_midi_creator.get_selection_list(); const std::array<midi_device, max_midi_devices>& midi_sel_list = m_emu_settings->m_midi_creator.get_selection_list();
for (s32 index = static_cast<int>(midi_sel_list.size()) - 1; index >= 0; index--) for (s32 index = static_cast<int>(midi_sel_list.size()) - 1; index >= 0; index--)
{ {