diff -r aa7dc7faf1bb -r 358a601bfe81 AlsaBridge.cpp --- a/AlsaBridge.cpp Fri May 09 23:17:36 2025 +0200 +++ b/AlsaBridge.cpp Sun May 11 00:30:03 2025 +0200 @@ -43,9 +43,14 @@ std::recursive_mutex midiMutex; std::atomic stopped{false}; - std::string findDeviceName(std::regex cardNamePattern) { + struct FoundDevice { + std::string id; + std::string name; + }; + FoundDevice findDeviceName(std::regex cardNamePattern) { std::vector cardNumbers; + std::vector cardNames; logger->log(L::INFO, "Looking for available cards:"); @@ -58,6 +63,7 @@ if (std::regex_match(longName, cardNamePattern)) { cardNumbers.push_back(card); + cardNames.push_back(longName); logMessage << " [matches]"; } @@ -69,7 +75,7 @@ if (cardNumbers.size() == 1) { const auto n = std::to_string(cardNumbers[0]); logger->log(L::INFO, "Going to fix card #" + n); - return "hw:" + n; + return {"hw:" + n, cardNames[0]}; } else if (cardNumbers.empty()) { throw std::invalid_argument( "No card with matching name found. Is the card connected? " @@ -89,6 +95,7 @@ } void run() { + MidiMessage msg; while (!stopped) { { std::lock_guard lock(midiMutex); @@ -96,8 +103,32 @@ uint8_t buf[256]; ssize_t length = snd_rawmidi_read(input, buf, sizeof (buf)); if (length > 0 && length <= sizeof (buf)) { - // TODO: multiple messages combined together? - djmFix->receive(MidiMessage(buf, buf + length)); + // Parse MIDI messages and ignore/skip unwanted data. + // Needed for DJM-V10 that sends annoying amounts of 0xF8. + for (int i = 0; i < length; i++) { + uint8_t b = buf[i]; + if (b == MIDI_CMD_COMMON_SYSEX) { + // start of MIDI SysEx message + msg.clear(); + msg.push_back(b); + } else if (b == MIDI_CMD_COMMON_SYSEX_END) { + // end of MIDI SysEx message + msg.push_back(b); + djmFix->receive(msg); + msg.clear(); + } else if (b == MIDI_CMD_COMMON_CLOCK) { + logger->log(L::FINEST, "timing clock ignored"); + } else if (b == MIDI_CMD_COMMON_SENSING) { + logger->log(L::FINEST, "active sensing ignored"); + } else if (b & 0x80) { + // unknown status, drop previous data + msg.clear(); + logger->log(L::FINER, "unknown message ignored"); + } else { + // message data + msg.push_back(b); + } + } } } std::this_thread::sleep_for(std::chrono::milliseconds(100)); @@ -114,12 +145,13 @@ if (djmFix == nullptr) throw std::invalid_argument("Need a djmFix for AlsaBridge."); - std::string deviceName = findDeviceName(std::regex(cardNamePattern)); + FoundDevice found = findDeviceName(std::regex(cardNamePattern)); int mode = SND_RAWMIDI_NONBLOCK; - int error = snd_rawmidi_open(&input, &output, deviceName.c_str(), mode); + int error = snd_rawmidi_open(&input, &output, found.id.c_str(), mode); if (error) throw std::invalid_argument("Unable to open ALSA device."); + djmFix->setDeviceName(found.name); djmFix->setMidiSender(this); }