Use windows runtime midi api

WinRTMidi DLL

This project is no longer supported. Please report issues with the Windows::Device::Midi API using the Windows 10 Feedback Hub App

This GitHub WinRTMidi project wraps the Windows Runtime Windows::Devices::Midi API
in a Win32 DLL that can be dynamically loaded by a standard Win32 application. If the application is running on a device with Windows 10, the DLL will
load and you will be able to use the Windows::Devices::Midi API via a C interface exported by the DLL.
If your application is running on devices with Windows 7 or Windows 8/8.1, the winrtmidi DLL will not load. Your application will need to test if it is running on Windows 10 before
attempting to load the DLL (See Testing for Windows 10 below). The Windows::Devices::Midi API is ony available on devices running Windows 10.

This DLL is useful for the scenario where you have an existing Win32 MIDI application and want to use the new Windows::Devices::Midi API. If you are not able to update your application to a
Windows 10 UWP app, you can use the winrtmidi DLL to access the Windows::Devices::Midi API when your application is running on a device with Windows 10. You can use the winrtmidi DLL with
applications built with Visual Studio 2010-2015. There is no need to rebuild your application with Visual Studio 2015 to access the Windows::Devices::Midi API using the winrtmidi DLL.

The recommended steps to use this DLL are as follows:

  1. Ship the winrtmidi DLL with your Win32 application but do not link to the DLL.
  2. When your Win32 application runs, check if your application is running on Windows 10 (See Testing for Windows 10 below).
  3. If your application is running on Windows 10, dynamically load the winrtmidi DLL using LoadLibrary().
    • If your application is not running on Windows 10, continue to use the WinMM MIDI API.
  4. Get pointers to the various winrtmidi functions using GetProcAddress().
  5. Initialize the winrtmidi API using the winrt_initialize_midi() function.
  6. Obtain a MIDI port using the winrt_open_midi_in_port() or winrt_open_midi_out_port() functions.
  7. For more information see example code below.

The WinRTMid DLL enables the following MIDI functionality from the Windows::Devices::Midi API:

  • Enumerate MIDI ports.
  • Notification when MIDI ports are added or removed.
  • Create a MIDI in or out port.
  • Send MIDI messages on a MIDI out port.
  • Receive MIDI messages from a MIDI in port.
  • Destroy a MIDI port.
  • Access Bluetooth MIDI ports
  • Multi-client MIDI port support

Requirements to build the winrtmidi DLL

Visual Studio 2015 (Update 3 recommended) with Universal Windows App Development Tools and Windows 10 Tools and SDKs installed

Adding the winrtmidi DLL to your Win32 Project

Your Win32 application should not statically link to the winrtmidi DLL as it will only load if your application is running on Windows 10. Therefore, you will need to check if your app is
running on Windows 10 before attempting to load the winrtmidi DLL. You will ship the winrtmidi DLL and dynamically load it when required by your application.

In order to make it easy to add the winrtdll to your application, we have provided a prebuilt version of the DLL as a NuGet package. The NuGet package is available at: https://www.nuget.org/packages/winrtmidi/ Please note that this is a native nuget package and is not compatible with C# projects. You will need to manually download the dll from nuget using the download instructions below and incorporate it into your C# project (just like any other native c dll). You will then use pinvoke to call its methods.

You can add the winrtmidi NuGet package to your Visual Studio 2010 to 2015 project. Please note that Visual Studio 2010 SP1 is required to correctly support incremental link in debug builds.

Adding the winrtmidi DLL to your Win32 Project Using NuGet

  1. If the NuGet package manager is not installed in your version of Visual Studio, install it using the Tools | Extensions… menu option.

  2. Right-click on your application project and select Manage NuGet Packages from the dropdown menu.

    Manage NuGet Packages

  3. Click on the Browse tab, enter winrtmidi in the search field, enable the Include prerelease option. Click on install.

    Select winrtmidi NuGet Package

  4. Your project is now set up with the include paths to the winrtmidi header files. The winrtmidi dll will also be copied automatically to your .exe’s output directory.

  5. In the source file you want to use winrtmidi functions add the following include:

  6. Look at the MidiClient.cpp example for how to:

    • Load the winrtmidi DLL
    • Get pointers to the winrtmidi functions
    • Initialize the winrtmidi api
    • Enumerate MIDI in and out ports
    • Open MIDI ports
    • Send and receive MIDI messages

Obtaining the Prebuilt winrtmidi DLLs

You can also obtain the prebuilt winrtmidi dlls by directly downloading the winrtmidi NuGet package from nuget.org.

  1. Download the nuget package file. You may need to change the version number in the following URL to get the latest version. http://api.nuget.org/packages/winrt.0.0.1.nupkg

  2. Change the .nupkg extension to .zip

  3. Unzip the file. The winrtmidi DLLs will be in the bin folder of the extracted folder. The winrtmidi header files will be in the Include folder.

#Testing for Windows 10 #

Starting with Windows 8.1, the following Win32 version checking functions will return version 6.2.0.0 for Windows 8.1 and above:

  • GetVersion()
  • GetVersionEx()
  • VerifyVersionInfo()

GetVersion() and GetVersionEx() have also been deprecated in Windows 10. In order to correctly obtain the Windows OS version your application is running on, you can do one of the following strategies:

  1. Add an application manifest to your application and use VerifyVersionInfo() to test for Windows 10.
  2. Get the version of kernel32.dll. This method does not require adding an application manifest to ensure correct Windows 8.1/10 version numbers.

If you do not check for Windows 10 and attempt to load the winrtmidi DLL on Windows 7 or 8, your application will quit with the following error:

WinRT DLL Load Error

Method 1: Testing for Windows 10 Using an Application Manifest

  1. Create a file called app.manifest.

  2. Add the following XML to the app.manifest file:

    	<?xml version="1.0" encoding="utf-8" standalone="yes"?>
    	<assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1" xmlns:asmv3="urn:schemas-microsoft-com:asm.v3">
    		<compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1"> 
    			<application> 
    				<!-- Windows 10 --> 
    				<supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}"/>
    				<!-- Windows 8.1 -->
    				<supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}"/>
    				<!-- Windows Vista -->
    				<supportedOS Id="{e2011457-1546-43c5-a5fe-008deee3d3f0}"/> 
    				<!-- Windows 7 -->
    				<supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}"/>
    				<!-- Windows 8 -->
    				<supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}"/>
    			</application> 
    		</compatibility>
    	</assembly>
  3. Right click on your application project and select Properties.

    Properties

  4. Select the Linker | Manifest Tool | Input and Output option and enter the path to the app.manifest file.

    Application Manifest Path

  5. Use the following function to test for Windows 10 in your application. If the function returns true, it is safe to load the winrtmidi DLL.
    This method will work with Visual Studio 2010-2015. This method is also provided in WinRTMidi\WindowsVersionHelper.h which you can add to your project.

    	bool windows10orGreaterWithManifest()
    	{
    		OSVERSIONINFOEX  osvi;
    		DWORDLONG dwlConditionMask = 0;
    		int op = VER_GREATER_EQUAL;
    
    		ZeroMemory(&osvi, sizeof(OSVERSIONINFOEX));
    		osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
    		osvi.dwMajorVersion = 10;
    		VER_SET_CONDITION(dwlConditionMask, VER_MAJORVERSION, op);
    
    		BOOL result = VerifyVersionInfo(&osvi, VER_MAJORVERSION ,dwlConditionMask);
    		return result ? true : false;
    	}

Method 2: Testing for Windows 10 using kernel32.dll ##

If you do not want to add an application manifest to your application, you can still test for Windows 10 by checking the version of kernel32.dll
installed on the device running your application.

  1. Add the following to the source file you will use to test for Windows 10.

    	#pragma comment(lib, "version.lib") 
  2. Use the following function to test for Windows 10. The function obtains the path to kernel32.dll and checks its version number.
    This method is also provided in WinRTMidi\WindowsVersionHelper.h which you can add to your project.

    	bool windows10orGreater()
    	{
    		static const wchar_t kernel32[] = L"\\kernel32.dll";
    		wchar_t path[MAX_PATH];
    
    		unsigned int n = GetSystemDirectory(path, MAX_PATH);
    		memcpy_s(path + n, MAX_PATH, kernel32, sizeof(kernel32));
    
    		unsigned int size = GetFileVersionInfoSize(path, NULL);
    		if (size == 0)
    		{
    			return false;
    		}
    
    		std::vector<char> verionInfo;
    		verionInfo.resize(size);
    		BOOL result = GetFileVersionInfo(path, 0, size, verionInfo.data());
    		if (!result || GetLastError() != S_OK)
    		{
    			return false;
    		}
    
    		VS_FIXEDFILEINFO *vinfo;
    		result = VerQueryValue(verionInfo.data(), L"\\", (LPVOID *)&vinfo, &size);
    		if (!result || size < sizeof(VS_FIXEDFILEINFO))
    		{
    			return false;
    		}
    
    		return HIWORD(vinfo->dwProductVersionMS) >= 10;
    	}

Get JUCE

Enables Win32 applications to access the Windows::Devices::Midi API when running on Windows 10.

This GitHub WinRTMidi project wraps the Windows Runtime Windows::Devices::Midi API
in a Win32 DLL that can be dynamically loaded by a standard Win32 application. If the application is running on a device with Windows 10, the DLL will
load and you will be able to use the Windows::Devices::Midi API via a C interface exported by the DLL.
If your application is running on devices with Windows 7 or Windows 8/8.1, the winrtmidi DLL will not load. Your application will need to test if it is running on Windows 10 before
attempting to load the DLL (See Testing for Windows 10 below). The Windows::Devices::Midi API is ony available on devices running Windows 10.

This DLL is useful for the scenario where you have an existing Win32 MIDI application and want to use the new Windows::Devices::Midi API. If you are not able to update your application to a
Windows 10 UWP app, you can use the winrtmidi DLL to access the Windows::Devices::Midi API when your application is running on a device with Windows 10. You can use the winrtmidi DLL with
applications built with Visual Studio 2010-2015. There is no need to rebuild your application with Visual Studio 2015 to access the Windows::Devices::Midi API using the winrtmidi DLL.

The recommended steps to use this DLL are as follows:

  1. Ship the winrtmidi DLL with your Win32 application but do not link to the DLL.
  2. When your Win32 application runs, check if your application is running on Windows 10 (See Testing for Windows 10 below).
  3. If your application is running on Windows 10, dynamically load the winrtmidi DLL using LoadLibrary().
    • If your application is not running on Windows 10, continue to use the WinMM MIDI API.
  4. Get pointers to the various winrtmidi functions using GetProcAddress().
  5. Initialize the winrtmidi API using the winrt_initialize_midi() function.
  6. Obtain a MIDI port using the winrt_open_midi_in_port() or winrt_open_midi_out_port() functions.
  7. For more information see example code below.

The WinRTMid DLL enables the following MIDI functionality from the Windows::Devices::Midi API:

  • Enumerate MIDI ports.
  • Notification when MIDI ports are added or removed.
  • Create a MIDI in or out port.
  • Send MIDI messages on a MIDI out port.
  • Receive MIDI messages from a MIDI in port.
  • Destroy a MIDI port.
  • Access Bluetooth MIDI ports
  • Multi-client MIDI port support

Requirements to build the winrtmidi DLL

Visual Studio 2015 (Update 3 recommended) with Universal Windows App Development Tools and Windows 10 Tools and SDKs installed

Adding the winrtmidi DLL to your Win32 Project

Your Win32 application should not statically link to the winrtmidi DLL as it will only load if your application is running on Windows 10. Therefore, you will need to check if your app is
running on Windows 10 before attempting to load the winrtmidi DLL. You will ship the winrtmidi DLL and dynamically load it when required by your application.

In order to make it easy to add the winrtdll to your application, we have provided a prebuilt version of the DLL as a NuGet package. The NuGet package is available at: https://www.nuget.org/packages/winrtmidi/ Please note that this is a native nuget package and is not compatible with C# projects. You will need to manually download the dll from nuget using the download instructions below and incorporate it into your C# project (just like any other native c dll). You will then use pinvoke to call its methods.

You can add the winrtmidi NuGet package to your Visual Studio 2010 to 2015 project. Please note that Visual Studio 2010 SP1 is required to correctly support incremental link in debug builds.

Adding the winrtmidi DLL to your Win32 Project Using NuGet

  1. If the NuGet package manager is not installed in your version of Visual Studio, install it using the Tools | Extensions… menu option.
  2. Right-click on your application project and select Manage NuGet Packages from the dropdown menu.

    Manage NuGet Packages

  3. Click on the Browse tab, enter winrtmidi in the search field, enable the Include prerelease option. Click on install.

    Select winrtmidi NuGet Package

  4. Your project is now set up with the include paths to the winrtmidi header files. The winrtmidi dll will also be copied automatically to your .exe’s output directory.

  5. In the source file you want to use winrtmidi functions add the following include:

  6. Look at the MidiClient.cpp example for how to:
    • Load the winrtmidi DLL
    • Get pointers to the winrtmidi functions
    • Initialize the winrtmidi api
    • Enumerate MIDI in and out ports
    • Open MIDI ports
    • Send and receive MIDI messages

Obtaining the Prebuilt winrtmidi DLLs

You can also obtain the prebuilt winrtmidi dlls by directly downloading the winrtmidi NuGet package from nuget.org.

  1. Download the nuget package file. You may need to change the version number in the following URL to get the latest version. http://api.nuget.org/packages/winrt.0.0.1.nupkg

  2. Change the .nupkg extension to .zip

  3. Unzip the file. The winrtmidi DLLs will be in the bin folder of the extracted folder. The winrtmidi header files will be in the Include folder.

Testing for Windows 10

Starting with Windows 8.1, the following Win32 version checking functions will return version 6.2.0.0 for Windows 8.1 and above:

  • GetVersion()
  • GetVersionEx()
  • VerifyVersionInfo()

GetVersion() and GetVersionEx() have also been deprecated in Windows 10. In order to correctly obtain the Windows OS version your application is running on, you can do one of the following strategies:

  1. Add an application manifest to your application and use VerifyVersionInfo() to test for Windows 10.
  2. Get the version of kernel32.dll. This method does not require adding an application manifest to ensure correct Windows 8.1/10 version numbers.

If you do not check for Windows 10 and attempt to load the winrtmidi DLL on Windows 7 or 8, your application will quit with the following error:

WinRT DLL Load Error

Method 1: Testing for Windows 10 Using an Application Manifest

  1. Create a file called app.manifest.
  2. Add the following XML to the app.manifest file:

        <?xml version="1.0" encoding="utf-8" standalone="yes"?>
        <assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1" xmlns:asmv3="urn:schemas-microsoft-com:asm.v3">
            <compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1"> 
                <application> 
                    <!-- Windows 10 --> 
                    <supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}"/>
                    <!-- Windows 8.1 -->
                    <supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}"/>
                    <!-- Windows Vista -->
                    <supportedOS Id="{e2011457-1546-43c5-a5fe-008deee3d3f0}"/> 
                    <!-- Windows 7 -->
                    <supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}"/>
                    <!-- Windows 8 -->
                    <supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}"/>
                </application> 
            </compatibility>
        </assembly>
  3. Right click on your application project and select Properties.

    Properties

  4. Select the Linker | Manifest Tool | Input and Output option and enter the path to the app.manifest file.

    Application Manifest Path

  5. Use the following function to test for Windows 10 in your application. If the function returns true, it is safe to load the winrtmidi DLL.
    This method will work with Visual Studio 2010-2015. This method is also provided in WinRTMidi\WindowsVersionHelper.h which you can add to your project.

        bool windows10orGreaterWithManifest()
        {
            OSVERSIONINFOEX  osvi;
            DWORDLONG dwlConditionMask = 0;
            int op = VER_GREATER_EQUAL;
    
            ZeroMemory(&osvi, sizeof(OSVERSIONINFOEX));
            osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
            osvi.dwMajorVersion = 10;
            VER_SET_CONDITION(dwlConditionMask, VER_MAJORVERSION, op);
    
            BOOL result = VerifyVersionInfo(&osvi, VER_MAJORVERSION ,dwlConditionMask);
            return result ? true : false;
        }

Method 2: Testing for Windows 10 using kernel32.dll

If you do not want to add an application manifest to your application, you can still test for Windows 10 by checking the version of kernel32.dll
installed on the device running your application.

  1. Add the following to the source file you will use to test for Windows 10.

        #pragma comment(lib, "version.lib") 
  2. Use the following function to test for Windows 10. The function obtains the path to kernel32.dll and checks its version number.
    This method is also provided in WinRTMidi\WindowsVersionHelper.h which you can add to your project.

        bool windows10orGreater()
        {
            static const wchar_t kernel32[] = L"\\kernel32.dll";
            wchar_t path[MAX_PATH];
    
            unsigned int n = GetSystemDirectory(path, MAX_PATH);
            memcpy_s(path + n, MAX_PATH, kernel32, sizeof(kernel32));
    
            unsigned int size = GetFileVersionInfoSize(path, NULL);
            if (size == 0)
            {
                return false;
            }
    
            std::vector<char> verionInfo;
            verionInfo.resize(size);
            BOOL result = GetFileVersionInfo(path, 0, size, verionInfo.data());
            if (!result || GetLastError() != S_OK)
            {
                return false;
            }
    
            VS_FIXEDFILEINFO *vinfo;
            result = VerQueryValue(verionInfo.data(), L"\\", (LPVOID *)&vinfo, &size);
            if (!result || size < sizeof(VS_FIXEDFILEINFO))
            {
                return false;
            }
    
            return HIWORD(vinfo->dwProductVersionMS) >= 10;
        }

Project description

Windows Runtime (WinRT) APIs for for the Windows.Devices.Midi namespace.

This package provides the winrt.windows.devices.midi module.

Project details

Download files

Download the file for your platform. If you’re not sure which to choose, learn more about installing packages.

Source Distribution

Built Distributions

File details

Details for the file winrt_windows_devices_midi-3.1.0.tar.gz.

File metadata

  • Download URL:
    winrt_windows_devices_midi-3.1.0.tar.gz

  • Upload date:
  • Size: 16.5 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.12.9

File hashes

Hashes for winrt_windows_devices_midi-3.1.0.tar.gz

Algorithm Hash digest
SHA256 6c60e0bac99b00b76613a311ac4a3e2e72e65dbd7c9b14be4d6254b8835c9b58
MD5 e9ab8e338de30fdb62c74eb634221a03
BLAKE2b-256 313d2a9e9de1db70bd1b8d84aeee9b161d5682251476bcd2ef2c13cc3cfbcffe

See more details on using hashes here.

File details

Details for the file winrt_windows_devices_midi-3.1.0-cp313-cp313-win_arm64.whl.

File metadata

  • Download URL:
    winrt_windows_devices_midi-3.1.0-cp313-cp313-win_arm64.whl

  • Upload date:
  • Size: 73.6 kB
  • Tags: CPython 3.13, Windows ARM64
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.12.9

File hashes

Hashes for winrt_windows_devices_midi-3.1.0-cp313-cp313-win_arm64.whl

Algorithm Hash digest
SHA256 85d21c6c2106738048ced9397cb9021ffe9dfe9b01f4b9b74f2010f5a76a2395
MD5 777d74a53bdee923a1954880709a8831
BLAKE2b-256 b502d8dcaf5ec47cf0e9da36c4eaaddcaf8ea1b622fe14cc155dab143328b4f5

See more details on using hashes here.

File details

Details for the file winrt_windows_devices_midi-3.1.0-cp313-cp313-win_amd64.whl.

File metadata

  • Download URL:
    winrt_windows_devices_midi-3.1.0-cp313-cp313-win_amd64.whl

  • Upload date:
  • Size: 77.7 kB
  • Tags: CPython 3.13, Windows x86-64
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.12.9

File hashes

Hashes for winrt_windows_devices_midi-3.1.0-cp313-cp313-win_amd64.whl

Algorithm Hash digest
SHA256 8732abd0747d6cb89ba51b29b7573d7033aa0fb939e02a8a1e8b89d3d90da18c
MD5 bafa8156fd13c6a8212eaecbd2678536
BLAKE2b-256 8a1028c0086b05dd6c7392d7e0a5f4ba3bb125dcd69ff39baee693da24d3c71a

See more details on using hashes here.

File details

Details for the file winrt_windows_devices_midi-3.1.0-cp313-cp313-win32.whl.

File metadata

  • Download URL:
    winrt_windows_devices_midi-3.1.0-cp313-cp313-win32.whl

  • Upload date:
  • Size: 75.7 kB
  • Tags: CPython 3.13, Windows x86
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.12.9

File hashes

Hashes for winrt_windows_devices_midi-3.1.0-cp313-cp313-win32.whl

Algorithm Hash digest
SHA256 b6e3aa8cae416a631d9b02fd187976e41d21080dff9501beed67297a8c7c0a72
MD5 7f0e1b140e89db2d3a2aa75982bcd7df
BLAKE2b-256 f6fe724b90eddf7a24b64f2af0e42157b05e9bb1999eb2783347f44de74da735

See more details on using hashes here.

File details

Details for the file winrt_windows_devices_midi-3.1.0-cp312-cp312-win_arm64.whl.

File metadata

  • Download URL:
    winrt_windows_devices_midi-3.1.0-cp312-cp312-win_arm64.whl

  • Upload date:
  • Size: 73.5 kB
  • Tags: CPython 3.12, Windows ARM64
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.12.9

File hashes

Hashes for winrt_windows_devices_midi-3.1.0-cp312-cp312-win_arm64.whl

Algorithm Hash digest
SHA256 e4979f7f256471fe21533d190a784ef4ef9b06ffae576cfdf9333e728b7feee4
MD5 6b2ec5001d616f5105b1be2f73e7d9f6
BLAKE2b-256 cfa2031004278e0014964ed1d7b6a53b57a3df6682d1a29440ef29291f95f75f

See more details on using hashes here.

File details

Details for the file winrt_windows_devices_midi-3.1.0-cp312-cp312-win_amd64.whl.

File metadata

  • Download URL:
    winrt_windows_devices_midi-3.1.0-cp312-cp312-win_amd64.whl

  • Upload date:
  • Size: 77.7 kB
  • Tags: CPython 3.12, Windows x86-64
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.12.9

File hashes

Hashes for winrt_windows_devices_midi-3.1.0-cp312-cp312-win_amd64.whl

Algorithm Hash digest
SHA256 9016b45dba8c54c513f7f25556f30888686431b27d0ed752f81458e65e3b5e28
MD5 57f01981e6d25644b9301c1879797a22
BLAKE2b-256 211f985428ae38eeefd3ca5b749209256c0e0be33739ea27200252ea120f1c3a

See more details on using hashes here.

File details

Details for the file winrt_windows_devices_midi-3.1.0-cp312-cp312-win32.whl.

File metadata

  • Download URL:
    winrt_windows_devices_midi-3.1.0-cp312-cp312-win32.whl

  • Upload date:
  • Size: 75.7 kB
  • Tags: CPython 3.12, Windows x86
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.12.9

File hashes

Hashes for winrt_windows_devices_midi-3.1.0-cp312-cp312-win32.whl

Algorithm Hash digest
SHA256 399f5f5931d7801da35d8f5831be6d5ff9343b2ac65a5fd845a173d12f3424a3
MD5 d57963ef38f5f83afb9a2f5006163d4e
BLAKE2b-256 38e5f9d92aa151985f08c29cc69ebd28d3ee88f727de557b3b095d05942ec2a4

See more details on using hashes here.

File details

Details for the file winrt_windows_devices_midi-3.1.0-cp311-cp311-win_arm64.whl.

File metadata

  • Download URL:
    winrt_windows_devices_midi-3.1.0-cp311-cp311-win_arm64.whl

  • Upload date:
  • Size: 73.7 kB
  • Tags: CPython 3.11, Windows ARM64
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.12.9

File hashes

Hashes for winrt_windows_devices_midi-3.1.0-cp311-cp311-win_arm64.whl

Algorithm Hash digest
SHA256 17f32b16f08971ab7d8af5166a1547fe436db3bfcc57bf62fdcd4534fe02537d
MD5 e681b2241af0c49e0d5e26531f5e93d8
BLAKE2b-256 730cc6ed483f083f83bda890e38a26ae83d8ae14cc694aab4ffeb33f886531d8

See more details on using hashes here.

File details

Details for the file winrt_windows_devices_midi-3.1.0-cp311-cp311-win_amd64.whl.

File metadata

  • Download URL:
    winrt_windows_devices_midi-3.1.0-cp311-cp311-win_amd64.whl

  • Upload date:
  • Size: 78.2 kB
  • Tags: CPython 3.11, Windows x86-64
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.12.9

File hashes

Hashes for winrt_windows_devices_midi-3.1.0-cp311-cp311-win_amd64.whl

Algorithm Hash digest
SHA256 f3b2313d37887452a9934909213b8edd19820716080d86286ef9b263badee6a4
MD5 c261ee4a9bd792052c6c0957ca854b6b
BLAKE2b-256 06fcb86ba210367d731a36ddad4f0ee6009ffcc695e5c6eb076af3921a2e7696

See more details on using hashes here.

File details

Details for the file winrt_windows_devices_midi-3.1.0-cp311-cp311-win32.whl.

File metadata

  • Download URL:
    winrt_windows_devices_midi-3.1.0-cp311-cp311-win32.whl

  • Upload date:
  • Size: 75.6 kB
  • Tags: CPython 3.11, Windows x86
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.12.9

File hashes

Hashes for winrt_windows_devices_midi-3.1.0-cp311-cp311-win32.whl

Algorithm Hash digest
SHA256 9e2991c0b6e6b05add23f4e702323f25cbd41c155b3b54470eaf54d4c1a9ed33
MD5 8c38f647755192a69bcaba2f1acb291b
BLAKE2b-256 3c855a5ca291917e532b567e536a187c6898c76e985d01a93ac45b67b178436b

See more details on using hashes here.

File details

Details for the file winrt_windows_devices_midi-3.1.0-cp310-cp310-win_arm64.whl.

File metadata

  • Download URL:
    winrt_windows_devices_midi-3.1.0-cp310-cp310-win_arm64.whl

  • Upload date:
  • Size: 73.8 kB
  • Tags: CPython 3.10, Windows ARM64
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.12.9

File hashes

Hashes for winrt_windows_devices_midi-3.1.0-cp310-cp310-win_arm64.whl

Algorithm Hash digest
SHA256 a71b4a32df26bcfa4e5ed40e65b84d785b720a712777d6ccffd0b8c4b4de9fb5
MD5 37b2caba4ec034f9a5a02dcefd2f21c2
BLAKE2b-256 b4131924b8bcd322cb68432055a328803f947301a547bcb58f5abdd8f5d99042

See more details on using hashes here.

File details

Details for the file winrt_windows_devices_midi-3.1.0-cp310-cp310-win_amd64.whl.

File metadata

  • Download URL:
    winrt_windows_devices_midi-3.1.0-cp310-cp310-win_amd64.whl

  • Upload date:
  • Size: 78.4 kB
  • Tags: CPython 3.10, Windows x86-64
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.12.9

File hashes

Hashes for winrt_windows_devices_midi-3.1.0-cp310-cp310-win_amd64.whl

Algorithm Hash digest
SHA256 89edea2bca9b05c5db277b106988588f9e7b455ddfbdd41f20a455a9cf6eed9d
MD5 1faa9a45f177a149c32ffb814306c124
BLAKE2b-256 a99168312d515b2ca44b396b2496d280b44e62a4ddc2e3d9b5eb30ea0122cdd9

See more details on using hashes here.

File details

Details for the file winrt_windows_devices_midi-3.1.0-cp310-cp310-win32.whl.

File metadata

  • Download URL:
    winrt_windows_devices_midi-3.1.0-cp310-cp310-win32.whl

  • Upload date:
  • Size: 75.7 kB
  • Tags: CPython 3.10, Windows x86
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.12.9

File hashes

Hashes for winrt_windows_devices_midi-3.1.0-cp310-cp310-win32.whl

Algorithm Hash digest
SHA256 8d22cc2c9e3760cd588a3b0aa22d64ce0f066f6b16d209adfbaa4b47fb900952
MD5 c071f553beefdaf59e9d7b489a0b1826
BLAKE2b-256 41e7a2448a432e0b0d5043c4ceb9b62e24b8f4c3f05d1b5d546adc9f29ce3c16

See more details on using hashes here.

File details

Details for the file winrt_windows_devices_midi-3.1.0-cp39-cp39-win_arm64.whl.

File metadata

  • Download URL:
    winrt_windows_devices_midi-3.1.0-cp39-cp39-win_arm64.whl

  • Upload date:
  • Size: 74.1 kB
  • Tags: CPython 3.9, Windows ARM64
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.12.9

File hashes

Hashes for winrt_windows_devices_midi-3.1.0-cp39-cp39-win_arm64.whl

Algorithm Hash digest
SHA256 3b2383a3ca8b0973dbae5f121e4e89dc903280f4a70e9c466e419c91bc914a6f
MD5 031fe9b6d6d4afe04a0c56c0bdc5ab5a
BLAKE2b-256 ebb4e9b2fd9348838361c3192c04b24fb11031de7be35467a620880e9df62bdb

See more details on using hashes here.

File details

Details for the file winrt_windows_devices_midi-3.1.0-cp39-cp39-win_amd64.whl.

File metadata

  • Download URL:
    winrt_windows_devices_midi-3.1.0-cp39-cp39-win_amd64.whl

  • Upload date:
  • Size: 78.7 kB
  • Tags: CPython 3.9, Windows x86-64
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.12.9

File hashes

Hashes for winrt_windows_devices_midi-3.1.0-cp39-cp39-win_amd64.whl

Algorithm Hash digest
SHA256 d32b1c6b1a18eb4999d33897e543c14b3dc7386004f21b7fdcfcc0861f4fd6bc
MD5 48f390e2129d086d14520415758b2945
BLAKE2b-256 a0fa536492a2ae65c1573b2f7e2ba1312a13fbef1cc51e92ec7ad753fe42c2d4

See more details on using hashes here.

File details

Details for the file winrt_windows_devices_midi-3.1.0-cp39-cp39-win32.whl.

File metadata

  • Download URL:
    winrt_windows_devices_midi-3.1.0-cp39-cp39-win32.whl

  • Upload date:
  • Size: 75.4 kB
  • Tags: CPython 3.9, Windows x86
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.12.9

File hashes

Hashes for winrt_windows_devices_midi-3.1.0-cp39-cp39-win32.whl

Algorithm Hash digest
SHA256 9cffaf72e64ca7d3b8dbc217b269d864dc0ef6b6879632cee7799062b3274730
MD5 5763ce1a2cea9595acec56ecdd74331e
BLAKE2b-256 96b0b3772b28d492fa61332da6ebcdc87a7f6b9f00e380a4478d009d78c69b43

See more details on using hashes here.

This article describes using the Windows MIDI API functions in a managed environment.

  • Download source — 161.9 KB

Introduction

This code was created to send and receive MIDI system exclusive messages to a GT-8 guitar processor. The MIDI send and receive functions have been available in Windows since NT. At this time, there are no .NET functions available to perform the same functions. The API functions can be interfaced with .NET using the standard PInvoke methods. However, the functions work asynchronously and so require callback functions to signal to the calling code when data transfer is complete. Most of the articles available which describe how to use this API use the Windows message option as a callback. While this creates a perfectly functional program, it does not allow encapsulation as a Window must be used to receive the callback messages. It also requires the Window Procedure to be overridden to handle the MIDI messages. This article describes using the callback function option so that all MIDI functionality can be contained within a single class.

Background

PInvoke allows .NET managed code call unmanaged API functions. A typical API function declaration would be as shown here:

[DllImport("winmm.dll", SetLastError=true)]
    public static extern uint midiOutGetNumDevs();

The midiOutGetNumDevs function is held in the winmm.dll. The function must be marked as extern as there will be no function body (it is implemented in the DLL).

The SetLastError attribute is set so that if any errors occur during the API call, these can be retrieved using the Marshal.GetLastWin32Error function.

If the API functions have reference parameters that are not simple variable types, these parameters must be sent as a pointer to unmanaged memory. A block of unmanaged memory can be created using the Marsal.AllocHGlobal function. There are also functions within the Marshal class to copy data between managed and unmanaged memory.

Unmanaged memory is not garbage collected (only the pointers are). So, it is important to make sure that any unmanaged memory used is released correctly using the Marshal.Release function.

The standard practice is to store all the API declarations for the application as static functions within a single class.

Using the Code

The attached source code contains an application for sending a receiving data from a BOSS GT-8 guitar processor. This means that some of the code is specific to the application. However there are classes for sending and receiving MIDI data that can be reused in other applications to communicate with any MIDI devices which require short or long MIDI messages.

All API declarations are contained within the CExternals class. By comparing the code in this class with the API documentation, the methods used can be applied to any API function.

CMIDIOutDevice

The CMIDIOutDevice class is used to send short or long MIDI messages via the PCs MIDI port. First, the ListDevices method is called to return a list of all available MIDI output ports. It is important to note the index of the devices in the list as this index must be used to access the desired port. To open a port, call the OpenPort method. This takes a single parameter which is the index of the port to open.

With the port open, a short message can be sent using the SendShortMessage. This requires three parameters for the MIDI status, parameter 1 and parameter 2 (see MIDI documentation for further details).

To send a long (or System Exclusive) message, the SendLongMessage method is used. This requires a byte array containing all the data to send via the open MIDI port. All bytes in the array will be sent starting at 0. If there are any headers or footers required by the MIDI device, then these must also be included in the array.

The OpenPort, ClosePort, SendShortMessage and SendLongMessage functions are asynchronous. When the required function completes, a MessageRecieved event will be raised to indicate that the function has completed.

CMIDIInDevice

The CMIDIInDevice operates on the same principles as the CMIDIOutDevice. The available devices are again listed using the ListDevices function. Note that not all devices can receive as well as send messages.

When the desired port is opened with the OpenPort method, the class will listen for short and long messages on the selected port. If a short message is received, the ShortMessage event will be raised containing the status, parameter1 and parameter2 of the MIDI message.

For a long message, the class will wait until the receive buffer is full or the port is closed. It will then return a LongMessage event. This contains a byte array containing the received data. The size of the receive data buffer is set when the class is instantiated.

Messages received from the MIDI port will be sent via the MessageReceived events.

If any errors occur when handling the received data, these will be raised as ReceiveError events.

Points of Interest

Handling Unmanaged Pointers

The real interest from the program comes from handling the sending and receiving of the Long (System Exclusive) messages.

To send a long message, the midiOutLongMsg() API function is used. The documentation for this function can be found on MSDN.  The first and last parameters are simple values.  However, the lpMidiOutHdr parameter requires a pointer to a MIDIHDR structure. Sending a structure to an API function normally does not cause any problems. However, in this case, one of the members of the structure is a pointer to the data buffer containing the long message. Because the API function manipulates the data in the buffer, both the structure pointer and the data buffer pointer within it must be to unmanaged memory. But, they also require data from the managed parts of the program.

First of all, an instance of the structure MIDIHDR is created (typMsgHeader). As this is managed, data can be entered into its fields in the normal way. The lpData field (the pointer to the unmanaged memory buffer) is assigned to an unmanaged data pointer. This is the same size as the managed byte array (messageBuffer):

typMsgHeader.lpData = Marshal.AllocHGlobal(messageBuffer.Count());

The data from the managed array can then be copied into the data of this pointer using the Marshall.Copy function:

Marshal.Copy(messageBuffer, 0, typMsgHeader.lpData, messageBuffer.Count());

A second unmanaged data pointer is then created. This time with the size of the structure (using the Marshall.SizeOf() function:

DataBufferPointer = Marshal.AllocHGlobal(Marshal.SizeOf(typMsgHeader));

The data from the managed memory is then copied to unmanaged memory using the Marshall.StructureToPtr():

Marshal.StructureToPtr(typMsgHeader, DataBufferPointer, true);

Finally, the API function can be called using the unmanaged data pointer to the structure:

lngReturn = (uint)CExternals.midiOutLongMsg(mMIDIOutHandle, DataBufferPointer, 
(uint)Marshal.SizeOf(typMsgHeader));

It should be noted that the header still needs to be prepared by calling the appropriate API function before it can be sent. An example of manipulating the header and sending the data using the APIs can be found in the SendLongMessage function of CMIDIOutDevice.

The creation of the data buffer structure is similar when calling the MIDI receive API. This can be found in the StartRecording function of CMIDIInDevice. However, in this case the buffer must be transferred back in to managed memory to read the received data. This is done in the LongMessageReceived function of CMIDIInDevice. Firstly, the structure pointer is copied to an instance of the MIDIHDR structure;

InHeader = (CExternals.MIDIHDR) Marshal.PtrToStructure(DataBufferPointer, 
typeof(CExternals.MIDIHDR));

The data buffer pointer can then be accessed and copied to a byte array:

Marshal.Copy(InHeader.lpData, MIDIInBuffer, 0, mInBufferLength);

It should be noted that the structure pointer must not be destroyed before the data is read out of the buffer. Also, as the structure and data pointers are to unmanaged areas, the memory used will not be garbage collected. So, it is important to ensure that this data is released correctly to prevent memory leaks. To release unmanaged memory, use the Marshal.Release function.

API Callback Functions

API functions that require callback functions are surprisingly simple to handle. The steps are as follows:

  1. Create a delegate for the callback function with the same parameter and return values as the API documentation.
  2. Declare the API requiring the callback function with the callback parameter declared with a type of the delegate created above.
  3. Create a function to handle the callback messages with a signature that matches the delegate.
  4. When calling the API function , create an instance of the delegate and assign this as the appropriate parameter in the callback function.

Threading Issues

Because the MIDI API calls act asynchronously, the callback functions when events occur will be on a different thread to the calling function. This causes problems, especially if you want to display the data in a form as the callback thread cannot access the controls running on the main UI thread. It is possible to correct this issue in the form. However this means that whoever is using the MIDI classes needs to be aware of this to prevent errors. An alternative is to use the extremely useful (but often overlooked) SynchronisationContext class. This can be used to essentially post messages between threads.

So, by recording the calling thread when the class is instantiated, data from the callback threads can be safely transferred to the main thread using the SychronisationContext instance.

Понравилась статья? Поделить с друзьями:
0 0 голоса
Рейтинг статьи
Подписаться
Уведомить о
guest

0 комментариев
Старые
Новые Популярные
Межтекстовые Отзывы
Посмотреть все комментарии
  • Приложение для подключения к удаленному рабочему столу windows
  • Jre 8u301 windows x64 exe
  • Как выглядит лицензия windows 10
  • Как переключаться между учетными записями в windows 11
  • Что будет если лицензия windows 10 истечет