Files

97 lines
2.7 KiB
C++
Raw Permalink Normal View History

2024-10-09 02:01:23 +02:00
#pragma once
2024-10-28 19:24:18 +01:00
#include <libremidi/detail/ump_stream.hpp>
2024-10-09 02:01:23 +02:00
#include <libremidi/backends/winmidi/config.hpp>
#include <libremidi/backends/winmidi/helpers.hpp>
#include <libremidi/backends/winmidi/observer.hpp>
#include <libremidi/detail/midi_out.hpp>
namespace libremidi::winmidi
{
class midi_out_impl final
: public midi2::out_api
, public error_handler
, public winmidi_shared_data
2024-10-09 02:01:23 +02:00
{
public:
struct
: libremidi::output_configuration
, winmidi::output_configuration
{
} configuration;
midi_out_impl(libremidi::output_configuration&& conf, winmidi::output_configuration&& apiconf)
: configuration{std::move(conf), std::move(apiconf)}
, m_session{
configuration.context ? *configuration.context
: MidiSession::Create(to_hstring(configuration.client_name))}
2024-10-09 02:01:23 +02:00
{
2024-10-28 19:24:18 +01:00
this->client_open_ = stdx::error{};
2024-10-09 02:01:23 +02:00
}
~midi_out_impl() override { close_port(); }
libremidi::API get_current_api() const noexcept override
{
return libremidi::API::WINDOWS_MIDI_SERVICES;
}
2024-10-28 19:24:18 +01:00
stdx::error open_port(const output_port& port, std::string_view) override
2024-10-09 02:01:23 +02:00
{
auto device_id = std::get_if<std::string>(&port.device);
if (!device_id)
return std::errc::invalid_argument;
auto [ep, gp] = get_port(*device_id, port.port);
if (!ep || !gp)
2024-10-28 19:24:18 +01:00
return std::errc::address_not_available;
2024-10-09 02:01:23 +02:00
m_endpoint = m_session.CreateEndpointConnection(ep.EndpointDeviceId());
2024-10-28 19:24:18 +01:00
m_endpoint.Open();
return stdx::error{};
2024-10-09 02:01:23 +02:00
}
2024-10-28 19:24:18 +01:00
stdx::error close_port() override
2024-10-09 02:01:23 +02:00
{
2024-10-28 19:24:18 +01:00
m_session.DisconnectEndpointConnection(m_endpoint.ConnectionId());
return stdx::error{};
2024-10-09 02:01:23 +02:00
}
2024-10-28 19:24:18 +01:00
stdx::error send_ump(const uint32_t* message, size_t size) override
2024-10-09 02:01:23 +02:00
{
2024-10-28 19:24:18 +01:00
auto write_func = [this](const uint32_t* ump, int64_t bytes) -> std::errc {
MidiSendMessageResults ret{};
switch(bytes / 4)
{
case 1:
ret = m_endpoint.SendSingleMessagePacket(MidiMessage32(0, ump[0]));
break;
case 2:
ret = m_endpoint.SendSingleMessagePacket(MidiMessage64(0, ump[0], ump[1]));
break;
case 3:
ret = m_endpoint.SendSingleMessagePacket(MidiMessage96(0, ump[0], ump[1], ump[2]));
break;
case 4:
ret = m_endpoint.SendSingleMessagePacket(MidiMessage128(0, ump[0], ump[1], ump[2], ump[3]));
break;
default:
return std::errc::bad_message;
}
if(ret != MidiSendMessageResults::Succeeded)
return std::errc::bad_message;
return std::errc{0};
};
2024-10-09 02:01:23 +02:00
2024-10-28 19:24:18 +01:00
return segment_ump_stream(message, size, write_func, []() {});
2024-10-09 02:01:23 +02:00
}
private:
2024-10-28 19:24:18 +01:00
MidiSession m_session;
winrt::Microsoft::Windows::Devices::Midi2::MidiEndpointConnection m_endpoint{nullptr};
2024-10-09 02:01:23 +02:00
};
}