2 * Sample Wine Driver for Linux
4 * Copyright 1994 Martin Ayotte
8 * - record/play should and must be done asynchronous
9 * - segmented/linear pointer problems (lpData in waveheaders,W*_DONE cbs)
20 #include <sys/ioctl.h>
29 #include <linux/soundcard.h>
31 #include <machine/soundcard.h>
37 #if defined(linux) || defined(__FreeBSD__)
38 #define SOUND_DEV "/dev/dsp"
39 #define MIXER_DEV "/dev/mixer"
42 #define IOCTL(a,b,c) ((-1==ioctl(a,b,&c))&&(perror("ioctl:"#b":"#c),0))
44 #define IOCTL(a,b,c) (c = ioctl(a,b,c) )
47 #define MAX_WAVOUTDRV (1)
48 #define MAX_WAVINDRV (1)
49 #define MAX_MCIWAVDRV (1)
55 WAVEOPENDESC waveDesc
;
65 DWORD bufsize
; /* Linux '/dev/dsp' give us that size */
66 WAVEOPENDESC waveDesc
;
70 DWORD dwTotalRecorded
;
74 int nUseCount
; /* Incremented for each shared open */
75 BOOL16 fShareable
; /* TRUE if first open was shareable */
76 WORD wNotifyDeviceID
;/* MCI device ID with a pending notification */
77 HANDLE16 hCallback
; /* Callback handle for pending notification */
78 HMMIO16 hFile
; /* mmio file handle open as Element */
79 MCI_WAVE_OPEN_PARMS16 openParms
;
80 PCMWAVEFORMAT WaveFormat
;
82 BOOL16 fInput
; /* FALSE = Output, TRUE = Input */
85 static LINUX_WAVEOUT WOutDev
[MAX_WAVOUTDRV
];
86 static LINUX_WAVEIN WInDev
[MAX_WAVOUTDRV
];
87 static LINUX_MCIWAVE MCIWavDev
[MAX_MCIWAVDRV
];
90 /**************************************************************************
91 * WAVE_NotifyClient [internal]
93 static DWORD
WAVE_NotifyClient(UINT16 wDevID
, WORD wMsg
,
94 DWORD dwParam1
, DWORD dwParam2
)
96 dprintf_mciwave(stddeb
,"WAVE_NotifyClient // wDevID = %04X wMsg = %d dwParm1 = %04lX dwParam2 = %04lX\n",wDevID
, wMsg
, dwParam1
, dwParam2
);
102 if (wDevID
> MAX_WAVOUTDRV
) return MCIERR_INTERNAL
;
104 if (WOutDev
[wDevID
].wFlags
!= DCB_NULL
&& !DriverCallback(
105 WOutDev
[wDevID
].waveDesc
.dwCallBack
,
106 WOutDev
[wDevID
].wFlags
,
107 WOutDev
[wDevID
].waveDesc
.hWave
,
109 WOutDev
[wDevID
].waveDesc
.dwInstance
,
112 dprintf_mciwave(stddeb
,"WAVE_NotifyClient // can't notify client !\n");
113 return MMSYSERR_NOERROR
;
120 if (wDevID
> MAX_WAVINDRV
) return MCIERR_INTERNAL
;
122 if (WInDev
[wDevID
].wFlags
!= DCB_NULL
&& !DriverCallback(
123 WInDev
[wDevID
].waveDesc
.dwCallBack
, WInDev
[wDevID
].wFlags
,
124 WInDev
[wDevID
].waveDesc
.hWave
, wMsg
,
125 WInDev
[wDevID
].waveDesc
.dwInstance
, dwParam1
, dwParam2
)) {
126 dprintf_mciwave(stddeb
,"WAVE_NotifyClient // can't notify client !\n");
127 return MMSYSERR_NOERROR
;
135 /**************************************************************************
136 * WAVE_mciOpen [internal]
138 static DWORD
WAVE_mciOpen(UINT16 wDevID
, DWORD dwFlags
, LPMCI_WAVE_OPEN_PARMS16 lpParms
)
140 LPPCMWAVEFORMAT lpWaveFormat
;
141 WAVEOPENDESC waveDesc
;
142 LPSTR lpstrElementName
;
146 dprintf_mciwave(stddeb
,"WAVE_mciOpen(%04X, %08lX, %p)\n",
147 wDevID
, dwFlags
, lpParms
);
148 if (lpParms
== NULL
) return MCIERR_INTERNAL
;
150 if (MCIWavDev
[wDevID
].nUseCount
> 0) {
151 /* The driver already open on this channel */
152 /* If the driver was opened shareable before and this open specifies */
153 /* shareable then increment the use count */
154 if (MCIWavDev
[wDevID
].fShareable
&& (dwFlags
& MCI_OPEN_SHAREABLE
))
155 ++MCIWavDev
[wDevID
].nUseCount
;
157 return MCIERR_MUST_USE_SHAREABLE
;
159 MCIWavDev
[wDevID
].nUseCount
= 1;
160 MCIWavDev
[wDevID
].fShareable
= dwFlags
& MCI_OPEN_SHAREABLE
;
163 MCIWavDev
[wDevID
].fInput
= FALSE
;
165 dprintf_mciwave(stddeb
,"WAVE_mciOpen // wDevID=%04X\n", wDevID
);
166 dprintf_mciwave(stddeb
,"WAVE_mciOpen // before OPEN_ELEMENT\n");
167 if (dwFlags
& MCI_OPEN_ELEMENT
) {
168 lpstrElementName
= (LPSTR
)PTR_SEG_TO_LIN(lpParms
->lpstrElementName
);
169 dprintf_mciwave(stddeb
,"WAVE_mciOpen // MCI_OPEN_ELEMENT '%s' !\n",
171 if ( lpstrElementName
&& (strlen(lpstrElementName
) > 0)) {
172 strcpy(str
, lpstrElementName
);
174 MCIWavDev
[wDevID
].hFile
= mmioOpen16(str
, NULL
,
175 MMIO_ALLOCBUF
| MMIO_READWRITE
| MMIO_EXCLUSIVE
);
176 if (MCIWavDev
[wDevID
].hFile
== 0) {
177 dprintf_mciwave(stddeb
,"WAVE_mciOpen // can't find file='%s' !\n", str
);
178 return MCIERR_FILE_NOT_FOUND
;
182 MCIWavDev
[wDevID
].hFile
= 0;
184 dprintf_mciwave(stddeb
,"WAVE_mciOpen // hFile=%u\n", MCIWavDev
[wDevID
].hFile
);
185 memcpy(&MCIWavDev
[wDevID
].openParms
, lpParms
, sizeof(MCI_WAVE_OPEN_PARMS16
));
186 MCIWavDev
[wDevID
].wNotifyDeviceID
= lpParms
->wDeviceID
;
187 lpWaveFormat
= &MCIWavDev
[wDevID
].WaveFormat
;
191 lpWaveFormat->wf.wFormatTag = WAVE_FORMAT_PCM;
192 lpWaveFormat->wBitsPerSample = 8;
193 lpWaveFormat->wf.nChannels = 1;
194 lpWaveFormat->wf.nSamplesPerSec = 11025;
195 lpWaveFormat->wf.nAvgBytesPerSec = 11025;
196 lpWaveFormat->wf.nBlockAlign = 1;
198 if (MCIWavDev
[wDevID
].hFile
!= 0) {
201 if (mmioDescend(MCIWavDev
[wDevID
].hFile
, &ckMainRIFF
, NULL
, 0) != 0)
202 return MCIERR_INTERNAL
;
203 dprintf_mciwave(stddeb
,
204 "WAVE_mciOpen // ParentChunk ckid=%.4s fccType=%.4s cksize=%08lX \n",
205 (LPSTR
)&ckMainRIFF
.ckid
, (LPSTR
)&ckMainRIFF
.fccType
,
207 if ((ckMainRIFF
.ckid
!= FOURCC_RIFF
) ||
208 (ckMainRIFF
.fccType
!= mmioFOURCC('W', 'A', 'V', 'E')))
209 return MCIERR_INTERNAL
;
210 mmckInfo
.ckid
= mmioFOURCC('f', 'm', 't', ' ');
211 if (mmioDescend(MCIWavDev
[wDevID
].hFile
, &mmckInfo
, &ckMainRIFF
, MMIO_FINDCHUNK
) != 0)
212 return MCIERR_INTERNAL
;
213 dprintf_mciwave(stddeb
,
214 "WAVE_mciOpen // Chunk Found ckid=%.4s fccType=%.4s cksize=%08lX \n",
215 (LPSTR
)&mmckInfo
.ckid
, (LPSTR
)&mmckInfo
.fccType
,
217 if (mmioRead(MCIWavDev
[wDevID
].hFile
, (HPSTR
) lpWaveFormat
,
218 (long) sizeof(PCMWAVEFORMAT
)) != (long) sizeof(PCMWAVEFORMAT
))
219 return MCIERR_INTERNAL
;
220 mmckInfo
.ckid
= mmioFOURCC('d', 'a', 't', 'a');
221 if (mmioDescend(MCIWavDev
[wDevID
].hFile
, &mmckInfo
, &ckMainRIFF
, MMIO_FINDCHUNK
) != 0)
222 return MCIERR_INTERNAL
;
223 dprintf_mciwave(stddeb
,
224 "WAVE_mciOpen // Chunk Found ckid=%.4s fccType=%.4s cksize=%08lX \n",
225 (LPSTR
)&mmckInfo
.ckid
, (LPSTR
)&mmckInfo
.fccType
,
227 dprintf_mciwave(stddeb
,
228 "WAVE_mciOpen // nChannels=%d nSamplesPerSec=%ld\n",
229 lpWaveFormat
->wf
.nChannels
, lpWaveFormat
->wf
.nSamplesPerSec
);
230 lpWaveFormat
->wBitsPerSample
= 0;
232 lpWaveFormat
->wf
.nAvgBytesPerSec
=
233 lpWaveFormat
->wf
.nSamplesPerSec
* lpWaveFormat
->wf
.nBlockAlign
;
234 waveDesc
.lpFormat
= (LPWAVEFORMAT
)lpWaveFormat
;
237 By default the device will be opened for output, the MCI_CUE function is there to
238 change from output to input and back
241 dwRet
=wodMessage(wDevID
,WODM_OPEN
,0,(DWORD
)&waveDesc
,CALLBACK_NULL
);
245 /**************************************************************************
246 * WAVE_mciCue [internal]
249 static DWORD
WAVE_mciCue(UINT16 wDevID
, DWORD dwParam
, LPMCI_GENERIC_PARMS lpParms
)
254 This routine is far from complete. At the moment only a check is done on the
255 MCI_WAVE_INPUT flag. No explicit check on MCI_WAVE_OUTPUT is done since that
258 The flags MCI_NOTIFY (and the callback parameter in lpParms) and MCI_WAIT
263 WAVEOPENDESC waveDesc
;
265 dprintf_mciwave(stddeb
,"WAVE_mciCue(%u, %08lX, %p);\n", wDevID
, dwParam
, lpParms
);
267 /* always close elements ? */
269 if (MCIWavDev
[wDevID
].hFile
!= 0) {
270 mmioClose(MCIWavDev
[wDevID
].hFile
, 0);
271 MCIWavDev
[wDevID
].hFile
= 0;
274 dwRet
= MMSYSERR_NOERROR
; /* assume success */
275 if ((dwParam
& MCI_WAVE_INPUT
) && !MCIWavDev
[wDevID
].fInput
) {
276 /* FIXME this is just a hack WOutDev should be hidden here */
277 memcpy(&waveDesc
,&WOutDev
[wDevID
].waveDesc
,sizeof(WAVEOPENDESC
));
279 dwRet
= wodMessage(wDevID
, WODM_CLOSE
, 0, 0L, 0L);
280 if (dwRet
!= MMSYSERR_NOERROR
) return MCIERR_INTERNAL
;
281 dwRet
= widMessage(wDevID
, WIDM_OPEN
, 0, (DWORD
)&waveDesc
, CALLBACK_NULL
);
282 MCIWavDev
[wDevID
].fInput
= TRUE
;
284 else if (MCIWavDev
[wDevID
].fInput
) {
285 /* FIXME this is just a hack WInDev should be hidden here */
286 memcpy(&waveDesc
,&WInDev
[wDevID
].waveDesc
,sizeof(WAVEOPENDESC
));
288 dwRet
= widMessage(wDevID
, WIDM_CLOSE
, 0, 0L, 0L);
289 if (dwRet
!= MMSYSERR_NOERROR
) return MCIERR_INTERNAL
;
290 dwRet
= wodMessage(wDevID
, WODM_OPEN
, 0, (DWORD
)&waveDesc
, CALLBACK_NULL
);
291 MCIWavDev
[wDevID
].fInput
= FALSE
;
296 /**************************************************************************
297 * WAVE_mciClose [internal]
299 static DWORD
WAVE_mciClose(UINT16 wDevID
, DWORD dwParam
, LPMCI_GENERIC_PARMS lpParms
)
303 dprintf_mciwave(stddeb
,
304 "WAVE_mciClose(%u, %08lX, %p);\n", wDevID
, dwParam
, lpParms
);
305 MCIWavDev
[wDevID
].nUseCount
--;
306 if (MCIWavDev
[wDevID
].nUseCount
== 0) {
307 if (MCIWavDev
[wDevID
].hFile
!= 0) {
308 mmioClose(MCIWavDev
[wDevID
].hFile
, 0);
309 MCIWavDev
[wDevID
].hFile
= 0;
311 if (MCIWavDev
[wDevID
].fInput
)
312 dwRet
= widMessage(wDevID
, WIDM_CLOSE
, 0, 0L, 0L);
314 dwRet
= wodMessage(wDevID
, WODM_CLOSE
, 0, 0L, 0L);
316 if (dwRet
!= MMSYSERR_NOERROR
) return MCIERR_INTERNAL
;
322 /**************************************************************************
323 * WAVE_mciPlay [internal]
325 static DWORD
WAVE_mciPlay(UINT16 wDevID
, DWORD dwFlags
, LPMCI_PLAY_PARMS lpParms
)
333 dprintf_mciwave(stddeb
,
334 "WAVE_mciPlay(%u, %08lX, %p);\n", wDevID
, dwFlags
, lpParms
);
336 if (MCIWavDev
[wDevID
].fInput
) {
337 dprintf_mciwave(stddeb
,"WAVE_mciPlay // cannot play on input device\n");
338 return MCIERR_NONAPPLICABLE_FUNCTION
;
341 if (MCIWavDev
[wDevID
].hFile
== 0) {
342 dprintf_mciwave(stddeb
,"WAVE_mciPlay // can't find file='%08lx' !\n",
343 MCIWavDev
[wDevID
].openParms
.lpstrElementName
);
344 return MCIERR_FILE_NOT_FOUND
;
346 start
= 1; end
= 99999;
347 if (dwFlags
& MCI_FROM
) {
348 start
= lpParms
->dwFrom
;
349 dprintf_mciwave(stddeb
,
350 "WAVE_mciPlay // MCI_FROM=%d \n", start
);
352 if (dwFlags
& MCI_TO
) {
354 dprintf_mciwave(stddeb
,"WAVE_mciPlay // MCI_TO=%d \n", end
);
357 if (dwFlags
& MCI_NOTIFY
) {
358 dprintf_mciwave(stddeb
,
359 "WAVE_mciPlay // MCI_NOTIFY %08lX !\n", lpParms
->dwCallback
);
362 dprintf_mciwave(stddeb
,
363 "WAVE_mciPlay // Can't 'fork' process !\n");
368 dprintf_mciwave(stddeb
,"WAVE_mciPlay // process started ! return to caller...\n");
374 lpWaveHdr
= &MCIWavDev
[wDevID
].WaveHdr
;
375 hData
= GlobalAlloc16(GMEM_MOVEABLE
, bufsize
);
376 lpWaveHdr
->lpData
= (LPSTR
) GlobalLock16(hData
);
377 lpWaveHdr
->dwUser
= 0L;
378 lpWaveHdr
->dwFlags
= 0L;
379 lpWaveHdr
->dwLoops
= 0L;
380 dwRet
=wodMessage(wDevID
,WODM_PREPARE
,0,(DWORD
)lpWaveHdr
,sizeof(WAVEHDR
));
382 count
= mmioRead(MCIWavDev
[wDevID
].hFile
, lpWaveHdr
->lpData
, bufsize
);
383 dprintf_mciwave(stddeb
,"WAVE_mciPlay // mmioRead bufsize=%ld count=%ld\n", bufsize
, count
);
384 if (count
< 1) break;
385 lpWaveHdr
->dwBufferLength
= count
;
386 /* lpWaveHdr->dwBytesRecorded = count; */
387 dprintf_mciwave(stddeb
,"WAVE_mciPlay // before WODM_WRITE lpWaveHdr=%p dwBufferLength=%lu dwBytesRecorded=%lu\n",
388 lpWaveHdr
, lpWaveHdr
->dwBufferLength
, lpWaveHdr
->dwBytesRecorded
);
389 dwRet
=wodMessage(wDevID
,WODM_WRITE
,0,(DWORD
)lpWaveHdr
,sizeof(WAVEHDR
));
391 dwRet
= wodMessage(wDevID
,WODM_UNPREPARE
,0,(DWORD
)lpWaveHdr
,sizeof(WAVEHDR
));
392 if (lpWaveHdr
->lpData
!= NULL
) {
393 GlobalUnlock16(hData
);
395 lpWaveHdr
->lpData
= NULL
;
397 if (dwFlags
& MCI_NOTIFY
) {
398 dprintf_mciwave(stddeb
,"WAVE_mciPlay // MCI_NOTIFY_SUCCESSFUL %08lX !\n", lpParms
->dwCallback
);
399 mciDriverNotify((HWND16
)LOWORD(lpParms
->dwCallback
),
400 MCIWavDev
[wDevID
].wNotifyDeviceID
, MCI_NOTIFY_SUCCESSFUL
);
406 /**************************************************************************
407 * WAVE_mciRecord [internal]
409 static DWORD
WAVE_mciRecord(UINT16 wDevID
, DWORD dwFlags
, LPMCI_RECORD_PARMS lpParms
)
417 dprintf_mciwave(stddeb
,
418 "WAVE_mciRecord(%u, %08lX, %p);\n", wDevID
, dwFlags
, lpParms
);
420 if (!MCIWavDev
[wDevID
].fInput
) {
421 dprintf_mciwave(stddeb
,"WAVE_mciPlay // cannot record on output device\n");
422 return MCIERR_NONAPPLICABLE_FUNCTION
;
425 if (MCIWavDev
[wDevID
].hFile
== 0) {
426 dprintf_mciwave(stddeb
,"WAVE_mciRecord // can't find file='%08lx' !\n",
427 MCIWavDev
[wDevID
].openParms
.lpstrElementName
);
428 return MCIERR_FILE_NOT_FOUND
;
430 start
= 1; end
= 99999;
431 if (dwFlags
& MCI_FROM
) {
432 start
= lpParms
->dwFrom
;
433 dprintf_mciwave(stddeb
,
434 "WAVE_mciRecord // MCI_FROM=%d \n", start
);
436 if (dwFlags
& MCI_TO
) {
438 dprintf_mciwave(stddeb
,"WAVE_mciRecord // MCI_TO=%d \n", end
);
441 lpWaveHdr
= &MCIWavDev
[wDevID
].WaveHdr
;
442 hData
= GlobalAlloc16(GMEM_MOVEABLE
, bufsize
);
443 lpWaveHdr
->lpData
= (LPSTR
)GlobalLock16(hData
);
444 lpWaveHdr
->dwBufferLength
= bufsize
;
445 lpWaveHdr
->dwUser
= 0L;
446 lpWaveHdr
->dwFlags
= 0L;
447 lpWaveHdr
->dwLoops
= 0L;
448 dwRet
=widMessage(wDevID
,WIDM_PREPARE
,0,(DWORD
)lpWaveHdr
,sizeof(WAVEHDR
));
449 dprintf_mciwave(stddeb
,"WAVE_mciRecord // after WIDM_PREPARE \n");
451 lpWaveHdr
->dwBytesRecorded
= 0;
452 dwRet
= widMessage(wDevID
, WIDM_START
, 0, 0L, 0L);
453 dprintf_mciwave(stddeb
,
454 "WAVE_mciRecord // after WIDM_START lpWaveHdr=%p dwBytesRecorded=%lu\n",
455 lpWaveHdr
, lpWaveHdr
->dwBytesRecorded
);
456 if (lpWaveHdr
->dwBytesRecorded
== 0) break;
458 dprintf_mciwave(stddeb
,"WAVE_mciRecord // before WIDM_UNPREPARE \n");
459 dwRet
= widMessage(wDevID
,WIDM_UNPREPARE
,0,(DWORD
)lpWaveHdr
,sizeof(WAVEHDR
));
460 dprintf_mciwave(stddeb
,"WAVE_mciRecord // after WIDM_UNPREPARE \n");
461 if (lpWaveHdr
->lpData
!= NULL
) {
462 GlobalUnlock16(hData
);
464 lpWaveHdr
->lpData
= NULL
;
466 if (dwFlags
& MCI_NOTIFY
) {
467 dprintf_mciwave(stddeb
,"WAVE_mciRecord // MCI_NOTIFY_SUCCESSFUL %08lX !\n", lpParms
->dwCallback
);
468 mciDriverNotify((HWND16
)LOWORD(lpParms
->dwCallback
),
469 MCIWavDev
[wDevID
].wNotifyDeviceID
, MCI_NOTIFY_SUCCESSFUL
);
475 /**************************************************************************
476 * WAVE_mciStop [internal]
478 static DWORD
WAVE_mciStop(UINT16 wDevID
, DWORD dwFlags
, LPMCI_GENERIC_PARMS lpParms
)
482 dprintf_mciwave(stddeb
,
483 "WAVE_mciStop(%u, %08lX, %p);\n", wDevID
, dwFlags
, lpParms
);
484 if (lpParms
== NULL
) return MCIERR_INTERNAL
;
485 if (MCIWavDev
[wDevID
].fInput
)
486 dwRet
= widMessage(wDevID
, WIDM_STOP
, 0, dwFlags
, (DWORD
)lpParms
);
488 dwRet
= wodMessage(wDevID
, WODM_STOP
, 0, dwFlags
, (DWORD
)lpParms
);
494 /**************************************************************************
495 * WAVE_mciPause [internal]
497 static DWORD
WAVE_mciPause(UINT16 wDevID
, DWORD dwFlags
, LPMCI_GENERIC_PARMS lpParms
)
501 dprintf_mciwave(stddeb
,
502 "WAVE_mciPause(%u, %08lX, %p);\n", wDevID
, dwFlags
, lpParms
);
503 if (lpParms
== NULL
) return MCIERR_INTERNAL
;
504 if (MCIWavDev
[wDevID
].fInput
)
505 dwRet
= widMessage(wDevID
, WIDM_PAUSE
, 0, dwFlags
, (DWORD
)lpParms
);
507 dwRet
= wodMessage(wDevID
, WODM_PAUSE
, 0, dwFlags
, (DWORD
)lpParms
);
513 /**************************************************************************
514 * WAVE_mciResume [internal]
516 static DWORD
WAVE_mciResume(UINT16 wDevID
, DWORD dwFlags
, LPMCI_GENERIC_PARMS lpParms
)
518 dprintf_mciwave(stddeb
,
519 "WAVE_mciResume(%u, %08lX, %p);\n", wDevID
, dwFlags
, lpParms
);
520 if (lpParms
== NULL
) return MCIERR_INTERNAL
;
525 /**************************************************************************
526 * WAVE_mciSet [internal]
528 static DWORD
WAVE_mciSet(UINT16 wDevID
, DWORD dwFlags
, LPMCI_SET_PARMS lpParms
)
530 dprintf_mciwave(stddeb
,
531 "WAVE_mciSet(%u, %08lX, %p);\n", wDevID
, dwFlags
, lpParms
);
532 if (lpParms
== NULL
) return MCIERR_INTERNAL
;
533 dprintf_mciwave(stddeb
,
534 "WAVE_mciSet // dwTimeFormat=%08lX\n", lpParms
->dwTimeFormat
);
535 dprintf_mciwave(stddeb
,
536 "WAVE_mciSet // dwAudio=%08lX\n", lpParms
->dwAudio
);
537 if (dwFlags
& MCI_SET_TIME_FORMAT
) {
538 switch (lpParms
->dwTimeFormat
) {
539 case MCI_FORMAT_MILLISECONDS
:
540 dprintf_mciwave(stddeb
, "WAVE_mciSet // MCI_FORMAT_MILLISECONDS !\n");
542 case MCI_FORMAT_BYTES
:
543 dprintf_mciwave(stddeb
, "WAVE_mciSet // MCI_FORMAT_BYTES !\n");
545 case MCI_FORMAT_SAMPLES
:
546 dprintf_mciwave(stddeb
, "WAVE_mciSet // MCI_FORMAT_SAMPLES !\n");
549 dprintf_mciwave(stddeb
, "WAVE_mciSet // bad time format !\n");
550 return MCIERR_BAD_TIME_FORMAT
;
553 if (dwFlags
& MCI_SET_VIDEO
) return MCIERR_UNSUPPORTED_FUNCTION
;
554 if (dwFlags
& MCI_SET_DOOR_OPEN
) return MCIERR_UNSUPPORTED_FUNCTION
;
555 if (dwFlags
& MCI_SET_DOOR_CLOSED
) return MCIERR_UNSUPPORTED_FUNCTION
;
556 if (dwFlags
& MCI_SET_AUDIO
)
557 dprintf_mciwave(stddeb
,"WAVE_mciSet // MCI_SET_AUDIO !\n");
558 if (dwFlags
&& MCI_SET_ON
) {
559 dprintf_mciwave(stddeb
,"WAVE_mciSet // MCI_SET_ON !\n");
560 if (dwFlags
&& MCI_SET_AUDIO_LEFT
)
561 dprintf_mciwave(stddeb
,"WAVE_mciSet // MCI_SET_AUDIO_LEFT !\n");
562 if (dwFlags
&& MCI_SET_AUDIO_RIGHT
)
563 dprintf_mciwave(stddeb
,"WAVE_mciSet // MCI_SET_AUDIO_RIGHT !\n");
565 if (dwFlags
& MCI_SET_OFF
)
566 dprintf_mciwave(stddeb
,"WAVE_mciSet // MCI_SET_OFF !\n");
567 if (dwFlags
& MCI_WAVE_INPUT
)
568 dprintf_mciwave(stddeb
,"WAVE_mciSet // MCI_WAVE_INPUT !\n");
569 if (dwFlags
& MCI_WAVE_OUTPUT
)
570 dprintf_mciwave(stddeb
,"WAVE_mciSet // MCI_WAVE_OUTPUT !\n");
571 if (dwFlags
& MCI_WAVE_SET_ANYINPUT
)
572 dprintf_mciwave(stddeb
,"WAVE_mciSet // MCI_WAVE_SET_ANYINPUT !\n");
573 if (dwFlags
& MCI_WAVE_SET_ANYOUTPUT
)
574 dprintf_mciwave(stddeb
,"WAVE_mciSet // MCI_WAVE_SET_ANYOUTPUT !\n");
575 if (dwFlags
& MCI_WAVE_SET_AVGBYTESPERSEC
)
576 dprintf_mciwave(stddeb
,
577 "WAVE_mciSet // MCI_WAVE_SET_AVGBYTESPERSEC !\n");
578 if (dwFlags
& MCI_WAVE_SET_BITSPERSAMPLE
)
579 dprintf_mciwave(stddeb
,
580 "WAVE_mciSet // MCI_WAVE_SET_BITSPERSAMPLE !\n");
581 if (dwFlags
& MCI_WAVE_SET_BLOCKALIGN
)
582 dprintf_mciwave(stddeb
,"WAVE_mciSet // MCI_WAVE_SET_BLOCKALIGN !\n");
583 if (dwFlags
& MCI_WAVE_SET_CHANNELS
)
584 dprintf_mciwave(stddeb
,"WAVE_mciSet // MCI_WAVE_SET_CHANNELS !\n");
585 if (dwFlags
& MCI_WAVE_SET_FORMATTAG
)
586 dprintf_mciwave(stddeb
,"WAVE_mciSet // MCI_WAVE_SET_FORMATTAG !\n");
587 if (dwFlags
& MCI_WAVE_SET_SAMPLESPERSEC
)
588 dprintf_mciwave(stddeb
,
589 "WAVE_mciSet // MCI_WAVE_SET_SAMPLESPERSEC !\n");
594 /**************************************************************************
595 * WAVE_mciStatus [internal]
597 static DWORD
WAVE_mciStatus(UINT16 wDevID
, DWORD dwFlags
, LPMCI_STATUS_PARMS lpParms
)
599 dprintf_mciwave(stddeb
,
600 "WAVE_mciStatus(%u, %08lX, %p);\n", wDevID
, dwFlags
, lpParms
);
601 if (lpParms
== NULL
) return MCIERR_INTERNAL
;
602 if (dwFlags
& MCI_STATUS_ITEM
) {
603 switch(lpParms
->dwItem
) {
604 case MCI_STATUS_CURRENT_TRACK
:
605 lpParms
->dwReturn
= 1;
607 case MCI_STATUS_LENGTH
:
608 lpParms
->dwReturn
= 5555;
609 if (dwFlags
& MCI_TRACK
) {
610 lpParms
->dwTrack
= 1;
611 lpParms
->dwReturn
= 2222;
614 case MCI_STATUS_MODE
:
615 lpParms
->dwReturn
= MCI_MODE_STOP
;
617 case MCI_STATUS_MEDIA_PRESENT
:
618 dprintf_mciwave(stddeb
,"WAVE_mciStatus // MCI_STATUS_MEDIA_PRESENT !\n");
619 lpParms
->dwReturn
= TRUE
;
621 case MCI_STATUS_NUMBER_OF_TRACKS
:
622 lpParms
->dwReturn
= 1;
624 case MCI_STATUS_POSITION
:
625 lpParms
->dwReturn
= 3333;
626 if (dwFlags
& MCI_STATUS_START
)
628 if (dwFlags
& MCI_TRACK
) {
629 lpParms
->dwTrack
= 1;
630 lpParms
->dwReturn
= 777;
633 case MCI_STATUS_READY
:
634 dprintf_mciwave(stddeb
,"WAVE_mciStatus // MCI_STATUS_READY !\n");
635 lpParms
->dwReturn
= TRUE
;
637 case MCI_STATUS_TIME_FORMAT
:
638 dprintf_mciwave(stddeb
,"WAVE_mciStatus // MCI_STATUS_TIME_FORMAT !\n");
639 lpParms
->dwReturn
= MCI_FORMAT_MILLISECONDS
;
642 dprintf_mciwave(stddeb
,"WAVE_mciStatus // MCI_WAVE_INPUT !\n");
643 lpParms
->dwReturn
= 0;
645 case MCI_WAVE_OUTPUT
:
646 dprintf_mciwave(stddeb
,"WAVE_mciStatus // MCI_WAVE_OUTPUT !\n");
647 lpParms
->dwReturn
= 0;
649 case MCI_WAVE_STATUS_AVGBYTESPERSEC
:
650 dprintf_mciwave(stddeb
,"WAVE_mciStatus // MCI_WAVE_STATUS_AVGBYTESPERSEC !\n");
651 lpParms
->dwReturn
= 22050;
653 case MCI_WAVE_STATUS_BITSPERSAMPLE
:
654 dprintf_mciwave(stddeb
,"WAVE_mciStatus // MCI_WAVE_STATUS_BITSPERSAMPLE !\n");
655 lpParms
->dwReturn
= 8;
657 case MCI_WAVE_STATUS_BLOCKALIGN
:
658 dprintf_mciwave(stddeb
,"WAVE_mciStatus // MCI_WAVE_STATUS_BLOCKALIGN !\n");
659 lpParms
->dwReturn
= 1;
661 case MCI_WAVE_STATUS_CHANNELS
:
662 dprintf_mciwave(stddeb
,"WAVE_mciStatus // MCI_WAVE_STATUS_CHANNELS !\n");
663 lpParms
->dwReturn
= 1;
665 case MCI_WAVE_STATUS_FORMATTAG
:
666 dprintf_mciwave(stddeb
,"WAVE_mciStatus // MCI_WAVE_FORMATTAG !\n");
667 lpParms
->dwReturn
= WAVE_FORMAT_PCM
;
669 case MCI_WAVE_STATUS_LEVEL
:
670 dprintf_mciwave(stddeb
,"WAVE_mciStatus // MCI_WAVE_STATUS_LEVEL !\n");
671 lpParms
->dwReturn
= 0xAAAA5555;
673 case MCI_WAVE_STATUS_SAMPLESPERSEC
:
674 dprintf_mciwave(stddeb
,"WAVE_mciStatus // MCI_WAVE_STATUS_SAMPLESPERSEC !\n");
675 lpParms
->dwReturn
= 22050;
678 dprintf_mciwave(stddeb
,"WAVE_mciStatus // unknown command %08lX !\n", lpParms
->dwItem
);
679 return MCIERR_UNRECOGNIZED_COMMAND
;
682 if (dwFlags
& MCI_NOTIFY
) {
683 dprintf_mciwave(stddeb
,"WAVE_mciStatus // MCI_NOTIFY_SUCCESSFUL %08lX !\n", lpParms
->dwCallback
);
684 mciDriverNotify((HWND16
)LOWORD(lpParms
->dwCallback
),
685 MCIWavDev
[wDevID
].wNotifyDeviceID
, MCI_NOTIFY_SUCCESSFUL
);
690 /**************************************************************************
691 * WAVE_mciGetDevCaps [internal]
693 static DWORD
WAVE_mciGetDevCaps(UINT16 wDevID
, DWORD dwFlags
,
694 LPMCI_GETDEVCAPS_PARMS lpParms
)
696 dprintf_mciwave(stddeb
,
697 "WAVE_mciGetDevCaps(%u, %08lX, %p);\n", wDevID
, dwFlags
, lpParms
);
698 if (lpParms
== NULL
) return MCIERR_INTERNAL
;
699 if (dwFlags
& MCI_GETDEVCAPS_ITEM
) {
700 switch(lpParms
->dwItem
) {
701 case MCI_GETDEVCAPS_CAN_RECORD
:
702 lpParms
->dwReturn
= TRUE
;
704 case MCI_GETDEVCAPS_HAS_AUDIO
:
705 lpParms
->dwReturn
= TRUE
;
707 case MCI_GETDEVCAPS_HAS_VIDEO
:
708 lpParms
->dwReturn
= FALSE
;
710 case MCI_GETDEVCAPS_DEVICE_TYPE
:
711 lpParms
->dwReturn
= MCI_DEVTYPE_WAVEFORM_AUDIO
;
713 case MCI_GETDEVCAPS_USES_FILES
:
714 lpParms
->dwReturn
= TRUE
;
716 case MCI_GETDEVCAPS_COMPOUND_DEVICE
:
717 lpParms
->dwReturn
= TRUE
;
719 case MCI_GETDEVCAPS_CAN_EJECT
:
720 lpParms
->dwReturn
= FALSE
;
722 case MCI_GETDEVCAPS_CAN_PLAY
:
723 lpParms
->dwReturn
= TRUE
;
725 case MCI_GETDEVCAPS_CAN_SAVE
:
726 lpParms
->dwReturn
= TRUE
;
728 case MCI_WAVE_GETDEVCAPS_INPUTS
:
729 lpParms
->dwReturn
= 1;
731 case MCI_WAVE_GETDEVCAPS_OUTPUTS
:
732 lpParms
->dwReturn
= 1;
735 return MCIERR_UNRECOGNIZED_COMMAND
;
741 /**************************************************************************
742 * WAVE_mciInfo [internal]
744 static DWORD
WAVE_mciInfo(UINT16 wDevID
, DWORD dwFlags
, LPMCI_INFO_PARMS16 lpParms
)
746 dprintf_mciwave(stddeb
,
747 "WAVE_mciInfo(%u, %08lX, %p);\n", wDevID
, dwFlags
, lpParms
);
748 if (lpParms
== NULL
) return MCIERR_INTERNAL
;
749 lpParms
->lpstrReturn
= NULL
;
751 case MCI_INFO_PRODUCT
:
752 lpParms
->lpstrReturn
= "Linux Sound System 0.5";
755 lpParms
->lpstrReturn
=
756 (LPSTR
)MCIWavDev
[wDevID
].openParms
.lpstrElementName
;
759 lpParms
->lpstrReturn
= "Linux Sound System 0.5";
761 case MCI_WAVE_OUTPUT
:
762 lpParms
->lpstrReturn
= "Linux Sound System 0.5";
765 return MCIERR_UNRECOGNIZED_COMMAND
;
767 if (lpParms
->lpstrReturn
!= NULL
)
768 lpParms
->dwRetSize
= strlen(lpParms
->lpstrReturn
);
770 lpParms
->dwRetSize
= 0;
775 /*-----------------------------------------------------------------------*/
778 /**************************************************************************
779 * wodGetDevCaps [internal]
781 static DWORD
wodGetDevCaps(WORD wDevID
, LPWAVEOUTCAPS16 lpCaps
, DWORD dwSize
)
789 dprintf_mciwave(stddeb
,
790 "wodGetDevCaps(%u, %p, %lu);\n", wDevID
, lpCaps
, dwSize
);
791 if (lpCaps
== NULL
) return MMSYSERR_NOTENABLED
;
792 if (access(SOUND_DEV
,0) != 0) return MMSYSERR_NOTENABLED
;
793 audio
= open (SOUND_DEV
, O_WRONLY
, 0);
794 if (audio
== -1) return MMSYSERR_ALLOCATED
;
796 lpCaps
->wMid
= 0x0002;
797 lpCaps
->wPid
= 0x0104;
798 strcpy(lpCaps
->szPname
, "SB16 Wave Out");
800 lpCaps
->wMid
= 0x00FF; /* Manufac ID */
801 lpCaps
->wPid
= 0x0001; /* Product ID */
802 strcpy(lpCaps
->szPname
, "Linux WAVOUT Driver");
804 lpCaps
->vDriverVersion
= 0x0100;
805 lpCaps
->dwFormats
= 0x00000000;
806 lpCaps
->dwSupport
= WAVECAPS_VOLUME
;
807 lpCaps
->wChannels
= (IOCTL(audio
, SNDCTL_DSP_STEREO
, dsp_stereo
) != 0) ? 1 : 2;
808 if (lpCaps
->wChannels
> 1) lpCaps
->dwSupport
|= WAVECAPS_LRVOLUME
;
809 bytespersmpl
= (IOCTL(audio
, SNDCTL_DSP_SAMPLESIZE
, samplesize
) != 0) ? 1 : 2;
811 if (IOCTL(audio
, SNDCTL_DSP_SPEED
, smplrate
) == 0) {
812 lpCaps
->dwFormats
|= WAVE_FORMAT_4M08
;
813 if (lpCaps
->wChannels
> 1)
814 lpCaps
->dwFormats
|= WAVE_FORMAT_4S08
;
815 if (bytespersmpl
> 1) {
816 lpCaps
->dwFormats
|= WAVE_FORMAT_4M16
;
817 if (lpCaps
->wChannels
> 1)
818 lpCaps
->dwFormats
|= WAVE_FORMAT_4S16
;
822 if (IOCTL(audio
, SNDCTL_DSP_SPEED
, smplrate
) == 0) {
823 lpCaps
->dwFormats
|= WAVE_FORMAT_2M08
;
824 if (lpCaps
->wChannels
> 1)
825 lpCaps
->dwFormats
|= WAVE_FORMAT_2S08
;
826 if (bytespersmpl
> 1) {
827 lpCaps
->dwFormats
|= WAVE_FORMAT_2M16
;
828 if (lpCaps
->wChannels
> 1)
829 lpCaps
->dwFormats
|= WAVE_FORMAT_2S16
;
833 if (IOCTL(audio
, SNDCTL_DSP_SPEED
, smplrate
) == 0) {
834 lpCaps
->dwFormats
|= WAVE_FORMAT_1M08
;
835 if (lpCaps
->wChannels
> 1)
836 lpCaps
->dwFormats
|= WAVE_FORMAT_1S08
;
837 if (bytespersmpl
> 1) {
838 lpCaps
->dwFormats
|= WAVE_FORMAT_1M16
;
839 if (lpCaps
->wChannels
> 1)
840 lpCaps
->dwFormats
|= WAVE_FORMAT_1S16
;
844 dprintf_mciwave(stddeb
,
845 "wodGetDevCaps // dwFormats = %08lX\n", lpCaps
->dwFormats
);
846 return MMSYSERR_NOERROR
;
850 /**************************************************************************
853 static DWORD
wodOpen(WORD wDevID
, LPWAVEOPENDESC lpDesc
, DWORD dwFlags
)
855 int audio
,abuf_size
,smplrate
,samplesize
,dsp_stereo
;
856 LPWAVEFORMAT lpFormat
;
858 dprintf_mciwave(stddeb
,
859 "wodOpen(%u, %p, %08lX);\n", wDevID
, lpDesc
, dwFlags
);
860 if (lpDesc
== NULL
) {
861 dprintf_mciwave(stddeb
,"Linux 'wodOpen' // Invalid Parameter !\n");
862 return MMSYSERR_INVALPARAM
;
864 if (wDevID
>= MAX_WAVOUTDRV
) {
865 dprintf_mciwave(stddeb
,"Linux 'wodOpen' // MAX_WAVOUTDRV reached !\n");
866 return MMSYSERR_ALLOCATED
;
868 WOutDev
[wDevID
].unixdev
= 0;
869 if (access(SOUND_DEV
,0) != 0) return MMSYSERR_NOTENABLED
;
870 audio
= open (SOUND_DEV
, O_WRONLY
, 0);
872 dprintf_mciwave(stddeb
,"Linux 'wodOpen' // can't open !\n");
873 return MMSYSERR_ALLOCATED
;
875 IOCTL(audio
, SNDCTL_DSP_GETBLKSIZE
, abuf_size
);
876 if (abuf_size
< 1024 || abuf_size
> 65536) {
878 dprintf_mciwave(stddeb
,"Linux 'wodOpen' // IOCTL can't 'SNDCTL_DSP_GETBLKSIZE' !\n");
880 dprintf_mciwave(stddeb
,"Linux 'wodOpen' // SNDCTL_DSP_GETBLKSIZE Invalid bufsize !\n");
881 return MMSYSERR_NOTENABLED
;
883 WOutDev
[wDevID
].wFlags
= HIWORD(dwFlags
& CALLBACK_TYPEMASK
);
884 switch(WOutDev
[wDevID
].wFlags
) {
886 dprintf_mciwave(stddeb
, "Linux 'wodOpen' // CALLBACK_NULL !\n");
889 dprintf_mciwave(stddeb
, "Linux 'wodOpen' // CALLBACK_WINDOW !\n");
892 dprintf_mciwave(stddeb
, "Linux 'wodOpen' // CALLBACK_TASK !\n");
895 dprintf_mciwave(stddeb
, "Linux 'wodOpen' // CALLBACK_FUNCTION !\n");
898 WOutDev
[wDevID
].lpQueueHdr
= NULL
;
899 WOutDev
[wDevID
].unixdev
= audio
;
900 WOutDev
[wDevID
].dwTotalPlayed
= 0;
901 WOutDev
[wDevID
].bufsize
= abuf_size
;
902 /* FIXME: copy lpFormat too? */
903 memcpy(&WOutDev
[wDevID
].waveDesc
, lpDesc
, sizeof(WAVEOPENDESC
));
904 dprintf_mciwave(stddeb
,"Linux 'wodOpen' // lpDesc->lpFormat = %p\n",lpDesc
->lpFormat
);
905 lpFormat
= lpDesc
->lpFormat
;
906 dprintf_mciwave(stddeb
,"Linux 'wodOpen' // lpFormat = %p\n",lpFormat
);
907 if (lpFormat
->wFormatTag
!= WAVE_FORMAT_PCM
) {
908 dprintf_mciwave(stddeb
,"Linux 'wodOpen' // Bad format %04X !\n",
909 lpFormat
->wFormatTag
);
910 dprintf_mciwave(stddeb
,"Linux 'wodOpen' // Bad nChannels %d !\n",
911 lpFormat
->nChannels
);
912 dprintf_mciwave(stddeb
,"Linux 'wodOpen' // Bad nSamplesPerSec %ld !\n",
913 lpFormat
->nSamplesPerSec
);
914 return WAVERR_BADFORMAT
;
916 memcpy(&WOutDev
[wDevID
].Format
, lpFormat
, sizeof(PCMWAVEFORMAT
));
917 if (WOutDev
[wDevID
].Format
.wf
.nChannels
== 0) return WAVERR_BADFORMAT
;
918 if (WOutDev
[wDevID
].Format
.wf
.nSamplesPerSec
== 0) return WAVERR_BADFORMAT
;
919 dprintf_mciwave(stddeb
,"Linux 'wodOpen' // wBitsPerSample=%u !\n",
920 WOutDev
[wDevID
].Format
.wBitsPerSample
);
921 if (WOutDev
[wDevID
].Format
.wBitsPerSample
== 0) {
922 WOutDev
[wDevID
].Format
.wBitsPerSample
= 8 *
923 (WOutDev
[wDevID
].Format
.wf
.nAvgBytesPerSec
/
924 WOutDev
[wDevID
].Format
.wf
.nSamplesPerSec
) /
925 WOutDev
[wDevID
].Format
.wf
.nChannels
;
927 samplesize
= WOutDev
[wDevID
].Format
.wBitsPerSample
;
928 smplrate
= WOutDev
[wDevID
].Format
.wf
.nSamplesPerSec
;
929 dsp_stereo
= (WOutDev
[wDevID
].Format
.wf
.nChannels
> 1) ? TRUE
: FALSE
;
930 IOCTL(audio
, SNDCTL_DSP_SPEED
, smplrate
);
931 IOCTL(audio
, SNDCTL_DSP_SAMPLESIZE
, samplesize
);
932 IOCTL(audio
, SNDCTL_DSP_STEREO
, dsp_stereo
);
933 dprintf_mciwave(stddeb
,"Linux 'wodOpen' // wBitsPerSample=%u !\n",
934 WOutDev
[wDevID
].Format
.wBitsPerSample
);
935 dprintf_mciwave(stddeb
,"Linux 'wodOpen' // nAvgBytesPerSec=%lu !\n",
936 WOutDev
[wDevID
].Format
.wf
.nAvgBytesPerSec
);
937 dprintf_mciwave(stddeb
,"Linux 'wodOpen' // nSamplesPerSec=%lu !\n",
938 WOutDev
[wDevID
].Format
.wf
.nSamplesPerSec
);
939 dprintf_mciwave(stddeb
,"Linux 'wodOpen' // nChannels=%u !\n",
940 WOutDev
[wDevID
].Format
.wf
.nChannels
);
941 if (WAVE_NotifyClient(wDevID
, WOM_OPEN
, 0L, 0L) != MMSYSERR_NOERROR
) {
942 dprintf_mciwave(stddeb
,"Linux 'wodOpen' // can't notify client !\n");
943 return MMSYSERR_INVALPARAM
;
945 return MMSYSERR_NOERROR
;
948 /**************************************************************************
949 * wodClose [internal]
951 static DWORD
wodClose(WORD wDevID
)
953 dprintf_mciwave(stddeb
,"wodClose(%u);\n", wDevID
);
954 if (wDevID
> MAX_WAVOUTDRV
) return MMSYSERR_INVALPARAM
;
955 if (WOutDev
[wDevID
].unixdev
== 0) {
956 dprintf_mciwave(stddeb
,"Linux 'wodClose' // can't close !\n");
957 return MMSYSERR_NOTENABLED
;
959 if (WOutDev
[wDevID
].lpQueueHdr
!= NULL
) {
960 dprintf_mciwave(stddeb
,"linux 'wodclose' // still buffers open !\n");
961 /* Don't care. Who needs those buffers anyway */
962 /*return WAVERR_STILLPLAYING; */
964 close(WOutDev
[wDevID
].unixdev
);
965 WOutDev
[wDevID
].unixdev
= 0;
966 WOutDev
[wDevID
].bufsize
= 0;
967 WOutDev
[wDevID
].lpQueueHdr
= NULL
;
968 if (WAVE_NotifyClient(wDevID
, WOM_CLOSE
, 0L, 0L) != MMSYSERR_NOERROR
) {
969 dprintf_mciwave(stddeb
,"Linux 'wodClose' // can't notify client !\n");
970 return MMSYSERR_INVALPARAM
;
972 return MMSYSERR_NOERROR
;
975 /**************************************************************************
976 * wodWrite [internal]
977 * FIXME: this should _APPEND_ the lpWaveHdr to the output queue of the
978 * device, and initiate async playing.
980 static DWORD
wodWrite(WORD wDevID
, LPWAVEHDR lpWaveHdr
, DWORD dwSize
)
986 dprintf_mciwave(stddeb
,"wodWrite(%u, %p, %08lX);\n", wDevID
, lpWaveHdr
, dwSize
);
987 if (WOutDev
[wDevID
].unixdev
== 0) {
988 dprintf_mciwave(stddeb
,"Linux 'wodWrite' // can't play !\n");
989 return MMSYSERR_NOTENABLED
;
991 if (lpWaveHdr
->lpData
== NULL
) return WAVERR_UNPREPARED
;
992 if (!(lpWaveHdr
->dwFlags
& WHDR_PREPARED
)) return WAVERR_UNPREPARED
;
993 if (lpWaveHdr
->dwFlags
& WHDR_INQUEUE
) return WAVERR_STILLPLAYING
;
994 lpWaveHdr
->dwFlags
&= ~WHDR_DONE
;
995 lpWaveHdr
->dwFlags
|= WHDR_INQUEUE
;
996 dprintf_mciwave(stddeb
,
997 "wodWrite() // dwBufferLength %lu !\n", lpWaveHdr
->dwBufferLength
);
998 dprintf_mciwave(stddeb
,
999 "wodWrite() // WOutDev[%u].unixdev %u !\n", wDevID
, WOutDev
[wDevID
].unixdev
);
1000 lpData
= lpWaveHdr
->lpData
;
1001 count
= write (WOutDev
[wDevID
].unixdev
, lpData
, lpWaveHdr
->dwBufferLength
);
1002 dprintf_mciwave(stddeb
,"wodWrite()//write returned count %u !\n",count
);
1003 if (count
!= lpWaveHdr
->dwBufferLength
) {
1004 dprintf_mciwave(stddeb
,"Linux 'wodWrite' // error writting !\n");
1005 return MMSYSERR_NOTENABLED
;
1007 WOutDev
[wDevID
].dwTotalPlayed
+= count
;
1008 lpWaveHdr
->dwFlags
&= ~WHDR_INQUEUE
;
1009 lpWaveHdr
->dwFlags
|= WHDR_DONE
;
1010 if ((DWORD
)lpWaveHdr
->lpData
!=lpWaveHdr
->reserved
) {
1011 /* FIXME: what if it expects it's OWN lpwavehdr back? */
1012 xwavehdr
= SEGPTR_NEW(WAVEHDR
);
1013 memcpy(xwavehdr
,lpWaveHdr
,sizeof(WAVEHDR
));
1014 xwavehdr
->lpData
= (LPBYTE
)xwavehdr
->reserved
;
1015 if (WAVE_NotifyClient(wDevID
, WOM_DONE
, (DWORD
)SEGPTR_GET(xwavehdr
), count
) != MMSYSERR_NOERROR
) {
1016 dprintf_mciwave(stddeb
,"Linux 'wodWrite' // can't notify client !\n");
1017 SEGPTR_FREE(xwavehdr
);
1018 return MMSYSERR_INVALPARAM
;
1020 SEGPTR_FREE(xwavehdr
);
1022 if (WAVE_NotifyClient(wDevID
, WOM_DONE
, (DWORD
)lpWaveHdr
, count
) != MMSYSERR_NOERROR
) {
1023 dprintf_mciwave(stddeb
,"Linux 'wodWrite' // can't notify client !\n");
1024 return MMSYSERR_INVALPARAM
;
1027 return MMSYSERR_NOERROR
;
1030 /**************************************************************************
1031 * wodPrepare [internal]
1033 static DWORD
wodPrepare(WORD wDevID
, LPWAVEHDR lpWaveHdr
, DWORD dwSize
)
1035 dprintf_mciwave(stddeb
,
1036 "wodPrepare(%u, %p, %08lX);\n", wDevID
, lpWaveHdr
, dwSize
);
1037 if (WOutDev
[wDevID
].unixdev
== 0) {
1038 dprintf_mciwave(stddeb
,"Linux 'wodPrepare' // can't prepare !\n");
1039 return MMSYSERR_NOTENABLED
;
1041 /* don't append to queue, wodWrite does that */
1042 WOutDev
[wDevID
].dwTotalPlayed
= 0;
1043 if (lpWaveHdr
->dwFlags
& WHDR_INQUEUE
)
1044 return WAVERR_STILLPLAYING
;
1045 lpWaveHdr
->dwFlags
|= WHDR_PREPARED
;
1046 lpWaveHdr
->dwFlags
&= ~WHDR_DONE
;
1047 return MMSYSERR_NOERROR
;
1050 /**************************************************************************
1051 * wodUnprepare [internal]
1053 static DWORD
wodUnprepare(WORD wDevID
, LPWAVEHDR lpWaveHdr
, DWORD dwSize
)
1055 dprintf_mciwave(stddeb
,
1056 "wodUnprepare(%u, %p, %08lX);\n", wDevID
, lpWaveHdr
, dwSize
);
1057 if (WOutDev
[wDevID
].unixdev
== 0) {
1058 dprintf_mciwave(stddeb
,"Linux 'wodUnprepare' // can't unprepare !\n");
1059 return MMSYSERR_NOTENABLED
;
1061 if (lpWaveHdr
->dwFlags
& WHDR_INQUEUE
)
1062 return WAVERR_STILLPLAYING
;
1064 lpWaveHdr
->dwFlags
&= ~WHDR_PREPARED
;
1065 lpWaveHdr
->dwFlags
|= WHDR_DONE
;
1066 dprintf_mciwave(stddeb
,
1067 "Linux 'wodUnprepare' // all headers unprepared !\n");
1068 return MMSYSERR_NOERROR
;
1071 /**************************************************************************
1072 * wodRestart [internal]
1074 static DWORD
wodRestart(WORD wDevID
)
1076 dprintf_mciwave(stddeb
,"wodRestart(%u);\n", wDevID
);
1077 if (WOutDev
[wDevID
].unixdev
== 0) {
1078 dprintf_mciwave(stddeb
,"Linux 'wodRestart' // can't restart !\n");
1079 return MMSYSERR_NOTENABLED
;
1081 /* FIXME: is NotifyClient with WOM_DONE right ? (Comet Busters 1.3.3 needs this notification) */
1082 if (WAVE_NotifyClient(wDevID
, WOM_DONE
, 0L, 0L) != MMSYSERR_NOERROR
) {
1083 dprintf_mciwave(stddeb
,"Linux 'wodRestart' // can't notify client !\n");
1084 return MMSYSERR_INVALPARAM
;
1087 return MMSYSERR_NOERROR
;
1090 /**************************************************************************
1091 * wodReset [internal]
1093 static DWORD
wodReset(WORD wDevID
)
1095 dprintf_mciwave(stddeb
,"wodReset(%u);\n", wDevID
);
1096 if (WOutDev
[wDevID
].unixdev
== 0) {
1097 dprintf_mciwave(stddeb
,"Linux 'wodReset' // can't reset !\n");
1098 return MMSYSERR_NOTENABLED
;
1100 return MMSYSERR_NOERROR
;
1104 /**************************************************************************
1105 * wodGetPosition [internal]
1107 static DWORD
wodGetPosition(WORD wDevID
, LPMMTIME16 lpTime
, DWORD uSize
)
1110 dprintf_mciwave(stddeb
,"wodGetPosition(%u, %p, %lu);\n", wDevID
, lpTime
, uSize
);
1111 if (WOutDev
[wDevID
].unixdev
== 0) {
1112 dprintf_mciwave(stddeb
,"Linux 'wodGetPosition' // can't get pos !\n");
1113 return MMSYSERR_NOTENABLED
;
1115 if (lpTime
== NULL
) return MMSYSERR_INVALPARAM
;
1116 dprintf_mciwave(stddeb
,"wodGetPosition // wType=%04X !\n",
1118 dprintf_mciwave(stddeb
,"wodGetPosition // wBitsPerSample=%u\n",
1119 WOutDev
[wDevID
].Format
.wBitsPerSample
);
1120 dprintf_mciwave(stddeb
,"wodGetPosition // nSamplesPerSec=%lu\n",
1121 WOutDev
[wDevID
].Format
.wf
.nSamplesPerSec
);
1122 dprintf_mciwave(stddeb
,"wodGetPosition // nChannels=%u\n",
1123 WOutDev
[wDevID
].Format
.wf
.nChannels
);
1124 dprintf_mciwave(stddeb
,"wodGetPosition // nAvgBytesPerSec=%lu\n",
1125 WOutDev
[wDevID
].Format
.wf
.nAvgBytesPerSec
);
1126 switch(lpTime
->wType
) {
1128 lpTime
->u
.cb
= WOutDev
[wDevID
].dwTotalPlayed
;
1129 dprintf_mciwave(stddeb
,"wodGetPosition // TIME_BYTES=%lu\n", lpTime
->u
.cb
);
1132 dprintf_mciwave(stddeb
,"wodGetPosition // dwTotalPlayed=%lu\n",
1133 WOutDev
[wDevID
].dwTotalPlayed
);
1134 dprintf_mciwave(stddeb
,"wodGetPosition // wBitsPerSample=%u\n",
1135 WOutDev
[wDevID
].Format
.wBitsPerSample
);
1136 lpTime
->u
.sample
= WOutDev
[wDevID
].dwTotalPlayed
* 8 /
1137 WOutDev
[wDevID
].Format
.wBitsPerSample
;
1138 dprintf_mciwave(stddeb
,"wodGetPosition // TIME_SAMPLES=%lu\n", lpTime
->u
.sample
);
1141 time
= WOutDev
[wDevID
].dwTotalPlayed
/
1142 (WOutDev
[wDevID
].Format
.wf
.nAvgBytesPerSec
/ 1000);
1143 lpTime
->u
.smpte
.hour
= time
/ 108000;
1144 time
-= lpTime
->u
.smpte
.hour
* 108000;
1145 lpTime
->u
.smpte
.min
= time
/ 1800;
1146 time
-= lpTime
->u
.smpte
.min
* 1800;
1147 lpTime
->u
.smpte
.sec
= time
/ 30;
1148 time
-= lpTime
->u
.smpte
.sec
* 30;
1149 lpTime
->u
.smpte
.frame
= time
;
1150 lpTime
->u
.smpte
.fps
= 30;
1151 dprintf_mciwave(stddeb
,
1152 "wodGetPosition // TIME_SMPTE=%02u:%02u:%02u:%02u\n",
1153 lpTime
->u
.smpte
.hour
, lpTime
->u
.smpte
.min
,
1154 lpTime
->u
.smpte
.sec
, lpTime
->u
.smpte
.frame
);
1157 dprintf_mciwave(stddeb
,"wodGetPosition() format not supported ! use TIME_MS !\n");
1158 lpTime
->wType
= TIME_MS
;
1160 lpTime
->u
.ms
= WOutDev
[wDevID
].dwTotalPlayed
/
1161 (WOutDev
[wDevID
].Format
.wf
.nAvgBytesPerSec
/ 1000);
1162 dprintf_mciwave(stddeb
,"wodGetPosition // TIME_MS=%lu\n", lpTime
->u
.ms
);
1165 return MMSYSERR_NOERROR
;
1168 /**************************************************************************
1169 * wodGetVolume [internal]
1171 static DWORD
wodGetVolume(WORD wDevID
, LPDWORD lpdwVol
)
1174 int volume
, left
, right
;
1175 dprintf_mciwave(stddeb
,"wodGetVolume(%u, %p);\n", wDevID
, lpdwVol
);
1176 if (lpdwVol
== NULL
) return MMSYSERR_NOTENABLED
;
1177 if ((mixer
= open(MIXER_DEV
, O_RDONLY
)) < 0) {
1178 dprintf_mciwave(stddeb
, "Linux 'wodGetVolume' // mixer device not available !\n");
1179 return MMSYSERR_NOTENABLED
;
1181 if (ioctl(mixer
, SOUND_MIXER_READ_PCM
, &volume
) == -1) {
1182 dprintf_mciwave(stddeb
,"Linux 'wodGetVolume' // unable read mixer !\n");
1183 return MMSYSERR_NOTENABLED
;
1186 left
= volume
& 0x7F;
1187 right
= (volume
>> 8) & 0x7F;
1188 dprintf_mciwave(stddeb
,"Linux 'wodGetVolume' // left=%d right=%d !\n", left
, right
);
1189 *lpdwVol
= MAKELONG(left
<< 9, right
<< 9);
1190 return MMSYSERR_NOERROR
;
1194 /**************************************************************************
1195 * wodSetVolume [internal]
1197 static DWORD
wodSetVolume(WORD wDevID
, DWORD dwParam
)
1201 dprintf_mciwave(stddeb
,"wodSetVolume(%u, %08lX);\n", wDevID
, dwParam
);
1202 volume
= (LOWORD(dwParam
) >> 9 & 0x7F) +
1203 ((HIWORD(dwParam
) >> 9 & 0x7F) << 8);
1204 if ((mixer
= open(MIXER_DEV
, O_WRONLY
)) < 0) {
1205 dprintf_mciwave(stddeb
, "Linux 'wodSetVolume' // mixer device not available !\n");
1206 return MMSYSERR_NOTENABLED
;
1208 if (ioctl(mixer
, SOUND_MIXER_WRITE_PCM
, &volume
) == -1) {
1209 dprintf_mciwave(stddeb
,"Linux 'wodSetVolume' // unable set mixer !\n");
1210 return MMSYSERR_NOTENABLED
;
1213 return MMSYSERR_NOERROR
;
1216 #endif /* linux || __FreeBSD__*/
1218 /**************************************************************************
1219 * wodMessage [sample driver]
1221 DWORD
wodMessage(WORD wDevID
, WORD wMsg
, DWORD dwUser
,
1222 DWORD dwParam1
, DWORD dwParam2
)
1224 dprintf_mciwave(stddeb
,"wodMessage(%u, %04X, %08lX, %08lX, %08lX);\n",
1225 wDevID
, wMsg
, dwUser
, dwParam1
, dwParam2
);
1226 #if defined(linux) || defined(__FreeBSD__)
1229 return wodOpen(wDevID
, (LPWAVEOPENDESC
)dwParam1
, dwParam2
);
1231 return wodClose(wDevID
);
1233 return wodWrite(wDevID
, (LPWAVEHDR
)dwParam1
, dwParam2
);
1235 return MMSYSERR_NOTSUPPORTED
;
1237 return MMSYSERR_NOTSUPPORTED
;
1239 return wodGetPosition(wDevID
, (LPMMTIME16
)dwParam1
, dwParam2
);
1240 case WODM_BREAKLOOP
:
1241 return MMSYSERR_NOTSUPPORTED
;
1243 return wodPrepare(wDevID
, (LPWAVEHDR
)dwParam1
, dwParam2
);
1244 case WODM_UNPREPARE
:
1245 return wodUnprepare(wDevID
, (LPWAVEHDR
)dwParam1
, dwParam2
);
1246 case WODM_GETDEVCAPS
:
1247 return wodGetDevCaps(wDevID
,(LPWAVEOUTCAPS16
)dwParam1
,dwParam2
);
1248 case WODM_GETNUMDEVS
:
1251 return MMSYSERR_NOTSUPPORTED
;
1253 return MMSYSERR_NOTSUPPORTED
;
1254 case WODM_GETPLAYBACKRATE
:
1255 return MMSYSERR_NOTSUPPORTED
;
1256 case WODM_SETPLAYBACKRATE
:
1257 return MMSYSERR_NOTSUPPORTED
;
1258 case WODM_GETVOLUME
:
1259 return wodGetVolume(wDevID
, (LPDWORD
)dwParam1
);
1260 case WODM_SETVOLUME
:
1261 return wodSetVolume(wDevID
, dwParam1
);
1263 return wodRestart(wDevID
);
1265 return wodReset(wDevID
);
1267 dprintf_mciwave(stddeb
,"wodMessage // unknown message !\n");
1269 return MMSYSERR_NOTSUPPORTED
;
1271 return MMSYSERR_NOTENABLED
;
1276 /*-----------------------------------------------------------------------*/
1278 #if defined(linux) || defined(__FreeBSD__)
1280 /**************************************************************************
1281 * widGetDevCaps [internal]
1283 static DWORD
widGetDevCaps(WORD wDevID
, LPWAVEINCAPS16 lpCaps
, DWORD dwSize
)
1285 int audio
,smplrate
,samplesize
=16,dsp_stereo
=1,bytespersmpl
;
1287 dprintf_mciwave(stddeb
,
1288 "widGetDevCaps(%u, %p, %lu);\n", wDevID
, lpCaps
, dwSize
);
1289 if (lpCaps
== NULL
) return MMSYSERR_NOTENABLED
;
1290 if (access(SOUND_DEV
,0) != 0) return MMSYSERR_NOTENABLED
;
1291 audio
= open (SOUND_DEV
, O_RDONLY
, 0);
1292 if (audio
== -1) return MMSYSERR_ALLOCATED
;
1294 lpCaps
->wMid
= 0x0002;
1295 lpCaps
->wPid
= 0x0004;
1296 strcpy(lpCaps
->szPname
, "SB16 Wave In");
1298 lpCaps
->wMid
= 0x00FF; /* Manufac ID */
1299 lpCaps
->wPid
= 0x0001; /* Product ID */
1300 strcpy(lpCaps
->szPname
, "Linux WAVIN Driver");
1302 lpCaps
->dwFormats
= 0x00000000;
1303 lpCaps
->wChannels
= (IOCTL(audio
, SNDCTL_DSP_STEREO
, dsp_stereo
) != 0) ? 1 : 2;
1304 bytespersmpl
= (IOCTL(audio
, SNDCTL_DSP_SAMPLESIZE
, samplesize
) != 0) ? 1 : 2;
1306 if (IOCTL(audio
, SNDCTL_DSP_SPEED
, smplrate
) == 0) {
1307 lpCaps
->dwFormats
|= WAVE_FORMAT_4M08
;
1308 if (lpCaps
->wChannels
> 1)
1309 lpCaps
->dwFormats
|= WAVE_FORMAT_4S08
;
1310 if (bytespersmpl
> 1) {
1311 lpCaps
->dwFormats
|= WAVE_FORMAT_4M16
;
1312 if (lpCaps
->wChannels
> 1)
1313 lpCaps
->dwFormats
|= WAVE_FORMAT_4S16
;
1317 if (IOCTL(audio
, SNDCTL_DSP_SPEED
, smplrate
) == 0) {
1318 lpCaps
->dwFormats
|= WAVE_FORMAT_2M08
;
1319 if (lpCaps
->wChannels
> 1)
1320 lpCaps
->dwFormats
|= WAVE_FORMAT_2S08
;
1321 if (bytespersmpl
> 1) {
1322 lpCaps
->dwFormats
|= WAVE_FORMAT_2M16
;
1323 if (lpCaps
->wChannels
> 1)
1324 lpCaps
->dwFormats
|= WAVE_FORMAT_2S16
;
1328 if (IOCTL(audio
, SNDCTL_DSP_SPEED
, smplrate
) == 0) {
1329 lpCaps
->dwFormats
|= WAVE_FORMAT_1M08
;
1330 if (lpCaps
->wChannels
> 1)
1331 lpCaps
->dwFormats
|= WAVE_FORMAT_1S08
;
1332 if (bytespersmpl
> 1) {
1333 lpCaps
->dwFormats
|= WAVE_FORMAT_1M16
;
1334 if (lpCaps
->wChannels
> 1)
1335 lpCaps
->dwFormats
|= WAVE_FORMAT_1S16
;
1339 dprintf_mciwave(stddeb
,
1340 "widGetDevCaps // dwFormats = %08lX\n", lpCaps
->dwFormats
);
1341 return MMSYSERR_NOERROR
;
1345 /**************************************************************************
1346 * widOpen [internal]
1348 static DWORD
widOpen(WORD wDevID
, LPWAVEOPENDESC lpDesc
, DWORD dwFlags
)
1350 int audio
,abuf_size
,smplrate
,samplesize
,dsp_stereo
;
1351 LPWAVEFORMAT lpFormat
;
1353 dprintf_mciwave(stddeb
, "widOpen(%u, %p, %08lX);\n", wDevID
, lpDesc
, dwFlags
);
1354 if (lpDesc
== NULL
) {
1355 dprintf_mciwave(stddeb
,"Linux 'widOpen' // Invalid Parameter !\n");
1356 return MMSYSERR_INVALPARAM
;
1358 if (wDevID
>= MAX_WAVINDRV
) {
1359 dprintf_mciwave(stddeb
,"Linux 'widOpen' // MAX_WAVINDRV reached !\n");
1360 return MMSYSERR_ALLOCATED
;
1362 WInDev
[wDevID
].unixdev
= 0;
1363 if (access(SOUND_DEV
,0) != 0) return MMSYSERR_NOTENABLED
;
1364 audio
= open (SOUND_DEV
, O_RDONLY
, 0);
1366 dprintf_mciwave(stddeb
,"Linux 'widOpen' // can't open !\n");
1367 return MMSYSERR_ALLOCATED
;
1369 IOCTL(audio
, SNDCTL_DSP_GETBLKSIZE
, abuf_size
);
1370 if (abuf_size
< 1024 || abuf_size
> 65536) {
1371 if (abuf_size
== -1)
1372 dprintf_mciwave(stddeb
,"Linux 'widOpen' // IOCTL can't 'SNDCTL_DSP_GETBLKSIZE' !\n");
1374 dprintf_mciwave(stddeb
,"Linux 'widOpen' // SNDCTL_DSP_GETBLKSIZE Invalid bufsize !\n");
1375 return MMSYSERR_NOTENABLED
;
1377 WInDev
[wDevID
].wFlags
= HIWORD(dwFlags
& CALLBACK_TYPEMASK
);
1378 switch(WInDev
[wDevID
].wFlags
) {
1380 dprintf_mciwave(stddeb
,"Linux 'widOpen' // CALLBACK_NULL!\n");
1383 dprintf_mciwave(stddeb
,"Linux 'widOpen' // CALLBACK_WINDOW!\n");
1386 dprintf_mciwave(stddeb
,"Linux 'widOpen' // CALLBACK_TASK!\n");
1389 dprintf_mciwave(stddeb
,"Linux 'widOpen' // CALLBACK_FUNCTION!\n");
1392 if (WInDev
[wDevID
].lpQueueHdr
) {
1393 HeapFree(GetProcessHeap(),0,WInDev
[wDevID
].lpQueueHdr
);
1394 WInDev
[wDevID
].lpQueueHdr
= NULL
;
1396 WInDev
[wDevID
].unixdev
= audio
;
1397 WInDev
[wDevID
].bufsize
= abuf_size
;
1398 WInDev
[wDevID
].dwTotalRecorded
= 0;
1399 memcpy(&WInDev
[wDevID
].waveDesc
, lpDesc
, sizeof(WAVEOPENDESC
));
1400 lpFormat
= (LPWAVEFORMAT
) lpDesc
->lpFormat
;
1401 if (lpFormat
->wFormatTag
!= WAVE_FORMAT_PCM
) {
1402 dprintf_mciwave(stddeb
,"Linux 'widOpen' // Bad format %04X !\n",
1403 lpFormat
->wFormatTag
);
1404 return WAVERR_BADFORMAT
;
1406 memcpy(&WInDev
[wDevID
].Format
, lpFormat
, sizeof(PCMWAVEFORMAT
));
1407 WInDev
[wDevID
].Format
.wBitsPerSample
= 8; /* <-------------- */
1408 if (WInDev
[wDevID
].Format
.wf
.nChannels
== 0) return WAVERR_BADFORMAT
;
1409 if (WInDev
[wDevID
].Format
.wf
.nSamplesPerSec
== 0) return WAVERR_BADFORMAT
;
1410 if (WInDev
[wDevID
].Format
.wBitsPerSample
== 0) {
1411 WInDev
[wDevID
].Format
.wBitsPerSample
= 8 *
1412 (WInDev
[wDevID
].Format
.wf
.nAvgBytesPerSec
/
1413 WInDev
[wDevID
].Format
.wf
.nSamplesPerSec
) /
1414 WInDev
[wDevID
].Format
.wf
.nChannels
;
1416 samplesize
= WInDev
[wDevID
].Format
.wBitsPerSample
;
1417 smplrate
= WInDev
[wDevID
].Format
.wf
.nSamplesPerSec
;
1418 dsp_stereo
= (WInDev
[wDevID
].Format
.wf
.nChannels
> 1) ? TRUE
: FALSE
;
1419 IOCTL(audio
, SNDCTL_DSP_SPEED
, smplrate
);
1420 IOCTL(audio
, SNDCTL_DSP_SAMPLESIZE
, samplesize
);
1421 IOCTL(audio
, SNDCTL_DSP_STEREO
, dsp_stereo
);
1422 dprintf_mciwave(stddeb
,"Linux 'widOpen' // wBitsPerSample=%u !\n",
1423 WInDev
[wDevID
].Format
.wBitsPerSample
);
1424 dprintf_mciwave(stddeb
,"Linux 'widOpen' // nSamplesPerSec=%lu !\n",
1425 WInDev
[wDevID
].Format
.wf
.nSamplesPerSec
);
1426 dprintf_mciwave(stddeb
,"Linux 'widOpen' // nChannels=%u !\n",
1427 WInDev
[wDevID
].Format
.wf
.nChannels
);
1428 dprintf_mciwave(stddeb
,"Linux 'widOpen' // nAvgBytesPerSec=%lu\n",
1429 WInDev
[wDevID
].Format
.wf
.nAvgBytesPerSec
);
1430 if (WAVE_NotifyClient(wDevID
, WIM_OPEN
, 0L, 0L) != MMSYSERR_NOERROR
) {
1431 dprintf_mciwave(stddeb
,"Linux 'widOpen' // can't notify client !\n");
1432 return MMSYSERR_INVALPARAM
;
1434 return MMSYSERR_NOERROR
;
1437 /**************************************************************************
1438 * widClose [internal]
1440 static DWORD
widClose(WORD wDevID
)
1442 dprintf_mciwave(stddeb
,"widClose(%u);\n", wDevID
);
1443 if (wDevID
> MAX_WAVINDRV
) return MMSYSERR_INVALPARAM
;
1444 if (WInDev
[wDevID
].unixdev
== 0) {
1445 dprintf_mciwave(stddeb
,"Linux 'widClose' // can't close !\n");
1446 return MMSYSERR_NOTENABLED
;
1448 if (WInDev
[wDevID
].lpQueueHdr
!= NULL
) {
1449 dprintf_mciwave(stddeb
,"linux 'widclose' // still buffers open !\n");
1450 return WAVERR_STILLPLAYING
;
1452 close(WInDev
[wDevID
].unixdev
);
1453 WInDev
[wDevID
].unixdev
= 0;
1454 WInDev
[wDevID
].bufsize
= 0;
1455 if (WAVE_NotifyClient(wDevID
, WIM_CLOSE
, 0L, 0L) != MMSYSERR_NOERROR
) {
1456 dprintf_mciwave(stddeb
,"Linux 'widClose' // can't notify client !\n");
1457 return MMSYSERR_INVALPARAM
;
1459 return MMSYSERR_NOERROR
;
1462 /**************************************************************************
1463 * widAddBuffer [internal]
1465 static DWORD
widAddBuffer(WORD wDevID
, LPWAVEHDR lpWaveHdr
, DWORD dwSize
)
1470 dprintf_mciwave(stddeb
,
1471 "widAddBuffer(%u, %p, %08lX);\n", wDevID
, lpWaveHdr
, dwSize
);
1472 if (WInDev
[wDevID
].unixdev
== 0) {
1473 dprintf_mciwave(stddeb
,"Linux 'widAddBuffer' // can't do it !\n");
1474 return MMSYSERR_NOTENABLED
;
1476 if (!(lpWaveHdr
->dwFlags
& WHDR_PREPARED
)) {
1477 dprintf_mciwave(stddeb
, "Linux 'widAddBuffer' // never been prepared !\n");
1478 return WAVERR_UNPREPARED
;
1480 if (lpWaveHdr
->dwFlags
& WHDR_INQUEUE
) {
1481 dprintf_mciwave(stddeb
, "Linux 'widAddBuffer' // header already in use !\n");
1482 return WAVERR_STILLPLAYING
;
1484 lpWaveHdr
->dwFlags
|= WHDR_PREPARED
;
1485 lpWaveHdr
->dwFlags
|= WHDR_INQUEUE
;
1486 lpWaveHdr
->dwFlags
&= ~WHDR_DONE
;
1487 lpWaveHdr
->dwBytesRecorded
= 0;
1488 if (WInDev
[wDevID
].lpQueueHdr
== NULL
) {
1489 WInDev
[wDevID
].lpQueueHdr
= lpWaveHdr
;
1491 lpWIHdr
= WInDev
[wDevID
].lpQueueHdr
;
1492 while (lpWIHdr
->lpNext
!= NULL
) {
1493 lpWIHdr
= lpWIHdr
->lpNext
;
1496 lpWIHdr
->lpNext
= lpWaveHdr
;
1497 lpWaveHdr
->lpNext
= NULL
;
1500 dprintf_mciwave(stddeb
,
1501 "widAddBuffer // buffer added ! (now %u in queue)\n", count
);
1502 return MMSYSERR_NOERROR
;
1505 /**************************************************************************
1506 * widPrepare [internal]
1508 static DWORD
widPrepare(WORD wDevID
, LPWAVEHDR lpWaveHdr
, DWORD dwSize
)
1510 dprintf_mciwave(stddeb
,
1511 "widPrepare(%u, %p, %08lX);\n", wDevID
, lpWaveHdr
, dwSize
);
1512 if (WInDev
[wDevID
].unixdev
== 0) {
1513 dprintf_mciwave(stddeb
,"Linux 'widPrepare' // can't prepare !\n");
1514 return MMSYSERR_NOTENABLED
;
1516 if (lpWaveHdr
->dwFlags
& WHDR_INQUEUE
)
1517 return WAVERR_STILLPLAYING
;
1518 lpWaveHdr
->dwFlags
|= WHDR_PREPARED
;
1519 lpWaveHdr
->dwFlags
&= ~WHDR_INQUEUE
;
1520 lpWaveHdr
->dwFlags
&= ~WHDR_DONE
;
1521 lpWaveHdr
->dwBytesRecorded
= 0;
1522 dprintf_mciwave(stddeb
,"Linux 'widPrepare' // header prepared !\n");
1523 return MMSYSERR_NOERROR
;
1526 /**************************************************************************
1527 * widUnprepare [internal]
1529 static DWORD
widUnprepare(WORD wDevID
, LPWAVEHDR lpWaveHdr
, DWORD dwSize
)
1531 dprintf_mciwave(stddeb
,
1532 "widUnprepare(%u, %p, %08lX);\n", wDevID
, lpWaveHdr
, dwSize
);
1533 if (WInDev
[wDevID
].unixdev
== 0) {
1534 dprintf_mciwave(stddeb
,"Linux 'widUnprepare' // can't unprepare !\n");
1535 return MMSYSERR_NOTENABLED
;
1537 lpWaveHdr
->dwFlags
&= ~WHDR_PREPARED
;
1538 lpWaveHdr
->dwFlags
&= ~WHDR_INQUEUE
;
1539 lpWaveHdr
->dwFlags
|= WHDR_DONE
;
1541 dprintf_mciwave(stddeb
, "Linux 'widUnprepare' // all headers unprepared !\n");
1542 return MMSYSERR_NOERROR
;
1545 /**************************************************************************
1546 * widStart [internal]
1548 static DWORD
widStart(WORD wDevID
)
1553 LPWAVEHDR
*lpWaveHdr
;
1555 dprintf_mciwave(stddeb
,"widStart(%u);\n", wDevID
);
1556 if (WInDev
[wDevID
].unixdev
== 0) {
1557 dprintf_mciwave(stddeb
, "Linux 'widStart' // can't start recording !\n");
1558 return MMSYSERR_NOTENABLED
;
1561 lpWaveHdr
= &(WInDev
[wDevID
].lpQueueHdr
);
1562 dprintf_mciwave(stddeb
,"Linux 'widstart'// lpWaveHdr = %08lx\n",(DWORD
)lpWaveHdr
);
1563 if (!*lpWaveHdr
|| !(*lpWaveHdr
)->lpData
) {
1564 dprintf_mciwave(stddeb
,"Linux 'widStart' // never been prepared !\n");
1565 return WAVERR_UNPREPARED
;
1568 while(*lpWaveHdr
!= NULL
) {
1569 lpWIHdr
= *lpWaveHdr
;
1570 dprintf_mciwave(stddeb
,
1571 "widStart // recording buf#%u=%p size=%lu \n",
1572 count
, lpWIHdr
->lpData
, lpWIHdr
->dwBufferLength
);
1574 bytesRead
= read (WInDev
[wDevID
].unixdev
,
1576 lpWIHdr
->dwBufferLength
);
1578 perror("read from audio device");
1579 fprintf(stderr
,"bytesread = %d (%ld)\n",bytesRead
,lpWIHdr
->dwBufferLength
);
1580 lpWIHdr
->dwBytesRecorded
= bytesRead
;
1581 WInDev
[wDevID
].dwTotalRecorded
+= lpWIHdr
->dwBytesRecorded
;
1582 lpWIHdr
->dwFlags
&= ~WHDR_INQUEUE
;
1583 lpWIHdr
->dwFlags
|= WHDR_DONE
;
1585 /* FIXME: should pass segmented pointer here, do we need that?*/
1586 if (WAVE_NotifyClient(wDevID
, WIM_DATA
, (DWORD
)lpWaveHdr
, lpWIHdr
->dwBytesRecorded
) != MMSYSERR_NOERROR
) {
1587 dprintf_mciwave(stddeb
, "Linux 'widStart' // can't notify client !\n");
1588 return MMSYSERR_INVALPARAM
;
1590 /* removes the current block from the queue */
1591 *lpWaveHdr
= lpWIHdr
->lpNext
;
1594 dprintf_mciwave(stddeb
,"widStart // end of recording !\n");
1596 return MMSYSERR_NOERROR
;
1599 /**************************************************************************
1600 * widStop [internal]
1602 static DWORD
widStop(WORD wDevID
)
1604 dprintf_mciwave(stddeb
,"widStop(%u);\n", wDevID
);
1605 if (WInDev
[wDevID
].unixdev
== 0) {
1606 dprintf_mciwave(stddeb
,"Linux 'widStop' // can't stop !\n");
1607 return MMSYSERR_NOTENABLED
;
1609 return MMSYSERR_NOERROR
;
1612 /**************************************************************************
1613 * widReset [internal]
1615 static DWORD
widReset(WORD wDevID
)
1617 dprintf_mciwave(stddeb
,"widReset(%u);\n", wDevID
);
1618 if (WInDev
[wDevID
].unixdev
== 0) {
1619 dprintf_mciwave(stddeb
,"Linux 'widReset' // can't reset !\n");
1620 return MMSYSERR_NOTENABLED
;
1622 return MMSYSERR_NOERROR
;
1625 /**************************************************************************
1626 * widGetPosition [internal]
1628 static DWORD
widGetPosition(WORD wDevID
, LPMMTIME16 lpTime
, DWORD uSize
)
1632 dprintf_mciwave(stddeb
,
1633 "widGetPosition(%u, %p, %lu);\n", wDevID
, lpTime
, uSize
);
1634 if (WInDev
[wDevID
].unixdev
== 0) {
1635 dprintf_mciwave(stddeb
,"Linux 'widGetPosition' // can't get pos !\n");
1636 return MMSYSERR_NOTENABLED
;
1638 if (lpTime
== NULL
) return MMSYSERR_INVALPARAM
;
1639 dprintf_mciwave(stddeb
,"widGetPosition // wType=%04X !\n",
1641 dprintf_mciwave(stddeb
,"widGetPosition // wBitsPerSample=%u\n",
1642 WInDev
[wDevID
].Format
.wBitsPerSample
);
1643 dprintf_mciwave(stddeb
,"widGetPosition // nSamplesPerSec=%lu\n",
1644 WInDev
[wDevID
].Format
.wf
.nSamplesPerSec
);
1645 dprintf_mciwave(stddeb
,"widGetPosition // nChannels=%u\n",
1646 WInDev
[wDevID
].Format
.wf
.nChannels
);
1647 dprintf_mciwave(stddeb
,"widGetPosition // nAvgBytesPerSec=%lu\n",
1648 WInDev
[wDevID
].Format
.wf
.nAvgBytesPerSec
);
1650 switch(lpTime
->wType
) {
1652 lpTime
->u
.cb
= WInDev
[wDevID
].dwTotalRecorded
;
1653 dprintf_mciwave(stddeb
,
1654 "widGetPosition // TIME_BYTES=%lu\n", lpTime
->u
.cb
);
1657 lpTime
->u
.sample
= WInDev
[wDevID
].dwTotalRecorded
* 8 /
1658 WInDev
[wDevID
].Format
.wBitsPerSample
;
1659 dprintf_mciwave(stddeb
,
1660 "widGetPosition // TIME_SAMPLES=%lu\n",
1664 time
= WInDev
[wDevID
].dwTotalRecorded
/
1665 (WInDev
[wDevID
].Format
.wf
.nAvgBytesPerSec
/ 1000);
1666 lpTime
->u
.smpte
.hour
= time
/ 108000;
1667 time
-= lpTime
->u
.smpte
.hour
* 108000;
1668 lpTime
->u
.smpte
.min
= time
/ 1800;
1669 time
-= lpTime
->u
.smpte
.min
* 1800;
1670 lpTime
->u
.smpte
.sec
= time
/ 30;
1671 time
-= lpTime
->u
.smpte
.sec
* 30;
1672 lpTime
->u
.smpte
.frame
= time
;
1673 lpTime
->u
.smpte
.fps
= 30;
1674 dprintf_mciwave(stddeb
,"widGetPosition // TIME_SMPTE=%02u:%02u:%02u:%02u\n",
1675 lpTime
->u
.smpte
.hour
, lpTime
->u
.smpte
.min
,
1676 lpTime
->u
.smpte
.sec
, lpTime
->u
.smpte
.frame
);
1679 dprintf_mciwave(stddeb
,"widGetPosition() format not supported ! use TIME_MS !\n");
1680 lpTime
->wType
= TIME_MS
;
1682 lpTime
->u
.ms
= WInDev
[wDevID
].dwTotalRecorded
/
1683 (WInDev
[wDevID
].Format
.wf
.nAvgBytesPerSec
/ 1000);
1684 dprintf_mciwave(stddeb
,
1685 "widGetPosition // TIME_MS=%lu\n", lpTime
->u
.ms
);
1688 return MMSYSERR_NOERROR
;
1691 #endif /* linux || __FreeBSD__ */
1693 /**************************************************************************
1694 * widMessage [sample driver]
1696 DWORD
widMessage(WORD wDevID
, WORD wMsg
, DWORD dwUser
,
1697 DWORD dwParam1
, DWORD dwParam2
)
1699 dprintf_mciwave(stddeb
,"widMessage(%u, %04X, %08lX, %08lX, %08lX);\n",
1700 wDevID
, wMsg
, dwUser
, dwParam1
, dwParam2
);
1701 #if defined(linux) || defined(__FreeBSD__)
1704 return widOpen(wDevID
, (LPWAVEOPENDESC
)dwParam1
, dwParam2
);
1706 return widClose(wDevID
);
1707 case WIDM_ADDBUFFER
:
1708 return widAddBuffer(wDevID
, (LPWAVEHDR
)dwParam1
, dwParam2
);
1710 return widPrepare(wDevID
, (LPWAVEHDR
)dwParam1
, dwParam2
);
1711 case WIDM_UNPREPARE
:
1712 return widUnprepare(wDevID
, (LPWAVEHDR
)dwParam1
, dwParam2
);
1713 case WIDM_GETDEVCAPS
:
1714 return widGetDevCaps(wDevID
, (LPWAVEINCAPS16
)dwParam1
,dwParam2
);
1715 case WIDM_GETNUMDEVS
:
1718 return widGetPosition(wDevID
, (LPMMTIME16
)dwParam1
, dwParam2
);
1720 return widReset(wDevID
);
1722 return widStart(wDevID
);
1724 return widStop(wDevID
);
1726 return widStop(wDevID
);
1728 dprintf_mciwave(stddeb
,"widMessage // unknown message !\n");
1730 return MMSYSERR_NOTSUPPORTED
;
1732 return MMSYSERR_NOTENABLED
;
1737 /**************************************************************************
1738 * AUDIO_DriverProc [sample driver]
1740 LONG
WAVE_DriverProc(DWORD dwDevID
, HDRVR16 hDriv
, WORD wMsg
,
1741 DWORD dwParam1
, DWORD dwParam2
)
1743 #if defined(linux) || defined(__FreeBSD__)
1744 dprintf_mciwave(stddeb
,"WAVE_DriverProc(%08lX, %04X, %04X, %08lX, %08lX)\n",
1745 dwDevID
, hDriv
, wMsg
, dwParam1
, dwParam2
);
1759 case DRV_QUERYCONFIGURE
:
1762 MessageBox16(0, "Sample MultiMedia Linux Driver !",
1763 "MMLinux Driver", MB_OK
);
1766 return DRVCNF_RESTART
;
1768 return DRVCNF_RESTART
;
1769 case MCI_OPEN_DRIVER
:
1771 return WAVE_mciOpen(dwDevID
, dwParam1
, (LPMCI_WAVE_OPEN_PARMS16
)PTR_SEG_TO_LIN(dwParam2
));
1773 return WAVE_mciCue(dwDevID
, dwParam1
, (LPMCI_GENERIC_PARMS
)PTR_SEG_TO_LIN(dwParam2
));
1774 case MCI_CLOSE_DRIVER
:
1776 return WAVE_mciClose(dwDevID
, dwParam1
, (LPMCI_GENERIC_PARMS
)PTR_SEG_TO_LIN(dwParam2
));
1778 return WAVE_mciPlay(dwDevID
, dwParam1
, (LPMCI_PLAY_PARMS
)PTR_SEG_TO_LIN(dwParam2
));
1780 return WAVE_mciRecord(dwDevID
, dwParam1
, (LPMCI_RECORD_PARMS
)PTR_SEG_TO_LIN(dwParam2
));
1782 return WAVE_mciStop(dwDevID
, dwParam1
, (LPMCI_GENERIC_PARMS
)PTR_SEG_TO_LIN(dwParam2
));
1784 return WAVE_mciSet(dwDevID
, dwParam1
, (LPMCI_SET_PARMS
)PTR_SEG_TO_LIN(dwParam2
));
1786 return WAVE_mciPause(dwDevID
, dwParam1
, (LPMCI_GENERIC_PARMS
)PTR_SEG_TO_LIN(dwParam2
));
1788 return WAVE_mciResume(dwDevID
, dwParam1
, (LPMCI_GENERIC_PARMS
)PTR_SEG_TO_LIN(dwParam2
));
1790 return WAVE_mciStatus(dwDevID
, dwParam1
, (LPMCI_STATUS_PARMS
)PTR_SEG_TO_LIN(dwParam2
));
1791 case MCI_GETDEVCAPS
:
1792 return WAVE_mciGetDevCaps(dwDevID
, dwParam1
, (LPMCI_GETDEVCAPS_PARMS
)PTR_SEG_TO_LIN(dwParam2
));
1794 return WAVE_mciInfo(dwDevID
, dwParam1
, (LPMCI_INFO_PARMS16
)PTR_SEG_TO_LIN(dwParam2
));
1797 return MMSYSERR_NOTSUPPORTED
;
1799 return MMSYSERR_NOTSUPPORTED
;
1801 return MMSYSERR_NOTSUPPORTED
;
1803 return MMSYSERR_NOTSUPPORTED
;
1805 return MMSYSERR_NOTSUPPORTED
;
1807 return MMSYSERR_NOTSUPPORTED
;
1809 return MMSYSERR_NOTSUPPORTED
;
1811 return MMSYSERR_NOTSUPPORTED
;
1813 return MMSYSERR_NOTSUPPORTED
;
1815 return MMSYSERR_NOTSUPPORTED
;
1817 return MMSYSERR_NOTSUPPORTED
;
1819 return MMSYSERR_NOTSUPPORTED
;
1821 return MMSYSERR_NOTSUPPORTED
;
1823 return MMSYSERR_NOTSUPPORTED
;
1825 return MMSYSERR_NOTSUPPORTED
;
1827 return MMSYSERR_NOTSUPPORTED
;
1829 return MMSYSERR_NOTSUPPORTED
;
1832 return DefDriverProc(dwDevID
, hDriv
, wMsg
, dwParam1
, dwParam2
);
1835 return MMSYSERR_NOTENABLED
;