From 521c21ac6bc7c777836fc276e6b02324ad9b3d49 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean-Micha=C3=ABl=20Celerier?= Date: Sun, 20 Sep 2026 00:35:34 -0400 Subject: [PATCH 1/2] webmidi: do not call an observer callback that was not set Every other backend checks first; the browser one did not, so an observer watching only inputs threw std::bad_function_call as soon as an output port showed up. Also fixes the emscripten guard of midi1::default_api(), which never matched. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01SCvayD61okH7PATstw4whi --- include/libremidi/api.hpp | 6 +++--- include/libremidi/backends/emscripten/observer.cpp | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/include/libremidi/api.hpp b/include/libremidi/api.hpp index 2a957fcf..ce5ba692 100644 --- a/include/libremidi/api.hpp +++ b/include/libremidi/api.hpp @@ -62,8 +62,8 @@ inline constexpr libremidi::API default_api() noexcept return API::WINDOWS_MM; #elif defined(LIBREMIDI_ALSA) return API::ALSA_SEQ; -#elif defined(__emscripten__) - return API::EMSCRIPTEN_WEBMIDI; +#elif defined(__EMSCRIPTEN__) + return API::WEBMIDI; #elif defined(LIBREMIDI_ANDROID) return API::ANDROID_AMIDI; #else @@ -83,7 +83,7 @@ inline constexpr libremidi::API default_api() noexcept return API::WINDOWS_MIDI_SERVICES; #elif defined(LIBREMIDI_ALSA) return API::ALSA_SEQ_UMP; -#elif defined(__emscripten__) +#elif defined(__EMSCRIPTEN__) return API::DUMMY; #else return API::DUMMY; diff --git a/include/libremidi/backends/emscripten/observer.cpp b/include/libremidi/backends/emscripten/observer.cpp index 6c895156..9e5e0cb5 100644 --- a/include/libremidi/backends/emscripten/observer.cpp +++ b/include/libremidi/backends/emscripten/observer.cpp @@ -92,14 +92,14 @@ LIBREMIDI_INLINE void observer_emscripten::update( for (std::size_t i = m_known_inputs.size(); i < current_inputs.size(); i++) { m_known_inputs.push_back(current_inputs[i]); - if (notify) + if (notify && configuration.input_added) configuration.input_added(to_port_info(i, m_known_inputs[i])); } for (std::size_t i = m_known_outputs.size(); i < current_outputs.size(); i++) { m_known_outputs.push_back(current_outputs[i]); - if (notify) + if (notify && configuration.output_added) configuration.output_added(to_port_info(i, m_known_outputs[i])); } } From 3a91ebd18c01fdcd8a73b268e45ef922d5940601 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean-Micha=C3=ABl=20Celerier?= Date: Sun, 20 Sep 2026 11:00:02 -0400 Subject: [PATCH 2/2] webmidi: read the right EM_ASM argument when closing an input stop_stream() passes one argument and read it as $1, so closing a Web MIDI input threw a TypeError out of the destructor and aborted the program. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01SCvayD61okH7PATstw4whi --- include/libremidi/backends/emscripten/midi_access.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/libremidi/backends/emscripten/midi_access.hpp b/include/libremidi/backends/emscripten/midi_access.hpp index 02708a7b..8f3a9957 100644 --- a/include/libremidi/backends/emscripten/midi_access.hpp +++ b/include/libremidi/backends/emscripten/midi_access.hpp @@ -303,10 +303,10 @@ class midi_access_emscripten return; const auto& id = m_current_inputs[port_index].id; - EM_ASM(const id = UTF8ToString($1); + EM_ASM(const id = UTF8ToString($0); let input = globalThis.__libreMidi_access.inputs.get(id); - input.onmidimessage = undefined;, id.c_str()); + if (input) input.onmidimessage = null;, id.c_str()); } std::vector m_observers;