| 6 | #include <poll.h> |
| 7 | |
| 8 | int main() |
| 9 | { |
| 10 | auto callback = [](const libremidi::message& message) { std::cout << message << std::endl; }; |
| 11 | |
| 12 | std::vector<std::function<int(std::span<pollfd>)>> callbacks; |
| 13 | std::vector<pollfd> fds; |
| 14 | |
| 15 | auto register_fds = [&](const libremidi::manual_poll_parameters& params) { |
| 16 | fds.insert(fds.end(), params.fds.begin(), params.fds.end()); |
| 17 | callbacks.push_back(params.callback); |
| 18 | return true; |
| 19 | }; |
| 20 | |
| 21 | libremidi::observer obs{{}, libremidi::alsa_raw_observer_configuration{}}; |
| 22 | |
| 23 | // Create as many midi_in as there are connected MIDI sources |
| 24 | std::vector<libremidi::midi_in> midiin; |
| 25 | for (auto& port : obs.get_input_ports()) |
| 26 | { |
| 27 | midiin.emplace_back( |
| 28 | libremidi::input_configuration{.on_message = callback}, |
| 29 | libremidi::alsa_raw_input_configuration{.manual_poll = register_fds}); |
| 30 | midiin.back().open_port(port); |
| 31 | } |
| 32 | |
| 33 | for (;;) |
| 34 | { |
| 35 | // Option 1: |
| 36 | // Combine all the fds in your own fd array, |
| 37 | // and run poll manually |
| 38 | #if 1 |
| 39 | // Poll |
| 40 | int err = poll(fds.data(), fds.size(), -1); |
| 41 | if (err < 0) |
| 42 | return err; |
| 43 | |
| 44 | // Look for who's ready: |
| 45 | // Note: you have to pass the fds back to the API as the |
| 46 | // ALSA functions also need to process the fds in addition to poll |
| 47 | // so you need to keep track of which fds are for which midi_in... |
| 48 | // In practice it seems that ALSA only uses one FD so it's simply the index |
| 49 | // in the array but not sure how future-proof this is |
| 50 | for (int i = 0; i < std::ssize(fds); i++) |
| 51 | { |
| 52 | if (fds[i].revents & POLLIN) |
| 53 | { |
| 54 | auto err = callbacks[i]({fds.data() + i, 1}); |
| 55 | if (err < 0 && err != -EAGAIN) |
| 56 | return -err; |
| 57 | } |
| 58 | } |
| 59 | #else |
| 60 | // Option 2: |
| 61 | // It's also possible to simply pass an empty set of FDs and |
| 62 | // just process at some custom time interval, |
| 63 | // in this case no "poll" mechanism is used at all |
| 64 | for (auto& callback : callbacks) |
| 65 | { |