MMSYSERR_NOMEM when calling midiInOpen() only when other midi apps are open

1k views Asked by At

I am trying to open a midi port on windows using midiInOpen. The call normally works great (I'm using the RtMidi wrapper, and the code is quite clean), but it returns MMSYSERR_NOMEM if Ableton Live is open. The machine has plenty of ram left (4GB), and closing other applications doesn't seem to have any effect.

Am I running into some kind of internal resource limit in winmm?

I am running Windows 7 on a new Intel NUC machine, the calls are coming from RtMidi.cpp, and I am wrapping them in a CPython module but not doing anything else fancy. I am an experienced C++ developer and can get my fingers into this if someone can point the way.

Thanks!

void MidiInWinMM :: openPort( unsigned int portNumber, const std::string /*portName*/ )
{
  if ( connected_ ) {
    errorString_ = "MidiInWinMM::openPort: a valid connection already exists!";
    error( RtMidiError::WARNING, errorString_ );
    return;
  }

  unsigned int nDevices = midiInGetNumDevs();
  if (nDevices == 0) {
    errorString_ = "MidiInWinMM::openPort: no MIDI input sources found!";
    error( RtMidiError::NO_DEVICES_FOUND, errorString_ );
    return;
  }

  if ( portNumber >= nDevices ) {
    std::ostringstream ost;
    ost << "MidiInWinMM::openPort: the 'portNumber' argument (" << portNumber << ") is invalid.";
    errorString_ = ost.str();
    error( RtMidiError::INVALID_PARAMETER, errorString_ );
    return;
  }

  WinMidiData *data = static_cast<WinMidiData *> (apiData_);
  MMRESULT result = midiInOpen( &data->inHandle,
                                portNumber,
                                (DWORD_PTR)&midiInputCallback,
                                (DWORD_PTR)&inputData_,
                                CALLBACK_FUNCTION );
  if ( result != MMSYSERR_NOERROR ) {
    if(result == MMSYSERR_ALLOCATED) printf("MMSYSERR_ALLOCATED: %i\n", MMSYSERR_ALLOCATED);
    if(result == MMSYSERR_BADDEVICEID) printf("MMSYSERR_BADDEVICEID: %i\n", MMSYSERR_BADDEVICEID);
    if(result == MMSYSERR_INVALFLAG) printf("MMSYSERR_INVALFLAG: %i\n", MMSYSERR_INVALFLAG);
    if(result == MMSYSERR_INVALPARAM) printf("MMSYSERR_INVALPARAM: %i\n", MMSYSERR_INVALPARAM);
    if(result == MMSYSERR_NOMEM) printf("MMSYSERR_NOMEM: %i\n", MMSYSERR_NOMEM);
    errorString_ = "MidiInWinMM::openPort: error creating Windows MM MIDI input port.";
    error( RtMidiError::DRIVER_ERROR, errorString_ );
    return;
  }

  // Allocate and init the sysex buffers.
  for ( int i=0; i<RT_SYSEX_BUFFER_COUNT; ++i ) {
    data->sysexBuffer[i] = (MIDIHDR*) new char[ sizeof(MIDIHDR) ];
    data->sysexBuffer[i]->lpData = new char[ RT_SYSEX_BUFFER_SIZE ];
    data->sysexBuffer[i]->dwBufferLength = RT_SYSEX_BUFFER_SIZE;
    data->sysexBuffer[i]->dwUser = i; // We use the dwUser parameter as buffer indicator
    data->sysexBuffer[i]->dwFlags = 0;

    result = midiInPrepareHeader( data->inHandle, data->sysexBuffer[i], sizeof(MIDIHDR) );
    if ( result != MMSYSERR_NOERROR ) {
      midiInClose( data->inHandle );
      errorString_ = "MidiInWinMM::openPort: error starting Windows MM MIDI input port (PrepareHeader).";
      error( RtMidiError::DRIVER_ERROR, errorString_ );
      return;
    }

    // Register the buffer.
    result = midiInAddBuffer( data->inHandle, data->sysexBuffer[i], sizeof(MIDIHDR) );
    if ( result != MMSYSERR_NOERROR ) {
      midiInClose( data->inHandle );
      errorString_ = "MidiInWinMM::openPort: error starting Windows MM MIDI input port (AddBuffer).";
      error( RtMidiError::DRIVER_ERROR, errorString_ );
      return;
    }
  }

  result = midiInStart( data->inHandle );
  if ( result != MMSYSERR_NOERROR ) {
    midiInClose( data->inHandle );
    errorString_ = "MidiInWinMM::openPort: error starting Windows MM MIDI input port.";
    error( RtMidiError::DRIVER_ERROR, errorString_ );
    return;
  }

  connected_ = true;
}
1

There are 1 answers

0
Oldes On

I had the same error when calling midiInOpen function in my command line tool (that is the reason why I'm here) and found, that it was because I had another (also command line) connection to my midi device connected in the same time.

When I closed the first one, I was able to open it in the main app again.

In your case its the Ableton which holds the connection. I'm not an expert, but I believe, you can have the device connected only to one application.