Files

106 lines
3.0 KiB
C++
Raw Permalink Normal View History

2024-10-09 02:01:23 +02:00
#if defined(__EMSCRIPTEN__)
#include <libremidi/backends/emscripten/midi_access.hpp>
#include <libremidi/backends/emscripten/observer.hpp>
#include <cassert>
namespace libremidi
{
LIBREMIDI_INLINE observer_emscripten::observer_emscripten(
observer_configuration&& conf, emscripten_observer_configuration&& apiconf)
: configuration{std::move(conf), std::move(apiconf)}
{
if (!configuration.has_callbacks())
return;
auto& webmidi = webmidi_helpers::midi_access_emscripten::instance();
webmidi.register_observer(*this);
// Trigger an initial notification
webmidi.load_current_infos();
if (configuration.notify_in_constructor)
update(webmidi.inputs(), webmidi.outputs());
}
LIBREMIDI_INLINE observer_emscripten::~observer_emscripten()
{
if (!configuration.has_callbacks())
return;
webmidi_helpers::midi_access_emscripten::instance().unregister_observer(*this);
}
LIBREMIDI_INLINE
libremidi::API observer_emscripten::get_current_api() const noexcept
{
return libremidi::API::WEBMIDI;
}
template <bool Input>
static auto to_port_info(int index, const webmidi_helpers::device_information& dev)
-> std::conditional_t<Input, input_port, output_port>
{
return {
{.client = 0,
.port = (uint64_t)index,
.manufacturer = "",
.device_name = "",
.port_name = dev.name,
.display_name = dev.name}};
}
LIBREMIDI_INLINE
std::vector<libremidi::input_port> observer_emscripten::get_input_ports() const noexcept
{
std::vector<libremidi::input_port> ret;
auto& webmidi = webmidi_helpers::midi_access_emscripten::instance();
webmidi.load_current_infos();
for (std::size_t i = 0, n = webmidi.input_count(); i < n; i++)
{
ret.push_back(to_port_info<true>(i, webmidi.inputs()[i]));
}
return ret;
}
LIBREMIDI_INLINE
std::vector<libremidi::output_port> observer_emscripten::get_output_ports() const noexcept
{
std::vector<libremidi::output_port> ret;
auto& webmidi = webmidi_helpers::midi_access_emscripten::instance();
webmidi.load_current_infos();
for (std::size_t i = 0, n = webmidi.output_count(); i < n; i++)
{
ret.push_back(to_port_info<false>(i, webmidi.outputs()[i]));
}
return ret;
}
LIBREMIDI_INLINE void observer_emscripten::update(
const std::vector<observer_emscripten::device>& current_inputs,
const std::vector<observer_emscripten::device>& current_outputs)
{
// WebMIDI never remove inputs, it just marks them as disconnected.
// At least in known browsers...
assert(current_inputs.size() >= m_known_inputs.size());
assert(current_outputs.size() >= m_known_outputs.size());
for (std::size_t i = m_known_inputs.size(); i < current_inputs.size(); i++)
{
m_known_inputs.push_back(current_inputs[i]);
configuration.input_added(to_port_info<true>(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]);
configuration.output_added(to_port_info<false>(i, m_known_outputs[i]));
}
}
}
#endif