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