MF_API bool MFMidi_Start(MFDevice *pDevice) { MFMidiPC_MidiInputDevice *pMidi = (MFMidiPC_MidiInputDevice*)pDevice->pInternal; if (pDevice->state == MFDevState_Active) { MFDebug_Warn(1, "Midi input device already started!"); return false; } if (pDevice->state != MFDevState_Ready) { MFDebug_Warn(1, "Midi input device not ready!"); return false; } pMidi->numEvents = pMidi->numEventsRead = 0; MMRESULT r = midiInStart(pMidi->hMidiIn); if (r != MMSYSERR_NOERROR) { pDevice->state = MFDevState_Unknown; wchar_t errorBuffer[256]; midiInGetErrorText(r, errorBuffer, sizeof(errorBuffer)); MFDebug_Warn(1, MFStr("Couldn't start MIDI device: %s", MFString_WCharAsUTF8(errorBuffer))); return false; } pDevice->state = MFDevState_Active; return true; }
static void winmm_get_host_error(PmInternal * midi, char * msg, UINT len) { /* precondition: midi != NULL */ midiwinmm_node * m = (midiwinmm_node *) midi->descriptor; char *hdr1 = "Host error: "; char *hdr2 = "Host callback error: "; msg[0] = 0; /* initialize result string to empty */ if (descriptors[midi->device_id].pub.input) { /* input and output use different winmm API calls */ if (m) { /* make sure there is an open device to examine */ if (m->error != MMSYSERR_NOERROR) { int n = str_copy_len(msg, hdr1, len); /* read and record host error */ int err = midiInGetErrorText(m->error, msg + n, len - n); assert(err == MMSYSERR_NOERROR); m->error = MMSYSERR_NOERROR; } } } else { /* output port */ if (m) { if (m->error != MMSYSERR_NOERROR) { int n = str_copy_len(msg, hdr1, len); int err = midiOutGetErrorText(m->error, msg + n, len - n); assert(err == MMSYSERR_NOERROR); m->error = MMSYSERR_NOERROR; } } } }
bool _error( MMRESULT res ) { if ( ! res ) return 1; midiInGetErrorText( res, _err, 1024 ); printf( "Midi Error: %s\n", _err ); return 0; //MessageBox( NULL, _err, "midi in", MB_OK ); }
QString mmErrorString(MMRESULT err) { QString errstr; #ifdef UNICODE WCHAR buffer[1024]; midiInGetErrorText(err, &buffer[0], sizeof(buffer)); errstr = QString::fromUtf16((const ushort*)buffer); #else char buffer[1024]; midiOutGetErrorText(err, &buffer[0], sizeof(buffer)); errstr = QString::fromLocal8Bit(buffer); #endif return errstr; }
//_________________________________________________________ static char *makeShortString (char *s, SlotRefNum ref, int errCode, short in) { static char out[1024]; char buff[kGetErrorTextBuf]; TSlotInfos infos; if(in) midiInGetErrorText(errCode, buff, kGetErrorTextBuf); else midiOutGetErrorText(errCode, buff, kGetErrorTextBuf); infos.name[0] = 0; MidiGetSlotInfos (ref, &infos); wsprintf (out, "%s : %s error\n%s", infos.name, s, buff); return out; }
/* * assume midi is non-null (checked by caller) */ static PmError winmm_in_close(PmInternal *midi) { midiwinmm_type m = (midiwinmm_type) midi->descriptor; if (!m) return pmBadPtr; /* device to close */ if (pm_hosterror = midiInStop(m->handle.in)) { midiInReset(m->handle.in); /* try to reset and close port */ midiInClose(m->handle.in); } else if (pm_hosterror = midiInReset(m->handle.in)) { midiInClose(m->handle.in); /* best effort to close midi port */ } else { pm_hosterror = midiInClose(m->handle.in); } midi->descriptor = NULL; pm_free(m); /* delete */ if (pm_hosterror) { int err = midiInGetErrorText(pm_hosterror, (char *) pm_hosterror_text, PM_HOST_ERROR_MSG_LEN); assert(err == MMSYSERR_NOERROR); return pmHostError; } return pmNoError; }
void moMidiDevice::PrintMidiInErrorMsg(unsigned long err) { #ifdef WIN32 #define BUFFERSIZE 200 char buffer[BUFFERSIZE]; if (!(err = midiInGetErrorText(err, &buffer[0], BUFFERSIZE))) { printf("%s\r\n", &buffer[0]); } else if (err == MMSYSERR_BADERRNUM) { printf("Strange error number returned!\r\n"); } else if (err == MMSYSERR_INVALPARAM) { printf("Specified pointer is invalid!\r\n"); } else { printf("Unable to allocate/lock memory!\r\n"); } #endif }
static void msw_midiinerror(char *s, int err) { char t[256]; midiInGetErrorText(err, t, 256); fprintf(stderr, s, t); }
static PmError winmm_in_open(PmInternal *midi, void *driverInfo) { DWORD dwDevice; int i = midi->device_id; midiwinmm_type m; LPMIDIHDR hdr; dwDevice = (DWORD) descriptors[i].descriptor; /* create system dependent device data */ m = (midiwinmm_type) pm_alloc(sizeof(midiwinmm_node)); /* create */ midi->descriptor = m; if (!m) goto no_memory; m->handle.in = NULL; m->buffers = NULL; m->num_buffers = 0; m->next_buffer = 0; m->last_time = 0; m->first_message = TRUE; /* not used for input */ m->sysex_mode = FALSE; m->sysex_word = 0; m->sysex_byte_count = 0; m->sync_time = 0; m->delta = 0; m->error = MMSYSERR_NOERROR; m->callback_error = MMSYSERR_NOERROR; /* open device */ pm_hosterror = midiInOpen(&(m->handle.in), /* input device handle */ dwDevice, /* device ID */ (DWORD) winmm_in_callback, /* callback address */ (DWORD) midi, /* callback instance data */ CALLBACK_FUNCTION); /* callback is a procedure */ if (pm_hosterror) goto free_descriptor; /* allocate first buffer for sysex data */ hdr = allocate_buffer(PM_DEFAULT_SYSEX_BUFFER_SIZE); if (!hdr) goto close_device; pm_hosterror = midiInPrepareHeader(m->handle.in, hdr, sizeof(MIDIHDR)); if (pm_hosterror) { pm_free(hdr); goto close_device; } pm_hosterror = midiInAddBuffer(m->handle.in, hdr, sizeof(MIDIHDR)); if (pm_hosterror) goto close_device; /* allocate second buffer */ hdr = allocate_buffer(PM_DEFAULT_SYSEX_BUFFER_SIZE); if (!hdr) goto close_device; pm_hosterror = midiInPrepareHeader(m->handle.in, hdr, sizeof(MIDIHDR)); if (pm_hosterror) { pm_free(hdr); goto reset_device; /* because first buffer was added */ } pm_hosterror = midiInAddBuffer(m->handle.in, hdr, sizeof(MIDIHDR)); if (pm_hosterror) goto reset_device; /* start device */ pm_hosterror = midiInStart(m->handle.in); if (pm_hosterror) goto reset_device; return pmNoError; /* undo steps leading up to the detected error */ reset_device: /* ignore return code (we already have an error to report) */ midiInReset(m->handle.in); close_device: midiInClose(m->handle.in); /* ignore return code */ free_descriptor: midi->descriptor = NULL; pm_free(m); no_memory: if (pm_hosterror) { int err = midiInGetErrorText(pm_hosterror, (char *) pm_hosterror_text, PM_HOST_ERROR_MSG_LEN); assert(err == MMSYSERR_NOERROR); return pmHostError; } /* if !pm_hosterror, then the error must be pmInsufficientMemory */ return pmInsufficientMemory; /* note: if we return an error code, the device will be closed and memory will be freed. It's up to the caller to free the parameter midi */ }
static PmError winmm_in_open(PmInternal *midi, void *driverInfo) { DWORD dwDevice; int i = midi->device_id; int max_sysex_len = midi->buffer_len * 4; int num_input_buffers = max_sysex_len / INPUT_SYSEX_LEN; midiwinmm_type m; dwDevice = (DWORD) descriptors[i].descriptor; /* create system dependent device data */ m = (midiwinmm_type) pm_alloc(sizeof(midiwinmm_node)); /* create */ midi->descriptor = m; if (!m) goto no_memory; m->handle.in = NULL; m->buffers = NULL; /* not used for input */ m->num_buffers = 0; /* not used for input */ m->max_buffers = FALSE; /* not used for input */ m->buffers_expanded = 0; /* not used for input */ m->next_buffer = 0; /* not used for input */ m->buffer_signal = 0; /* not used for input */ m->last_time = 0; m->first_message = TRUE; /* not used for input */ m->sysex_mode = FALSE; m->sysex_word = 0; m->sysex_byte_count = 0; m->hdr = NULL; /* not used for input */ m->sync_time = 0; m->delta = 0; m->error = MMSYSERR_NOERROR; /* 4000 is based on Windows documentation -- that's the value used in the memory manager. It's small enough that it should not hurt performance even if it's not optimal. */ InitializeCriticalSectionAndSpinCount(&m->lock, 4000); /* open device */ pm_hosterror = midiInOpen( &(m->handle.in), /* input device handle */ dwDevice, /* device ID */ (DWORD_PTR) winmm_in_callback, /* callback address */ (DWORD_PTR) midi, /* callback instance data */ CALLBACK_FUNCTION); /* callback is a procedure */ if (pm_hosterror) goto free_descriptor; if (num_input_buffers < MIN_INPUT_BUFFERS) num_input_buffers = MIN_INPUT_BUFFERS; for (i = 0; i < num_input_buffers; i++) { if (allocate_input_buffer(m->handle.in, INPUT_SYSEX_LEN)) { /* either pm_hosterror was set, or the proper return code is pmInsufficientMemory */ goto close_device; } } /* start device */ pm_hosterror = midiInStart(m->handle.in); if (pm_hosterror) goto reset_device; return pmNoError; /* undo steps leading up to the detected error */ reset_device: /* ignore return code (we already have an error to report) */ midiInReset(m->handle.in); close_device: midiInClose(m->handle.in); /* ignore return code */ free_descriptor: midi->descriptor = NULL; pm_free(m); no_memory: if (pm_hosterror) { int err = midiInGetErrorText(pm_hosterror, (char *) pm_hosterror_text, PM_HOST_ERROR_MSG_LEN); assert(err == MMSYSERR_NOERROR); return pmHostError; } /* if !pm_hosterror, then the error must be pmInsufficientMemory */ return pmInsufficientMemory; /* note: if we return an error code, the device will be closed and memory will be freed. It's up to the caller to free the parameter midi */ }
char* MIDI_IN_GetErrorStr(INT32 err) { winMidiInErrMsg[0] = 0; midiInGetErrorText((MMRESULT) err, winMidiInErrMsg, WIN_MAX_ERROR_LEN); return winMidiInErrMsg; }
static char* fluid_winmidi_input_error(int no) { midiInGetErrorText(no, fluid_winmidi_error_buffer, 256); return fluid_winmidi_error_buffer; }
static void CALLBACK MidiInProc(HMIDIIN hMidiIn, UINT wMsg, DWORD_PTR dwInstance, DWORD_PTR dwParam1, DWORD_PTR dwParam2) { MFDevice *pDevice = (MFDevice*)dwInstance; MFMidiPC_MidiInputDevice *pMidi = (MFMidiPC_MidiInputDevice*)pDevice->pInternal; switch(wMsg) { case MIM_OPEN: MFDebug_Log(0, MFStr("Opened MIDI input device: %s", pDevice->strings[MFDS_ID])); break; case MIM_CLOSE: MFDebug_Log(0, MFStr("Closed MIDI input device: %s", pDevice->strings[MFDS_ID])); break; case MIM_MOREDATA: MFDebug_Log(0, "MIDI message: MIM_MOREDATA"); break; case MIM_DATA: { MFMidiEvent ev; MFMidi_DecodeShortMessage((uint32)dwParam1, &ev, (uint32)dwParam2); switch(ev.ev) { case MFMET_NoteOff: pMidi->channels[ev.channel].notes[ev.noteOff.note] = 0; break; case MFMET_NoteOn: case MFMET_NoteAftertouch: pMidi->channels[ev.channel].notes[ev.noteOn.note] = ev.noteOn.velocity; break; case MFMET_ControlChange: pMidi->channels[ev.channel].control[ev.controlChange.control] = ev.controlChange.value; break; case MFMET_ProgramChange: pMidi->channels[ev.channel].program = ev.programChange.program; break; case MFMET_ChannelAftertouch: // TODO: ... what is this? break; case MFMET_PitchBend: pMidi->channels[ev.channel].pitch = ev.pitchBend.value; break; default: MFDebug_Assert(false, "Why are we getting sys events?"); break; } if (pMidi->bBuffered || pMidi->pEventCallback) { if (pMidi->bBuffered) { if (pMidi->numEvents >= pMidi->numAllocated) { pMidi->numAllocated *= 2; pMidi->pEvents = (MFMidiEvent*)MFHeap_Realloc(pMidi->pEvents, sizeof(MFMidiEvent)*pMidi->numAllocated); } pMidi->pEvents[pMidi->numEvents++] = ev; } if (pMidi->pEventCallback) { pMidi->pEventCallback(pDevice, &ev); } } break; } case MIM_LONGDATA: { MIDIHDR *pHdr = (MIDIHDR*)dwParam1; MFMidiEvent ev; MFMidi_DecodePacket((const uint8*)pHdr->lpData, pHdr->dwBytesRecorded, &ev, (uint32)dwParam2); if (pMidi->bBuffered || pMidi->pEventCallback) { if (pMidi->bBuffered) { if (pMidi->numEvents >= pMidi->numAllocated) { pMidi->numAllocated *= 2; pMidi->pEvents = (MFMidiEvent*)MFHeap_Realloc(pMidi->pEvents, sizeof(MFMidiEvent)*pMidi->numAllocated); } pMidi->pEvents[pMidi->numEvents++] = ev; } if (pMidi->pEventCallback) { pMidi->pEventCallback(pDevice, &ev); } } MMRESULT r = midiInAddBuffer(pMidi->hMidiIn, pHdr, sizeof(*pHdr)); if (r != MMSYSERR_NOERROR) { wchar_t errorBuffer[256]; midiInGetErrorText(r, errorBuffer, sizeof(errorBuffer)); MFDebug_Warn(1, MFStr("Failed to open MIDI input device: %s", MFString_WCharAsUTF8(errorBuffer))); } break; } case MIM_ERROR: case MIM_LONGERROR: { MFDebug_Log(0, MFStr("MIDI input error: %d, 0x%08X : 0x%08X", wMsg, dwParam1, dwParam2)); break; } } }
MF_API bool MFMidi_OpenInput(MFDevice *pDevice, bool bBuffered, MFMidiEventCallback *pEventCallback) { MFDebug_Assert(pDevice->type == MFDT_MidiInput, "Not a MIDI device!"); if (pDevice->state == MFDevState_Ready || pDevice->state == MFDevState_Active) { MFDebug_Warn(1, "Midi input device already opened!"); return false; } if (pDevice->state != MFDevState_Available) { MFDebug_Warn(1, "Unable to open midi input device!"); return false; } MFMidiPC_MidiInputDevice *pMidi = (MFMidiPC_MidiInputDevice*)pDevice->pInternal; // find and open the device // TODO: FIXME! this won't work if there are 2 instances of the same device attached to the PC!!! UINT numInputDevices = midiInGetNumDevs(); UINT i = 0; for (; i < numInputDevices; ++i) { MIDIINCAPS caps; MMRESULT r = midiInGetDevCaps(i, &caps, sizeof(caps)); if (r != MMSYSERR_NOERROR) continue; if (caps.wMid == pMidi->mid && caps.wPid == pMidi->pid) break; } if (i == numInputDevices) { MFDebug_Warn(1, MFStr("Midi output device '%s' not found!", pDevice->strings[MFDS_ID])); pDevice->state = MFDevState_Unknown; // set this flag? return false; } MMRESULT r = midiInOpen(&pMidi->hMidiIn, i, (DWORD_PTR)MidiInProc, (DWORD_PTR)pDevice, CALLBACK_FUNCTION | MIDI_IO_STATUS); if (r != MMSYSERR_NOERROR) { pMidi->hMidiIn = NULL; pDevice->state = MFDevState_Unknown; wchar_t errorBuffer[256]; midiInGetErrorText(r, errorBuffer, sizeof(errorBuffer)); MFDebug_Warn(1, MFStr("Failed to open MIDI input device: %s", MFString_WCharAsUTF8(errorBuffer))); return false; } MFZeroMemory(&pMidi->sysexRecv, sizeof(pMidi->sysexRecv)); pMidi->sysexRecv.lpData = (LPSTR)pMidi->sysexRecvBuffer; pMidi->sysexRecv.dwBufferLength = sizeof(pMidi->sysexRecvBuffer); r = midiInPrepareHeader(pMidi->hMidiIn, &pMidi->sysexRecv, sizeof(pMidi->sysexRecv)); if (r != MMSYSERR_NOERROR) { wchar_t errorBuffer[256]; midiInGetErrorText(r, errorBuffer, sizeof(errorBuffer)); MFDebug_Warn(1, MFStr("Failed to open MIDI input device: %s", MFString_WCharAsUTF8(errorBuffer))); } r = midiInAddBuffer(pMidi->hMidiIn, &pMidi->sysexRecv, sizeof(pMidi->sysexRecv)); if (r != MMSYSERR_NOERROR) { wchar_t errorBuffer[256]; midiInGetErrorText(r, errorBuffer, sizeof(errorBuffer)); MFDebug_Warn(1, MFStr("Failed to open MIDI input device: %s", MFString_WCharAsUTF8(errorBuffer))); } pMidi->bBuffered = bBuffered; pMidi->pEventCallback = pEventCallback; pMidi->numAllocated = 256; pMidi->pEvents = (MFMidiEvent*)MFHeap_Alloc(sizeof(MFMidiEvent) * pMidi->numAllocated); pDevice->state = MFDevState_Ready; if (!bBuffered && !pEventCallback) MFMidi_Start(pDevice); return true; }