AlsaBridge.cpp
branchv_0
changeset 13 334b727f7516
parent 12 15d87fdd6e6c
equal deleted inserted replaced
12:15d87fdd6e6c 13:334b727f7516
    13  *
    13  *
    14  * You should have received a copy of the GNU General Public License
    14  * You should have received a copy of the GNU General Public License
    15  * along with this program. If not, see <http://www.gnu.org/licenses/>.
    15  * along with this program. If not, see <http://www.gnu.org/licenses/>.
    16  */
    16  */
    17 #include <iostream>
    17 #include <iostream>
       
    18 #include <iomanip>
    18 #include <sstream>
    19 #include <sstream>
    19 #include <stdexcept>
    20 #include <stdexcept>
    20 #include <thread>
    21 #include <thread>
    21 #include <mutex>
    22 #include <mutex>
    22 #include <atomic>
    23 #include <atomic>
    73 		} else {
    74 		} else {
    74 			throw std::invalid_argument("Multiple cards with matching name found. Please provide a name pattern that matches only one card");
    75 			throw std::invalid_argument("Multiple cards with matching name found. Please provide a name pattern that matches only one card");
    75 		}
    76 		}
    76 	}
    77 	}
    77 
    78 
       
    79 	std::string toString(const MidiMessage& midiMessage) {
       
    80 		std::stringstream result;
       
    81 		for (uint8_t b : midiMessage) result << std::hex << std::setw(2) << std::setfill('0') << (int) b;
       
    82 		return result.str();
       
    83 	}
       
    84 
    78 	void run() {
    85 	void run() {
    79 		while (!stopped) {
    86 		while (!stopped) {
    80 			{
    87 			{
    81 				std::lock_guard<std::recursive_mutex> lock(midiMutex);
    88 				std::lock_guard<std::recursive_mutex> lock(midiMutex);
    82 				// TODO: poll
    89 				// TODO: poll
    91 		}
    98 		}
    92 	}
    99 	}
    93 public:
   100 public:
    94 
   101 
    95 	AlsaBridgeImpl(djmfix::DJMFix* djmFix, const std::string& cardNamePattern, djmfix::logging::Logger* logger) : djmFix(djmFix), logger(logger ? logger : djmfix::logging::blackhole()) {
   102 	AlsaBridgeImpl(djmfix::DJMFix* djmFix, const std::string& cardNamePattern, djmfix::logging::Logger* logger) : djmFix(djmFix), logger(logger ? logger : djmfix::logging::blackhole()) {
    96 		if (djmFix == nullptr) throw std::invalid_argument("need a djmFix for AlsaBridge");
   103 		if (djmFix == nullptr) throw std::invalid_argument("Need a djmFix for AlsaBridge.");
    97 
   104 
    98 		std::string deviceName = findDeviceName(std::regex(cardNamePattern));
   105 		std::string deviceName = findDeviceName(std::regex(cardNamePattern));
    99 
   106 
   100 		int error = snd_rawmidi_open(&input, &output, deviceName.c_str(), SND_RAWMIDI_NONBLOCK);
   107 		int error = snd_rawmidi_open(&input, &output, deviceName.c_str(), SND_RAWMIDI_NONBLOCK);
   101 		if (error) throw std::invalid_argument("unable to open ALSA device");
   108 		if (error) throw std::invalid_argument("Unable to open ALSA device.");
   102 
   109 
   103 
   110 
   104 		djmFix->setMidiSender(this);
   111 		djmFix->setMidiSender(this);
   105 	}
   112 	}
   106 
   113 
   107 	virtual ~AlsaBridgeImpl() {
   114 	virtual ~AlsaBridgeImpl() {
   108 		// TODO: do not use raw/exclusive access to the MIDI device
   115 		// TODO: do not use raw/exclusive access to the MIDI device
   109 		snd_rawmidi_close(input);
   116 		snd_rawmidi_close(input);
   110 		snd_rawmidi_close(output);
   117 		snd_rawmidi_close(output);
   111 		logger->log(L::FINE, "~AlsaBridgeImpl()");
   118 		logger->log(L::FINER, "~AlsaBridgeImpl()");
   112 	}
   119 	}
   113 
   120 
   114 	virtual void start() override {
   121 	virtual void start() override {
   115 		djmFix->start();
   122 		djmFix->start();
   116 		receivingThread = std::thread(&AlsaBridgeImpl::run, this);
   123 		receivingThread = std::thread(&AlsaBridgeImpl::run, this);
   123 	}
   130 	}
   124 
   131 
   125 	virtual void send(MidiMessage midiMessage) override {
   132 	virtual void send(MidiMessage midiMessage) override {
   126 		std::lock_guard<std::recursive_mutex> lock(midiMutex);
   133 		std::lock_guard<std::recursive_mutex> lock(midiMutex);
   127 		ssize_t length = snd_rawmidi_write(output, midiMessage.data(), midiMessage.size());
   134 		ssize_t length = snd_rawmidi_write(output, midiMessage.data(), midiMessage.size());
   128 		logger->log(L::INFO, "AlsaBridgeImpl::send(): length = " + std::to_string(length));
   135 		logger->log(L::FINE, "Sent message: length = " + std::to_string(length) + " data = " + toString(midiMessage));
   129 	}
   136 	}
   130 
   137 
   131 };
   138 };
   132 
   139 
   133 AlsaBridge* create(djmfix::DJMFix* djmFix, const std::string& deviceName, djmfix::logging::Logger* logger) {
   140 AlsaBridge* create(djmfix::DJMFix* djmFix, const std::string& deviceName, djmfix::logging::Logger* logger) {