Find card by a name pattern (regular expression) instead using hardcoded name.
By default, we look for card with name matching the "Pioneer DJ.*" pattern and we expect exactly one card to be found.
Custom pattern can be provided as a command-line argument.
Whole name would look something like this: "Pioneer DJ Corporation DJM-250MK2 at usb-0000:01:00.0-10.1, high speed".
--- a/AlsaBridge.cpp Mon Jan 04 00:15:56 2021 +0100
+++ b/AlsaBridge.cpp Mon Jan 04 13:38:08 2021 +0100
@@ -19,6 +19,7 @@
#include <thread>
#include <mutex>
#include <atomic>
+#include <regex>
#include <alsa/asoundlib.h>
@@ -36,6 +37,34 @@
std::recursive_mutex midiMutex;
std::atomic<bool> stopped{false};
+ std::string findDeviceName(std::regex cardNamePattern) {
+
+ std::vector<int> cardNumbers;
+
+ std::cerr << "Looking for available cards:" << std::endl; // TODO: do not mess STDIO
+
+ for (int card = -1; snd_card_next(&card) == 0 && card >= 0;) {
+ char* longName = nullptr;
+ snd_card_get_longname(card, &longName);
+ std::cerr << "card: #" << card << ": '" << longName << "'"; // TODO: do not mess STDIO
+ if (std::regex_match(longName, cardNamePattern)) {
+ cardNumbers.push_back(card);
+ std::cerr << " [matches]"; // TODO: do not mess STDIO
+ }
+ std::cerr << std::endl;
+ free(longName);
+ }
+
+ if (cardNumbers.size() == 1) {
+ std::cerr << "Going to fix card #" << cardNumbers[0] << std::endl; // TODO: do not mess STDIO
+ return "hw:" + std::to_string(cardNumbers[0]);
+ } else if (cardNumbers.empty()) {
+ throw std::invalid_argument("No card with matching name found. Is the card connected? Maybe try to provide different name pattern.");
+ } else {
+ throw std::invalid_argument("Multiple cards with matching name found. Please provide a name pattern that matches only one card");
+ }
+ }
+
void run() {
while (!stopped) {
{
@@ -53,9 +82,11 @@
}
public:
- AlsaBridgeImpl(djmfix::DJMFix* djmFix, const std::string& deviceName) : djmFix(djmFix) {
+ AlsaBridgeImpl(djmfix::DJMFix* djmFix, const std::string& cardNamePattern) : djmFix(djmFix) {
if (djmFix == nullptr) throw std::invalid_argument("need a djmFix for AlsaBridge");
+ std::string deviceName = findDeviceName(std::regex(cardNamePattern));
+
int error = snd_rawmidi_open(&input, &output, deviceName.c_str(), SND_RAWMIDI_NONBLOCK);
if (error) throw std::invalid_argument("unable to open ALSA device");
--- a/AlsaBridge.h Mon Jan 04 00:15:56 2021 +0100
+++ b/AlsaBridge.h Mon Jan 04 13:38:08 2021 +0100
@@ -31,7 +31,7 @@
};
-AlsaBridge* create(djmfix::DJMFix* djmFix, const std::string& deviceName);
+AlsaBridge* create(djmfix::DJMFix* djmFix, const std::string& cardNamePattern);
}
}
--- a/djm-fix.cpp Mon Jan 04 00:15:56 2021 +0100
+++ b/djm-fix.cpp Mon Jan 04 13:38:08 2021 +0100
@@ -70,22 +70,29 @@
* make # we can skip this step, it will be compiled on the first run
*
* Run:
- * make run
+ * make run # in most cases
+ * build/djm-fix 'Pioneer DJ.*' # or provide custom name pattern (regular expression) to select the proper card
*
* Stop:
* press Ctrl+C
+ *
+ * Look for updates in the Mercurial repositories and at <https://blog.frantovo.cz/c/387/>.
*/
int main(int argc, char**argv) {
- std::string deviceName = argc == 2 ? argv[1] : "hw:1"; // FIXME: parse CLI options + automatic device search
+ try {
+ std::string cardNamePattern = argc == 2 ? argv[1] : "Pioneer DJ.*";
- signal(SIGINT, interrupt);
- std::unique_ptr<djmfix::DJMFix> djmFix(djmfix::create());
- std::unique_ptr<djmfix::alsa::AlsaBridge> alsaBridge(djmfix::alsa::create(djmFix.get(), deviceName));
+ signal(SIGINT, interrupt);
+ std::unique_ptr<djmfix::DJMFix> djmFix(djmfix::create());
+ std::unique_ptr<djmfix::alsa::AlsaBridge> alsaBridge(djmfix::alsa::create(djmFix.get(), cardNamePattern));
- alsaBridge->start();
- while (run) std::this_thread::sleep_for(std::chrono::milliseconds(100));
- alsaBridge->stop();
+ alsaBridge->start();
+ while (run) std::this_thread::sleep_for(std::chrono::milliseconds(100));
+ alsaBridge->stop();
- return 0;
+ return 0;
+ } catch (const std::exception& e) {
+ std::cerr << "ERROR: " << e.what() << std::endl; // TODO: do not mess STDIO
+ }
}