Updated.
[wine] / dlls / winmm / wavemap / wavemap.c
1 /* -*- tab-width: 8; c-basic-offset: 4 -*- */
2 /*                                 
3  * Wine Wave mapper driver
4  *
5  * Copyright    1999 Eric Pouech
6  */
7
8 /* TODOs
9  *      + implement wavein as waveout has been implemented
10  *      + better protection against evilish dwUser parameters
11  *      + use asynchronous ACM conversion
12  */
13
14 #include <string.h>
15 #include "windef.h"
16 #include "winbase.h"
17 #include "wingdi.h"
18 #include "winuser.h"
19 #include "mmddk.h"
20 #include "msacm.h"
21 #include "debugtools.h"
22
23 DEFAULT_DEBUG_CHANNEL(msacm);
24
25 typedef struct tagWAVEMAPDATA {
26     struct tagWAVEMAPDATA*      self;
27     HWAVE       hWave;
28     HACMSTREAM  hAcmStream;
29     /* needed data to filter callbacks. Only needed when hAcmStream is not 0 */
30     DWORD       dwCallback;
31     DWORD       dwClientInstance;
32     DWORD       dwFlags;
33 } WAVEMAPDATA;
34
35 static  BOOL    WAVEMAP_IsData(WAVEMAPDATA* wm)
36 {
37     return (!IsBadReadPtr(wm, sizeof(WAVEMAPDATA)) && wm->self == wm);
38 }
39
40 /*======================================================================*
41  *                  WAVE OUT part                                       *
42  *======================================================================*/
43
44 static void     CALLBACK WAVEMAP_DstCallback(HDRVR hDev, UINT uMsg, DWORD dwInstance, 
45                                              DWORD dwParam1, DWORD dwParam2)
46 {
47     WAVEMAPDATA*        wom = (WAVEMAPDATA*)dwInstance;
48
49     TRACE("(0x%x %u %ld %lx %lx);\n", hDev, uMsg, dwInstance, dwParam1, dwParam2);
50
51     switch (uMsg) {
52     case WOM_OPEN:
53     case WOM_CLOSE:
54         /* dwParam1 & dwParam2 are supposed to be 0, nothing to do */
55         break;
56     case WOM_DONE:
57         {
58             LPWAVEHDR           lpWaveHdrDst = (LPWAVEHDR)dwParam1;
59             PACMSTREAMHEADER    ash = (PACMSTREAMHEADER)((LPSTR)lpWaveHdrDst - sizeof(ACMSTREAMHEADER));
60             LPWAVEHDR           lpWaveHdrSrc = (LPWAVEHDR)ash->dwUser;
61
62             lpWaveHdrSrc->dwFlags &= ~WHDR_INQUEUE;
63             lpWaveHdrSrc->dwFlags |= WHDR_DONE;
64             dwParam1 = (DWORD)lpWaveHdrSrc;
65         }
66         break;
67     default:
68         ERR("Unknown msg %u\n", uMsg);
69     }
70
71     DriverCallback(wom->dwCallback, HIWORD(wom->dwFlags), hDev, uMsg, 
72                    wom->dwClientInstance, dwParam1, dwParam2);
73 }
74
75 static  DWORD   wodOpenHelper(WAVEMAPDATA* wom, UINT idx, 
76                               LPWAVEOPENDESC lpDesc, LPWAVEFORMATEX lpwfx, 
77                               DWORD dwFlags)
78 {
79     DWORD       ret;
80
81     /* destination is always PCM, so the formulas below apply */
82     lpwfx->nBlockAlign = (lpwfx->nChannels * lpwfx->wBitsPerSample) / 8;
83     lpwfx->nAvgBytesPerSec = lpwfx->nSamplesPerSec * lpwfx->nBlockAlign;
84     ret = acmStreamOpen(&wom->hAcmStream, 0, lpDesc->lpFormat, lpwfx, NULL, 0L, 0L, 
85                         (dwFlags & WAVE_FORMAT_QUERY) ? ACM_STREAMOPENF_QUERY : 0L);
86     if (ret != MMSYSERR_NOERROR)
87         return ret;
88     return waveOutOpen(&wom->hWave, idx, lpwfx, (DWORD)WAVEMAP_DstCallback, 
89                        (DWORD)wom, (dwFlags & ~CALLBACK_TYPEMASK) | CALLBACK_FUNCTION);
90 }
91
92 static  DWORD   wodOpen(LPDWORD lpdwUser, LPWAVEOPENDESC lpDesc, DWORD dwFlags)
93 {
94     UINT                nd = waveOutGetNumDevs();
95     UINT                i;
96     WAVEMAPDATA*        wom = HeapAlloc(GetProcessHeap(), 0, sizeof(WAVEMAPDATA));
97     WAVEFORMATEX        wfx;
98
99     TRACE("(%p %p %08lx\n", lpdwUser, lpDesc, dwFlags);
100
101     if (!wom)
102         return MMSYSERR_NOMEM;
103
104     wom->self = wom;
105
106     for (i = 0; i < nd; i++) {
107         /* if no ACM stuff is involved, no need to handle callbacks at this
108          * level, this will be done transparently
109          */
110         if (waveOutOpen(&wom->hWave, i, lpDesc->lpFormat, lpDesc->dwCallback, 
111                         lpDesc->dwInstance, dwFlags) == MMSYSERR_NOERROR) {
112             wom->hAcmStream = 0;
113             goto found;
114         }
115     }
116
117     wfx.wFormatTag = WAVE_FORMAT_PCM;
118     wfx.cbSize = 0; /* normally, this field is not used for PCM format, just in case */
119     /* try some ACM stuff */
120
121     wom->dwCallback = lpDesc->dwCallback;
122     wom->dwFlags = dwFlags;
123     wom->dwClientInstance = lpDesc->dwInstance;
124
125 #define TRY(sps,bps)    wfx.nSamplesPerSec = (sps); wfx.wBitsPerSample = (bps); \
126                         if (wodOpenHelper(wom, i, lpDesc, &wfx, dwFlags) == MMSYSERR_NOERROR) goto found;
127
128     for (i = 0; i < nd; i++) {
129         /* first try with same stereo/mono option as source */
130         wfx.nChannels = lpDesc->lpFormat->nChannels;
131         TRY(44100, 8);
132         TRY(22050, 8);
133         TRY(11025, 8);
134
135         /* 2^3 => 1, 1^3 => 2, so if stereo, try mono (and the other way around) */
136         wfx.nChannels ^= 3; 
137         TRY(44100, 8);
138         TRY(22050, 8);
139         TRY(11025, 8);
140     }
141 #undef TRY
142                       
143     HeapFree(GetProcessHeap(), 0, wom);
144     return MMSYSERR_ALLOCATED;
145 found:
146     if (dwFlags & WAVE_FORMAT_QUERY) {
147         lpDesc->hWave = 0;
148         *lpdwUser = 0L;
149         HeapFree(GetProcessHeap(), 0, wom);
150     } else {
151         lpDesc->hWave = wom->hWave;
152         *lpdwUser = (DWORD)wom;
153     }
154     return MMSYSERR_NOERROR;
155 }
156
157 static  DWORD   wodClose(WAVEMAPDATA* wom)
158 {
159     DWORD ret = waveOutClose(wom->hWave);
160
161     if (ret == MMSYSERR_NOERROR) {
162         if (wom->hAcmStream) {
163             ret = acmStreamClose(wom->hAcmStream, 0);
164         }
165         if (ret == MMSYSERR_NOERROR) {
166             HeapFree(GetProcessHeap(), 0, wom);
167         }
168     }
169     return ret;
170 }
171
172 static  DWORD   wodWrite(WAVEMAPDATA* wom, LPWAVEHDR lpWaveHdrSrc, DWORD dwParam2)
173 {
174     PACMSTREAMHEADER    ash;
175     LPWAVEHDR           lpWaveHdrDst;
176
177     if (!wom->hAcmStream) {
178         return waveOutWrite(wom->hWave, lpWaveHdrSrc, dwParam2);
179     }
180     
181     lpWaveHdrSrc->dwFlags |= WHDR_INQUEUE;
182     ash = (PACMSTREAMHEADER)lpWaveHdrSrc->reserved;
183     if (acmStreamConvert(wom->hAcmStream, ash, 0L) != MMSYSERR_NOERROR)
184         return MMSYSERR_ERROR;
185     
186     lpWaveHdrDst = (LPWAVEHDR)((LPSTR)ash + sizeof(ACMSTREAMHEADER));
187     lpWaveHdrDst->dwBufferLength = ash->cbDstLengthUsed;
188     return waveOutWrite(wom->hWave, lpWaveHdrDst, sizeof(*lpWaveHdrDst));
189 }
190
191 static  DWORD   wodPrepare(WAVEMAPDATA* wom, LPWAVEHDR lpWaveHdrSrc, DWORD dwParam2)
192 {
193     PACMSTREAMHEADER    ash;
194     DWORD               size;
195     DWORD               dwRet;
196     LPWAVEHDR           lpWaveHdrDst;
197
198     if (!wom->hAcmStream) {
199         return waveOutPrepareHeader(wom->hWave, lpWaveHdrSrc, dwParam2);
200     }
201     if (acmStreamSize(wom->hAcmStream, lpWaveHdrSrc->dwBufferLength, &size, ACM_STREAMSIZEF_SOURCE) != MMSYSERR_NOERROR)
202         return MMSYSERR_ERROR;
203
204     ash = HeapAlloc(GetProcessHeap(), 0, sizeof(ACMSTREAMHEADER) + sizeof(WAVEHDR) + size);
205     if (ash == NULL)
206         return MMSYSERR_NOMEM;
207
208     ash->cbStruct = sizeof(*ash);
209     ash->fdwStatus = 0L;
210     ash->dwUser = (DWORD)lpWaveHdrSrc;
211     ash->pbSrc = lpWaveHdrSrc->lpData;
212     ash->cbSrcLength = lpWaveHdrSrc->dwBufferLength;
213     /* ash->cbSrcLengthUsed */
214     ash->dwSrcUser = lpWaveHdrSrc->dwUser; /* FIXME ? */
215     ash->pbDst = (LPSTR)ash + sizeof(ACMSTREAMHEADER) + sizeof(WAVEHDR);
216     ash->cbDstLength = size;
217     /* ash->cbDstLengthUsed */
218     ash->dwDstUser = 0; /* FIXME ? */
219     dwRet = acmStreamPrepareHeader(wom->hAcmStream, ash, 0L);
220     if (dwRet != MMSYSERR_NOERROR)
221         goto errCleanUp;
222
223     lpWaveHdrDst = (LPWAVEHDR)((LPSTR)ash + sizeof(ACMSTREAMHEADER));
224     lpWaveHdrDst->lpData = ash->pbDst;
225     lpWaveHdrDst->dwBufferLength = size; /* conversion is not done yet */
226     lpWaveHdrDst->dwFlags = 0;
227     lpWaveHdrDst->dwLoops = 0;
228     dwRet = waveOutPrepareHeader(wom->hWave, lpWaveHdrDst, sizeof(*lpWaveHdrDst));
229     if (dwRet != MMSYSERR_NOERROR)
230         goto errCleanUp;
231
232     lpWaveHdrSrc->reserved = (DWORD)ash;
233     lpWaveHdrSrc->dwFlags = WHDR_PREPARED;
234     TRACE("=> (0)\n");
235     return MMSYSERR_NOERROR;
236 errCleanUp:
237     TRACE("=> (%ld)\n", dwRet);
238     HeapFree(GetProcessHeap(), 0, ash);
239     return dwRet;
240 }
241
242 static  DWORD   wodUnprepare(WAVEMAPDATA* wom, LPWAVEHDR lpWaveHdrSrc, DWORD dwParam2)
243 {
244     PACMSTREAMHEADER    ash;
245     LPWAVEHDR           lpWaveHdrDst;
246     DWORD               dwRet1, dwRet2;
247
248     if (!wom->hAcmStream) {
249         return waveOutUnprepareHeader(wom->hWave, lpWaveHdrSrc, dwParam2);
250     }
251     ash = (PACMSTREAMHEADER)lpWaveHdrSrc->reserved;
252     dwRet1 = acmStreamUnprepareHeader(wom->hAcmStream, ash, 0L);
253     
254     lpWaveHdrDst = (LPWAVEHDR)((LPSTR)ash + sizeof(ACMSTREAMHEADER));
255     dwRet2 = waveOutUnprepareHeader(wom->hWave, lpWaveHdrDst, sizeof(*lpWaveHdrDst));
256
257     HeapFree(GetProcessHeap(), 0, ash);
258     
259     lpWaveHdrSrc->dwFlags &= ~WHDR_PREPARED;
260     return (dwRet1 == MMSYSERR_NOERROR) ? dwRet2 : dwRet1;
261 }
262
263 static  DWORD   wodGetPosition(WAVEMAPDATA* wom, LPMMTIME lpTime, DWORD dwParam2)
264 {
265     return waveOutGetPosition(wom->hWave, lpTime, dwParam2);
266 }
267
268 static  DWORD   wodGetDevCaps(UINT wDevID, WAVEMAPDATA* wom, LPWAVEOUTCAPSA lpWaveCaps, DWORD dwParam2)
269 {
270     /* if opened low driver, forward message */
271     if (WAVEMAP_IsData(wom))
272         return waveOutGetDevCapsA(wom->hWave, lpWaveCaps, dwParam2);
273     /* otherwise, return caps of mapper itself */
274     if (wDevID == (UINT)-1 || wDevID == (UINT16)-1) {
275         lpWaveCaps->wMid = 0x00FF;
276         lpWaveCaps->wPid = 0x0001;
277         lpWaveCaps->vDriverVersion = 0x0100;
278         strcpy(lpWaveCaps->szPname, "Wine wave out mapper");
279         lpWaveCaps->dwFormats = 
280             WAVE_FORMAT_4M08 | WAVE_FORMAT_4S08 | WAVE_FORMAT_4M16 | WAVE_FORMAT_4S16 |
281             WAVE_FORMAT_2M08 | WAVE_FORMAT_2S08 | WAVE_FORMAT_2M16 | WAVE_FORMAT_2S16 |
282             WAVE_FORMAT_1M08 | WAVE_FORMAT_1S08 | WAVE_FORMAT_1M16 | WAVE_FORMAT_1S16;
283         lpWaveCaps->wChannels = 2;
284         lpWaveCaps->dwSupport = WAVECAPS_VOLUME | WAVECAPS_LRVOLUME;
285
286         return MMSYSERR_NOERROR;
287     }
288     ERR("This shouldn't happen\n");
289     return MMSYSERR_ERROR; 
290 }
291
292 static  DWORD   wodGetVolume(UINT wDevID, WAVEMAPDATA* wom, LPDWORD lpVol)
293 {
294     if (WAVEMAP_IsData(wom))
295         return waveOutGetVolume(wom->hWave, lpVol);
296     return MMSYSERR_NOERROR;
297 }
298
299 static  DWORD   wodSetVolume(UINT wDevID, WAVEMAPDATA* wom, DWORD vol)
300 {
301     if (WAVEMAP_IsData(wom))
302         return waveOutSetVolume(wom->hWave, vol);
303     return MMSYSERR_NOERROR;
304 }
305
306 static  DWORD   wodPause(WAVEMAPDATA* wom)
307 {
308     return waveOutPause(wom->hWave);
309 }
310
311 static  DWORD   wodRestart(WAVEMAPDATA* wom)
312 {
313     return waveOutRestart(wom->hWave);
314 }
315
316 static  DWORD   wodReset(WAVEMAPDATA* wom)
317 {
318     return waveOutReset(wom->hWave);
319 }
320
321 static  DWORD   wodBreakLoop(WAVEMAPDATA* wom)
322 {
323     return waveOutBreakLoop(wom->hWave);
324 }
325
326 static  DWORD   wodMapperStatus(WAVEMAPDATA* wom, DWORD flags, LPVOID ptr)
327 {
328     UINT        id;
329     DWORD       ret = MMSYSERR_NOTSUPPORTED;
330
331     switch (flags) {
332     case WAVEOUT_MAPPER_STATUS_DEVICE:  
333         ret = waveOutGetID(wom->hWave, &id);
334         *(LPDWORD)ptr = id;
335         break;
336     case WAVEOUT_MAPPER_STATUS_MAPPED:
337         FIXME("Unsupported flag=%ld\n", flags);
338         *(LPDWORD)ptr = 0; /* FIXME ?? */       
339         break;
340     case WAVEOUT_MAPPER_STATUS_FORMAT:
341         FIXME("Unsupported flag=%ld\n", flags);
342         /* ptr points to a WAVEFORMATEX struct - before or after streaming ? */
343         *(LPDWORD)ptr = 0;
344         break;
345     default:
346         FIXME("Unsupported flag=%ld\n", flags);
347         *(LPDWORD)ptr = 0;
348         break;
349     }
350     return ret;
351 }
352
353 /**************************************************************************
354  *                              WAVEMAP_wodMessage      [sample driver]
355  */
356 DWORD WINAPI WAVEMAP_wodMessage(UINT wDevID, UINT wMsg, DWORD dwUser, 
357                                 DWORD dwParam1, DWORD dwParam2)
358 {
359     TRACE("(%u, %04X, %08lX, %08lX, %08lX);\n",
360           wDevID, wMsg, dwUser, dwParam1, dwParam2);
361     
362     switch (wMsg) {
363     case DRVM_INIT:
364     case DRVM_EXIT:
365     case DRVM_ENABLE:
366     case DRVM_DISABLE:
367         /* FIXME: Pretend this is supported */
368         return 0;
369     case WODM_OPEN:             return wodOpen          ((LPDWORD)dwUser,      (LPWAVEOPENDESC)dwParam1,dwParam2);
370     case WODM_CLOSE:            return wodClose         ((WAVEMAPDATA*)dwUser);
371     case WODM_WRITE:            return wodWrite         ((WAVEMAPDATA*)dwUser, (LPWAVEHDR)dwParam1,     dwParam2);
372     case WODM_PAUSE:            return wodPause         ((WAVEMAPDATA*)dwUser);
373     case WODM_GETPOS:           return wodGetPosition   ((WAVEMAPDATA*)dwUser, (LPMMTIME)dwParam1,      dwParam2);
374     case WODM_BREAKLOOP:        return wodBreakLoop     ((WAVEMAPDATA*)dwUser);
375     case WODM_PREPARE:          return wodPrepare       ((WAVEMAPDATA*)dwUser, (LPWAVEHDR)dwParam1,     dwParam2);
376     case WODM_UNPREPARE:        return wodUnprepare     ((WAVEMAPDATA*)dwUser, (LPWAVEHDR)dwParam1,     dwParam2);
377     case WODM_GETDEVCAPS:       return wodGetDevCaps    (wDevID, (WAVEMAPDATA*)dwUser, (LPWAVEOUTCAPSA)dwParam1,dwParam2);
378     case WODM_GETNUMDEVS:       return 1;
379     case WODM_GETPITCH:         return MMSYSERR_NOTSUPPORTED;
380     case WODM_SETPITCH:         return MMSYSERR_NOTSUPPORTED;
381     case WODM_GETPLAYBACKRATE:  return MMSYSERR_NOTSUPPORTED;
382     case WODM_SETPLAYBACKRATE:  return MMSYSERR_NOTSUPPORTED;
383     case WODM_GETVOLUME:        return wodGetVolume     (wDevID, (WAVEMAPDATA*)dwUser, (LPDWORD)dwParam1);
384     case WODM_SETVOLUME:        return wodSetVolume     (wDevID, (WAVEMAPDATA*)dwUser, dwParam1);
385     case WODM_RESTART:          return wodRestart       ((WAVEMAPDATA*)dwUser);
386     case WODM_RESET:            return wodReset         ((WAVEMAPDATA*)dwUser);
387     case WODM_MAPPER_STATUS:    return wodMapperStatus  ((WAVEMAPDATA*)dwUser, dwParam1, (LPVOID)dwParam2);
388     default:
389         FIXME("unknown message %d!\n", wMsg);
390     }
391     return MMSYSERR_NOTSUPPORTED;
392 }
393
394 /*======================================================================*
395  *                  WAVE IN part                                        *
396  *======================================================================*/
397
398 static  DWORD   widOpen(LPDWORD lpdwUser, LPWAVEOPENDESC lpDesc, DWORD dwFlags)
399 {
400     UINT                nd = waveInGetNumDevs();
401     UINT                i;
402     WAVEMAPDATA*        wim = HeapAlloc(GetProcessHeap(), 0, sizeof(WAVEMAPDATA));
403
404     TRACE("(%p %p %08lx\n", lpdwUser, lpDesc, dwFlags);
405
406     wim->self = wim;
407
408     for (i = 0; i < nd; i++) {
409         if (waveInOpen(&wim->hWave, i, lpDesc->lpFormat, lpDesc->dwCallback, 
410                         lpDesc->dwInstance, dwFlags) == MMSYSERR_NOERROR) {
411             lpDesc->hWave = wim->hWave;
412             *lpdwUser = (DWORD)wim;
413             return MMSYSERR_NOERROR;
414         }
415     }
416     HeapFree(GetProcessHeap(), 0, wim);
417     return MMSYSERR_ALLOCATED;
418 }
419
420 static  DWORD   widClose(WAVEMAPDATA* wim)
421 {
422     DWORD ret = waveInClose(wim->hWave);
423     if (ret == MMSYSERR_NOERROR)
424         HeapFree(GetProcessHeap(), 0, wim);
425     return ret;
426 }
427
428 static  DWORD   widAddBuffer(WAVEMAPDATA* wim, LPWAVEHDR lpWaveHdr, DWORD dwParam2)
429 {
430     return waveInAddBuffer(wim->hWave, lpWaveHdr, dwParam2);
431 }
432
433 static  DWORD   widPrepare(WAVEMAPDATA* wim, LPWAVEHDR lpWaveHdr, DWORD dwParam2)
434 {
435     return waveInPrepareHeader(wim->hWave, lpWaveHdr, dwParam2);
436 }
437
438 static  DWORD   widUnprepare(WAVEMAPDATA* wim, LPWAVEHDR lpWaveHdr, DWORD dwParam2)
439 {
440     return waveInUnprepareHeader(wim->hWave, lpWaveHdr, dwParam2);
441 }
442
443 static  DWORD   widGetPosition(WAVEMAPDATA* wim, LPMMTIME lpTime, DWORD dwParam2)
444 {
445     return waveInGetPosition(wim->hWave, lpTime, dwParam2);
446 }
447
448 static  DWORD   widGetDevCaps(UINT wDevID, WAVEMAPDATA* wim, LPWAVEINCAPSA lpWaveCaps, DWORD dwParam2)
449 {
450     /* if opened low driver, forward message */
451     if (WAVEMAP_IsData(wim))
452         return waveInGetDevCapsA(wim->hWave, lpWaveCaps, dwParam2);
453     /* otherwise, return caps of mapper itself */
454     if (wDevID == (UINT)-1 || wDevID == (UINT16)-1) {
455         lpWaveCaps->wMid = 0x00FF;
456         lpWaveCaps->wPid = 0x0001;
457         lpWaveCaps->vDriverVersion = 0x0001;
458         strcpy(lpWaveCaps->szPname, "Wine wave in mapper");
459         lpWaveCaps->dwFormats = 
460             WAVE_FORMAT_4M08 | WAVE_FORMAT_4S08 | WAVE_FORMAT_4M16 | WAVE_FORMAT_4S16 |
461             WAVE_FORMAT_2M08 | WAVE_FORMAT_2S08 | WAVE_FORMAT_2M16 | WAVE_FORMAT_2S16 |
462             WAVE_FORMAT_1M08 | WAVE_FORMAT_1S08 | WAVE_FORMAT_1M16 | WAVE_FORMAT_1S16;    
463         lpWaveCaps->wChannels = 2;
464         return MMSYSERR_NOERROR;
465     }
466     ERR("This shouldn't happen\n");
467     return MMSYSERR_ERROR; 
468 }
469
470 static  DWORD   widStop(WAVEMAPDATA* wim)
471 {
472     return waveInStop(wim->hWave);
473 }
474
475 static  DWORD   widStart(WAVEMAPDATA* wim)
476 {
477     return waveInStart(wim->hWave);
478 }
479
480 static  DWORD   widReset(WAVEMAPDATA* wim)
481 {
482     return waveInReset(wim->hWave);
483 }
484
485 static  DWORD   widMapperStatus(WAVEMAPDATA* wim, DWORD flags, LPVOID ptr)
486 {
487     UINT        id;
488     DWORD       ret = MMSYSERR_NOTSUPPORTED;
489
490     switch (flags) {
491     case WAVEIN_MAPPER_STATUS_DEVICE:   
492         ret = waveInGetID(wim->hWave, &id);
493         *(LPDWORD)ptr = id;
494         break;
495     case WAVEIN_MAPPER_STATUS_MAPPED:
496         FIXME("Unsupported yet flag=%ld\n", flags);
497         *(LPDWORD)ptr = 0; /* FIXME ?? */       
498         break;
499     case WAVEIN_MAPPER_STATUS_FORMAT:
500         FIXME("Unsupported flag=%ld\n", flags);
501         /* ptr points to a WAVEFORMATEX struct  - before or after streaming ? */
502         *(LPDWORD)ptr = 0; /* FIXME ?? */       
503         break;
504     default:
505         FIXME("Unsupported flag=%ld\n", flags);
506         *(LPDWORD)ptr = 0;
507         break;
508     }
509     return ret;
510 }
511
512 /**************************************************************************
513  *                              WAVEMAP_widMessage      [sample driver]
514  */
515 DWORD WINAPI WAVEMAP_widMessage(WORD wDevID, WORD wMsg, DWORD dwUser, 
516                                 DWORD dwParam1, DWORD dwParam2)
517 {
518     TRACE("(%u, %04X, %08lX, %08lX, %08lX);\n",
519           wDevID, wMsg, dwUser, dwParam1, dwParam2);
520
521     switch (wMsg) {
522     case DRVM_INIT:
523     case DRVM_EXIT:
524     case DRVM_ENABLE:
525     case DRVM_DISABLE:
526         /* FIXME: Pretend this is supported */
527         return 0;
528
529     case WIDM_OPEN:             return widOpen          ((LPDWORD)dwUser,     (LPWAVEOPENDESC)dwParam1, dwParam2);
530     case WIDM_CLOSE:            return widClose         ((WAVEMAPDATA*)dwUser);
531
532     case WIDM_ADDBUFFER:        return widAddBuffer     ((WAVEMAPDATA*)dwUser, (LPWAVEHDR)dwParam1,     dwParam2);
533     case WIDM_PREPARE:          return widPrepare       ((WAVEMAPDATA*)dwUser, (LPWAVEHDR)dwParam1,     dwParam2);
534     case WIDM_UNPREPARE:        return widUnprepare     ((WAVEMAPDATA*)dwUser, (LPWAVEHDR)dwParam1,     dwParam2);
535     case WIDM_GETDEVCAPS:       return widGetDevCaps    (wDevID, (WAVEMAPDATA*)dwUser, (LPWAVEINCAPSA)dwParam1, dwParam2);
536     case WIDM_GETNUMDEVS:       return 1;
537     case WIDM_GETPOS:           return widGetPosition   ((WAVEMAPDATA*)dwUser, (LPMMTIME)dwParam1,      dwParam2);
538     case WIDM_RESET:            return widReset         ((WAVEMAPDATA*)dwUser);
539     case WIDM_START:            return widStart         ((WAVEMAPDATA*)dwUser);
540     case WIDM_STOP:             return widStop          ((WAVEMAPDATA*)dwUser);
541     case WIDM_MAPPER_STATUS:    return widMapperStatus  ((WAVEMAPDATA*)dwUser, dwParam1, (LPVOID)dwParam2);
542     default:
543         FIXME("unknown message %u!\n", wMsg);
544     }
545     return MMSYSERR_NOTSUPPORTED;
546 }
547
548 /*======================================================================*
549  *                  Driver part                                         *
550  *======================================================================*/
551
552 static  struct WINE_WAVEMAP* oss = NULL;
553
554 /**************************************************************************
555  *                              WAVEMAP_drvOpen                 [internal]      
556  */
557 static  DWORD   WAVEMAP_drvOpen(LPSTR str)
558 {
559     if (oss)
560         return 0;
561     
562     /* I know, this is ugly, but who cares... */
563     oss = (struct WINE_WAVEMAP*)1;
564     return 1;
565 }
566
567 /**************************************************************************
568  *                              WAVEMAP_drvClose                [internal]      
569  */
570 static  DWORD   WAVEMAP_drvClose(DWORD dwDevID)
571 {
572     if (oss) {
573         oss = NULL;
574         return 1;
575     }
576     return 0;
577 }
578
579 /**************************************************************************
580  *                              WAVEMAP_DriverProc              [internal]
581  */
582 LONG CALLBACK   WAVEMAP_DriverProc(DWORD dwDevID, HDRVR hDriv, DWORD wMsg, 
583                                    DWORD dwParam1, DWORD dwParam2)
584 {
585 /* EPP     TRACE("(%08lX, %04X, %08lX, %08lX, %08lX)\n",  */
586 /* EPP    dwDevID, hDriv, wMsg, dwParam1, dwParam2); */
587     
588     switch(wMsg) {
589     case DRV_LOAD:              return 1;
590     case DRV_FREE:              return 1;
591     case DRV_OPEN:              return WAVEMAP_drvOpen((LPSTR)dwParam1);
592     case DRV_CLOSE:             return WAVEMAP_drvClose(dwDevID);
593     case DRV_ENABLE:            return 1;
594     case DRV_DISABLE:           return 1;
595     case DRV_QUERYCONFIGURE:    return 1;
596     case DRV_CONFIGURE:         MessageBoxA(0, "WAVEMAP MultiMedia Driver !", "OSS Driver", MB_OK);     return 1;
597     case DRV_INSTALL:           return DRVCNF_RESTART;
598     case DRV_REMOVE:            return DRVCNF_RESTART;
599     default:
600         return DefDriverProc(dwDevID, hDriv, wMsg, dwParam1, dwParam2);
601     }
602 }
603
604