midi mapper revisited
eric pouech
eric.pouech at wanadoo.fr
Mon May 21 03:34:16 CDT 2001
this patch does two different things:
- it removes the midiIn mapper which doesn't exist under windows
- it adds the ability (for those who have several MIDI output channels
on their sound card(s))
to drive how channels for the mapper will be directed to several midi
out devices
in order no to have error messages, you need to add this key to your
registry
[HKEY_LOCAL_USER\Software\Microsoft\Windows\CurrentVersion\Multimedia\MIDIMap]
989041554
"AutoScheme"=dword:00000000
"CurrentInstrument"="#0"
"UseScheme"=dword:00000000
this will tell the midi mapper to direct all channels to device #0
for more detailed use of the registry settings, read the MM
documentation
A+
--
---------------
Eric Pouech (http://perso.wanadoo.fr/eric.pouech/)
"The future will be better tomorrow", Vice President Dan Quayle
-------------- next part --------------
Name: midimap
ChangeLog: made midi mapper more robust
added channel to device/channel mapping
removed midiIn mapping (it doesn't exist on Windows)
GenDate: 2001/05/21 08:06:25 UTC
ModifiedFiles: dlls/winmm/midimap/midimap.c dlls/winmm/midimap/midimap.drv.spec winedefault.reg
AddedFiles:
===================================================================
RCS file: /usr/share/cvs/cvsroot/wine/wine/dlls/winmm/midimap/midimap.c,v
retrieving revision 1.7
diff -u -u -r1.7 midimap.c
--- dlls/winmm/midimap/midimap.c 2001/01/26 20:43:45 1.7
+++ dlls/winmm/midimap/midimap.c 2001/05/21 07:15:41
@@ -2,250 +2,435 @@
/*
* Wine Midi mapper driver
*
- * Copyright 1999 Eric Pouech
+ * Copyright 1999, 2000, 2001 Eric Pouech
+ *
+ * TODO:
+ * notification has to be implemented
+ * IDF file loading
*/
#include <string.h>
+#include <stdlib.h>
#include "windef.h"
#include "winbase.h"
#include "wingdi.h"
#include "winuser.h"
#include "mmddk.h"
+#include "winreg.h"
#include "debugtools.h"
+/*
+ * Here's how Windows stores the midiOut mapping information.
+ *
+ * Full form (in HKU) is:
+ *
+ * [Software\\Microsoft\\Windows\\CurrentVersion\\Multimedia\\MIDIMap] 988836060
+ * "AutoScheme"=dword:00000000
+ * "ConfigureCount"=dword:00000004
+ * "CurrentInstrument"="Wine OSS midi"
+ * "CurrentScheme"="epp"
+ * "DriverList"=""
+ * "UseScheme"=dword:00000000
+ *
+ * AutoScheme: ?
+ * CurrentInstrument: name of midiOut device to use when UseScheme is 0. Wine uses an extension
+ * of the form #n to link to n'th midiOut device of the system
+ * CurrentScheme: when UseScheme is non null, it's the scheme to use (see below)
+ * DriverList: ?
+ * UseScheme: trigger for simple/complex mapping
+ *
+ * A scheme is defined (in HKLM) as:
+ *
+ * [System\\CurrentControlSet\\Control\\MediaProperties\\PrivateProperties\\Midi\\Schemes\\<nameScheme>]
+ * <nameScheme>: one key for each defined scheme (system wide)
+ * under each one of these <nameScheme> keys, there's:
+ * [...\\<nameScheme>\\<idxDevice>]
+ * "Channels"="<bitMask>"
+ * (the default value of this key also refers to the name of the device).
+ *
+ * this defines, for each midiOut device (identified by its index in <idxDevice>), which
+ * channels have to be mapped onto it. The <bitMask> defines the channels (from 0 to 15)
+ * will be mapped (mapping occurs for channel <ch> if bit <ch> is set in <bitMask>
+ *
+ * Further mapping information can also be defined in:
+ * [System\\CurrentControlSet\\Control\\MediaProperties\\PrivateProperties\\Midi\\Ports\\<nameDevice>\\Instruments\\<idx>]
+ * "Definition"="<.idf file>"
+ * "FriendlyName"="#for .idx file#"
+ * "Port"="<idxPort>"
+ *
+ * This last part isn't implemented (.idf file support).
+ */
+
DEFAULT_DEBUG_CHANNEL(msacm);
-typedef struct tagMIDIMAPDATA {
+typedef struct tagMIDIOUTPORT
+{
+ char name[MAXPNAMELEN];
+ int loaded;
+ HMIDI hMidi;
+ unsigned short uDevID;
+ LPBYTE lpbPatch;
+ unsigned int aChn[16];
+} MIDIOUTPORT;
+
+typedef struct tagMIDIMAPDATA
+{
struct tagMIDIMAPDATA* self;
- HMIDI hMidi;
+ MIDIOUTPORT* ChannelMap[16];
} MIDIMAPDATA;
-static BOOL MIDIMAP_IsData(MIDIMAPDATA* mm)
+static MIDIOUTPORT* midiOutPorts;
+static unsigned numMidiOutPorts;
+
+static BOOL MIDIMAP_IsBadData(MIDIMAPDATA* mm)
{
- return (!IsBadReadPtr(mm, sizeof(MIDIMAPDATA)) && mm->self == mm);
+ if (!IsBadReadPtr(mm, sizeof(MIDIMAPDATA)) && mm->self == mm)
+ return FALSE;
+ TRACE("Bad midimap data (%p)\n", mm);
+ return TRUE;
}
-
-/*======================================================================*
- * MIDI OUT part *
- *======================================================================*/
-static DWORD modOpen(LPDWORD lpdwUser, LPMIDIOPENDESC lpDesc, DWORD dwFlags)
+static BOOL MIDIMAP_FindPort(const char* name, unsigned* dev)
{
- 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;
- }
+ for (*dev = 0; *dev < numMidiOutPorts; (*dev)++)
+ {
+ TRACE("%s\n", midiOutPorts[*dev].name);
+ if (strcmp(midiOutPorts[*dev].name, name) == 0)
+ return TRUE;
}
- HeapFree(GetProcessHeap(), 0, mom);
- return MMSYSERR_ALLOCATED;
+ /* try the form #nnn */
+ if (*name == '#' && isdigit(name[1]))
+ {
+ *dev = atoi(name + 1);
+ if (*dev < numMidiOutPorts)
+ return TRUE;
+ }
+ return FALSE;
}
-static DWORD modClose(MIDIMAPDATA* mom)
+static BOOL MIDIMAP_LoadSettingsDefault(MIDIMAPDATA* mom, const char* port)
{
- DWORD ret = midiOutClose(mom->hMidi);
- if (ret == MMSYSERR_NOERROR)
- HeapFree(GetProcessHeap(), 0, mom);
- return ret;
-}
+ unsigned i, dev = 0;
-static DWORD modLongData(MIDIMAPDATA* mom, LPMIDIHDR lpMidiHdr, DWORD dwParam2)
-{
- return midiOutLongMsg(mom->hMidi, lpMidiHdr, dwParam2);
-}
+ if (port != NULL && !MIDIMAP_FindPort(port, &dev))
+ {
+ ERR("Registry glitch: couldn't find midi out (%s)\n", port);
+ dev = 0;
+ }
+
+ /* sets default */
+ for (i = 0; i < 16; i++) mom->ChannelMap[i] = &midiOutPorts[dev];
-static DWORD modData(MIDIMAPDATA* mom, DWORD dwParam)
-{
- return midiOutShortMsg(mom->hMidi, dwParam);
+ return TRUE;
}
-static DWORD modPrepare(MIDIMAPDATA* mom, LPMIDIHDR lpMidiHdr, DWORD dwParam2)
+static BOOL MIDIMAP_LoadSettingsScheme(MIDIMAPDATA* mom, const char* scheme)
{
- return midiOutPrepareHeader(mom->hMidi, lpMidiHdr, dwParam2);
-}
+ HKEY hSchemesKey, hKey, hPortKey;
+ unsigned i, idx, dev;
+ char buffer[256], port[256];
+ DWORD type, size, mask;
-static DWORD modUnprepare(MIDIMAPDATA* mom, LPMIDIHDR lpMidiHdr, DWORD dwParam2)
-{
- return midiOutUnprepareHeader(mom->hMidi, lpMidiHdr, dwParam2);
-}
+ for (i = 0; i < 16; i++) mom->ChannelMap[i] = NULL;
-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;
+ if (RegOpenKeyA(HKEY_LOCAL_MACHINE,
+ "System\\CurrentControlSet\\Control\\MediaProperties\\PrivateProperties\\Midi\\Schemes",
+ &hSchemesKey))
+ {
+ return FALSE;
+ }
+ if (RegOpenKeyA(hSchemesKey, scheme, &hKey))
+ {
+ RegCloseKey(hSchemesKey);
+ return FALSE;
+ }
- return MMSYSERR_NOERROR;
+ for (idx = 0; !RegEnumKeyA(hKey, idx, buffer, sizeof(buffer)); idx++)
+ {
+ if (RegOpenKeyA(hKey, buffer, &hPortKey)) continue;
+
+ size = sizeof(port);
+ if (RegQueryValueExA(hPortKey, NULL, 0, &type, port, &size)) continue;
+
+ if (!MIDIMAP_FindPort(port, &dev)) continue;
+
+ size = sizeof(mask);
+ if (RegQueryValueExA(hPortKey, "Channels", 0, &type, (void*)&mask, &size))
+ continue;
+
+ for (i = 0; i < 16; i++)
+ {
+ if (mask & (1 << i))
+ {
+ if (mom->ChannelMap[i])
+ ERR("Quirks in registry, channel %u is mapped twice\n", i);
+ mom->ChannelMap[i] = &midiOutPorts[dev];
+ }
+ }
}
- 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;
+ RegCloseKey(hSchemesKey);
+ RegCloseKey(hKey);
+
+ return TRUE;
}
-static DWORD modSetVolume(UINT wDevID, MIDIMAPDATA* mom, DWORD vol)
+static BOOL MIDIMAP_LoadSettings(MIDIMAPDATA* mom)
{
- if (MIDIMAP_IsData(mom))
- return midiOutSetVolume(mom->hMidi, vol);
- return MMSYSERR_ERROR;
-}
+ HKEY hKey;
+ BOOL ret;
-static DWORD modReset(MIDIMAPDATA* mom)
-{
- return midiOutReset(mom->hMidi);
+ if (RegOpenKeyA(HKEY_CURRENT_USER,
+ "Software\\Microsoft\\Windows\\CurrentVersion\\Multimedia\\MIDIMap", &hKey))
+ {
+ ret = MIDIMAP_LoadSettingsDefault(mom, NULL);
+ }
+ else
+ {
+ DWORD type, size, out;
+ char buffer[256];
+
+ ret = 2;
+ size = sizeof(out);
+ if (!RegQueryValueExA(hKey, "UseScheme", 0, &type, (void*)&out, &size) && out)
+ {
+ size = sizeof(buffer);
+ if (!RegQueryValueExA(hKey, "CurrentScheme", 0, &type, buffer, &size))
+ {
+ if (!(ret = MIDIMAP_LoadSettingsScheme(mom, buffer)))
+ ret = MIDIMAP_LoadSettingsDefault(mom, NULL);
+ }
+ else
+ {
+ ERR("Wrong registry: UseScheme is active, but no CurrentScheme found\n");
+ }
+ }
+ if (ret == 2)
+ {
+ size = sizeof(buffer);
+ if (!RegQueryValueExA(hKey, "CurrentInstrument", 0, &type, buffer, &size) && *buffer)
+ {
+ ret = MIDIMAP_LoadSettingsDefault(mom, buffer);
+ }
+ else
+ {
+ ret = MIDIMAP_LoadSettingsDefault(mom, NULL);
+ }
+ }
+ }
+ RegCloseKey(hKey);
+
+ if (TRACE_ON(msacm))
+ {
+ unsigned i;
+
+ for (i = 0; i < 16; i++)
+ {
+ TRACE("chnMap[% 2d] => %d\n",
+ i, mom->ChannelMap[i] ? mom->ChannelMap[i]->uDevID : -1);
+ }
+ }
+ return ret;
}
-/**************************************************************************
- * MIDIMAP_modMessage [sample driver]
- */
-DWORD WINAPI MIDIMAP_modMessage(UINT wDevID, UINT wMsg, DWORD dwUser,
- DWORD dwParam1, DWORD dwParam2)
+static DWORD modOpen(LPDWORD lpdwUser, LPMIDIOPENDESC lpDesc, DWORD dwFlags)
{
- 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;
+ MIDIMAPDATA* mom = HeapAlloc(GetProcessHeap(), 0, sizeof(MIDIMAPDATA));
- case MODM_OPEN: return modOpen ((LPDWORD)dwUser, (LPMIDIOPENDESC)dwParam1,dwParam2);
- case MODM_CLOSE: return modClose ((MIDIMAPDATA*)dwUser);
+ TRACE("(%p %p %08lx\n", lpdwUser, lpDesc, dwFlags);
- 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);
+ if (!mom) return MMSYSERR_NOMEM;
- 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);
+ if (MIDIMAP_LoadSettings(mom))
+ {
+ *lpdwUser = (DWORD)mom;
+ mom->self = mom;
+
+ return MMSYSERR_NOERROR;
}
- return MMSYSERR_NOTSUPPORTED;
+ HeapFree(GetProcessHeap(), 0, mom);
+ return MIDIERR_INVALIDSETUP;
}
-
-/*======================================================================*
- * MIDI IN part *
- *======================================================================*/
-static DWORD midOpen(LPDWORD lpdwUser, LPMIDIOPENDESC lpDesc, DWORD dwFlags)
+static DWORD modClose(MIDIMAPDATA* mom)
{
- UINT nd = midiInGetNumDevs();
- UINT i;
- MIDIMAPDATA* mim = HeapAlloc(GetProcessHeap(), 0, sizeof(MIDIMAPDATA));
+ UINT i;
+ DWORD ret = MMSYSERR_NOERROR;
- TRACE("(%p %p %08lx\n", lpdwUser, lpDesc, dwFlags);
+ if (MIDIMAP_IsBadData(mom)) return MMSYSERR_ERROR;
- 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;
+ for (i = 0; i < 16; i++)
+ {
+ DWORD t;
+ if (mom->ChannelMap[i] && mom->ChannelMap[i]->loaded > 0)
+ {
+ t = midiOutClose(mom->ChannelMap[i]->hMidi);
+ if (t == MMSYSERR_NOERROR)
+ {
+ mom->ChannelMap[i]->loaded = 0;
+ mom->ChannelMap[i]->hMidi = 0;
+ }
+ else if (ret == MMSYSERR_NOERROR)
+ ret = t;
}
}
- 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);
+ HeapFree(GetProcessHeap(), 0, mom);
return ret;
}
-static DWORD midAddBuffer(MIDIMAPDATA* mim, LPMIDIHDR lpMidiHdr, DWORD dwParam2)
+static DWORD modLongData(MIDIMAPDATA* mom, LPMIDIHDR lpMidiHdr, DWORD dwParam2)
{
- return midiInAddBuffer(mim->hMidi, lpMidiHdr, dwParam2);
+ WORD chn;
+ DWORD ret = MMSYSERR_NOERROR;
+ MIDIHDR mh;
+
+ if (MIDIMAP_IsBadData(mom))
+ return MMSYSERR_ERROR;
+
+ mh = *lpMidiHdr;
+ for (chn = 0; chn < 16; chn++)
+ {
+ if (mom->ChannelMap[chn] && mom->ChannelMap[chn]->loaded > 0)
+ {
+ mh.dwFlags = 0;
+ midiOutPrepareHeader(mom->ChannelMap[chn]->hMidi, &mh, sizeof(mh));
+ ret = midiOutLongMsg(mom->ChannelMap[chn]->hMidi, &mh, sizeof(mh));
+ midiOutUnprepareHeader(mom->ChannelMap[chn]->hMidi, &mh, sizeof(mh));
+ if (ret != MMSYSERR_NOERROR) break;
+ }
+ }
+ return ret;
}
-static DWORD midPrepare(MIDIMAPDATA* mim, LPMIDIHDR lpMidiHdr, DWORD dwParam2)
+static DWORD modData(MIDIMAPDATA* mom, DWORD dwParam)
{
- return midiInPrepareHeader(mim->hMidi, lpMidiHdr, dwParam2);
-}
+ BYTE lb = LOBYTE(LOWORD(dwParam));
+ WORD chn = lb & 0x0F;
+ DWORD ret = MMSYSERR_NOERROR;
+
+ if (MIDIMAP_IsBadData(mom))
+ return MMSYSERR_ERROR;
+
+ if (!mom->ChannelMap[chn]) return MMSYSERR_NOERROR;
+
+ switch (lb & 0xF0)
+ {
+ case 0x80:
+ case 0x90:
+ case 0xA0:
+ case 0xB0:
+ case 0xC0:
+ case 0xD0:
+ case 0xE0:
+ if (mom->ChannelMap[chn]->loaded == 0)
+ {
+ if (midiOutOpen(&mom->ChannelMap[chn]->hMidi, mom->ChannelMap[chn]->uDevID,
+ 0L, 0L, CALLBACK_NULL) == MMSYSERR_NOERROR)
+ mom->ChannelMap[chn]->loaded = 1;
+ else
+ mom->ChannelMap[chn]->loaded = -1;
+ /* FIXME: should load here the IDF midi data... and allow channel and
+ * patch mappings
+ */
+ }
+ if (mom->ChannelMap[chn]->loaded > 0)
+ {
+ /* change channel */
+ dwParam &= ~0x0F;
+ dwParam |= mom->ChannelMap[chn]->aChn[chn];
+
+ if ((LOBYTE(LOWORD(dwParam)) & 0xF0) == 0xC0 /* program change */ &&
+ mom->ChannelMap[chn]->lpbPatch)
+ {
+ BYTE patch = HIBYTE(LOWORD(dwParam));
+
+ /* change patch */
+ dwParam &= ~0x0000FF00;
+ dwParam |= mom->ChannelMap[chn]->lpbPatch[patch];
+ }
+ ret = midiOutShortMsg(mom->ChannelMap[chn]->hMidi, dwParam);
+ }
+ break;
+ case 0xF0:
+ for (chn = 0; chn < 16; chn++)
+ {
+ if (mom->ChannelMap[chn]->loaded > 0)
+ ret = midiOutShortMsg(mom->ChannelMap[chn]->hMidi, dwParam);
+ }
+ break;
+ default:
+ FIXME("ooch %lu\n", dwParam);
+ }
-static DWORD midUnprepare(MIDIMAPDATA* mim, LPMIDIHDR lpMidiHdr, DWORD dwParam2)
-{
- return midiInUnprepareHeader(mim->hMidi, lpMidiHdr, dwParam2);
+ return ret;
}
-static DWORD midGetDevCaps(UINT wDevID, MIDIMAPDATA* mim, LPMIDIINCAPSA lpMidiCaps, DWORD dwParam2)
+static DWORD modPrepare(MIDIMAPDATA* mom, LPMIDIHDR lpMidiHdr, 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;
+ if (MIDIMAP_IsBadData(mom)) return MMSYSERR_ERROR;
+ if (lpMidiHdr->dwFlags & (MHDR_ISSTRM|MHDR_PREPARED))
+ return MMSYSERR_INVALPARAM;
- return MMSYSERR_NOERROR;
- }
- ERR("This shouldn't happen\n");
- return MMSYSERR_ERROR;
+ lpMidiHdr->dwFlags |= MHDR_PREPARED;
+ return MMSYSERR_NOERROR;
}
-static DWORD midStop(MIDIMAPDATA* mim)
+static DWORD modUnprepare(MIDIMAPDATA* mom, LPMIDIHDR lpMidiHdr, DWORD dwParam2)
{
- return midiInStop(mim->hMidi);
-}
+ if (MIDIMAP_IsBadData(mom)) return MMSYSERR_ERROR;
+ if ((lpMidiHdr->dwFlags & MHDR_ISSTRM) || !(lpMidiHdr->dwFlags & MHDR_PREPARED))
+ return MMSYSERR_INVALPARAM;
+
+ lpMidiHdr->dwFlags &= ~MHDR_PREPARED;
+ return MMSYSERR_NOERROR;
+}
+
+static DWORD modGetDevCaps(UINT wDevID, MIDIMAPDATA* mom, LPMIDIOUTCAPSA lpMidiCaps, DWORD size)
+{
+ 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 = 0L;
-static DWORD midStart(MIDIMAPDATA* mim)
-{
- return midiInStart(mim->hMidi);
+ return MMSYSERR_NOERROR;
}
-static DWORD midReset(MIDIMAPDATA* mim)
+static DWORD modReset(MIDIMAPDATA* mom)
{
- return midiInReset(mim->hMidi);
+ WORD chn;
+ DWORD ret = MMSYSERR_NOERROR;
+
+ if (MIDIMAP_IsBadData(mom))
+ return MMSYSERR_ERROR;
+
+ for (chn = 0; chn < 16; chn++)
+ {
+ if (mom->ChannelMap[chn] && mom->ChannelMap[chn]->loaded > 0)
+ {
+ ret = midiOutReset(mom->ChannelMap[chn]->hMidi);
+ if (ret != MMSYSERR_NOERROR) break;
+ }
+ }
+ return ret;
}
/**************************************************************************
- * MIDIMAP_midMessage [sample driver]
+ * MIDIMAP_modMessage [sample driver]
*/
-DWORD WINAPI MIDIMAP_midMessage(WORD wDevID, WORD wMsg, DWORD dwUser,
+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) {
+
+ switch (wMsg)
+ {
case DRVM_INIT:
case DRVM_EXIT:
case DRVM_ENABLE:
@@ -253,19 +438,21 @@
/* 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 MODM_OPEN: return modOpen ((LPDWORD)dwUser, (LPMIDIOPENDESC)dwParam1,dwParam2);
+ case MODM_CLOSE: return modClose ((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);
+ 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_RESET: return modReset ((MIDIMAPDATA*)dwUser);
+
+ case MODM_GETDEVCAPS: return modGetDevCaps (wDevID, (MIDIMAPDATA*)dwUser, (LPMIDIOUTCAPSA)dwParam1,dwParam2);
+ case MODM_GETNUMDEVS: return 1;
+ case MODM_GETVOLUME: return MMSYSERR_NOTSUPPORTED;
+ case MODM_SETVOLUME: return MMSYSERR_NOTSUPPORTED;
default:
- FIXME("unknown message %u!\n", wMsg);
+ FIXME("unknown message %d!\n", wMsg);
}
return MMSYSERR_NOTSUPPORTED;
}
@@ -274,18 +461,38 @@
* Driver part *
*======================================================================*/
-static struct WINE_MIDIMAP* oss = NULL;
-
/**************************************************************************
* MIDIMAP_drvOpen [internal]
*/
static DWORD MIDIMAP_drvOpen(LPSTR str)
{
- if (oss)
+ MIDIOUTCAPSA moc;
+ unsigned dev, i;
+
+ if (midiOutPorts)
return 0;
- /* I know, this is ugly, but who cares... */
- oss = (struct WINE_MIDIMAP*)1;
+ numMidiOutPorts = midiOutGetNumDevs();
+ midiOutPorts = HeapAlloc(GetProcessHeap(), 0,
+ numMidiOutPorts * sizeof(MIDIOUTPORT));
+ for (dev = 0; dev < numMidiOutPorts; dev++)
+ {
+ if (midiOutGetDevCapsA((HMIDIOUT)dev, &moc, sizeof(moc)) == 0L)
+ {
+ strcpy(midiOutPorts[dev].name, moc.szPname);
+ midiOutPorts[dev].loaded = 0;
+ midiOutPorts[dev].hMidi = 0;
+ midiOutPorts[dev].uDevID = 0;
+ midiOutPorts[dev].lpbPatch = NULL;
+ for (i = 0; i < 16; i++)
+ midiOutPorts[dev].aChn[i] = i;
+ }
+ else
+ {
+ midiOutPorts[dev].loaded = -1;
+ }
+ }
+
return 1;
}
@@ -294,8 +501,10 @@
*/
static DWORD MIDIMAP_drvClose(DWORD dwDevID)
{
- if (oss) {
- oss = NULL;
+ if (midiOutPorts)
+ {
+ HeapFree(GetProcessHeap(), 0, midiOutPorts);
+ midiOutPorts = NULL;
return 1;
}
return 0;
@@ -310,7 +519,8 @@
/* EPP TRACE("(%08lX, %04X, %08lX, %08lX, %08lX)\n", */
/* EPP dwDevID, hDriv, wMsg, dwParam1, dwParam2); */
- switch(wMsg) {
+ switch (wMsg)
+ {
case DRV_LOAD: return 1;
case DRV_FREE: return 1;
case DRV_OPEN: return MIDIMAP_drvOpen((LPSTR)dwParam1);
Index: dlls/winmm/midimap/midimap.drv.spec
===================================================================
RCS file: /usr/share/cvs/cvsroot/wine/wine/dlls/winmm/midimap/midimap.drv.spec,v
retrieving revision 1.3
diff -u -u -r1.3 midimap.drv.spec
--- dlls/winmm/midimap/midimap.drv.spec 2000/11/05 04:53:18 1.3
+++ dlls/winmm/midimap/midimap.drv.spec 2000/11/14 07:20:59
@@ -4,11 +4,11 @@
import winmm.dll
import user32.dll
+import advapi32.dll
import kernel32.dll
import ntdll.dll
debug_channels (msacm)
@ stdcall DriverProc(long long long long long) MIDIMAP_DriverProc
-@ stdcall midMessage(long long long long long) MIDIMAP_midMessage
@ stdcall modMessage(long long long long long) MIDIMAP_modMessage
Index: winedefault.reg
===================================================================
RCS file: /usr/share/cvs/cvsroot/wine/wine/winedefault.reg,v
retrieving revision 1.23
diff -u -u -r1.23 winedefault.reg
--- winedefault.reg 2001/05/10 03:10:06 1.23
+++ winedefault.reg 2001/05/21 08:03:08
@@ -155,6 +155,16 @@
"ThreadingModel"="Both"
#
+# Entries for Multimedia
+#
+
+# Midi Mapper
+[HKEY_LOCAL_USER\Software\Microsoft\Windows\CurrentVersion\Multimedia\MIDIMap] 989041554
+"AutoScheme"=dword:00000000
+"CurrentInstrument"="#0"
+"UseScheme"=dword:00000000
+
+#
# Entries for IWebBrowser
# Used by Internet Explorer HTML-rendering control
#
More information about the wine-patches
mailing list