[PATCH 03/12] winecoreaudio: Move midi_init and midi_release to the unixlib.

Huw Davies huw at codeweavers.com
Thu Nov 25 05:03:38 CST 2021


midi_init temporarily returns unix-side info, which will eventually
be removed.

Signed-off-by: Huw Davies <huw at codeweavers.com>
---
 dlls/winecoreaudio.drv/coreaudio.c |   2 +
 dlls/winecoreaudio.drv/coremidi.c  | 233 +++++++++++++++++++++++++----
 dlls/winecoreaudio.drv/coremidi.h  |  28 +++-
 dlls/winecoreaudio.drv/midi.c      | 153 ++++---------------
 dlls/winecoreaudio.drv/unixlib.h   |  13 ++
 5 files changed, 276 insertions(+), 153 deletions(-)

diff --git a/dlls/winecoreaudio.drv/coreaudio.c b/dlls/winecoreaudio.drv/coreaudio.c
index fd32a2a99ac..9476b6baf6f 100644
--- a/dlls/winecoreaudio.drv/coreaudio.c
+++ b/dlls/winecoreaudio.drv/coreaudio.c
@@ -1629,4 +1629,6 @@ unixlib_entry_t __wine_unix_call_funcs[] =
     get_frequency,
     is_started,
     set_volumes,
+    midi_init,
+    midi_release,
 };
diff --git a/dlls/winecoreaudio.drv/coremidi.c b/dlls/winecoreaudio.drv/coremidi.c
index 92f52c972d3..dedfa0aa9ee 100644
--- a/dlls/winecoreaudio.drv/coremidi.c
+++ b/dlls/winecoreaudio.drv/coremidi.c
@@ -21,46 +21,90 @@
  * License along with this library; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  */
-
+#if 0
+#pragma makedep unix
+#endif
 
 #include "config.h"
 
-#include <CoreMIDI/CoreMIDI.h>
+#define ULONG __carbon_ULONG
+#define E_INVALIDARG __carbon_E_INVALIDARG
+#define E_OUTOFMEMORY __carbon_E_OUTOFMEMORY
+#define E_HANDLE __carbon_E_HANDLE
+#define E_ACCESSDENIED __carbon_E_ACCESSDENIED
+#define E_UNEXPECTED __carbon_E_UNEXPECTED
+#define E_FAIL __carbon_E_FAIL
+#define E_ABORT __carbon_E_ABORT
+#define E_POINTER __carbon_E_POINTER
+#define E_NOINTERFACE __carbon_E_NOINTERFACE
+#define E_NOTIMPL __carbon_E_NOTIMPL
+#define S_FALSE __carbon_S_FALSE
+#define S_OK __carbon_S_OK
+#define HRESULT_FACILITY __carbon_HRESULT_FACILITY
+#define IS_ERROR __carbon_IS_ERROR
+#define FAILED __carbon_FAILED
+#define SUCCEEDED __carbon_SUCCEEDED
+#define MAKE_HRESULT __carbon_MAKE_HRESULT
+#define HRESULT __carbon_HRESULT
+#define STDMETHODCALLTYPE __carbon_STDMETHODCALLT
 #include <mach/mach_time.h>
+#include <CoreMIDI/CoreMIDI.h>
+#include <AudioUnit/AudioUnit.h>
+#include <AudioToolbox/AudioToolbox.h>
+#undef ULONG
+#undef E_INVALIDARG
+#undef E_OUTOFMEMORY
+#undef E_HANDLE
+#undef E_ACCESSDENIED
+#undef E_UNEXPECTED
+#undef E_FAIL
+#undef E_ABORT
+#undef E_POINTER
+#undef E_NOINTERFACE
+#undef E_NOTIMPL
+#undef S_FALSE
+#undef S_OK
+#undef HRESULT_FACILITY
+#undef IS_ERROR
+#undef FAILED
+#undef SUCCEEDED
+#undef MAKE_HRESULT
+#undef HRESULT
+#undef STDMETHODCALLTYPE
 
-#include "coremidi.h"
-
-
-MIDIClientRef CoreMIDI_CreateClient(CFStringRef name)
-{
-    MIDIClientRef client = 0;
-
-    if (MIDIClientCreate(name, NULL /* FIXME use notify proc */, NULL, &client) != noErr)
-        return 0;
+#include "ntstatus.h"
+#define WIN32_NO_STATUS
+#include "windef.h"
+#include "winbase.h"
+#include "winnls.h"
+#include "winreg.h"
+#include "mmsystem.h"
+#include "mmddk.h"
+#include "mmdeviceapi.h"
+#include "audioclient.h"
+#include "wine/debug.h"
+#include "wine/unicode.h"
+#include "wine/unixlib.h"
 
-    return client;
-}
+#include "coremidi.h"
+#include "unixlib.h"
 
-void CoreMIDI_GetObjectName(MIDIObjectRef obj, char *name, int size)
-{
-    OSStatus err = noErr;
-    CFStringRef cfname;
+WINE_DEFAULT_DEBUG_CHANNEL(midi);
 
-    err = MIDIObjectGetStringProperty(obj, kMIDIPropertyName, &cfname);
-    if (err == noErr)
-    {
-        CFStringGetCString(cfname, name, size, kCFStringEncodingASCII);
-        CFRelease(cfname);
-    }
-}
+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;
 
 /*
  *  CoreMIDI IO threaded callback,
  *  we can't call Wine debug channels, critical section or anything using NtCurrentTeb here.
  */
-void MIDIIn_ReadProc(const MIDIPacketList *pktlist, void *refCon, void *connRefCon)
+static void midi_in_read_proc(const MIDIPacketList *pktlist, void *refCon, void *connRefCon)
 {
-    CFMessagePortRef msg_port = CFMessagePortCreateRemote(kCFAllocatorDefault, MIDIInThreadPortName);
+    CFMessagePortRef msg_port = CFMessagePortCreateRemote(kCFAllocatorDefault, midi_in_thread_port_name);
     MIDIPacket *packet = (MIDIPacket *)pktlist->packet;
     CFMutableDataRef data;
     MIDIMessage msg;
@@ -82,3 +126,140 @@ void MIDIIn_ReadProc(const MIDIPacketList *pktlist, void *refCon, void *connRefC
     }
     CFRelease(msg_port);
 }
+
+NTSTATUS midi_init(void *args)
+{
+    CFStringRef name = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("wineMIDIClient.%d"), getpid());
+    struct midi_init_params *params = args;
+    OSStatus sc;
+    UINT i;
+
+    sc = MIDIClientCreate(name, NULL /* FIXME use notify proc */, NULL, &midi_client);
+    CFRelease(name);
+    if (sc)
+    {
+        ERR("can't create MIDI Client\n");
+        *params->err = DRV_FAILURE;
+        return STATUS_SUCCESS;
+    }
+
+    num_dests = MAX_MIDI_SYNTHS + MIDIGetNumberOfDestinations();
+    num_srcs = MIDIGetNumberOfSources();
+
+    TRACE("num_dests %d num_srcs %d\n", num_dests, num_srcs);
+
+    dests = calloc(num_dests, sizeof(*dests));
+    srcs = calloc(num_srcs, sizeof(*srcs));
+
+    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);
+    }
+
+    if (num_dests > MAX_MIDI_SYNTHS)
+    {
+        name = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("WineOutputPort.%u"), getpid());
+        MIDIOutputPortCreate(midi_client, name, &midi_out_port);
+        CFRelease(name);
+    }
+
+    /* initialize sources */
+    for (i = 0; i < num_srcs; i++)
+    {
+        srcs[i].wDevID = i;
+        srcs[i].source = MIDIGetSource(i);
+
+        sc = MIDIObjectGetStringProperty(srcs[i].source, kMIDIPropertyName, &name);
+        if (!sc)
+        {
+            int len = min(CFStringGetLength(name), ARRAY_SIZE(srcs[i].caps.szPname) - 1);
+            CFStringGetCharacters(name, CFRangeMake(0, len), srcs[i].caps.szPname);
+            srcs[i].caps.szPname[len] = '\0';
+        }
+        MIDIPortConnectSource(midi_in_port, srcs[i].source, &srcs[i].wDevID);
+
+        srcs[i].state = 0;
+        /* FIXME */
+        srcs[i].caps.wMid = 0x00FF; 	/* Manufac ID */
+        srcs[i].caps.wPid = 0x0001; 	/* Product ID */
+        srcs[i].caps.vDriverVersion = 0x0001;
+        srcs[i].caps.dwSupport = 0;
+    }
+
+    /* initialise MIDI synths */
+    for (i = 0; i < MAX_MIDI_SYNTHS; i++)
+    {
+        static const WCHAR synth_name[] = {'C','o','r','e','A','u','d','i','o',' ','M','I','D','I',' ','S','y','n','t','h',' '};
+
+        C_ASSERT(MAX_MIDI_SYNTHS < 10);
+        memcpy(dests[i].caps.szPname, synth_name, sizeof(synth_name));
+        dests[i].caps.szPname[ARRAY_SIZE(synth_name)] = '1' + i;
+        dests[i].caps.szPname[ARRAY_SIZE(synth_name) + 1] = '\0';
+
+        dests[i].caps.wTechnology = MOD_SYNTH;
+        dests[i].caps.wChannelMask = 0xFFFF;
+
+        dests[i].caps.wMid = 0x00FF; 	/* Manufac ID */
+        dests[i].caps.wPid = 0x0001; 	/* Product ID */
+        dests[i].caps.vDriverVersion = 0x0001;
+        dests[i].caps.dwSupport = MIDICAPS_VOLUME;
+        dests[i].caps.wVoices = 16;
+        dests[i].caps.wNotes = 16;
+    }
+    /* initialise available destinations */
+    for (i = MAX_MIDI_SYNTHS; i < num_dests; i++)
+    {
+        dests[i].dest = MIDIGetDestination(i - MAX_MIDI_SYNTHS);
+
+        sc = MIDIObjectGetStringProperty(dests[i].dest, kMIDIPropertyName, &name);
+        if (!sc)
+        {
+            int len = min(CFStringGetLength(name), ARRAY_SIZE(dests[i].caps.szPname) - 1);
+            CFStringGetCharacters(name, CFRangeMake(0, len), dests[i].caps.szPname);
+            dests[i].caps.szPname[len] = '\0';
+        }
+
+        dests[i].caps.wTechnology = MOD_MIDIPORT;
+        dests[i].caps.wChannelMask = 0xFFFF;
+
+        dests[i].caps.wMid = 0x00FF; 	/* Manufac ID */
+        dests[i].caps.wPid = 0x0001;
+        dests[i].caps.vDriverVersion = 0x0001;
+        dests[i].caps.dwSupport = 0;
+        dests[i].caps.wVoices = 0;
+        dests[i].caps.wNotes = 0;
+    }
+
+    params->num_dests = num_dests;
+    params->num_srcs = num_srcs;
+    params->dests = dests;
+    params->srcs = srcs;
+    params->midi_out_port = (void *)midi_out_port;
+    params->midi_in_port = (void *)midi_in_port;
+
+    *params->err = DRV_SUCCESS;
+    return STATUS_SUCCESS;
+}
+
+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);
+    }
+
+    if (midi_client) MIDIClientDispose(midi_client); /* MIDIClientDispose will close all ports */
+
+    free(srcs);
+    free(dests);
+
+    return STATUS_SUCCESS;
+}
diff --git a/dlls/winecoreaudio.drv/coremidi.h b/dlls/winecoreaudio.drv/coremidi.h
index 47566345b54..ca669db7db1 100644
--- a/dlls/winecoreaudio.drv/coremidi.h
+++ b/dlls/winecoreaudio.drv/coremidi.h
@@ -23,6 +23,8 @@
 
 #include <CoreFoundation/CoreFoundation.h>
 
+#define MAX_MIDI_SYNTHS 1
+
 #ifdef WINE_DEFINITIONS
 /*
  * Due to CoreMIDI headers conflict redefine some types for Wine
@@ -73,7 +75,31 @@ extern void MIDIIn_ReadProc(const MIDIPacketList *pktlist, void *refCon, void *c
 extern void MIDIOut_Send(MIDIPortRef port, MIDIEndpointRef dest, UInt8 *buffer, unsigned length);
 
 /* midi.c */
-extern CFStringRef MIDIInThreadPortName;
+typedef struct midi_dest
+{
+    /* graph and synth are only used for MIDI Synth */
+    AUGraph graph;
+    AudioUnit synth;
+
+    MIDIEndpointRef dest;
+
+    MIDIOUTCAPSW caps;
+    MIDIOPENDESC midiDesc;
+    WORD wFlags;
+} MIDIDestination;
+
+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;
diff --git a/dlls/winecoreaudio.drv/midi.c b/dlls/winecoreaudio.drv/midi.c
index 2c89f32b430..000c57ad98d 100644
--- a/dlls/winecoreaudio.drv/midi.c
+++ b/dlls/winecoreaudio.drv/midi.c
@@ -35,9 +35,13 @@
 #include "winuser.h"
 #include "winnls.h"
 #include "mmddk.h"
+#include "mmdeviceapi.h"
+#include "audioclient.h"
 #include "wine/unicode.h"
 #include "wine/debug.h"
+#include "wine/unixlib.h"
 #include "coreaudio.h"
+#include "unixlib.h"
 
 WINE_DEFAULT_DEBUG_CHANNEL(midi);
 
@@ -46,45 +50,17 @@ WINE_DEFAULT_DEBUG_CHANNEL(midi);
 #define WINE_DEFINITIONS
 #include "coremidi.h"
 
-static MIDIClientRef wineMIDIClient = NULL;
-
 static DWORD MIDIOut_NumDevs = 0;
 static DWORD MIDIIn_NumDevs = 0;
 
-typedef struct tagMIDIDestination {
-    /* graph and synth are only used for MIDI Synth */
-    AUGraph graph;
-    AudioUnit synth;
-
-    MIDIEndpointRef dest;
-
-    MIDIOUTCAPSW caps;
-    MIDIOPENDESC midiDesc;
-    WORD wFlags;
-} MIDIDestination;
-
-typedef struct tagMIDISource {
-    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;
-
 static CRITICAL_SECTION midiInLock; /* Critical section for MIDI In */
-CFStringRef MIDIInThreadPortName = NULL;
+static CFStringRef MIDIInThreadPortName;
 
 static DWORD WINAPI MIDIIn_MessageThread(LPVOID p);
 
 static MIDIPortRef MIDIInPort = NULL;
 static MIDIPortRef MIDIOutPort = NULL;
 
-#define MAX_MIDI_SYNTHS 1
-
 MIDIDestination *destinations;
 MIDISource *sources;
 
@@ -92,127 +68,52 @@ extern int SynthUnit_CreateDefaultSynthUnit(AUGraph *graph, AudioUnit *synth);
 extern int SynthUnit_Initialize(AudioUnit synth, AUGraph graph);
 extern int SynthUnit_Close(AUGraph graph);
 
-
-LONG CoreAudio_MIDIInit(void)
+static LONG CoreAudio_MIDIInit(void)
 {
-    int i;
-    CHAR szPname[MAXPNAMELEN] = {0};
+    struct midi_init_params params;
+    DWORD err;
 
-    int numDest = MIDIGetNumberOfDestinations();
-    CFStringRef name = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("wineMIDIClient.%d"), getpid());
+    params.err = &err;
 
-    wineMIDIClient = CoreMIDI_CreateClient( name );
-    if (wineMIDIClient == NULL)
+    UNIX_CALL(midi_init, &params);
+    if (err != DRV_SUCCESS)
     {
-        CFRelease(name);
-        ERR("can't create wineMIDIClient\n");
-        return DRV_FAILURE;
+        ERR("can't create midi client\n");
+        return err;
     }
-    CFRelease(name);
 
-    MIDIOut_NumDevs = MAX_MIDI_SYNTHS;
-    MIDIOut_NumDevs += numDest;
-
-    MIDIIn_NumDevs = MIDIGetNumberOfSources();
-
-    TRACE("MIDIOut_NumDevs %d MIDIIn_NumDevs %d\n", MIDIOut_NumDevs, MIDIIn_NumDevs);
-
-    destinations = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, MIDIOut_NumDevs * sizeof(MIDIDestination));
-    sources = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, MIDIIn_NumDevs * sizeof(MIDISource));
+    MIDIOut_NumDevs = params.num_dests;
+    MIDIIn_NumDevs = params.num_srcs;
+    destinations = params.dests;
+    sources = params.srcs;
+    MIDIOutPort = params.midi_out_port;
+    MIDIInPort = params.midi_in_port;
 
     if (MIDIIn_NumDevs > 0)
     {
         InitializeCriticalSection(&midiInLock);
         midiInLock.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": midiInLock");
+
         MIDIInThreadPortName = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("MIDIInThreadPortName.%u"), getpid());
         CloseHandle( CreateThread(NULL, 0, MIDIIn_MessageThread, NULL, 0, NULL));
-
-        name = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("WineInputPort.%u"), getpid());
-        MIDIInputPortCreate(wineMIDIClient, name, MIDIIn_ReadProc, NULL, &MIDIInPort);
-        CFRelease(name);
     }
-    if (numDest > 0)
-    {
-        name = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("WineOutputPort.%u"), getpid());
-        MIDIOutputPortCreate(wineMIDIClient, name, &MIDIOutPort);
-        CFRelease(name);
-    }
-
-    /* initialize sources */
-    for (i = 0; i < MIDIIn_NumDevs; i++)
-    {
-        sources[i].wDevID = i;
-        sources[i].source = MIDIGetSource(i);
-
-        CoreMIDI_GetObjectName(sources[i].source, szPname, sizeof(szPname));
-        MultiByteToWideChar(CP_ACP, 0, szPname, -1, sources[i].caps.szPname, ARRAY_SIZE(sources[i].caps.szPname));
-
-        MIDIPortConnectSource(MIDIInPort, sources[i].source, &sources[i].wDevID);
-
-        sources[i].state = 0;
-        /* FIXME */
-        sources[i].caps.wMid = 0x00FF; 	/* Manufac ID */
-        sources[i].caps.wPid = 0x0001; 	/* Product ID */
-        sources[i].caps.vDriverVersion = 0x0001;
-        sources[i].caps.dwSupport = 0;
-    }
-
-    /* initialise MIDI synths */
-    for (i = 0; i < MAX_MIDI_SYNTHS; i++)
-    {
-        snprintf(szPname, sizeof(szPname), "CoreAudio MIDI Synth %d", i);
-        MultiByteToWideChar(CP_ACP, 0, szPname, -1, destinations[i].caps.szPname, ARRAY_SIZE(destinations[i].caps.szPname));
-
-        destinations[i].caps.wTechnology = MOD_SYNTH;
-        destinations[i].caps.wChannelMask = 0xFFFF;
-
-        destinations[i].caps.wMid = 0x00FF; 	/* Manufac ID */
-        destinations[i].caps.wPid = 0x0001; 	/* Product ID */
-        destinations[i].caps.vDriverVersion = 0x0001;
-        destinations[i].caps.dwSupport = MIDICAPS_VOLUME;
-        destinations[i].caps.wVoices = 16;
-        destinations[i].caps.wNotes = 16;
-    }
-    /* initialise available destinations */
-    for (i = MAX_MIDI_SYNTHS; i < numDest + MAX_MIDI_SYNTHS; i++)
-    {
-        destinations[i].dest = MIDIGetDestination(i - MAX_MIDI_SYNTHS);
-
-        CoreMIDI_GetObjectName(destinations[i].dest, szPname, sizeof(szPname));
-        MultiByteToWideChar(CP_ACP, 0, szPname, -1, destinations[i].caps.szPname, ARRAY_SIZE(destinations[i].caps.szPname));
-
-        destinations[i].caps.wTechnology = MOD_MIDIPORT;
-        destinations[i].caps.wChannelMask = 0xFFFF;
-
-        destinations[i].caps.wMid = 0x00FF; 	/* Manufac ID */
-        destinations[i].caps.wPid = 0x0001;
-        destinations[i].caps.vDriverVersion = 0x0001;
-        destinations[i].caps.dwSupport = 0;
-        destinations[i].caps.wVoices = 0;
-        destinations[i].caps.wNotes = 0;
-    }
-    return DRV_SUCCESS;
+    return err;
 }
 
-LONG CoreAudio_MIDIRelease(void)
+static LONG CoreAudio_MIDIRelease(void)
 {
     TRACE("\n");
+
+    UNIX_CALL(midi_release, NULL);
+    sources = NULL;
+    destinations = NULL;
+
     if (MIDIIn_NumDevs > 0)
     {
-        CFMessagePortRef messagePort;
-        /* Stop CFRunLoop in MIDIIn_MessageThread */
-        messagePort = CFMessagePortCreateRemote(kCFAllocatorDefault, MIDIInThreadPortName);
-        CFMessagePortSendRequest(messagePort, 1, NULL, 0.0, 0.0, NULL, NULL);
-        CFRelease(messagePort);
-
         midiInLock.DebugInfo->Spare[0] = 0;
         DeleteCriticalSection(&midiInLock);
     }
 
-    if (wineMIDIClient) MIDIClientDispose(wineMIDIClient); /* MIDIClientDispose will close all ports */
-
-    HeapFree(GetProcessHeap(), 0, sources);
-    HeapFree(GetProcessHeap(), 0, destinations);
     return DRV_SUCCESS;
 }
 
diff --git a/dlls/winecoreaudio.drv/unixlib.h b/dlls/winecoreaudio.drv/unixlib.h
index 6f51c7877fa..6dfb68d202f 100644
--- a/dlls/winecoreaudio.drv/unixlib.h
+++ b/dlls/winecoreaudio.drv/unixlib.h
@@ -182,6 +182,14 @@ struct set_volumes_params
     int channel;
 };
 
+struct midi_init_params
+{
+    DWORD *err;
+    UINT num_dests, num_srcs;
+    void *dests, *srcs;
+    void *midi_out_port, *midi_in_port;
+};
+
 enum unix_funcs
 {
     unix_get_endpoint_ids,
@@ -204,8 +212,13 @@ enum unix_funcs
     unix_get_frequency,
     unix_is_started,
     unix_set_volumes,
+    unix_midi_init,
+    unix_midi_release,
 };
 
+NTSTATUS midi_init( void * ) DECLSPEC_HIDDEN;
+NTSTATUS midi_release( void * ) DECLSPEC_HIDDEN;
+
 extern unixlib_handle_t coreaudio_handle;
 
 #define UNIX_CALL( func, params ) __wine_unix_call( coreaudio_handle, unix_ ## func, params )
-- 
2.23.0




More information about the wine-devel mailing list