diff options
| -rw-r--r-- | MIDI.cpp | 60 | ||||
| -rw-r--r-- | MIDI.h | 3 | ||||
| -rw-r--r-- | StatusLED.cpp | 26 | ||||
| -rw-r--r-- | StatusLED.h | 13 | 
4 files changed, 95 insertions, 7 deletions
| @@ -1,6 +1,14 @@  #include "MIDI.h" +#include <unordered_set> +#include <string> + +namespace { +  std::unordered_set<std::string> supported_devices{"AudioBox 22 VSL", "CH345", "M2"}; +} +  MIDI::MIDI(): +  m_client{},    seq_handle{},    in_port{},    npfd{}, @@ -17,7 +25,9 @@ MIDI::MIDI():      throw std::runtime_error("MIDI client name couldn't be set");    } -  if (0 > ((in_port = snd_seq_create_simple_port(seq_handle, "24:0", +  detect_port(); + +  if (0 > ((in_port = snd_seq_create_simple_port(seq_handle, fmt::format("{}:0", m_client).c_str(),                      SND_SEQ_PORT_CAP_WRITE | SND_SEQ_PORT_CAP_SUBS_WRITE | SND_SEQ_PORT_CAP_READ | SND_SEQ_PORT_CAP_SUBS_READ,                      SND_SEQ_PORT_TYPE_APPLICATION))))    { @@ -29,7 +39,7 @@ MIDI::MIDI():    if (1) {      snd_seq_addr_t sender, dest;      snd_seq_port_subscribe_t *subs; -    sender.client = 24; +    sender.client = m_client;      sender.port = 0;      dest.client = snd_seq_client_id(seq_handle);      dest.port = in_port; @@ -45,7 +55,7 @@ MIDI::MIDI():        throw std::runtime_error("MIDI port couldn't be connected");      }    } else { -    if (0 > snd_seq_connect_from(seq_handle, in_port, 24, 0)) +    if (0 > snd_seq_connect_from(seq_handle, in_port, m_client, 0))      {        throw std::runtime_error("MIDI port couldn't be connected");      } @@ -75,6 +85,50 @@ MIDI::MIDI():    }  } +void MIDI::detect_port(void) +{ +  bool found{}; + +  snd_seq_client_info_t *cinfo; +  snd_seq_port_info_t *pinfo; + +  snd_seq_client_info_alloca(&cinfo); +  snd_seq_port_info_alloca(&pinfo); + +  snd_seq_client_info_set_client(cinfo, -1); +  while (snd_seq_query_next_client(seq_handle, cinfo) >= 0) { +    int client = snd_seq_client_info_get_client(cinfo); + +    snd_seq_port_info_set_client(pinfo, client); +    snd_seq_port_info_set_port(pinfo, -1); +    while (snd_seq_query_next_port(seq_handle, pinfo) >= 0) { +      /* port must understand MIDI messages */ +      if (!(snd_seq_port_info_get_type(pinfo) +            & SND_SEQ_PORT_TYPE_MIDI_GENERIC)) +              continue; +      /* we need both WRITE and SUBS_WRITE */ +      if ((snd_seq_port_info_get_capability(pinfo) +           & (SND_SEQ_PORT_CAP_WRITE | SND_SEQ_PORT_CAP_SUBS_WRITE)) +          != (SND_SEQ_PORT_CAP_WRITE | SND_SEQ_PORT_CAP_SUBS_WRITE)) +              continue; +      if (supported_devices.contains(std::string{snd_seq_client_info_get_name(cinfo)})) { +        m_client = snd_seq_port_info_get_client(pinfo); +        found = true; +      } +      //std::cout << fmt::format("DEBUG: {}", get_midi_port()) << std::endl; +      //printf("%3d:%-3d  %-32.32s %s\n", +      //       snd_seq_port_info_get_client(pinfo), +      //       snd_seq_port_info_get_port(pinfo), +      //       snd_seq_client_info_get_name(cinfo), +      //       snd_seq_port_info_get_name(pinfo)); +    } +  } + +  if (!found) { +    throw std::runtime_error("No MIDI device found"); +  } +} +  MIDI::~MIDI()  {    snd_midi_event_free(midi_event_parser); @@ -34,6 +34,9 @@ public:    void wait_for_event();  private: +  void detect_port(void); + +  int m_client;    snd_seq_t *seq_handle;    int in_port;    int npfd; diff --git a/StatusLED.cpp b/StatusLED.cpp index c3544a5..3013ddb 100644 --- a/StatusLED.cpp +++ b/StatusLED.cpp @@ -1,10 +1,32 @@  #include "StatusLED.h" -StatusLED::StatusLED() +namespace fs = std::filesystem; + +StatusLED::StatusLED(): m_mode{Mode::OK}, m_bpm{60}  {  }  void StatusLED::addLED(const LED& led)  { -  m_leds.push_back(led); +  if (fs::exists(led.green) && fs::exists(led.red)) { +    m_leds.push_back(led); +  } +} + +void StatusLED::setMode(Mode mode) +{ +  m_mode = mode; +} + +void StatusLED::setBPM(int bpm) +{ +  m_bpm = bpm; +} + +void StatusLED::initLED(const LED& led) +{ +} + +void StatusLED::updateLED(const LED& led) +{  } diff --git a/StatusLED.h b/StatusLED.h index 39b19f5..b1c0f23 100644 --- a/StatusLED.h +++ b/StatusLED.h @@ -5,6 +5,7 @@  struct LED  { +  // the root to the whole LED interface, e.g. "/sys/class/leds/ACT"    std::filesystem::path green;    std::filesystem::path red;  }; @@ -14,15 +15,23 @@ class StatusLED  public:    enum class Mode    { -    OK, // green -    Error // red +    OK,     // green +    OKBeat, // green with heartbeat +    Error,  // red    };    StatusLED();    void addLED(const LED& led); +  void setMode(Mode mode); +  void setBPM(int bpm); +  private: +  void initLED(const LED& led); +  void updateLED(const LED& led); +    std::vector<LED> m_leds; // on best effort base, those will all show the same status    Mode m_mode; +  int m_bpm;  }; | 
