Better support for multiple midi devices on the OSS interface.
This commit is contained in:
parent
2b855deddb
commit
f086286d4f
|
@ -29,6 +29,7 @@
|
|||
#include "config.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#ifdef HAVE_UNISTD_H
|
||||
# include <unistd.h>
|
||||
#endif
|
||||
|
@ -52,7 +53,7 @@ WINE_DEFAULT_DEBUG_CHANNEL(midi);
|
|||
#define MIDI_SEQ "/dev/sequencer"
|
||||
|
||||
typedef struct {
|
||||
int state;
|
||||
int state; /* -1 disabled, 0 is no recording started, 1 in recording, bit 2 set if in sys exclusive recording */
|
||||
DWORD bufsize;
|
||||
MIDIOPENDESC midiDesc;
|
||||
WORD wFlags;
|
||||
|
@ -62,54 +63,37 @@ typedef struct {
|
|||
unsigned char incPrev;
|
||||
char incLen;
|
||||
DWORD startTime;
|
||||
MIDIINCAPSA caps;
|
||||
} WINE_MIDIIN;
|
||||
|
||||
typedef struct {
|
||||
int state;
|
||||
BOOL bEnabled;
|
||||
DWORD bufsize;
|
||||
MIDIOPENDESC midiDesc;
|
||||
WORD wFlags;
|
||||
LPMIDIHDR lpQueueHdr;
|
||||
DWORD dwTotalPlayed;
|
||||
void* lpExtra; /* according to port type (MIDI, FM...), extra data when needed */
|
||||
MIDIOUTCAPSA caps;
|
||||
} WINE_MIDIOUT;
|
||||
|
||||
static WINE_MIDIIN MidiInDev [MAX_MIDIINDRV ];
|
||||
static WINE_MIDIOUT MidiOutDev[MAX_MIDIOUTDRV];
|
||||
|
||||
/* this is the total number of MIDI out devices found */
|
||||
static int MODM_NUMDEVS = 0;
|
||||
/* this is the number of FM synthetizers (index from 0 to
|
||||
NUMFMSYNTHDEVS - 1) */
|
||||
static int MODM_NUMFMSYNTHDEVS = 0;
|
||||
/* this is the number of Midi ports (index from NUMFMSYNTHDEVS to
|
||||
NUMFMSYNTHDEVS + NUMMIDIDEVS - 1) */
|
||||
static int MODM_NUMMIDIDEVS = 0;
|
||||
/* this is the total number of MIDI out devices found (synth and port) */
|
||||
static int MODM_NumDevs = 0;
|
||||
/* this is the number of FM synthetizers (index from 0 to NUMFMSYNTHDEVS - 1) */
|
||||
static int MODM_NumFMSynthDevs = 0;
|
||||
/* the Midi ports have index from NUMFMSYNTHDEVS to NumDevs - 1 */
|
||||
|
||||
/* this is the total number of MIDI out devices found */
|
||||
static int MIDM_NUMDEVS = 0;
|
||||
static int MIDM_NumDevs = 0;
|
||||
|
||||
static int midiSeqFD = -1;
|
||||
static int numOpenMidiSeq = 0;
|
||||
static UINT midiInTimerID = 0;
|
||||
static int numStartedMidiIn = 0;
|
||||
|
||||
/* this structure holds pointers with information for each MIDI
|
||||
* out device found.
|
||||
*/
|
||||
static LPMIDIOUTCAPSA midiOutDevices[MAX_MIDIOUTDRV];
|
||||
|
||||
/* this structure holds pointers with information for each MIDI
|
||||
* in device found.
|
||||
*/
|
||||
static LPMIDIINCAPSA midiInDevices [MAX_MIDIINDRV];
|
||||
|
||||
/*
|
||||
* FIXME : all tests on device ID for midXXX and modYYY are made against
|
||||
* MAX_MIDIxxDRV (when they are made) but should be done against the actual
|
||||
* number of midi devices found...
|
||||
*/
|
||||
|
||||
/*======================================================================*
|
||||
* Low level MIDI implementation *
|
||||
*======================================================================*/
|
||||
|
@ -186,51 +170,51 @@ BOOL OSS_MidiInit(void)
|
|||
}
|
||||
|
||||
for (i = 0; i < numsynthdevs; i++) {
|
||||
LPMIDIOUTCAPSA tmplpCaps;
|
||||
|
||||
sinfo.device = i;
|
||||
status = ioctl(midiSeqFD, SNDCTL_SYNTH_INFO, &sinfo);
|
||||
if (status == -1) {
|
||||
ERR("ioctl for synth info failed.\n");
|
||||
midiCloseSeq();
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
tmplpCaps = HeapAlloc(GetProcessHeap(), 0, sizeof(MIDIOUTCAPSA));
|
||||
if (!tmplpCaps)
|
||||
break;
|
||||
/* We also have the information sinfo.synth_subtype, not used here
|
||||
*/
|
||||
|
||||
/* Manufac ID. We do not have access to this with soundcard.h
|
||||
* Does not seem to be a problem, because in mmsystem.h only
|
||||
* Microsoft's ID is listed.
|
||||
*/
|
||||
tmplpCaps->wMid = 0x00FF;
|
||||
tmplpCaps->wPid = 0x0001; /* FIXME Product ID */
|
||||
MidiOutDev[i].caps.wMid = 0x00FF;
|
||||
MidiOutDev[i].caps.wPid = 0x0001; /* FIXME Product ID */
|
||||
/* Product Version. We simply say "1" */
|
||||
tmplpCaps->vDriverVersion = 0x001;
|
||||
strcpy(tmplpCaps->szPname, sinfo.name);
|
||||
|
||||
tmplpCaps->wTechnology = MIDI_UnixToWindowsDeviceType(sinfo.synth_type);
|
||||
tmplpCaps->wVoices = sinfo.nr_voices;
|
||||
|
||||
/* FIXME Is it possible to know the maximum
|
||||
* number of simultaneous notes of a soundcard ?
|
||||
* I believe we don't have this information, but
|
||||
* it's probably equal or more than wVoices
|
||||
*/
|
||||
tmplpCaps->wNotes = sinfo.nr_voices;
|
||||
tmplpCaps->wChannelMask= 0xFFFF;
|
||||
MidiOutDev[i].caps.vDriverVersion = 0x001;
|
||||
MidiOutDev[i].caps.wChannelMask = 0xFFFF;
|
||||
|
||||
/* FIXME Do we have this information?
|
||||
* Assuming the soundcards can handle
|
||||
* MIDICAPS_VOLUME and MIDICAPS_LRVOLUME but
|
||||
* not MIDICAPS_CACHE.
|
||||
*/
|
||||
tmplpCaps->dwSupport = MIDICAPS_VOLUME|MIDICAPS_LRVOLUME;
|
||||
MidiOutDev[i].caps.dwSupport = MIDICAPS_VOLUME|MIDICAPS_LRVOLUME;
|
||||
|
||||
midiOutDevices[i] = tmplpCaps;
|
||||
sinfo.device = i;
|
||||
status = ioctl(midiSeqFD, SNDCTL_SYNTH_INFO, &sinfo);
|
||||
if (status == -1) {
|
||||
ERR("ioctl for synth info failed on %d, disabling it.\n", i);
|
||||
|
||||
sprintf(MidiOutDev[i].caps.szPname, "Wine OSS Midi Out (#%d) - disabled", i);
|
||||
|
||||
MidiOutDev[i].caps.wTechnology = MOD_MIDIPORT;
|
||||
MidiOutDev[i].caps.wVoices = 16;
|
||||
MidiOutDev[i].caps.wNotes = 16;
|
||||
MidiOutDev[i].bEnabled = FALSE;
|
||||
} else {
|
||||
strcpy(MidiOutDev[i].caps.szPname, sinfo.name);
|
||||
|
||||
MidiOutDev[i].caps.wTechnology = MIDI_UnixToWindowsDeviceType(sinfo.synth_type);
|
||||
MidiOutDev[i].caps.wVoices = sinfo.nr_voices;
|
||||
|
||||
/* FIXME Is it possible to know the maximum
|
||||
* number of simultaneous notes of a soundcard ?
|
||||
* I believe we don't have this information, but
|
||||
* it's probably equal or more than wVoices
|
||||
*/
|
||||
MidiOutDev[i].caps.wNotes = sinfo.nr_voices;
|
||||
MidiOutDev[i].bEnabled = TRUE;
|
||||
}
|
||||
|
||||
/* We also have the information sinfo.synth_subtype, not used here
|
||||
*/
|
||||
|
||||
if (sinfo.capabilities & SYNTH_CAP_INPUT) {
|
||||
FIXME("Synthesizer support MIDI in. Not supported yet (please report)\n");
|
||||
|
@ -238,8 +222,9 @@ BOOL OSS_MidiInit(void)
|
|||
|
||||
TRACE("SynthOut[%d]\tname='%s' techn=%d voices=%d notes=%d chnMsk=%04x support=%ld\n"
|
||||
"\tOSS info: synth subtype=%d capa=%lx\n",
|
||||
i, tmplpCaps->szPname, tmplpCaps->wTechnology, tmplpCaps->wVoices,
|
||||
tmplpCaps->wNotes, tmplpCaps->wChannelMask, tmplpCaps->dwSupport,
|
||||
i, MidiOutDev[i].caps.szPname, MidiOutDev[i].caps.wTechnology,
|
||||
MidiOutDev[i].caps.wVoices, MidiOutDev[i].caps.wNotes,
|
||||
MidiOutDev[i].caps.wChannelMask, MidiOutDev[i].caps.dwSupport,
|
||||
sinfo.synth_subtype, (long)sinfo.capabilities);
|
||||
}
|
||||
|
||||
|
@ -247,8 +232,8 @@ BOOL OSS_MidiInit(void)
|
|||
status = ioctl(midiSeqFD, SNDCTL_SEQ_NRMIDIS, &nummididevs);
|
||||
if (status == -1) {
|
||||
ERR("ioctl on nr midi failed.\n");
|
||||
midiCloseSeq();
|
||||
return TRUE;
|
||||
nummididevs = 0;
|
||||
goto wrapup;
|
||||
}
|
||||
|
||||
/* FIXME: the two restrictions below could be loosen in some cases */
|
||||
|
@ -265,20 +250,10 @@ BOOL OSS_MidiInit(void)
|
|||
}
|
||||
|
||||
for (i = 0; i < nummididevs; i++) {
|
||||
LPMIDIOUTCAPSA tmplpOutCaps;
|
||||
LPMIDIINCAPSA tmplpInCaps;
|
||||
|
||||
minfo.device = i;
|
||||
status = ioctl(midiSeqFD, SNDCTL_MIDI_INFO, &minfo);
|
||||
if (status == -1) {
|
||||
ERR("ioctl on midi info for device %d failed.\n", i);
|
||||
midiCloseSeq();
|
||||
return TRUE;
|
||||
}
|
||||
if (status == -1) WARN("ioctl on midi info for device %d failed.\n", i);
|
||||
|
||||
tmplpOutCaps = HeapAlloc(GetProcessHeap(), 0, sizeof(MIDIOUTCAPSA));
|
||||
if (!tmplpOutCaps)
|
||||
break;
|
||||
/* This whole part is somewhat obscure to me. I'll keep trying to dig
|
||||
info about it. If you happen to know, please tell us. The very
|
||||
descritive minfo.dev_type was not used here.
|
||||
|
@ -286,27 +261,27 @@ BOOL OSS_MidiInit(void)
|
|||
/* Manufac ID. We do not have access to this with soundcard.h
|
||||
Does not seem to be a problem, because in mmsystem.h only
|
||||
Microsoft's ID is listed */
|
||||
tmplpOutCaps->wMid = 0x00FF;
|
||||
tmplpOutCaps->wPid = 0x0001; /* FIXME Product ID */
|
||||
MidiOutDev[numsynthdevs + i].caps.wMid = 0x00FF;
|
||||
MidiOutDev[numsynthdevs + i].caps.wPid = 0x0001; /* FIXME Product ID */
|
||||
/* Product Version. We simply say "1" */
|
||||
tmplpOutCaps->vDriverVersion = 0x001;
|
||||
strcpy(tmplpOutCaps->szPname, minfo.name);
|
||||
|
||||
tmplpOutCaps->wTechnology = MOD_MIDIPORT; /* FIXME Is this right? */
|
||||
MidiOutDev[numsynthdevs + i].caps.vDriverVersion = 0x001;
|
||||
if (status == -1) {
|
||||
sprintf(MidiOutDev[numsynthdevs + i].caps.szPname, "Wine OSS Midi Out (#%d) - disabled", numsynthdevs + i);
|
||||
MidiOutDev[numsynthdevs + i].bEnabled = FALSE;
|
||||
} else {
|
||||
strcpy(MidiOutDev[numsynthdevs + i].caps.szPname, minfo.name);
|
||||
MidiOutDev[numsynthdevs + i].bEnabled = TRUE;
|
||||
}
|
||||
MidiOutDev[numsynthdevs + i].caps.wTechnology = MOD_MIDIPORT; /* FIXME Is this right? */
|
||||
/* Does it make any difference? */
|
||||
tmplpOutCaps->wVoices = 16;
|
||||
MidiOutDev[numsynthdevs + i].caps.wVoices = 16;
|
||||
/* Does it make any difference? */
|
||||
tmplpOutCaps->wNotes = 16;
|
||||
tmplpOutCaps->wChannelMask= 0xFFFF;
|
||||
MidiOutDev[numsynthdevs + i].caps.wNotes = 16;
|
||||
MidiOutDev[numsynthdevs + i].caps.wChannelMask= 0xFFFF;
|
||||
|
||||
/* FIXME Does it make any difference? */
|
||||
tmplpOutCaps->dwSupport = MIDICAPS_VOLUME|MIDICAPS_LRVOLUME;
|
||||
MidiOutDev[numsynthdevs + i].caps.dwSupport = MIDICAPS_VOLUME|MIDICAPS_LRVOLUME;
|
||||
|
||||
midiOutDevices[numsynthdevs + i] = tmplpOutCaps;
|
||||
|
||||
tmplpInCaps = HeapAlloc(GetProcessHeap(), 0, sizeof(MIDIINCAPSA));
|
||||
if (!tmplpInCaps)
|
||||
break;
|
||||
/* This whole part is somewhat obscure to me. I'll keep trying to dig
|
||||
info about it. If you happen to know, please tell us. The very
|
||||
descritive minfo.dev_type was not used here.
|
||||
|
@ -314,33 +289,36 @@ BOOL OSS_MidiInit(void)
|
|||
/* Manufac ID. We do not have access to this with soundcard.h
|
||||
Does not seem to be a problem, because in mmsystem.h only
|
||||
Microsoft's ID is listed */
|
||||
tmplpInCaps->wMid = 0x00FF;
|
||||
tmplpInCaps->wPid = 0x0001; /* FIXME Product ID */
|
||||
MidiInDev[i].caps.wMid = 0x00FF;
|
||||
MidiInDev[i].caps.wPid = 0x0001; /* FIXME Product ID */
|
||||
/* Product Version. We simply say "1" */
|
||||
tmplpInCaps->vDriverVersion = 0x001;
|
||||
strcpy(tmplpInCaps->szPname, minfo.name);
|
||||
|
||||
MidiInDev[i].caps.vDriverVersion = 0x001;
|
||||
if (status == -1) {
|
||||
sprintf(MidiInDev[i].caps.szPname, "Wine OSS Midi In (#%d) - disabled", numsynthdevs + i);
|
||||
MidiInDev[i].state = -1;
|
||||
} else {
|
||||
strcpy(MidiInDev[i].caps.szPname, minfo.name);
|
||||
MidiInDev[i].state = 0;
|
||||
}
|
||||
/* FIXME : could we get better information than that ? */
|
||||
tmplpInCaps->dwSupport = MIDICAPS_VOLUME|MIDICAPS_LRVOLUME;
|
||||
|
||||
midiInDevices[i] = tmplpInCaps;
|
||||
MidiInDev[i].caps.dwSupport = MIDICAPS_VOLUME|MIDICAPS_LRVOLUME;
|
||||
|
||||
TRACE("MidiOut[%d]\tname='%s' techn=%d voices=%d notes=%d chnMsk=%04x support=%ld\n"
|
||||
"MidiIn [%d]\tname='%s' support=%ld\n"
|
||||
"\tOSS info: midi dev-type=%d, capa=%lx\n",
|
||||
i, tmplpOutCaps->szPname, tmplpOutCaps->wTechnology,
|
||||
tmplpOutCaps->wVoices, tmplpOutCaps->wNotes,
|
||||
tmplpOutCaps->wChannelMask, tmplpOutCaps->dwSupport,
|
||||
i, tmplpInCaps->szPname, tmplpInCaps->dwSupport,
|
||||
i, MidiOutDev[numsynthdevs + i].caps.szPname, MidiOutDev[numsynthdevs + i].caps.wTechnology,
|
||||
MidiOutDev[numsynthdevs + i].caps.wVoices, MidiOutDev[numsynthdevs + i].caps.wNotes,
|
||||
MidiOutDev[numsynthdevs + i].caps.wChannelMask, MidiOutDev[numsynthdevs + i].caps.dwSupport,
|
||||
i, MidiInDev[i].caps.szPname, MidiInDev[i].caps.dwSupport,
|
||||
minfo.dev_type, (long)minfo.capabilities);
|
||||
}
|
||||
|
||||
wrapup:
|
||||
/* windows does not seem to differentiate Synth from MIDI devices */
|
||||
MODM_NUMFMSYNTHDEVS = numsynthdevs;
|
||||
MODM_NUMMIDIDEVS = nummididevs;
|
||||
MODM_NUMDEVS = numsynthdevs + nummididevs;
|
||||
MODM_NumFMSynthDevs = numsynthdevs;
|
||||
MODM_NumDevs = numsynthdevs + nummididevs;
|
||||
|
||||
MIDM_NUMDEVS = nummididevs;
|
||||
MIDM_NumDevs = nummididevs;
|
||||
|
||||
/* close file and exit */
|
||||
midiCloseSeq();
|
||||
|
@ -366,8 +344,8 @@ static DWORD MIDI_NotifyClient(UINT wDevID, WORD wMsg,
|
|||
case MOM_OPEN:
|
||||
case MOM_CLOSE:
|
||||
case MOM_DONE:
|
||||
if (wDevID > MAX_MIDIOUTDRV)
|
||||
return MCIERR_INTERNAL;
|
||||
if (wDevID > MODM_NumDevs)
|
||||
return MMSYSERR_BADDEVICEID;
|
||||
|
||||
dwCallBack = MidiOutDev[wDevID].midiDesc.dwCallback;
|
||||
uFlags = MidiOutDev[wDevID].wFlags;
|
||||
|
@ -379,8 +357,8 @@ static DWORD MIDI_NotifyClient(UINT wDevID, WORD wMsg,
|
|||
case MIM_CLOSE:
|
||||
case MIM_DATA:
|
||||
case MIM_ERROR:
|
||||
if (wDevID > MAX_MIDIINDRV)
|
||||
return MCIERR_INTERNAL;
|
||||
if (wDevID > MIDM_NumDevs)
|
||||
return MMSYSERR_BADDEVICEID;
|
||||
|
||||
dwCallBack = MidiInDev[wDevID].midiDesc.dwCallback;
|
||||
uFlags = MidiInDev[wDevID].wFlags;
|
||||
|
@ -389,11 +367,11 @@ static DWORD MIDI_NotifyClient(UINT wDevID, WORD wMsg,
|
|||
break;
|
||||
default:
|
||||
WARN("Unsupported MSW-MIDI message %u\n", wMsg);
|
||||
return MCIERR_INTERNAL;
|
||||
return MMSYSERR_ERROR;
|
||||
}
|
||||
|
||||
return DriverCallback(dwCallBack, uFlags, hDev, wMsg, dwInstance, dwParam1, dwParam2) ?
|
||||
0 : MCIERR_INTERNAL;
|
||||
0 : MMSYSERR_ERROR;
|
||||
}
|
||||
|
||||
static int midi_warn = 1;
|
||||
|
@ -476,12 +454,12 @@ static void midReceiveChar(WORD wDevID, unsigned char value, DWORD dwTime)
|
|||
|
||||
TRACE("Adding %02xh to %d[%d]\n", value, wDevID, MidiInDev[wDevID].incLen);
|
||||
|
||||
if (wDevID >= MAX_MIDIINDRV) {
|
||||
if (wDevID >= MIDM_NumDevs) {
|
||||
WARN("bad devID\n");
|
||||
return;
|
||||
}
|
||||
if (MidiInDev[wDevID].state == 0) {
|
||||
TRACE("input not started, thrown away\n");
|
||||
if (MidiInDev[wDevID].state <= 0) {
|
||||
TRACE("disabled or input not started, thrown away\n");
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -627,10 +605,10 @@ static DWORD midGetDevCaps(WORD wDevID, LPMIDIINCAPSA lpCaps, DWORD dwSize)
|
|||
{
|
||||
TRACE("(%04X, %p, %08lX);\n", wDevID, lpCaps, dwSize);
|
||||
|
||||
if (wDevID >= MIDM_NUMDEVS) return MMSYSERR_BADDEVICEID;
|
||||
if (wDevID >= MIDM_NumDevs) return MMSYSERR_BADDEVICEID;
|
||||
if (lpCaps == NULL) return MMSYSERR_INVALPARAM;
|
||||
|
||||
memcpy(lpCaps, midiInDevices[wDevID], min(dwSize, sizeof(*lpCaps)));
|
||||
memcpy(lpCaps, &MidiInDev[wDevID].caps, min(dwSize, sizeof(*lpCaps)));
|
||||
|
||||
return MMSYSERR_NOERROR;
|
||||
}
|
||||
|
@ -650,10 +628,14 @@ static DWORD midOpen(WORD wDevID, LPMIDIOPENDESC lpDesc, DWORD dwFlags)
|
|||
/* FIXME :
|
||||
* how to check that content of lpDesc is correct ?
|
||||
*/
|
||||
if (wDevID >= MAX_MIDIINDRV) {
|
||||
if (wDevID >= MIDM_NumDevs) {
|
||||
WARN("wDevID too large (%u) !\n", wDevID);
|
||||
return MMSYSERR_BADDEVICEID;
|
||||
}
|
||||
if (MidiInDev[wDevID].state == -1) {
|
||||
WARN("device disabled\n");
|
||||
return MIDIERR_NODEVICE;
|
||||
}
|
||||
if (MidiInDev[wDevID].midiDesc.hMidi != 0) {
|
||||
WARN("device already open !\n");
|
||||
return MMSYSERR_ALLOCATED;
|
||||
|
@ -708,7 +690,7 @@ static DWORD midClose(WORD wDevID)
|
|||
|
||||
TRACE("(%04X);\n", wDevID);
|
||||
|
||||
if (wDevID >= MAX_MIDIINDRV) {
|
||||
if (wDevID >= MIDM_NumDevs) {
|
||||
WARN("wDevID too big (%u) !\n", wDevID);
|
||||
return MMSYSERR_BADDEVICEID;
|
||||
}
|
||||
|
@ -749,6 +731,9 @@ static DWORD midAddBuffer(WORD wDevID, LPMIDIHDR lpMidiHdr, DWORD dwSize)
|
|||
{
|
||||
TRACE("(%04X, %p, %08lX);\n", wDevID, lpMidiHdr, dwSize);
|
||||
|
||||
if (wDevID >= MIDM_NumDevs) return MMSYSERR_BADDEVICEID;
|
||||
if (MidiInDev[wDevID].state == -1) return MIDIERR_NODEVICE;
|
||||
|
||||
if (lpMidiHdr == NULL) return MMSYSERR_INVALPARAM;
|
||||
if (sizeof(MIDIHDR) > dwSize) return MMSYSERR_INVALPARAM;
|
||||
if (lpMidiHdr->dwBufferLength == 0) return MMSYSERR_INVALPARAM;
|
||||
|
@ -794,6 +779,9 @@ static DWORD midUnprepare(WORD wDevID, LPMIDIHDR lpMidiHdr, DWORD dwSize)
|
|||
{
|
||||
TRACE("(%04X, %p, %08lX);\n", wDevID, lpMidiHdr, dwSize);
|
||||
|
||||
if (wDevID >= MIDM_NumDevs) return MMSYSERR_BADDEVICEID;
|
||||
if (MidiInDev[wDevID].state == -1) return MIDIERR_NODEVICE;
|
||||
|
||||
if (dwSize < sizeof(MIDIHDR) || lpMidiHdr == 0 ||
|
||||
lpMidiHdr->lpData == 0 || lpMidiHdr->dwBufferLength >= 0x10000ul)
|
||||
return MMSYSERR_INVALPARAM;
|
||||
|
@ -815,6 +803,9 @@ static DWORD midReset(WORD wDevID)
|
|||
|
||||
TRACE("(%04X);\n", wDevID);
|
||||
|
||||
if (wDevID >= MIDM_NumDevs) return MMSYSERR_BADDEVICEID;
|
||||
if (MidiInDev[wDevID].state == -1) return MIDIERR_NODEVICE;
|
||||
|
||||
while (MidiInDev[wDevID].lpQueueHdr) {
|
||||
MidiInDev[wDevID].lpQueueHdr->dwFlags &= ~MHDR_INQUEUE;
|
||||
MidiInDev[wDevID].lpQueueHdr->dwFlags |= MHDR_DONE;
|
||||
|
@ -837,7 +828,8 @@ static DWORD midStart(WORD wDevID)
|
|||
{
|
||||
TRACE("(%04X);\n", wDevID);
|
||||
|
||||
/* FIXME : should test value of wDevID */
|
||||
if (wDevID >= MIDM_NumDevs) return MMSYSERR_BADDEVICEID;
|
||||
if (MidiInDev[wDevID].state == -1) return MIDIERR_NODEVICE;
|
||||
|
||||
MidiInDev[wDevID].state = 1;
|
||||
MidiInDev[wDevID].startTime = GetTickCount();
|
||||
|
@ -851,7 +843,9 @@ static DWORD midStop(WORD wDevID)
|
|||
{
|
||||
TRACE("(%04X);\n", wDevID);
|
||||
|
||||
/* FIXME : should test value of wDevID */
|
||||
if (wDevID >= MIDM_NumDevs) return MMSYSERR_BADDEVICEID;
|
||||
if (MidiInDev[wDevID].state == -1) return MIDIERR_NODEVICE;
|
||||
|
||||
MidiInDev[wDevID].state = 0;
|
||||
return MMSYSERR_NOERROR;
|
||||
}
|
||||
|
@ -942,7 +936,7 @@ static void modFMReset(WORD wDevID)
|
|||
sChannel* channel = extra->channel;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < midiOutDevices[wDevID]->wVoices; i++) {
|
||||
for (i = 0; i < MidiOutDev[wDevID].caps.wVoices; i++) {
|
||||
if (voice[i].status != sVS_UNUSED) {
|
||||
SEQ_STOP_NOTE(wDevID, i, voice[i].note, 64);
|
||||
}
|
||||
|
@ -977,10 +971,10 @@ static DWORD modGetDevCaps(WORD wDevID, LPMIDIOUTCAPSA lpCaps, DWORD dwSize)
|
|||
{
|
||||
TRACE("(%04X, %p, %08lX);\n", wDevID, lpCaps, dwSize);
|
||||
|
||||
if (wDevID >= MODM_NUMDEVS) return MMSYSERR_BADDEVICEID;
|
||||
if (wDevID >= MODM_NumDevs) return MMSYSERR_BADDEVICEID;
|
||||
if (lpCaps == NULL) return MMSYSERR_INVALPARAM;
|
||||
|
||||
memcpy(lpCaps, midiOutDevices[wDevID], min(dwSize, sizeof(*lpCaps)));
|
||||
memcpy(lpCaps, &MidiOutDev[wDevID].caps, min(dwSize, sizeof(*lpCaps)));
|
||||
|
||||
return MMSYSERR_NOERROR;
|
||||
}
|
||||
|
@ -995,7 +989,7 @@ static DWORD modOpen(WORD wDevID, LPMIDIOPENDESC lpDesc, DWORD dwFlags)
|
|||
WARN("Invalid Parameter !\n");
|
||||
return MMSYSERR_INVALPARAM;
|
||||
}
|
||||
if (wDevID >= MAX_MIDIOUTDRV) {
|
||||
if (wDevID >= MODM_NumDevs) {
|
||||
TRACE("MAX_MIDIOUTDRV reached !\n");
|
||||
return MMSYSERR_BADDEVICEID;
|
||||
}
|
||||
|
@ -1003,23 +997,29 @@ static DWORD modOpen(WORD wDevID, LPMIDIOPENDESC lpDesc, DWORD dwFlags)
|
|||
WARN("device already open !\n");
|
||||
return MMSYSERR_ALLOCATED;
|
||||
}
|
||||
if (!MidiOutDev[wDevID].bEnabled) {
|
||||
WARN("device disabled !\n");
|
||||
return MIDIERR_NODEVICE;
|
||||
}
|
||||
if ((dwFlags & ~CALLBACK_TYPEMASK) != 0) {
|
||||
WARN("bad dwFlags\n");
|
||||
return MMSYSERR_INVALFLAG;
|
||||
}
|
||||
if (midiOutDevices[wDevID] == NULL) {
|
||||
TRACE("un-allocated wDevID\n");
|
||||
return MMSYSERR_BADDEVICEID;
|
||||
if (!MidiOutDev[wDevID].bEnabled) {
|
||||
TRACE("disabled wDevID\n");
|
||||
return MMSYSERR_NOTENABLED;
|
||||
}
|
||||
|
||||
MidiOutDev[wDevID].lpExtra = 0;
|
||||
|
||||
switch (midiOutDevices[wDevID]->wTechnology) {
|
||||
switch (MidiOutDev[wDevID].caps.wTechnology) {
|
||||
case MOD_FMSYNTH:
|
||||
{
|
||||
void* extra = HeapAlloc(GetProcessHeap(), 0,
|
||||
sizeof(struct sFMextra) +
|
||||
sizeof(struct sVoice) * (midiOutDevices[wDevID]->wVoices - 1));
|
||||
void* extra;
|
||||
|
||||
extra = HeapAlloc(GetProcessHeap(), 0,
|
||||
sizeof(struct sFMextra) +
|
||||
sizeof(struct sVoice) * (MidiOutDev[wDevID].caps.wVoices - 1));
|
||||
|
||||
if (extra == 0) {
|
||||
WARN("can't alloc extra data !\n");
|
||||
|
@ -1047,7 +1047,7 @@ static DWORD modOpen(WORD wDevID, LPMIDIOPENDESC lpDesc, DWORD dwFlags)
|
|||
break;
|
||||
default:
|
||||
WARN("Technology not supported (yet) %d !\n",
|
||||
midiOutDevices[wDevID]->wTechnology);
|
||||
MidiOutDev[wDevID].caps.wTechnology);
|
||||
return MMSYSERR_NOTENABLED;
|
||||
}
|
||||
|
||||
|
@ -1088,14 +1088,14 @@ static DWORD modClose(WORD wDevID)
|
|||
return MMSYSERR_ERROR;
|
||||
}
|
||||
|
||||
switch (midiOutDevices[wDevID]->wTechnology) {
|
||||
switch (MidiOutDev[wDevID].caps.wTechnology) {
|
||||
case MOD_FMSYNTH:
|
||||
case MOD_MIDIPORT:
|
||||
midiCloseSeq();
|
||||
break;
|
||||
default:
|
||||
WARN("Technology not supported (yet) %d !\n",
|
||||
midiOutDevices[wDevID]->wTechnology);
|
||||
MidiOutDev[wDevID].caps.wTechnology);
|
||||
return MMSYSERR_NOTENABLED;
|
||||
}
|
||||
|
||||
|
@ -1124,11 +1124,14 @@ static DWORD modData(WORD wDevID, DWORD dwParam)
|
|||
|
||||
TRACE("(%04X, %08lX);\n", wDevID, dwParam);
|
||||
|
||||
if (wDevID >= MODM_NumDevs) return MMSYSERR_BADDEVICEID;
|
||||
if (!MidiOutDev[wDevID].bEnabled) return MIDIERR_NODEVICE;
|
||||
|
||||
if (midiSeqFD == -1) {
|
||||
WARN("can't play !\n");
|
||||
return MIDIERR_NODEVICE;
|
||||
}
|
||||
switch (midiOutDevices[wDevID]->wTechnology) {
|
||||
switch (MidiOutDev[wDevID].caps.wTechnology) {
|
||||
case MOD_FMSYNTH:
|
||||
/* FIXME:
|
||||
* - chorus depth controller is not used
|
||||
|
@ -1142,7 +1145,7 @@ static DWORD modData(WORD wDevID, DWORD dwParam)
|
|||
|
||||
switch (evt & 0xF0) {
|
||||
case MIDI_NOTEOFF:
|
||||
for (i = 0; i < midiOutDevices[wDevID]->wVoices; i++) {
|
||||
for (i = 0; i < MidiOutDev[wDevID].caps.wVoices; i++) {
|
||||
/* don't stop sustained notes */
|
||||
if (voice[i].status == sVS_PLAYING && voice[i].channel == chn && voice[i].note == d1) {
|
||||
voice[i].status = sVS_UNUSED;
|
||||
|
@ -1152,7 +1155,7 @@ static DWORD modData(WORD wDevID, DWORD dwParam)
|
|||
break;
|
||||
case MIDI_NOTEON:
|
||||
if (d2 == 0) { /* note off if velocity == 0 */
|
||||
for (i = 0; i < midiOutDevices[wDevID]->wVoices; i++) {
|
||||
for (i = 0; i < MidiOutDev[wDevID].caps.wVoices; i++) {
|
||||
/* don't stop sustained notes */
|
||||
if (voice[i].status == sVS_PLAYING && voice[i].channel == chn && voice[i].note == d1) {
|
||||
voice[i].status = sVS_UNUSED;
|
||||
|
@ -1166,7 +1169,7 @@ static DWORD modData(WORD wDevID, DWORD dwParam)
|
|||
* - if replaying the same note on the same channel
|
||||
* - the older voice (LRU)
|
||||
*/
|
||||
for (i = nv = 0; i < midiOutDevices[wDevID]->wVoices; i++) {
|
||||
for (i = nv = 0; i < MidiOutDev[wDevID].caps.wVoices; i++) {
|
||||
if (voice[i].status == sVS_UNUSED ||
|
||||
(voice[i].note == d1 && voice[i].channel == chn)) {
|
||||
nv = i;
|
||||
|
@ -1203,7 +1206,7 @@ static DWORD modData(WORD wDevID, DWORD dwParam)
|
|||
voice[nv].cntMark = extra->counter++;
|
||||
break;
|
||||
case MIDI_KEY_PRESSURE:
|
||||
for (i = 0; i < midiOutDevices[wDevID]->wVoices; i++) {
|
||||
for (i = 0; i < MidiOutDev[wDevID].caps.wVoices; i++) {
|
||||
if (voice[i].status != sVS_UNUSED && voice[i].channel == chn && voice[i].note == d1) {
|
||||
SEQ_KEY_PRESSURE(wDevID, i, d1, d2);
|
||||
}
|
||||
|
@ -1217,13 +1220,13 @@ static DWORD modData(WORD wDevID, DWORD dwParam)
|
|||
case CTL_EXPRESSION: channel[chn].expression = d2; break;
|
||||
case CTL_SUSTAIN: channel[chn].sustain = d2;
|
||||
if (d2) {
|
||||
for (i = 0; i < midiOutDevices[wDevID]->wVoices; i++) {
|
||||
for (i = 0; i < MidiOutDev[wDevID].caps.wVoices; i++) {
|
||||
if (voice[i].status == sVS_PLAYING && voice[i].channel == chn) {
|
||||
voice[i].status = sVS_SUSTAINED;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (i = 0; i < midiOutDevices[wDevID]->wVoices; i++) {
|
||||
for (i = 0; i < MidiOutDev[wDevID].caps.wVoices; i++) {
|
||||
if (voice[i].status == sVS_SUSTAINED && voice[i].channel == chn) {
|
||||
voice[i].status = sVS_UNUSED;
|
||||
SEQ_STOP_NOTE(wDevID, i, voice[i].note, 64);
|
||||
|
@ -1240,7 +1243,7 @@ static DWORD modData(WORD wDevID, DWORD dwParam)
|
|||
case 0x0000:
|
||||
if (channel[chn].benderRange != d2) {
|
||||
channel[chn].benderRange = d2;
|
||||
for (i = 0; i < midiOutDevices[wDevID]->wVoices; i++) {
|
||||
for (i = 0; i < MidiOutDev[wDevID].caps.wVoices; i++) {
|
||||
if (voice[i].channel == chn) {
|
||||
SEQ_BENDER_RANGE(wDevID, i, channel[chn].benderRange);
|
||||
}
|
||||
|
@ -1250,7 +1253,7 @@ static DWORD modData(WORD wDevID, DWORD dwParam)
|
|||
|
||||
case 0x7F7F:
|
||||
channel[chn].benderRange = 2;
|
||||
for (i = 0; i < midiOutDevices[wDevID]->wVoices; i++) {
|
||||
for (i = 0; i < MidiOutDev[wDevID].caps.wVoices; i++) {
|
||||
if (voice[i].channel == chn) {
|
||||
SEQ_BENDER_RANGE(wDevID, i, channel[chn].benderRange);
|
||||
}
|
||||
|
@ -1269,7 +1272,7 @@ static DWORD modData(WORD wDevID, DWORD dwParam)
|
|||
/* FIXME: I don't know if I have to take care of the channel
|
||||
* for this control ?
|
||||
*/
|
||||
for (i = 0; i < midiOutDevices[wDevID]->wVoices; i++) {
|
||||
for (i = 0; i < MidiOutDev[wDevID].caps.wVoices; i++) {
|
||||
if (voice[i].status != sVS_UNUSED && voice[i].channel == chn) {
|
||||
voice[i].status = sVS_UNUSED;
|
||||
SEQ_STOP_NOTE(wDevID, i, voice[i].note, 64);
|
||||
|
@ -1280,7 +1283,7 @@ static DWORD modData(WORD wDevID, DWORD dwParam)
|
|||
/* FIXME: I don't know if I have to take care of the channel
|
||||
* for this control ?
|
||||
*/
|
||||
for (i = 0; i < midiOutDevices[wDevID]->wVoices; i++) {
|
||||
for (i = 0; i < MidiOutDev[wDevID].caps.wVoices; i++) {
|
||||
if (voice[i].status == sVS_PLAYING && voice[i].channel == chn) {
|
||||
voice[i].status = sVS_UNUSED;
|
||||
SEQ_STOP_NOTE(wDevID, i, voice[i].note, 64);
|
||||
|
@ -1297,7 +1300,7 @@ static DWORD modData(WORD wDevID, DWORD dwParam)
|
|||
channel[chn].program = d1;
|
||||
break;
|
||||
case MIDI_CHN_PRESSURE:
|
||||
for (i = 0; i < midiOutDevices[wDevID]->wVoices; i++) {
|
||||
for (i = 0; i < MidiOutDev[wDevID].caps.wVoices; i++) {
|
||||
if (voice[i].status != sVS_UNUSED && voice[i].channel == chn) {
|
||||
SEQ_KEY_PRESSURE(wDevID, i, voice[i].note, d1);
|
||||
}
|
||||
|
@ -1305,7 +1308,7 @@ static DWORD modData(WORD wDevID, DWORD dwParam)
|
|||
break;
|
||||
case MIDI_PITCH_BEND:
|
||||
channel[chn].bender = (d2 << 7) + d1;
|
||||
for (i = 0; i < midiOutDevices[wDevID]->wVoices; i++) {
|
||||
for (i = 0; i < MidiOutDev[wDevID].caps.wVoices; i++) {
|
||||
if (voice[i].channel == chn) {
|
||||
SEQ_BENDER(wDevID, i, channel[chn].bender);
|
||||
}
|
||||
|
@ -1328,7 +1331,7 @@ static DWORD modData(WORD wDevID, DWORD dwParam)
|
|||
break;
|
||||
case MOD_MIDIPORT:
|
||||
{
|
||||
int dev = wDevID - MODM_NUMFMSYNTHDEVS;
|
||||
int dev = wDevID - MODM_NumFMSynthDevs;
|
||||
if (dev < 0) {
|
||||
WARN("Internal error on devID (%u) !\n", wDevID);
|
||||
return MIDIERR_NODEVICE;
|
||||
|
@ -1392,7 +1395,7 @@ static DWORD modData(WORD wDevID, DWORD dwParam)
|
|||
break;
|
||||
default:
|
||||
WARN("Technology not supported (yet) %d !\n",
|
||||
midiOutDevices[wDevID]->wTechnology);
|
||||
MidiOutDev[wDevID].caps.wTechnology);
|
||||
return MMSYSERR_NOTENABLED;
|
||||
}
|
||||
|
||||
|
@ -1411,6 +1414,9 @@ static DWORD modLongData(WORD wDevID, LPMIDIHDR lpMidiHdr, DWORD dwSize)
|
|||
|
||||
TRACE("(%04X, %p, %08lX);\n", wDevID, lpMidiHdr, dwSize);
|
||||
|
||||
if (wDevID >= MODM_NumDevs) return MMSYSERR_BADDEVICEID;
|
||||
if (!MidiOutDev[wDevID].bEnabled) return MIDIERR_NODEVICE;
|
||||
|
||||
if (midiSeqFD == -1) {
|
||||
WARN("can't play !\n");
|
||||
return MIDIERR_NODEVICE;
|
||||
|
@ -1441,23 +1447,23 @@ static DWORD modLongData(WORD wDevID, LPMIDIHDR lpMidiHdr, DWORD dwSize)
|
|||
lpData[0], lpData[1], lpData[2], lpData[lpMidiHdr->dwBufferLength-3],
|
||||
lpData[lpMidiHdr->dwBufferLength-2], lpData[lpMidiHdr->dwBufferLength-1]);
|
||||
|
||||
switch (midiOutDevices[wDevID]->wTechnology) {
|
||||
switch (MidiOutDev[wDevID].caps.wTechnology) {
|
||||
case MOD_FMSYNTH:
|
||||
/* FIXME: I don't think there is much to do here */
|
||||
break;
|
||||
case MOD_MIDIPORT:
|
||||
if (lpData[0] != 0xF0) {
|
||||
/* Send end of System Exclusive */
|
||||
SEQ_MIDIOUT(wDevID - MODM_NUMFMSYNTHDEVS, 0xF0);
|
||||
SEQ_MIDIOUT(wDevID - MODM_NumFMSynthDevs, 0xF0);
|
||||
WARN("Adding missing 0xF0 marker at the beginning of "
|
||||
"system exclusive byte stream\n");
|
||||
}
|
||||
for (count = 0; count < lpMidiHdr->dwBytesRecorded; count++) {
|
||||
SEQ_MIDIOUT(wDevID - MODM_NUMFMSYNTHDEVS, lpData[count]);
|
||||
SEQ_MIDIOUT(wDevID - MODM_NumFMSynthDevs, lpData[count]);
|
||||
}
|
||||
if (lpData[count - 1] != 0xF7) {
|
||||
/* Send end of System Exclusive */
|
||||
SEQ_MIDIOUT(wDevID - MODM_NUMFMSYNTHDEVS, 0xF7);
|
||||
SEQ_MIDIOUT(wDevID - MODM_NumFMSynthDevs, 0xF7);
|
||||
WARN("Adding missing 0xF7 marker at the end of "
|
||||
"system exclusive byte stream\n");
|
||||
}
|
||||
|
@ -1465,7 +1471,7 @@ static DWORD modLongData(WORD wDevID, LPMIDIHDR lpMidiHdr, DWORD dwSize)
|
|||
break;
|
||||
default:
|
||||
WARN("Technology not supported (yet) %d !\n",
|
||||
midiOutDevices[wDevID]->wTechnology);
|
||||
MidiOutDev[wDevID].caps.wTechnology);
|
||||
return MMSYSERR_NOTENABLED;
|
||||
}
|
||||
|
||||
|
@ -1537,6 +1543,9 @@ static DWORD modReset(WORD wDevID)
|
|||
|
||||
TRACE("(%04X);\n", wDevID);
|
||||
|
||||
if (wDevID >= MODM_NumDevs) return MMSYSERR_BADDEVICEID;
|
||||
if (!MidiOutDev[wDevID].bEnabled) return MIDIERR_NODEVICE;
|
||||
|
||||
/* stop all notes */
|
||||
/* FIXME: check if 0x78B0 is channel dependant or not. I coded it so that
|
||||
* it's channel dependent...
|
||||
|
@ -1585,7 +1594,7 @@ DWORD WINAPI OSS_midMessage(UINT wDevID, UINT wMsg, DWORD dwUser,
|
|||
case MIDM_GETDEVCAPS:
|
||||
return midGetDevCaps(wDevID, (LPMIDIINCAPSA)dwParam1,dwParam2);
|
||||
case MIDM_GETNUMDEVS:
|
||||
return MIDM_NUMDEVS;
|
||||
return MIDM_NumDevs;
|
||||
case MIDM_RESET:
|
||||
return midReset(wDevID);
|
||||
case MIDM_START:
|
||||
|
@ -1631,7 +1640,7 @@ DWORD WINAPI OSS_modMessage(UINT wDevID, UINT wMsg, DWORD dwUser,
|
|||
case MODM_GETDEVCAPS:
|
||||
return modGetDevCaps(wDevID, (LPMIDIOUTCAPSA)dwParam1, dwParam2);
|
||||
case MODM_GETNUMDEVS:
|
||||
return MODM_NUMDEVS;
|
||||
return MODM_NumDevs;
|
||||
case MODM_GETVOLUME:
|
||||
return 0;
|
||||
case MODM_SETVOLUME:
|
||||
|
|
Loading…
Reference in New Issue