[PATCH] some alsa midi fixes
Ralf Beck
musical_snake at gmx.de
Sun May 13 13:32:20 CDT 2007
Hello,
this patch fixes:
- Bug 8096
- incorrect handling of pitchbender on midi-in
- add midi-in midiclock/start/stop/continue/spp/song sel
- make midi-out midiclock/start/stop/continue/spp/song sel handling same
style as on midi-in
Sorry it is a normal diff, not a git patch, but i don't want to checkout
a complete 89MB tree with my analog modem.
Ralf
-------------- next part --------------
--- wine-0.9.37/dlls/winealsa.drv/midi.c 2007-05-11 19:35:02.000000000 +0200
+++ wine-patched/dlls/winealsa.drv/midi.c 2007-05-13 20:13:01.000000000 +0200
@@ -1,3 +1,4 @@
+1,1381c1,1350
/* -*- tab-width: 8; c-basic-offset: 4 -*- */
/*
@@ -319,6 +320,7 @@ static DWORD WINAPI midRecThread(LPVOID
FIXME("Unexpected event received, type = %x from %d:%d\n", ev->type, ev->source.client, ev->source.port);
else {
DWORD dwTime, toSend = 0;
+ int value = 0;
/* FIXME: Should use ev->time instead for better accuracy */
dwTime = GetTickCount() - MidiInDev[wDevID].startTime;
TRACE("Event received, type = %x, device = %d\n", ev->type, wDevID);
@@ -337,7 +339,8 @@ static DWORD WINAPI midRecThread(LPVOID
toSend = (ev->data.control.value << 16) | (ev->data.control.param << 8) | MIDI_CMD_CONTROL | ev->data.control.channel;
break;
case SND_SEQ_EVENT_PITCHBEND:
- toSend = (ev->data.control.value << 16) | (ev->data.control.param << 8) | MIDI_CMD_BENDER | ev->data.control.channel;
+ value = ev->data.control.value + 0x2000;
+ toSend = (((value >> 7) & 0x7f) << 16) | ((value & 0x7f) << 8) | MIDI_CMD_BENDER | ev->data.control.channel;
break;
case SND_SEQ_EVENT_PGMCHANGE:
toSend = (ev->data.control.value << 16) | (ev->data.control.param << 8) | MIDI_CMD_PGM_CHANGE | ev->data.control.channel;
@@ -345,6 +348,27 @@ static DWORD WINAPI midRecThread(LPVOID
case SND_SEQ_EVENT_CHANPRESS:
toSend = (ev->data.control.value << 16) | (ev->data.control.param << 8) | MIDI_CMD_CHANNEL_PRESSURE | ev->data.control.channel;
break;
+ case SND_SEQ_EVENT_CLOCK:
+ toSend = 0xF8;
+ break;
+ case SND_SEQ_EVENT_START:
+ toSend = 0xFA;
+ break;
+ case SND_SEQ_EVENT_CONTINUE:
+ toSend = 0xFB;
+ break;
+ case SND_SEQ_EVENT_STOP:
+ toSend = 0xFC;
+ break;
+ case SND_SEQ_EVENT_SONGPOS:
+ toSend = (((ev->data.control.value >> 7) & 0x7f) << 16) | ((ev->data.control.value & 0x7f) << 8) | 0xF2;
+ break;
+ case SND_SEQ_EVENT_SONGSEL:
+ toSend = ((ev->data.control.value & 0x7f) << 8) | 0xF3;
+ break;
+ case SND_SEQ_EVENT_RESET:
+ toSend = 0xFF;
+ break;
case SND_SEQ_EVENT_SYSEX:
{
int len = ev->data.ext.len;
@@ -551,6 +575,7 @@ static DWORD midAddBuffer(WORD wDevID, L
if (!(lpMidiHdr->dwFlags & MHDR_PREPARED)) return MIDIERR_UNPREPARED;
EnterCriticalSection(&crit_sect);
+ lpMidiHdr->dwFlags |= MHDR_INQUEUE;
if (MidiInDev[wDevID].lpQueueHdr == 0) {
MidiInDev[wDevID].lpQueueHdr = lpMidiHdr;
} else {
@@ -843,58 +868,64 @@ static DWORD modData(WORD wDevID, DWORD
case MIDI_CMD_CHANNEL_PRESSURE:
snd_seq_ev_set_chanpress(&event, evt&0x0F, d1);
break;
- case MIDI_CMD_COMMON_SYSEX:
- switch (evt & 0x0F) {
- case 0x00: /* System Exclusive, don't do it on modData,
- * should require modLongData*/
- case 0x01: /* Undefined */
- case 0x04: /* Undefined. */
- case 0x05: /* Undefined. */
- case 0x07: /* End of Exclusive. */
- case 0x09: /* Undefined. */
- case 0x0D: /* Undefined. */
- handled = 0;
- break;
- case 0x06: /* Tune Request */
- case 0x08: /* Timing Clock. */
- case 0x0A: /* Start. */
- case 0x0B: /* Continue */
- case 0x0C: /* Stop */
- case 0x0E: /* Active Sensing. */
- /* FIXME: Is this function suitable for these purposes
- (and also Song Select and Song Position Pointer) */
- snd_seq_ev_set_sysex(&event, 1, &evt);
- break;
- case 0x0F: /* Reset */
- /* snd_seq_ev_set_sysex(&event, 1, &evt);
- this other way may be better */
- {
- BYTE reset_sysex_seq[] = {MIDI_CMD_COMMON_SYSEX, 0x7e, 0x7f, 0x09, 0x01, 0xf7};
- snd_seq_ev_set_sysex(&event, sizeof(reset_sysex_seq), reset_sysex_seq);
- }
+ case MIDI_CMD_COMMON_SYSEX:
+ switch (evt) {
+ case MIDI_CMD_COMMON_SONG_POS:
+ event.type = SND_SEQ_EVENT_SONGPOS;
+ event.flags &= ~SND_SEQ_EVENT_LENGTH_MASK;
+ event.flags |= SND_SEQ_EVENT_LENGTH_FIXED;
+ event.data.control.value = ((unsigned int)d2 << 7) + (unsigned int)d1;
break;
- case 0x03: /* Song Select. */
- {
- BYTE buf[2];
- buf[0] = evt;
- buf[1] = d1;
- snd_seq_ev_set_sysex(&event, sizeof(buf), buf);
- }
- break;
- case 0x02: /* Song Position Pointer. */
- {
- BYTE buf[3];
- buf[0] = evt;
- buf[1] = d1;
- buf[2] = d2;
- snd_seq_ev_set_sysex(&event, sizeof(buf), buf);
- }
+ case MIDI_CMD_COMMON_SONG_SELECT:
+ event.type = SND_SEQ_EVENT_SONGSEL;
+ event.flags &= ~SND_SEQ_EVENT_LENGTH_MASK;
+ event.flags |= SND_SEQ_EVENT_LENGTH_FIXED;
+ event.data.control.value = (unsigned int)d1;
break;
- }
- break;
+ case MIDI_CMD_COMMON_TUNE_REQUEST:
+ event.type = SND_SEQ_EVENT_TUNE_REQUEST;
+ event.flags &= ~SND_SEQ_EVENT_LENGTH_MASK;
+ event.flags |= SND_SEQ_EVENT_LENGTH_FIXED;
+ break;
+ case MIDI_CMD_COMMON_CLOCK:
+ event.type = SND_SEQ_EVENT_CLOCK;
+ event.flags &= ~SND_SEQ_EVENT_LENGTH_MASK;
+ event.flags |= SND_SEQ_EVENT_LENGTH_FIXED;
+ break;
+ case MIDI_CMD_COMMON_START:
+ event.type = SND_SEQ_EVENT_START;
+ event.flags &= ~SND_SEQ_EVENT_LENGTH_MASK;
+ event.flags |= SND_SEQ_EVENT_LENGTH_FIXED;
+ break;
+ case MIDI_CMD_COMMON_CONTINUE:
+ event.type = SND_SEQ_EVENT_CONTINUE;
+ event.flags &= ~SND_SEQ_EVENT_LENGTH_MASK;
+ event.flags |= SND_SEQ_EVENT_LENGTH_FIXED;
+ break;
+ case MIDI_CMD_COMMON_STOP:
+ event.type = SND_SEQ_EVENT_STOP;
+ event.flags &= ~SND_SEQ_EVENT_LENGTH_MASK;
+ event.flags |= SND_SEQ_EVENT_LENGTH_FIXED;
+ break;
+ case MIDI_CMD_COMMON_SENSING:
+ handled = 0;
+ break;
+ case MIDI_CMD_COMMON_RESET:
+ event.type = SND_SEQ_EVENT_RESET;
+ event.flags &= ~SND_SEQ_EVENT_LENGTH_MASK;
+ event.flags |= SND_SEQ_EVENT_LENGTH_FIXED;
+ break;
+ default:
+ handled = 0;
+ }
+ break;
+
+ default:
+ handled = 0;
}
if (handled)
snd_seq_event_output_direct(midiSeq, &event);
+ snd_seq_drain_output(midiSeq);
}
break;
default:
More information about the wine-patches
mailing list