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