diff --git a/rpcs3/Emu/Io/RB3MidiDrums.cpp b/rpcs3/Emu/Io/RB3MidiDrums.cpp index 61b172bbdd..4bdc253c69 100644 --- a/rpcs3/Emu/Io/RB3MidiDrums.cpp +++ b/rpcs3/Emu/Io/RB3MidiDrums.cpp @@ -412,7 +412,10 @@ usb_device_rb3_midi_drums::usb_device_rb3_midi_drums(const std::array& lo usb_device_rb3_midi_drums::~usb_device_rb3_midi_drums() { - rtmidi_in_free(midi_in); + if (midi_in) + { + rtmidi_in_free(midi_in); + } } static const std::array disabled_response = { diff --git a/rpcs3/Emu/Io/RB3MidiGuitar.cpp b/rpcs3/Emu/Io/RB3MidiGuitar.cpp index 1d6d10bb76..923fc3a98b 100644 --- a/rpcs3/Emu/Io/RB3MidiGuitar.cpp +++ b/rpcs3/Emu/Io/RB3MidiGuitar.cpp @@ -100,7 +100,10 @@ usb_device_rb3_midi_guitar::usb_device_rb3_midi_guitar(const std::array& usb_device_rb3_midi_guitar::~usb_device_rb3_midi_guitar() { - rtmidi_in_free(midi_in); + if (midi_in) + { + rtmidi_in_free(midi_in); + } } static const std::array disabled_response = { diff --git a/rpcs3/Emu/Io/RB3MidiKeyboard.cpp b/rpcs3/Emu/Io/RB3MidiKeyboard.cpp index ccfc2dbdc8..f96f138628 100644 --- a/rpcs3/Emu/Io/RB3MidiKeyboard.cpp +++ b/rpcs3/Emu/Io/RB3MidiKeyboard.cpp @@ -86,7 +86,10 @@ usb_device_rb3_midi_keyboard::usb_device_rb3_midi_keyboard(const std::array disabled_response = { diff --git a/rpcs3/rpcs3qt/config_checker.cpp b/rpcs3/rpcs3qt/config_checker.cpp index f8ff600205..9833959ced 100644 --- a/rpcs3/rpcs3qt/config_checker.cpp +++ b/rpcs3/rpcs3qt/config_checker.cpp @@ -302,7 +302,7 @@ bool config_checker::check_config(cfg_mode mode, QString content_or_serial, QStr const std::array def_devices = mc.get_selection_list(); mc.parse_devices(val); - const std::array devices = mc.get_selection_list(); + const std::array& devices = mc.get_selection_list(); 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 def_devices = mc.get_selection_list(); mc.parse_devices(val); - const std::array devices = mc.get_selection_list(); + const std::array& devices = mc.get_selection_list(); for (usz i = 0; i < devices.size(); i++) { diff --git a/rpcs3/rpcs3qt/microphone_creator.cpp b/rpcs3/rpcs3qt/microphone_creator.cpp index c44449c544..7b9a0d6829 100644 --- a/rpcs3/rpcs3qt/microphone_creator.cpp +++ b/rpcs3/rpcs3qt/microphone_creator.cpp @@ -14,7 +14,7 @@ microphone_creator::microphone_creator() } // 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"); } @@ -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; } -std::array microphone_creator::get_selection_list() const +const std::array& microphone_creator::get_selection_list() const { return m_sel_list; } diff --git a/rpcs3/rpcs3qt/microphone_creator.h b/rpcs3/rpcs3qt/microphone_creator.h index 37b2672083..2a1c71ddd1 100644 --- a/rpcs3/rpcs3qt/microphone_creator.h +++ b/rpcs3/rpcs3qt/microphone_creator.h @@ -15,12 +15,12 @@ class microphone_creator : public QObject public: microphone_creator(); - QString get_none(); + QString get_none() const; std::string set_device(u32 num, const QString& text); void parse_devices(std::string_view list); void refresh_list(); - QStringList get_microphone_list() const; - std::array get_selection_list() const; + const QStringList& get_microphone_list() const; + const std::array& get_selection_list() const; private: QStringList m_microphone_list; diff --git a/rpcs3/rpcs3qt/midi_creator.cpp b/rpcs3/rpcs3qt/midi_creator.cpp index d4ad70d5e9..587b1a04eb 100644 --- a/rpcs3/rpcs3qt/midi_creator.cpp +++ b/rpcs3/rpcs3qt/midi_creator.cpp @@ -8,24 +8,57 @@ LOG_CHANNEL(cfg_log, "CFG"); +const auto midi_deleter = [](RtMidiWrapper* ptr) { if (ptr) rtmidi_in_free(ptr); }; +using midi_ptr = std::unique_ptr; + +std::mutex midi_creator::m_midi_init_mutex = {}; +std::unique_ptr midi_creator::m_midi_init_thread = {}; + midi_creator::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([] + { + [[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. -QString midi_creator::get_none() +QString midi_creator::get_none() const { return tr("None", "MIDI device"); } 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.append(get_none()); - const auto deleter = [](RtMidiWrapper* ptr) { if (ptr) rtmidi_in_free(ptr); }; - std::unique_ptr midi_in(rtmidi_in_create_default()); + midi_ptr midi_in(rtmidi_in_create_default()); ensure(midi_in); 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; } -std::array midi_creator::get_selection_list() const +const std::array& midi_creator::get_selection_list() const { return m_sel_list; } diff --git a/rpcs3/rpcs3qt/midi_creator.h b/rpcs3/rpcs3qt/midi_creator.h index 5a8cb05fd6..3aefcb8a7d 100644 --- a/rpcs3/rpcs3qt/midi_creator.h +++ b/rpcs3/rpcs3qt/midi_creator.h @@ -3,6 +3,9 @@ #include "util/types.hpp" #include "Emu/Io/midi_config_types.h" +#include +#include + #include #include @@ -12,14 +15,18 @@ class midi_creator : public QObject public: midi_creator(); - QString get_none(); + virtual ~midi_creator(); + + QString get_none() const; std::string set_device(u32 num, const midi_device& device); void parse_devices(std::string_view list); void refresh_list(); - QStringList get_midi_list() const; - std::array get_selection_list() const; + const QStringList& get_midi_list() const; + const std::array& get_selection_list() const; private: + static std::mutex m_midi_init_mutex; + static std::unique_ptr m_midi_init_thread; QStringList m_midi_list; std::array m_sel_list; }; diff --git a/rpcs3/rpcs3qt/settings_dialog.cpp b/rpcs3/rpcs3qt/settings_dialog.cpp index ce791f18c5..c84cdc53c6 100644 --- a/rpcs3/rpcs3qt/settings_dialog.cpp +++ b/rpcs3/rpcs3qt/settings_dialog.cpp @@ -933,8 +933,11 @@ settings_dialog::settings_dialog(std::shared_ptr gui_settings, std QStringList cur_list = m_emu_settings->m_microphone_creator.get_microphone_list(); for (u32 subindex = 0; subindex < m_mics_combo.size(); subindex++) { - if (subindex != index && m_mics_combo[subindex]->currentText() != mic_none) - cur_list.removeOne(m_mics_combo[subindex]->currentText()); + if (subindex == index) continue; + 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]->clear(); @@ -949,7 +952,9 @@ settings_dialog::settings_dialog(std::shared_ptr gui_settings, std { 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) + { m_mics_combo[next_index]->setCurrentText(mic_none); + } propagate_used_devices(); }; @@ -1102,7 +1107,7 @@ settings_dialog::settings_dialog(std::shared_ptr gui_settings, std m_emu_settings->m_microphone_creator.parse_devices(m_emu_settings->GetSetting(emu_settings_type::MicrophoneDevices)); - const std::array mic_sel_list = m_emu_settings->m_microphone_creator.get_selection_list(); + const std::array& mic_sel_list = m_emu_settings->m_microphone_creator.get_selection_list(); for (s32 index = static_cast(mic_sel_list.size()) - 1; index >= 0; index--) { @@ -1276,8 +1281,11 @@ settings_dialog::settings_dialog(std::shared_ptr gui_settings, std QStringList cur_list = m_emu_settings->m_midi_creator.get_midi_list(); for (u32 subindex = 0; subindex < m_midi_device_combo.size(); subindex++) { - if (subindex != index && m_midi_device_combo[subindex]->currentText() != midi_none) - cur_list.removeOne(m_midi_device_combo[subindex]->currentText()); + if (subindex == index) continue; + 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]->clear(); @@ -1326,7 +1334,7 @@ settings_dialog::settings_dialog(std::shared_ptr gui_settings, std m_emu_settings->m_midi_creator.parse_devices(m_emu_settings->GetSetting(emu_settings_type::MidiDevices)); - const std::array midi_sel_list = m_emu_settings->m_midi_creator.get_selection_list(); + const std::array& midi_sel_list = m_emu_settings->m_midi_creator.get_selection_list(); for (s32 index = static_cast(midi_sel_list.size()) - 1; index >= 0; index--) {