tags:

views:

291

answers:

1

Hello

I've written a simple MIDI console application in C++. Here's the whole thing:

#include <windows.h>
#include <iostream>
#include <math.h>
using namespace std;
void CALLBACK midiInputCallback(HMIDIIN hMidiIn, UINT wMsg, DWORD_PTR dwInstance, DWORD_PTR dwParam1, DWORD_PTR dwParam2) {
 switch (wMsg) {
  case MIM_MOREDATA:
  case MIM_DATA:
   cout << dwParam1 << " ";
   PlaySound("jingle.wav", NULL, SND_ASYNC | SND_FILENAME);
   break;
 }
}
int main() {
 unsigned int numDevs = midiInGetNumDevs();
 cout << numDevs << " MIDI devices connected:" << endl;
 MIDIINCAPS inputCapabilities;
 for (unsigned int i = 0; i < numDevs; i++) {
  midiInGetDevCaps(i, &inputCapabilities, sizeof(inputCapabilities));
  cout << "[" << i << "] " << inputCapabilities.szPname << endl;
 }
 int portID;
 cout << "Enter the port which you want to connect to: ";
 cin >> portID;
 cout << "Trying to connect with the device on port " << portID << "..." << endl;
 LPHMIDIIN device = new HMIDIIN[numDevs];
 int flag = midiInOpen(&device[portID], portID, (DWORD)&midiInputCallback, 0, CALLBACK_FUNCTION);
 if (flag != MMSYSERR_NOERROR) {
  cout << "Error opening MIDI port." << endl;
  return 1;
 } else {
  cout << "You are now connected to port " << portID << "!" << endl;
  midiInStart(device[portID]);
 }
 while (1) {}
}

You can see that there's a callback function for handling the incoming MIDI messages from the device. Here is the description of this function on MSDN. On that page they say that the meaning of dwParam1 and dwParam2 are specified to the messagetype (wMsg), like MIM_DATA.

If I look up the documentation of MIM_DATA, I can see that it is a doubleword (DWORD?) and that it has a 'high word' and a 'low word'. How can I now get data like the name of the control on the MIDI device that sended the data and what value it sends?

I would appreciate it if somebody can correct my code if it can be done better.

Thanks :)

+5  A: 

To access the data you need to use dwParam1 and dwParam2 and call the macros HIWORD and LOWORD to get the high and low word from them. Respectively use HIBYTE and LOBYTE to get the data out of those words. In case of MIM_DATA, unfortunately that's byte encoded MIDI data, so you'll have to find the specific meanings for those -- these are documented here -- MIDI Messages.

Your code however has a potential problem -- as we read in the MSDN pages:

"Applications should not call any multimedia functions from inside the callback function, as doing so can cause a deadlock. Other system functions can safely be called from the callback".

And you're calling PlaySound in the Callback...

Kornel Kisielewicz
That's really cool. :) It works, didn't think it would be that simple!And thanks for giving such a quick and helpful reply.
Midas
Thanks for your note about `PlaySound`. It was just a tryout to use that function there so I can still change that.
Midas