예제 #1
0
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)));
	}
}
예제 #2
0
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;
}
예제 #3
0
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;
	}
}
예제 #4
0
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;
}
예제 #5
0
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)));
	}
}
예제 #6
0
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;
		}
	}
}
예제 #7
0
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;
}
예제 #8
0
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));
	}
}
예제 #9
0
const char* MFFileNative_MakeAbsolute(const char *pFilename)
{
	wchar_t path[256];
	GetFullPathName(MFString_UFT8AsWChar(pFilename), sizeof(path)/sizeof(path[0]), path, NULL);
	return MFString_WCharAsUTF8(path);
}