[PATCH 2/4] wineoss: Move MODM_DATA to the unixlib.
Andrew Eikum
aeikum at codeweavers.com
Thu Apr 21 08:42:18 CDT 2022
Signed-off-by: Andrew Eikum <aeikum at codeweavers.com>
On Thu, Apr 21, 2022 at 07:52:16AM +0100, Huw Davies wrote:
> Signed-off-by: Huw Davies <huw at codeweavers.com>
> ---
> dlls/wineoss.drv/midi.c | 338 +------------------------------------
> dlls/wineoss.drv/oss.c | 1 -
> dlls/wineoss.drv/ossmidi.c | 301 ++++++++++++++++++++++++++++++++-
> dlls/wineoss.drv/unixlib.h | 9 -
> 4 files changed, 301 insertions(+), 348 deletions(-)
>
> diff --git a/dlls/wineoss.drv/midi.c b/dlls/wineoss.drv/midi.c
> index 70bc4b7b9bd..1751af2349e 100644
> --- a/dlls/wineoss.drv/midi.c
> +++ b/dlls/wineoss.drv/midi.c
> @@ -692,46 +692,6 @@ static DWORD midStop(WORD wDevID)
>
> /*-----------------------------------------------------------------------*/
>
> -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;
> -
> -#define IS_DRUM_CHANNEL(_xtra, _chn) ((_xtra)->drumSetMask & (1 << (_chn)))
> -
> /**************************************************************************
> * modGetDevCaps [internal]
> */
> @@ -747,295 +707,6 @@ static DWORD modGetDevCaps(WORD wDevID, LPMIDIOUTCAPSW lpCaps, DWORD dwSize)
> return MMSYSERR_NOERROR;
> }
>
> -static UINT midi_out_fm_data(WORD dev_id, UINT data)
> -{
> - struct midi_dest *dest = MidiOutDev + dev_id;
> - WORD evt = LOBYTE(LOWORD(data));
> - WORD d1 = HIBYTE(LOWORD(data));
> - WORD d2 = LOBYTE(HIWORD(data));
> - sFMextra *extra = dest->lpExtra;
> - sVoice *voice = extra->voice;
> - sChannel *channel = extra->channel;
> - int chn = (evt & 0x0F), i, nv;
> -
> - /* FIXME: chorus depth controller is not used */
> -
> - switch (evt & 0xF0)
> - {
> - case MIDI_NOTEOFF:
> - for (i = 0; i < dest->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;
> - SEQ_STOP_NOTE(dev_id, i, d1, d2);
> - }
> - }
> - break;
> - case MIDI_NOTEON:
> - if (d2 == 0) /* note off if velocity == 0 */
> - {
> - for (i = 0; i < dest->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;
> - SEQ_STOP_NOTE(dev_id, i, d1, 64);
> - }
> - }
> - break;
> - }
> - /* finding out in this order :
> - * - an empty voice
> - * - if replaying the same note on the same channel
> - * - the older voice (LRU)
> - */
> - for (i = nv = 0; i < dest->caps.wVoices; i++)
> - {
> - if (voice[i].status == sVS_UNUSED || (voice[i].note == d1 && voice[i].channel == chn))
> - {
> - nv = i;
> - break;
> - }
> - if (voice[i].cntMark < voice[0].cntMark)
> - nv = i;
> - }
> - TRACE("playing on voice=%d, pgm=%d, pan=0x%02X, vol=0x%02X, bender=0x%02X, note=0x%02X, vel=0x%02X\n",
> - nv, channel[chn].program, channel[chn].balance, channel[chn].volume, channel[chn].bender, d1, d2);
> -
> - SEQ_SET_PATCH(dev_id, nv, IS_DRUM_CHANNEL(extra, chn) ?
> - (128 + d1) : channel[chn].program);
> - SEQ_BENDER_RANGE(dev_id, nv, channel[chn].benderRange * 100);
> - SEQ_BENDER(dev_id, nv, channel[chn].bender);
> - SEQ_CONTROL(dev_id, nv, CTL_PAN, channel[chn].balance);
> - SEQ_CONTROL(dev_id, nv, CTL_EXPRESSION, channel[chn].expression);
> - SEQ_START_NOTE(dev_id, nv, d1, d2);
> - voice[nv].status = channel[chn].sustain ? sVS_SUSTAINED : sVS_PLAYING;
> - voice[nv].note = d1;
> - voice[nv].channel = chn;
> - voice[nv].cntMark = extra->counter++;
> - break;
> - case MIDI_KEY_PRESSURE:
> - for (i = 0; i < dest->caps.wVoices; i++)
> - if (voice[i].status != sVS_UNUSED && voice[i].channel == chn && voice[i].note == d1)
> - SEQ_KEY_PRESSURE(dev_id, i, d1, d2);
> - break;
> - case MIDI_CTL_CHANGE:
> - switch (d1)
> - {
> - case CTL_BANK_SELECT: channel[chn].bank = d2; break;
> - case CTL_MAIN_VOLUME: channel[chn].volume = d2; break;
> - case CTL_PAN: channel[chn].balance = d2; break;
> - case CTL_EXPRESSION: channel[chn].expression = d2; break;
> - case CTL_SUSTAIN: channel[chn].sustain = d2;
> - if (d2)
> - {
> - for (i = 0; i < dest->caps.wVoices; i++)
> - if (voice[i].status == sVS_PLAYING && voice[i].channel == chn)
> - voice[i].status = sVS_SUSTAINED;
> - }
> - else
> - {
> - for (i = 0; i < dest->caps.wVoices; i++)
> - {
> - if (voice[i].status == sVS_SUSTAINED && voice[i].channel == chn)
> - {
> - voice[i].status = sVS_UNUSED;
> - SEQ_STOP_NOTE(dev_id, i, voice[i].note, 64);
> - }
> - }
> - }
> - break;
> - case CTL_NONREG_PARM_NUM_LSB: channel[chn].nrgPmtLSB = d2; break;
> - case CTL_NONREG_PARM_NUM_MSB: channel[chn].nrgPmtMSB = d2; break;
> - case CTL_REGIST_PARM_NUM_LSB: channel[chn].regPmtLSB = d2; break;
> - case CTL_REGIST_PARM_NUM_MSB: channel[chn].regPmtMSB = d2; break;
> - case CTL_DATA_ENTRY:
> - switch ((channel[chn].regPmtMSB << 8) | channel[chn].regPmtLSB)
> - {
> - case 0x0000:
> - if (channel[chn].benderRange != d2)
> - {
> - channel[chn].benderRange = d2;
> - for (i = 0; i < dest->caps.wVoices; i++)
> - if (voice[i].channel == chn)
> - SEQ_BENDER_RANGE(dev_id, i, channel[chn].benderRange);
> - }
> - break;
> -
> - case 0x7F7F:
> - channel[chn].benderRange = 2;
> - for (i = 0; i < dest->caps.wVoices; i++)
> - if (voice[i].channel == chn)
> - SEQ_BENDER_RANGE(dev_id, i, channel[chn].benderRange);
> - break;
> - default:
> - TRACE("Data entry: regPmt=0x%02x%02x, nrgPmt=0x%02x%02x with %x\n",
> - channel[chn].regPmtMSB, channel[chn].regPmtLSB,
> - channel[chn].nrgPmtMSB, channel[chn].nrgPmtLSB, d2);
> - break;
> - }
> - break;
> -
> - case 0x78: /* all sounds off */
> - /* FIXME: I don't know if I have to take care of the channel for this control? */
> - for (i = 0; i < dest->caps.wVoices; i++)
> - {
> - if (voice[i].status != sVS_UNUSED && voice[i].channel == chn)
> - {
> - voice[i].status = sVS_UNUSED;
> - SEQ_STOP_NOTE(dev_id, i, voice[i].note, 64);
> - }
> - }
> - break;
> - case 0x7B: /* all notes off */
> - /* FIXME: I don't know if I have to take care of the channel for this control? */
> - for (i = 0; i < dest->caps.wVoices; i++)
> - {
> - if (voice[i].status == sVS_PLAYING && voice[i].channel == chn)
> - {
> - voice[i].status = sVS_UNUSED;
> - SEQ_STOP_NOTE(dev_id, i, voice[i].note, 64);
> - }
> - }
> - break;
> - default:
> - TRACE("Dropping MIDI control event 0x%02x(%02x) on channel %d\n", d1, d2, chn);
> - break;
> - }
> - break;
> - case MIDI_PGM_CHANGE:
> - channel[chn].program = d1;
> - break;
> - case MIDI_CHN_PRESSURE:
> - for (i = 0; i < dest->caps.wVoices; i++)
> - if (voice[i].status != sVS_UNUSED && voice[i].channel == chn)
> - SEQ_KEY_PRESSURE(dev_id, i, voice[i].note, d1);
> -
> - break;
> - case MIDI_PITCH_BEND:
> - channel[chn].bender = (d2 << 7) + d1;
> - for (i = 0; i < dest->caps.wVoices; i++)
> - if (voice[i].channel == chn)
> - SEQ_BENDER(dev_id, i, channel[chn].bender);
> - break;
> - case MIDI_SYSTEM_PREFIX:
> - switch (evt & 0x0F)
> - {
> - case 0x0F: /* Reset */
> - OSS_CALL(midi_out_fm_reset, (void *)(UINT_PTR)dev_id);
> - break;
> - default:
> - WARN("Unsupported (yet) system event %02x\n", evt & 0x0F);
> - }
> - break;
> - default:
> - WARN("Internal error, shouldn't happen (event=%08x)\n", evt & 0xF0);
> - return MMSYSERR_NOTENABLED;
> - }
> -
> - SEQ_DUMPBUF();
> - return MMSYSERR_NOERROR;
> -}
> -
> -static UINT midi_out_port_data(WORD dev_id, UINT data)
> -{
> - WORD evt = LOBYTE(LOWORD(data));
> - WORD d1 = HIBYTE(LOWORD(data));
> - WORD d2 = LOBYTE(HIWORD(data));
> - int dev = dev_id - MODM_NumFMSynthDevs;
> -
> - if (dev < 0)
> - {
> - WARN("Internal error on devID (%u) !\n", dev_id);
> - return MIDIERR_NODEVICE;
> - }
> -
> - switch (evt & 0xF0)
> - {
> - case MIDI_NOTEOFF:
> - case MIDI_NOTEON:
> - case MIDI_KEY_PRESSURE:
> - case MIDI_CTL_CHANGE:
> - case MIDI_PITCH_BEND:
> - SEQ_MIDIOUT(dev, evt);
> - SEQ_MIDIOUT(dev, d1);
> - SEQ_MIDIOUT(dev, d2);
> - break;
> - case MIDI_PGM_CHANGE:
> - case MIDI_CHN_PRESSURE:
> - SEQ_MIDIOUT(dev, evt);
> - SEQ_MIDIOUT(dev, d1);
> - break;
> - case MIDI_SYSTEM_PREFIX:
> - switch (evt & 0x0F)
> - {
> - case 0x00: /* System Exclusive, don't do it on MODM_DATA, should require MODM_LONGDATA */
> - case 0x04: /* Undefined. */
> - case 0x05: /* Undefined. */
> - case 0x07: /* End of Exclusive. */
> - case 0x09: /* Undefined. */
> - case 0x0D: /* Undefined. */
> - break;
> - case 0x06: /* Tune Request */
> - case 0x08: /* Timing Clock. */
> - case 0x0A: /* Start. */
> - case 0x0B: /* Continue */
> - case 0x0C: /* Stop */
> - case 0x0E: /* Active Sensing. */
> - SEQ_MIDIOUT(dev, evt);
> - break;
> - case 0x0F: /* Reset */
> - SEQ_MIDIOUT(dev, MIDI_SYSTEM_PREFIX);
> - SEQ_MIDIOUT(dev, 0x7e);
> - SEQ_MIDIOUT(dev, 0x7f);
> - SEQ_MIDIOUT(dev, 0x09);
> - SEQ_MIDIOUT(dev, 0x01);
> - SEQ_MIDIOUT(dev, 0xf7);
> - break;
> - case 0x01: /* MTC Quarter frame */
> - case 0x03: /* Song Select. */
> - SEQ_MIDIOUT(dev, evt);
> - SEQ_MIDIOUT(dev, d1);
> - case 0x02: /* Song Position Pointer. */
> - SEQ_MIDIOUT(dev, evt);
> - SEQ_MIDIOUT(dev, d1);
> - SEQ_MIDIOUT(dev, d2);
> - }
> - break;
> - }
> -
> - SEQ_DUMPBUF();
> - return MMSYSERR_NOERROR;
> -}
> -
> -/**************************************************************************
> - * modData [internal]
> - */
> -static DWORD modData(WORD wDevID, DWORD dwParam)
> -{
> - TRACE("(%04X, %08X);\n", wDevID, dwParam);
> -
> - if (wDevID >= MODM_NumDevs) return MMSYSERR_BADDEVICEID;
> - if (!MidiOutDev[wDevID].bEnabled) return MIDIERR_NODEVICE;
> -
> - if (MidiOutDev[wDevID].fd == -1) {
> - WARN("can't play !\n");
> - return MIDIERR_NODEVICE;
> - }
> - switch (MidiOutDev[wDevID].caps.wTechnology) {
> - case MOD_FMSYNTH:
> - return midi_out_fm_data(wDevID, dwParam);
> - case MOD_MIDIPORT:
> - return midi_out_port_data(wDevID, dwParam);
> - }
> -
> - WARN("Technology not supported (yet) %d !\n",
> - MidiOutDev[wDevID].caps.wTechnology);
> - return MMSYSERR_NOTENABLED;
> -}
> -
> /**************************************************************************
> * modLongData [internal]
> */
> @@ -1164,6 +835,9 @@ static DWORD modGetVolume(WORD wDevID, DWORD* lpdwVolume)
> return (MidiOutDev[wDevID].caps.dwSupport & MIDICAPS_VOLUME) ? 0 : MMSYSERR_NOTSUPPORTED;
> }
>
> +DWORD WINAPI OSS_modMessage(UINT wDevID, UINT wMsg, DWORD_PTR dwUser,
> + DWORD_PTR dwParam1, DWORD_PTR dwParam2);
> +
> /**************************************************************************
> * modReset [internal]
> */
> @@ -1182,9 +856,9 @@ static DWORD modReset(WORD wDevID)
> */
> for (chn = 0; chn < 16; chn++) {
> /* turn off every note */
> - modData(wDevID, 0x7800 | MIDI_CTL_CHANGE | chn);
> + OSS_modMessage(wDevID, MODM_DATA, 0, 0x7800 | MIDI_CTL_CHANGE | chn, 0);
> /* remove sustain on all channels */
> - modData(wDevID, (CTL_SUSTAIN << 8) | MIDI_CTL_CHANGE | chn);
> + OSS_modMessage(wDevID, MODM_DATA, 0, (CTL_SUSTAIN << 8) | MIDI_CTL_CHANGE | chn, 0);
> }
> /* FIXME: the LongData buffers must also be returned to the app */
> return MMSYSERR_NOERROR;
> @@ -1255,8 +929,6 @@ DWORD WINAPI OSS_modMessage(UINT wDevID, UINT wMsg, DWORD_PTR dwUser,
> return OSS_MidiInit();
> case DRVM_EXIT:
> return OSS_MidiExit();
> - case MODM_DATA:
> - return modData(wDevID, dwParam1);
> case MODM_LONGDATA:
> return modLongData(wDevID, (LPMIDIHDR)dwParam1, dwParam2);
> case MODM_PREPARE:
> diff --git a/dlls/wineoss.drv/oss.c b/dlls/wineoss.drv/oss.c
> index 1bd5ddb5762..db2f705a0c5 100644
> --- a/dlls/wineoss.drv/oss.c
> +++ b/dlls/wineoss.drv/oss.c
> @@ -1409,5 +1409,4 @@ unixlib_entry_t __wine_unix_call_funcs[] =
> midi_out_message,
>
> midi_seq_open,
> - midi_out_fm_reset,
> };
> diff --git a/dlls/wineoss.drv/ossmidi.c b/dlls/wineoss.drv/ossmidi.c
> index 613b070fde5..ee83da8bfcd 100644
> --- a/dlls/wineoss.drv/ossmidi.c
> +++ b/dlls/wineoss.drv/ossmidi.c
> @@ -93,6 +93,8 @@ typedef struct sFMextra
> */
> } sFMextra;
>
> +#define IS_DRUM_CHANNEL(_xtra, _chn) ((_xtra)->drumSetMask & (1 << (_chn)))
> +
> WINE_DEFAULT_DEBUG_CHANNEL(midi);
>
> static int oss_to_win_device_type(int type)
> @@ -458,9 +460,8 @@ static int midi_out_fm_load(WORD dev_id, int fd)
> return 0;
> }
>
> -NTSTATUS midi_out_fm_reset(void *args)
> +static void midi_out_fm_reset(WORD dev_id)
> {
> - WORD dev_id = (WORD)(UINT_PTR)args;
> struct midi_dest *dest = dests + dev_id;
> sFMextra *extra = dest->lpExtra;
> sVoice *voice = extra->voice;
> @@ -492,8 +493,6 @@ NTSTATUS midi_out_fm_reset(void *args)
> extra->counter = 0;
> extra->drumSetMask = 1 << 9; /* channel 10 is normally drums, sometimes 16 also */
> SEQ_DUMPBUF();
> -
> - return STATUS_SUCCESS;
> }
>
> static void set_out_notify(struct notify_context *notify, struct midi_dest *dest, WORD dev_id, WORD msg,
> @@ -572,7 +571,7 @@ static UINT midi_out_open(WORD dev_id, MIDIOPENDESC *midi_desc, UINT flags, stru
> free(extra);
> return MMSYSERR_ERROR;
> }
> - midi_out_fm_reset((void *)(UINT_PTR)dev_id);
> + midi_out_fm_reset(dev_id);
> break;
> }
> case MOD_MIDIPORT:
> @@ -645,6 +644,295 @@ static UINT midi_out_close(WORD dev_id, struct notify_context *notify)
> return MMSYSERR_NOERROR;
> }
>
> +static UINT midi_out_fm_data(WORD dev_id, UINT data)
> +{
> + struct midi_dest *dest = dests + dev_id;
> + WORD evt = LOBYTE(LOWORD(data));
> + WORD d1 = HIBYTE(LOWORD(data));
> + WORD d2 = LOBYTE(HIWORD(data));
> + sFMextra *extra = dest->lpExtra;
> + sVoice *voice = extra->voice;
> + sChannel *channel = extra->channel;
> + int chn = (evt & 0x0F), i, nv;
> +
> + /* FIXME: chorus depth controller is not used */
> +
> + switch (evt & 0xF0)
> + {
> + case MIDI_NOTEOFF:
> + for (i = 0; i < dest->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;
> + SEQ_STOP_NOTE(dev_id, i, d1, d2);
> + }
> + }
> + break;
> + case MIDI_NOTEON:
> + if (d2 == 0) /* note off if velocity == 0 */
> + {
> + for (i = 0; i < dest->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;
> + SEQ_STOP_NOTE(dev_id, i, d1, 64);
> + }
> + }
> + break;
> + }
> + /* finding out in this order :
> + * - an empty voice
> + * - if replaying the same note on the same channel
> + * - the older voice (LRU)
> + */
> + for (i = nv = 0; i < dest->caps.wVoices; i++)
> + {
> + if (voice[i].status == sVS_UNUSED || (voice[i].note == d1 && voice[i].channel == chn))
> + {
> + nv = i;
> + break;
> + }
> + if (voice[i].cntMark < voice[0].cntMark)
> + nv = i;
> + }
> + TRACE("playing on voice=%d, pgm=%d, pan=0x%02X, vol=0x%02X, bender=0x%02X, note=0x%02X, vel=0x%02X\n",
> + nv, channel[chn].program, channel[chn].balance, channel[chn].volume, channel[chn].bender, d1, d2);
> +
> + SEQ_SET_PATCH(dev_id, nv, IS_DRUM_CHANNEL(extra, chn) ?
> + (128 + d1) : channel[chn].program);
> + SEQ_BENDER_RANGE(dev_id, nv, channel[chn].benderRange * 100);
> + SEQ_BENDER(dev_id, nv, channel[chn].bender);
> + SEQ_CONTROL(dev_id, nv, CTL_PAN, channel[chn].balance);
> + SEQ_CONTROL(dev_id, nv, CTL_EXPRESSION, channel[chn].expression);
> + SEQ_START_NOTE(dev_id, nv, d1, d2);
> + voice[nv].status = channel[chn].sustain ? sVS_SUSTAINED : sVS_PLAYING;
> + voice[nv].note = d1;
> + voice[nv].channel = chn;
> + voice[nv].cntMark = extra->counter++;
> + break;
> + case MIDI_KEY_PRESSURE:
> + for (i = 0; i < dest->caps.wVoices; i++)
> + if (voice[i].status != sVS_UNUSED && voice[i].channel == chn && voice[i].note == d1)
> + SEQ_KEY_PRESSURE(dev_id, i, d1, d2);
> + break;
> + case MIDI_CTL_CHANGE:
> + switch (d1)
> + {
> + case CTL_BANK_SELECT: channel[chn].bank = d2; break;
> + case CTL_MAIN_VOLUME: channel[chn].volume = d2; break;
> + case CTL_PAN: channel[chn].balance = d2; break;
> + case CTL_EXPRESSION: channel[chn].expression = d2; break;
> + case CTL_SUSTAIN: channel[chn].sustain = d2;
> + if (d2)
> + {
> + for (i = 0; i < dest->caps.wVoices; i++)
> + if (voice[i].status == sVS_PLAYING && voice[i].channel == chn)
> + voice[i].status = sVS_SUSTAINED;
> + }
> + else
> + {
> + for (i = 0; i < dest->caps.wVoices; i++)
> + {
> + if (voice[i].status == sVS_SUSTAINED && voice[i].channel == chn)
> + {
> + voice[i].status = sVS_UNUSED;
> + SEQ_STOP_NOTE(dev_id, i, voice[i].note, 64);
> + }
> + }
> + }
> + break;
> + case CTL_NONREG_PARM_NUM_LSB: channel[chn].nrgPmtLSB = d2; break;
> + case CTL_NONREG_PARM_NUM_MSB: channel[chn].nrgPmtMSB = d2; break;
> + case CTL_REGIST_PARM_NUM_LSB: channel[chn].regPmtLSB = d2; break;
> + case CTL_REGIST_PARM_NUM_MSB: channel[chn].regPmtMSB = d2; break;
> + case CTL_DATA_ENTRY:
> + switch ((channel[chn].regPmtMSB << 8) | channel[chn].regPmtLSB)
> + {
> + case 0x0000:
> + if (channel[chn].benderRange != d2)
> + {
> + channel[chn].benderRange = d2;
> + for (i = 0; i < dest->caps.wVoices; i++)
> + if (voice[i].channel == chn)
> + SEQ_BENDER_RANGE(dev_id, i, channel[chn].benderRange);
> + }
> + break;
> +
> + case 0x7F7F:
> + channel[chn].benderRange = 2;
> + for (i = 0; i < dest->caps.wVoices; i++)
> + if (voice[i].channel == chn)
> + SEQ_BENDER_RANGE(dev_id, i, channel[chn].benderRange);
> + break;
> + default:
> + TRACE("Data entry: regPmt=0x%02x%02x, nrgPmt=0x%02x%02x with %x\n",
> + channel[chn].regPmtMSB, channel[chn].regPmtLSB,
> + channel[chn].nrgPmtMSB, channel[chn].nrgPmtLSB, d2);
> + break;
> + }
> + break;
> +
> + case 0x78: /* all sounds off */
> + /* FIXME: I don't know if I have to take care of the channel for this control? */
> + for (i = 0; i < dest->caps.wVoices; i++)
> + {
> + if (voice[i].status != sVS_UNUSED && voice[i].channel == chn)
> + {
> + voice[i].status = sVS_UNUSED;
> + SEQ_STOP_NOTE(dev_id, i, voice[i].note, 64);
> + }
> + }
> + break;
> + case 0x7B: /* all notes off */
> + /* FIXME: I don't know if I have to take care of the channel for this control? */
> + for (i = 0; i < dest->caps.wVoices; i++)
> + {
> + if (voice[i].status == sVS_PLAYING && voice[i].channel == chn)
> + {
> + voice[i].status = sVS_UNUSED;
> + SEQ_STOP_NOTE(dev_id, i, voice[i].note, 64);
> + }
> + }
> + break;
> + default:
> + TRACE("Dropping MIDI control event 0x%02x(%02x) on channel %d\n", d1, d2, chn);
> + break;
> + }
> + break;
> + case MIDI_PGM_CHANGE:
> + channel[chn].program = d1;
> + break;
> + case MIDI_CHN_PRESSURE:
> + for (i = 0; i < dest->caps.wVoices; i++)
> + if (voice[i].status != sVS_UNUSED && voice[i].channel == chn)
> + SEQ_KEY_PRESSURE(dev_id, i, voice[i].note, d1);
> +
> + break;
> + case MIDI_PITCH_BEND:
> + channel[chn].bender = (d2 << 7) + d1;
> + for (i = 0; i < dest->caps.wVoices; i++)
> + if (voice[i].channel == chn)
> + SEQ_BENDER(dev_id, i, channel[chn].bender);
> + break;
> + case MIDI_SYSTEM_PREFIX:
> + switch (evt & 0x0F)
> + {
> + case 0x0F: /* Reset */
> + midi_out_fm_reset(dev_id);
> + break;
> + default:
> + WARN("Unsupported (yet) system event %02x\n", evt & 0x0F);
> + }
> + break;
> + default:
> + WARN("Internal error, shouldn't happen (event=%08x)\n", evt & 0xF0);
> + return MMSYSERR_NOTENABLED;
> + }
> +
> + SEQ_DUMPBUF();
> + return MMSYSERR_NOERROR;
> +}
> +
> +static UINT midi_out_port_data(WORD dev_id, UINT data)
> +{
> + WORD evt = LOBYTE(LOWORD(data));
> + WORD d1 = HIBYTE(LOWORD(data));
> + WORD d2 = LOBYTE(HIWORD(data));
> + int dev = dev_id - num_synths;
> +
> + if (dev < 0)
> + {
> + WARN("Internal error on devID (%u) !\n", dev_id);
> + return MIDIERR_NODEVICE;
> + }
> +
> + switch (evt & 0xF0)
> + {
> + case MIDI_NOTEOFF:
> + case MIDI_NOTEON:
> + case MIDI_KEY_PRESSURE:
> + case MIDI_CTL_CHANGE:
> + case MIDI_PITCH_BEND:
> + SEQ_MIDIOUT(dev, evt);
> + SEQ_MIDIOUT(dev, d1);
> + SEQ_MIDIOUT(dev, d2);
> + break;
> + case MIDI_PGM_CHANGE:
> + case MIDI_CHN_PRESSURE:
> + SEQ_MIDIOUT(dev, evt);
> + SEQ_MIDIOUT(dev, d1);
> + break;
> + case MIDI_SYSTEM_PREFIX:
> + switch (evt & 0x0F)
> + {
> + case 0x00: /* System Exclusive, don't do it on MODM_DATA, should require MODM_LONGDATA */
> + case 0x04: /* Undefined. */
> + case 0x05: /* Undefined. */
> + case 0x07: /* End of Exclusive. */
> + case 0x09: /* Undefined. */
> + case 0x0D: /* Undefined. */
> + break;
> + case 0x06: /* Tune Request */
> + case 0x08: /* Timing Clock. */
> + case 0x0A: /* Start. */
> + case 0x0B: /* Continue */
> + case 0x0C: /* Stop */
> + case 0x0E: /* Active Sensing. */
> + SEQ_MIDIOUT(dev, evt);
> + break;
> + case 0x0F: /* Reset */
> + SEQ_MIDIOUT(dev, MIDI_SYSTEM_PREFIX);
> + SEQ_MIDIOUT(dev, 0x7e);
> + SEQ_MIDIOUT(dev, 0x7f);
> + SEQ_MIDIOUT(dev, 0x09);
> + SEQ_MIDIOUT(dev, 0x01);
> + SEQ_MIDIOUT(dev, 0xf7);
> + break;
> + case 0x01: /* MTC Quarter frame */
> + case 0x03: /* Song Select. */
> + SEQ_MIDIOUT(dev, evt);
> + SEQ_MIDIOUT(dev, d1);
> + case 0x02: /* Song Position Pointer. */
> + SEQ_MIDIOUT(dev, evt);
> + SEQ_MIDIOUT(dev, d1);
> + SEQ_MIDIOUT(dev, d2);
> + }
> + break;
> + }
> +
> + SEQ_DUMPBUF();
> + return MMSYSERR_NOERROR;
> +}
> +
> +static UINT midi_out_data(WORD dev_id, UINT data)
> +{
> + struct midi_dest *dest;
> +
> + TRACE("(%04X, %08X);\n", dev_id, data);
> +
> + if (dev_id >= num_dests) return MMSYSERR_BADDEVICEID;
> + dest = dests + dev_id;
> + if (!dest->bEnabled) return MIDIERR_NODEVICE;
> +
> + if (dest->fd == -1)
> + {
> + WARN("can't play !\n");
> + return MIDIERR_NODEVICE;
> + }
> + switch (dest->caps.wTechnology)
> + {
> + case MOD_FMSYNTH:
> + return midi_out_fm_data(dev_id, data);
> + case MOD_MIDIPORT:
> + return midi_out_port_data(dev_id, data);
> + }
> +
> + WARN("Technology not supported (yet) %d !\n", dest->caps.wTechnology);
> + return MMSYSERR_NOTENABLED;
> +}
>
> NTSTATUS midi_out_message(void *args)
> {
> @@ -665,6 +953,9 @@ NTSTATUS midi_out_message(void *args)
> case MODM_CLOSE:
> *params->err = midi_out_close(params->dev_id, params->notify);
> break;
> + case MODM_DATA:
> + *params->err = midi_out_data(params->dev_id, params->param_1);
> + break;
> default:
> TRACE("Unsupported message\n");
> *params->err = MMSYSERR_NOTSUPPORTED;
> diff --git a/dlls/wineoss.drv/unixlib.h b/dlls/wineoss.drv/unixlib.h
> index 75506d445bc..d56e11b8d23 100644
> --- a/dlls/wineoss.drv/unixlib.h
> +++ b/dlls/wineoss.drv/unixlib.h
> @@ -276,13 +276,6 @@ struct midi_seq_open_params
> int fd;
> };
>
> -struct midi_out_fm_load_params
> -{
> - WORD dev_id;
> - int fd;
> - int ret;
> -};
> -
> enum oss_funcs
> {
> oss_test_connect,
> @@ -312,13 +305,11 @@ enum oss_funcs
> oss_midi_out_message,
>
> oss_midi_seq_open, /* temporary */
> - oss_midi_out_fm_reset,
> };
>
> NTSTATUS midi_init(void *args) DECLSPEC_HIDDEN;
> NTSTATUS midi_out_message(void *args) DECLSPEC_HIDDEN;
> NTSTATUS midi_seq_open(void *args) DECLSPEC_HIDDEN;
> -NTSTATUS midi_out_fm_reset(void *args) DECLSPEC_HIDDEN;
>
> extern unixlib_handle_t oss_handle;
>
> --
> 2.25.1
>
>
More information about the wine-devel
mailing list