Midifle ports
Supported bindings: ossia
Midifile ports are currently only supported with the ossia binding.
They allow to define an input which will be the content of a MIDI file.
Port definition
A midifile input port assumes the existence of a MIDI event structure.
The whole thing can look like this:
struct midi_event
{
  // The MIDI messages
  std::vector<unsigned char> bytes;
  // Can also be this, but meta events won't be available 
  // since they are > 3 bytes.
  unsigned char bytes[3];
  
  // optional, delta time in ticks
  int tick_delta;
  // optional, time since the beginning in ticks
  int tick_absolute; 
};
struct
{
  static consteval auto name() { return "My midifile"}
  struct {
    // Can be any vector-ish container, but must support push_back
    std::vector<std::vector<midi_event>> tracks; 
    // If present, the length in ticks 
    int64_t length{};
    // If present, the length in ticks     
    int64_t ticks_per_beat{};
    // If present, the length in ticks     
    float starting_tempo{};
    std::string_view filename; // Currently loaded midifile
  } midifile;
} snd;
A few helper types are provided:
struct midi_track_event
{
  boost::container::small_vector<uint8_t, 15> bytes;
  int tick_delta = 0;
};
struct simple_midi_track_event
{
  uint8_t bytes[3];
  int64_t tick_absolute;
};
struct {
  // Default event type is simple_midi_track_event for performance and compile times, 
  // but it can be changed through the template arguments
  halp::midifile_port<"My midifile", midi_track_event> snd;
} inputs;
Callback
Like other ports, it is possible to get an update callback, by implementing an update method ;
the simplest way is to make an empty struct which inherits from halp::midifile_port
struct : halp::midifile_port<"My midifile"> {
  void update(MyObject& obj) {
    // This code is called whenever the midifile has been changed by the user
  }
} port_name;