celtera/libremidi

v4 requirements gathering thread

jcelerier opened this issue · 2 comments

Hello,
for anyone interested I'd like to pin this issue to discuss proposed API changes and reworks in a future version.

It'll be in this branch : https://github.com/jcelerier/libremidi/tree/v4

  • C++20 as minimum, unconditionally enable <span>, etc.
  • Refactor the library classes in individual files to make everything easier to edit
  • #73
    • ALSA -> not available yet on a released ALSA version it seems
    • CoreMIDI
    • Win32
  • Refactor the various individual queues, semaphores and threading objects used across the backends.
    • custom semaphore -> std::semaphore
    • pthread -> std::thread
  • Enable configuring a custom queue type through some config.hpp -> now unnecessary, queue API has been removed as it can be built more efficiently on top of libremidi::midi_in in user code.
  • Allow to construct specific MIDI APIs with a specific context object (for instance passing an existing jack_client_t to midi_in_jack, etc) to enable to integrate more easily against existing run-loops - would fix #62 and also the macOS MIDIClient issue which required a singleton in rtmidi
    • mainly this also imply that we need to move the ability to execute the run-loop methods outside of the library if necessary, e.g. to run inside the user's existing audio callback?
    • alsa raw
    • alsa seq
    • jack
    • coremidi
    • emscripten? -> it's global anyways
    • uwp? -> it's global anyways
  • Instead of passing various "varying" arguments & calling member functions before init, simply have a single "configuration" struct passed to the ctor: > done! see reworked examples in the branch
struct jack_in_conf {
  std::string_view client_name;
  void* context; // e.g. an existing jack or pipewire client
  int queue_size;
  int buffer_size;
};

struct configuration { 
  api_configuration api; // std::variant<jack_in_conf, alsa_in_conf, etc...>;

  chunking_parameters chunks;

  bool ignore_sysex; 
  bool ignore_time;
  bool ignore_sense;
};

libremidi::midi_in mid{ configuration {
  .api = jack_api_configuration { 
    .client_name = "foo" 
   }
 , .ignore_time = true 
}};
  • timestamps double -> int(64?) in libremidi::message #68 (done)
  • timestamps in nanoseconds everywhere
  • allow to choose whether we want timestamps and in which format (relative, or absolute with e.g. monotonic clock)
  • std::function_ref support if available?
  • finding a better way to name devices to prevent name conflicts. Ideally we would use something like libusb if available to get some proprely unique identifier (#57 #17)
  • pipewire backend - I have experience with the audio part as I developed a back-end for ossia here: https://github.com/ossia/libossia/blob/master/src/ossia/audio/pipewire_protocol.hpp
  • remove all the logging with std::cerr > put behind an ifdef and LIBREMIDI_DEBUG
  • allow users to plug-in their own custom logging back-end instead
  • backport the fixes that happened in RtMidi since then:
    git diff -w 6ad9c059ce895c44616bcfa8104ca94678bc9408 -- RtMidi.cpp RtMidi.h
  • passing timestamps: master...wip/midi_write_ts
  • observers: make sure that they all behave the same and stay coherent with what midi_in / midi_out says about the ports
  • document the semantic of the ins / outs for each backend
  • #74
    • alsa_raw
    • coremidi
  • #75
    • alsa_raw
    • alsa_seq
    • observers
  • refactor the observers and give them a context object too, to allow sharing the context with midi_in / midi_out
  • #76
  • thread-safety annotations with clang

Relevant:

  • what else?

Not an API change, but it would be nice to get libremidi on vcpkg

closing as it's pretty much where I want it to be.. just have to finish the MIDI 2 backends =)