[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, &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