wineoss: Add a temporary midi_out_fm_reset syscall.

Signed-off-by: Huw Davies <huw@codeweavers.com>
Signed-off-by: Andrew Eikum <aeikum@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Huw Davies 2022-04-20 09:04:03 -05:00 committed by Alexandre Julliard
parent bbe19f20a9
commit 5ebc7d78aa
4 changed files with 118 additions and 38 deletions

View file

@ -737,42 +737,6 @@ static int modFMLoad(WORD dev, int fd)
return params.ret;
}
/**************************************************************************
* modFMReset [internal]
*/
static void modFMReset(WORD wDevID)
{
sFMextra* extra = MidiOutDev[wDevID].lpExtra;
sVoice* voice = extra->voice;
sChannel* channel = extra->channel;
int 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);
}
SEQ_KEY_PRESSURE(wDevID, i, 127, 0);
SEQ_CONTROL(wDevID, i, SEQ_VOLMODE, VOL_METHOD_LINEAR);
voice[i].note = 0;
voice[i].channel = -1;
voice[i].cntMark = 0;
voice[i].status = sVS_UNUSED;
}
for (i = 0; i < 16; i++) {
channel[i].program = 0;
channel[i].bender = 8192;
channel[i].benderRange = 2;
channel[i].bank = 0;
channel[i].volume = 127;
channel[i].balance = 64;
channel[i].expression = 0;
channel[i].sustain = 0;
}
extra->counter = 0;
extra->drumSetMask = 1 << 9; /* channel 10 is normally drums, sometimes 16 also */
SEQ_DUMPBUF();
}
#define IS_DRUM_CHANNEL(_xtra, _chn) ((_xtra)->drumSetMask & (1 << (_chn)))
/**************************************************************************
@ -846,7 +810,7 @@ static DWORD modOpen(WORD wDevID, LPMIDIOPENDESC lpDesc, DWORD dwFlags)
HeapFree(GetProcessHeap(), 0, extra);
return MMSYSERR_ERROR;
}
modFMReset(wDevID);
OSS_CALL(midi_out_fm_reset, (void *)(UINT_PTR)wDevID);
}
break;
case MOD_MIDIPORT:
@ -1120,7 +1084,7 @@ static DWORD modData(WORD wDevID, DWORD dwParam)
case MIDI_SYSTEM_PREFIX:
switch (evt & 0x0F) {
case 0x0F: /* Reset */
modFMReset(wDevID);
OSS_CALL(midi_out_fm_reset, (void *)(UINT_PTR)wDevID);
break;
default:
WARN("Unsupported (yet) system event %02x\n", evt & 0x0F);

View file

@ -1409,4 +1409,5 @@ unixlib_entry_t __wine_unix_call_funcs[] =
midi_seq_open,
midi_out_fm_load,
midi_out_fm_reset,
};

View file

@ -52,6 +52,47 @@ static unsigned int num_dests, num_srcs, num_synths, seq_refs;
static struct midi_dest dests[MAX_MIDIOUTDRV];
static struct midi_src srcs[MAX_MIDIINDRV];
typedef struct sVoice
{
int note; /* 0 means not used */
int channel;
unsigned cntMark : 30,
status : 2;
#define sVS_UNUSED 0
#define sVS_PLAYING 1
#define sVS_SUSTAINED 2
} sVoice;
typedef struct sChannel
{
int program;
int bender;
int benderRange;
/* controllers */
int bank; /* CTL_BANK_SELECT */
int volume; /* CTL_MAIN_VOLUME */
int balance; /* CTL_BALANCE */
int expression; /* CTL_EXPRESSION */
int sustain; /* CTL_SUSTAIN */
unsigned char nrgPmtMSB; /* Non register Parameters */
unsigned char nrgPmtLSB;
unsigned char regPmtMSB; /* Non register Parameters */
unsigned char regPmtLSB;
} sChannel;
typedef struct sFMextra
{
unsigned counter;
int drumSetMask;
sChannel channel[16]; /* MIDI has only 16 channels */
sVoice voice[1]; /* dyn allocated according to sound card */
/* do not append fields below voice[1] since the size of this structure
* depends on the number of available voices on the FM synth...
*/
} sFMextra;
WINE_DEFAULT_DEBUG_CHANNEL(midi);
static int oss_to_win_device_type(int type)
@ -346,6 +387,40 @@ wrapup:
return STATUS_SUCCESS;
}
/* FIXME: this is a bad idea, it's even not static... */
SEQ_DEFINEBUF(1024);
/* FIXME: this is not reentrant, not static - because of global variable
* _seqbuf and al.
*/
/**************************************************************************
* seqbuf_dump [internal]
*
* Used by SEQ_DUMPBUF to flush the buffer.
*
*/
void seqbuf_dump(void)
{
int fd;
/* The device is already open, but there's no way to pass the
fd to this function. Rather than rely on a global variable
we pretend to open the seq again. */
fd = seq_open();
if (_seqbufptr)
{
if (write(fd, _seqbuf, _seqbufptr) == -1)
{
WARN("Can't write data to sequencer %d, errno %d (%s)!\n",
fd, errno, strerror(errno));
}
/* FIXME: In any case buffer is lost so that if many errors occur the buffer
* will not overrun */
_seqbufptr = 0;
}
seq_close(fd);
}
extern const unsigned char midiFMInstrumentPatches[16 * 128];
extern const unsigned char midiFMDrumsPatches[16 * 128];
@ -388,3 +463,41 @@ NTSTATUS midi_out_fm_load(void *args)
params->ret = 0;
return STATUS_SUCCESS;
}
NTSTATUS midi_out_fm_reset(void *args)
{
WORD dev_id = (WORD)(UINT_PTR)args;
struct midi_dest *dest = dests + dev_id;
sFMextra *extra = dest->lpExtra;
sVoice *voice = extra->voice;
sChannel *channel = extra->channel;
int i;
for (i = 0; i < dest->caps.wVoices; i++)
{
if (voice[i].status != sVS_UNUSED)
SEQ_STOP_NOTE(dev_id, i, voice[i].note, 64);
SEQ_KEY_PRESSURE(dev_id, i, 127, 0);
SEQ_CONTROL(dev_id, i, SEQ_VOLMODE, VOL_METHOD_LINEAR);
voice[i].note = 0;
voice[i].channel = -1;
voice[i].cntMark = 0;
voice[i].status = sVS_UNUSED;
}
for (i = 0; i < 16; i++)
{
channel[i].program = 0;
channel[i].bender = 8192;
channel[i].benderRange = 2;
channel[i].bank = 0;
channel[i].volume = 127;
channel[i].balance = 64;
channel[i].expression = 0;
channel[i].sustain = 0;
}
extra->counter = 0;
extra->drumSetMask = 1 << 9; /* channel 10 is normally drums, sometimes 16 also */
SEQ_DUMPBUF();
return STATUS_SUCCESS;
}

View file

@ -288,11 +288,13 @@ enum oss_funcs
oss_midi_seq_open, /* temporary */
oss_midi_out_fm_load,
oss_midi_out_fm_reset,
};
NTSTATUS midi_init(void *args) DECLSPEC_HIDDEN;
NTSTATUS midi_seq_open(void *args) DECLSPEC_HIDDEN;
NTSTATUS midi_out_fm_load(void *args) DECLSPEC_HIDDEN;
NTSTATUS midi_out_fm_reset(void *args) DECLSPEC_HIDDEN;
extern unixlib_handle_t oss_handle;