[PATCH 3/6] winecoreaudio: Move the midi input event processing to the unixlib.
Andrew Eikum
aeikum at codeweavers.com
Wed Dec 1 08:45:42 CST 2021
Signed-off-by: Andrew Eikum <aeikum at codeweavers.com>
On Tue, Nov 30, 2021 at 07:56:30AM +0000, Huw Davies wrote:
> Notifications of incoming data are now directly added to a notify
> ring-buffer by macOS's midi read callback. The ring-buffer is
> implemented with an unused sentinel directly before the read ptr to
> distinguish between the full vs empty state. Notifications are
> processed by the client's notify thread via the midi_notify_wait
> syscall.
>
> Note that the read callback thread is not a Win32 thread, so the
> Win32 api cannot be used in anything that it calls.
>
> Signed-off-by: Huw Davies <huw at codeweavers.com>
> ---
> dlls/winecoreaudio.drv/coreaudio.c | 2 -
> dlls/winecoreaudio.drv/coremidi.c | 163 +++++++++++++++++++----
> dlls/winecoreaudio.drv/coremidi.h | 86 ------------
> dlls/winecoreaudio.drv/midi.c | 204 +----------------------------
> dlls/winecoreaudio.drv/unixlib.h | 6 +-
> 5 files changed, 140 insertions(+), 321 deletions(-)
> delete mode 100644 dlls/winecoreaudio.drv/coremidi.h
>
> diff --git a/dlls/winecoreaudio.drv/coreaudio.c b/dlls/winecoreaudio.drv/coreaudio.c
> index 1efcfdba3f4..e6ce5c33e36 100644
> --- a/dlls/winecoreaudio.drv/coreaudio.c
> +++ b/dlls/winecoreaudio.drv/coreaudio.c
> @@ -1634,6 +1634,4 @@ unixlib_entry_t __wine_unix_call_funcs[] =
> midi_out_message,
> midi_in_message,
> midi_notify_wait,
> -
> - midi_in_lock, /* temporary */
> };
> diff --git a/dlls/winecoreaudio.drv/coremidi.c b/dlls/winecoreaudio.drv/coremidi.c
> index bb8cb23f83b..ae8b71e002b 100644
> --- a/dlls/winecoreaudio.drv/coremidi.c
> +++ b/dlls/winecoreaudio.drv/coremidi.c
> @@ -89,7 +89,6 @@
> #include "wine/unixlib.h"
>
> #include "coreaudio.h"
> -#include "coremidi.h"
> #include "unixlib.h"
>
> WINE_DEFAULT_DEBUG_CHANNEL(midi);
> @@ -107,12 +106,24 @@ struct midi_dest
> WORD wFlags;
> };
>
> +struct midi_src
> +{
> + MIDIEndpointRef source;
> +
> + WORD wDevID;
> + int state; /* 0 is no recording started, 1 in recording, bit 2 set if in sys exclusive recording */
> + MIDIINCAPSW caps;
> + MIDIOPENDESC midiDesc;
> + LPMIDIHDR lpQueueHdr;
> + WORD wFlags;
> + DWORD startTime;
> +};
> +
> static MIDIClientRef midi_client;
> static MIDIPortRef midi_out_port, midi_in_port;
> static UINT num_dests, num_srcs;
> static struct midi_dest *dests;
> static struct midi_src *srcs;
> -static CFStringRef midi_in_thread_port_name;
>
> static pthread_mutex_t midi_in_mutex = PTHREAD_MUTEX_INITIALIZER;
>
> @@ -123,6 +134,8 @@ static BOOL notify_quit;
> static struct notify_context notify_buffer[NOTIFY_BUFFER_SIZE];
> static struct notify_context *notify_read, *notify_write;
>
> +#define MAX_MIDI_SYNTHS 1
> +
> NTSTATUS midi_in_lock(void *args)
> {
> BOOL lock = !!args;
> @@ -146,11 +159,49 @@ static void set_in_notify(struct notify_context *notify, struct midi_src *src, W
> notify->instance = src->midiDesc.dwInstance;
> }
>
> +/*
> + * 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 (++notify >= notify_buffer + ARRAY_SIZE(notify_buffer))
> + notify = notify_buffer;
> +
> + return notify;
> +}
> +
> +static void notify_buffer_add(struct notify_context *notify)
> +{
> + struct notify_context *next = notify_buffer_next(notify_write);
> +
> + if (next == notify_read) /* buffer is full - we can't issue a WARN() in a non-Win32 thread */
> + notify_read = notify_buffer_next(notify_read); /* drop the oldest notification */
> + *notify_write = *notify;
> + notify_write = next;
> +}
> +
> +static BOOL notify_buffer_empty(void)
> +{
> + return notify_read == notify_write;
> +}
> +
> +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) notify_buffer_add(notify);
> else notify_quit = TRUE;
> pthread_cond_signal(¬ify_cond);
>
> @@ -169,29 +220,94 @@ static uint64_t get_time_ms(void)
> return mach_absolute_time() / 1000000 * timebase.numer / timebase.denom;
> }
>
> +static void process_sysex_packet(struct midi_src *src, MIDIPacket *packet)
> +{
> + unsigned int pos = 0, len = packet->length, copy_len;
> + DWORD current_time = get_time_ms() - src->startTime;
> + struct notify_context notify;
> +
> + src->state |= 2;
> +
> + midi_in_lock((void *)TRUE);
> +
> + while (len)
> + {
> + MIDIHDR *hdr = src->lpQueueHdr;
> + if (!hdr) break;
> +
> + copy_len = min(len, hdr->dwBufferLength - hdr->dwBytesRecorded);
> + memcpy(hdr->lpData + hdr->dwBytesRecorded, packet->data + pos, copy_len);
> + hdr->dwBytesRecorded += copy_len;
> + len -= copy_len;
> + pos += copy_len;
> +
> + if ((hdr->dwBytesRecorded == hdr->dwBufferLength) ||
> + (*(BYTE*)(hdr->lpData + hdr->dwBytesRecorded - 1) == 0xf7))
> + { /* buffer full or end of sysex message */
> + src->lpQueueHdr = hdr->lpNext;
> + hdr->dwFlags &= ~MHDR_INQUEUE;
> + hdr->dwFlags |= MHDR_DONE;
> + set_in_notify(¬ify, src, src->wDevID, MIM_LONGDATA, (DWORD_PTR)hdr, current_time);
> + notify_post(¬ify);
> + src->state &= ~2;
> + }
> + }
> +
> + midi_in_lock((void *)FALSE);
> +}
> +
> +static void process_small_packet(struct midi_src *src, MIDIPacket *packet)
> +{
> + DWORD current_time = get_time_ms() - src->startTime, data;
> + struct notify_context notify;
> + unsigned int pos = 0;
> +
> + while (pos < packet->length)
> + {
> + data = 0;
> + switch (packet->data[pos] & 0xf0)
> + {
> + case 0xf0:
> + data = packet->data[pos];
> + pos++;
> + break;
> + case 0xc0:
> + case 0xd0:
> + data = (packet->data[pos + 1] << 8) | packet->data[pos];
> + pos += 2;
> + break;
> + default:
> + data = (packet->data[pos + 2] << 16) | (packet->data[pos + 1] << 8) |
> + packet->data[pos];
> + pos += 3;
> + break;
> + }
> + set_in_notify(¬ify, src, src->wDevID, MIM_DATA, data, current_time);
> + notify_post(¬ify);
> + }
> +}
> +
> static void midi_in_read_proc(const MIDIPacketList *pktlist, void *refCon, void *connRefCon)
> {
> - CFMessagePortRef msg_port = CFMessagePortCreateRemote(kCFAllocatorDefault, midi_in_thread_port_name);
> MIDIPacket *packet = (MIDIPacket *)pktlist->packet;
> - CFMutableDataRef data;
> - MIDIMessage msg;
> + WORD dev_id = *(WORD *)connRefCon;
> + struct midi_src *src;
> unsigned int i;
>
> + if (dev_id >= num_srcs) return;
> + src = srcs + dev_id;
> + if (src->state < 1) /* input not started */
> + return;
> +
> for (i = 0; i < pktlist->numPackets; ++i)
> {
> - msg.devID = *(UInt16 *)connRefCon;
> - msg.length = packet->length;
> - data = CFDataCreateMutable(kCFAllocatorDefault, sizeof(msg) + packet->length);
> - if (data)
> - {
> - CFDataAppendBytes(data, (UInt8 *)&msg, sizeof(msg));
> - CFDataAppendBytes(data, packet->data, packet->length);
> - CFMessagePortSendRequest(msg_port, 0, data, 0.0, 0.0, NULL, NULL);
> - CFRelease(data);
> - }
> + if (packet->data[0] == 0xf0 || src->state & 2)
> + process_sysex_packet(src, packet);
> + else
> + process_small_packet(src, packet);
> +
> packet = MIDIPacketNext(packet);
> }
> - CFRelease(msg_port);
> }
>
> NTSTATUS midi_init(void *args)
> @@ -225,7 +341,6 @@ NTSTATUS midi_init(void *args)
>
> if (num_srcs > 0)
> {
> - midi_in_thread_port_name = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("MIDIInThreadPortName.%u"), getpid());
> name = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("WineInputPort.%u"), getpid());
> MIDIInputPortCreate(midi_client, name, midi_in_read_proc, NULL, &midi_in_port);
> CFRelease(name);
> @@ -306,8 +421,6 @@ NTSTATUS midi_init(void *args)
> }
>
> params->num_srcs = num_srcs;
> - params->srcs = srcs;
> - params->midi_in_port = (void *)midi_in_port;
>
> *params->err = DRV_SUCCESS;
> return STATUS_SUCCESS;
> @@ -315,15 +428,8 @@ NTSTATUS midi_init(void *args)
>
> NTSTATUS midi_release(void *args)
> {
> - CFMessagePortRef msg_port;
> -
> if (num_srcs)
> {
> - /* Stop CFRunLoop in MIDIIn_MessageThread */
> - msg_port = CFMessagePortCreateRemote(kCFAllocatorDefault, midi_in_thread_port_name);
> - CFMessagePortSendRequest(msg_port, 1, NULL, 0.0, 0.0, NULL, NULL);
> - CFRelease(msg_port);
> -
> /* stop the notify_wait thread */
> notify_post(NULL);
> }
> @@ -1114,10 +1220,11 @@ NTSTATUS midi_notify_wait(void *args)
>
> pthread_mutex_lock(¬ify_mutex);
>
> - while (!notify_quit)
> + while (!notify_quit && notify_buffer_empty())
> pthread_cond_wait(¬ify_cond, ¬ify_mutex);
>
> *params->quit = notify_quit;
> + if (!notify_quit) notify_buffer_remove(params->notify);
>
> pthread_mutex_unlock(¬ify_mutex);
>
> diff --git a/dlls/winecoreaudio.drv/coremidi.h b/dlls/winecoreaudio.drv/coremidi.h
> deleted file mode 100644
> index e6d5c8c18c8..00000000000
> --- a/dlls/winecoreaudio.drv/coremidi.h
> +++ /dev/null
> @@ -1,86 +0,0 @@
> -/*
> - * Wine Midi driver for Mac OS X
> - *
> - * Copyright 2006 Emmanuel Maillard
> - *
> - * This library is free software; you can redistribute it and/or
> - * modify it under the terms of the GNU Lesser General Public
> - * License as published by the Free Software Foundation; either
> - * version 2.1 of the License, or (at your option) any later version.
> - *
> - * This library is distributed in the hope that it will be useful,
> - * but WITHOUT ANY WARRANTY; without even the implied warranty of
> - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
> - * Lesser General Public License for more details.
> - *
> - * You should have received a copy of the GNU Lesser General Public
> - * License along with this library; if not, write to the Free Software
> - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
> - */
> -
> -#ifndef WINE_COREMIDI_H
> -#define WINE_COREMIDI_H
> -
> -#include <CoreFoundation/CoreFoundation.h>
> -
> -#define MAX_MIDI_SYNTHS 1
> -
> -#ifdef WINE_DEFINITIONS
> -/*
> - * Due to CoreMIDI headers conflict redefine some types for Wine
> - */
> -typedef void *MIDIClientRef;
> -typedef void *MIDIEndpointRef;
> -typedef void *MIDIPortRef;
> -typedef void *MIDIObjectRef;
> -
> -typedef struct MIDIPacketList MIDIPacketList;
> -
> -/*
> - * functions
> - */
> -extern OSStatus MIDIClientDispose(MIDIClientRef client);
> -extern unsigned MIDIGetNumberOfDestinations(void);
> -extern MIDIEndpointRef MIDIGetDestination(unsigned i);
> -extern unsigned MIDIGetNumberOfSources(void);
> -extern MIDIEndpointRef MIDIGetSource(unsigned i);
> -extern OSStatus MIDIOutputPortCreate(MIDIClientRef client, CFStringRef portName, MIDIPortRef *outPort);
> -
> -typedef void (*MIDIReadProc)(const MIDIPacketList *pktlist, void *readProcRefCon, void *srcConnRefCon);
> -extern OSStatus MIDIInputPortCreate(MIDIClientRef client, CFStringRef portName, MIDIReadProc readProc, void *refCon, MIDIPortRef *outPort);
> -
> -extern OSStatus MIDIObjectGetProperties(MIDIObjectRef obj, CFPropertyListRef *outProperties, Boolean deep);
> -
> -extern OSStatus MIDIPortConnectSource(MIDIPortRef port, MIDIEndpointRef source, void *connRefCon);
> -
> -/*
> - * Due to AudioUnit headers conflict redefine some types.
> - */
> -typedef void *AudioUnit;
> -typedef void *AUGraph;
> -
> -extern OSStatus MusicDeviceMIDIEvent(AudioUnit au, UInt32 inStatus, UInt32 inData1, UInt32 inData2, UInt32 inOffsetSampleFrame);
> -extern OSStatus MusicDeviceSysEx(AudioUnit au, const UInt8 *inData, UInt32 inLength);
> -#endif
> -
> -/* midi.c */
> -typedef struct midi_src
> -{
> - MIDIEndpointRef source;
> -
> - WORD wDevID;
> - int state; /* 0 is no recording started, 1 in recording, bit 2 set if in sys exclusive recording */
> - MIDIINCAPSW caps;
> - MIDIOPENDESC midiDesc;
> - LPMIDIHDR lpQueueHdr;
> - WORD wFlags;
> - DWORD startTime;
> -} MIDISource;
> -
> -typedef struct {
> - UInt16 devID;
> - UInt16 length;
> - Byte data[];
> -} MIDIMessage;
> -
> -#endif
> diff --git a/dlls/winecoreaudio.drv/midi.c b/dlls/winecoreaudio.drv/midi.c
> index e9cdb2a8ec4..262713dd003 100644
> --- a/dlls/winecoreaudio.drv/midi.c
> +++ b/dlls/winecoreaudio.drv/midi.c
> @@ -45,31 +45,8 @@
>
> WINE_DEFAULT_DEBUG_CHANNEL(midi);
>
> -#include <mach/mach_time.h>
> -#include <CoreAudio/CoreAudio.h>
> -
> -#define WINE_DEFINITIONS
> -#include "coremidi.h"
> -
> static DWORD MIDIIn_NumDevs = 0;
>
> -
> -static CFStringRef MIDIInThreadPortName;
> -
> -static DWORD WINAPI MIDIIn_MessageThread(LPVOID p);
> -
> -static MIDIPortRef MIDIInPort = NULL;
> -
> -MIDISource *sources;
> -
> -static uint64_t get_time_ms(void)
> -{
> - static mach_timebase_info_data_t timebase;
> -
> - if (!timebase.denom) mach_timebase_info(&timebase);
> - return mach_absolute_time() / 1000000 * timebase.numer / timebase.denom;
> -}
> -
> static void notify_client(struct notify_context *notify)
> {
> TRACE("dev_id=%d msg=%d param1=%04lX param2=%04lX\n", notify->dev_id, notify->msg, notify->param_1, notify->param_2);
> @@ -81,14 +58,17 @@ static void notify_client(struct notify_context *notify)
> static DWORD WINAPI notify_thread(void *p)
> {
> struct midi_notify_wait_params params;
> + struct notify_context notify;
> BOOL quit;
>
> + params.notify = ¬ify;
> params.quit = &quit;
>
> while (1)
> {
> UNIX_CALL(midi_notify_wait, ¶ms);
> if (quit) break;
> + if (notify.send_notify) notify_client(¬ify);
> }
> return 0;
> }
> @@ -108,15 +88,10 @@ static LONG CoreAudio_MIDIInit(void)
> }
>
> MIDIIn_NumDevs = params.num_srcs;
> - sources = params.srcs;
> - MIDIInPort = params.midi_in_port;
>
> if (MIDIIn_NumDevs > 0)
> - {
> - MIDIInThreadPortName = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("MIDIInThreadPortName.%u"), getpid());
> - CloseHandle( CreateThread(NULL, 0, MIDIIn_MessageThread, NULL, 0, NULL));
> CloseHandle(CreateThread(NULL, 0, notify_thread, NULL, 0, NULL));
> - }
> +
> return err;
> }
>
> @@ -125,181 +100,10 @@ static LONG CoreAudio_MIDIRelease(void)
> TRACE("\n");
>
> UNIX_CALL(midi_release, NULL);
> - sources = NULL;
>
> return DRV_SUCCESS;
> }
>
> -
> -/**************************************************************************
> - * 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=%d wMsg=%d dwParm1=%04lX dwParam2=%04lX\n", wDevID, wMsg, dwParam1, dwParam2);
> -
> - switch (wMsg) {
> - case MIM_DATA:
> - case MIM_LONGDATA:
> - case MIM_ERROR:
> - case MIM_LONGERROR:
> - case MIM_MOREDATA:
> - dwCallBack = sources[wDevID].midiDesc.dwCallback;
> - uFlags = sources[wDevID].wFlags;
> - hDev = sources[wDevID].midiDesc.hMidi;
> - dwInstance = sources[wDevID].midiDesc.dwInstance;
> - break;
> - default:
> - ERR("Unsupported MSW-MIDI message %u\n", wMsg);
> - return;
> - }
> -
> - DriverCallback(dwCallBack, uFlags, hDev, wMsg, dwInstance, dwParam1, dwParam2);
> -}
> -
> -static void midi_lock( BOOL lock )
> -{
> - UNIX_CALL(midi_in_lock, (void *)lock);
> -}
> -
> -/*
> - * MIDI In Mach message handling
> - */
> -static CFDataRef MIDIIn_MessageHandler(CFMessagePortRef local, SInt32 msgid, CFDataRef data, void *info)
> -{
> - MIDIMessage *msg = NULL;
> - int i = 0;
> - MIDISource *src = NULL;
> - DWORD sendData = 0;
> - int pos = 0;
> - DWORD currentTime;
> - BOOL sysexStart;
> -
> - switch (msgid)
> - {
> - case 0:
> - msg = (MIDIMessage *) CFDataGetBytePtr(data);
> - TRACE("devID=%d\n", msg->devID);
> - for (i = 0; i < msg->length; ++i) {
> - TRACE("%02X ", msg->data[i]);
> - }
> - TRACE("\n");
> - src = &sources[msg->devID];
> - if (src->state < 1)
> - {
> - TRACE("input not started, thrown away\n");
> - return NULL;
> - }
> -
> - sysexStart = (msg->data[0] == 0xF0);
> -
> - if (sysexStart || src->state & 2) {
> - int pos = 0;
> - int len = msg->length;
> -
> - if (sysexStart) {
> - TRACE("Receiving sysex message\n");
> - src->state |= 2;
> - }
> -
> - midi_lock( TRUE );
> - currentTime = get_time_ms() - src->startTime;
> -
> - while (len) {
> - LPMIDIHDR lpMidiHdr = src->lpQueueHdr;
> -
> - if (lpMidiHdr != NULL) {
> - int copylen = min(len, lpMidiHdr->dwBufferLength - lpMidiHdr->dwBytesRecorded);
> - memcpy(lpMidiHdr->lpData + lpMidiHdr->dwBytesRecorded, msg->data + pos, copylen);
> - lpMidiHdr->dwBytesRecorded += copylen;
> - len -= copylen;
> - pos += copylen;
> -
> - TRACE("Copied %d bytes of sysex message\n", copylen);
> -
> - if ((lpMidiHdr->dwBytesRecorded == lpMidiHdr->dwBufferLength) ||
> - (*(BYTE*)(lpMidiHdr->lpData + lpMidiHdr->dwBytesRecorded - 1) == 0xF7)) {
> - TRACE("Sysex message complete (or buffer limit reached), dispatching %d bytes\n", lpMidiHdr->dwBytesRecorded);
> - src->lpQueueHdr = lpMidiHdr->lpNext;
> - lpMidiHdr->dwFlags &= ~MHDR_INQUEUE;
> - lpMidiHdr->dwFlags |= MHDR_DONE;
> - MIDI_NotifyClient(msg->devID, MIM_LONGDATA, (DWORD_PTR)lpMidiHdr, currentTime);
> - src->state &= ~2;
> - }
> - }
> - else {
> - FIXME("Sysex data received but no buffer to store it!\n");
> - break;
> - }
> - }
> -
> - midi_lock( FALSE );
> - return NULL;
> - }
> -
> - midi_lock( TRUE );
> - currentTime = get_time_ms() - src->startTime;
> -
> - while (pos < msg->length)
> - {
> - sendData = 0;
> - switch (msg->data[pos] & 0xF0)
> - {
> - case 0xF0:
> - sendData = (msg->data[pos] << 0);
> - pos++;
> - break;
> -
> - case 0xC0:
> - case 0xD0:
> - sendData = (msg->data[pos + 1] << 8) | (msg->data[pos] << 0);
> - pos += 2;
> - break;
> - default:
> - sendData = (msg->data[pos + 2] << 16) |
> - (msg->data[pos + 1] << 8) |
> - (msg->data[pos] << 0);
> - pos += 3;
> - break;
> - }
> - MIDI_NotifyClient(msg->devID, MIM_DATA, sendData, currentTime);
> - }
> - midi_lock( FALSE );
> - break;
> - default:
> - CFRunLoopStop(CFRunLoopGetCurrent());
> - break;
> - }
> - return NULL;
> -}
> -
> -static DWORD WINAPI MIDIIn_MessageThread(LPVOID p)
> -{
> - CFMessagePortRef local;
> - CFRunLoopSourceRef source;
> - Boolean info;
> -
> - local = CFMessagePortCreateLocal(kCFAllocatorDefault, MIDIInThreadPortName, &MIDIIn_MessageHandler, NULL, &info);
> -
> - source = CFMessagePortCreateRunLoopSource(kCFAllocatorDefault, local, 0);
> - CFRunLoopAddSource(CFRunLoopGetCurrent(), source, kCFRunLoopDefaultMode);
> -
> - CFRunLoopRun();
> -
> - CFRunLoopSourceInvalidate(source);
> - CFRelease(source);
> - CFRelease(local);
> - CFRelease(MIDIInThreadPortName);
> - MIDIInThreadPortName = NULL;
> -
> - return 0;
> -}
> -
> /**************************************************************************
> * modMessage
> */
> diff --git a/dlls/winecoreaudio.drv/unixlib.h b/dlls/winecoreaudio.drv/unixlib.h
> index 67fcc35ce4c..d44a7a013e8 100644
> --- a/dlls/winecoreaudio.drv/unixlib.h
> +++ b/dlls/winecoreaudio.drv/unixlib.h
> @@ -187,8 +187,6 @@ struct midi_init_params
> {
> DWORD *err;
> UINT num_srcs;
> - void *srcs;
> - void *midi_in_port;
> };
>
> struct notify_context
> @@ -228,6 +226,7 @@ struct midi_in_message_params
>
> struct midi_notify_wait_params
> {
> + struct notify_context *notify;
> BOOL *quit;
> };
>
> @@ -258,8 +257,6 @@ enum unix_funcs
> unix_midi_out_message,
> unix_midi_in_message,
> unix_midi_notify_wait,
> -
> - unix_midi_in_lock, /* temporary */
> };
>
> NTSTATUS midi_init( void * ) DECLSPEC_HIDDEN;
> @@ -267,7 +264,6 @@ NTSTATUS midi_release( void * ) DECLSPEC_HIDDEN;
> NTSTATUS midi_out_message( void * ) DECLSPEC_HIDDEN;
> NTSTATUS midi_in_message( void * ) DECLSPEC_HIDDEN;
> NTSTATUS midi_notify_wait( void * ) DECLSPEC_HIDDEN;
> -NTSTATUS midi_in_lock( void * ) DECLSPEC_HIDDEN;
>
> extern unixlib_handle_t coreaudio_handle;
>
> --
> 2.23.0
>
>
More information about the wine-devel
mailing list