2#include <ossia/network/context.hpp> 
    4#include <ossia-qt/protocols/utils.hpp> 
   11#include <libremidi/libremidi.hpp> 
   13#include <nano_observer.hpp> 
   35class qml_midi_outbound_socket
 
   37    , 
public Nano::Observer
 
   39  W_OBJECT(qml_midi_outbound_socket)
 
   41  qml_midi_outbound_socket() { }
 
   43  ~qml_midi_outbound_socket() { close(); }
 
   45  void open(
const libremidi::port_information& pi)
 
   50      libremidi::output_configuration config;
 
   53      m_midi_out = std::make_unique<libremidi::midi_out>(config);
 
   56      if(
auto err = m_midi_out->open_port(
static_cast<const libremidi::output_port&
>(pi));
 
   59        if(onError.isCallable())
 
   61          const auto& msg = err.message();
 
   63              { onError.call({QString::fromUtf8(msg.data(), msg.size())}); });
 
   71      if(onOpen.isCallable())
 
   73        run_on_qt_thread({ onOpen.call({qjsEngine(
this)->newQObject(
this)}); });
 
   76    catch(
const std::exception& e)
 
   78      if(onError.isCallable())
 
   80        run_on_qt_thread({ onError.call({QString::fromUtf8(e.what())}); });
 
   90      m_observer = std::make_unique<libremidi::observer>();
 
   93      auto ports = m_observer->get_output_ports();
 
   97        if(onError.isCallable())
 
   99          run_on_qt_thread({ onError.call({
"No MIDI output ports available"}); });
 
  107    catch(
const std::exception& e)
 
  109      if(onError.isCallable())
 
  111        run_on_qt_thread({ onError.call({QString::fromUtf8(e.what())}); });
 
  124      if(onClose.isCallable())
 
  126        run_on_qt_thread({ onClose.call(); });
 
  133  void sendMessage(QVariantList bytes)
 
  135    if(!m_is_open || !m_midi_out)
 
  138    libremidi::message msg;
 
  139    for(
const auto& 
byte : bytes)
 
  141      msg.bytes.push_back(
static_cast<uint8_t
>(
byte.toInt()));
 
  144    if(
auto err = m_midi_out->send_message(msg); err != stdx::error{})
 
  146      if(onError.isCallable())
 
  148        const auto& errmsg = err.message();
 
  150            { onError.call({QString::fromUtf8(errmsg.data(), errmsg.size())}); });
 
  157  void sendNoteOn(
int channel, 
int note, 
int velocity)
 
  159    if(!m_is_open || !m_midi_out)
 
  162    if(channel < 1 || channel > 16 || note < 0 || note > 127 || velocity < 0 || velocity > 127)
 
  165    m_midi_out->send_message(0x90 | (channel - 1), note, velocity);
 
  169  void sendNoteOff(
int channel, 
int note, 
int velocity)
 
  171    if(!m_is_open || !m_midi_out)
 
  174    if(channel < 1 || channel > 16 || note < 0 || note > 127 || velocity < 0 || velocity > 127)
 
  177    m_midi_out->send_message(0x80 | (channel - 1), note, velocity);
 
  181  void sendControlChange(
int channel, 
int controller, 
int value)
 
  183    if(!m_is_open || !m_midi_out)
 
  186    if(channel < 1 || channel > 16 || controller < 0 || controller > 127 || value < 0 || value > 127)
 
  189    m_midi_out->send_message(0xB0 | (channel - 1), controller, value);
 
  191  W_SLOT(sendControlChange)
 
  193  void sendProgramChange(
int channel, 
int program)
 
  195    if(!m_is_open || !m_midi_out)
 
  198    if(channel < 1 || channel > 16 || program < 0 || program > 127)
 
  201    m_midi_out->send_message(0xC0 | (channel - 1), program);
 
  203  W_SLOT(sendProgramChange)
 
  205  void sendPitchBend(
int channel, 
int value)
 
  207    if(!m_is_open || !m_midi_out)
 
  210    if(channel < 1 || channel > 16 || value < 0 || value > 16383)
 
  213    m_midi_out->send_message(0xE0 | (channel - 1), value & 0x7F, (value >> 7) & 0x7F);
 
  215  W_SLOT(sendPitchBend)
 
  217  void sendSysex(QVariantList data)
 
  219    if(!m_is_open || !m_midi_out)
 
  222    libremidi::message msg;
 
  223    msg.bytes.push_back(0xF0); 
 
  224    for(
const auto& 
byte : data)
 
  226      int val = 
byte.toInt();
 
  227      if(val >= 0 && val <= 127) 
 
  228        msg.bytes.push_back(
static_cast<uint8_t
>(val));
 
  230    msg.bytes.push_back(0xF7); 
 
  232    if(
auto err = m_midi_out->send_message(msg); err != stdx::error{})
 
  234      if(onError.isCallable())
 
  236        const auto& errmsg = err.message();
 
  238            { onError.call({QString::fromUtf8(errmsg.data(), errmsg.size())}); });
 
  250  std::unique_ptr<libremidi::observer> m_observer;
 
  251  std::unique_ptr<libremidi::midi_out> m_midi_out;
 
  252  std::atomic_bool m_is_open{
false};
 
Definition qml_device.cpp:43