[PATCH 1/1] handling sysex midi messages in winecoreaudio

tinez tinez at tlen.pl
Wed Feb 25 14:58:41 CST 2015


Hi,

this patch fixes handling sysex midi messages in winecoreaudio driver. 
The code was based on winealsa driver implementation.
I've tested it using external midi hardware + midi monitoring tools 
(MidiOX). My motivation was to fix Nord Modular Editor software
which is needed to control Nord Modular G1 hardware synthetizer. After 
applying the patch it works without problems.
I've also sent out patch to electro-music.com for other people to test 
and it was received well (you can see the thread here 
electro-music.com/forum/viewtopic.php?t=62683).

regards, tinez

---
  dlls/winecoreaudio.drv/midi.c | 66 
++++++++++++++++++++++++++++++-------------
  1 file changed, 47 insertions(+), 19 deletions(-)
-------------- next part --------------
From e18b1c9876730d9557b97f3e16249b20eae4e875 Mon Sep 17 00:00:00 2001
From: tinez <tinez at tlen.pl>
Date: Thu, 21 Aug 2014 23:13:31 +0200
Subject: [PATCH 1/1] handling sysex midi messages in winecoreaudio

---
 dlls/winecoreaudio.drv/midi.c | 66 ++++++++++++++++++++++++++++++-------------
 1 file changed, 47 insertions(+), 19 deletions(-)

diff --git a/dlls/winecoreaudio.drv/midi.c b/dlls/winecoreaudio.drv/midi.c
index 8593e9c..c7a1ded 100644
--- a/dlls/winecoreaudio.drv/midi.c
+++ b/dlls/winecoreaudio.drv/midi.c
@@ -437,9 +437,9 @@ static DWORD MIDIOut_LongData(WORD wDevID, LPMIDIHDR lpMidiHdr, DWORD dwSize)
             return MMSYSERR_ERROR;
         }
     }
-    else
+    else if (destinations[wDevID].caps.wTechnology == MOD_MIDIPORT)
     {
-        FIXME("MOD_MIDIPORT\n");
+        MIDIOut_Send(MIDIOutPort, destinations[wDevID].dest, lpData, lpMidiHdr->dwBufferLength);
     }
 
     lpMidiHdr->dwFlags &= ~MHDR_INQUEUE;
@@ -836,26 +836,55 @@ static CFDataRef MIDIIn_MessageHandler(CFMessagePortRef local, SInt32 msgid, CFD
             if (src->state < 1)
             {
                 TRACE("input not started, thrown away\n");
-                goto done;
-            }
-            /* FIXME skipping SysEx */
-            if (msg->data[0] == 0xF0)
-            {
-                FIXME("Starting System Exclusive\n");
-                src->state |= 2;
+                return NULL;
             }
-            if (src->state & 2)
-            {
-                for (i = 0; i < msg->length; ++i)
-                {
-                    if (msg->data[i] == 0xF7)
-                    {
-                        FIXME("Ending System Exclusive\n");
-                        src->state &= ~2;
+
+            bool sysexStart = (msg->data[0] == 0xF0);
+
+            if (sysexStart || src->state & 2) {
+                if (sysexStart) {
+                    TRACE("Receiving sysex message\n");
+                    src->state |= 2;
+                }
+
+                int pos = 0;
+                int len = msg->length;
+
+                EnterCriticalSection(&midiInLock);
+                currentTime = GetTickCount() - src->startTime;
+
+                while (len) {
+                    LPMIDIHDR lpMidiHdr = src->lpQueueHdr;
+
+                    if (lpMidiHdr != NULL) {
+                        int copylen = min(len, lpMidiHdr->dwBufferLength - lpMidiHdr->dwBytesRecorded);
+                        memcpy(lpMidiHdr->lpData + lpMidiHdr->dwBytesRecorded, msg->data + pos, copylen);
+                        lpMidiHdr->dwBytesRecorded += copylen;
+                        len -= copylen;
+                        pos += copylen;
+
+                        TRACE("Copied %d bytes of sysex message\n", copylen);
+
+                        if ((lpMidiHdr->dwBytesRecorded == lpMidiHdr->dwBufferLength) ||
+				            (*(BYTE*)(lpMidiHdr->lpData + lpMidiHdr->dwBytesRecorded - 1) == 0xF7)) {
+                            TRACE("Sysex message complete (or buffer limit reached), dispatching %d bytes\n", lpMidiHdr->dwBytesRecorded);
+                            src->lpQueueHdr = lpMidiHdr->lpNext;
+                            lpMidiHdr->dwFlags &= ~MHDR_INQUEUE;
+                            lpMidiHdr->dwFlags |= MHDR_DONE;
+                            MIDI_NotifyClient(msg->devID, MIM_LONGDATA, (DWORD_PTR)lpMidiHdr, currentTime);
+                            src->state &= ~2;
+                        }
+                    }
+			        else {
+                        FIXME("Sysex data received but no buffer to store it!\n");
+                        break;
                     }
                 }
-                goto done;
+
+                LeaveCriticalSection(&midiInLock);
+                return NULL;
             }
+
             EnterCriticalSection(&midiInLock);
             currentTime = GetTickCount() - src->startTime;
 
@@ -889,7 +918,6 @@ static CFDataRef MIDIIn_MessageHandler(CFMessagePortRef local, SInt32 msgid, CFD
             CFRunLoopStop(CFRunLoopGetCurrent());
             break;
     }
-done:
     return NULL;
 }
 
-- 
1.9.3 (Apple Git-50)



More information about the wine-patches mailing list