[PATCH 5/6] wineoss: Move MIDM_OPEN and MIDM_CLOSE to the unixlib.

Andrew Eikum aeikum at codeweavers.com
Fri Apr 29 08:59:15 CDT 2022


Signed-off-by: Andrew Eikum <aeikum at codeweavers.com>

On Fri, Apr 29, 2022 at 08:29:57AM +0100, Huw Davies wrote:
> Signed-off-by: Huw Davies <huw at codeweavers.com>
> ---
>  dlls/wineoss.drv/Makefile.in |   2 +-
>  dlls/wineoss.drv/midi.c      | 243 -----------------------------------
>  dlls/wineoss.drv/oss.c       |   3 -
>  dlls/wineoss.drv/ossmidi.c   | 193 +++++++++++++++++++++++++---
>  dlls/wineoss.drv/unixlib.h   |  35 -----
>  5 files changed, 175 insertions(+), 301 deletions(-)
> 
> diff --git a/dlls/wineoss.drv/Makefile.in b/dlls/wineoss.drv/Makefile.in
> index 04b438da71e..13fb18b6004 100644
> --- a/dlls/wineoss.drv/Makefile.in
> +++ b/dlls/wineoss.drv/Makefile.in
> @@ -3,7 +3,7 @@ MODULE    = wineoss.drv
>  UNIXLIB   = wineoss.so
>  IMPORTS   = uuid ole32 user32 advapi32
>  DELAYIMPORTS = winmm
> -EXTRALIBS = $(OSS4_LIBS)
> +EXTRALIBS = $(OSS4_LIBS) $(PTHREAD_LIBS)
>  EXTRAINCL = $(OSS4_CFLAGS)
>  
>  EXTRADLLFLAGS = -mcygwin
> diff --git a/dlls/wineoss.drv/midi.c b/dlls/wineoss.drv/midi.c
> index c83dd55fd6b..84a4fac4b74 100644
> --- a/dlls/wineoss.drv/midi.c
> +++ b/dlls/wineoss.drv/midi.c
> @@ -63,23 +63,10 @@
>  
>  WINE_DEFAULT_DEBUG_CHANNEL(midi);
>  
> -static WINE_MIDIIN *MidiInDev;
> -
> -/* this is the total number of MIDI out devices found */
> -static	int 		MIDM_NumDevs = 0;
> -
> -static	int		numStartedMidiIn = 0;
> -
> -static int rec_cancel_pipe[2];
> -static HANDLE hThread;
> -
>  /*======================================================================*
>   *                  Low level MIDI implementation			*
>   *======================================================================*/
>  
> -static int midiOpenSeq(void);
> -static int midiCloseSeq(int);
> -
>  static int MIDI_loadcount;
>  /**************************************************************************
>   * 			OSS_MidiInit				[internal]
> @@ -100,11 +87,6 @@ static LRESULT OSS_MidiInit(void)
>      params.err = &err;
>      OSS_CALL(midi_init, &params);
>  
> -    if (!err)
> -    {
> -        MidiInDev = params.srcs;
> -        MIDM_NumDevs = params.num_srcs;
> -    }
>      return err;
>  }
>  
> @@ -120,9 +102,6 @@ static LRESULT OSS_MidiExit(void)
>      if (--MIDI_loadcount)
>          return 1;
>  
> -    MidiInDev = NULL;
> -    MIDM_NumDevs = 0;
> -
>      return 0;
>  }
>  
> @@ -135,224 +114,6 @@ static void notify_client(struct notify_context *notify)
>                     notify->instance, notify->param_1, notify->param_2);
>  }
>  
> -/**************************************************************************
> - * 			MIDI_NotifyClient			[internal]
> - */
> -static void MIDI_NotifyClient(UINT wDevID, WORD wMsg,
> -			      DWORD_PTR dwParam1, DWORD_PTR dwParam2)
> -{
> -    DWORD_PTR 		dwCallBack;
> -    UINT 		uFlags;
> -    HANDLE		hDev;
> -    DWORD_PTR 		dwInstance;
> -
> -    TRACE("wDevID = %04X wMsg = %d dwParm1 = %04lX dwParam2 = %04lX\n",
> -	  wDevID, wMsg, dwParam1, dwParam2);
> -
> -    switch (wMsg) {
> -    case MIM_OPEN:
> -    case MIM_CLOSE:
> -    case MIM_DATA:
> -    case MIM_LONGDATA:
> -    case MIM_ERROR:
> -    case MIM_LONGERROR:
> -    case MIM_MOREDATA:
> -	if (wDevID > MIDM_NumDevs) return;
> -
> -	dwCallBack = MidiInDev[wDevID].midiDesc.dwCallback;
> -	uFlags = MidiInDev[wDevID].wFlags;
> -	hDev = MidiInDev[wDevID].midiDesc.hMidi;
> -	dwInstance = MidiInDev[wDevID].midiDesc.dwInstance;
> -	break;
> -    default:
> -	ERR("Unsupported MSW-MIDI message %u\n", wMsg);
> -	return;
> -    }
> -
> -    DriverCallback(dwCallBack, uFlags, hDev, wMsg, dwInstance, dwParam1, dwParam2);
> -}
> -
> -/**************************************************************************
> - * 			midiOpenSeq				[internal]
> - */
> -static int midiOpenSeq(void)
> -{
> -    struct midi_seq_open_params params;
> -
> -    params.close = 0;
> -    params.fd = -1;
> -    OSS_CALL(midi_seq_open, &params);
> -
> -    return params.fd;
> -}
> -
> -/**************************************************************************
> - * 			midiCloseSeq				[internal]
> - */
> -static int midiCloseSeq(int fd)
> -{
> -    struct midi_seq_open_params params;
> -
> -    params.close = 1;
> -    params.fd = fd;
> -    OSS_CALL(midi_seq_open, &params);
> -
> -    return 0;
> -}
> -
> -static void handle_midi_data(unsigned char *buffer, unsigned int len)
> -{
> -    struct midi_handle_data_params params;
> -
> -    params.buffer = buffer;
> -    params.len = len;
> -    OSS_CALL(midi_handle_data, &params);
> -}
> -
> -static DWORD WINAPI midRecThread(void *arg)
> -{
> -    int fd = (int)(INT_PTR)arg;
> -    unsigned char buffer[256];
> -    int len;
> -    struct pollfd pollfd[2];
> -
> -    pollfd[0].fd = rec_cancel_pipe[0];
> -    pollfd[0].events = POLLIN;
> -    pollfd[1].fd = fd;
> -    pollfd[1].events = POLLIN;
> -
> -    while (1)
> -    {
> -	/* Check if an event is present */
> -	if (poll(pollfd, ARRAY_SIZE(pollfd), -1) <= 0)
> -	    continue;
> -
> -	if (pollfd[0].revents & POLLIN) /* cancelled */
> -	    break;
> -
> -	len = read(fd, buffer, sizeof(buffer));
> -
> -	if (len > 0 && len % 4 == 0)
> -	    handle_midi_data(buffer, len);
> -    }
> -    return 0;
> -}
> -
> -/**************************************************************************
> - * 			midOpen					[internal]
> - */
> -static DWORD midOpen(WORD wDevID, LPMIDIOPENDESC lpDesc, DWORD dwFlags)
> -{
> -    int fd;
> -
> -    TRACE("(%04X, %p, %08X);\n", wDevID, lpDesc, dwFlags);
> -
> -    if (lpDesc == NULL) {
> -	WARN("Invalid Parameter !\n");
> -	return MMSYSERR_INVALPARAM;
> -    }
> -
> -    /* FIXME :
> -     *	how to check that content of lpDesc is correct ?
> -     */
> -    if (wDevID >= MIDM_NumDevs) {
> -	WARN("wDevID too large (%u) !\n", wDevID);
> -	return MMSYSERR_BADDEVICEID;
> -    }
> -    if (MidiInDev[wDevID].state == -1) {        
> -        WARN("device disabled\n");
> -        return MIDIERR_NODEVICE;
> -    }
> -    if (MidiInDev[wDevID].midiDesc.hMidi != 0) {
> -	WARN("device already open !\n");
> -	return MMSYSERR_ALLOCATED;
> -    }
> -    if ((dwFlags & MIDI_IO_STATUS) != 0) {
> -	WARN("No support for MIDI_IO_STATUS in dwFlags yet, ignoring it\n");
> -	dwFlags &= ~MIDI_IO_STATUS;
> -    }
> -    if ((dwFlags & ~CALLBACK_TYPEMASK) != 0) {
> -	FIXME("Bad dwFlags\n");
> -	return MMSYSERR_INVALFLAG;
> -    }
> -
> -    fd = midiOpenSeq();
> -    if (fd < 0) {
> -	return MMSYSERR_ERROR;
> -    }
> -
> -    if (numStartedMidiIn++ == 0) {
> -	pipe(rec_cancel_pipe);
> -	hThread = CreateThread(NULL, 0, midRecThread, (void *)(INT_PTR)fd, 0, NULL);
> -	if (!hThread) {
> -	    close(rec_cancel_pipe[0]);
> -	    close(rec_cancel_pipe[1]);
> -	    numStartedMidiIn = 0;
> -	    WARN("Couldn't create thread for midi-in\n");
> -	    midiCloseSeq(fd);
> -	    return MMSYSERR_ERROR;
> -	}
> -        SetThreadPriority(hThread, THREAD_PRIORITY_TIME_CRITICAL);
> -	TRACE("Created thread for midi-in\n");
> -    }
> -
> -    MidiInDev[wDevID].wFlags = HIWORD(dwFlags & CALLBACK_TYPEMASK);
> -
> -    MidiInDev[wDevID].lpQueueHdr = NULL;
> -    MidiInDev[wDevID].midiDesc = *lpDesc;
> -    MidiInDev[wDevID].state = 0;
> -    MidiInDev[wDevID].incLen = 0;
> -    MidiInDev[wDevID].startTime = 0;
> -    MidiInDev[wDevID].fd = fd;
> -
> -    MIDI_NotifyClient(wDevID, MIM_OPEN, 0L, 0L);
> -    return MMSYSERR_NOERROR;
> -}
> -
> -/**************************************************************************
> - * 			midClose				[internal]
> - */
> -static DWORD midClose(WORD wDevID)
> -{
> -    int		ret = MMSYSERR_NOERROR;
> -
> -    TRACE("(%04X);\n", wDevID);
> -
> -    if (wDevID >= MIDM_NumDevs) {
> -	WARN("wDevID too big (%u) !\n", wDevID);
> -	return MMSYSERR_BADDEVICEID;
> -    }
> -    if (MidiInDev[wDevID].midiDesc.hMidi == 0) {
> -	WARN("device not opened !\n");
> -	return MMSYSERR_ERROR;
> -    }
> -    if (MidiInDev[wDevID].lpQueueHdr != 0) {
> -	return MIDIERR_STILLPLAYING;
> -    }
> -
> -    if (MidiInDev[wDevID].fd == -1) {
> -	WARN("ooops !\n");
> -	return MMSYSERR_ERROR;
> -    }
> -    if (--numStartedMidiIn == 0) {
> -	TRACE("Stopping thread for midi-in\n");
> -	write(rec_cancel_pipe[1], "x", 1);
> -	if (WaitForSingleObject(hThread, 5000) != WAIT_OBJECT_0) {
> -	    WARN("Thread end not signaled, force termination\n");
> -	    TerminateThread(hThread, 0);
> -	}
> -	close(rec_cancel_pipe[0]);
> -	close(rec_cancel_pipe[1]);
> -    	TRACE("Stopped thread for midi-in\n");
> -    }
> -    midiCloseSeq(MidiInDev[wDevID].fd);
> -    MidiInDev[wDevID].fd = -1;
> -
> -    MIDI_NotifyClient(wDevID, MIM_CLOSE, 0L, 0L);
> -    MidiInDev[wDevID].midiDesc.hMidi = 0;
> -    return ret;
> -}
> -
>  /*======================================================================*
>   *                  	    MIDI entry points 				*
>   *======================================================================*/
> @@ -374,10 +135,6 @@ DWORD WINAPI OSS_midMessage(UINT wDevID, UINT wMsg, DWORD_PTR dwUser,
>          return OSS_MidiInit();
>      case DRVM_EXIT:
>          return OSS_MidiExit();
> -    case MIDM_OPEN:
> -	return midOpen(wDevID, (LPMIDIOPENDESC)dwParam1, dwParam2);
> -    case MIDM_CLOSE:
> -	return midClose(wDevID);
>      }
>  
>      params.dev_id = wDevID;
> diff --git a/dlls/wineoss.drv/oss.c b/dlls/wineoss.drv/oss.c
> index c5b422a60c9..b0a411ecd9b 100644
> --- a/dlls/wineoss.drv/oss.c
> +++ b/dlls/wineoss.drv/oss.c
> @@ -1410,7 +1410,4 @@ unixlib_entry_t __wine_unix_call_funcs[] =
>      midi_out_message,
>      midi_in_message,
>      midi_notify_wait,
> -
> -    midi_seq_open,
> -    midi_handle_data,
>  };
> diff --git a/dlls/wineoss.drv/ossmidi.c b/dlls/wineoss.drv/ossmidi.c
> index 9c8ca8a8f39..072a9815c35 100644
> --- a/dlls/wineoss.drv/ossmidi.c
> +++ b/dlls/wineoss.drv/ossmidi.c
> @@ -33,6 +33,7 @@
>  #include <stdint.h>
>  #include <time.h>
>  #include <unistd.h>
> +#include <poll.h>
>  #include <errno.h>
>  #include <sys/types.h>
>  #include <sys/stat.h>
> @@ -45,6 +46,7 @@
>  #define WIN32_NO_STATUS
>  #include "winternl.h"
>  #include "audioclient.h"
> +#include "mmddk.h"
>  
>  #include "wine/debug.h"
>  #include "wine/unixlib.h"
> @@ -62,12 +64,30 @@ struct midi_dest
>      int                 fd;
>  };
>  
> +struct midi_src
> +{
> +    int                 state; /* -1 disabled, 0 is no recording started, 1 in recording, bit 2 set if in sys exclusive recording */
> +    MIDIOPENDESC        midiDesc;
> +    WORD                wFlags;
> +    MIDIHDR            *lpQueueHdr;
> +    unsigned char       incoming[3];
> +    unsigned char       incPrev;
> +    char                incLen;
> +    UINT                startTime;
> +    MIDIINCAPSW         caps;
> +    int                 fd;
> +};
> +
>  static pthread_mutex_t in_buffer_mutex = PTHREAD_MUTEX_INITIALIZER;
>  
>  static unsigned int num_dests, num_srcs, num_synths, seq_refs;
>  static struct midi_dest dests[MAX_MIDIOUTDRV];
>  static struct midi_src srcs[MAX_MIDIINDRV];
>  
> +static unsigned int num_midi_in_started;
> +static int rec_cancel_pipe[2];
> +static pthread_t rec_thread_id;
> +
>  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;
> @@ -281,18 +301,6 @@ static int seq_close(int fd)
>      return 0;
>  }
>  
> -NTSTATUS midi_seq_open(void *args)
> -{
> -    struct midi_seq_open_params *params = args;
> -
> -    if (!params->close)
> -        params->fd = seq_open();
> -    else
> -        seq_close(params->fd);
> -
> -    return STATUS_SUCCESS;
> -}
> -
>  NTSTATUS midi_init(void *args)
>  {
>      struct midi_init_params *params = args;
> @@ -499,8 +507,6 @@ wrapup:
>      seq_close(fd);
>  
>      *params->err = 0;
> -    params->num_srcs = num_srcs;
> -    params->srcs = srcs;
>  
>      return STATUS_SUCCESS;
>  }
> @@ -1313,11 +1319,8 @@ static void handle_regular_data(struct midi_src *src, unsigned char value, UINT
>      }
>  }
>  
> -NTSTATUS midi_handle_data(void *args)
> +static void handle_midi_data(unsigned char *buffer, unsigned int len)
>  {
> -    struct midi_handle_data_params *params = args;
> -    unsigned char *buffer = params->buffer;
> -    unsigned int len = params->len;
>      unsigned int time = get_time_msec(), i;
>      struct midi_src *src;
>      unsigned char value;
> @@ -1339,7 +1342,153 @@ NTSTATUS midi_handle_data(void *args)
>          else
>              handle_regular_data(src, value, time - src->startTime);
>      }
> -    return STATUS_SUCCESS;
> +}
> +
> +static void *rec_thread_proc(void *arg)
> +{
> +    int fd = PtrToLong(arg);
> +    unsigned char buffer[256];
> +    int len;
> +    struct pollfd pollfd[2];
> +
> +    pollfd[0].fd = rec_cancel_pipe[0];
> +    pollfd[0].events = POLLIN;
> +    pollfd[1].fd = fd;
> +    pollfd[1].events = POLLIN;
> +
> +    while (1)
> +    {
> +        /* Check if an event is present */
> +        if (poll(pollfd, ARRAY_SIZE(pollfd), -1) <= 0)
> +            continue;
> +
> +        if (pollfd[0].revents & POLLIN) /* cancelled */
> +            break;
> +
> +        len = read(fd, buffer, sizeof(buffer));
> +
> +        if (len > 0 && len % 4 == 0)
> +            handle_midi_data(buffer, len);
> +    }
> +    return NULL;
> +}
> +
> +static UINT midi_in_open(WORD dev_id, MIDIOPENDESC *desc, UINT flags, struct notify_context *notify)
> +{
> +    struct midi_src *src;
> +    int fd;
> +
> +    TRACE("(%04X, %p, %08X);\n", dev_id, desc, flags);
> +
> +    if (desc == NULL)
> +    {
> +        WARN("Invalid Parameter !\n");
> +        return MMSYSERR_INVALPARAM;
> +    }
> +
> +    /* FIXME :
> +     * how to check that content of lpDesc is correct ?
> +     */
> +    if (dev_id >= num_srcs)
> +    {
> +        WARN("wDevID too large (%u) !\n", dev_id);
> +        return MMSYSERR_BADDEVICEID;
> +    }
> +    src = srcs + dev_id;
> +    if (src->state == -1)
> +    {
> +        WARN("device disabled\n");
> +        return MIDIERR_NODEVICE;
> +    }
> +    if (src->midiDesc.hMidi != 0)
> +    {
> +        WARN("device already open !\n");
> +        return MMSYSERR_ALLOCATED;
> +    }
> +    if ((flags & MIDI_IO_STATUS) != 0)
> +    {
> +        WARN("No support for MIDI_IO_STATUS in dwFlags yet, ignoring it\n");
> +        flags &= ~MIDI_IO_STATUS;
> +    }
> +    if ((flags & ~CALLBACK_TYPEMASK) != 0)
> +    {
> +        FIXME("Bad flags\n");
> +        return MMSYSERR_INVALFLAG;
> +    }
> +
> +    fd = seq_open();
> +    if (fd < 0)
> +        return MMSYSERR_ERROR;
> +
> +    if (num_midi_in_started++ == 0)
> +    {
> +        pipe(rec_cancel_pipe);
> +        if (pthread_create(&rec_thread_id, NULL, rec_thread_proc, LongToPtr(fd)))
> +        {
> +            close(rec_cancel_pipe[0]);
> +            close(rec_cancel_pipe[1]);
> +            num_midi_in_started = 0;
> +            WARN("Couldn't create thread for midi-in\n");
> +            seq_close(fd);
> +            return MMSYSERR_ERROR;
> +        }
> +        TRACE("Created thread for midi-in\n");
> +    }
> +
> +    src->wFlags = HIWORD(flags & CALLBACK_TYPEMASK);
> +
> +    src->lpQueueHdr = NULL;
> +    src->midiDesc = *desc;
> +    src->state = 0;
> +    src->incLen = 0;
> +    src->startTime = 0;
> +    src->fd = fd;
> +
> +    set_in_notify(notify, src, dev_id, MIM_OPEN, 0, 0);
> +    return MMSYSERR_NOERROR;
> +}
> +
> +static UINT midi_in_close(WORD dev_id, struct notify_context *notify)
> +{
> +    struct midi_src *src;
> +
> +    TRACE("(%04X);\n", dev_id);
> +
> +    if (dev_id >= num_srcs)
> +    {
> +        WARN("dev_id too big (%u) !\n", dev_id);
> +        return MMSYSERR_BADDEVICEID;
> +    }
> +    src = srcs + dev_id;
> +    if (src->midiDesc.hMidi == 0)
> +    {
> +        WARN("device not opened !\n");
> +        return MMSYSERR_ERROR;
> +    }
> +    if (src->lpQueueHdr != 0)
> +        return MIDIERR_STILLPLAYING;
> +
> +    if (src->fd == -1)
> +    {
> +        WARN("ooops !\n");
> +        return MMSYSERR_ERROR;
> +    }
> +    if (--num_midi_in_started == 0)
> +    {
> +        TRACE("Stopping thread for midi-in\n");
> +        write(rec_cancel_pipe[1], "x", 1);
> +        pthread_join(rec_thread_id, NULL);
> +        close(rec_cancel_pipe[0]);
> +        close(rec_cancel_pipe[1]);
> +        TRACE("Stopped thread for midi-in\n");
> +    }
> +    seq_close(src->fd);
> +    src->fd = -1;
> +
> +    set_in_notify(notify, src, dev_id, MIM_CLOSE, 0, 0);
> +    src->midiDesc.hMidi = 0;
> +
> +    return MMSYSERR_NOERROR;
>  }
>  
>  static UINT midi_in_add_buffer(WORD dev_id, MIDIHDR *hdr, UINT hdr_size)
> @@ -1544,6 +1693,12 @@ NTSTATUS midi_in_message(void *args)
>          /* FIXME: Pretend this is supported */
>          *params->err = MMSYSERR_NOERROR;
>          break;
> +    case MIDM_OPEN:
> +        *params->err = midi_in_open(params->dev_id, (MIDIOPENDESC *)params->param_1, params->param_2, params->notify);
> +        break;
> +    case MIDM_CLOSE:
> +        *params->err = midi_in_close(params->dev_id, params->notify);
> +        break;
>      case MIDM_ADDBUFFER:
>          *params->err = midi_in_add_buffer(params->dev_id, (MIDIHDR *)params->param_1, params->param_2);
>          break;
> diff --git a/dlls/wineoss.drv/unixlib.h b/dlls/wineoss.drv/unixlib.h
> index 90d0c47421c..d3dda7c76f2 100644
> --- a/dlls/wineoss.drv/unixlib.h
> +++ b/dlls/wineoss.drv/unixlib.h
> @@ -209,27 +209,9 @@ struct is_started_params
>      HRESULT result;
>  };
>  
> -#include <mmddk.h> /* temporary */
> -
> -typedef struct midi_src
> -{
> -    int                 state; /* -1 disabled, 0 is no recording started, 1 in recording, bit 2 set if in sys exclusive recording */
> -    MIDIOPENDESC        midiDesc;
> -    WORD                wFlags;
> -    MIDIHDR            *lpQueueHdr;
> -    unsigned char       incoming[3];
> -    unsigned char       incPrev;
> -    char                incLen;
> -    UINT                startTime;
> -    MIDIINCAPSW         caps;
> -    int                 fd;
> -} WINE_MIDIIN;
> -
>  struct midi_init_params
>  {
>      UINT *err;
> -    unsigned int num_srcs;
> -    struct midi_src *srcs;
>  };
>  
>  struct notify_context
> @@ -273,18 +255,6 @@ struct midi_notify_wait_params
>      struct notify_context *notify;
>  };
>  
> -struct midi_seq_open_params
> -{
> -    int close;
> -    int fd;
> -};
> -
> -struct midi_handle_data_params
> -{
> -    unsigned char *buffer;
> -    unsigned int len;
> -};
> -
>  enum oss_funcs
>  {
>      oss_test_connect,
> @@ -315,9 +285,6 @@ enum oss_funcs
>      oss_midi_out_message,
>      oss_midi_in_message,
>      oss_midi_notify_wait,
> -
> -    oss_midi_seq_open, /* temporary */
> -    oss_midi_handle_data,
>  };
>  
>  NTSTATUS midi_init(void *args) DECLSPEC_HIDDEN;
> @@ -325,8 +292,6 @@ NTSTATUS midi_release(void *args) DECLSPEC_HIDDEN;
>  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_handle_data(void *args) DECLSPEC_HIDDEN;
>  
>  extern unixlib_handle_t oss_handle;
>  
> -- 
> 2.25.1
> 
> 



More information about the wine-devel mailing list