14#ifndef WIN32_LEAN_AND_MEAN
15#define WIN32_LEAN_AND_MEAN
25void MidiInWindows::registerAll(EventDistributor& eventDistributor,
27 PluggingController& controller)
30 for (
auto i :
xrange(w32_midiInGetVFNsNum())) {
31 controller.registerPluggable(std::make_unique<MidiInWindows>(
32 eventDistributor, scheduler, i));
37MidiInWindows::MidiInWindows(EventDistributor& eventDistributor_,
39 : eventDistributor(eventDistributor_), scheduler(scheduler_)
40 , devIdx(unsigned(-1))
42 name = w32_midiInGetVFN(num);
43 desc = w32_midiInGetRDN(num);
45 eventDistributor.registerEventListener(EventType::MIDI_IN_WINDOWS, *
this);
48MidiInWindows::~MidiInWindows()
50 eventDistributor.unregisterEventListener(EventType::MIDI_IN_WINDOWS, *
this);
56void MidiInWindows::plugHelper(
Connector& connector_, EmuTime::param )
59 midiConnector.setDataBits(SerialDataInterface::DATA_8);
60 midiConnector.setStopBits(SerialDataInterface::STOP_1);
61 midiConnector.setParityBit(
false, SerialDataInterface::EVEN);
63 setConnector(&connector_);
67 std::unique_lock<std::mutex> threadIdLock(threadIdMutex);
68 thread = std::thread([
this]() { run(); });
69 threadIdCond.wait(threadIdLock);
72 std::lock_guard<std::mutex> devIdxLock(devIdxMutex);
73 devIdx = w32_midiInOpen(name.c_str(), threadId);
75 devIdxCond.notify_all();
76 if (devIdx ==
unsigned(-1)) {
77 throw PlugException(
"Failed to open " + name);
81void MidiInWindows::unplugHelper(EmuTime::param )
83 assert(devIdx !=
unsigned(-1));
84 w32_midiInClose(devIdx);
85 devIdx = unsigned(-1);
94std::string_view MidiInWindows::getDescription()
const
99void MidiInWindows::procLongMsg(LPMIDIHDR p)
101 if (p->dwBytesRecorded) {
103 std::lock_guard<std::mutex> lock(queueMutex);
104 for (
auto i :
xrange(p->dwBytesRecorded)) {
105 queue.push_back(p->lpData[i]);
108 eventDistributor.distributeEvent(
109 Event::create<MidiInWindowsEvent>());
113void MidiInWindows::procShortMsg(DWORD param)
116 switch (param & 0xF0) {
117 case 0x80:
case 0x90:
case 0xA0:
case 0xB0:
case 0xE0:
119 case 0xC0:
case 0xD0:
124 std::lock_guard<std::mutex> lock(queueMutex);
126 queue.push_back(param & 0xFF);
129 eventDistributor.distributeEvent(
130 Event::create<MidiInWindowsEvent>());
133void MidiInWindows::run()
135 assert(isPluggedIn());
138 std::lock_guard<std::mutex> threadIdLock(threadIdMutex);
139 threadId = GetCurrentThreadId();
143 std::unique_lock<std::mutex> devIdxLock(devIdxMutex);
144 threadIdCond.notify_all();
145 devIdxCond.wait(devIdxLock);
148 bool fexit = devIdx == unsigned(-1);
151 if (GetMessage(&msg,
nullptr, 0, 0) ==
one_of(0, -1)) {
154 switch (msg.message) {
158 case MM_MIM_MOREDATA:
159 procShortMsg(DWORD(msg.lParam));
161 case MM_MIM_LONGDATA:
162 procLongMsg(
reinterpret_cast<LPMIDIHDR
>(msg.lParam));
165 case MM_MIM_LONGERROR:
177void MidiInWindows::signal(EmuTime::param time)
180 if (!conn->acceptsData()) {
181 std::lock_guard<std::mutex> lock(queueMutex);
185 if (!conn->ready())
return;
189 std::lock_guard<std::mutex> lock(queueMutex);
190 if (queue.empty())
return;
191 data = queue.pop_front();
193 conn->recvByte(data, time);
197int MidiInWindows::signalEvent(
const Event& )
200 signal(scheduler.getCurrentTime());
202 std::lock_guard<std::mutex> lock(queueMutex);
208template<
typename Archive>
std::string getName(KeyCode keyCode)
Translate key code to key name.
This file implemented 3 utility functions:
void serialize(Archive &ar, T &t, unsigned version)
#define INSTANTIATE_SERIALIZE_METHODS(CLASS)
constexpr auto xrange(T e)