diff options
author | Roland Reichwein <mail@reichwein.it> | 2025-01-20 16:32:33 +0100 |
---|---|---|
committer | Roland Reichwein <mail@reichwein.it> | 2025-01-20 16:32:33 +0100 |
commit | ef578ac72a70bfbe8aee726d43374c841d77ade4 (patch) | |
tree | daa87af254aa5bc3fbb9b2276f1059c872c2a423 | |
parent | 7ecbb11321a05f7498f36ff91d08b51fd3d00a62 (diff) |
Detect MIDI port
-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; }; |