--- wine-0.9.36/dlls/winealsa.drv/midi.c.jacklab	2007-04-25 19:11:57.000000000 +0200
+++ wine-0.9.36/dlls/winealsa.drv/midi.c	2007-04-29 22:14:39.000000000 +0200
@@ -50,6 +50,7 @@
 #include "mmddk.h"
 #include "alsa.h"
 #include "wine/debug.h"
+#include <sched.h>
 
 WINE_DEFAULT_DEBUG_CHANNEL(midi);
 
@@ -318,7 +319,8 @@
 	    if ((wDevID == MIDM_NumDevs) || (MidiInDev[wDevID].state != 1))
 		FIXME("Unexpected event received, type = %x from %d:%d\n", ev->type, ev->source.client, ev->source.port);
 	    else {
		DWORD dwTime, toSend = 0;
+                char *buf = (char *)&toSend; // i like more using a char stream
 		/* 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,10 @@
 		    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;
+                    buf[0] = MIDI_CMD_BENDER | ev->data.control.channel;
+	            int value = ev->data.control.value + 0x2000;
+	            buf[1] = value & 0x7f;
+	            buf[2] = (value >> 7) & 0x7f;
 		    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 +350,30 @@
 		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:
+		    buf[0] = 0xF8;
+		    break;
+		case SND_SEQ_EVENT_START:
+		    buf[0] = 0xFA;
+		    break;
+		case SND_SEQ_EVENT_CONTINUE:
+		    buf[0] = 0xFB;
+		    break;
+		case SND_SEQ_EVENT_STOP:
+		    buf[0] = 0xFC;
+		    break;
+		case SND_SEQ_EVENT_SONGPOS:
+		    buf[0] = 0xF2;
+	            buf[1] = ev->data.control.value & 0x7f;
+	            buf[2] = (ev->data.control.value >> 7) & 0x7f;
+		    break;
+		case SND_SEQ_EVENT_SONGSEL:
+		    buf[0] = 0xF3;
+	            buf[1] = ev->data.control.value & 0x7f;
+		    break;
+		case SND_SEQ_EVENT_RESET:
+		    buf[0] = 0xFF;
+		    break;
 		case SND_SEQ_EVENT_SYSEX:
 		    {
 			int len = ev->data.ext.len;
@@ -464,7 +493,7 @@
 	    midiCloseSeq();
 	    return MMSYSERR_ERROR;
 	}
-        SetThreadPriority(hThread, THREAD_PRIORITY_TIME_CRITICAL);
+      SetThreadPriority(hThread, THREAD_PRIORITY_TIME_CRITICAL);
 	TRACE("Created thread for midi-in\n");
     }
 
@@ -551,6 +580,7 @@
     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 +873,64 @@
 	    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 * 128 + (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:
