summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorRoland Reichwein <mail@reichwein.it>2025-01-20 16:32:33 +0100
committerRoland Reichwein <mail@reichwein.it>2025-01-20 16:32:33 +0100
commitef578ac72a70bfbe8aee726d43374c841d77ade4 (patch)
treedaa87af254aa5bc3fbb9b2276f1059c872c2a423
parent7ecbb11321a05f7498f36ff91d08b51fd3d00a62 (diff)
Detect MIDI port
-rw-r--r--MIDI.cpp60
-rw-r--r--MIDI.h3
-rw-r--r--StatusLED.cpp26
-rw-r--r--StatusLED.h13
4 files changed, 95 insertions, 7 deletions
diff --git a/MIDI.cpp b/MIDI.cpp
index 278e810..d4f5928 100644
--- a/MIDI.cpp
+++ b/MIDI.cpp
@@ -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);
diff --git a/MIDI.h b/MIDI.h
index ee01f5b..46d7482 100644
--- a/MIDI.h
+++ b/MIDI.h
@@ -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;
};