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:
- Ship the winrtmidi DLL with your Win32 application but do not link to the DLL.
- When your Win32 application runs, check if your application is running on Windows 10 (See Testing for Windows 10 below).
- 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.
- Get pointers to the various winrtmidi functions using GetProcAddress().
- Initialize the winrtmidi API using the winrt_initialize_midi() function.
- Obtain a MIDI port using the winrt_open_midi_in_port() or winrt_open_midi_out_port() functions.
- 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
-
If the NuGet package manager is not installed in your version of Visual Studio, install it using the Tools | Extensions… menu option.
-
Right-click on your application project and select Manage NuGet Packages from the dropdown menu.
-
Click on the Browse tab, enter winrtmidi in the search field, enable the Include prerelease option. Click on install.
-
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.
-
In the source file you want to use winrtmidi functions add the following include:
-
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.
-
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
-
Change the .nupkg extension to .zip
-
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:
- Add an application manifest to your application and use VerifyVersionInfo() to test for Windows 10.
- 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:
Method 1: Testing for Windows 10 Using an Application Manifest
-
Create a file called app.manifest.
-
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>
-
Right click on your application project and select Properties.
-
Select the Linker | Manifest Tool | Input and Output option and enter the path to the app.manifest file.
-
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.
-
Add the following to the source file you will use to test for Windows 10.
#pragma comment(lib, "version.lib")
-
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:
- Ship the winrtmidi DLL with your Win32 application but do not link to the DLL.
- When your Win32 application runs, check if your application is running on Windows 10 (See Testing for Windows 10 below).
- 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.
- Get pointers to the various winrtmidi functions using GetProcAddress().
- Initialize the winrtmidi API using the winrt_initialize_midi() function.
- Obtain a MIDI port using the winrt_open_midi_in_port() or winrt_open_midi_out_port() functions.
- 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
- If the NuGet package manager is not installed in your version of Visual Studio, install it using the Tools | Extensions… menu option.
-
Right-click on your application project and select Manage NuGet Packages from the dropdown menu.
-
Click on the Browse tab, enter winrtmidi in the search field, enable the Include prerelease option. Click on install.
-
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.
-
In the source file you want to use winrtmidi functions add the following include:
- 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.
-
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
-
Change the .nupkg extension to .zip
-
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:
- Add an application manifest to your application and use VerifyVersionInfo() to test for Windows 10.
- 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:
Method 1: Testing for Windows 10 Using an Application Manifest
- Create a file called app.manifest.
-
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>
-
Right click on your application project and select Properties.
-
Select the Linker | Manifest Tool | Input and Output option and enter the path to the app.manifest file.
-
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.
-
Add the following to the source file you will use to test for Windows 10.
#pragma comment(lib, "version.lib")
-
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:
- Create a delegate for the callback function with the same parameter and return values as the API documentation.
- Declare the API requiring the callback function with the callback parameter declared with a type of the delegate created above.
- Create a function to handle the callback messages with a signature that matches the delegate.
- 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.