2#include <ossia/network/context.hpp>
4#include <ossia-qt/protocols/utils.hpp>
11#include <libremidi/libremidi.hpp>
13#include <nano_observer.hpp>
36class qml_ump_outbound_socket
38 ,
public Nano::Observer
40 W_OBJECT(qml_ump_outbound_socket)
42 qml_ump_outbound_socket() { }
44 ~qml_ump_outbound_socket() { close(); }
46 void open(
const libremidi::port_information& pi)
51 libremidi::output_configuration config;
54 m_ump_out = std::make_unique<libremidi::midi_out>(
55 config, libremidi::midi2::default_api());
58 if(
auto err = m_ump_out->open_port(
static_cast<const libremidi::output_port&
>(pi));
61 if(onError.isCallable())
63 const auto& msg = err.message();
65 { onError.call({QString::fromUtf8(msg.data(), msg.size())}); });
73 if(onOpen.isCallable())
75 run_on_qt_thread({ onOpen.call({qjsEngine(
this)->newQObject(
this)}); });
78 catch(
const std::exception& e)
80 if(onError.isCallable())
82 run_on_qt_thread({ onError.call({QString::fromUtf8(e.what())}); });
92 m_observer = std::make_unique<libremidi::observer>(
93 libremidi::observer_configuration{}, libremidi::midi2::default_api());
96 auto ports = m_observer->get_output_ports();
100 if(onError.isCallable())
102 run_on_qt_thread({ onError.call({
"No UMP output ports available"}); });
110 catch(
const std::exception& e)
112 if(onError.isCallable())
114 run_on_qt_thread({ onError.call({QString::fromUtf8(e.what())}); });
127 if(onClose.isCallable())
129 run_on_qt_thread({ onClose.call(); });
136 void sendMessage(QVariantList words)
138 if(!m_is_open || !m_ump_out)
141 if(words.size() != 4)
143 if(onError.isCallable())
145 run_on_qt_thread({ onError.call({
"UMP message must contain exactly 4 words"}); });
152 for(
int i = 0; i < 4; ++i)
154 msg.data[i] =
static_cast<uint32_t
>(words[i].toUInt());
157 if(
auto err = m_ump_out->send_ump(msg); err != stdx::error{})
159 if(onError.isCallable())
161 const auto& errmsg = err.message();
163 { onError.call({QString::fromUtf8(errmsg.data(), errmsg.size())}); });
170 void sendNoteOn(
int group,
int channel,
int note,
int velocity,
int attributeType,
int attribute)
172 if(!m_is_open || !m_ump_out)
175 if(group < 1 || group > 16 || channel < 1 || channel > 16 ||
176 note < 0 || note > 127 || velocity < 0 || velocity > 65535)
182 msg.data[0] = (0x4 << 28) | ((group - 1) << 24) | (0x90 << 16) | ((channel - 1) << 16) | (note << 8) | attributeType;
184 msg.data[1] = (velocity << 16) | (attribute & 0xFFFF);
188 m_ump_out->send_ump(msg);
192 void sendNoteOff(
int group,
int channel,
int note,
int velocity,
int attributeType,
int attribute)
194 if(!m_is_open || !m_ump_out)
197 if(group < 1 || group > 16 || channel < 1 || channel > 16 ||
198 note < 0 || note > 127 || velocity < 0 || velocity > 65535)
204 msg.data[0] = (0x4 << 28) | ((group - 1) << 24) | (0x80 << 16) | ((channel - 1) << 16) | (note << 8) | attributeType;
206 msg.data[1] = (velocity << 16) | (attribute & 0xFFFF);
210 m_ump_out->send_ump(msg);
214 void sendControlChange(
int group,
int channel,
int controller,
int value)
216 if(!m_is_open || !m_ump_out)
219 if(group < 1 || group > 16 || channel < 1 || channel > 16 ||
220 controller < 0 || controller > 127)
226 msg.data[0] = (0x4 << 28) | ((group - 1) << 24) | (0xB0 << 16) | ((channel - 1) << 16) | (controller << 8);
228 msg.data[1] =
static_cast<uint32_t
>(value);
232 m_ump_out->send_ump(msg);
234 W_SLOT(sendControlChange)
236 void sendProgramChange(
int group,
int channel,
int program,
int bankMSB,
int bankLSB)
238 if(!m_is_open || !m_ump_out)
241 if(group < 1 || group > 16 || channel < 1 || channel > 16 ||
242 program < 0 || program > 127 || bankMSB < 0 || bankMSB > 127 || bankLSB < 0 || bankLSB > 127)
248 msg.data[0] = (0x4 << 28) | ((group - 1) << 24) | (0xC0 << 16) | ((channel - 1) << 16);
250 msg.data[1] = (program << 24) | (bankMSB << 8) | bankLSB;
254 m_ump_out->send_ump(msg);
256 W_SLOT(sendProgramChange)
258 void sendPitchBend(
int group,
int channel,
int value)
260 if(!m_is_open || !m_ump_out)
263 if(group < 1 || group > 16 || channel < 1 || channel > 16)
269 msg.data[0] = (0x4 << 28) | ((group - 1) << 24) | (0xE0 << 16) | ((channel - 1) << 16);
271 msg.data[1] =
static_cast<uint32_t
>(value);
275 m_ump_out->send_ump(msg);
277 W_SLOT(sendPitchBend)
285 std::unique_ptr<libremidi::observer> m_observer;
286 std::unique_ptr<libremidi::midi_out> m_ump_out;
287 std::atomic_bool m_is_open{
false};
Definition qml_device.cpp:43