midi_init temporarily returns unix-side info, which will eventually
be removed.
Signed-off-by: Huw Davies <huw(a)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, ¶ms);
+ 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