Updated.
[wine] / dlls / winmm / midimap / midimap.c
1 /* -*- tab-width: 8; c-basic-offset: 4 -*- */
2 /*                                 
3  * Wine Midi mapper driver
4  *
5  * Copyright    1999 Eric Pouech
6  */
7
8 #include <string.h>
9 #include "windef.h"
10 #include "winbase.h"
11 #include "wingdi.h"
12 #include "winuser.h"
13 #include "mmddk.h"
14 #include "debugtools.h"
15
16 DEFAULT_DEBUG_CHANNEL(msacm);
17
18 typedef struct tagMIDIMAPDATA {
19     struct tagMIDIMAPDATA*      self;
20     HMIDI       hMidi;
21 } MIDIMAPDATA;
22
23 static  BOOL    MIDIMAP_IsData(MIDIMAPDATA* mm)
24 {
25     return (!IsBadReadPtr(mm, sizeof(MIDIMAPDATA)) && mm->self == mm);
26 }
27
28 /*======================================================================*
29  *                  MIDI OUT part                                       *
30  *======================================================================*/
31
32 static  DWORD   modOpen(LPDWORD lpdwUser, LPMIDIOPENDESC lpDesc, DWORD dwFlags)
33 {
34     UINT                nd = midiOutGetNumDevs();
35     UINT                i;
36     MIDIMAPDATA*        mom = HeapAlloc(GetProcessHeap(), 0, sizeof(MIDIMAPDATA));
37
38     TRACE("(%p %p %08lx\n", lpdwUser, lpDesc, dwFlags);
39
40     for (i = 0; i < nd; i++) {
41         if (midiOutOpen(&mom->hMidi, i, lpDesc->dwCallback, 
42                         lpDesc->dwInstance, dwFlags) == MMSYSERR_NOERROR) {
43             lpDesc->hMidi = mom->hMidi;
44             *lpdwUser = (DWORD)mom;
45             return MMSYSERR_NOERROR;
46         }
47     }
48     HeapFree(GetProcessHeap(), 0, mom);
49     return MMSYSERR_ALLOCATED;
50 }
51
52 static  DWORD   modClose(MIDIMAPDATA* mom)
53 {
54     DWORD ret = midiOutClose(mom->hMidi);
55     if (ret == MMSYSERR_NOERROR)
56         HeapFree(GetProcessHeap(), 0, mom);
57     return ret;
58 }
59
60 static  DWORD   modLongData(MIDIMAPDATA* mom, LPMIDIHDR lpMidiHdr, DWORD dwParam2)
61 {
62     return midiOutLongMsg(mom->hMidi, lpMidiHdr, dwParam2);
63 }
64
65 static  DWORD   modData(MIDIMAPDATA* mom, DWORD dwParam)
66 {
67     return midiOutShortMsg(mom->hMidi, dwParam);
68 }
69
70 static  DWORD   modPrepare(MIDIMAPDATA* mom, LPMIDIHDR lpMidiHdr, DWORD dwParam2)
71 {
72     return midiOutPrepareHeader(mom->hMidi, lpMidiHdr, dwParam2);
73 }
74
75 static  DWORD   modUnprepare(MIDIMAPDATA* mom, LPMIDIHDR lpMidiHdr, DWORD dwParam2)
76 {
77     return midiOutUnprepareHeader(mom->hMidi, lpMidiHdr, dwParam2);
78 }
79
80 static  DWORD   modGetDevCaps(UINT wDevID, MIDIMAPDATA* mom, LPMIDIOUTCAPSA lpMidiCaps, DWORD dwParam2)
81 {
82     /* if opened low driver, forward message */
83     if (MIDIMAP_IsData(mom))
84         return midiOutGetDevCapsA(mom->hMidi, lpMidiCaps, dwParam2);
85     /* otherwise, return caps of mapper itself */
86     if (wDevID == (UINT)-1 || wDevID == (UINT16)-1) {
87         lpMidiCaps->wMid = 0x00FF;
88         lpMidiCaps->wPid = 0x0001;
89         lpMidiCaps->vDriverVersion = 0x0100;
90         strcpy(lpMidiCaps->szPname, "Wine midi out mapper");
91         lpMidiCaps->wTechnology = MOD_MAPPER;
92         lpMidiCaps->wVoices = 0;
93         lpMidiCaps->wNotes = 0;
94         lpMidiCaps->wChannelMask = 0xFFFF;
95         lpMidiCaps->dwSupport = MIDICAPS_LRVOLUME | MIDICAPS_VOLUME;
96
97         return MMSYSERR_NOERROR;
98     }
99     ERR("This shouldn't happen\n");
100     return MMSYSERR_ERROR; 
101 }
102
103 static  DWORD   modGetVolume(UINT wDevID, MIDIMAPDATA* mom, LPDWORD lpVol)
104 {
105     if (MIDIMAP_IsData(mom))
106         return midiOutGetVolume(mom->hMidi, lpVol);
107     return MMSYSERR_ERROR;
108 }
109
110 static  DWORD   modSetVolume(UINT wDevID, MIDIMAPDATA* mom, DWORD vol)
111 {
112     if (MIDIMAP_IsData(mom))
113         return midiOutSetVolume(mom->hMidi, vol);
114     return MMSYSERR_ERROR;
115 }
116
117 static  DWORD   modReset(MIDIMAPDATA* mom)
118 {
119     return midiOutReset(mom->hMidi);
120 }
121
122 /**************************************************************************
123  *                              MIDIMAP_modMessage      [sample driver]
124  */
125 DWORD WINAPI MIDIMAP_modMessage(UINT wDevID, UINT wMsg, DWORD dwUser, 
126                                 DWORD dwParam1, DWORD dwParam2)
127 {
128     TRACE("(%u, %04X, %08lX, %08lX, %08lX);\n",
129           wDevID, wMsg, dwUser, dwParam1, dwParam2);
130     
131     switch (wMsg) {
132     case DRVM_INIT:
133     case DRVM_EXIT:
134     case DRVM_ENABLE:
135     case DRVM_DISABLE:
136         /* FIXME: Pretend this is supported */
137         return 0;
138
139     case MODM_OPEN:             return modOpen          ((LPDWORD)dwUser,      (LPMIDIOPENDESC)dwParam1,dwParam2);
140     case MODM_CLOSE:            return modClose         ((MIDIMAPDATA*)dwUser);
141
142     case MODM_DATA:             return modData          ((MIDIMAPDATA*)dwUser, dwParam1);
143     case MODM_LONGDATA:         return modLongData      ((MIDIMAPDATA*)dwUser, (LPMIDIHDR)dwParam1,     dwParam2);
144     case MODM_PREPARE:          return modPrepare       ((MIDIMAPDATA*)dwUser, (LPMIDIHDR)dwParam1,     dwParam2);
145     case MODM_UNPREPARE:        return modUnprepare     ((MIDIMAPDATA*)dwUser, (LPMIDIHDR)dwParam1,     dwParam2);
146
147     case MODM_GETDEVCAPS:       return modGetDevCaps    (wDevID, (MIDIMAPDATA*)dwUser, (LPMIDIOUTCAPSA)dwParam1,dwParam2);
148     case MODM_GETNUMDEVS:       return 1;
149     case MODM_GETVOLUME:        return modGetVolume     (wDevID, (MIDIMAPDATA*)dwUser, (LPDWORD)dwParam1);
150     case MODM_SETVOLUME:        return modSetVolume     (wDevID, (MIDIMAPDATA*)dwUser, dwParam1);
151     case MODM_RESET:            return modReset         ((MIDIMAPDATA*)dwUser);
152     default:
153         FIXME("unknown message %d!\n", wMsg);
154     }
155     return MMSYSERR_NOTSUPPORTED;
156 }
157
158 /*======================================================================*
159  *                  MIDI IN part                                        *
160  *======================================================================*/
161
162 static  DWORD   midOpen(LPDWORD lpdwUser, LPMIDIOPENDESC lpDesc, DWORD dwFlags)
163 {
164     UINT                nd = midiInGetNumDevs();
165     UINT                i;
166     MIDIMAPDATA*        mim = HeapAlloc(GetProcessHeap(), 0, sizeof(MIDIMAPDATA));
167
168     TRACE("(%p %p %08lx\n", lpdwUser, lpDesc, dwFlags);
169
170     for (i = 0; i < nd; i++) {
171         if (midiInOpen(&mim->hMidi, i, lpDesc->dwCallback, 
172                         lpDesc->dwInstance, dwFlags) == MMSYSERR_NOERROR) {
173             lpDesc->hMidi = mim->hMidi;
174             *lpdwUser = (DWORD)mim;
175             return MMSYSERR_NOERROR;
176         }
177     }
178     HeapFree(GetProcessHeap(), 0, mim);
179     return MMSYSERR_ALLOCATED;
180 }
181
182 static  DWORD   midClose(MIDIMAPDATA* mim)
183 {
184     DWORD ret = midiInClose(mim->hMidi);
185     if (ret == MMSYSERR_NOERROR)
186         HeapFree(GetProcessHeap(), 0, mim);
187     return ret;
188 }
189
190 static  DWORD   midAddBuffer(MIDIMAPDATA* mim, LPMIDIHDR lpMidiHdr, DWORD dwParam2)
191 {
192     return midiInAddBuffer(mim->hMidi, lpMidiHdr, dwParam2);
193 }
194
195 static  DWORD   midPrepare(MIDIMAPDATA* mim, LPMIDIHDR lpMidiHdr, DWORD dwParam2)
196 {
197     return midiInPrepareHeader(mim->hMidi, lpMidiHdr, dwParam2);
198 }
199
200 static  DWORD   midUnprepare(MIDIMAPDATA* mim, LPMIDIHDR lpMidiHdr, DWORD dwParam2)
201 {
202     return midiInUnprepareHeader(mim->hMidi, lpMidiHdr, dwParam2);
203 }
204
205 static  DWORD   midGetDevCaps(UINT wDevID, MIDIMAPDATA* mim, LPMIDIINCAPSA lpMidiCaps, DWORD dwParam2)
206 {
207     /* if opened low driver, forward message */
208     if (MIDIMAP_IsData(mim))
209         return midiInGetDevCapsA(mim->hMidi, lpMidiCaps, dwParam2);
210     /* otherwise, return caps of mapper itself */
211     if (wDevID == (UINT)-1 || wDevID == (UINT16)-1) {
212         lpMidiCaps->wMid = 0x00FF;
213         lpMidiCaps->wPid = 0x0001;
214         lpMidiCaps->vDriverVersion = 0x0100;
215         strcpy(lpMidiCaps->szPname, "Wine midi int mapper");
216         lpMidiCaps->dwSupport = 0;
217
218         return MMSYSERR_NOERROR;
219     }
220     ERR("This shouldn't happen\n");
221     return MMSYSERR_ERROR; 
222 }
223
224 static  DWORD   midStop(MIDIMAPDATA* mim)
225 {
226     return midiInStop(mim->hMidi);
227 }
228
229 static  DWORD   midStart(MIDIMAPDATA* mim)
230 {
231     return midiInStart(mim->hMidi);
232 }
233
234 static  DWORD   midReset(MIDIMAPDATA* mim)
235 {
236     return midiInReset(mim->hMidi);
237 }
238
239 /**************************************************************************
240  *                              MIDIMAP_midMessage      [sample driver]
241  */
242 DWORD WINAPI MIDIMAP_midMessage(WORD wDevID, WORD wMsg, DWORD dwUser, 
243                                 DWORD dwParam1, DWORD dwParam2)
244 {
245     TRACE("(%u, %04X, %08lX, %08lX, %08lX);\n",
246           wDevID, wMsg, dwUser, dwParam1, dwParam2);
247
248     switch (wMsg) {
249     case DRVM_INIT:
250     case DRVM_EXIT:
251     case DRVM_ENABLE:
252     case DRVM_DISABLE:
253         /* FIXME: Pretend this is supported */
254         return 0;
255
256     case MIDM_OPEN:             return midOpen          ((LPDWORD)dwUser,     (LPMIDIOPENDESC)dwParam1, dwParam2);
257     case MIDM_CLOSE:            return midClose         ((MIDIMAPDATA*)dwUser);
258
259     case MIDM_ADDBUFFER:        return midAddBuffer     ((MIDIMAPDATA*)dwUser, (LPMIDIHDR)dwParam1, dwParam2);
260     case MIDM_PREPARE:          return midPrepare       ((MIDIMAPDATA*)dwUser, (LPMIDIHDR)dwParam1, dwParam2);
261     case MIDM_UNPREPARE:        return midUnprepare     ((MIDIMAPDATA*)dwUser, (LPMIDIHDR)dwParam1, dwParam2);
262     case MIDM_GETDEVCAPS:       return midGetDevCaps    (wDevID, (MIDIMAPDATA*)dwUser, (LPMIDIINCAPSA)dwParam1, dwParam2);
263     case MIDM_GETNUMDEVS:       return 1;
264     case MIDM_RESET:            return midReset         ((MIDIMAPDATA*)dwUser);
265     case MIDM_START:            return midStart         ((MIDIMAPDATA*)dwUser);
266     case MIDM_STOP:             return midStop          ((MIDIMAPDATA*)dwUser);
267     default:
268         FIXME("unknown message %u!\n", wMsg);
269     }
270     return MMSYSERR_NOTSUPPORTED;
271 }
272
273 /*======================================================================*
274  *                  Driver part                                         *
275  *======================================================================*/
276
277 static  struct WINE_MIDIMAP* oss = NULL;
278
279 /**************************************************************************
280  *                              MIDIMAP_drvOpen                 [internal]      
281  */
282 static  DWORD   MIDIMAP_drvOpen(LPSTR str)
283 {
284     if (oss)
285         return 0;
286     
287     /* I know, this is ugly, but who cares... */
288     oss = (struct WINE_MIDIMAP*)1;
289     return 1;
290 }
291
292 /**************************************************************************
293  *                              MIDIMAP_drvClose                [internal]      
294  */
295 static  DWORD   MIDIMAP_drvClose(DWORD dwDevID)
296 {
297     if (oss) {
298         oss = NULL;
299         return 1;
300     }
301     return 0;
302 }
303
304 /**************************************************************************
305  *                              MIDIMAP_DriverProc              [internal]
306  */
307 LONG CALLBACK   MIDIMAP_DriverProc(DWORD dwDevID, HDRVR hDriv, DWORD wMsg, 
308                                    DWORD dwParam1, DWORD dwParam2)
309 {
310 /* EPP     TRACE("(%08lX, %04X, %08lX, %08lX, %08lX)\n",  */
311 /* EPP    dwDevID, hDriv, wMsg, dwParam1, dwParam2); */
312     
313     switch(wMsg) {
314     case DRV_LOAD:              return 1;
315     case DRV_FREE:              return 1;
316     case DRV_OPEN:              return MIDIMAP_drvOpen((LPSTR)dwParam1);
317     case DRV_CLOSE:             return MIDIMAP_drvClose(dwDevID);
318     case DRV_ENABLE:            return 1;
319     case DRV_DISABLE:           return 1;
320     case DRV_QUERYCONFIGURE:    return 1;
321     case DRV_CONFIGURE:         MessageBoxA(0, "MIDIMAP MultiMedia Driver !", "OSS Driver", MB_OK);     return 1;
322     case DRV_INSTALL:           return DRVCNF_RESTART;
323     case DRV_REMOVE:            return DRVCNF_RESTART;
324     default:
325         return DefDriverProc(dwDevID, hDriv, wMsg, dwParam1, dwParam2);
326     }
327 }
328
329