Emmanuel Maillard : winecoreaudio: Initial MIDI In support on Mac OS X.

Alexandre Julliard julliard at wine.codeweavers.com
Thu Apr 26 10:23:57 CDT 2007


Module: wine
Branch: master
Commit: 4903fbedc9ee791a41be60f48ca3975ec365f24c
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=4903fbedc9ee791a41be60f48ca3975ec365f24c

Author: Emmanuel Maillard <mahanuu at free.fr>
Date:   Thu Apr 26 00:57:31 2007 +0200

winecoreaudio: Initial MIDI In support on Mac OS X.

---

 dlls/winecoreaudio.drv/coremidi.c             |   20 ++++++
 dlls/winecoreaudio.drv/coremidi.h             |   12 ++++
 dlls/winecoreaudio.drv/midi.c                 |   78 ++++++++++++++++++++++++-
 dlls/winecoreaudio.drv/winecoreaudio.drv.spec |    1 +
 4 files changed, 110 insertions(+), 1 deletions(-)

diff --git a/dlls/winecoreaudio.drv/coremidi.c b/dlls/winecoreaudio.drv/coremidi.c
index 59101ee..ab4cd87 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 69fd4ce..182c190 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 fd00cb3..d12532c 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 dced551..41bbf84 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




More information about the wine-cvs mailing list