[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