[PATCH 2/6] wineoss: Move the midi in data handlers to the unixlib.

Huw Davies huw at codeweavers.com
Fri Apr 29 02:29:54 CDT 2022


The syscall itself is temporary.

Signed-off-by: Huw Davies <huw at codeweavers.com>
---
 dlls/wineoss.drv/midi.c    | 129 +------------------------
 dlls/wineoss.drv/oss.c     |   2 +-
 dlls/wineoss.drv/ossmidi.c | 189 +++++++++++++++++++++++++++++++++++--
 dlls/wineoss.drv/unixlib.h |  10 +-
 4 files changed, 196 insertions(+), 134 deletions(-)

diff --git a/dlls/wineoss.drv/midi.c b/dlls/wineoss.drv/midi.c
index b3f980ab3da..0afd9985c03 100644
--- a/dlls/wineoss.drv/midi.c
+++ b/dlls/wineoss.drv/midi.c
@@ -126,16 +126,6 @@ static LRESULT OSS_MidiExit(void)
     return 0;
 }
 
-static void in_buffer_lock(void)
-{
-    OSS_CALL(midi_in_lock, ULongToPtr(1));
-}
-
-static void in_buffer_unlock(void)
-{
-    OSS_CALL(midi_in_lock, ULongToPtr(0));
-}
-
 static void notify_client(struct notify_context *notify)
 {
     TRACE("dev_id = %d msg = %d param1 = %04lX param2 = %04lX\n",
@@ -210,123 +200,13 @@ static int midiCloseSeq(int fd)
     return 0;
 }
 
-static void handle_sysex_data(struct midi_src *src, unsigned char value, UINT time)
-{
-    MIDIHDR *hdr;
-    BOOL done = FALSE;
-
-    src->state |= 2;
-    src->incLen = 0;
-
-    in_buffer_lock();
-
-    hdr = src->lpQueueHdr;
-    if (hdr)
-    {
-        BYTE *data = (BYTE *)hdr->lpData;
-
-        data[hdr->dwBytesRecorded++] = value;
-        if (hdr->dwBytesRecorded == hdr->dwBufferLength)
-            done = TRUE;
-    }
-
-    if (value == 0xf7) /* end */
-    {
-        src->state &= ~2;
-        done = TRUE;
-    }
-
-    if (done && hdr)
-    {
-        src->lpQueueHdr = hdr->lpNext;
-        hdr->dwFlags &= ~MHDR_INQUEUE;
-        hdr->dwFlags |= MHDR_DONE;
-        MIDI_NotifyClient(src - MidiInDev, MIM_LONGDATA, (UINT_PTR)hdr, time);
-    }
-
-    in_buffer_unlock();
-}
-
-static void handle_regular_data(struct midi_src *src, unsigned char value, UINT time)
-{
-    UINT to_send = 0;
-
-#define IS_CMD(_x)     (((_x) & 0x80) == 0x80)
-#define IS_SYS_CMD(_x) (((_x) & 0xF0) == 0xF0)
-
-    if (!IS_CMD(value) && src->incLen == 0) /* try to reuse old cmd */
-    {
-        if (IS_CMD(src->incPrev) && !IS_SYS_CMD(src->incPrev))
-        {
-            src->incoming[0] = src->incPrev;
-            src->incLen = 1;
-        }
-        else
-        {
-            /* FIXME: should generate MIM_ERROR notification */
-            return;
-        }
-    }
-    src->incoming[(int)src->incLen++] = value;
-    if (src->incLen == 1 && !IS_SYS_CMD(src->incoming[0]))
-        /* store new cmd, just in case */
-        src->incPrev = src->incoming[0];
-
-#undef IS_CMD
-#undef IS_SYS_CMD
-
-    switch (src->incoming[0] & 0xF0)
-    {
-    case MIDI_NOTEOFF:
-    case MIDI_NOTEON:
-    case MIDI_KEY_PRESSURE:
-    case MIDI_CTL_CHANGE:
-    case MIDI_PITCH_BEND:
-        if (src->incLen == 3)
-            to_send = (src->incoming[2] << 16) | (src->incoming[1] << 8) |
-                src->incoming[0];
-        break;
-    case MIDI_PGM_CHANGE:
-    case MIDI_CHN_PRESSURE:
-        if (src->incLen == 2)
-            to_send = (src->incoming[1] << 8) | src->incoming[0];
-        break;
-    case MIDI_SYSTEM_PREFIX:
-        if (src->incLen == 1)
-            to_send = src->incoming[0];
-        break;
-    }
-
-    if (to_send)
-    {
-        src->incLen = 0;
-        MIDI_NotifyClient(src - MidiInDev, MIM_DATA, to_send, time);
-    }
-}
-
 static void handle_midi_data(unsigned char *buffer, unsigned int len)
 {
-    unsigned int time = GetTickCount(), i;
-    struct midi_src *src;
-    unsigned char value;
-    WORD dev_id;
+    struct midi_handle_data_params params;
 
-    for (i = 0; i < len; i += (buffer[i] & 0x80) ? 8 : 4)
-    {
-        if (buffer[i] != SEQ_MIDIPUTC) continue;
-
-        dev_id = buffer[i + 2];
-        value = buffer[i + 1];
-
-        if (dev_id >= MIDM_NumDevs) continue;
-        src = MidiInDev + dev_id;
-        if (src->state <= 0) continue;
-
-        if (value == 0xf0 || src->state & 2) /* system exclusive */
-            handle_sysex_data(src, value, time - src->startTime);
-        else
-            handle_regular_data(src, value, time - src->startTime);
-    }
+    params.buffer = buffer;
+    params.len = len;
+    OSS_CALL(midi_handle_data, &params);
 }
 
 static DWORD WINAPI midRecThread(void *arg)
@@ -565,6 +445,7 @@ static DWORD WINAPI notify_thread(void *p)
     {
         OSS_CALL(midi_notify_wait, &params);
         if (quit) break;
+        if (notify.send_notify) notify_client(&notify);
     }
     return 0;
 }
diff --git a/dlls/wineoss.drv/oss.c b/dlls/wineoss.drv/oss.c
index 8fda9270a4e..c5b422a60c9 100644
--- a/dlls/wineoss.drv/oss.c
+++ b/dlls/wineoss.drv/oss.c
@@ -1412,5 +1412,5 @@ unixlib_entry_t __wine_unix_call_funcs[] =
     midi_notify_wait,
 
     midi_seq_open,
-    midi_in_lock,
+    midi_handle_data,
 };
diff --git a/dlls/wineoss.drv/ossmidi.c b/dlls/wineoss.drv/ossmidi.c
index 0790eaaec1a..1695f1d2f7b 100644
--- a/dlls/wineoss.drv/ossmidi.c
+++ b/dlls/wineoss.drv/ossmidi.c
@@ -68,7 +68,11 @@ static struct midi_src srcs[MAX_MIDIINDRV];
 
 static pthread_mutex_t notify_mutex = PTHREAD_MUTEX_INITIALIZER;
 static pthread_cond_t notify_read_cond = PTHREAD_COND_INITIALIZER;
+static pthread_cond_t notify_write_cond = PTHREAD_COND_INITIALIZER;
 static BOOL notify_quit;
+#define NOTIFY_BUFFER_SIZE 64 + 1 /* + 1 for the sentinel */
+static struct notify_context notify_buffer[NOTIFY_BUFFER_SIZE];
+static struct notify_context *notify_read = notify_buffer, *notify_write = notify_buffer;
 
 typedef struct sVoice
 {
@@ -151,19 +155,59 @@ static void in_buffer_unlock(void)
     pthread_mutex_unlock(&in_buffer_mutex);
 }
 
-NTSTATUS midi_in_lock(void *args)
+/*
+ * notify buffer: The notification ring buffer is implemented so that
+ * there is always at least one unused sentinel before the current
+ * read position in order to allow detection of the full vs empty
+ * state.
+ */
+static struct notify_context *notify_buffer_next(struct notify_context *notify)
 {
-    if (args) in_buffer_lock();
-    else in_buffer_unlock();
+    if (++notify >= notify_buffer + ARRAY_SIZE(notify_buffer))
+        notify = notify_buffer;
 
-    return STATUS_SUCCESS;
+    return notify;
+}
+
+static BOOL notify_buffer_empty(void)
+{
+    return notify_read == notify_write;
+}
+
+static BOOL notify_buffer_full(void)
+{
+    return notify_buffer_next(notify_write) == notify_read;
+}
+
+static BOOL notify_buffer_add(struct notify_context *notify)
+{
+    if (notify_buffer_full()) return FALSE;
+
+    *notify_write = *notify;
+    notify_write = notify_buffer_next(notify_write);
+    return TRUE;
+}
+
+static BOOL notify_buffer_remove(struct notify_context *notify)
+{
+    if (notify_buffer_empty()) return FALSE;
+
+    *notify = *notify_read;
+    notify_read = notify_buffer_next(notify_read);
+    return TRUE;
 }
 
 static void notify_post(struct notify_context *notify)
 {
     pthread_mutex_lock(&notify_mutex);
 
-    if (notify) FIXME("Not yet handled\n");
+    if (notify)
+    {
+        while (notify_buffer_full())
+            pthread_cond_wait(&notify_write_cond, &notify_mutex);
+
+        notify_buffer_add(notify);
+    }
     else notify_quit = TRUE;
     pthread_cond_signal(&notify_read_cond);
 
@@ -1157,6 +1201,133 @@ static UINT midi_out_reset(WORD dev_id)
     return MMSYSERR_NOERROR;
 }
 
+static void handle_sysex_data(struct midi_src *src, unsigned char value, UINT time)
+{
+    struct notify_context notify;
+    MIDIHDR *hdr;
+    BOOL done = FALSE;
+
+    src->state |= 2;
+    src->incLen = 0;
+
+    in_buffer_lock();
+
+    hdr = src->lpQueueHdr;
+    if (hdr)
+    {
+        BYTE *data = (BYTE *)hdr->lpData;
+
+        data[hdr->dwBytesRecorded++] = value;
+        if (hdr->dwBytesRecorded == hdr->dwBufferLength)
+            done = TRUE;
+    }
+
+    if (value == 0xf7) /* end */
+    {
+        src->state &= ~2;
+        done = TRUE;
+    }
+
+    if (done && hdr)
+    {
+        src->lpQueueHdr = hdr->lpNext;
+        hdr->dwFlags &= ~MHDR_INQUEUE;
+        hdr->dwFlags |= MHDR_DONE;
+        set_in_notify(&notify, src, src - srcs, MIM_LONGDATA, (UINT_PTR)hdr, time);
+        notify_post(&notify);
+    }
+
+    in_buffer_unlock();
+}
+
+static void handle_regular_data(struct midi_src *src, unsigned char value, UINT time)
+{
+    struct notify_context notify;
+    UINT to_send = 0;
+
+#define IS_CMD(_x)     (((_x) & 0x80) == 0x80)
+#define IS_SYS_CMD(_x) (((_x) & 0xF0) == 0xF0)
+
+    if (!IS_CMD(value) && src->incLen == 0) /* try to reuse old cmd */
+    {
+        if (IS_CMD(src->incPrev) && !IS_SYS_CMD(src->incPrev))
+        {
+            src->incoming[0] = src->incPrev;
+            src->incLen = 1;
+        }
+        else
+        {
+            /* FIXME: should generate MIM_ERROR notification */
+            return;
+        }
+    }
+    src->incoming[(int)src->incLen++] = value;
+    if (src->incLen == 1 && !IS_SYS_CMD(src->incoming[0]))
+        /* store new cmd, just in case */
+        src->incPrev = src->incoming[0];
+
+#undef IS_CMD
+#undef IS_SYS_CMD
+
+    switch (src->incoming[0] & 0xF0)
+    {
+    case MIDI_NOTEOFF:
+    case MIDI_NOTEON:
+    case MIDI_KEY_PRESSURE:
+    case MIDI_CTL_CHANGE:
+    case MIDI_PITCH_BEND:
+        if (src->incLen == 3)
+            to_send = (src->incoming[2] << 16) | (src->incoming[1] << 8) |
+                src->incoming[0];
+        break;
+    case MIDI_PGM_CHANGE:
+    case MIDI_CHN_PRESSURE:
+        if (src->incLen == 2)
+            to_send = (src->incoming[1] << 8) | src->incoming[0];
+        break;
+    case MIDI_SYSTEM_PREFIX:
+        if (src->incLen == 1)
+            to_send = src->incoming[0];
+        break;
+    }
+
+    if (to_send)
+    {
+        src->incLen = 0;
+        set_in_notify(&notify, src, src - srcs, MIM_DATA, to_send, time);
+        notify_post(&notify);
+    }
+}
+
+NTSTATUS midi_handle_data(void *args)
+{
+    struct midi_handle_data_params *params = args;
+    unsigned char *buffer = params->buffer;
+    unsigned int len = params->len;
+    unsigned int time = NtGetTickCount(), i;
+    struct midi_src *src;
+    unsigned char value;
+    WORD dev_id;
+
+    for (i = 0; i < len; i += (buffer[i] & 0x80) ? 8 : 4)
+    {
+        if (buffer[i] != SEQ_MIDIPUTC) continue;
+
+        dev_id = buffer[i + 2];
+        value = buffer[i + 1];
+
+        if (dev_id >= num_srcs) continue;
+        src = srcs + dev_id;
+        if (src->state <= 0) continue;
+
+        if (value == 0xf0 || src->state & 2) /* system exclusive */
+            handle_sysex_data(src, value, time - src->startTime);
+        else
+            handle_regular_data(src, value, time - src->startTime);
+    }
+    return STATUS_SUCCESS;
+}
+
 static UINT midi_in_add_buffer(WORD dev_id, MIDIHDR *hdr, UINT hdr_size)
 {
     struct midi_src *src;
@@ -1397,11 +1568,15 @@ NTSTATUS midi_notify_wait(void *args)
 
     pthread_mutex_lock(&notify_mutex);
 
-    while (!notify_quit)
+    while (!notify_quit && notify_buffer_empty())
         pthread_cond_wait(&notify_read_cond, &notify_mutex);
 
     *params->quit = notify_quit;
-
+    if (!notify_quit)
+    {
+        notify_buffer_remove(params->notify);
+        pthread_cond_signal(&notify_write_cond);
+    }
     pthread_mutex_unlock(&notify_mutex);
 
     return STATUS_SUCCESS;
diff --git a/dlls/wineoss.drv/unixlib.h b/dlls/wineoss.drv/unixlib.h
index ddeba49556c..90d0c47421c 100644
--- a/dlls/wineoss.drv/unixlib.h
+++ b/dlls/wineoss.drv/unixlib.h
@@ -279,6 +279,12 @@ struct midi_seq_open_params
     int fd;
 };
 
+struct midi_handle_data_params
+{
+    unsigned char *buffer;
+    unsigned int len;
+};
+
 enum oss_funcs
 {
     oss_test_connect,
@@ -311,7 +317,7 @@ enum oss_funcs
     oss_midi_notify_wait,
 
     oss_midi_seq_open, /* temporary */
-    oss_midi_in_lock,
+    oss_midi_handle_data,
 };
 
 NTSTATUS midi_init(void *args) DECLSPEC_HIDDEN;
@@ -320,7 +326,7 @@ NTSTATUS midi_out_message(void *args) DECLSPEC_HIDDEN;
 NTSTATUS midi_in_message(void *args) DECLSPEC_HIDDEN;
 NTSTATUS midi_notify_wait(void *args) DECLSPEC_HIDDEN;
 NTSTATUS midi_seq_open(void *args) DECLSPEC_HIDDEN;
-NTSTATUS midi_in_lock(void *args) DECLSPEC_HIDDEN;
+NTSTATUS midi_handle_data(void *args) DECLSPEC_HIDDEN;
 
 extern unixlib_handle_t oss_handle;
 
-- 
2.25.1




More information about the wine-devel mailing list