MF_API void MFMidi_SendPacket(MFDevice *pDevice, const uint8 *pBytes, size_t len) { MFMidiPC_MidiOutputDevice *pMidi = (MFMidiPC_MidiOutputDevice*)pDevice->pInternal; // TODO: get hdr from pool... MIDIHDR hdr; MFZeroMemory(&hdr, sizeof(hdr)); hdr.lpData = (LPSTR)pBytes; hdr.dwBufferLength = (DWORD)len; hdr.dwBytesRecorded = (DWORD)len; hdr.dwUser = (DWORD_PTR)pDevice; MMRESULT r = midiOutPrepareHeader(pMidi->hMidiOut, &hdr, sizeof(hdr)); if (r != MMSYSERR_NOERROR) { wchar_t errorBuffer[256]; midiOutGetErrorText(r, errorBuffer, sizeof(errorBuffer)); MFDebug_Warn(1, MFStr("Failed to send MIDI message: %s", MFString_WCharAsUTF8(errorBuffer))); return; } r = midiOutLongMsg(pMidi->hMidiOut, &hdr, sizeof(hdr)); if (r != MMSYSERR_NOERROR) { wchar_t errorBuffer[256]; midiOutGetErrorText(r, errorBuffer, sizeof(errorBuffer)); MFDebug_Warn(1, MFStr("Failed to send MIDI message: %s", MFString_WCharAsUTF8(errorBuffer))); } }
void MidiDriver_WIN::check_error(MMRESULT result) { char buf[200]; if (result != MMSYSERR_NOERROR) { midiOutGetErrorText(result, buf, 200); warning("MM System Error '%s'", buf); } }
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; } } } }
static void CALLBACK MidiOutProc(HMIDIOUT hMidiOut, UINT wMsg, DWORD_PTR dwInstance, DWORD_PTR dwParam1, DWORD_PTR dwParam2) { MFDevice *pDevice = (MFDevice*)dwInstance; MFMidiPC_MidiOutputDevice *pMidi = (MFMidiPC_MidiOutputDevice*)pDevice->pInternal; switch (wMsg) { case MOM_OPEN: MFDebug_Log(0, MFStr("Opened MIDI output device: %s", pDevice->strings[MFDS_ID])); break; case MOM_CLOSE: MFDebug_Log(0, MFStr("Opened MIDI output device: %s", pDevice->strings[MFDS_ID])); break; case MOM_DONE: { MIDIHDR *pHdr = (MIDIHDR*)dwParam1; MMRESULT r = midiOutUnprepareHeader(pMidi->hMidiOut, pHdr, sizeof(*pHdr)); if (r != MMSYSERR_NOERROR) { wchar_t errorBuffer[256]; midiOutGetErrorText(r, errorBuffer, sizeof(errorBuffer)); MFDebug_Warn(1, MFStr("Failed to cleanup MIDI message: %s", MFString_WCharAsUTF8(errorBuffer))); } // TODO: return to pool... break; } case MOM_POSITIONCB: MFDebug_Log(0, "MIDI output device: Position CB"); break; } }
MF_API bool MFMidi_OpenOutput(MFDevice *pDevice) { MFDebug_Assert(pDevice->type == MFDT_MidiOutput, "Not a MIDI device!"); if (pDevice->state == MFDevState_Ready) { MFDebug_Warn(1, "Midi output device already opened!"); return false; } if (pDevice->state != MFDevState_Available) { MFDebug_Warn(1, "Unable to open midi output device!"); return false; } MFMidiPC_MidiOutputDevice *pMidi = (MFMidiPC_MidiOutputDevice*)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 numOutputDevices = midiOutGetNumDevs(); UINT i = 0; for (; i < numOutputDevices; ++i) { MIDIOUTCAPS caps; MMRESULT r = midiOutGetDevCaps(i, &caps, sizeof(caps)); if (r != MMSYSERR_NOERROR) continue; if (caps.wMid == pMidi->mid && caps.wPid == pMidi->pid) break; } if (i == numOutputDevices) { MFDebug_Log(0, MFStr("Midi output device '%s' not found!", pDevice->strings[MFDS_ID])); pDevice->state = MFDevState_Unknown; // set this flag? return false; } MMRESULT r = midiOutOpen(&pMidi->hMidiOut, i, (DWORD_PTR)MidiOutProc, (DWORD_PTR)pDevice, CALLBACK_FUNCTION); if (r != MMSYSERR_NOERROR) { pMidi->hMidiOut = NULL; pDevice->state = MFDevState_Unknown; wchar_t errorBuffer[256]; midiOutGetErrorText(r, errorBuffer, sizeof(errorBuffer)); MFDebug_Warn(1, MFStr("Failed to open MIDI output device: %s", MFString_WCharAsUTF8(errorBuffer))); return false; } pDevice->state = MFDevState_Ready; return true; }
MF_API void MFMidi_SendShortMessage(MFDevice *pDevice, uint32 message) { MFMidiPC_MidiOutputDevice *pMidi = (MFMidiPC_MidiOutputDevice*)pDevice->pInternal; MMRESULT r = midiOutShortMsg(pMidi->hMidiOut, (DWORD)message); if (r != MMSYSERR_NOERROR) { wchar_t errorBuffer[256]; midiOutGetErrorText(r, errorBuffer, sizeof(errorBuffer)); MFDebug_Warn(1, MFStr("Failed to send MIDI message: %s", MFString_WCharAsUTF8(errorBuffer))); } }
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; }
void MidiUartWinClass::midiSendLong(unsigned char *buf, unsigned long len) { MIDIHDR midiHdr; midiHdr.lpData = (CHAR *)buf; midiHdr.dwBufferLength = len; midiHdr.dwFlags = 0; UINT err = midiOutPrepareHeader(outHandle, &midiHdr, sizeof(MIDIHDR)); if (err) { char errBuf[256]; midiOutGetErrorText(err, errBuf, sizeof(errBuf)); printf("error sending long message: %s\n", errBuf); } while (MIDIERR_STILLPLAYING == midiOutUnprepareHeader(outHandle, &midiHdr, sizeof(MIDIHDR))) ; }
static void s_SetMidiError(const char *reason, UINT val) { UINT retVal; char errBuffer[MAXERRORLENGTH]; retVal = midiOutGetErrorText(val, errBuffer, MAXERRORLENGTH); if(retVal == MMSYSERR_NOERROR) { /* Returned OK. Do nothing. */ } else if(retVal == MMSYSERR_BADERRNUM) { sprintf(errBuffer, "Unrecognized MIDI error occurred (%d).", val); } else if(retVal == MMSYSERR_INVALPARAM) { sprintf(errBuffer, "Invalid error parameter found while retrieving error %d.", val); } else { sprintf(errBuffer, "Unknown error occurred while retrieving error %d.", val); } (void)PyErr_Format(PyExc_RuntimeError, "MIDI error encountered while %s: %s", reason, errBuffer); }
void midiSendLong(unsigned char *buf, unsigned long len) { MIDIHDR midiHdr; HANDLE hBuffer; hBuffer = GlobalAlloc(GHND, len); if (!hBuffer) { logPrintf(LOG_ERROR, "error allocating buffer for sysex\n"); return; } midiHdr.lpData = (LPBYTE)GlobalLock(hBuffer); if (midiHdr.lpData) { midiHdr.dwBufferLength = len; midiHdr.dwFlags = 0; debugPrintf(2, "midiSendLong: \n"); debugHexdump(2, buf, len); UINT err = midiOutPrepareHeader(outHandle, &midiHdr, sizeof(MIDIHDR)); if (!err) { memcpy(midiHdr.lpData, buf, len); err = midiOutLongMsg(outHandle, &midiHdr, sizeof(MIDIHDR)); if (err) { char errBuf[256]; midiOutGetErrorText(err, errBuf, sizeof(errBuf)); logPrintf(LOG_ERROR, "error sending long message: %s\n", errBuf); } while (MIDIERR_STILLPLAYING == midiOutUnprepareHeader(outHandle, &midiHdr, sizeof(MIDIHDR))) { ; } debugPrintf(2, "midiSendLong finished\n"); } } GlobalUnlock(hBuffer); GlobalFree(hBuffer); }
/* see comments for winmm_in_close */ static PmError winmm_out_close(PmInternal *midi) { midiwinmm_type m = (midiwinmm_type) midi->descriptor; if (m->handle.out) { /* device to close */ if (midi->latency == 0) { pm_hosterror = midiOutClose(m->handle.out); } else { pm_hosterror = midiStreamClose(m->handle.stream); } /* regardless of outcome, free memory */ winmm_out_delete(midi); } if (pm_hosterror) { int err = midiOutGetErrorText(pm_hosterror, (char *) pm_hosterror_text, PM_HOST_ERROR_MSG_LEN); assert(err == MMSYSERR_NOERROR); return pmHostError; } return pmNoError; }
/* ------------------------- MIDI output -------------------------- */ static void msw_midiouterror(char *s, int err) { char t[256]; midiOutGetErrorText(err, t, 256); fprintf(stderr, s, t); }
static PmError winmm_out_open(PmInternal *midi, void *driverInfo) { DWORD dwDevice; int i = midi->device_id; midiwinmm_type m; MIDIPROPTEMPO propdata; MIDIPROPTIMEDIV divdata; int max_sysex_len = midi->buffer_len * 4; int output_buffer_len; int num_buffers; 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.out = NULL; m->buffers = NULL; m->num_buffers = 0; m->max_buffers = 0; m->buffers_expanded = FALSE; m->next_buffer = 0; m->last_time = 0; m->first_message = TRUE; /* we treat first message as special case */ m->sysex_mode = FALSE; m->sysex_word = 0; m->sysex_byte_count = 0; m->hdr = NULL; m->sync_time = 0; m->delta = 0; m->error = MMSYSERR_NOERROR; /* create a signal */ m->buffer_signal = CreateEvent(NULL, FALSE, FALSE, NULL); /* this should only fail when there are very serious problems */ assert(m->buffer_signal); /* open device */ if (midi->latency == 0) { /* use simple midi out calls */ pm_hosterror = midiOutOpen( (LPHMIDIOUT) & m->handle.out, /* device Handle */ dwDevice, /* device ID */ /* note: same callback fn as for StreamOpen: */ (DWORD_PTR) winmm_streamout_callback, /* callback fn */ (DWORD_PTR) midi, /* callback instance data */ CALLBACK_FUNCTION); /* callback type */ } else { /* use stream-based midi output (schedulable in future) */ pm_hosterror = midiStreamOpen( &m->handle.stream, /* device Handle */ (LPUINT) & dwDevice, /* device ID pointer */ 1, /* reserved, must be 1 */ (DWORD_PTR) winmm_streamout_callback, (DWORD_PTR) midi, /* callback instance data */ CALLBACK_FUNCTION); } if (pm_hosterror != MMSYSERR_NOERROR) { goto free_descriptor; } if (midi->latency == 0) { num_buffers = NUM_SIMPLE_SYSEX_BUFFERS; output_buffer_len = max_sysex_len / num_buffers; if (output_buffer_len < MIN_SIMPLE_SYSEX_LEN) output_buffer_len = MIN_SIMPLE_SYSEX_LEN; } else { long dur = 0; num_buffers = max(midi->buffer_len, midi->latency / 2); if (num_buffers < MIN_STREAM_BUFFERS) num_buffers = MIN_STREAM_BUFFERS; output_buffer_len = STREAM_BUFFER_LEN; propdata.cbStruct = sizeof(MIDIPROPTEMPO); propdata.dwTempo = 480000; /* microseconds per quarter */ pm_hosterror = midiStreamProperty(m->handle.stream, (LPBYTE) & propdata, MIDIPROP_SET | MIDIPROP_TEMPO); if (pm_hosterror) goto close_device; divdata.cbStruct = sizeof(MIDIPROPTEMPO); divdata.dwTimeDiv = 480; /* divisions per quarter */ pm_hosterror = midiStreamProperty(m->handle.stream, (LPBYTE) & divdata, MIDIPROP_SET | MIDIPROP_TIMEDIV); if (pm_hosterror) goto close_device; } /* allocate buffers */ if (allocate_buffers(m, output_buffer_len, num_buffers)) goto free_buffers; /* start device */ if (midi->latency != 0) { pm_hosterror = midiStreamRestart(m->handle.stream); if (pm_hosterror != MMSYSERR_NOERROR) goto free_buffers; } return pmNoError; free_buffers: /* buffers are freed below by winmm_out_delete */ close_device: midiOutClose(m->handle.out); free_descriptor: midi->descriptor = NULL; winmm_out_delete(midi); /* frees buffers and m */ no_memory: if (pm_hosterror) { int err = midiOutGetErrorText(pm_hosterror, (char *) pm_hosterror_text, PM_HOST_ERROR_MSG_LEN); assert(err == MMSYSERR_NOERROR); return pmHostError; } return pmInsufficientMemory; }
static void logMidiOutError (MMRESULT error, int errorLevel, const char *action) { char text[MAXERRORLENGTH]; midiOutGetErrorText(error, text, sizeof(text)); logMessage(errorLevel, "%s error %d: %s", action, error, text); }
void MFMidi_InitModulePlatformSpecific() { UINT numInputDevices = midiInGetNumDevs(); for (UINT i = 0; i < numInputDevices; ++i) { MIDIINCAPS caps; MMRESULT r = midiInGetDevCaps(i, &caps, sizeof(caps)); if (r != MMSYSERR_NOERROR) { wchar_t errorBuffer[256]; midiOutGetErrorText(r, errorBuffer, sizeof(errorBuffer)); MFDebug_Warn(1, MFStr("Failed to query midi input device: %s", MFString_WCharAsUTF8(errorBuffer))); continue; } MFDevice *pDevice = MFDevice_AllocDevice(MFDT_MidiInput, &DestroyInputDevice); pDevice->pInternal = MFHeap_AllocAndZero(sizeof(MFMidiPC_MidiInputDevice)); pDevice->state = MFDevState_Available; MFMidiPC_MidiOutputDevice *pDev = (MFMidiPC_MidiOutputDevice*)pDevice->pInternal; pDev->mid = caps.wMid; pDev->pid = caps.wPid; MFString_CopyUTF16ToUTF8(pDevice->strings[MFDS_ID], caps.szPname); MFString_CopyUTF16ToUTF8(pDevice->strings[MFDS_DeviceName], caps.szPname); MFString_CopyUTF16ToUTF8(pDevice->strings[MFDS_Description], caps.szPname); MFString_CopyUTF16ToUTF8(pDevice->strings[MFDS_InterfaceName], caps.szPname); // MFDS_Manufacturer MFDebug_Log(0, MFStr("Found midi input device: %s (%04X:%04X) - state: %d", pDevice->strings[MFDS_ID], caps.wMid, caps.wPid, pDevice->state)); } UINT numOutputDevices = midiOutGetNumDevs(); for (UINT i = 0; i < numOutputDevices; ++i) { MIDIOUTCAPS caps; MMRESULT r = midiOutGetDevCaps(i, &caps, sizeof(caps)); if (r != MMSYSERR_NOERROR) { wchar_t errorBuffer[256]; midiOutGetErrorText(r, errorBuffer, sizeof(errorBuffer)); MFDebug_Warn(1, MFStr("Failed to query midi output device: %s", MFString_WCharAsUTF8(errorBuffer))); continue; } MFDevice *pDevice = MFDevice_AllocDevice(MFDT_MidiOutput, &DestroyOutputDevice); pDevice->pInternal = MFHeap_AllocAndZero(sizeof(MFMidiPC_MidiOutputDevice)); pDevice->state = MFDevState_Available; MFMidiPC_MidiOutputDevice *pDev = (MFMidiPC_MidiOutputDevice*)pDevice->pInternal; pDev->mid = caps.wMid; pDev->pid = caps.wPid; MFString_CopyUTF16ToUTF8(pDevice->strings[MFDS_ID], caps.szPname); MFString_CopyUTF16ToUTF8(pDevice->strings[MFDS_DeviceName], caps.szPname); MFString_CopyUTF16ToUTF8(pDevice->strings[MFDS_Description], caps.szPname); MFString_CopyUTF16ToUTF8(pDevice->strings[MFDS_InterfaceName], caps.szPname); // MFDS_Manufacturer MFDebug_Log(0, MFStr("Found midi output device: %s (%04X:%04X) - state: %d", pDevice->strings[MFDS_ID], caps.wMid, caps.wPid, pDevice->state)); } }