midi_init temporarily returns unix-side info, which will eventually be removed.
Signed-off-by: Huw Davies huw@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 )
Signed-off-by: Andrew Eikum aeikum@codeweavers.com
On Thu, Nov 25, 2021 at 11:03:38AM +0000, Huw Davies wrote:
midi_init temporarily returns unix-side info, which will eventually be removed.
Signed-off-by: Huw Davies huw@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