3#ifdef MAYAFLUX_PLATFORM_WINDOWS
7#ifndef WIN32_LEAN_AND_MEAN
8#define WIN32_LEAN_AND_MEAN
34class MAYAFLUX_API WinMmMidiBackend :
public IInputBackend {
37 std::vector<std::string> input_port_filters;
38 bool auto_open_inputs {
true };
39 bool enable_sysex {
true };
40 std::string virtual_port_name {
"MayaFlux" };
44 explicit WinMmMidiBackend(Config config);
45 ~WinMmMidiBackend()
override;
47 WinMmMidiBackend(
const WinMmMidiBackend&) =
delete;
48 WinMmMidiBackend& operator=(
const WinMmMidiBackend&) =
delete;
49 WinMmMidiBackend(WinMmMidiBackend&&) =
delete;
50 WinMmMidiBackend& operator=(WinMmMidiBackend&&) =
delete;
53 void start()
override;
57 [[nodiscard]]
bool is_initialized()
const override {
return m_initialized.load(); }
58 [[nodiscard]]
bool is_running()
const override {
return m_running.load(); }
60 [[nodiscard]] std::vector<InputDeviceInfo> get_devices()
const override;
61 size_t refresh_devices()
override;
63 bool open_device(uint32_t device_id)
override;
64 void close_device(uint32_t device_id)
override;
65 [[nodiscard]]
bool is_device_open(uint32_t device_id)
const override;
66 [[nodiscard]] std::vector<uint32_t> get_open_devices()
const override;
68 void set_input_callback(InputCallback callback)
override;
69 void set_device_callback(DeviceCallback callback)
override;
71 [[nodiscard]]
InputType get_type()
const override {
return InputType::MIDI; }
72 [[nodiscard]] std::string get_name()
const override {
return "MIDI (WinMM)"; }
73 [[nodiscard]] std::string get_version()
const override;
76 static constexpr size_t k_sysex_buf_size { 256 };
77 static constexpr size_t k_sysex_buf_count { 2 };
79 struct MIDIPortInfo : InputDeviceInfo {
80 UINT winmm_device_id { 0 };
83 struct MIDIPortState {
85 uint32_t device_id { 0 };
86 HMIDIIN handle {
nullptr };
87 std::atomic<bool> active {
false };
88 std::function<void(
const InputValue&)> input_callback;
89 MIDIHDR sysex_headers[k_sysex_buf_count] {};
90 std::array<std::vector<uint8_t>, k_sysex_buf_count> sysex_bufs;
94 std::atomic<bool> m_initialized {
false };
95 std::atomic<bool> m_running {
false };
97 mutable std::mutex m_devices_mutex;
98 std::unordered_map<uint32_t, MIDIPortInfo> m_enumerated_devices;
99 std::unordered_map<uint32_t, std::shared_ptr<MIDIPortState>> m_open_devices;
100 uint32_t m_next_device_id { 1 };
104 mutable std::mutex m_callback_mutex;
106 bool port_matches_filter(
const std::string& name)
const;
107 uint32_t find_or_assign_device_id(UINT winmm_id);
108 void queue_sysex_buffers(MIDIPortState& state);
109 void notify_device_change(
const InputDeviceInfo& info,
bool connected);
111 static void CALLBACK midi_callback(HMIDIIN handle, UINT msg,
112 DWORD_PTR user_data, DWORD_PTR param1, DWORD_PTR param2);
InputType
Input backend type enumeration.
std::function< void(const InputValue &)> InputCallback
Callback signature for input events.
std::function< void(const InputDeviceInfo &, bool connected)> DeviceCallback
Callback signature for device connection/disconnection events.
@ CALLBACK
Use callback for custom transition.
void stop()
Stop all Portal::Graphics operations.
bool is_initialized()
Checks if the default engine has been initialized.