33 snd_rawmidi_t* input; |
34 snd_rawmidi_t* input; |
34 snd_rawmidi_t* output; |
35 snd_rawmidi_t* output; |
35 std::thread receivingThread; |
36 std::thread receivingThread; |
36 std::recursive_mutex midiMutex; |
37 std::recursive_mutex midiMutex; |
37 std::atomic<bool> stopped{false}; |
38 std::atomic<bool> stopped{false}; |
|
39 |
|
40 std::string findDeviceName(std::regex cardNamePattern) { |
|
41 |
|
42 std::vector<int> cardNumbers; |
|
43 |
|
44 std::cerr << "Looking for available cards:" << std::endl; // TODO: do not mess STDIO |
|
45 |
|
46 for (int card = -1; snd_card_next(&card) == 0 && card >= 0;) { |
|
47 char* longName = nullptr; |
|
48 snd_card_get_longname(card, &longName); |
|
49 std::cerr << "card: #" << card << ": '" << longName << "'"; // TODO: do not mess STDIO |
|
50 if (std::regex_match(longName, cardNamePattern)) { |
|
51 cardNumbers.push_back(card); |
|
52 std::cerr << " [matches]"; // TODO: do not mess STDIO |
|
53 } |
|
54 std::cerr << std::endl; |
|
55 free(longName); |
|
56 } |
|
57 |
|
58 if (cardNumbers.size() == 1) { |
|
59 std::cerr << "Going to fix card #" << cardNumbers[0] << std::endl; // TODO: do not mess STDIO |
|
60 return "hw:" + std::to_string(cardNumbers[0]); |
|
61 } else if (cardNumbers.empty()) { |
|
62 throw std::invalid_argument("No card with matching name found. Is the card connected? Maybe try to provide different name pattern."); |
|
63 } else { |
|
64 throw std::invalid_argument("Multiple cards with matching name found. Please provide a name pattern that matches only one card"); |
|
65 } |
|
66 } |
38 |
67 |
39 void run() { |
68 void run() { |
40 while (!stopped) { |
69 while (!stopped) { |
41 { |
70 { |
42 std::lock_guard<std::recursive_mutex> lock(midiMutex); |
71 std::lock_guard<std::recursive_mutex> lock(midiMutex); |
51 std::this_thread::sleep_for(std::chrono::milliseconds(100)); |
80 std::this_thread::sleep_for(std::chrono::milliseconds(100)); |
52 } |
81 } |
53 } |
82 } |
54 public: |
83 public: |
55 |
84 |
56 AlsaBridgeImpl(djmfix::DJMFix* djmFix, const std::string& deviceName) : djmFix(djmFix) { |
85 AlsaBridgeImpl(djmfix::DJMFix* djmFix, const std::string& cardNamePattern) : djmFix(djmFix) { |
57 if (djmFix == nullptr) throw std::invalid_argument("need a djmFix for AlsaBridge"); |
86 if (djmFix == nullptr) throw std::invalid_argument("need a djmFix for AlsaBridge"); |
|
87 |
|
88 std::string deviceName = findDeviceName(std::regex(cardNamePattern)); |
58 |
89 |
59 int error = snd_rawmidi_open(&input, &output, deviceName.c_str(), SND_RAWMIDI_NONBLOCK); |
90 int error = snd_rawmidi_open(&input, &output, deviceName.c_str(), SND_RAWMIDI_NONBLOCK); |
60 if (error) throw std::invalid_argument("unable to open ALSA device"); |
91 if (error) throw std::invalid_argument("unable to open ALSA device"); |
61 |
92 |
62 |
93 |