/* -*- tab-width: 8; c-basic-offset: 4 -*- */ /* * Wine Midi mapper driver * * Copyright 1999 Eric Pouech */ #include "windef.h" #include "wingdi.h" #include "winuser.h" #include "mmddk.h" #include "debugtools.h" DEFAULT_DEBUG_CHANNEL(msacm) typedef struct tagMIDIMAPDATA { struct tagMIDIMAPDATA* self; HMIDI hMidi; } MIDIMAPDATA; static BOOL MIDIMAP_IsData(MIDIMAPDATA* mm) { return (!IsBadReadPtr(mm, sizeof(MIDIMAPDATA)) && mm->self == mm); } /*======================================================================* * MIDI OUT part * *======================================================================*/ static DWORD modOpen(LPDWORD lpdwUser, LPMIDIOPENDESC lpDesc, DWORD dwFlags) { UINT nd = midiOutGetNumDevs(); UINT i; MIDIMAPDATA* mom = HeapAlloc(GetProcessHeap(), 0, sizeof(MIDIMAPDATA)); TRACE("(%p %p %08lx\n", lpdwUser, lpDesc, dwFlags); for (i = 0; i < nd; i++) { if (midiOutOpen(&mom->hMidi, i, lpDesc->dwCallback, lpDesc->dwInstance, dwFlags) == MMSYSERR_NOERROR) { lpDesc->hMidi = mom->hMidi; *lpdwUser = (DWORD)mom; return MMSYSERR_NOERROR; } } HeapFree(GetProcessHeap(), 0, mom); return MMSYSERR_ALLOCATED; } static DWORD modClose(MIDIMAPDATA* mom) { DWORD ret = midiOutClose(mom->hMidi); if (ret == MMSYSERR_NOERROR) HeapFree(GetProcessHeap(), 0, mom); return ret; } static DWORD modLongData(MIDIMAPDATA* mom, LPMIDIHDR lpMidiHdr, DWORD dwParam2) { return midiOutLongMsg(mom->hMidi, lpMidiHdr, dwParam2); } static DWORD modData(MIDIMAPDATA* mom, DWORD dwParam) { return midiOutShortMsg(mom->hMidi, dwParam); } static DWORD modPrepare(MIDIMAPDATA* mom, LPMIDIHDR lpMidiHdr, DWORD dwParam2) { return midiOutPrepareHeader(mom->hMidi, lpMidiHdr, dwParam2); } static DWORD modUnprepare(MIDIMAPDATA* mom, LPMIDIHDR lpMidiHdr, DWORD dwParam2) { return midiOutUnprepareHeader(mom->hMidi, lpMidiHdr, dwParam2); } static DWORD modGetDevCaps(UINT wDevID, MIDIMAPDATA* mom, LPMIDIOUTCAPSA lpMidiCaps, DWORD dwParam2) { /* if opened low driver, forward message */ if (MIDIMAP_IsData(mom)) return midiOutGetDevCapsA(mom->hMidi, lpMidiCaps, dwParam2); /* otherwise, return caps of mapper itself */ if (wDevID == (UINT)-1 || wDevID == (UINT16)-1) { lpMidiCaps->wMid = 0x00FF; lpMidiCaps->wPid = 0x0001; lpMidiCaps->vDriverVersion = 0x0100; strcpy(lpMidiCaps->szPname, "Wine midi out mapper"); lpMidiCaps->wTechnology = MOD_MAPPER; lpMidiCaps->wVoices = 0; lpMidiCaps->wNotes = 0; lpMidiCaps->wChannelMask = 0xFFFF; lpMidiCaps->dwSupport = MIDICAPS_LRVOLUME | MIDICAPS_VOLUME; return MMSYSERR_NOERROR; } ERR("This shouldn't happen\n"); return MMSYSERR_ERROR; } static DWORD modGetVolume(UINT wDevID, MIDIMAPDATA* mom, LPDWORD lpVol) { if (MIDIMAP_IsData(mom)) return midiOutGetVolume(mom->hMidi, lpVol); return MMSYSERR_ERROR; } static DWORD modSetVolume(UINT wDevID, MIDIMAPDATA* mom, DWORD vol) { if (MIDIMAP_IsData(mom)) return midiOutSetVolume(mom->hMidi, vol); return MMSYSERR_ERROR; } static DWORD modReset(MIDIMAPDATA* mom) { return midiOutReset(mom->hMidi); } /************************************************************************** * MIDIMAP_modMessage [sample driver] */ DWORD WINAPI MIDIMAP_modMessage(UINT wDevID, UINT wMsg, DWORD dwUser, DWORD dwParam1, DWORD dwParam2) { TRACE("(%u, %04X, %08lX, %08lX, %08lX);\n", wDevID, wMsg, dwUser, dwParam1, dwParam2); switch (wMsg) { case DRVM_INIT: case DRVM_EXIT: case DRVM_ENABLE: case DRVM_DISABLE: /* FIXME: Pretend this is supported */ return 0; case MODM_OPEN: return modOpen ((LPDWORD)dwUser, (LPMIDIOPENDESC)dwParam1,dwParam2); case MODM_CLOSE: return modClose ((MIDIMAPDATA*)dwUser); case MODM_DATA: return modData ((MIDIMAPDATA*)dwUser, dwParam1); case MODM_LONGDATA: return modLongData ((MIDIMAPDATA*)dwUser, (LPMIDIHDR)dwParam1, dwParam2); case MODM_PREPARE: return modPrepare ((MIDIMAPDATA*)dwUser, (LPMIDIHDR)dwParam1, dwParam2); case MODM_UNPREPARE: return modUnprepare ((MIDIMAPDATA*)dwUser, (LPMIDIHDR)dwParam1, dwParam2); case MODM_GETDEVCAPS: return modGetDevCaps (wDevID, (MIDIMAPDATA*)dwUser, (LPMIDIOUTCAPSA)dwParam1,dwParam2); case MODM_GETNUMDEVS: return 1; case MODM_GETVOLUME: return modGetVolume (wDevID, (MIDIMAPDATA*)dwUser, (LPDWORD)dwParam1); case MODM_SETVOLUME: return modSetVolume (wDevID, (MIDIMAPDATA*)dwUser, dwParam1); case MODM_RESET: return modReset ((MIDIMAPDATA*)dwUser); default: FIXME("unknown message %d!\n", wMsg); } return MMSYSERR_NOTSUPPORTED; } /*======================================================================* * MIDI IN part * *======================================================================*/ static DWORD midOpen(LPDWORD lpdwUser, LPMIDIOPENDESC lpDesc, DWORD dwFlags) { UINT nd = midiInGetNumDevs(); UINT i; MIDIMAPDATA* mim = HeapAlloc(GetProcessHeap(), 0, sizeof(MIDIMAPDATA)); TRACE("(%p %p %08lx\n", lpdwUser, lpDesc, dwFlags); for (i = 0; i < nd; i++) { if (midiInOpen(&mim->hMidi, i, lpDesc->dwCallback, lpDesc->dwInstance, dwFlags) == MMSYSERR_NOERROR) { lpDesc->hMidi = mim->hMidi; *lpdwUser = (DWORD)mim; return MMSYSERR_NOERROR; } } HeapFree(GetProcessHeap(), 0, mim); return MMSYSERR_ALLOCATED; } static DWORD midClose(MIDIMAPDATA* mim) { DWORD ret = midiInClose(mim->hMidi); if (ret == MMSYSERR_NOERROR) HeapFree(GetProcessHeap(), 0, mim); return ret; } static DWORD midAddBuffer(MIDIMAPDATA* mim, LPMIDIHDR lpMidiHdr, DWORD dwParam2) { return midiInAddBuffer(mim->hMidi, lpMidiHdr, dwParam2); } static DWORD midPrepare(MIDIMAPDATA* mim, LPMIDIHDR lpMidiHdr, DWORD dwParam2) { return midiInPrepareHeader(mim->hMidi, lpMidiHdr, dwParam2); } static DWORD midUnprepare(MIDIMAPDATA* mim, LPMIDIHDR lpMidiHdr, DWORD dwParam2) { return midiInUnprepareHeader(mim->hMidi, lpMidiHdr, dwParam2); } static DWORD midGetDevCaps(UINT wDevID, MIDIMAPDATA* mim, LPMIDIINCAPSA lpMidiCaps, DWORD dwParam2) { /* if opened low driver, forward message */ if (MIDIMAP_IsData(mim)) return midiInGetDevCapsA(mim->hMidi, lpMidiCaps, dwParam2); /* otherwise, return caps of mapper itself */ if (wDevID == (UINT)-1 || wDevID == (UINT16)-1) { lpMidiCaps->wMid = 0x00FF; lpMidiCaps->wPid = 0x0001; lpMidiCaps->vDriverVersion = 0x0100; strcpy(lpMidiCaps->szPname, "Wine midi int mapper"); lpMidiCaps->dwSupport = 0; return MMSYSERR_NOERROR; } ERR("This shouldn't happen\n"); return MMSYSERR_ERROR; } static DWORD midStop(MIDIMAPDATA* mim) { return midiInStop(mim->hMidi); } static DWORD midStart(MIDIMAPDATA* mim) { return midiInStart(mim->hMidi); } static DWORD midReset(MIDIMAPDATA* mim) { return midiInReset(mim->hMidi); } /************************************************************************** * MIDIMAP_midMessage [sample driver] */ DWORD WINAPI MIDIMAP_midMessage(WORD wDevID, WORD wMsg, DWORD dwUser, DWORD dwParam1, DWORD dwParam2) { TRACE("(%u, %04X, %08lX, %08lX, %08lX);\n", wDevID, wMsg, dwUser, dwParam1, dwParam2); switch (wMsg) { case DRVM_INIT: case DRVM_EXIT: case DRVM_ENABLE: case DRVM_DISABLE: /* FIXME: Pretend this is supported */ return 0; case MIDM_OPEN: return midOpen ((LPDWORD)dwUser, (LPMIDIOPENDESC)dwParam1, dwParam2); case MIDM_CLOSE: return midClose ((MIDIMAPDATA*)dwUser); case MIDM_ADDBUFFER: return midAddBuffer ((MIDIMAPDATA*)dwUser, (LPMIDIHDR)dwParam1, dwParam2); case MIDM_PREPARE: return midPrepare ((MIDIMAPDATA*)dwUser, (LPMIDIHDR)dwParam1, dwParam2); case MIDM_UNPREPARE: return midUnprepare ((MIDIMAPDATA*)dwUser, (LPMIDIHDR)dwParam1, dwParam2); case MIDM_GETDEVCAPS: return midGetDevCaps (wDevID, (MIDIMAPDATA*)dwUser, (LPMIDIINCAPSA)dwParam1, dwParam2); case MIDM_GETNUMDEVS: return 1; case MIDM_RESET: return midReset ((MIDIMAPDATA*)dwUser); case MIDM_START: return midStart ((MIDIMAPDATA*)dwUser); case MIDM_STOP: return midStop ((MIDIMAPDATA*)dwUser); default: FIXME("unknown message %u!\n", wMsg); } return MMSYSERR_NOTSUPPORTED; } /*======================================================================* * Driver part * *======================================================================*/ static struct WINE_MIDIMAP* oss = NULL; /************************************************************************** * MIDIMAP_drvOpen [internal] */ static DWORD MIDIMAP_drvOpen(LPSTR str) { if (oss) return 0; /* I know, this is ugly, but who cares... */ oss = (struct WINE_MIDIMAP*)1; return 1; } /************************************************************************** * MIDIMAP_drvClose [internal] */ static DWORD MIDIMAP_drvClose(DWORD dwDevID) { if (oss) { oss = NULL; return 1; } return 0; } /************************************************************************** * MIDIMAP_DriverProc [internal] */ LONG CALLBACK MIDIMAP_DriverProc(DWORD dwDevID, HDRVR hDriv, DWORD wMsg, DWORD dwParam1, DWORD dwParam2) { /* EPP TRACE("(%08lX, %04X, %08lX, %08lX, %08lX)\n", */ /* EPP dwDevID, hDriv, wMsg, dwParam1, dwParam2); */ switch(wMsg) { case DRV_LOAD: return 1; case DRV_FREE: return 1; case DRV_OPEN: return MIDIMAP_drvOpen((LPSTR)dwParam1); case DRV_CLOSE: return MIDIMAP_drvClose(dwDevID); case DRV_ENABLE: return 1; case DRV_DISABLE: return 1; case DRV_QUERYCONFIGURE: return 1; case DRV_CONFIGURE: MessageBoxA(0, "MIDIMAP MultiMedia Driver !", "OSS Driver", MB_OK); return 1; case DRV_INSTALL: return DRVCNF_RESTART; case DRV_REMOVE: return DRVCNF_RESTART; default: return DefDriverProc(dwDevID, hDriv, wMsg, dwParam1, dwParam2); } }