Skip to content

Instantly share code, notes, and snippets.

@yoggy
Created December 16, 2011 08:46
Show Gist options
  • Star 10 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save yoggy/1485181 to your computer and use it in GitHub Desktop.
Save yoggy/1485181 to your computer and use it in GitHub Desktop.
MIDI-in sample program for Win32 (using winmm.lib)
#include <SDKDDKVer.h>
#include <Windows.h>
#include <stdio.h>
#include <conio.h>
#include <mmsystem.h>
#pragma comment(lib, "winmm.lib")
void PrintMidiDevices()
{
UINT nMidiDeviceNum;
MIDIINCAPS caps;
nMidiDeviceNum = midiInGetNumDevs();
if (nMidiDeviceNum == 0) {
fprintf(stderr, "midiInGetNumDevs() return 0...");
return;
}
printf("== PrintMidiDevices() == \n");
for (unsigned int i = 0; i < nMidiDeviceNum; ++i) {
midiInGetDevCaps(i, &caps, sizeof(MIDIINCAPS));
printf("\t%d : name = %s\n", i, caps.szPname);
}
printf("=====\n");
}
void CALLBACK MidiInProc(HMIDIIN hMidiIn, UINT wMsg, DWORD dwInstance, DWORD dwParam1, DWORD dwParam2)
{
switch(wMsg) {
case MIM_OPEN:
printf("wMsg=MIM_OPEN\n");
break;
case MIM_CLOSE:
printf("wMsg=MIM_CLOSE\n");
break;
case MIM_DATA:
printf("wMsg=MIM_DATA, dwInstance=%08x, dwParam1=%08x, dwParam2=%08x\n", dwInstance, dwParam1, dwParam2);
break;
case MIM_LONGDATA:
printf("wMsg=MIM_LONGDATA\n");
break;
case MIM_ERROR:
printf("wMsg=MIM_ERROR\n");
break;
case MIM_LONGERROR:
printf("wMsg=MIM_LONGERROR\n");
break;
case MIM_MOREDATA:
printf("wMsg=MIM_MOREDATA\n");
break;
default:
printf("wMsg = unknown\n");
break;
}
return;
}
int main(int argc, char* argv[])
{
HMIDIIN hMidiDevice = NULL;;
DWORD nMidiPort = 0;
UINT nMidiDeviceNum;
MMRESULT rv;
PrintMidiDevices();
nMidiDeviceNum = midiInGetNumDevs();
if (nMidiDeviceNum == 0) {
fprintf(stderr, "midiInGetNumDevs() return 0...");
return -1;
}
rv = midiInOpen(&hMidiDevice, nMidiPort, (DWORD)(void*)MidiInProc, 0, CALLBACK_FUNCTION);
if (rv != MMSYSERR_NOERROR) {
fprintf(stderr, "midiInOpen() failed...rv=%d", rv);
return -1;
}
midiInStart(hMidiDevice);
while(true) {
if (!_kbhit()) {
Sleep(100);
continue;
}
int c = _getch();
if (c == VK_ESCAPE) break;
if (c == 'q') break;
}
midiInStop(hMidiDevice);
midiInClose(hMidiDevice);
hMidiDevice = NULL;
return 0;
}
@lycium
Copy link

lycium commented Jun 18, 2018

To make this work on 64bit, change DWORD to DWORD_PTR on line 75.

@RANKOmen
Copy link

Windows 10, Codeblock.
Hello thank's for this code. Pehaps could you help me:
i receive callback message for MIM_OPEN, MIM_CLOSE, MIM_DATA but nothing
for MIM_LONGDATA: i tried with a lot of sysex (F0 .. .. .. .. .. .. .. F7) type.
But the issue is not specific to your code and is systematic with every program i buid using midi callback( with codebock or Visual Studio)
Everytime i receive callback message for MIM_OPEN, MIM_CLOSE, MIM_DATA but nothing for MIM_LONGDATA. It's frustrating.

Do you think windows 10 is the problem or other ? Thank in advance for your help

@Kalfan
Copy link

Kalfan commented Sep 9, 2019

@Kalfan
Copy link

Kalfan commented Sep 9, 2019

Ignore the above but the Low-level MIDI APIs do work in Win10 perfectly.

@Kalfan
Copy link

Kalfan commented Sep 10, 2019

If problem persists then try to move the midi functions to a separate file or move the midi functions into a separate thread.

@Erriez
Copy link

Erriez commented Jul 16, 2022

Thanks for pointing to this MIDI C++ code.

The midi_in_sample.cpp requires some modification to build for 64-bit:

  1. As reported earlier: DWORD to DWORD_PTR line 75.
  2. It prints only one character of the MIDI port name, because incaps.szPname is a WCHAR type. Replaced printf with wprintf with whcar.h include.
  3. Added MIDI output ports in function PrintMidiDevices().

Complete code:

#include <SDKDDKVer.h>
#include <Windows.h>

#include <stdio.h>
#include <conio.h>
#include <wchar.h>

#include <mmsystem.h>
#pragma comment(lib, "winmm.lib")

void PrintMidiDevices()
{
	UINT nMidiDeviceNum;
	MIDIINCAPS incaps;
	MIDIOUTCAPS outcaps;

	nMidiDeviceNum = midiInGetNumDevs();
	if (nMidiDeviceNum == 0) {
		fprintf(stderr, "midiInGetNumDevs() return 0...");
		return;
	}

	printf("MIDI input devices:\n");
	for (unsigned int i = 0; i < midiInGetNumDevs(); i++) {
		midiInGetDevCaps(i, &incaps, sizeof(MIDIINCAPS));
		wprintf(L"    %d : name = %s\n", i, incaps.szPname);
	}

	printf("MIDI output devices:\n");
	for (unsigned int i = 0; i < midiOutGetNumDevs(); i++) {
		midiOutGetDevCaps(i, &outcaps, sizeof(MIDIINCAPS));
		wprintf(L"    %d : name = %s\n", i, outcaps.szPname);
	}

	printf("\n");
}

void CALLBACK MidiInProc(HMIDIIN hMidiIn, UINT wMsg, DWORD dwInstance, DWORD dwParam1, DWORD dwParam2)
{
	switch (wMsg) {
	case MIM_OPEN:
		printf("wMsg=MIM_OPEN\n");
		break;
	case MIM_CLOSE:
		printf("wMsg=MIM_CLOSE\n");
		break;
	case MIM_DATA:
		printf("wMsg=MIM_DATA, dwInstance=%08x, dwParam1=%08x, dwParam2=%08x\n", dwInstance, dwParam1, dwParam2);
		break;
	case MIM_LONGDATA:
		printf("wMsg=MIM_LONGDATA\n");
		break;
	case MIM_ERROR:
		printf("wMsg=MIM_ERROR\n");
		break;
	case MIM_LONGERROR:
		printf("wMsg=MIM_LONGERROR\n");
		break;
	case MIM_MOREDATA:
		printf("wMsg=MIM_MOREDATA\n");
		break;
	default:
		printf("wMsg = unknown\n");
		break;
	}
	return;
}

int main(int argc, char* argv[])
{
	HMIDIIN hMidiDevice = NULL;;
	DWORD nMidiPort = 0;
	UINT nMidiDeviceNum;
	MMRESULT rv;

	PrintMidiDevices();

	nMidiDeviceNum = midiInGetNumDevs();
	if (nMidiDeviceNum == 0) {
		fprintf(stderr, "midiInGetNumDevs() return 0...");
		return -1;
	}

	rv = midiInOpen(&hMidiDevice, nMidiPort, (DWORD_PTR)(void*)MidiInProc, 0, CALLBACK_FUNCTION);
	if (rv != MMSYSERR_NOERROR) {
		fprintf(stderr, "midiInOpen() failed...rv=%d", rv);
		return -1;
	}

	midiInStart(hMidiDevice);

	while (true) {
		if (!_kbhit()) {
			Sleep(100);
			continue;
		}
		int c = _getch();
		if (c == VK_ESCAPE) break;
		if (c == 'q') break;
	}

	midiInStop(hMidiDevice);
	midiInClose(hMidiDevice);
	hMidiDevice = NULL;

	return 0;
}

Copy link

ghost commented Nov 11, 2023

this code works, but do you know if there's any way to make it work while using FL Studio as well? I'd like to have FL Studio running so that I get sound out of it, but want to process the midi input with C++/C# so I can show notes on the staff as I play. if I try to have both programs running at once, neither one works, it gives the "midiInOpen() failed" error.... thanks

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment