diff --git a/dlls/winecoreaudio.drv/coremidi.c b/dlls/winecoreaudio.drv/coremidi.c index 59101ee982d..ab4cd8781ab 100644 --- a/dlls/winecoreaudio.drv/coremidi.c +++ b/dlls/winecoreaudio.drv/coremidi.c @@ -52,4 +52,24 @@ void CoreMIDI_GetObjectName(MIDIObjectRef obj, char *name, int size) } } +/* + * 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) +{ + unsigned int i; + MIDIMessage msg; + + MIDIPacket *packet = (MIDIPacket *)pktlist->packet; + for (i = 0; i < pktlist->numPackets; ++i) { + msg.devID = *((UInt16 *)refCon); + msg.length = packet->length; + memcpy(msg.data, packet->data, sizeof(packet->data)); + + /* send message to Wine */ + + packet = MIDIPacketNext(packet); + } +} #endif /* HAVE_COREAUDIO_COREAUDIO_H */ diff --git a/dlls/winecoreaudio.drv/coremidi.h b/dlls/winecoreaudio.drv/coremidi.h index 69fd4ce788a..182c19040d0 100644 --- a/dlls/winecoreaudio.drv/coremidi.h +++ b/dlls/winecoreaudio.drv/coremidi.h @@ -44,8 +44,13 @@ 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. */ @@ -60,8 +65,15 @@ extern int AudioUnit_SetVolume(AudioUnit au, float left, float right); extern int AudioUnit_GetVolume(AudioUnit au, float *left, float *right); #endif +typedef struct { + UInt16 devID; + UInt16 length; + Byte data[256]; +} MIDIMessage; + /* coremidi.c */ extern MIDIClientRef CoreMIDI_CreateClient(CFStringRef name); extern void CoreMIDI_GetObjectName(MIDIObjectRef obj, char *name, int size); +extern void MIDIIn_ReadProc(const MIDIPacketList *pktlist, void *refCon, void *connRefCon); #endif diff --git a/dlls/winecoreaudio.drv/midi.c b/dlls/winecoreaudio.drv/midi.c index fd00cb375e7..d12532cf87f 100644 --- a/dlls/winecoreaudio.drv/midi.c +++ b/dlls/winecoreaudio.drv/midi.c @@ -52,6 +52,7 @@ WINE_DEFAULT_DEBUG_CHANNEL(midi); 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 */ @@ -64,9 +65,22 @@ typedef struct tagMIDIDestination { WORD wFlags; } MIDIDestination; +typedef struct tagMIDISource { + MIDIPortRef port; + 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; + + #define MAX_MIDI_SYNTHS 1 MIDIDestination *destinations; +MIDISource *sources; extern int SynthUnit_CreateDefaultSynthUnit(AUGraph *graph, AudioUnit *synth); extern int SynthUnit_Initialize(AudioUnit synth, AUGraph graph); @@ -93,9 +107,36 @@ LONG CoreAudio_MIDIInit(void) MIDIOut_NumDevs = MAX_MIDI_SYNTHS; MIDIOut_NumDevs += numDest; - TRACE("MIDIOut_NumDevs %d\n", MIDIOut_NumDevs); + 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)); + + /* initialize sources */ + for (i = 0; i < MIDIIn_NumDevs; i++) + { + MIDIEndpointRef endpoint = MIDIGetSource(i); + + sources[i].wDevID = i; + + CoreMIDI_GetObjectName(endpoint, szPname, sizeof(szPname)); + MultiByteToWideChar(CP_ACP, 0, szPname, -1, sources[i].caps.szPname, sizeof(sources[i].caps.szPname)/sizeof(WCHAR)); + + name = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("WineInputPort.%d.%u"), i, getpid()); + MIDIInputPortCreate(wineMIDIClient, name, MIDIIn_ReadProc, &sources[i].wDevID, &sources[i].port); + CFRelease(name); + + MIDIPortConnectSource(sources[i].port, endpoint, NULL); + + 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++) @@ -142,6 +183,8 @@ LONG CoreAudio_MIDIRelease(void) { TRACE("\n"); if (wineMIDIClient) MIDIClientDispose(wineMIDIClient); /* MIDIClientDispose will close all ports */ + + HeapFree(GetProcessHeap(), 0, sources); HeapFree(GetProcessHeap(), 0, destinations); return 1; } @@ -565,6 +608,33 @@ DWORD WINAPI CoreAudio_modMessage(UINT wDevID, UINT wMsg, DWORD dwUser, DWORD dw return MMSYSERR_NOTSUPPORTED; } +/************************************************************************** +* midMessage +*/ +DWORD WINAPI CoreAudio_midMessage(UINT wDevID, UINT wMsg, DWORD dwUser, DWORD dwParam1, DWORD dwParam2) +{ + TRACE("%d %08x %08x %08x %08x\n", wDevID, wMsg, dwUser, dwParam1, dwParam2); + switch (wMsg) { + case DRVM_INIT: + case DRVM_EXIT: + case DRVM_ENABLE: + case DRVM_DISABLE: + return 0; + case MIDM_OPEN: + case MIDM_CLOSE: + case MIDM_ADDBUFFER: + case MIDM_PREPARE: + case MIDM_UNPREPARE: + case MIDM_GETDEVCAPS: + case MIDM_GETNUMDEVS: + case MIDM_START: + case MIDM_STOP: + case MIDM_RESET: + default: + TRACE("Unsupported message\n"); + } + return MMSYSERR_NOTSUPPORTED; +} #else DWORD WINAPI CoreAudio_modMessage(UINT wDevID, UINT wMsg, DWORD dwUser, DWORD dwParam1, DWORD dwParam2) @@ -573,4 +643,10 @@ DWORD WINAPI CoreAudio_modMessage(UINT wDevID, UINT wMsg, DWORD dwUser, DWORD dw return MMSYSERR_NOTENABLED; } +DWORD WINAPI CoreAudio_midMessage(UINT wDevID, UINT wMsg, DWORD dwUser, + DWORD dwParam1, DWORD dwParam2) +{ + TRACE("%08x, %08x, %08x, %08x, %08x\n", wDevID, wMsg, dwUser, dwParam1, dwParam2); + return MMSYSERR_NOTENABLED; +} #endif diff --git a/dlls/winecoreaudio.drv/winecoreaudio.drv.spec b/dlls/winecoreaudio.drv/winecoreaudio.drv.spec index dced551bebb..41bbf841965 100644 --- a/dlls/winecoreaudio.drv/winecoreaudio.drv.spec +++ b/dlls/winecoreaudio.drv/winecoreaudio.drv.spec @@ -1,4 +1,5 @@ @ stdcall -private DriverProc(long long long long long) CoreAudio_DriverProc @ stdcall -private widMessage(long long long long long) CoreAudio_widMessage @ stdcall -private wodMessage(long long long long long) CoreAudio_wodMessage +@ stdcall -private midMessage(long long long long long) CoreAudio_midMessage @ stdcall -private modMessage(long long long long long) CoreAudio_modMessage