[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, ¶ms);
}
static DWORD WINAPI midRecThread(void *arg)
@@ -565,6 +445,7 @@ static DWORD WINAPI notify_thread(void *p)
{
OSS_CALL(midi_notify_wait, ¶ms);
if (quit) break;
+ if (notify.send_notify) notify_client(¬ify);
}
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(¬ify_mutex);
- if (notify) FIXME("Not yet handled\n");
+ if (notify)
+ {
+ while (notify_buffer_full())
+ pthread_cond_wait(¬ify_write_cond, ¬ify_mutex);
+
+ notify_buffer_add(notify);
+ }
else notify_quit = TRUE;
pthread_cond_signal(¬ify_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(¬ify, src, src - srcs, MIM_LONGDATA, (UINT_PTR)hdr, time);
+ notify_post(¬ify);
+ }
+
+ 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(¬ify, src, src - srcs, MIM_DATA, to_send, time);
+ notify_post(¬ify);
+ }
+}
+
+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(¬ify_mutex);
- while (!notify_quit)
+ while (!notify_quit && notify_buffer_empty())
pthread_cond_wait(¬ify_read_cond, ¬ify_mutex);
*params->quit = notify_quit;
-
+ if (!notify_quit)
+ {
+ notify_buffer_remove(params->notify);
+ pthread_cond_signal(¬ify_write_cond);
+ }
pthread_mutex_unlock(¬ify_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