Skip to content

Commit

Permalink
Audio: Add Api to get the shared Midi Out Instance
Browse files Browse the repository at this point in the history
Solves errors and lag in the audio settings when the device is opened multiple times
  • Loading branch information
Ghabry committed Mar 26, 2024
1 parent b7c3638 commit 90facf9
Show file tree
Hide file tree
Showing 5 changed files with 30 additions and 11 deletions.
10 changes: 10 additions & 0 deletions src/audio.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@

// Headers
#include <string>
#include "audio_generic_midiout.h"
#include "filesystem_stream.h"
#include "audio_secache.h"
#include "game_config.h"
Expand All @@ -39,6 +40,15 @@ struct AudioInterface {

virtual void vGetConfig(Game_ConfigAudio& cfg) const = 0;

/**
* Instantiates and returns the Native Midi Out device.
* The Midi Out device is usually an exclusive resource.
* Implementing classes should only create one Midi Out and return the
* shared instance.
* @return Native Midi Out Device or nullptr on error
*/
virtual GenericAudioMidiOut* CreateAndGetMidiOut() { return nullptr; }

/**
* Update audio. Must be called each frame.
*/
Expand Down
23 changes: 14 additions & 9 deletions src/audio_generic.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -198,6 +198,19 @@ void GenericAudio::Update() {
// no-op, handled by the Decode function called through a thread
}

GenericAudioMidiOut* GenericAudio::CreateAndGetMidiOut() {
if (!midi_thread) {
midi_thread = std::make_unique<GenericAudioMidiOut>();
std::string status_message;
if (midi_thread->IsInitialized(status_message)) {
midi_thread->StartThread();
} else {
midi_thread.reset();
}
}
return midi_thread.get();
}

void GenericAudio::SetFormat(int frequency, AudioDecoder::Format format, int channels) {
output_format.frequency = frequency;
output_format.format = format;
Expand All @@ -222,15 +235,7 @@ bool GenericAudio::PlayOnChannel(BgmChannel& chan, Filesystem_Stream::InputStrea
bool wildmidi = Audio().GetWildMidiEnabled() && MidiDecoder::CreateWildMidi(true);

if (!fluidsynth && !wildmidi && Audio().GetNativeMidiEnabled()) {
if (!midi_thread) {
midi_thread = std::make_unique<GenericAudioMidiOut>();
std::string status_message;
if (midi_thread->IsInitialized(status_message)) {
midi_thread->StartThread();
} else {
midi_thread.reset();
}
}
CreateAndGetMidiOut();

if (midi_thread) {
midi_thread->LockMutex();
Expand Down
2 changes: 2 additions & 0 deletions src/audio_generic.h
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,8 @@ class GenericAudio : public AudioInterface {

void vGetConfig(Game_ConfigAudio&) const override {}

GenericAudioMidiOut* CreateAndGetMidiOut() override;

void SetFormat(int frequency, AudioDecoder::Format format, int channels);

virtual void LockMutex() const = 0;
Expand Down
3 changes: 2 additions & 1 deletion src/platform/linux/midiout_device_alsa.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,8 @@ AlsaMidiOutDevice::AlsaMidiOutDevice(std::string& status_message) {
return;
}

Output::Debug("ALSA MIDI: Using client {}:{}:{}", dst_client, dst_port_name, dst_port);
status_message = fmt::format("ALSA MIDI: Using client {}:{}:{}", dst_client, dst_port_name, dst_port);
Output::DebugStr(status_message);

status = snd_seq_create_simple_port(midi_out, "Harmony",
SND_SEQ_PORT_CAP_WRITE | SND_SEQ_PORT_CAP_SUBS_WRITE, SND_SEQ_PORT_TYPE_APPLICATION);
Expand Down
3 changes: 2 additions & 1 deletion src/window_settings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -327,7 +327,8 @@ void Window_Settings::RefreshAudioMidi() {

if (cfg.native_midi.IsOptionVisible()) {
AddOption(cfg.native_midi, []() { Audio().SetNativeMidiEnabled(Audio().GetConfig().native_midi.Toggle()); });
if (!GenericAudioMidiOut().IsInitialized(GetFrame().options.back().help2)) {
auto midi_out = Audio().CreateAndGetMidiOut();
if (!midi_out || !midi_out->IsInitialized(GetFrame().options.back().help2)) {
GetFrame().options.back().text += " [Not working]";
GetFrame().options.back().color = Font::ColorKnockout;
} else if (cfg.native_midi.Get() && !used) {
Expand Down

0 comments on commit 90facf9

Please sign in to comment.