Initial commit

This commit is contained in:
alexpete
2021-03-05 11:26:34 -08:00
commit a10351f38d
27091 changed files with 5521199 additions and 0 deletions
@@ -0,0 +1,72 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
// Copyright (c) 2009, Tom Lokovic
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
namespace Midi
{
/// <summary>
/// Common base class for input and output devices.
/// </summary>
/// This base class exists mainly so that input and output devices can both go into the same
/// kinds of MidiMessages.
public class DeviceBase
{
/// <summary>
/// Protected constructor.
/// </summary>
/// <param name="name">The name of this device.</param>
protected DeviceBase(string name)
{
Name = name;
}
/// <summary>
/// The name of this device.
/// </summary>
public string Name { get; private set; }
}
/// <summary>
/// Exception thrown when an operation on a MIDI device cannot be satisfied.
/// </summary>
public class DeviceException : System.ApplicationException
{
/// <summary>
/// Constructs exception with a specific error message.
/// </summary>
/// <param name="message"></param>
public DeviceException(string message) { }
}
}
@@ -0,0 +1,385 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
// Copyright (c) 2009, Tom Lokovic
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
using System;
using System.Collections.ObjectModel;
using System.Text;
namespace Midi
{
/// <summary>
/// A MIDI input device.
/// </summary>
public class InputDevice : DeviceBase
{
#region Delegates
/// <summary>
/// Delegate called when an input device receives a midi message.
/// </summary>
public delegate void MidiHandler(MidiMessage msg);
#endregion
#region Events
/// <summary>
/// Event called when an input device receives a midi message.
/// </summary>
public event MidiHandler MidiTrigger;
/// <summary>
/// Removes all event handlers from the input events on this device.
/// </summary>
public void RemoveAllEventHandlers()
{
MidiTrigger = null;
}
#endregion
#region Public Methods and Properties
/// <summary>
/// List of input devices installed on this system.
/// </summary>
public static ReadOnlyCollection<InputDevice> InstalledDevices
{
get
{
lock (staticLock)
{
if (installedDevices == null)
{
installedDevices = MakeDeviceList();
}
return new ReadOnlyCollection<InputDevice>(installedDevices);
}
}
}
/// <summary>
/// True if this device has been successfully opened.
/// </summary>
public bool IsOpen
{
get
{
if (isInsideInputHandler)
{
return true;
}
lock (this)
{
return isOpen;
}
}
}
/// <summary>
/// Opens this input device.
/// </summary>
/// <exception cref="InvalidOperationException">The device is already open.</exception>
/// <exception cref="DeviceException">The device cannot be opened.</exception>
/// <remarks>Note that Open() establishes a connection to the device, but no messages will
/// be received until <see cref="StartReceiving"/> is called.</remarks>
public void Open()
{
if (isInsideInputHandler)
{
throw new InvalidOperationException("Device is open.");
}
lock (this)
{
CheckNotOpen();
CheckReturnCode(Win32API.midiInOpen(out handle, deviceId,
inputCallbackDelegate, (UIntPtr)0));
isOpen = true;
}
}
/// <summary>
/// Closes this input device.
/// </summary>
/// <exception cref="InvalidOperationException">The device is not open or is still
/// receiving.</exception>
/// <exception cref="DeviceException">The device cannot be closed.</exception>
public void Close()
{
if (isInsideInputHandler)
{
throw new InvalidOperationException("Device is receiving.");
}
lock (this)
{
CheckOpen();
CheckReturnCode(Win32API.midiInClose(handle));
isOpen = false;
}
}
/// <summary>
/// True if this device is receiving messages.
/// </summary>
public bool IsReceiving
{
get
{
if (isInsideInputHandler)
{
return true;
}
lock (this)
{
return isReceiving;
}
}
}
/// <summary>
/// Starts this input device receiving messages.
/// </summary>
public void StartReceiving()//Clock clock)
{
if (isInsideInputHandler)
{
throw new InvalidOperationException("Device is receiving.");
}
lock (this)
{
CheckOpen();
CheckNotReceiving();
CheckReturnCode(Win32API.midiInStart(handle));
isReceiving = true;
//this.clock = clock;
}
}
/// <summary>
/// Stops this input device from receiving messages.
/// </summary>
/// <remarks>
/// <para>This method waits for all in-progress input event handlers to finish, and then
/// joins (shuts down) the background thread that was created in
/// <see cref="StartReceiving"/>. Thus, when this function returns you can be sure that no
/// more event handlers will be invoked.</para>
/// <para>It is illegal to call this method from an input event handler (ie, from the
/// background thread), and doing so throws an exception. If an event handler really needs
/// to call this method, consider using BeginInvoke to schedule it on another thread.</para>
/// </remarks>
/// <exception cref="InvalidOperationException">The device is not open; is not receiving;
/// or called from within an event handler (ie, from the background thread).</exception>
/// <exception cref="DeviceException">The device cannot start receiving.</exception>
public void StopReceiving()
{
if (isInsideInputHandler)
{
throw new InvalidOperationException(
"Can't call StopReceiving() from inside an input handler.");
}
lock (this)
{
CheckReceiving();
CheckReturnCode(Win32API.midiInStop(handle));
//clock = null;
isReceiving = false;
}
}
#endregion
#region Private Methods
/// <summary>
/// Makes sure rc is MidiWin32Wrapper.MMSYSERR_NOERROR. If not, throws an exception with an
/// appropriate error message.
/// </summary>
/// <param name="rc"></param>
private static void CheckReturnCode(Win32API.MMRESULT rc)
{
if (rc != Win32API.MMRESULT.MMSYSERR_NOERROR)
{
StringBuilder errorMsg = new StringBuilder(128);
rc = Win32API.midiInGetErrorText(rc, errorMsg);
if (rc != Win32API.MMRESULT.MMSYSERR_NOERROR)
{
throw new DeviceException("no error details");
}
throw new DeviceException(errorMsg.ToString());
}
}
/// <summary>
/// Throws a MidiDeviceException if this device is not open.
/// </summary>
private void CheckOpen()
{
if (!isOpen)
{
throw new InvalidOperationException("Device is not open.");
}
}
/// <summary>
/// Throws a MidiDeviceException if this device is open.
/// </summary>
private void CheckNotOpen()
{
if (isOpen)
{
throw new InvalidOperationException("Device is open.");
}
}
/// <summary>
/// Throws a MidiDeviceException if this device is not receiving.
/// </summary>
private void CheckReceiving()
{
if (!isReceiving)
{
throw new DeviceException("device not receiving");
}
}
/// <summary>
/// Throws a MidiDeviceException if this device is receiving.
/// </summary>
private void CheckNotReceiving()
{
if (isReceiving)
{
throw new DeviceException("device receiving");
}
}
/// <summary>
/// Private Constructor, only called by the getter for the InstalledDevices property.
/// </summary>
/// <param name="deviceId">Position of this device in the list of all devices.</param>
/// <param name="caps">Win32 Struct with device metadata</param>
private InputDevice(UIntPtr deviceId, Win32API.MIDIINCAPS caps)
: base(caps.szPname)
{
this.deviceId = deviceId;
this.caps = caps;
this.inputCallbackDelegate = new Win32API.MidiInProc(this.InputCallback);
this.isOpen = false;
//this.clock = null;
}
/// <summary>
/// Private method for constructing the array of MidiInputDevices by calling the Win32 api.
/// </summary>
/// <returns></returns>
private static InputDevice[] MakeDeviceList()
{
#if __MonoCS__
return new InputDevice[0];
#else
uint inDevs = Win32API.midiInGetNumDevs();
InputDevice[] result = new InputDevice[inDevs];
for (uint deviceId = 0; deviceId < inDevs; deviceId++)
{
Win32API.MIDIINCAPS caps = new Win32API.MIDIINCAPS();
Win32API.midiInGetDevCaps((UIntPtr)deviceId, out caps);
result[deviceId] = new InputDevice((UIntPtr)deviceId, caps);
}
return result;
#endif
}
/// <summary>
/// The input callback for midiOutOpen.
/// </summary>
private void InputCallback(Win32API.HMIDIIN hMidiIn, Win32API.MidiInMessage wMsg,
UIntPtr dwInstance, UIntPtr dwParam1, UIntPtr dwParam2)
{
isInsideInputHandler = true;
try
{
if (wMsg == Win32API.MidiInMessage.MIM_DATA)
{
int channel;
int mode;
int code;
int velocity;
UInt32 win32Timestamp;
if (MidiTrigger != null)
{
ShortMsg.DecodeMsg(dwParam1, dwParam2, out channel, out mode, out code, out velocity, out win32Timestamp);
MidiTrigger(new MidiMessage(this, channel, mode, code, velocity));
}
}
}
finally
{
isInsideInputHandler = false;
}
}
#endregion
#region Private Fields
// Access to the global state is guarded by lock(staticLock).
private static Object staticLock = new Object();
private static InputDevice[] installedDevices = null;
// These fields initialized in the constructor never change after construction,
// so they don't need to be guarded by a lock. We keep a reference to the
// callback delegate because we pass it to unmanaged code (midiInOpen) and unmanaged code
// cannot prevent the garbage collector from collecting the delegate.
private UIntPtr deviceId;
private Win32API.MIDIINCAPS caps;
private Win32API.MidiInProc inputCallbackDelegate;
// Access to the Open/Close state is guarded by lock(this).
private bool isOpen;
private bool isReceiving;
//private Clock clock;
private Win32API.HMIDIIN handle;
/// <summary>
/// Thread-local, set to true when called by an input handler, false in all other threads.
/// </summary>
[ThreadStatic]
static bool isInsideInputHandler = false;
#endregion
}
}
@@ -0,0 +1,101 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
// Copyright (c) 2009, Tom Lokovic
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
using System;
namespace Midi
{
/// <summary>
/// Base class for messages relevant to a specific device.
/// </summary>
public abstract class DeviceMessage
{
/// <summary>
/// Protected constructor.
/// </summary>
protected DeviceMessage(DeviceBase device)//, float time) : base(time)
{
if (device == null)
{
throw new ArgumentNullException("device");
}
Device = device;
}
/// <summary>
/// The device from which this message originated, or for which it is destined.
/// </summary>
public DeviceBase Device { get; private set; }
}
/// <summary>
/// Note On message.
/// </summary>
public class MidiMessage : DeviceMessage
{
/// <summary>
/// Constructs a Midi message.
/// </summary>
public MidiMessage(DeviceBase device, int channel, int mode, int code, int velocity)
:base(device)
{
Channel = channel;
Mode = mode;
Code = code;
Velocity = velocity;
}
/// <summary>
/// Channel.
/// </summary>
public int Channel { get; private set; }
/// <summary>
/// Mode.
/// </summary>
public int Mode { get; private set; }
/// <summary>
/// Code.
/// </summary>
public int Code { get; private set; }
/// <summary>
/// Velocity.
/// </summary>
public int Velocity { get; private set; }
}
}
@@ -0,0 +1,69 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
// Copyright (c) 2009, Tom Lokovic
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
using System;
using System.Collections.Generic;
namespace Midi
{
/// <summary>
/// Utility functions for encoding and decoding short messages.
/// </summary>
static class ShortMsg
{
/// <summary>
/// Decodes a Note On short message.
/// </summary>
public static void DecodeMsg(UIntPtr dwParam1, UIntPtr dwParam2,
out int channel, out int mode, out int code, out int velocity, out UInt32 timestamp)
{
channel = (int)dwParam1 & 0x0f;
mode = ((int)dwParam1 & 0xf0) >> 4;
code = ((int)dwParam1 & 0xff00) >> 8;
velocity = ((int)dwParam1 & 0xff0000) >> 16;
timestamp = (UInt32)dwParam2;
}
/// <summary>
/// Encodes a Note On short message.
/// </summary>
public static UInt32 EncodeMsg(int channel, int code, int velocity)
{
return (UInt32)(0x90 | (channel) | (code << 8) | (velocity << 16));
}
}
}
@@ -0,0 +1,428 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
// Copyright (c) 2009, Tom Lokovic
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
using System;
using System.Runtime.InteropServices;
using System.Text;
namespace Midi
{
/// <summary>
/// C# wrappers for the Win32 MIDI API.
/// </summary>
/// Because .NET does not provide MIDI support itself, in C# we must use P/Invoke to wrap the
/// Win32 API. That API consists of the MMSystem.h C header and the winmm.dll library. The API
/// is described in detail here: http://msdn.microsoft.com/en-us/library/ms712733(VS.85).aspx.
/// The P/Invoke interop mechanism is described here:
/// http://msdn.microsoft.com/en-us/library/aa288468(VS.71).aspx.
///
/// This file covers the subset of the MIDI protocol needed to manage input and output devices
/// and send and receive Note On/Off, Control Change, Pitch Bend and Program Change messages.
/// Other portions of the MIDI protocol (such as sysex events) are supported in the Win32 API
/// but are not wrapped here.
///
/// Some of the C functions are not typesafe when wrapped, so those wrappers are made private
/// and typesafe variants are provided.
static class Win32API
{
#region Constants
// The following constants come from MMSystem.h.
/// <summary>
/// Max length of a manufacturer name in the Win32 API.
/// </summary>
public const UInt32 MAXPNAMELEN = 32;
/// <summary>
/// Status type returned from most functions in the Win32 API.
/// </summary>
public enum MMRESULT : uint
{
// General return codes.
MMSYSERR_BASE = 0,
MMSYSERR_NOERROR = MMSYSERR_BASE + 0,
MMSYSERR_ERROR = MMSYSERR_BASE + 1,
MMSYSERR_BADDEVICEID = MMSYSERR_BASE + 2,
MMSYSERR_NOTENABLED = MMSYSERR_BASE + 3,
MMSYSERR_ALLOCATED = MMSYSERR_BASE + 4,
MMSYSERR_INVALHANDLE = MMSYSERR_BASE + 5,
MMSYSERR_NODRIVER = MMSYSERR_BASE + 6,
MMSYSERR_NOMEM = MMSYSERR_BASE + 7,
MMSYSERR_NOTSUPPORTED = MMSYSERR_BASE + 8,
MMSYSERR_BADERRNUM = MMSYSERR_BASE + 9,
MMSYSERR_INVALFLAG = MMSYSERR_BASE + 10,
MMSYSERR_INVALPARAM = MMSYSERR_BASE + 11,
MMSYSERR_HANDLEBUSY = MMSYSERR_BASE + 12,
MMSYSERR_INVALIDALIAS = MMSYSERR_BASE + 13,
MMSYSERR_BADDB = MMSYSERR_BASE + 14,
MMSYSERR_KEYNOTFOUND = MMSYSERR_BASE + 15,
MMSYSERR_READERROR = MMSYSERR_BASE + 16,
MMSYSERR_WRITEERROR = MMSYSERR_BASE + 17,
MMSYSERR_DELETEERROR = MMSYSERR_BASE + 18,
MMSYSERR_VALNOTFOUND = MMSYSERR_BASE + 19,
MMSYSERR_NODRIVERCB = MMSYSERR_BASE + 20,
MMSYSERR_MOREDATA = MMSYSERR_BASE + 21,
MMSYSERR_LASTERROR = MMSYSERR_BASE + 21,
// MIDI-specific return codes.
MIDIERR_BASE = 64,
MIDIERR_UNPREPARED = MIDIERR_BASE + 0,
MIDIERR_STILLPLAYING = MIDIERR_BASE + 1,
MIDIERR_NOMAP = MIDIERR_BASE + 2,
MIDIERR_NOTREADY = MIDIERR_BASE + 3,
MIDIERR_NODEVICE = MIDIERR_BASE + 4,
MIDIERR_INVALIDSETUP = MIDIERR_BASE + 5,
MIDIERR_BADOPENMODE = MIDIERR_BASE + 6,
MIDIERR_DONT_CONTINUE = MIDIERR_BASE + 7,
MIDIERR_LASTERROR = MIDIERR_BASE + 7
}
/// <summary>
/// Flags passed to midiInOpen() and midiOutOpen().
/// </summary>
public enum MidiOpenFlags : uint
{
CALLBACK_TYPEMASK = 0x70000,
CALLBACK_NULL = 0x00000,
CALLBACK_WINDOW = 0x10000,
CALLBACK_TASK = 0x20000,
CALLBACK_FUNCTION = 0x30000,
CALLBACK_THREAD = CALLBACK_TASK,
CALLBACK_EVENT = 0x50000,
MIDI_IO_STATUS = 0x00020
}
/// <summary>
/// Values for wTechnology field of MIDIOUTCAPS structure.
/// </summary>
public enum MidiDeviceType : ushort
{
MOD_MIDIPORT = 1,
MOD_SYNTH = 2,
MOD_SQSYNTH = 3,
MOD_FMSYNTH = 4,
MOD_MAPPER = 5,
MOD_WAVETABLE = 6,
MOD_SWSYNTH = 7
}
/// <summary>
/// Flags for dwSupport field of MIDIOUTCAPS structure.
/// </summary>
public enum MidiExtraFeatures : uint
{
MIDICAPS_VOLUME = 0x0001,
MIDICAPS_LRVOLUME = 0x0002,
MIDICAPS_CACHE = 0x0004,
MIDICAPS_STREAM = 0x0008
}
/// <summary>
/// "Midi Out Messages", passed to wMsg param of MidiOutProc.
/// </summary>
public enum MidiOutMessage : uint
{
MOM_OPEN = 0x3C7,
MOM_CLOSE = 0x3C8,
MOM_DONE = 0x3C9
}
/// <summary>
/// "Midi In Messages", passed to wMsg param of MidiInProc.
/// </summary>
public enum MidiInMessage : uint
{
MIM_OPEN = 0x3C1,
MIM_CLOSE = 0x3C2,
MIM_DATA = 0x3C3,
MIM_LONGDATA = 0x3C4,
MIM_ERROR = 0x3C5,
MIM_LONGERROR = 0x3C6,
MIM_MOREDATA = 0x3CC
}
#endregion
#region Handles
/// <summary>
/// Win32 handle for a MIDI output device.
/// </summary>
[StructLayout(LayoutKind.Sequential)]
public struct HMIDIOUT
{
public Int32 handle;
}
/// <summary>
/// Win32 handle for a MIDI input device.
/// </summary>
[StructLayout(LayoutKind.Sequential)]
public struct HMIDIIN
{
public Int32 handle;
}
#endregion
#region Structs
/// <summary>
/// Struct representing the capabilities of an output device.
/// </summary>
/// Win32 docs: http://msdn.microsoft.com/en-us/library/ms711619(VS.85).aspx
[StructLayout(LayoutKind.Sequential)]
public struct MIDIOUTCAPS
{
public UInt16 wMid;
public UInt16 wPid;
public UInt32 vDriverVersion;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = (int)MAXPNAMELEN)]
public string szPname;
public MidiDeviceType wTechnology;
public UInt16 wVoices;
public UInt16 wNotes;
public UInt16 wChannelMask;
public MidiExtraFeatures dwSupport;
}
/// <summary>
/// Struct representing the capabilities of an input device.
/// </summary>
/// Win32 docs: http://msdn.microsoft.com/en-us/library/ms711596(VS.85).aspx
[StructLayout(LayoutKind.Sequential)]
public struct MIDIINCAPS
{
public UInt16 wMid;
public UInt16 wPid;
public UInt32 vDriverVersion;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = (int)MAXPNAMELEN)]
public string szPname;
public UInt32 dwSupport;
}
#endregion
#region Functions for MIDI Output
/// <summary>
/// Returns the number of MIDI output devices on this system.
/// </summary>
/// Win32 docs: http://msdn.microsoft.com/en-us/library/ms711627(VS.85).aspx
[DllImport("winmm.dll", SetLastError = true)]
public static extern UInt32 midiOutGetNumDevs();
/// <summary>
/// Fills in the capabilities struct for a specific output device.
/// </summary>
/// NOTE: This is adapted from the original Win32 function in order to make it typesafe.
///
/// Win32 docs: http://msdn.microsoft.com/en-us/library/ms711621(VS.85).aspx
public static MMRESULT midiOutGetDevCaps(UIntPtr uDeviceID, out MIDIOUTCAPS caps)
{
return midiOutGetDevCaps(uDeviceID, out caps,
(UInt32)Marshal.SizeOf(typeof(MIDIOUTCAPS)));
}
/// <summary>
/// Callback invoked when a MIDI output device is opened, closed, or finished with a buffer.
/// </summary>
/// Win32 docs: http://msdn.microsoft.com/en-us/library/ms711637(VS.85).aspx
public delegate void MidiOutProc(HMIDIOUT hmo, MidiOutMessage wMsg, UIntPtr dwInstance,
UIntPtr dwParam1, UIntPtr dwParam2);
/// <summary>
/// Opens a MIDI output device.
/// </summary>
/// NOTE: This is adapted from the original Win32 function in order to make it typesafe.
///
/// Win32 docs: http://msdn.microsoft.com/en-us/library/ms711632(VS.85).aspx
public static MMRESULT midiOutOpen(out HMIDIOUT lphmo, UIntPtr uDeviceID,
MidiOutProc dwCallback, UIntPtr dwCallbackInstance)
{
return midiOutOpen(out lphmo, uDeviceID, dwCallback, dwCallbackInstance,
dwCallback == null ? MidiOpenFlags.CALLBACK_NULL : MidiOpenFlags.CALLBACK_FUNCTION);
}
/// <summary>
/// Turns off all notes and sustains on a MIDI output device.
/// </summary>
/// Win32 docs: http://msdn.microsoft.com/en-us/library/dd798479(VS.85).aspx
[DllImport("winmm.dll", SetLastError = true)]
public static extern MMRESULT midiOutReset(HMIDIOUT hmo);
/// <summary>
/// Closes a MIDI output device.
/// </summary>
/// Win32 docs: http://msdn.microsoft.com/en-us/library/ms711620(VS.85).aspx
[DllImport("winmm.dll", SetLastError = true)]
public static extern MMRESULT midiOutClose(HMIDIOUT hmo);
/// <summary>
/// Sends a short MIDI message (anything but sysex or stream).
/// </summary>
/// Win32 docs: http://msdn.microsoft.com/en-us/library/ms711640(VS.85).aspx
[DllImport("winmm.dll", SetLastError = true)]
public static extern MMRESULT midiOutShortMsg(HMIDIOUT hmo, UInt32 dwMsg);
/// <summary>
/// Gets the error text for a return code related to an output device.
/// </summary>
/// NOTE: This is adapted from the original Win32 function in order to make it typesafe.
///
/// Win32 docs: http://msdn.microsoft.com/en-us/library/ms711622(VS.85).aspx
public static MMRESULT midiOutGetErrorText(MMRESULT mmrError, StringBuilder lpText)
{
return midiOutGetErrorText(mmrError, lpText, (UInt32)lpText.Capacity);
}
#endregion
#region Functions for MIDI Input
/// <summary>
/// Returns the number of MIDI input devices on this system.
/// </summary>
/// Win32 docs: http://msdn.microsoft.com/en-us/library/ms711608(VS.85).aspx
[DllImport("winmm.dll", SetLastError = true)]
public static extern UInt32 midiInGetNumDevs();
/// <summary>
/// Fills in the capabilities struct for a specific input device.
/// </summary>
/// NOTE: This is adapted from the original Win32 function in order to make it typesafe.
///
/// Win32 docs: http://msdn.microsoft.com/en-us/library/ms711604(VS.85).aspx
public static MMRESULT midiInGetDevCaps(UIntPtr uDeviceID, out MIDIINCAPS caps)
{
return midiInGetDevCaps(uDeviceID, out caps,
(UInt32)Marshal.SizeOf(typeof(MIDIINCAPS)));
}
/// <summary>
/// Callback invoked when a MIDI event is received from an input device.
/// </summary>
/// Win32 docs: http://msdn.microsoft.com/en-us/library/ms711612(VS.85).aspx
public delegate void MidiInProc(HMIDIIN hMidiIn, MidiInMessage wMsg, UIntPtr dwInstance,
UIntPtr dwParam1, UIntPtr dwParam2);
/// <summary>
/// Opens a MIDI input device.
/// </summary>
/// NOTE: This is adapted from the original Win32 function in order to make it typesafe.
///
/// Win32 docs: http://msdn.microsoft.com/en-us/library/ms711610(VS.85).aspx
public static MMRESULT midiInOpen(out HMIDIIN lphMidiIn, UIntPtr uDeviceID,
MidiInProc dwCallback, UIntPtr dwCallbackInstance)
{
return midiInOpen(out lphMidiIn, uDeviceID, dwCallback, dwCallbackInstance,
dwCallback == null ? MidiOpenFlags.CALLBACK_NULL : MidiOpenFlags.CALLBACK_FUNCTION);
}
/// <summary>
/// Starts input on a MIDI input device.
/// </summary>
/// Win32 docs: http://msdn.microsoft.com/en-us/library/ms711614(VS.85).aspx
[DllImport("winmm.dll", SetLastError = true)]
public static extern MMRESULT midiInStart(HMIDIIN hMidiIn);
/// <summary>
/// Stops input on a MIDI input device.
/// </summary>
/// Win32 docs: http://msdn.microsoft.com/en-us/library/ms711615(VS.85).aspx
[DllImport("winmm.dll", SetLastError = true)]
public static extern MMRESULT midiInStop(HMIDIIN hMidiIn);
/// <summary>
/// Resets input on a MIDI input device.
/// </summary>
/// Win32 docs: http://msdn.microsoft.com/en-us/library/ms711613(VS.85).aspx
[DllImport("winmm.dll", SetLastError = true)]
public static extern MMRESULT midiInReset(HMIDIIN hMidiIn);
/// <summary>
/// Closes a MIDI input device.
/// </summary>
/// Win32 docs: http://msdn.microsoft.com/en-us/library/ms711602(VS.85).aspx
[DllImport("winmm.dll", SetLastError = true)]
public static extern MMRESULT midiInClose(HMIDIIN hMidiIn);
/// <summary>
/// Gets the error text for a return code related to an input device.
/// </summary>
/// NOTE: This is adapted from the original Win32 function in order to make it typesafe.
///
/// Win32 docs: http://msdn.microsoft.com/en-us/library/ms711605(VS.85).aspx
public static MMRESULT midiInGetErrorText(MMRESULT mmrError, StringBuilder lpText)
{
return midiInGetErrorText(mmrError, lpText, (UInt32)lpText.Capacity);
}
#endregion
#region Non-Typesafe Bindings
// The bindings in this section are not typesafe, so we make them private and privide
// typesafe variants above.
[DllImport("winmm.dll", SetLastError = true)]
private static extern MMRESULT midiOutGetDevCaps(UIntPtr uDeviceID, out MIDIOUTCAPS caps,
UInt32 cbMidiOutCaps);
[DllImport("winmm.dll", SetLastError = true)]
private static extern MMRESULT midiOutOpen(out HMIDIOUT lphmo, UIntPtr uDeviceID,
MidiOutProc dwCallback, UIntPtr dwCallbackInstance, MidiOpenFlags dwFlags);
[DllImport("winmm.dll", SetLastError = true)]
private static extern MMRESULT midiOutGetErrorText(MMRESULT mmrError, StringBuilder lpText,
UInt32 cchText);
[DllImport("winmm.dll", SetLastError = true)]
private static extern MMRESULT midiInGetDevCaps(UIntPtr uDeviceID, out MIDIINCAPS caps,
UInt32 cbMidiInCaps);
[DllImport("winmm.dll", SetLastError = true)]
private static extern MMRESULT midiInOpen(out HMIDIIN lphMidiIn, UIntPtr uDeviceID,
MidiInProc dwCallback, UIntPtr dwCallbackInstance, MidiOpenFlags dwFlags);
[DllImport("winmm.dll", SetLastError = true)]
private static extern MMRESULT midiInGetErrorText(MMRESULT mmrError, StringBuilder lpText,
UInt32 cchText);
#endregion
}
}