[PATCH 2/6] wineoss: Move the midi in data handlers to the unixlib.
Andrew Eikum
aeikum at codeweavers.com
Fri Apr 29 08:58:47 CDT 2022
Signed-off-by: Andrew Eikum <aeikum at codeweavers.com>
On Fri, Apr 29, 2022 at 08:29:54AM +0100, Huw Davies wrote:
> 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