1.1 --- a/AlsaBridge.cpp Fri May 09 23:17:36 2025 +0200
1.2 +++ b/AlsaBridge.cpp Sun May 11 00:30:03 2025 +0200
1.3 @@ -43,9 +43,14 @@
1.4 std::recursive_mutex midiMutex;
1.5 std::atomic<bool> stopped{false};
1.6
1.7 - std::string findDeviceName(std::regex cardNamePattern) {
1.8 + struct FoundDevice {
1.9 + std::string id;
1.10 + std::string name;
1.11 + };
1.12
1.13 + FoundDevice findDeviceName(std::regex cardNamePattern) {
1.14 std::vector<int> cardNumbers;
1.15 + std::vector<std::string> cardNames;
1.16
1.17 logger->log(L::INFO, "Looking for available cards:");
1.18
1.19 @@ -58,6 +63,7 @@
1.20
1.21 if (std::regex_match(longName, cardNamePattern)) {
1.22 cardNumbers.push_back(card);
1.23 + cardNames.push_back(longName);
1.24 logMessage << " [matches]";
1.25 }
1.26
1.27 @@ -69,7 +75,7 @@
1.28 if (cardNumbers.size() == 1) {
1.29 const auto n = std::to_string(cardNumbers[0]);
1.30 logger->log(L::INFO, "Going to fix card #" + n);
1.31 - return "hw:" + n;
1.32 + return {"hw:" + n, cardNames[0]};
1.33 } else if (cardNumbers.empty()) {
1.34 throw std::invalid_argument(
1.35 "No card with matching name found. Is the card connected? "
1.36 @@ -89,6 +95,7 @@
1.37 }
1.38
1.39 void run() {
1.40 + MidiMessage msg;
1.41 while (!stopped) {
1.42 {
1.43 std::lock_guard<std::recursive_mutex> lock(midiMutex);
1.44 @@ -96,8 +103,32 @@
1.45 uint8_t buf[256];
1.46 ssize_t length = snd_rawmidi_read(input, buf, sizeof (buf));
1.47 if (length > 0 && length <= sizeof (buf)) {
1.48 - // TODO: multiple messages combined together?
1.49 - djmFix->receive(MidiMessage(buf, buf + length));
1.50 + // Parse MIDI messages and ignore/skip unwanted data.
1.51 + // Needed for DJM-V10 that sends annoying amounts of 0xF8.
1.52 + for (int i = 0; i < length; i++) {
1.53 + uint8_t b = buf[i];
1.54 + if (b == MIDI_CMD_COMMON_SYSEX) {
1.55 + // start of MIDI SysEx message
1.56 + msg.clear();
1.57 + msg.push_back(b);
1.58 + } else if (b == MIDI_CMD_COMMON_SYSEX_END) {
1.59 + // end of MIDI SysEx message
1.60 + msg.push_back(b);
1.61 + djmFix->receive(msg);
1.62 + msg.clear();
1.63 + } else if (b == MIDI_CMD_COMMON_CLOCK) {
1.64 + logger->log(L::FINEST, "timing clock ignored");
1.65 + } else if (b == MIDI_CMD_COMMON_SENSING) {
1.66 + logger->log(L::FINEST, "active sensing ignored");
1.67 + } else if (b & 0x80) {
1.68 + // unknown status, drop previous data
1.69 + msg.clear();
1.70 + logger->log(L::FINER, "unknown message ignored");
1.71 + } else {
1.72 + // message data
1.73 + msg.push_back(b);
1.74 + }
1.75 + }
1.76 }
1.77 }
1.78 std::this_thread::sleep_for(std::chrono::milliseconds(100));
1.79 @@ -114,12 +145,13 @@
1.80 if (djmFix == nullptr)
1.81 throw std::invalid_argument("Need a djmFix for AlsaBridge.");
1.82
1.83 - std::string deviceName = findDeviceName(std::regex(cardNamePattern));
1.84 + FoundDevice found = findDeviceName(std::regex(cardNamePattern));
1.85
1.86 int mode = SND_RAWMIDI_NONBLOCK;
1.87 - int error = snd_rawmidi_open(&input, &output, deviceName.c_str(), mode);
1.88 + int error = snd_rawmidi_open(&input, &output, found.id.c_str(), mode);
1.89 if (error) throw std::invalid_argument("Unable to open ALSA device.");
1.90
1.91 + djmFix->setDeviceName(found.name);
1.92 djmFix->setMidiSender(this);
1.93 }
1.94