예제 #1
0
 static void DieOnError(int code)
 {
     if (code != 0)
     {
         throw new Win32Exception(code, $"{WinMMNatives.GetMidiOutErrorText(code)} ({code})");
     }
 }
예제 #2
0
        public Task CloseAsync()
        {
            return(Task.Run(() =>
            {
                lock (lockObject)
                {
                    Connection = MidiPortConnectionState.Pending;

                    DieOnError(WinMMNatives.midiInReset(handle));
                    DieOnError(WinMMNatives.midiInStop(handle));
                    DieOnError(WinMMNatives.midiInClose(handle));

                    // wait for the device driver to hand back the long buffers through HandleMidiInProc

                    for (int i = 0; i < 1000; i++)
                    {
                        lock (lockObject)
                        {
                            if (lmBuffers.Count < 1)
                            {
                                break;
                            }
                        }

                        Thread.Sleep(10);
                    }

                    Connection = MidiPortConnectionState.Closed;
                }
            }));
        }
예제 #3
0
 public void Send(byte [] mevent, int offset, int length, long timestamp)
 {
     foreach (var evt in MidiEvent.Convert(mevent, offset, length))
     {
         if (evt.StatusByte < 0xF0)
         {
             WinMMNatives.midiOutShortMsg(handle, (uint)(evt.StatusByte + (evt.Msb << 8) + (evt.Lsb << 16)));
         }
         else
         {
             MidiHdr sysex = default(MidiHdr);
             unsafe
             {
                 fixed(void *ptr = evt.Data)
                 {
                     sysex.Data         = (IntPtr)ptr;
                     sysex.BufferLength = evt.Data.Length;
                     sysex.Flags        = 0;
                     WinMMNatives.midiOutPrepareHeader(handle, ref sysex, (uint)Marshal.SizeOf(typeof(MidiHdr)));
                     WinMMNatives.midiOutLongMsg(handle, ref sysex, evt.Data.Length);
                 }
             }
         }
     }
 }
예제 #4
0
 public Task CloseAsync()
 {
     return(Task.Run(() =>
     {
         Connection = MidiPortConnectionState.Pending;
         WinMMNatives.midiOutClose(handle);
         Connection = MidiPortConnectionState.Closed;
     }));
 }
예제 #5
0
            public void UnPrepareHeader()
            {
                if (prepared)
                {
                    DieOnError(WinMMNatives.midiInUnprepareHeader(inputHandle, Ptr, midiHdrSize));
                }

                prepared = false;
            }
예제 #6
0
            public void PrepareHeader()
            {
                if (!prepared)
                {
                    DieOnError(WinMMNatives.midiInPrepareHeader(inputHandle, Ptr, midiHdrSize));
                }

                prepared = true;
            }
예제 #7
0
        public void Send(byte [] mevent, int offset, int length, long timestamp)
        {
            foreach (var evt in MidiEvent.Convert(mevent, offset, length))
            {
                if (evt.StatusByte < 0xF0)
                {
                    DieOnError(WinMMNatives.midiOutShortMsg(handle, (uint)(evt.StatusByte + (evt.Msb << 8) + (evt.Lsb << 16))));
                }
                else
                {
                    var    header   = new MidiHdr();
                    bool   prepared = false;
                    IntPtr ptr      = IntPtr.Zero;
                    var    hdrSize  = Marshal.SizeOf(typeof(MidiHdr));

                    try
                    {
                        // allocate unmanaged memory and hand ownership over to the device driver

                        header.Data         = Marshal.AllocHGlobal(evt.Data.Length);
                        header.BufferLength = evt.Data.Length;
                        Marshal.Copy(evt.Data, 0, header.Data, header.BufferLength);

                        ptr = Marshal.AllocHGlobal(hdrSize);
                        Marshal.StructureToPtr(header, ptr, false);

                        DieOnError(WinMMNatives.midiOutPrepareHeader(handle, ptr, hdrSize));
                        prepared = true;

                        DieOnError(WinMMNatives.midiOutLongMsg(handle, ptr, hdrSize));
                    }

                    finally
                    {
                        // reclaim ownership and free

                        if (prepared)
                        {
                            DieOnError(WinMMNatives.midiOutUnprepareHeader(handle, ptr, hdrSize));
                        }

                        if (header.Data != IntPtr.Zero)
                        {
                            Marshal.FreeHGlobal(header.Data);
                        }

                        if (ptr != IntPtr.Zero)
                        {
                            Marshal.FreeHGlobal(ptr);
                        }
                    }
                }
            }
        }
        private List <IMidiPortDetails> GetInputDevices()
        {
            List <IMidiPortDetails> deviceList = new List <IMidiPortDetails>();
            int devs = WinMMNatives.midiInGetNumDevs();

            for (uint i = 0; i < devs; i++)
            {
                MidiInCaps caps;
                WinMMNatives.midiInGetDevCaps((UIntPtr)i, out caps, (uint)Marshal.SizeOf <MidiInCaps>());
                deviceList.Add(new WinMMPortDetails(i, caps.Name, caps.DriverVersion));
            }
            ;
            return(deviceList);
        }
        private List <IMidiPortDetails> GetOutputDevices()
        {
            List <IMidiPortDetails> deviceList = new List <IMidiPortDetails>();
            int devs = WinMMNatives.midiOutGetNumDevs();

            for (uint i = 0; i < devs; i++)
            {
                MidiOutCaps caps;
                var         err = WinMMNatives.midiOutGetDevCaps((UIntPtr)i, out caps, (uint)Marshal.SizeOf <MidiOutCaps>());
                if (err != 0)
                {
                    throw new Win32Exception(err);
                }
                deviceList.Add(new WinMMPortDetails(i, caps.Name, caps.DriverVersion));
            }
            return(deviceList);
        }
예제 #10
0
        public WinMMMidiInput(IMidiPortDetails details)
        {
            Details = details;

            // prevent garbage collection of the delegate
            midiInProc = HandleMidiInProc;

            DieOnError(WinMMNatives.midiInOpen(out handle, uint.Parse(Details.Id), midiInProc,
                                               IntPtr.Zero, MidiInOpenFlags.Function | MidiInOpenFlags.MidiIoStatus));

            DieOnError(WinMMNatives.midiInStart(handle));

            while (lmBuffers.Count < LONG_BUFFER_COUNT)
            {
                var buffer = new LongMessageBuffer(handle);

                buffer.PrepareHeader();
                buffer.AddBuffer();

                lmBuffers.Add(buffer.Ptr, buffer);
            }

            Connection = MidiPortConnectionState.Open;
        }
예제 #11
0
 public WinMMMidiOutput(IMidiPortDetails details)
 {
     Details = details;
     WinMMNatives.midiOutOpen(out handle, uint.Parse(Details.Id), null, IntPtr.Zero, MidiOutOpenFlags.Null);
     Connection = MidiPortConnectionState.Open;
 }
예제 #12
0
 public void AddBuffer() =>
 DieOnError(WinMMNatives.midiInAddBuffer(inputHandle, Ptr, midiHdrSize));
예제 #13
0
 public WinMMMidiInput(IMidiPortDetails details)
 {
     Details = details;
     WinMMNatives.midiInOpen(out handle, uint.Parse(Details.Id), HandleMidiInProc, IntPtr.Zero, MidiInOpenFlags.Function);
     Connection = MidiPortConnectionState.Open;
 }