AlsaBridge.cpp
branchv_0
changeset 11 5b351628a377
parent 9 ee976a1d1f0a
child 12 15d87fdd6e6c
equal deleted inserted replaced
10:4d95b089457d 11:5b351628a377
    17 #include <iostream>
    17 #include <iostream>
    18 #include <stdexcept>
    18 #include <stdexcept>
    19 #include <thread>
    19 #include <thread>
    20 #include <mutex>
    20 #include <mutex>
    21 #include <atomic>
    21 #include <atomic>
       
    22 #include <regex>
    22 
    23 
    23 #include <alsa/asoundlib.h>
    24 #include <alsa/asoundlib.h>
    24 
    25 
    25 #include "AlsaBridge.h"
    26 #include "AlsaBridge.h"
    26 
    27 
    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