*
This commit is contained in:
@@ -0,0 +1,135 @@
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Threading;
|
||||
using static RushMidiLibrary.MidiApiWindows;
|
||||
|
||||
namespace RushMidiLibrary {
|
||||
public class MidiInputDevice : MidiDevice {
|
||||
private MidiApiWindows.MidiInProc _inputCallback;
|
||||
private UIntPtr _deviceId;
|
||||
private MidiApiWindows.HMIDIIN _deviceHandle;
|
||||
private Thread _messageProcessingThread;
|
||||
private bool _messageProcessingThreadExitRequest = false;
|
||||
|
||||
readonly BlockingCollection<Message> _messageQueue = new BlockingCollection<Message>();
|
||||
|
||||
private struct Message {
|
||||
public MidiApiWindows.HMIDIIN hMidiIn;
|
||||
public MidiApiWindows.MidiInMessage wMsg;
|
||||
public UIntPtr dwInstance;
|
||||
public UIntPtr dwParam1;
|
||||
public UIntPtr dwParam2;
|
||||
}
|
||||
|
||||
public MidiInputDevice(UIntPtr deviceId, MidiApiWindows.MIDIINCAPS caps) {
|
||||
_deviceId = deviceId;
|
||||
}
|
||||
|
||||
public static MidiInputDevice[] Enumerate() {
|
||||
var devs = MidiApiWindows.midiInGetNumDevs();
|
||||
MidiInputDevice[] result = new MidiInputDevice[devs];
|
||||
for (uint deviceId = 0; deviceId < devs; deviceId++) {
|
||||
MidiApiWindows.MIDIINCAPS caps;
|
||||
MidiApiWindows.midiInGetDevCaps((UIntPtr)deviceId, out caps);
|
||||
result[deviceId] = new MidiInputDevice((UIntPtr)deviceId, caps);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public void Open() {
|
||||
_inputCallback = this.InputCallback;
|
||||
|
||||
BeginMessageProcessing();
|
||||
try {
|
||||
CheckMMResult(MidiApiWindows.midiInOpen(out _deviceHandle, _deviceId, _inputCallback, (UIntPtr)0));
|
||||
}
|
||||
catch (Exception) {
|
||||
EndMessageProcessing();
|
||||
throw;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void Start() {
|
||||
CheckMMResult(MidiApiWindows.midiInStart(_deviceHandle));
|
||||
}
|
||||
|
||||
private void InputCallback(MidiApiWindows.HMIDIIN hMidiIn, MidiApiWindows.MidiInMessage wMsg, UIntPtr dwInstance, UIntPtr dwParam1, UIntPtr dwParam2) {
|
||||
Message message = new Message();
|
||||
message.hMidiIn = hMidiIn;
|
||||
message.wMsg = wMsg;
|
||||
message.dwInstance = dwInstance;
|
||||
message.dwParam1 = dwParam1;
|
||||
message.dwParam2 = dwParam2;
|
||||
_messageQueue.Add(message);
|
||||
}
|
||||
|
||||
|
||||
private void BeginMessageProcessing() {
|
||||
_messageProcessingThreadExitRequest = false;
|
||||
_messageProcessingThread = new Thread(MessageProcessingThreadHandler);
|
||||
_messageProcessingThread.Start();
|
||||
}
|
||||
|
||||
private void MessageProcessingThreadHandler() {
|
||||
while (!_messageProcessingThreadExitRequest) {
|
||||
Message message;
|
||||
if (_messageQueue.TryTake(out message, 100)) {
|
||||
HandleMessage(message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void EndMessageProcessing() {
|
||||
_messageProcessingThreadExitRequest = true;
|
||||
_messageProcessingThread.Join();
|
||||
}
|
||||
|
||||
private void HandleMessage(Message message) {
|
||||
|
||||
switch (message.wMsg) {
|
||||
case MidiInMessage.MIM_DATA:
|
||||
HandleMessageData(new MidiShortMessage(message.dwParam1, message.dwParam2));
|
||||
break;
|
||||
case MidiInMessage.MIM_LONGDATA:
|
||||
HandleMessageLongData(message.dwParam1, message.dwParam2);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private void HandleMessageData(MidiShortMessage message) {
|
||||
if (message.IsNoteOn) {
|
||||
MidiChannel channel;
|
||||
int noteId;
|
||||
int velocity;
|
||||
uint timestamp;
|
||||
message.GetNoteOn(out channel, out noteId, out velocity, out timestamp);
|
||||
|
||||
var note = new MidiNote(noteId);
|
||||
|
||||
Console.WriteLine($"Received short message NoteOn: Name={note.Name} Octave={note.OctaveName} Channel={channel.ToString()}, NoteId={noteId}, Velocity={velocity}, Timestapm={timestamp}");
|
||||
|
||||
} else if (message.IsNoteOff) {
|
||||
MidiChannel channel;
|
||||
int noteId;
|
||||
int velocity;
|
||||
uint timestamp;
|
||||
message.GetNoteOff(out channel, out noteId, out velocity, out timestamp);
|
||||
|
||||
var note = new MidiNote(noteId);
|
||||
|
||||
Console.WriteLine($"Received short message NoteOff: Name={note.Name} Octave={note.OctaveName} Channel={channel.ToString()}, NoteId={noteId}, Velocity={velocity}, Timestapm={timestamp}");
|
||||
|
||||
} else {
|
||||
Console.WriteLine($"Received short message");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void HandleMessageLongData(UIntPtr dwParam1, UIntPtr dwParam2) {
|
||||
Console.WriteLine($"Received long message");
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user