diff options
| author | tylermurphy534 <tylermurphy534@gmail.com> | 2022-11-06 15:12:42 -0500 |
|---|---|---|
| committer | tylermurphy534 <tylermurphy534@gmail.com> | 2022-11-06 15:12:42 -0500 |
| commit | eb84bb298d2b95aec7b2ae12cbf25ac64f25379a (patch) | |
| tree | efd616a157df06ab661c6d56651853431ac6b08b /VRCSDK3Worlds/Assets/VRCSDK/SDK3/Runtime/Midi | |
| download | unityprojects-eb84bb298d2b95aec7b2ae12cbf25ac64f25379a.tar.gz unityprojects-eb84bb298d2b95aec7b2ae12cbf25ac64f25379a.tar.bz2 unityprojects-eb84bb298d2b95aec7b2ae12cbf25ac64f25379a.zip | |
move to self host
Diffstat (limited to 'VRCSDK3Worlds/Assets/VRCSDK/SDK3/Runtime/Midi')
37 files changed, 954 insertions, 0 deletions
diff --git a/VRCSDK3Worlds/Assets/VRCSDK/SDK3/Runtime/Midi/PortMidi.meta b/VRCSDK3Worlds/Assets/VRCSDK/SDK3/Runtime/Midi/PortMidi.meta new file mode 100644 index 00000000..0b38e67b --- /dev/null +++ b/VRCSDK3Worlds/Assets/VRCSDK/SDK3/Runtime/Midi/PortMidi.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: c4ba92a5dc8e6c14bb9b8dfce6851a99 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/VRCSDK3Worlds/Assets/VRCSDK/SDK3/Runtime/Midi/PortMidi/Event.cs b/VRCSDK3Worlds/Assets/VRCSDK/SDK3/Runtime/Midi/PortMidi/Event.cs new file mode 100644 index 00000000..110564e7 --- /dev/null +++ b/VRCSDK3Worlds/Assets/VRCSDK/SDK3/Runtime/Midi/PortMidi/Event.cs @@ -0,0 +1,17 @@ +namespace PortMidi +{ + public class Event + { + public Event(PmEvent pmEvent) + { + this.Status = PortMidiMarshal.Pm_MessageStatus(pmEvent.message); + this.Data1 = PortMidiMarshal.Pm_MessageData1(pmEvent.message); + this.Data2 = PortMidiMarshal.Pm_MessageData2(pmEvent.message); + } + + public long Timestamp { get; set; } + public long Status { get; set; } + public long Data1 { get; set; } + public long Data2 { get; set; } + } +}
\ No newline at end of file diff --git a/VRCSDK3Worlds/Assets/VRCSDK/SDK3/Runtime/Midi/PortMidi/Event.cs.meta b/VRCSDK3Worlds/Assets/VRCSDK/SDK3/Runtime/Midi/PortMidi/Event.cs.meta new file mode 100644 index 00000000..d02de3b3 --- /dev/null +++ b/VRCSDK3Worlds/Assets/VRCSDK/SDK3/Runtime/Midi/PortMidi/Event.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 61b00e22036b5cc49a565aaec91ca8cb +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/VRCSDK3Worlds/Assets/VRCSDK/SDK3/Runtime/Midi/PortMidi/MidiDeviceInfo.cs b/VRCSDK3Worlds/Assets/VRCSDK/SDK3/Runtime/Midi/PortMidi/MidiDeviceInfo.cs new file mode 100644 index 00000000..001816fe --- /dev/null +++ b/VRCSDK3Worlds/Assets/VRCSDK/SDK3/Runtime/Midi/PortMidi/MidiDeviceInfo.cs @@ -0,0 +1,34 @@ +using System; +using System.Runtime.InteropServices; + +namespace PortMidi +{ + public struct MidiDeviceInfo + { + PmDeviceInfo info; + + internal MidiDeviceInfo(int id, IntPtr ptr) + { + ID = id; + this.info = (PmDeviceInfo) Marshal.PtrToStructure(ptr, typeof(PmDeviceInfo)); + } + + public int ID { get; set; } + + public string Interface => Marshal.PtrToStringAnsi(info.Interface); + + public string Name => Marshal.PtrToStringAnsi(info.Name); + + public bool IsInput => info.Input != 0; + + public bool IsOutput => info.Output != 0; + + public bool IsOpened => info.Opened != 0; + + public override string ToString() + { + return + $"{Interface} - {Name} ({(IsInput ? (IsOutput ? "I/O" : "Input") : (IsOutput ? "Output" : "N/A"))} {(IsOpened ? "open" : String.Empty)})"; + } + } +}
\ No newline at end of file diff --git a/VRCSDK3Worlds/Assets/VRCSDK/SDK3/Runtime/Midi/PortMidi/MidiDeviceInfo.cs.meta b/VRCSDK3Worlds/Assets/VRCSDK/SDK3/Runtime/Midi/PortMidi/MidiDeviceInfo.cs.meta new file mode 100644 index 00000000..60628362 --- /dev/null +++ b/VRCSDK3Worlds/Assets/VRCSDK/SDK3/Runtime/Midi/PortMidi/MidiDeviceInfo.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: bbb88a986ea685d41a9eac3aa3dd8c60 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/VRCSDK3Worlds/Assets/VRCSDK/SDK3/Runtime/Midi/PortMidi/MidiDeviceManager.cs b/VRCSDK3Worlds/Assets/VRCSDK/SDK3/Runtime/Midi/PortMidi/MidiDeviceManager.cs new file mode 100644 index 00000000..4628afc1 --- /dev/null +++ b/VRCSDK3Worlds/Assets/VRCSDK/SDK3/Runtime/Midi/PortMidi/MidiDeviceManager.cs @@ -0,0 +1,69 @@ +using System; +using System.Collections.Generic; +using PmDeviceID = System.Int32; +using PortMidiStream = System.IntPtr; +using PmError = PortMidi.MidiErrorType; + +namespace PortMidi +{ + public static class MidiDeviceManager + { + private const int DefaultBufferSize = 1024; + + static MidiDeviceManager() + { + PortMidiMarshal.Pm_Initialize(); + AppDomain.CurrentDomain.DomainUnload += delegate { PortMidiMarshal.Pm_Terminate(); }; + } + + public static int DeviceCount => PortMidiMarshal.Pm_CountDevices(); + + public static int DefaultInputDeviceId => PortMidiMarshal.Pm_GetDefaultInputDeviceID(); + + public static int DefaultOutputDeviceId => PortMidiMarshal.Pm_GetDefaultOutputDeviceID(); + + public static IEnumerable<MidiDeviceInfo> AllDevices + { + get + { + for (var i = 0; i < DeviceCount; i++) + { + yield return GetDeviceInfo(i); + } + } + } + + private static MidiDeviceInfo GetDeviceInfo(PmDeviceID id) + { + return new MidiDeviceInfo(id, PortMidiMarshal.Pm_GetDeviceInfo(id)); + } + + public static MidiInput OpenInput(PmDeviceID inputDevice) + { + return OpenInput(inputDevice, DefaultBufferSize); + } + + private static MidiInput OpenInput(PmDeviceID inputDevice, int bufferSize) + { + PortMidiStream stream = default; + var e = PortMidiMarshal.Pm_OpenInput(out stream, inputDevice, IntPtr.Zero, bufferSize, null, IntPtr.Zero); + if (e != PmError.NoError) + { + throw new MidiException(e, $"Failed to open MIDI input device {e}"); + } + + return new MidiInput(stream, inputDevice); + } + + public static MidiOutput OpenOutput(PmDeviceID outputDevice) + { + PortMidiStream stream; + var e = PortMidiMarshal.Pm_OpenOutput(out stream, outputDevice, IntPtr.Zero, 0, null, IntPtr.Zero, 0); + if (e != PmError.NoError) + { + throw new MidiException(e, $"Failed to open MIDI output device {e}"); + } + return new MidiOutput(stream, outputDevice, 0); + } + } +}
\ No newline at end of file diff --git a/VRCSDK3Worlds/Assets/VRCSDK/SDK3/Runtime/Midi/PortMidi/MidiDeviceManager.cs.meta b/VRCSDK3Worlds/Assets/VRCSDK/SDK3/Runtime/Midi/PortMidi/MidiDeviceManager.cs.meta new file mode 100644 index 00000000..3874e4b5 --- /dev/null +++ b/VRCSDK3Worlds/Assets/VRCSDK/SDK3/Runtime/Midi/PortMidi/MidiDeviceManager.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 02b0549f0815d8a4982133c0a99880cf +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/VRCSDK3Worlds/Assets/VRCSDK/SDK3/Runtime/Midi/PortMidi/MidiErrorType.cs b/VRCSDK3Worlds/Assets/VRCSDK/SDK3/Runtime/Midi/PortMidi/MidiErrorType.cs new file mode 100644 index 00000000..e03dfdcf --- /dev/null +++ b/VRCSDK3Worlds/Assets/VRCSDK/SDK3/Runtime/Midi/PortMidi/MidiErrorType.cs @@ -0,0 +1,18 @@ +namespace PortMidi +{ + public enum MidiErrorType + { + NoError = 0, + NoData = 0, + GotData = 1, + HostError = -10000, + InvalidDeviceId, + InsufficientMemory, + BufferTooSmall, + BufferOverflow, + BadPointer, + BadData, + InternalError, + BufferMaxSize, + } +}
\ No newline at end of file diff --git a/VRCSDK3Worlds/Assets/VRCSDK/SDK3/Runtime/Midi/PortMidi/MidiErrorType.cs.meta b/VRCSDK3Worlds/Assets/VRCSDK/SDK3/Runtime/Midi/PortMidi/MidiErrorType.cs.meta new file mode 100644 index 00000000..15768ae2 --- /dev/null +++ b/VRCSDK3Worlds/Assets/VRCSDK/SDK3/Runtime/Midi/PortMidi/MidiErrorType.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 6b1e1637c177e0c43af16fefddc0826c +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/VRCSDK3Worlds/Assets/VRCSDK/SDK3/Runtime/Midi/PortMidi/MidiEvent.cs b/VRCSDK3Worlds/Assets/VRCSDK/SDK3/Runtime/Midi/PortMidi/MidiEvent.cs new file mode 100644 index 00000000..b304cefd --- /dev/null +++ b/VRCSDK3Worlds/Assets/VRCSDK/SDK3/Runtime/Midi/PortMidi/MidiEvent.cs @@ -0,0 +1,31 @@ +using System; +using System.Runtime.InteropServices; + +namespace PortMidi +{ + [StructLayout(LayoutKind.Sequential)] + public struct MidiEvent + { + MidiMessage msg; + Int32 ts; + [NonSerialized] byte[] sysex; + + public MidiMessage Message + { + get => msg; + set => msg = value; + } + + public Int32 Timestamp + { + get => ts; + set => ts = value; + } + + public byte[] SysEx + { + get => sysex; + set => sysex = value; + } + } +}
\ No newline at end of file diff --git a/VRCSDK3Worlds/Assets/VRCSDK/SDK3/Runtime/Midi/PortMidi/MidiEvent.cs.meta b/VRCSDK3Worlds/Assets/VRCSDK/SDK3/Runtime/Midi/PortMidi/MidiEvent.cs.meta new file mode 100644 index 00000000..cb252310 --- /dev/null +++ b/VRCSDK3Worlds/Assets/VRCSDK/SDK3/Runtime/Midi/PortMidi/MidiEvent.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: b8f59aea3b1948f4ebb0d7835b69bbb7 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/VRCSDK3Worlds/Assets/VRCSDK/SDK3/Runtime/Midi/PortMidi/MidiException.cs b/VRCSDK3Worlds/Assets/VRCSDK/SDK3/Runtime/Midi/PortMidi/MidiException.cs new file mode 100644 index 00000000..551297b2 --- /dev/null +++ b/VRCSDK3Worlds/Assets/VRCSDK/SDK3/Runtime/Midi/PortMidi/MidiException.cs @@ -0,0 +1,22 @@ +using System; + +namespace PortMidi +{ + public class MidiException : Exception + { + MidiErrorType error_type; + + public MidiException(MidiErrorType errorType, string message) + : this(errorType, message, null) + { + } + + public MidiException(MidiErrorType errorType, string message, Exception innerException) + : base(message, innerException) + { + error_type = errorType; + } + + public MidiErrorType ErrorType => error_type; + } +}
\ No newline at end of file diff --git a/VRCSDK3Worlds/Assets/VRCSDK/SDK3/Runtime/Midi/PortMidi/MidiException.cs.meta b/VRCSDK3Worlds/Assets/VRCSDK/SDK3/Runtime/Midi/PortMidi/MidiException.cs.meta new file mode 100644 index 00000000..82da420f --- /dev/null +++ b/VRCSDK3Worlds/Assets/VRCSDK/SDK3/Runtime/Midi/PortMidi/MidiException.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: a9aa39367a5a6014e8ae35c4c0fc0fd0 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/VRCSDK3Worlds/Assets/VRCSDK/SDK3/Runtime/Midi/PortMidi/MidiFilter.cs b/VRCSDK3Worlds/Assets/VRCSDK/SDK3/Runtime/Midi/PortMidi/MidiFilter.cs new file mode 100644 index 00000000..d270806a --- /dev/null +++ b/VRCSDK3Worlds/Assets/VRCSDK/SDK3/Runtime/Midi/PortMidi/MidiFilter.cs @@ -0,0 +1,30 @@ +using System; + +namespace PortMidi +{ + [Flags] + public enum MidiFilter : int + { + Active = 1 << 0x0E, + SysEx = 1, + Clock = 1 << 0x08, + Play = ((1 << 0x0A) | (1 << 0x0C) | (1 << 0x0B)), + Tick = (1 << 0x09), + FD = (1 << 0x0D), + Undefined = FD, + Reset = (1 << 0x0F), + RealTime = (Active | SysEx | Clock | Play | Undefined | Reset | Tick), + Note = ((1 << 0x19) | (1 << 0x18)), + CAF = (1 << 0x1D), + PAF = (1 << 0x1A), + AF = (CAF | PAF), + Program = (1 << 0x1C), + Control = (1 << 0x1B), + PitchBend = (1 << 0x1E), + MTC = (1 << 0x01), + SongPosition = (1 << 0x02), + SongSelect = (1 << 0x03), + Tune = (1 << 0x06), + SystemCommon = (MTC | SongPosition | SongSelect | Tune) + } +}
\ No newline at end of file diff --git a/VRCSDK3Worlds/Assets/VRCSDK/SDK3/Runtime/Midi/PortMidi/MidiFilter.cs.meta b/VRCSDK3Worlds/Assets/VRCSDK/SDK3/Runtime/Midi/PortMidi/MidiFilter.cs.meta new file mode 100644 index 00000000..f553d7f5 --- /dev/null +++ b/VRCSDK3Worlds/Assets/VRCSDK/SDK3/Runtime/Midi/PortMidi/MidiFilter.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 9ddf13cca3c55164692f303b16a5fb2d +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/VRCSDK3Worlds/Assets/VRCSDK/SDK3/Runtime/Midi/PortMidi/MidiInput.cs b/VRCSDK3Worlds/Assets/VRCSDK/SDK3/Runtime/Midi/PortMidi/MidiInput.cs new file mode 100644 index 00000000..dbb35623 --- /dev/null +++ b/VRCSDK3Worlds/Assets/VRCSDK/SDK3/Runtime/Midi/PortMidi/MidiInput.cs @@ -0,0 +1,57 @@ +using System; +using System.Collections.Generic; +using System.Runtime.InteropServices; + +namespace PortMidi +{ + public class MidiInput : MidiStream + { + public MidiInput(IntPtr stream, Int32 inputDevice) + : base(stream, inputDevice) + { + } + + public bool HasData => PortMidiMarshal.Pm_Poll(stream) == MidiErrorType.GotData; + + public int Read(byte[] buffer, int index, int length) + { + var gch = GCHandle.Alloc(buffer); + try + { + var ptr = Marshal.UnsafeAddrOfPinnedArrayElement(buffer, index); + int size = PortMidiMarshal.Pm_Read(stream, ptr, length); + if (size < 0) + { + throw new MidiException((MidiErrorType) size, + PortMidiMarshal.Pm_GetErrorText((MidiErrorType) size)); + } + return size * 4; + } + finally + { + gch.Free(); + } + } + + public Event ReadEvent(byte[] buffer, int index, int length) + { + var gch = GCHandle.Alloc(buffer); + try + { + var ptr = Marshal.UnsafeAddrOfPinnedArrayElement(buffer, index); + int size = PortMidiMarshal.Pm_Read(stream, ptr, length); + if (size < 0) + { + throw new MidiException((MidiErrorType) size, + PortMidiMarshal.Pm_GetErrorText((MidiErrorType) size)); + } + + return new Event(Marshal.PtrToStructure<PmEvent>(ptr)); + } + finally + { + gch.Free(); + } + } + } +}
\ No newline at end of file diff --git a/VRCSDK3Worlds/Assets/VRCSDK/SDK3/Runtime/Midi/PortMidi/MidiInput.cs.meta b/VRCSDK3Worlds/Assets/VRCSDK/SDK3/Runtime/Midi/PortMidi/MidiInput.cs.meta new file mode 100644 index 00000000..c46ce4b1 --- /dev/null +++ b/VRCSDK3Worlds/Assets/VRCSDK/SDK3/Runtime/Midi/PortMidi/MidiInput.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 324be2ea40d796c49b74c60b8c2e5c97 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/VRCSDK3Worlds/Assets/VRCSDK/SDK3/Runtime/Midi/PortMidi/MidiMessage.cs b/VRCSDK3Worlds/Assets/VRCSDK/SDK3/Runtime/Midi/PortMidi/MidiMessage.cs new file mode 100644 index 00000000..a7b7c9c4 --- /dev/null +++ b/VRCSDK3Worlds/Assets/VRCSDK/SDK3/Runtime/Midi/PortMidi/MidiMessage.cs @@ -0,0 +1,20 @@ +using System; + +namespace PortMidi +{ + public struct MidiMessage + { + private int v; + public MidiMessage(int value) + { + v = value; + } + + public MidiMessage(int status, int data1, int data2) + { + v = ((data2 << 16) & 0xFF0000) | ((data1 << 8) & 0xFF00) | (status & 0xFF); + } + + public Int32 Value => v; + } +}
\ No newline at end of file diff --git a/VRCSDK3Worlds/Assets/VRCSDK/SDK3/Runtime/Midi/PortMidi/MidiMessage.cs.meta b/VRCSDK3Worlds/Assets/VRCSDK/SDK3/Runtime/Midi/PortMidi/MidiMessage.cs.meta new file mode 100644 index 00000000..02f67375 --- /dev/null +++ b/VRCSDK3Worlds/Assets/VRCSDK/SDK3/Runtime/Midi/PortMidi/MidiMessage.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: c18643a5c49be3649ade32f7c9b19e99 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/VRCSDK3Worlds/Assets/VRCSDK/SDK3/Runtime/Midi/PortMidi/MidiOutput.cs b/VRCSDK3Worlds/Assets/VRCSDK/SDK3/Runtime/Midi/PortMidi/MidiOutput.cs new file mode 100644 index 00000000..fe56081c --- /dev/null +++ b/VRCSDK3Worlds/Assets/VRCSDK/SDK3/Runtime/Midi/PortMidi/MidiOutput.cs @@ -0,0 +1,67 @@ +using System; +using System.Runtime.InteropServices; + +namespace PortMidi +{ + public class MidiOutput : MidiStream + { + public MidiOutput(IntPtr stream, Int32 outputDevice, int latency) + : base(stream, outputDevice) + { + } + + public void Write(MidiEvent midiEvent) + { + if (midiEvent.SysEx != null) + { + WriteSysEx(midiEvent.Timestamp, midiEvent.SysEx); + } + else + { + Write(midiEvent.Timestamp, midiEvent.Message); + } + } + + private void Write(Int32 when, MidiMessage msg) + { + var ret = PortMidiMarshal.Pm_WriteShort(stream, when, msg); + if (ret != MidiErrorType.NoError) + { + throw new MidiException(ret, + $"Failed to write message {msg.Value} : {PortMidiMarshal.Pm_GetErrorText((MidiErrorType) ret)}"); + } + } + + private void WriteSysEx(Int32 when, byte[] sysEx) + { + var ret = PortMidiMarshal.Pm_WriteSysEx(stream, when, sysEx); + if (ret != MidiErrorType.NoError) + throw new MidiException(ret, + $"Failed to write sysEx message : {PortMidiMarshal.Pm_GetErrorText((MidiErrorType) ret)}"); + } + + public void Write(MidiEvent[] buffer) + { + Write(buffer, 0, buffer.Length); + } + + private void Write(MidiEvent[] buffer, int index, int length) + { + var gch = GCHandle.Alloc(buffer); + try + { + var ptr = Marshal.UnsafeAddrOfPinnedArrayElement(buffer, index); + var ret = PortMidiMarshal.Pm_Write(stream, ptr, length); + if (ret != MidiErrorType.NoError) + { + throw new MidiException(ret, + $"Failed to write messages : {PortMidiMarshal.Pm_GetErrorText((MidiErrorType) ret)}"); + } + } + finally + { + gch.Free(); + } + } + } +}
\ No newline at end of file diff --git a/VRCSDK3Worlds/Assets/VRCSDK/SDK3/Runtime/Midi/PortMidi/MidiOutput.cs.meta b/VRCSDK3Worlds/Assets/VRCSDK/SDK3/Runtime/Midi/PortMidi/MidiOutput.cs.meta new file mode 100644 index 00000000..cc6a9a22 --- /dev/null +++ b/VRCSDK3Worlds/Assets/VRCSDK/SDK3/Runtime/Midi/PortMidi/MidiOutput.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: a806da9b51653af47b83c3c10a6eed65 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/VRCSDK3Worlds/Assets/VRCSDK/SDK3/Runtime/Midi/PortMidi/MidiStream.cs b/VRCSDK3Worlds/Assets/VRCSDK/SDK3/Runtime/Midi/PortMidi/MidiStream.cs new file mode 100644 index 00000000..e4d80447 --- /dev/null +++ b/VRCSDK3Worlds/Assets/VRCSDK/SDK3/Runtime/Midi/PortMidi/MidiStream.cs @@ -0,0 +1,41 @@ +using System; + +namespace PortMidi +{ + public abstract class MidiStream : IDisposable + { + internal IntPtr stream; + internal Int32 device; + + protected MidiStream(IntPtr stream, Int32 deviceID) + { + this.stream = stream; + this.device = deviceID; + } + + public void Abort() + { + PortMidiMarshal.Pm_Abort(stream); + } + + public void Close() + { + Dispose(); + } + + public void Dispose() + { + PortMidiMarshal.Pm_Close(stream); + } + + public void SetFilter(MidiFilter filters) + { + PortMidiMarshal.Pm_SetFilter(stream, filters); + } + + public void SetChannelMask(int mask) + { + PortMidiMarshal.Pm_SetChannelMask(stream, mask); + } + } +}
\ No newline at end of file diff --git a/VRCSDK3Worlds/Assets/VRCSDK/SDK3/Runtime/Midi/PortMidi/MidiStream.cs.meta b/VRCSDK3Worlds/Assets/VRCSDK/SDK3/Runtime/Midi/PortMidi/MidiStream.cs.meta new file mode 100644 index 00000000..a16d7e5c --- /dev/null +++ b/VRCSDK3Worlds/Assets/VRCSDK/SDK3/Runtime/Midi/PortMidi/MidiStream.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: f858f0a52902aaf4298247159434e1ae +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/VRCSDK3Worlds/Assets/VRCSDK/SDK3/Runtime/Midi/PortMidi/MidiTimeProcDelegate.cs b/VRCSDK3Worlds/Assets/VRCSDK/SDK3/Runtime/Midi/PortMidi/MidiTimeProcDelegate.cs new file mode 100644 index 00000000..c0a21dc2 --- /dev/null +++ b/VRCSDK3Worlds/Assets/VRCSDK/SDK3/Runtime/Midi/PortMidi/MidiTimeProcDelegate.cs @@ -0,0 +1,7 @@ +using System; +using PmTimestamp = System.Int32; + +namespace PortMidi +{ + public delegate PmTimestamp MidiTimeProcDelegate(IntPtr timeInfo); +}
\ No newline at end of file diff --git a/VRCSDK3Worlds/Assets/VRCSDK/SDK3/Runtime/Midi/PortMidi/MidiTimeProcDelegate.cs.meta b/VRCSDK3Worlds/Assets/VRCSDK/SDK3/Runtime/Midi/PortMidi/MidiTimeProcDelegate.cs.meta new file mode 100644 index 00000000..79fb10f5 --- /dev/null +++ b/VRCSDK3Worlds/Assets/VRCSDK/SDK3/Runtime/Midi/PortMidi/MidiTimeProcDelegate.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 63050b27ae9f6ab4cb3837f915f15067 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/VRCSDK3Worlds/Assets/VRCSDK/SDK3/Runtime/Midi/PortMidi/Plugins.meta b/VRCSDK3Worlds/Assets/VRCSDK/SDK3/Runtime/Midi/PortMidi/Plugins.meta new file mode 100644 index 00000000..9828731f --- /dev/null +++ b/VRCSDK3Worlds/Assets/VRCSDK/SDK3/Runtime/Midi/PortMidi/Plugins.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 743cfca463c6cc94fabfda636f4eb439 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/VRCSDK3Worlds/Assets/VRCSDK/SDK3/Runtime/Midi/PortMidi/Plugins/Windows.meta b/VRCSDK3Worlds/Assets/VRCSDK/SDK3/Runtime/Midi/PortMidi/Plugins/Windows.meta new file mode 100644 index 00000000..fe5fb2cb --- /dev/null +++ b/VRCSDK3Worlds/Assets/VRCSDK/SDK3/Runtime/Midi/PortMidi/Plugins/Windows.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: bc4d155a8e6f6f144871b6ee03542b7c +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/VRCSDK3Worlds/Assets/VRCSDK/SDK3/Runtime/Midi/PortMidi/Plugins/Windows/portmidi.dll b/VRCSDK3Worlds/Assets/VRCSDK/SDK3/Runtime/Midi/PortMidi/Plugins/Windows/portmidi.dll Binary files differnew file mode 100644 index 00000000..ba5be4e5 --- /dev/null +++ b/VRCSDK3Worlds/Assets/VRCSDK/SDK3/Runtime/Midi/PortMidi/Plugins/Windows/portmidi.dll diff --git a/VRCSDK3Worlds/Assets/VRCSDK/SDK3/Runtime/Midi/PortMidi/Plugins/Windows/portmidi.dll.meta b/VRCSDK3Worlds/Assets/VRCSDK/SDK3/Runtime/Midi/PortMidi/Plugins/Windows/portmidi.dll.meta new file mode 100644 index 00000000..36f81d69 --- /dev/null +++ b/VRCSDK3Worlds/Assets/VRCSDK/SDK3/Runtime/Midi/PortMidi/Plugins/Windows/portmidi.dll.meta @@ -0,0 +1,96 @@ +fileFormatVersion: 2 +guid: 372656c38e5c12f48b819e12fa08ac7b +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + '': Any + second: + enabled: 0 + settings: + Exclude Android: 1 + Exclude Editor: 0 + Exclude Linux: 0 + Exclude Linux64: 0 + Exclude LinuxUniversal: 0 + Exclude OSXUniversal: 0 + Exclude WebGL: 1 + Exclude Win: 0 + Exclude Win64: 0 + - first: + Android: Android + second: + enabled: 0 + settings: + CPU: ARMv7 + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 1 + settings: + CPU: AnyCPU + DefaultValueInitialized: true + OS: AnyOS + - first: + Facebook: Win + second: + enabled: 0 + settings: + CPU: AnyCPU + - first: + Facebook: Win64 + second: + enabled: 0 + settings: + CPU: AnyCPU + - first: + Standalone: Linux + second: + enabled: 1 + settings: + CPU: x86 + - first: + Standalone: Linux64 + second: + enabled: 1 + settings: + CPU: x86_64 + - first: + Standalone: LinuxUniversal + second: + enabled: 1 + settings: {} + - first: + Standalone: OSXUniversal + second: + enabled: 1 + settings: + CPU: AnyCPU + - first: + Standalone: Win + second: + enabled: 1 + settings: + CPU: AnyCPU + - first: + Standalone: Win64 + second: + enabled: 1 + settings: + CPU: AnyCPU + userData: + assetBundleName: + assetBundleVariant: diff --git a/VRCSDK3Worlds/Assets/VRCSDK/SDK3/Runtime/Midi/PortMidi/PmDeviceInfo.cs b/VRCSDK3Worlds/Assets/VRCSDK/SDK3/Runtime/Midi/PortMidi/PmDeviceInfo.cs new file mode 100644 index 00000000..e2ecccdd --- /dev/null +++ b/VRCSDK3Worlds/Assets/VRCSDK/SDK3/Runtime/Midi/PortMidi/PmDeviceInfo.cs @@ -0,0 +1,21 @@ +using System; +using System.Runtime.InteropServices; + +namespace PortMidi +{ + [StructLayout(LayoutKind.Sequential)] + internal struct PmDeviceInfo + { + public int StructVersion; + public IntPtr Interface; + public IntPtr Name; + public int Input; + public int Output; + public int Opened; + + public override string ToString() + { + return $"{StructVersion}, {Interface}, {Name}, {Input}, {Output}, {Opened}"; + } + } +}
\ No newline at end of file diff --git a/VRCSDK3Worlds/Assets/VRCSDK/SDK3/Runtime/Midi/PortMidi/PmDeviceInfo.cs.meta b/VRCSDK3Worlds/Assets/VRCSDK/SDK3/Runtime/Midi/PortMidi/PmDeviceInfo.cs.meta new file mode 100644 index 00000000..048fa702 --- /dev/null +++ b/VRCSDK3Worlds/Assets/VRCSDK/SDK3/Runtime/Midi/PortMidi/PmDeviceInfo.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: e20f952b815e0fd4c89e244be795b605 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/VRCSDK3Worlds/Assets/VRCSDK/SDK3/Runtime/Midi/PortMidi/PmEvent.cs b/VRCSDK3Worlds/Assets/VRCSDK/SDK3/Runtime/Midi/PortMidi/PmEvent.cs new file mode 100644 index 00000000..b5d68bce --- /dev/null +++ b/VRCSDK3Worlds/Assets/VRCSDK/SDK3/Runtime/Midi/PortMidi/PmEvent.cs @@ -0,0 +1,11 @@ +using PmMessage = System.Int32; +using PmTimestamp = System.Int32; + +namespace PortMidi +{ + public struct PmEvent + { + public PmMessage message; + public PmTimestamp timestamp; + } +}
\ No newline at end of file diff --git a/VRCSDK3Worlds/Assets/VRCSDK/SDK3/Runtime/Midi/PortMidi/PmEvent.cs.meta b/VRCSDK3Worlds/Assets/VRCSDK/SDK3/Runtime/Midi/PortMidi/PmEvent.cs.meta new file mode 100644 index 00000000..d8ec66ee --- /dev/null +++ b/VRCSDK3Worlds/Assets/VRCSDK/SDK3/Runtime/Midi/PortMidi/PmEvent.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 36b7824d7ad3b3f4fbb5ed6d2a5766ec +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/VRCSDK3Worlds/Assets/VRCSDK/SDK3/Runtime/Midi/PortMidi/PortMidiMarshal.cs b/VRCSDK3Worlds/Assets/VRCSDK/SDK3/Runtime/Midi/PortMidi/PortMidiMarshal.cs new file mode 100644 index 00000000..58f02e11 --- /dev/null +++ b/VRCSDK3Worlds/Assets/VRCSDK/SDK3/Runtime/Midi/PortMidi/PortMidiMarshal.cs @@ -0,0 +1,105 @@ +using System; +using System.Runtime.InteropServices; + +namespace PortMidi +{ + internal class PortMidiMarshal + { + private const int Hdrlength = 50; + private const uint PmHostErrorMsgLen = 256; + const int PmNoDevice = -1; + + [DllImport("portmidi")] + public static extern MidiErrorType Pm_Initialize(); + + [DllImport("portmidi")] + public static extern IntPtr Pm_GetDeviceInfo(Int32 id); + + [DllImport("portmidi")] + public static extern int Pm_CountDevices(); + + [DllImport("portmidi")] + public static extern Int32 Pm_GetDefaultInputDeviceID(); + + [DllImport("portmidi")] + public static extern Int32 Pm_GetDefaultOutputDeviceID(); + + [DllImport("portmidi")] + public static extern MidiErrorType Pm_OpenInput( + out IntPtr stream, + Int32 inputDevice, + IntPtr inputDriverInfo, + int bufferSize, + MidiTimeProcDelegate timeProc, + IntPtr timeInfo); + + [DllImport("portmidi")] + public static extern MidiErrorType Pm_OpenOutput( + out IntPtr stream, + Int32 outputDevice, + IntPtr outputDriverInfo, + int bufferSize, + MidiTimeProcDelegate time_proc, + IntPtr time_info, + int latency); + + [DllImport("portmidi")] + public static extern MidiErrorType Pm_SetFilter(IntPtr stream, MidiFilter filters); + + [DllImport("portmidi")] + public static extern MidiErrorType Pm_SetChannelMask(IntPtr stream, int mask); + + [DllImport("portmidi")] + public static extern MidiErrorType Pm_Poll(IntPtr stream); + + [DllImport("portmidi")] + public static extern int Pm_Read(IntPtr stream, IntPtr buffer, int length); + + [DllImport("portmidi")] + public static extern MidiErrorType Pm_Write(IntPtr stream, IntPtr buffer, int length); + + [DllImport("portmidi")] + public static extern MidiErrorType Pm_WriteSysEx(IntPtr stream, Int32 when, byte[] msg); + + [DllImport("portmidi")] + public static extern MidiErrorType Pm_WriteShort(IntPtr stream, Int32 when, MidiMessage msg); + + [DllImport("portmidi")] + public static extern MidiErrorType Pm_Abort(IntPtr stream); + + [DllImport("portmidi")] + public static extern MidiErrorType Pm_Close(IntPtr stream); + + [DllImport("portmidi")] + public static extern MidiErrorType Pm_Terminate(); + + [DllImport("portmidi")] + public static extern int Pm_HasHostError(IntPtr stream); + + [DllImport("portmidi")] + public static extern string Pm_GetErrorText(MidiErrorType errnum); + + [DllImport("portmidi")] + public static extern void Pm_GetHostErrorText(IntPtr msg, uint len); + + public static int Pm_Channel(int channel) + { + return 1 << channel; + } + + public static int Pm_MessageStatus(int msg) + { + return msg & 0xFF; + } + + public static int Pm_MessageData1(int msg) + { + return (msg >> 8) & 0xFF; + } + + public static int Pm_MessageData2(int msg) + { + return (msg >> 16) & 0xFF; + } + } +}
\ No newline at end of file diff --git a/VRCSDK3Worlds/Assets/VRCSDK/SDK3/Runtime/Midi/PortMidi/PortMidiMarshal.cs.meta b/VRCSDK3Worlds/Assets/VRCSDK/SDK3/Runtime/Midi/PortMidi/PortMidiMarshal.cs.meta new file mode 100644 index 00000000..09c36972 --- /dev/null +++ b/VRCSDK3Worlds/Assets/VRCSDK/SDK3/Runtime/Midi/PortMidi/PortMidiMarshal.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 5d4b9d0d9dfad1c4894df5c2a5530696 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/VRCSDK3Worlds/Assets/VRCSDK/SDK3/Runtime/Midi/VRCPortMidi.cs b/VRCSDK3Worlds/Assets/VRCSDK/SDK3/Runtime/Midi/VRCPortMidi.cs new file mode 100644 index 00000000..e4a6200b --- /dev/null +++ b/VRCSDK3Worlds/Assets/VRCSDK/SDK3/Runtime/Midi/VRCPortMidi.cs @@ -0,0 +1,116 @@ +#if (UNITY_STANDALONE_WIN || UNITY_EDITOR_WIN) && !UNITY_ANDROID +using System; +using System.Collections.Generic; +using System.Linq; +#if VRC_CLIENT +using VRC.Core; +#endif +using PortMidi; +using UnityEngine; +using VRC.SDK3.Midi; + + +namespace VRC.SDKBase.Midi +{ + public class VRCPortMidiInput: IVRCMidiInput + { + + private MidiInput _input; + private byte[] _data; + private MidiDeviceInfo _info; + + public bool OpenDevice(string name = null) + { + try + { + if (!string.IsNullOrWhiteSpace(name)) + { + _info = MidiDeviceManager.AllDevices.FirstOrDefault(device => + device.IsInput && device.Name.ToLower().Contains(name.ToLower())); + } + else + { + _info = MidiDeviceManager.AllDevices.FirstOrDefault(device => + device.ID == MidiDeviceManager.DefaultInputDeviceId); + } + + _input = MidiDeviceManager.OpenInput(_info.ID); + _input.SetFilter(MidiFilter.Active | MidiFilter.SysEx | MidiFilter.Clock | MidiFilter.Play | MidiFilter.Tick | MidiFilter.Undefined | MidiFilter.Reset | MidiFilter.RealTime | MidiFilter.AF | MidiFilter.Program | MidiFilter.PitchBend | MidiFilter.SystemCommon); + _data = new byte[1024]; + return true; + } + catch (Exception e) + { + #if VRC_CLIENT + VRC.Core.Logger.LogError($"Error opening Default Device: {e.Message}"); + #else + Debug.Log($"Error opening Default Device: {e.Message}"); + #endif + return false; + } + } + + public void Close() + { + if (_input != null) + { + _input.Close(); + } + } + + public void Update() + { + if (_input == null) return; + + if (_input.HasData) + { + // Portmidi reports 4 bytes per event but the buffer has 8 bytes so we multiply count by 2 + int count = (_input.Read(_data, 0, _data.Length)) * 2; + for (int i = 0; i < count; i+=8) + { + ConvertAndSend(_data[i], _data[i + 1], _data[i + 2]); + } + } + } + + public IEnumerable<string> GetDeviceNames() + { + return MidiDeviceManager.AllDevices.Select(d => d.Name); + } + + private void ConvertAndSend(byte status, byte data1, byte data2) + { + var command = status & 0xF0; // mask off all but top 4 bits + + if (command >= 0x80 && command <= 0xE0) { + // it's a voice message + // find the channel by masking off all but the low 4 bits + var channel = status & 0x0F; + + if (command == VRCMidiHandler.STATUS_NOTE_ON || command == VRCMidiHandler.STATUS_NOTE_OFF || command == VRCMidiHandler.STATUS_CONTROL_CHANGE) + { + OnMidiVoiceMessage?.Invoke(this, new MidiVoiceEventArgs(command, channel, data1, data2)); + } + else + { +#if VRC_CLIENT + VRC.Core.Logger.Log($"command:{command} channel:{channel} data1:{data1} data2:{data2}"); +#else + Debug.Log($"command:{command} channel:{channel} data1:{data1} data2:{data2}"); +#endif + } + + } + else + { + // it's a system message, ignore for now + OnMidiRawMessage?.Invoke(this, new MidiRawEventArgs(status, data1, data2)); + } + } + + public string Name => _info.Name; + public event MidiVoiceMessageDelegate OnMidiVoiceMessage; + public event MidiRawMessageDelegate OnMidiRawMessage; + } +} +#endif
\ No newline at end of file diff --git a/VRCSDK3Worlds/Assets/VRCSDK/SDK3/Runtime/Midi/VRCPortMidi.cs.meta b/VRCSDK3Worlds/Assets/VRCSDK/SDK3/Runtime/Midi/VRCPortMidi.cs.meta new file mode 100644 index 00000000..156b4665 --- /dev/null +++ b/VRCSDK3Worlds/Assets/VRCSDK/SDK3/Runtime/Midi/VRCPortMidi.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: fb33369bfa554472b08fc6828450a2c4 +timeCreated: 1607454401
\ No newline at end of file |