1 /* -*- tab-width: 8; c-basic-offset: 4 -*- */
3 * Sample Wine Driver for Open Sound System (featured in Linux and FreeBSD)
5 * Copyright 1994 Martin Ayotte
9 * - record/play should and must be done asynchronous
10 * - segmented/linear pointer problems (lpData in waveheaders,W*_DONE cbs)
22 #include <sys/ioctl.h>
23 #include "wine/winuser16.h"
25 #include "multimedia.h"
31 #define SOUND_DEV "/dev/dsp"
32 #define MIXER_DEV "/dev/mixer"
34 #define MAX_WAVEOUTDRV (1)
35 #define MAX_WAVEINDRV (1)
41 WAVEOPENDESC waveDesc
;
51 DWORD bufsize
; /* OpenSound '/dev/dsp' give us that size */
52 WAVEOPENDESC waveDesc
;
56 DWORD dwTotalRecorded
;
59 static WINE_WAVEOUT WOutDev
[MAX_WAVEOUTDRV
];
60 static WINE_WAVEIN WInDev
[MAX_WAVEOUTDRV
];
62 /*======================================================================*
63 * Low level WAVE implemantation *
64 *======================================================================*/
66 /**************************************************************************
67 * WAVE_NotifyClient [internal]
69 static DWORD
WAVE_NotifyClient(UINT16 wDevID
, WORD wMsg
,
70 DWORD dwParam1
, DWORD dwParam2
)
72 TRACE(wave
,"wDevID = %04X wMsg = %d dwParm1 = %04lX dwParam2 = %04lX\n",wDevID
, wMsg
, dwParam1
, dwParam2
);
78 if (wDevID
> MAX_WAVEOUTDRV
) return MCIERR_INTERNAL
;
80 if (WOutDev
[wDevID
].wFlags
!= DCB_NULL
&&
82 WOutDev
[wDevID
].waveDesc
.dwCallBack
,
83 WOutDev
[wDevID
].wFlags
,
84 WOutDev
[wDevID
].waveDesc
.hWave
,
86 WOutDev
[wDevID
].waveDesc
.dwInstance
,
89 WARN(wave
, "can't notify client !\n");
90 return MMSYSERR_NOERROR
;
97 if (wDevID
> MAX_WAVEINDRV
) return MCIERR_INTERNAL
;
99 if (WInDev
[wDevID
].wFlags
!= DCB_NULL
&&
101 WInDev
[wDevID
].waveDesc
.dwCallBack
,
102 WInDev
[wDevID
].wFlags
,
103 WInDev
[wDevID
].waveDesc
.hWave
,
105 WInDev
[wDevID
].waveDesc
.dwInstance
,
108 WARN(wave
, "can't notify client !\n");
109 return MMSYSERR_NOERROR
;
116 /**************************************************************************
117 * wodGetDevCaps [internal]
119 static DWORD
wodGetDevCaps(WORD wDevID
, LPWAVEOUTCAPS16 lpCaps
, DWORD dwSize
)
127 TRACE(wave
, "(%u, %p, %lu);\n", wDevID
, lpCaps
, dwSize
);
128 if (lpCaps
== NULL
) return MMSYSERR_NOTENABLED
;
129 if (access(SOUND_DEV
,0) != 0) return MMSYSERR_NOTENABLED
;
130 audio
= open (SOUND_DEV
, O_WRONLY
, 0);
131 if (audio
== -1) return MMSYSERR_ALLOCATED
;
133 lpCaps
->wMid
= 0x0002;
134 lpCaps
->wPid
= 0x0104;
135 strcpy(lpCaps
->szPname
, "SB16 Wave Out");
137 lpCaps
->wMid
= 0x00FF; /* Manufac ID */
138 lpCaps
->wPid
= 0x0001; /* Product ID */
139 strcpy(lpCaps
->szPname
, "OpenSoundSystem WAVOUT Driver");
141 lpCaps
->vDriverVersion
= 0x0100;
142 lpCaps
->dwFormats
= 0x00000000;
143 lpCaps
->dwSupport
= WAVECAPS_VOLUME
;
145 /* First bytespersampl, then stereo */
146 bytespersmpl
= (IOCTL(audio
, SNDCTL_DSP_SAMPLESIZE
, samplesize
) != 0) ? 1 : 2;
148 lpCaps
->wChannels
= (IOCTL(audio
, SNDCTL_DSP_STEREO
, dsp_stereo
) != 0) ? 1 : 2;
149 if (lpCaps
->wChannels
> 1) lpCaps
->dwSupport
|= WAVECAPS_LRVOLUME
;
152 if (IOCTL(audio
, SNDCTL_DSP_SPEED
, smplrate
) == 0) {
153 lpCaps
->dwFormats
|= WAVE_FORMAT_4M08
;
154 if (lpCaps
->wChannels
> 1)
155 lpCaps
->dwFormats
|= WAVE_FORMAT_4S08
;
156 if (bytespersmpl
> 1) {
157 lpCaps
->dwFormats
|= WAVE_FORMAT_4M16
;
158 if (lpCaps
->wChannels
> 1)
159 lpCaps
->dwFormats
|= WAVE_FORMAT_4S16
;
163 if (IOCTL(audio
, SNDCTL_DSP_SPEED
, smplrate
) == 0) {
164 lpCaps
->dwFormats
|= WAVE_FORMAT_2M08
;
165 if (lpCaps
->wChannels
> 1)
166 lpCaps
->dwFormats
|= WAVE_FORMAT_2S08
;
167 if (bytespersmpl
> 1) {
168 lpCaps
->dwFormats
|= WAVE_FORMAT_2M16
;
169 if (lpCaps
->wChannels
> 1)
170 lpCaps
->dwFormats
|= WAVE_FORMAT_2S16
;
174 if (IOCTL(audio
, SNDCTL_DSP_SPEED
, smplrate
) == 0) {
175 lpCaps
->dwFormats
|= WAVE_FORMAT_1M08
;
176 if (lpCaps
->wChannels
> 1)
177 lpCaps
->dwFormats
|= WAVE_FORMAT_1S08
;
178 if (bytespersmpl
> 1) {
179 lpCaps
->dwFormats
|= WAVE_FORMAT_1M16
;
180 if (lpCaps
->wChannels
> 1)
181 lpCaps
->dwFormats
|= WAVE_FORMAT_1S16
;
185 TRACE(wave
, "dwFormats = %08lX\n", lpCaps
->dwFormats
);
186 return MMSYSERR_NOERROR
;
190 /**************************************************************************
193 static DWORD
wodOpen(WORD wDevID
, LPWAVEOPENDESC lpDesc
, DWORD dwFlags
)
195 int audio
,abuf_size
,smplrate
,samplesize
,dsp_stereo
;
196 LPWAVEFORMAT lpFormat
;
198 TRACE(wave
, "(%u, %p, %08lX);\n", wDevID
, lpDesc
, dwFlags
);
199 if (lpDesc
== NULL
) {
200 WARN(wave
, "Invalid Parameter !\n");
201 return MMSYSERR_INVALPARAM
;
203 if (wDevID
>= MAX_WAVEOUTDRV
) {
204 TRACE(wave
,"MAX_WAVOUTDRV reached !\n");
205 return MMSYSERR_ALLOCATED
;
207 WOutDev
[wDevID
].unixdev
= 0;
208 if (access(SOUND_DEV
,0) != 0) return MMSYSERR_NOTENABLED
;
209 audio
= open (SOUND_DEV
, O_WRONLY
, 0);
211 WARN(wave
, "can't open !\n");
212 return MMSYSERR_ALLOCATED
;
214 IOCTL(audio
, SNDCTL_DSP_GETBLKSIZE
, abuf_size
);
215 if (abuf_size
< 1024 || abuf_size
> 65536) {
217 WARN(wave
, "IOCTL can't 'SNDCTL_DSP_GETBLKSIZE' !\n");
219 WARN(wave
, "SNDCTL_DSP_GETBLKSIZE Invalid bufsize !\n");
220 return MMSYSERR_NOTENABLED
;
222 WOutDev
[wDevID
].wFlags
= HIWORD(dwFlags
& CALLBACK_TYPEMASK
);
223 switch(WOutDev
[wDevID
].wFlags
) {
225 TRACE(wave
, "CALLBACK_NULL !\n");
228 TRACE(wave
, "CALLBACK_WINDOW !\n");
231 TRACE(wave
, "CALLBACK_TASK !\n");
234 TRACE(wave
, "CALLBACK_FUNCTION !\n");
237 WOutDev
[wDevID
].lpQueueHdr
= NULL
;
238 WOutDev
[wDevID
].unixdev
= audio
;
239 WOutDev
[wDevID
].dwTotalPlayed
= 0;
240 WOutDev
[wDevID
].bufsize
= abuf_size
;
241 /* FIXME: copy lpFormat too? */
242 memcpy(&WOutDev
[wDevID
].waveDesc
, lpDesc
, sizeof(WAVEOPENDESC
));
243 TRACE(wave
,"lpDesc->lpFormat = %p\n",lpDesc
->lpFormat
);
244 lpFormat
= lpDesc
->lpFormat
;
245 TRACE(wave
,"lpFormat = %p\n",lpFormat
);
246 if (lpFormat
->wFormatTag
!= WAVE_FORMAT_PCM
) {
247 WARN(wave
,"Bad format %04X !\n", lpFormat
->wFormatTag
);
248 WARN(wave
,"Bad nChannels %d !\n", lpFormat
->nChannels
);
249 WARN(wave
,"Bad nSamplesPerSec %ld !\n", lpFormat
->nSamplesPerSec
);
250 return WAVERR_BADFORMAT
;
252 memcpy(&WOutDev
[wDevID
].Format
, lpFormat
, sizeof(PCMWAVEFORMAT
));
253 if (WOutDev
[wDevID
].Format
.wf
.nChannels
== 0) return WAVERR_BADFORMAT
;
254 if (WOutDev
[wDevID
].Format
.wf
.nSamplesPerSec
== 0) return WAVERR_BADFORMAT
;
255 TRACE(wave
,"wBitsPerSample=%u !\n", WOutDev
[wDevID
].Format
.wBitsPerSample
);
256 if (WOutDev
[wDevID
].Format
.wBitsPerSample
== 0) {
257 WOutDev
[wDevID
].Format
.wBitsPerSample
= 8 *
258 (WOutDev
[wDevID
].Format
.wf
.nAvgBytesPerSec
/
259 WOutDev
[wDevID
].Format
.wf
.nSamplesPerSec
) /
260 WOutDev
[wDevID
].Format
.wf
.nChannels
;
262 samplesize
= WOutDev
[wDevID
].Format
.wBitsPerSample
;
263 smplrate
= WOutDev
[wDevID
].Format
.wf
.nSamplesPerSec
;
264 dsp_stereo
= (WOutDev
[wDevID
].Format
.wf
.nChannels
> 1) ? TRUE
: FALSE
;
266 /* First size and stereo then samplerate */
267 IOCTL(audio
, SNDCTL_DSP_SAMPLESIZE
, samplesize
);
268 IOCTL(audio
, SNDCTL_DSP_STEREO
, dsp_stereo
);
269 IOCTL(audio
, SNDCTL_DSP_SPEED
, smplrate
);
271 TRACE(wave
,"wBitsPerSample=%u !\n", WOutDev
[wDevID
].Format
.wBitsPerSample
);
272 TRACE(wave
,"nAvgBytesPerSec=%lu !\n", WOutDev
[wDevID
].Format
.wf
.nAvgBytesPerSec
);
273 TRACE(wave
,"nSamplesPerSec=%lu !\n", WOutDev
[wDevID
].Format
.wf
.nSamplesPerSec
);
274 TRACE(wave
,"nChannels=%u !\n", WOutDev
[wDevID
].Format
.wf
.nChannels
);
275 if (WAVE_NotifyClient(wDevID
, WOM_OPEN
, 0L, 0L) != MMSYSERR_NOERROR
) {
276 WARN(wave
, "can't notify client !\n");
277 return MMSYSERR_INVALPARAM
;
279 return MMSYSERR_NOERROR
;
282 /**************************************************************************
283 * wodClose [internal]
285 static DWORD
wodClose(WORD wDevID
)
287 TRACE(wave
,"(%u);\n", wDevID
);
289 if (wDevID
> MAX_WAVEOUTDRV
) return MMSYSERR_INVALPARAM
;
290 if (WOutDev
[wDevID
].unixdev
== 0) {
291 WARN(wave
, "can't close !\n");
292 return MMSYSERR_NOTENABLED
;
294 if (WOutDev
[wDevID
].lpQueueHdr
!= NULL
) {
295 WARN(wave
, "still buffers open !\n");
296 /* Don't care. Who needs those buffers anyway */
297 /*return WAVERR_STILLPLAYING; */
299 close(WOutDev
[wDevID
].unixdev
);
300 WOutDev
[wDevID
].unixdev
= 0;
301 WOutDev
[wDevID
].bufsize
= 0;
302 WOutDev
[wDevID
].lpQueueHdr
= NULL
;
303 if (WAVE_NotifyClient(wDevID
, WOM_CLOSE
, 0L, 0L) != MMSYSERR_NOERROR
) {
304 WARN(wave
, "can't notify client !\n");
305 return MMSYSERR_INVALPARAM
;
307 return MMSYSERR_NOERROR
;
310 /**************************************************************************
311 * wodWrite [internal]
312 * FIXME: this should _APPEND_ the lpWaveHdr to the output queue of the
313 * device, and initiate async playing.
315 static DWORD
wodWrite(WORD wDevID
, LPWAVEHDR lpWaveHdr
, DWORD dwSize
)
321 TRACE(wave
,"(%u, %p, %08lX);\n", wDevID
, lpWaveHdr
, dwSize
);
322 if (WOutDev
[wDevID
].unixdev
== 0) {
323 WARN(wave
, "can't play !\n");
324 return MMSYSERR_NOTENABLED
;
326 if (lpWaveHdr
->lpData
== NULL
) return WAVERR_UNPREPARED
;
327 if (!(lpWaveHdr
->dwFlags
& WHDR_PREPARED
)) return WAVERR_UNPREPARED
;
328 if (lpWaveHdr
->dwFlags
& WHDR_INQUEUE
) return WAVERR_STILLPLAYING
;
329 lpWaveHdr
->dwFlags
&= ~WHDR_DONE
;
330 lpWaveHdr
->dwFlags
|= WHDR_INQUEUE
;
331 TRACE(wave
, "dwBufferLength %lu !\n", lpWaveHdr
->dwBufferLength
);
332 TRACE(wave
, "WOutDev[%u].unixdev %u !\n", wDevID
, WOutDev
[wDevID
].unixdev
);
333 lpData
= lpWaveHdr
->lpData
;
334 count
= write (WOutDev
[wDevID
].unixdev
, lpData
, lpWaveHdr
->dwBufferLength
);
335 TRACE(wave
,"write returned count %u !\n",count
);
336 if (count
!= lpWaveHdr
->dwBufferLength
) {
337 WARN(wave
, " error writing !\n");
338 return MMSYSERR_NOTENABLED
;
340 WOutDev
[wDevID
].dwTotalPlayed
+= count
;
341 lpWaveHdr
->dwFlags
&= ~WHDR_INQUEUE
;
342 lpWaveHdr
->dwFlags
|= WHDR_DONE
;
343 if ((DWORD
)lpWaveHdr
->lpData
!=lpWaveHdr
->reserved
) {
344 /* FIXME: what if it expects it's OWN lpwavehdr back? */
345 xwavehdr
= SEGPTR_NEW(WAVEHDR
);
346 memcpy(xwavehdr
,lpWaveHdr
,sizeof(WAVEHDR
));
347 xwavehdr
->lpData
= (LPBYTE
)xwavehdr
->reserved
;
348 if (WAVE_NotifyClient(wDevID
, WOM_DONE
, (DWORD
)SEGPTR_GET(xwavehdr
), count
) != MMSYSERR_NOERROR
) {
349 WARN(wave
, "can't notify client !\n");
350 SEGPTR_FREE(xwavehdr
);
351 return MMSYSERR_INVALPARAM
;
353 SEGPTR_FREE(xwavehdr
);
355 if (WAVE_NotifyClient(wDevID
, WOM_DONE
, (DWORD
)lpWaveHdr
, count
) != MMSYSERR_NOERROR
) {
356 WARN(wave
, "can't notify client !\n");
357 return MMSYSERR_INVALPARAM
;
360 return MMSYSERR_NOERROR
;
363 /**************************************************************************
364 * wodPrepare [internal]
366 static DWORD
wodPrepare(WORD wDevID
, LPWAVEHDR lpWaveHdr
, DWORD dwSize
)
368 TRACE(wave
, "(%u, %p, %08lX);\n", wDevID
, lpWaveHdr
, dwSize
);
369 if (WOutDev
[wDevID
].unixdev
== 0) {
370 WARN(wave
, "can't prepare !\n");
371 return MMSYSERR_NOTENABLED
;
373 /* don't append to queue, wodWrite does that */
374 WOutDev
[wDevID
].dwTotalPlayed
= 0;
375 if (lpWaveHdr
->dwFlags
& WHDR_INQUEUE
)
376 return WAVERR_STILLPLAYING
;
377 lpWaveHdr
->dwFlags
|= WHDR_PREPARED
;
378 lpWaveHdr
->dwFlags
&= ~WHDR_DONE
;
379 return MMSYSERR_NOERROR
;
382 /**************************************************************************
383 * wodUnprepare [internal]
385 static DWORD
wodUnprepare(WORD wDevID
, LPWAVEHDR lpWaveHdr
, DWORD dwSize
)
387 TRACE(wave
, "(%u, %p, %08lX);\n", wDevID
, lpWaveHdr
, dwSize
);
388 if (WOutDev
[wDevID
].unixdev
== 0) {
389 WARN(wave
, "can't unprepare !\n");
390 return MMSYSERR_NOTENABLED
;
392 if (lpWaveHdr
->dwFlags
& WHDR_INQUEUE
)
393 return WAVERR_STILLPLAYING
;
395 lpWaveHdr
->dwFlags
&= ~WHDR_PREPARED
;
396 lpWaveHdr
->dwFlags
|= WHDR_DONE
;
397 TRACE(wave
, "all headers unprepared !\n");
398 return MMSYSERR_NOERROR
;
401 /**************************************************************************
402 * wodRestart [internal]
404 static DWORD
wodRestart(WORD wDevID
)
406 TRACE(wave
,"(%u);\n", wDevID
);
407 if (WOutDev
[wDevID
].unixdev
== 0) {
408 WARN(wave
, "can't restart !\n");
409 return MMSYSERR_NOTENABLED
;
411 /* FIXME: is NotifyClient with WOM_DONE right ? (Comet Busters 1.3.3 needs this notification) */
412 /* FIXME: Myst crashes with this ... hmm -MM
413 if (WAVE_NotifyClient(wDevID, WOM_DONE, 0L, 0L) != MMSYSERR_NOERROR) {
414 WARN(wave, "can't notify client !\n");
415 return MMSYSERR_INVALPARAM;
419 return MMSYSERR_NOERROR
;
422 /**************************************************************************
423 * wodReset [internal]
425 static DWORD
wodReset(WORD wDevID
)
427 TRACE(wave
,"(%u);\n", wDevID
);
428 if (WOutDev
[wDevID
].unixdev
== 0) {
429 WARN(wave
, "can't reset !\n");
430 return MMSYSERR_NOTENABLED
;
432 return MMSYSERR_NOERROR
;
436 /**************************************************************************
437 * wodGetPosition [internal]
439 static DWORD
wodGetPosition(WORD wDevID
, LPMMTIME16 lpTime
, DWORD uSize
)
442 TRACE(wave
,"(%u, %p, %lu);\n", wDevID
, lpTime
, uSize
);
443 if (WOutDev
[wDevID
].unixdev
== 0) {
444 WARN(wave
, "can't get pos !\n");
445 return MMSYSERR_NOTENABLED
;
447 if (lpTime
== NULL
) return MMSYSERR_INVALPARAM
;
448 TRACE(wave
,"wType=%04X !\n", lpTime
->wType
);
449 TRACE(wave
,"wBitsPerSample=%u\n", WOutDev
[wDevID
].Format
.wBitsPerSample
);
450 TRACE(wave
,"nSamplesPerSec=%lu\n", WOutDev
[wDevID
].Format
.wf
.nSamplesPerSec
);
451 TRACE(wave
,"nChannels=%u\n", WOutDev
[wDevID
].Format
.wf
.nChannels
);
452 TRACE(wave
,"nAvgBytesPerSec=%lu\n", WOutDev
[wDevID
].Format
.wf
.nAvgBytesPerSec
);
453 switch(lpTime
->wType
) {
455 lpTime
->u
.cb
= WOutDev
[wDevID
].dwTotalPlayed
;
456 TRACE(wave
,"TIME_BYTES=%lu\n", lpTime
->u
.cb
);
459 TRACE(wave
,"dwTotalPlayed=%lu\n", WOutDev
[wDevID
].dwTotalPlayed
);
460 TRACE(wave
,"wBitsPerSample=%u\n", WOutDev
[wDevID
].Format
.wBitsPerSample
);
461 lpTime
->u
.sample
= WOutDev
[wDevID
].dwTotalPlayed
* 8 /
462 WOutDev
[wDevID
].Format
.wBitsPerSample
;
463 TRACE(wave
,"TIME_SAMPLES=%lu\n", lpTime
->u
.sample
);
466 time
= WOutDev
[wDevID
].dwTotalPlayed
/
467 (WOutDev
[wDevID
].Format
.wf
.nAvgBytesPerSec
/ 1000);
468 lpTime
->u
.smpte
.hour
= time
/ 108000;
469 time
-= lpTime
->u
.smpte
.hour
* 108000;
470 lpTime
->u
.smpte
.min
= time
/ 1800;
471 time
-= lpTime
->u
.smpte
.min
* 1800;
472 lpTime
->u
.smpte
.sec
= time
/ 30;
473 time
-= lpTime
->u
.smpte
.sec
* 30;
474 lpTime
->u
.smpte
.frame
= time
;
475 lpTime
->u
.smpte
.fps
= 30;
476 TRACE(wave
, "wodGetPosition , TIME_SMPTE=%02u:%02u:%02u:%02u\n",
477 lpTime
->u
.smpte
.hour
, lpTime
->u
.smpte
.min
,
478 lpTime
->u
.smpte
.sec
, lpTime
->u
.smpte
.frame
);
481 FIXME(wave
, "wodGetPosition() format %d not supported ! use TIME_MS !\n",lpTime
->wType
);
482 lpTime
->wType
= TIME_MS
;
484 lpTime
->u
.ms
= WOutDev
[wDevID
].dwTotalPlayed
/
485 (WOutDev
[wDevID
].Format
.wf
.nAvgBytesPerSec
/ 1000);
486 TRACE(wave
,"wodGetPosition , TIME_MS=%lu\n", lpTime
->u
.ms
);
489 return MMSYSERR_NOERROR
;
492 /**************************************************************************
493 * wodGetVolume [internal]
495 static DWORD
wodGetVolume(WORD wDevID
, LPDWORD lpdwVol
)
498 int volume
, left
, right
;
499 TRACE(wave
,"(%u, %p);\n", wDevID
, lpdwVol
);
500 if (lpdwVol
== NULL
) return MMSYSERR_NOTENABLED
;
501 if ((mixer
= open(MIXER_DEV
, O_RDONLY
)) < 0) {
502 WARN(wave
, "mixer device not available !\n");
503 return MMSYSERR_NOTENABLED
;
505 if (ioctl(mixer
, SOUND_MIXER_READ_PCM
, &volume
) == -1) {
506 WARN(wave
, "unable read mixer !\n");
507 return MMSYSERR_NOTENABLED
;
510 left
= volume
& 0x7F;
511 right
= (volume
>> 8) & 0x7F;
512 TRACE(wave
,"left=%d right=%d !\n", left
, right
);
513 *lpdwVol
= MAKELONG(left
<< 9, right
<< 9);
514 return MMSYSERR_NOERROR
;
518 /**************************************************************************
519 * wodSetVolume [internal]
521 static DWORD
wodSetVolume(WORD wDevID
, DWORD dwParam
)
525 TRACE(wave
,"(%u, %08lX);\n", wDevID
, dwParam
);
526 volume
= (LOWORD(dwParam
) >> 9 & 0x7F) +
527 ((HIWORD(dwParam
) >> 9 & 0x7F) << 8);
528 if ((mixer
= open(MIXER_DEV
, O_WRONLY
)) < 0) {
529 WARN(wave
, "mixer device not available !\n");
530 return MMSYSERR_NOTENABLED
;
532 if (ioctl(mixer
, SOUND_MIXER_WRITE_PCM
, &volume
) == -1) {
533 WARN(wave
, "unable set mixer !\n");
534 return MMSYSERR_NOTENABLED
;
537 return MMSYSERR_NOERROR
;
540 /**************************************************************************
541 * wodMessage [sample driver]
543 DWORD WINAPI
wodMessage(WORD wDevID
, WORD wMsg
, DWORD dwUser
,
544 DWORD dwParam1
, DWORD dwParam2
)
547 TRACE(wave
,"wodMessage(%u, %04X, %08lX, %08lX, %08lX);\n",
548 wDevID
, wMsg
, dwUser
, dwParam1
, dwParam2
);
551 return wodOpen(wDevID
, (LPWAVEOPENDESC
)dwParam1
, dwParam2
);
553 return wodClose(wDevID
);
555 return wodWrite(wDevID
, (LPWAVEHDR
)dwParam1
, dwParam2
);
557 return MMSYSERR_NOTSUPPORTED
;
559 return MMSYSERR_NOTSUPPORTED
;
561 return wodGetPosition(wDevID
, (LPMMTIME16
)dwParam1
, dwParam2
);
563 return MMSYSERR_NOTSUPPORTED
;
565 return wodPrepare(wDevID
, (LPWAVEHDR
)dwParam1
, dwParam2
);
567 return wodUnprepare(wDevID
, (LPWAVEHDR
)dwParam1
, dwParam2
);
568 case WODM_GETDEVCAPS
:
569 return wodGetDevCaps(wDevID
,(LPWAVEOUTCAPS16
)dwParam1
,dwParam2
);
570 case WODM_GETNUMDEVS
:
571 /* FIXME: For now, only one sound device (SOUND_DEV) is allowed */
572 audio
= open (SOUND_DEV
, O_WRONLY
, 0);
583 return MMSYSERR_NOTSUPPORTED
;
585 return MMSYSERR_NOTSUPPORTED
;
586 case WODM_GETPLAYBACKRATE
:
587 return MMSYSERR_NOTSUPPORTED
;
588 case WODM_SETPLAYBACKRATE
:
589 return MMSYSERR_NOTSUPPORTED
;
591 return wodGetVolume(wDevID
, (LPDWORD
)dwParam1
);
593 return wodSetVolume(wDevID
, dwParam1
);
595 return wodRestart(wDevID
);
597 return wodReset(wDevID
);
599 WARN(wave
,"unknown message !\n");
601 return MMSYSERR_NOTSUPPORTED
;
605 /*-----------------------------------------------------------------------*/
607 /**************************************************************************
608 * widGetDevCaps [internal]
610 static DWORD
widGetDevCaps(WORD wDevID
, LPWAVEINCAPS16 lpCaps
, DWORD dwSize
)
612 int audio
,smplrate
,samplesize
=16,dsp_stereo
=1,bytespersmpl
;
614 TRACE(wave
, "(%u, %p, %lu);\n", wDevID
, lpCaps
, dwSize
);
615 if (lpCaps
== NULL
) return MMSYSERR_NOTENABLED
;
616 if (access(SOUND_DEV
,0) != 0) return MMSYSERR_NOTENABLED
;
617 audio
= open (SOUND_DEV
, O_RDONLY
, 0);
618 if (audio
== -1) return MMSYSERR_ALLOCATED
;
620 lpCaps
->wMid
= 0x0002;
621 lpCaps
->wPid
= 0x0004;
622 strcpy(lpCaps
->szPname
, "SB16 Wave In");
624 lpCaps
->wMid
= 0x00FF; /* Manufac ID */
625 lpCaps
->wPid
= 0x0001; /* Product ID */
626 strcpy(lpCaps
->szPname
, "OpenSoundSystem WAVIN Driver");
628 lpCaps
->dwFormats
= 0x00000000;
629 lpCaps
->wChannels
= (IOCTL(audio
, SNDCTL_DSP_STEREO
, dsp_stereo
) != 0) ? 1 : 2;
630 bytespersmpl
= (IOCTL(audio
, SNDCTL_DSP_SAMPLESIZE
, samplesize
) != 0) ? 1 : 2;
632 if (IOCTL(audio
, SNDCTL_DSP_SPEED
, smplrate
) == 0) {
633 lpCaps
->dwFormats
|= WAVE_FORMAT_4M08
;
634 if (lpCaps
->wChannels
> 1)
635 lpCaps
->dwFormats
|= WAVE_FORMAT_4S08
;
636 if (bytespersmpl
> 1) {
637 lpCaps
->dwFormats
|= WAVE_FORMAT_4M16
;
638 if (lpCaps
->wChannels
> 1)
639 lpCaps
->dwFormats
|= WAVE_FORMAT_4S16
;
643 if (IOCTL(audio
, SNDCTL_DSP_SPEED
, smplrate
) == 0) {
644 lpCaps
->dwFormats
|= WAVE_FORMAT_2M08
;
645 if (lpCaps
->wChannels
> 1)
646 lpCaps
->dwFormats
|= WAVE_FORMAT_2S08
;
647 if (bytespersmpl
> 1) {
648 lpCaps
->dwFormats
|= WAVE_FORMAT_2M16
;
649 if (lpCaps
->wChannels
> 1)
650 lpCaps
->dwFormats
|= WAVE_FORMAT_2S16
;
654 if (IOCTL(audio
, SNDCTL_DSP_SPEED
, smplrate
) == 0) {
655 lpCaps
->dwFormats
|= WAVE_FORMAT_1M08
;
656 if (lpCaps
->wChannels
> 1)
657 lpCaps
->dwFormats
|= WAVE_FORMAT_1S08
;
658 if (bytespersmpl
> 1) {
659 lpCaps
->dwFormats
|= WAVE_FORMAT_1M16
;
660 if (lpCaps
->wChannels
> 1)
661 lpCaps
->dwFormats
|= WAVE_FORMAT_1S16
;
665 TRACE(wave
, "dwFormats = %08lX\n", lpCaps
->dwFormats
);
666 return MMSYSERR_NOERROR
;
670 /**************************************************************************
673 static DWORD
widOpen(WORD wDevID
, LPWAVEOPENDESC lpDesc
, DWORD dwFlags
)
675 int audio
,abuf_size
,smplrate
,samplesize
,dsp_stereo
;
676 LPWAVEFORMAT lpFormat
;
678 TRACE(wave
, "(%u, %p, %08lX);\n", wDevID
, lpDesc
, dwFlags
);
679 if (lpDesc
== NULL
) {
680 WARN(wave
, "Invalid Parameter !\n");
681 return MMSYSERR_INVALPARAM
;
683 if (wDevID
>= MAX_WAVEINDRV
) {
684 TRACE(wave
,"MAX_WAVINDRV reached !\n");
685 return MMSYSERR_ALLOCATED
;
687 WInDev
[wDevID
].unixdev
= 0;
688 if (access(SOUND_DEV
,0) != 0) return MMSYSERR_NOTENABLED
;
689 audio
= open (SOUND_DEV
, O_RDONLY
, 0);
691 WARN(wave
,"can't open !\n");
692 return MMSYSERR_ALLOCATED
;
694 IOCTL(audio
, SNDCTL_DSP_GETBLKSIZE
, abuf_size
);
695 if (abuf_size
< 1024 || abuf_size
> 65536) {
697 WARN(wave
, "IOCTL can't 'SNDCTL_DSP_GETBLKSIZE' !\n");
699 WARN(wave
, "SNDCTL_DSP_GETBLKSIZE Invalid bufsize !\n");
700 return MMSYSERR_NOTENABLED
;
702 WInDev
[wDevID
].wFlags
= HIWORD(dwFlags
& CALLBACK_TYPEMASK
);
703 switch(WInDev
[wDevID
].wFlags
) {
705 TRACE(wave
,"CALLBACK_NULL!\n");
708 TRACE(wave
,"CALLBACK_WINDOW!\n");
711 TRACE(wave
,"CALLBACK_TASK!\n");
714 TRACE(wave
,"CALLBACK_FUNCTION!\n");
717 if (WInDev
[wDevID
].lpQueueHdr
) {
718 HeapFree(GetProcessHeap(),0,WInDev
[wDevID
].lpQueueHdr
);
719 WInDev
[wDevID
].lpQueueHdr
= NULL
;
721 WInDev
[wDevID
].unixdev
= audio
;
722 WInDev
[wDevID
].bufsize
= abuf_size
;
723 WInDev
[wDevID
].dwTotalRecorded
= 0;
724 memcpy(&WInDev
[wDevID
].waveDesc
, lpDesc
, sizeof(WAVEOPENDESC
));
725 lpFormat
= (LPWAVEFORMAT
) lpDesc
->lpFormat
;
726 if (lpFormat
->wFormatTag
!= WAVE_FORMAT_PCM
) {
727 WARN(wave
, "Bad format %04X !\n",
728 lpFormat
->wFormatTag
);
729 return WAVERR_BADFORMAT
;
731 memcpy(&WInDev
[wDevID
].Format
, lpFormat
, sizeof(PCMWAVEFORMAT
));
732 WInDev
[wDevID
].Format
.wBitsPerSample
= 8; /* <-------------- */
733 if (WInDev
[wDevID
].Format
.wf
.nChannels
== 0) return WAVERR_BADFORMAT
;
734 if (WInDev
[wDevID
].Format
.wf
.nSamplesPerSec
== 0) return WAVERR_BADFORMAT
;
735 if (WInDev
[wDevID
].Format
.wBitsPerSample
== 0) {
736 WInDev
[wDevID
].Format
.wBitsPerSample
= 8 *
737 (WInDev
[wDevID
].Format
.wf
.nAvgBytesPerSec
/
738 WInDev
[wDevID
].Format
.wf
.nSamplesPerSec
) /
739 WInDev
[wDevID
].Format
.wf
.nChannels
;
741 samplesize
= WInDev
[wDevID
].Format
.wBitsPerSample
;
742 smplrate
= WInDev
[wDevID
].Format
.wf
.nSamplesPerSec
;
743 dsp_stereo
= (WInDev
[wDevID
].Format
.wf
.nChannels
> 1) ? TRUE
: FALSE
;
744 IOCTL(audio
, SNDCTL_DSP_SPEED
, smplrate
);
745 IOCTL(audio
, SNDCTL_DSP_SAMPLESIZE
, samplesize
);
746 IOCTL(audio
, SNDCTL_DSP_STEREO
, dsp_stereo
);
747 TRACE(wave
,"wBitsPerSample=%u !\n", WInDev
[wDevID
].Format
.wBitsPerSample
);
748 TRACE(wave
,"nSamplesPerSec=%lu !\n", WInDev
[wDevID
].Format
.wf
.nSamplesPerSec
);
749 TRACE(wave
,"nChannels=%u !\n", WInDev
[wDevID
].Format
.wf
.nChannels
);
750 TRACE(wave
,"nAvgBytesPerSec=%lu\n", WInDev
[wDevID
].Format
.wf
.nAvgBytesPerSec
);
751 if (WAVE_NotifyClient(wDevID
, WIM_OPEN
, 0L, 0L) != MMSYSERR_NOERROR
) {
752 WARN(wave
,"can't notify client !\n");
753 return MMSYSERR_INVALPARAM
;
755 return MMSYSERR_NOERROR
;
758 /**************************************************************************
759 * widClose [internal]
761 static DWORD
widClose(WORD wDevID
)
763 TRACE(wave
,"(%u);\n", wDevID
);
764 if (wDevID
> MAX_WAVEINDRV
) return MMSYSERR_INVALPARAM
;
765 if (WInDev
[wDevID
].unixdev
== 0) {
766 WARN(wave
,"can't close !\n");
767 return MMSYSERR_NOTENABLED
;
769 if (WInDev
[wDevID
].lpQueueHdr
!= NULL
) {
770 WARN(wave
, "still buffers open !\n");
771 return WAVERR_STILLPLAYING
;
773 close(WInDev
[wDevID
].unixdev
);
774 WInDev
[wDevID
].unixdev
= 0;
775 WInDev
[wDevID
].bufsize
= 0;
776 if (WAVE_NotifyClient(wDevID
, WIM_CLOSE
, 0L, 0L) != MMSYSERR_NOERROR
) {
777 WARN(wave
,"can't notify client !\n");
778 return MMSYSERR_INVALPARAM
;
780 return MMSYSERR_NOERROR
;
783 /**************************************************************************
784 * widAddBuffer [internal]
786 static DWORD
widAddBuffer(WORD wDevID
, LPWAVEHDR lpWaveHdr
, DWORD dwSize
)
791 TRACE(wave
, "(%u, %p, %08lX);\n", wDevID
, lpWaveHdr
, dwSize
);
792 if (WInDev
[wDevID
].unixdev
== 0) {
793 WARN(wave
,"can't do it !\n");
794 return MMSYSERR_NOTENABLED
;
796 if (!(lpWaveHdr
->dwFlags
& WHDR_PREPARED
)) {
797 TRACE(wave
, "never been prepared !\n");
798 return WAVERR_UNPREPARED
;
800 if (lpWaveHdr
->dwFlags
& WHDR_INQUEUE
) {
801 TRACE(wave
, "header already in use !\n");
802 return WAVERR_STILLPLAYING
;
804 lpWaveHdr
->dwFlags
|= WHDR_PREPARED
;
805 lpWaveHdr
->dwFlags
|= WHDR_INQUEUE
;
806 lpWaveHdr
->dwFlags
&= ~WHDR_DONE
;
807 lpWaveHdr
->dwBytesRecorded
= 0;
808 if (WInDev
[wDevID
].lpQueueHdr
== NULL
) {
809 WInDev
[wDevID
].lpQueueHdr
= lpWaveHdr
;
811 lpWIHdr
= WInDev
[wDevID
].lpQueueHdr
;
812 while (lpWIHdr
->lpNext
!= NULL
) {
813 lpWIHdr
= lpWIHdr
->lpNext
;
816 lpWIHdr
->lpNext
= lpWaveHdr
;
817 lpWaveHdr
->lpNext
= NULL
;
820 TRACE(wave
, "buffer added ! (now %u in queue)\n", count
);
821 return MMSYSERR_NOERROR
;
824 /**************************************************************************
825 * widPrepare [internal]
827 static DWORD
widPrepare(WORD wDevID
, LPWAVEHDR lpWaveHdr
, DWORD dwSize
)
829 TRACE(wave
, "(%u, %p, %08lX);\n", wDevID
, lpWaveHdr
, dwSize
);
830 if (WInDev
[wDevID
].unixdev
== 0) {
831 WARN(wave
,"can't prepare !\n");
832 return MMSYSERR_NOTENABLED
;
834 if (lpWaveHdr
->dwFlags
& WHDR_INQUEUE
)
835 return WAVERR_STILLPLAYING
;
836 lpWaveHdr
->dwFlags
|= WHDR_PREPARED
;
837 lpWaveHdr
->dwFlags
&= ~WHDR_INQUEUE
;
838 lpWaveHdr
->dwFlags
&= ~WHDR_DONE
;
839 lpWaveHdr
->dwBytesRecorded
= 0;
840 TRACE(wave
,"header prepared !\n");
841 return MMSYSERR_NOERROR
;
844 /**************************************************************************
845 * widUnprepare [internal]
847 static DWORD
widUnprepare(WORD wDevID
, LPWAVEHDR lpWaveHdr
, DWORD dwSize
)
849 TRACE(wave
, "(%u, %p, %08lX);\n", wDevID
, lpWaveHdr
, dwSize
);
850 if (WInDev
[wDevID
].unixdev
== 0) {
851 WARN(wave
,"can't unprepare !\n");
852 return MMSYSERR_NOTENABLED
;
854 lpWaveHdr
->dwFlags
&= ~WHDR_PREPARED
;
855 lpWaveHdr
->dwFlags
&= ~WHDR_INQUEUE
;
856 lpWaveHdr
->dwFlags
|= WHDR_DONE
;
858 TRACE(wave
, "all headers unprepared !\n");
859 return MMSYSERR_NOERROR
;
862 /**************************************************************************
863 * widStart [internal]
865 static DWORD
widStart(WORD wDevID
)
870 LPWAVEHDR
*lpWaveHdr
;
872 TRACE(wave
,"(%u);\n", wDevID
);
873 if (WInDev
[wDevID
].unixdev
== 0) {
874 WARN(wave
, "can't start recording !\n");
875 return MMSYSERR_NOTENABLED
;
878 lpWaveHdr
= &(WInDev
[wDevID
].lpQueueHdr
);
879 TRACE(wave
,"lpWaveHdr = %08lx\n",(DWORD
)lpWaveHdr
);
880 if (!*lpWaveHdr
|| !(*lpWaveHdr
)->lpData
) {
881 TRACE(wave
,"never been prepared !\n");
882 return WAVERR_UNPREPARED
;
885 while(*lpWaveHdr
!= NULL
) {
886 lpWIHdr
= *lpWaveHdr
;
887 TRACE(wave
, "recording buf#%u=%p size=%lu \n",
888 count
, lpWIHdr
->lpData
, lpWIHdr
->dwBufferLength
);
890 bytesRead
= read (WInDev
[wDevID
].unixdev
,
892 lpWIHdr
->dwBufferLength
);
894 perror("read from audio device");
895 TRACE(wave
,"bytesread=%d (%ld)\n", bytesRead
, lpWIHdr
->dwBufferLength
);
896 lpWIHdr
->dwBytesRecorded
= bytesRead
;
897 WInDev
[wDevID
].dwTotalRecorded
+= lpWIHdr
->dwBytesRecorded
;
898 lpWIHdr
->dwFlags
&= ~WHDR_INQUEUE
;
899 lpWIHdr
->dwFlags
|= WHDR_DONE
;
901 /* FIXME: should pass segmented pointer here, do we need that?*/
902 if (WAVE_NotifyClient(wDevID
, WIM_DATA
, (DWORD
)lpWaveHdr
, lpWIHdr
->dwBytesRecorded
) != MMSYSERR_NOERROR
) {
903 WARN(wave
, "can't notify client !\n");
904 return MMSYSERR_INVALPARAM
;
906 /* removes the current block from the queue */
907 *lpWaveHdr
= lpWIHdr
->lpNext
;
910 TRACE(wave
,"end of recording !\n");
912 return MMSYSERR_NOERROR
;
915 /**************************************************************************
918 static DWORD
widStop(WORD wDevID
)
920 TRACE(wave
,"(%u);\n", wDevID
);
921 if (WInDev
[wDevID
].unixdev
== 0) {
922 WARN(wave
,"can't stop !\n");
923 return MMSYSERR_NOTENABLED
;
925 return MMSYSERR_NOERROR
;
928 /**************************************************************************
929 * widReset [internal]
931 static DWORD
widReset(WORD wDevID
)
933 TRACE(wave
,"(%u);\n", wDevID
);
934 if (WInDev
[wDevID
].unixdev
== 0) {
935 WARN(wave
,"can't reset !\n");
936 return MMSYSERR_NOTENABLED
;
938 return MMSYSERR_NOERROR
;
941 /**************************************************************************
942 * widGetPosition [internal]
944 static DWORD
widGetPosition(WORD wDevID
, LPMMTIME16 lpTime
, DWORD uSize
)
948 TRACE(wave
, "(%u, %p, %lu);\n", wDevID
, lpTime
, uSize
);
949 if (WInDev
[wDevID
].unixdev
== 0) {
950 WARN(wave
,"can't get pos !\n");
951 return MMSYSERR_NOTENABLED
;
953 if (lpTime
== NULL
) return MMSYSERR_INVALPARAM
;
954 TRACE(wave
,"wType=%04X !\n", lpTime
->wType
);
955 TRACE(wave
,"wBitsPerSample=%u\n", WInDev
[wDevID
].Format
.wBitsPerSample
);
956 TRACE(wave
,"nSamplesPerSec=%lu\n", WInDev
[wDevID
].Format
.wf
.nSamplesPerSec
);
957 TRACE(wave
,"nChannels=%u\n", WInDev
[wDevID
].Format
.wf
.nChannels
);
958 TRACE(wave
,"nAvgBytesPerSec=%lu\n", WInDev
[wDevID
].Format
.wf
.nAvgBytesPerSec
);
960 switch(lpTime
->wType
) {
962 lpTime
->u
.cb
= WInDev
[wDevID
].dwTotalRecorded
;
963 TRACE(wave
,"TIME_BYTES=%lu\n", lpTime
->u
.cb
);
966 lpTime
->u
.sample
= WInDev
[wDevID
].dwTotalRecorded
* 8 /
967 WInDev
[wDevID
].Format
.wBitsPerSample
;
968 TRACE(wave
, "TIME_SAMPLES=%lu\n", lpTime
->u
.sample
);
971 time
= WInDev
[wDevID
].dwTotalRecorded
/
972 (WInDev
[wDevID
].Format
.wf
.nAvgBytesPerSec
/ 1000);
973 lpTime
->u
.smpte
.hour
= time
/ 108000;
974 time
-= lpTime
->u
.smpte
.hour
* 108000;
975 lpTime
->u
.smpte
.min
= time
/ 1800;
976 time
-= lpTime
->u
.smpte
.min
* 1800;
977 lpTime
->u
.smpte
.sec
= time
/ 30;
978 time
-= lpTime
->u
.smpte
.sec
* 30;
979 lpTime
->u
.smpte
.frame
= time
;
980 lpTime
->u
.smpte
.fps
= 30;
981 TRACE(wave
,"TIME_SMPTE=%02u:%02u:%02u:%02u\n",
982 lpTime
->u
.smpte
.hour
, lpTime
->u
.smpte
.min
,
983 lpTime
->u
.smpte
.sec
, lpTime
->u
.smpte
.frame
);
986 lpTime
->u
.ms
= WInDev
[wDevID
].dwTotalRecorded
/
987 (WInDev
[wDevID
].Format
.wf
.nAvgBytesPerSec
/ 1000);
988 TRACE(wave
, "TIME_MS=%lu\n", lpTime
->u
.ms
);
991 FIXME(wave
, "format not supported ! use TIME_MS !\n");
992 lpTime
->wType
= TIME_MS
;
994 return MMSYSERR_NOERROR
;
997 /**************************************************************************
998 * widMessage [sample driver]
1000 DWORD WINAPI
widMessage(WORD wDevID
, WORD wMsg
, DWORD dwUser
,
1001 DWORD dwParam1
, DWORD dwParam2
)
1004 TRACE(wave
,"widMessage(%u, %04X, %08lX, %08lX, %08lX);\n",
1005 wDevID
, wMsg
, dwUser
, dwParam1
, dwParam2
);
1008 return widOpen(wDevID
, (LPWAVEOPENDESC
)dwParam1
, dwParam2
);
1010 return widClose(wDevID
);
1011 case WIDM_ADDBUFFER
:
1012 return widAddBuffer(wDevID
, (LPWAVEHDR
)dwParam1
, dwParam2
);
1014 return widPrepare(wDevID
, (LPWAVEHDR
)dwParam1
, dwParam2
);
1015 case WIDM_UNPREPARE
:
1016 return widUnprepare(wDevID
, (LPWAVEHDR
)dwParam1
, dwParam2
);
1017 case WIDM_GETDEVCAPS
:
1018 return widGetDevCaps(wDevID
, (LPWAVEINCAPS16
)dwParam1
,dwParam2
);
1019 case WIDM_GETNUMDEVS
:
1020 /* FIXME: For now, only one sound device (SOUND_DEV) is allowed */
1021 audio
= open (SOUND_DEV
, O_RDONLY
, 0);
1032 return widGetPosition(wDevID
, (LPMMTIME16
)dwParam1
, dwParam2
);
1034 return widReset(wDevID
);
1036 return widStart(wDevID
);
1038 return widStop(wDevID
);
1040 return widStop(wDevID
);
1042 WARN(wave
,"unknown message !\n");
1044 return MMSYSERR_NOTSUPPORTED
;
1048 /**************************************************************************
1049 * WAVE_DriverProc16 [sample driver]
1051 LONG
WAVE_DriverProc16(DWORD dwDevID
, HDRVR16 hDriv
, WORD wMsg
,
1052 DWORD dwParam1
, DWORD dwParam2
)
1054 TRACE(wave
,"(%08lX, %04X, %04X, %08lX, %08lX)\n", dwDevID
, hDriv
, wMsg
, dwParam1
, dwParam2
);
1057 case DRV_LOAD
: return 1;
1058 case DRV_FREE
: return 1;
1059 case DRV_OPEN
: return 1;
1060 case DRV_CLOSE
: return 1;
1061 case DRV_ENABLE
: return 1;
1062 case DRV_DISABLE
: return 1;
1063 case DRV_QUERYCONFIGURE
: return 1;
1064 case DRV_CONFIGURE
: MessageBox16(0, "Sample MultiMedia Linux Driver !", "MMLinux Driver", MB_OK
); return 1;
1065 case DRV_INSTALL
: return DRVCNF_RESTART
;
1066 case DRV_REMOVE
: return DRVCNF_RESTART
;
1068 FIXME(wave
, "is probably wrong msg=0x%04x\n", wMsg
);
1069 return DefDriverProc16(dwDevID
, hDriv
, wMsg
, dwParam1
, dwParam2
);
1071 return MMSYSERR_NOTENABLED
;
1074 /**************************************************************************
1075 * WAVE_DriverProc32 [sample driver]
1077 LONG
WAVE_DriverProc(DWORD dwDevID
, HDRVR16 hDriv
, DWORD wMsg
,
1078 DWORD dwParam1
, DWORD dwParam2
)
1080 TRACE(wave
,"(%08lX, %04X, %08lX, %08lX, %08lX)\n", dwDevID
, hDriv
, wMsg
, dwParam1
, dwParam2
);
1082 case DRV_LOAD
: return 1;
1083 case DRV_FREE
: return 1;
1084 case DRV_OPEN
: return 1;
1085 case DRV_CLOSE
: return 1;
1086 case DRV_ENABLE
: return 1;
1087 case DRV_DISABLE
: return 1;
1088 case DRV_QUERYCONFIGURE
: return 1;
1089 case DRV_CONFIGURE
: MessageBox16(0, "Sample MultiMedia Linux Driver !", "MMLinux Driver", MB_OK
); return 1;
1090 case DRV_INSTALL
: return DRVCNF_RESTART
;
1091 case DRV_REMOVE
: return DRVCNF_RESTART
;
1093 FIXME(wave
, "is probably wrong msg=0x%04lx\n", wMsg
);
1094 return DefDriverProc(dwDevID
, hDriv
, wMsg
, dwParam1
, dwParam2
);
1096 return MMSYSERR_NOTENABLED
;
1099 #else /* !HAVE_OSS */
1101 /**************************************************************************
1102 * wodMessage [sample driver]
1104 DWORD WINAPI
wodMessage(WORD wDevID
, WORD wMsg
, DWORD dwUser
,
1105 DWORD dwParam1
, DWORD dwParam2
)
1107 FIXME(wave
,"(%u, %04X, %08lX, %08lX, %08lX):stub\n", wDevID
, wMsg
, dwUser
, dwParam1
, dwParam2
);
1108 return MMSYSERR_NOTENABLED
;
1111 /**************************************************************************
1112 * widMessage [sample driver]
1114 DWORD WINAPI
widMessage(WORD wDevID
, WORD wMsg
, DWORD dwUser
,
1115 DWORD dwParam1
, DWORD dwParam2
)
1117 FIXME(wave
,"(%u, %04X, %08lX, %08lX, %08lX):stub\n", wDevID
, wMsg
, dwUser
, dwParam1
, dwParam2
);
1118 return MMSYSERR_NOTENABLED
;
1121 /**************************************************************************
1122 * WAVE_DriverProc16 [sample driver]
1124 LONG
WAVE_DriverProc16(DWORD dwDevID
, HDRVR16 hDriv
, WORD wMsg
,
1125 DWORD dwParam1
, DWORD dwParam2
)
1127 return MMSYSERR_NOTENABLED
;
1130 /**************************************************************************
1131 * WAVE_DriverProc32 [sample driver]
1133 LONG
WAVE_DriverProc(DWORD dwDevID
, HDRVR16 hDriv
, DWORD wMsg
,
1134 DWORD dwParam1
, DWORD dwParam2
)
1136 return MMSYSERR_NOTENABLED
;
1138 #endif /* HAVE_OSS */