2 * Sample Wine Driver for Linux
4 * Copyright 1994 Martin Ayotte
13 #include <sys/ioctl.h>
21 #include <linux/soundcard.h>
23 #include <machine/soundcard.h>
29 #if defined(linux) || defined(__FreeBSD__)
30 #define SOUND_DEV "/dev/dsp"
31 #define MIXER_DEV "/dev/mixer"
34 #define IOCTL(a,b,c) ((-1==ioctl(a,b,&c))&&(perror("ioctl:"#b":"#c),0))
36 #define IOCTL(a,b,c) (c = ioctl(a,b,c) )
39 #define MAX_WAVOUTDRV (1)
40 #define MAX_WAVINDRV (1)
41 #define MAX_MCIWAVDRV (1)
47 WAVEOPENDESC waveDesc
;
57 DWORD bufsize
; /* Linux '/dev/dsp' give us that size */
58 WAVEOPENDESC waveDesc
;
62 DWORD dwTotalRecorded
;
66 int nUseCount
; /* Incremented for each shared open */
67 BOOL16 fShareable
; /* TRUE if first open was shareable */
68 WORD wNotifyDeviceID
; /* MCI device ID with a pending notification */
69 HANDLE16 hCallback
; /* Callback handle for pending notification */
70 HMMIO16 hFile
; /* mmio file handle open as Element */
71 MCI_WAVE_OPEN_PARMS openParms
;
72 PCMWAVEFORMAT WaveFormat
;
74 BOOL16 fInput
; /* FALSE = Output, TRUE = Input */
77 static LINUX_WAVEOUT WOutDev
[MAX_WAVOUTDRV
];
78 static LINUX_WAVEIN WInDev
[MAX_WAVOUTDRV
];
79 static LINUX_MCIWAVE MCIWavDev
[MAX_MCIWAVDRV
];
82 /**************************************************************************
83 * WAVE_NotifyClient [internal]
85 static DWORD
WAVE_NotifyClient(UINT16 wDevID
, WORD wMsg
,
86 DWORD dwParam1
, DWORD dwParam2
)
88 dprintf_mciwave(stddeb
,"WAVE_NotifyClient // wDevID = %04X wMsg = %d dwParm1 = %04lX dwParam2 = %04lX\n",wDevID
, wMsg
, dwParam1
, dwParam2
);
90 if (wDevID
> MAX_WAVOUTDRV
) return MCIERR_INTERNAL
;
92 if (WInDev
[wDevID
].wFlags
!= DCB_NULL
&& !DriverCallback(
93 WInDev
[wDevID
].waveDesc
.dwCallBack
, WInDev
[wDevID
].wFlags
,
94 WInDev
[wDevID
].waveDesc
.hWave
, wMsg
,
95 WInDev
[wDevID
].waveDesc
.dwInstance
, dwParam1
, dwParam2
)) {
96 dprintf_mciwave(stddeb
,"WAVE_NotifyClient // can't notify client !\n");
97 return MMSYSERR_NOERROR
;
103 /**************************************************************************
104 * WAVE_mciOpen [internal]*/
105 static DWORD
WAVE_mciOpen(UINT16 wDevID
, DWORD dwFlags
, LPMCI_WAVE_OPEN_PARMS lpParms
)
108 LPWAVEFORMAT lpFormat
;
109 LPPCMWAVEFORMAT lpWaveFormat
;
111 LPWAVEOPENDESC lpDesc
;
112 LPSTR lpstrElementName
;
116 dprintf_mciwave(stddeb
,"WAVE_mciOpen(%04X, %08lX, %p)\n",
117 wDevID
, dwFlags
, lpParms
);
118 if (lpParms
== NULL
) return MCIERR_INTERNAL
;
120 if (MCIWavDev
[wDevID
].nUseCount
> 0) {
121 /* The driver already open on this channel */
122 /* If the driver was opened shareable before and this open specifies */
123 /* shareable then increment the use count */
124 if (MCIWavDev
[wDevID
].fShareable
&& (dwFlags
& MCI_OPEN_SHAREABLE
))
125 ++MCIWavDev
[wDevID
].nUseCount
;
127 return MCIERR_MUST_USE_SHAREABLE
;
130 MCIWavDev
[wDevID
].nUseCount
= 1;
131 MCIWavDev
[wDevID
].fShareable
= dwFlags
& MCI_OPEN_SHAREABLE
;
134 MCIWavDev
[wDevID
].fInput
= FALSE
;
136 dprintf_mciwave(stddeb
,"WAVE_mciOpen // wDevID=%04X\n", wDevID
);
137 dprintf_mciwave(stddeb
,"WAVE_mciOpen // before OPEN_ELEMENT\n");
138 if (dwFlags
& MCI_OPEN_ELEMENT
) {
139 lpstrElementName
= (LPSTR
)PTR_SEG_TO_LIN(lpParms
->lpstrElementName
);
140 dprintf_mciwave(stddeb
,"WAVE_mciOpen // MCI_OPEN_ELEMENT '%s' !\n",
142 if (strlen(lpstrElementName
) > 0) {
143 strcpy(str
, lpstrElementName
);
145 MCIWavDev
[wDevID
].hFile
= mmioOpen(str
, NULL
,
146 MMIO_ALLOCBUF
| MMIO_READWRITE
| MMIO_EXCLUSIVE
);
147 if (MCIWavDev
[wDevID
].hFile
== 0) {
148 dprintf_mciwave(stddeb
,"WAVE_mciOpen // can't find file='%s' !\n", str
);
149 return MCIERR_FILE_NOT_FOUND
;
153 MCIWavDev
[wDevID
].hFile
= 0;
155 dprintf_mciwave(stddeb
,"WAVE_mciOpen // hFile=%u\n", MCIWavDev
[wDevID
].hFile
);
156 memcpy(&MCIWavDev
[wDevID
].openParms
, lpParms
, sizeof(MCI_WAVE_OPEN_PARMS
));
157 MCIWavDev
[wDevID
].wNotifyDeviceID
= lpParms
->wDeviceID
;
158 lpWaveFormat
= &MCIWavDev
[wDevID
].WaveFormat
;
159 hDesc
= USER_HEAP_ALLOC(sizeof(WAVEOPENDESC
));
160 lpDesc
= (LPWAVEOPENDESC
) USER_HEAP_LIN_ADDR(hDesc
);
163 lpWaveFormat->wf.wFormatTag = WAVE_FORMAT_PCM;
164 lpWaveFormat->wBitsPerSample = 8;
165 lpWaveFormat->wf.nChannels = 1;
166 lpWaveFormat->wf.nSamplesPerSec = 11025;
167 lpWaveFormat->wf.nAvgBytesPerSec = 11025;
168 lpWaveFormat->wf.nBlockAlign = 1;
170 if (MCIWavDev
[wDevID
].hFile
!= 0) {
173 if (mmioDescend(MCIWavDev
[wDevID
].hFile
, &ckMainRIFF
, NULL
, 0) != 0) {
174 return MCIERR_INTERNAL
;
176 dprintf_mciwave(stddeb
,
177 "WAVE_mciOpen // ParentChunk ckid=%.4s fccType=%.4s cksize=%08lX \n",
178 (LPSTR
)&ckMainRIFF
.ckid
, (LPSTR
)&ckMainRIFF
.fccType
,
180 if ((ckMainRIFF
.ckid
!= FOURCC_RIFF
) ||
181 (ckMainRIFF
.fccType
!= mmioFOURCC('W', 'A', 'V', 'E'))) {
182 return MCIERR_INTERNAL
;
184 mmckInfo
.ckid
= mmioFOURCC('f', 'm', 't', ' ');
185 if (mmioDescend(MCIWavDev
[wDevID
].hFile
, &mmckInfo
, &ckMainRIFF
, MMIO_FINDCHUNK
) != 0) {
186 return MCIERR_INTERNAL
;
188 dprintf_mciwave(stddeb
,
189 "WAVE_mciOpen // Chunk Found ckid=%.4s fccType=%.4s cksize=%08lX \n",
190 (LPSTR
)&mmckInfo
.ckid
, (LPSTR
)&mmckInfo
.fccType
,
192 if (mmioRead(MCIWavDev
[wDevID
].hFile
, (HPSTR
) lpWaveFormat
,
193 (long) sizeof(PCMWAVEFORMAT
)) != (long) sizeof(PCMWAVEFORMAT
)) {
194 return MCIERR_INTERNAL
;
196 mmckInfo
.ckid
= mmioFOURCC('d', 'a', 't', 'a');
197 if (mmioDescend(MCIWavDev
[wDevID
].hFile
, &mmckInfo
, &ckMainRIFF
, MMIO_FINDCHUNK
) != 0) {
198 return MCIERR_INTERNAL
;
200 dprintf_mciwave(stddeb
,
201 "WAVE_mciOpen // Chunk Found ckid=%.4s fccType=%.4s cksize=%08lX \n",
202 (LPSTR
)&mmckInfo
.ckid
, (LPSTR
)&mmckInfo
.fccType
,
204 dprintf_mciwave(stddeb
,
205 "WAVE_mciOpen // nChannels=%d nSamplesPerSec=%ld\n",
206 lpWaveFormat
->wf
.nChannels
, lpWaveFormat
->wf
.nSamplesPerSec
);
207 lpWaveFormat
->wBitsPerSample
= 0;
210 lpWaveFormat
->wf
.nAvgBytesPerSec
=
211 lpWaveFormat
->wf
.nSamplesPerSec
* lpWaveFormat
->wf
.nBlockAlign
;
212 hFormat
= USER_HEAP_ALLOC(sizeof(PCMWAVEFORMAT
));
213 lpFormat
= (LPWAVEFORMAT
) USER_HEAP_LIN_ADDR(hFormat
);
214 memcpy(lpFormat
, lpWaveFormat
, sizeof(PCMWAVEFORMAT
));
215 lpDesc
->lpFormat
= (LPWAVEFORMAT
)USER_HEAP_SEG_ADDR(hFormat
);
216 lpDesc
= (LPWAVEOPENDESC
) USER_HEAP_SEG_ADDR(hDesc
);
219 By default the device will be opened for output, the MCI_CUE function is there to
220 change from output to input and back
223 dwRet
= wodMessage(wDevID
, WODM_OPEN
, 0, (DWORD
)lpDesc
, CALLBACK_NULL
);
225 USER_HEAP_FREE(hFormat
);
226 USER_HEAP_FREE(hDesc
);
230 /**************************************************************************
231 * WAVE_mciCue [internal]
234 static DWORD
WAVE_mciCue(UINT16 wDevID
, DWORD dwParam
, LPMCI_GENERIC_PARMS lpParms
)
239 This routine is far from complete. At the moment only a check is done on the
240 MCI_WAVE_INPUT flag. No explicit check on MCI_WAVE_OUTPUT is done since that
243 The flags MCI_NOTIFY (and the callback parameter in lpParms) and MCI_WAIT are
249 LPWAVEOPENDESC lpDesc
;
251 dprintf_mciwave(stddeb
,"WAVE_mciCue(%u, %08lX, %p);\n", wDevID
, dwParam
, lpParms
);
253 /* always close elements ? */
255 if (MCIWavDev
[wDevID
].hFile
!= 0) {
256 mmioClose(MCIWavDev
[wDevID
].hFile
, 0);
257 MCIWavDev
[wDevID
].hFile
= 0;
260 hDesc
= USER_HEAP_ALLOC(sizeof(WAVEOPENDESC
));
261 lpDesc
= (LPWAVEOPENDESC
) USER_HEAP_LIN_ADDR(hDesc
);
263 dwRet
= MMSYSERR_NOERROR
; /* assume success */
265 if ((dwParam
& MCI_WAVE_INPUT
) && !MCIWavDev
[wDevID
].fInput
) {
267 /* FIXME this is just a hack WOutDev should be hidden here */
268 memcpy(lpDesc
,&WOutDev
[wDevID
].waveDesc
,sizeof(WAVEOPENDESC
));
270 dwRet
= wodMessage(wDevID
, WODM_CLOSE
, 0, 0L, 0L);
271 if (dwRet
!= MMSYSERR_NOERROR
) return MCIERR_INTERNAL
;
272 dwRet
= widMessage(wDevID
, WIDM_OPEN
, 0, (DWORD
)lpDesc
, CALLBACK_NULL
);
274 else if (MCIWavDev
[wDevID
].fInput
) {
275 /* FIXME this is just a hack WInDev should be hidden here */
276 memcpy(lpDesc
,&WInDev
[wDevID
].waveDesc
,sizeof(WAVEOPENDESC
));
278 dwRet
= widMessage(wDevID
, WIDM_CLOSE
, 0, 0L, 0L);
279 if (dwRet
!= MMSYSERR_NOERROR
) return MCIERR_INTERNAL
;
280 dwRet
= wodMessage(wDevID
, WODM_OPEN
, 0, (DWORD
)lpDesc
, CALLBACK_NULL
);
283 USER_HEAP_FREE(hDesc
);
288 /**************************************************************************
289 * WAVE_mciClose [internal]
291 static DWORD
WAVE_mciClose(UINT16 wDevID
, DWORD dwParam
, LPMCI_GENERIC_PARMS lpParms
)
295 dprintf_mciwave(stddeb
,
296 "WAVE_mciClose(%u, %08lX, %p);\n", wDevID
, dwParam
, lpParms
);
297 MCIWavDev
[wDevID
].nUseCount
--;
298 if (MCIWavDev
[wDevID
].nUseCount
== 0) {
299 if (MCIWavDev
[wDevID
].hFile
!= 0) {
300 mmioClose(MCIWavDev
[wDevID
].hFile
, 0);
301 MCIWavDev
[wDevID
].hFile
= 0;
303 if (MCIWavDev
[wDevID
].fInput
)
304 dwRet
= widMessage(wDevID
, WIDM_CLOSE
, 0, 0L, 0L);
306 dwRet
= wodMessage(wDevID
, WODM_CLOSE
, 0, 0L, 0L);
308 if (dwRet
!= MMSYSERR_NOERROR
) return MCIERR_INTERNAL
;
314 /**************************************************************************
315 * WAVE_mciPlay [internal]
317 static DWORD
WAVE_mciPlay(UINT16 wDevID
, DWORD dwFlags
, LPMCI_PLAY_PARMS lpParms
)
324 LPWAVEHDR lp16WaveHdr
;
327 dprintf_mciwave(stddeb
,
328 "WAVE_mciPlay(%u, %08lX, %p);\n", wDevID
, dwFlags
, lpParms
);
330 if (MCIWavDev
[wDevID
].fInput
) {
331 dprintf_mciwave(stddeb
,"WAVE_mciPlay // cannot play on input device\n");
332 return MCIERR_NONAPPLICABLE_FUNCTION
;
335 if (MCIWavDev
[wDevID
].hFile
== 0) {
336 dprintf_mciwave(stddeb
,"WAVE_mciPlay // can't find file='%08lx' !\n",
337 MCIWavDev
[wDevID
].openParms
.lpstrElementName
);
338 return MCIERR_FILE_NOT_FOUND
;
340 start
= 1; end
= 99999;
341 if (dwFlags
& MCI_FROM
) {
342 start
= lpParms
->dwFrom
;
343 dprintf_mciwave(stddeb
,
344 "WAVE_mciPlay // MCI_FROM=%d \n", start
);
346 if (dwFlags
& MCI_TO
) {
348 dprintf_mciwave(stddeb
,"WAVE_mciPlay // MCI_TO=%d \n", end
);
351 if (dwFlags
& MCI_NOTIFY
) {
352 dprintf_mciwave(stddeb
,
353 "WAVE_mciPlay // MCI_NOTIFY %08lX !\n", lpParms
->dwCallback
);
356 dprintf_mciwave(stddeb
,
357 "WAVE_mciPlay // Can't 'fork' process !\n");
362 dprintf_mciwave(stddeb
,"WAVE_mciPlay // process started ! return to caller...\n");
368 lpWaveHdr
= &MCIWavDev
[wDevID
].WaveHdr
;
369 hData
= GlobalAlloc16(GMEM_MOVEABLE
, bufsize
);
370 lpWaveHdr
->lpData
= (LPSTR
) WIN16_GlobalLock16(hData
);
371 lpWaveHdr
->dwUser
= 0L;
372 lpWaveHdr
->dwFlags
= 0L;
373 lpWaveHdr
->dwLoops
= 0L;
374 hWaveHdr
= USER_HEAP_ALLOC(sizeof(WAVEHDR
));
375 lp16WaveHdr
= (LPWAVEHDR
) USER_HEAP_SEG_ADDR(hWaveHdr
);
376 memcpy(PTR_SEG_TO_LIN(lp16WaveHdr
), lpWaveHdr
, sizeof(WAVEHDR
));
377 lpWaveHdr
= PTR_SEG_TO_LIN(lp16WaveHdr
);
378 dwRet
= wodMessage(wDevID
, WODM_PREPARE
, 0, (DWORD
)lp16WaveHdr
, sizeof(WAVEHDR
));
380 count
= mmioRead(MCIWavDev
[wDevID
].hFile
,
381 PTR_SEG_TO_LIN(lpWaveHdr
->lpData
), bufsize
);
382 dprintf_mciwave(stddeb
,"WAVE_mciPlay // mmioRead bufsize=%ld count=%ld\n", bufsize
, count
);
383 if (count
< 1) break;
384 lpWaveHdr
->dwBufferLength
= count
;
385 /* lpWaveHdr->dwBytesRecorded = count; */
386 dprintf_mciwave(stddeb
,"WAVE_mciPlay // before WODM_WRITE lpWaveHdr=%p dwBufferLength=%lu dwBytesRecorded=%lu\n",
387 lpWaveHdr
, lpWaveHdr
->dwBufferLength
, lpWaveHdr
->dwBytesRecorded
);
388 dwRet
= wodMessage(wDevID
, WODM_WRITE
, 0, (DWORD
)lp16WaveHdr
, sizeof(WAVEHDR
));
390 dwRet
= wodMessage(wDevID
, WODM_UNPREPARE
, 0, (DWORD
)lp16WaveHdr
, sizeof(WAVEHDR
));
391 if (lpWaveHdr
->lpData
!= NULL
) {
392 GlobalUnlock16(hData
);
394 lpWaveHdr
->lpData
= NULL
;
396 USER_HEAP_FREE(hWaveHdr
);
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
)
416 LPWAVEHDR lp16WaveHdr
;
419 dprintf_mciwave(stddeb
,
420 "WAVE_mciRecord(%u, %08lX, %p);\n", wDevID
, dwFlags
, lpParms
);
422 if (!MCIWavDev
[wDevID
].fInput
) {
423 dprintf_mciwave(stddeb
,"WAVE_mciPlay // cannot record on output device\n");
424 return MCIERR_NONAPPLICABLE_FUNCTION
;
427 if (MCIWavDev
[wDevID
].hFile
== 0) {
428 dprintf_mciwave(stddeb
,"WAVE_mciRecord // can't find file='%08lx' !\n",
429 MCIWavDev
[wDevID
].openParms
.lpstrElementName
);
430 return MCIERR_FILE_NOT_FOUND
;
432 start
= 1; end
= 99999;
433 if (dwFlags
& MCI_FROM
) {
434 start
= lpParms
->dwFrom
;
435 dprintf_mciwave(stddeb
,
436 "WAVE_mciRecord // MCI_FROM=%d \n", start
);
438 if (dwFlags
& MCI_TO
) {
440 dprintf_mciwave(stddeb
,"WAVE_mciRecord // MCI_TO=%d \n", end
);
443 lpWaveHdr
= &MCIWavDev
[wDevID
].WaveHdr
;
444 hData
= GlobalAlloc16(GMEM_MOVEABLE
, bufsize
);
445 lpWaveHdr
->lpData
= (LPSTR
) WIN16_GlobalLock16(hData
);
446 lpWaveHdr
->dwBufferLength
= bufsize
;
447 lpWaveHdr
->dwUser
= 0L;
448 lpWaveHdr
->dwFlags
= 0L;
449 lpWaveHdr
->dwLoops
= 0L;
450 hWaveHdr
= USER_HEAP_ALLOC(sizeof(WAVEHDR
));
451 lp16WaveHdr
= (LPWAVEHDR
) USER_HEAP_SEG_ADDR(hWaveHdr
);
452 memcpy(PTR_SEG_TO_LIN(lp16WaveHdr
), lpWaveHdr
, sizeof(WAVEHDR
));
453 lpWaveHdr
= PTR_SEG_TO_LIN(lp16WaveHdr
);
454 dwRet
= widMessage(wDevID
, WIDM_PREPARE
, 0, (DWORD
)lp16WaveHdr
, sizeof(WAVEHDR
));
455 dprintf_mciwave(stddeb
,"WAVE_mciRecord // after WIDM_PREPARE \n");
457 lpWaveHdr
->dwBytesRecorded
= 0;
458 dwRet
= widMessage(wDevID
, WIDM_START
, 0, 0L, 0L);
459 dprintf_mciwave(stddeb
,
460 "WAVE_mciRecord // after WIDM_START lpWaveHdr=%p dwBytesRecorded=%lu\n",
461 lpWaveHdr
, lpWaveHdr
->dwBytesRecorded
);
462 if (lpWaveHdr
->dwBytesRecorded
== 0) break;
464 dprintf_mciwave(stddeb
,"WAVE_mciRecord // before WIDM_UNPREPARE \n");
465 dwRet
= widMessage(wDevID
, WIDM_UNPREPARE
, 0, (DWORD
)lp16WaveHdr
, sizeof(WAVEHDR
));
466 dprintf_mciwave(stddeb
,"WAVE_mciRecord // after WIDM_UNPREPARE \n");
467 if (lpWaveHdr
->lpData
!= NULL
) {
468 GlobalUnlock16(hData
);
470 lpWaveHdr
->lpData
= NULL
;
472 USER_HEAP_FREE(hWaveHdr
);
473 if (dwFlags
& MCI_NOTIFY
) {
474 dprintf_mciwave(stddeb
,"WAVE_mciRecord // MCI_NOTIFY_SUCCESSFUL %08lX !\n", lpParms
->dwCallback
);
475 mciDriverNotify((HWND16
)LOWORD(lpParms
->dwCallback
),
476 MCIWavDev
[wDevID
].wNotifyDeviceID
, MCI_NOTIFY_SUCCESSFUL
);
482 /**************************************************************************
483 * WAVE_mciStop [internal]
485 static DWORD
WAVE_mciStop(UINT16 wDevID
, DWORD dwFlags
, LPMCI_GENERIC_PARMS lpParms
)
487 dprintf_mciwave(stddeb
,
488 "WAVE_mciStop(%u, %08lX, %p);\n", wDevID
, dwFlags
, lpParms
);
489 if (lpParms
== NULL
) return MCIERR_INTERNAL
;
494 /**************************************************************************
495 * WAVE_mciPause [internal]
497 static DWORD
WAVE_mciPause(UINT16 wDevID
, DWORD dwFlags
, LPMCI_GENERIC_PARMS lpParms
)
499 dprintf_mciwave(stddeb
,
500 "WAVE_mciPause(%u, %08lX, %p);\n", wDevID
, dwFlags
, lpParms
);
501 if (lpParms
== NULL
) return MCIERR_INTERNAL
;
506 /**************************************************************************
507 * WAVE_mciResume [internal]
509 static DWORD
WAVE_mciResume(UINT16 wDevID
, DWORD dwFlags
, LPMCI_GENERIC_PARMS lpParms
)
511 dprintf_mciwave(stddeb
,
512 "WAVE_mciResume(%u, %08lX, %p);\n", wDevID
, dwFlags
, lpParms
);
513 if (lpParms
== NULL
) return MCIERR_INTERNAL
;
518 /**************************************************************************
519 * WAVE_mciSet [internal]
521 static DWORD
WAVE_mciSet(UINT16 wDevID
, DWORD dwFlags
, LPMCI_SET_PARMS lpParms
)
523 dprintf_mciwave(stddeb
,
524 "WAVE_mciSet(%u, %08lX, %p);\n", wDevID
, dwFlags
, lpParms
);
525 if (lpParms
== NULL
) return MCIERR_INTERNAL
;
526 dprintf_mciwave(stddeb
,
527 "WAVE_mciSet // dwTimeFormat=%08lX\n", lpParms
->dwTimeFormat
);
528 dprintf_mciwave(stddeb
,
529 "WAVE_mciSet // dwAudio=%08lX\n", lpParms
->dwAudio
);
530 if (dwFlags
& MCI_SET_TIME_FORMAT
) {
531 switch (lpParms
->dwTimeFormat
) {
532 case MCI_FORMAT_MILLISECONDS
:
533 dprintf_mciwave(stddeb
, "WAVE_mciSet // MCI_FORMAT_MILLISECONDS !\n");
535 case MCI_FORMAT_BYTES
:
536 dprintf_mciwave(stddeb
, "WAVE_mciSet // MCI_FORMAT_BYTES !\n");
538 case MCI_FORMAT_SAMPLES
:
539 dprintf_mciwave(stddeb
, "WAVE_mciSet // MCI_FORMAT_SAMPLES !\n");
542 dprintf_mciwave(stddeb
, "WAVE_mciSet // bad time format !\n");
543 return MCIERR_BAD_TIME_FORMAT
;
546 if (dwFlags
& MCI_SET_VIDEO
) return MCIERR_UNSUPPORTED_FUNCTION
;
547 if (dwFlags
& MCI_SET_DOOR_OPEN
) return MCIERR_UNSUPPORTED_FUNCTION
;
548 if (dwFlags
& MCI_SET_DOOR_CLOSED
) return MCIERR_UNSUPPORTED_FUNCTION
;
549 if (dwFlags
& MCI_SET_AUDIO
)
550 dprintf_mciwave(stddeb
,"WAVE_mciSet // MCI_SET_AUDIO !\n");
551 if (dwFlags
&& MCI_SET_ON
) {
552 dprintf_mciwave(stddeb
,"WAVE_mciSet // MCI_SET_ON !\n");
553 if (dwFlags
&& MCI_SET_AUDIO_LEFT
)
554 dprintf_mciwave(stddeb
,"WAVE_mciSet // MCI_SET_AUDIO_LEFT !\n");
555 if (dwFlags
&& MCI_SET_AUDIO_RIGHT
)
556 dprintf_mciwave(stddeb
,"WAVE_mciSet // MCI_SET_AUDIO_RIGHT !\n");
558 if (dwFlags
& MCI_SET_OFF
)
559 dprintf_mciwave(stddeb
,"WAVE_mciSet // MCI_SET_OFF !\n");
560 if (dwFlags
& MCI_WAVE_INPUT
)
561 dprintf_mciwave(stddeb
,"WAVE_mciSet // MCI_WAVE_INPUT !\n");
562 if (dwFlags
& MCI_WAVE_OUTPUT
)
563 dprintf_mciwave(stddeb
,"WAVE_mciSet // MCI_WAVE_OUTPUT !\n");
564 if (dwFlags
& MCI_WAVE_SET_ANYINPUT
)
565 dprintf_mciwave(stddeb
,"WAVE_mciSet // MCI_WAVE_SET_ANYINPUT !\n");
566 if (dwFlags
& MCI_WAVE_SET_ANYOUTPUT
)
567 dprintf_mciwave(stddeb
,"WAVE_mciSet // MCI_WAVE_SET_ANYOUTPUT !\n");
568 if (dwFlags
& MCI_WAVE_SET_AVGBYTESPERSEC
)
569 dprintf_mciwave(stddeb
,
570 "WAVE_mciSet // MCI_WAVE_SET_AVGBYTESPERSEC !\n");
571 if (dwFlags
& MCI_WAVE_SET_BITSPERSAMPLE
)
572 dprintf_mciwave(stddeb
,
573 "WAVE_mciSet // MCI_WAVE_SET_BITSPERSAMPLE !\n");
574 if (dwFlags
& MCI_WAVE_SET_BLOCKALIGN
)
575 dprintf_mciwave(stddeb
,"WAVE_mciSet // MCI_WAVE_SET_BLOCKALIGN !\n");
576 if (dwFlags
& MCI_WAVE_SET_CHANNELS
)
577 dprintf_mciwave(stddeb
,"WAVE_mciSet // MCI_WAVE_SET_CHANNELS !\n");
578 if (dwFlags
& MCI_WAVE_SET_FORMATTAG
)
579 dprintf_mciwave(stddeb
,"WAVE_mciSet // MCI_WAVE_SET_FORMATTAG !\n");
580 if (dwFlags
& MCI_WAVE_SET_SAMPLESPERSEC
)
581 dprintf_mciwave(stddeb
,
582 "WAVE_mciSet // MCI_WAVE_SET_SAMPLESPERSEC !\n");
587 /**************************************************************************
588 * WAVE_mciStatus [internal]
590 static DWORD
WAVE_mciStatus(UINT16 wDevID
, DWORD dwFlags
, LPMCI_STATUS_PARMS lpParms
)
592 dprintf_mciwave(stddeb
,
593 "WAVE_mciStatus(%u, %08lX, %p);\n", wDevID
, dwFlags
, lpParms
);
594 if (lpParms
== NULL
) return MCIERR_INTERNAL
;
595 if (dwFlags
& MCI_STATUS_ITEM
) {
596 switch(lpParms
->dwItem
) {
597 case MCI_STATUS_CURRENT_TRACK
:
598 lpParms
->dwReturn
= 1;
600 case MCI_STATUS_LENGTH
:
601 lpParms
->dwReturn
= 5555;
602 if (dwFlags
& MCI_TRACK
) {
603 lpParms
->dwTrack
= 1;
604 lpParms
->dwReturn
= 2222;
607 case MCI_STATUS_MODE
:
608 lpParms
->dwReturn
= MCI_MODE_STOP
;
610 case MCI_STATUS_MEDIA_PRESENT
:
611 dprintf_mciwave(stddeb
,"WAVE_mciStatus // MCI_STATUS_MEDIA_PRESENT !\n");
612 lpParms
->dwReturn
= TRUE
;
614 case MCI_STATUS_NUMBER_OF_TRACKS
:
615 lpParms
->dwReturn
= 1;
617 case MCI_STATUS_POSITION
:
618 lpParms
->dwReturn
= 3333;
619 if (dwFlags
& MCI_STATUS_START
) {
622 if (dwFlags
& MCI_TRACK
) {
623 lpParms
->dwTrack
= 1;
624 lpParms
->dwReturn
= 777;
627 case MCI_STATUS_READY
:
628 dprintf_mciwave(stddeb
,"WAVE_mciStatus // MCI_STATUS_READY !\n");
629 lpParms
->dwReturn
= TRUE
;
631 case MCI_STATUS_TIME_FORMAT
:
632 dprintf_mciwave(stddeb
,"WAVE_mciStatus // MCI_STATUS_TIME_FORMAT !\n");
633 lpParms
->dwReturn
= MCI_FORMAT_MILLISECONDS
;
636 dprintf_mciwave(stddeb
,"WAVE_mciStatus // MCI_WAVE_INPUT !\n");
637 lpParms
->dwReturn
= 0;
639 case MCI_WAVE_OUTPUT
:
640 dprintf_mciwave(stddeb
,"WAVE_mciStatus // MCI_WAVE_OUTPUT !\n");
641 lpParms
->dwReturn
= 0;
643 case MCI_WAVE_STATUS_AVGBYTESPERSEC
:
644 dprintf_mciwave(stddeb
,"WAVE_mciStatus // MCI_WAVE_STATUS_AVGBYTESPERSEC !\n");
645 lpParms
->dwReturn
= 22050;
647 case MCI_WAVE_STATUS_BITSPERSAMPLE
:
648 dprintf_mciwave(stddeb
,"WAVE_mciStatus // MCI_WAVE_STATUS_BITSPERSAMPLE !\n");
649 lpParms
->dwReturn
= 8;
651 case MCI_WAVE_STATUS_BLOCKALIGN
:
652 dprintf_mciwave(stddeb
,"WAVE_mciStatus // MCI_WAVE_STATUS_BLOCKALIGN !\n");
653 lpParms
->dwReturn
= 1;
655 case MCI_WAVE_STATUS_CHANNELS
:
656 dprintf_mciwave(stddeb
,"WAVE_mciStatus // MCI_WAVE_STATUS_CHANNELS !\n");
657 lpParms
->dwReturn
= 1;
659 case MCI_WAVE_STATUS_FORMATTAG
:
660 dprintf_mciwave(stddeb
,"WAVE_mciStatus // MCI_WAVE_FORMATTAG !\n");
661 lpParms
->dwReturn
= WAVE_FORMAT_PCM
;
663 case MCI_WAVE_STATUS_LEVEL
:
664 dprintf_mciwave(stddeb
,"WAVE_mciStatus // MCI_WAVE_STATUS_LEVEL !\n");
665 lpParms
->dwReturn
= 0xAAAA5555;
667 case MCI_WAVE_STATUS_SAMPLESPERSEC
:
668 dprintf_mciwave(stddeb
,"WAVE_mciStatus // MCI_WAVE_STATUS_SAMPLESPERSEC !\n");
669 lpParms
->dwReturn
= 22050;
672 dprintf_mciwave(stddeb
,"WAVE_mciStatus // unknown command %08lX !\n", lpParms
->dwItem
);
673 return MCIERR_UNRECOGNIZED_COMMAND
;
676 if (dwFlags
& MCI_NOTIFY
) {
677 dprintf_mciwave(stddeb
,"WAVE_mciStatus // MCI_NOTIFY_SUCCESSFUL %08lX !\n", lpParms
->dwCallback
);
678 mciDriverNotify((HWND16
)LOWORD(lpParms
->dwCallback
),
679 MCIWavDev
[wDevID
].wNotifyDeviceID
, MCI_NOTIFY_SUCCESSFUL
);
684 /**************************************************************************
685 * WAVE_mciGetDevCaps [internal]
687 static DWORD
WAVE_mciGetDevCaps(UINT16 wDevID
, DWORD dwFlags
,
688 LPMCI_GETDEVCAPS_PARMS lpParms
)
690 dprintf_mciwave(stddeb
,
691 "WAVE_mciGetDevCaps(%u, %08lX, %p);\n", wDevID
, dwFlags
, lpParms
);
692 if (lpParms
== NULL
) return MCIERR_INTERNAL
;
693 if (dwFlags
& MCI_GETDEVCAPS_ITEM
) {
694 switch(lpParms
->dwItem
) {
695 case MCI_GETDEVCAPS_CAN_RECORD
:
696 lpParms
->dwReturn
= TRUE
;
698 case MCI_GETDEVCAPS_HAS_AUDIO
:
699 lpParms
->dwReturn
= TRUE
;
701 case MCI_GETDEVCAPS_HAS_VIDEO
:
702 lpParms
->dwReturn
= FALSE
;
704 case MCI_GETDEVCAPS_DEVICE_TYPE
:
705 lpParms
->dwReturn
= MCI_DEVTYPE_WAVEFORM_AUDIO
;
707 case MCI_GETDEVCAPS_USES_FILES
:
708 lpParms
->dwReturn
= TRUE
;
710 case MCI_GETDEVCAPS_COMPOUND_DEVICE
:
711 lpParms
->dwReturn
= TRUE
;
713 case MCI_GETDEVCAPS_CAN_EJECT
:
714 lpParms
->dwReturn
= FALSE
;
716 case MCI_GETDEVCAPS_CAN_PLAY
:
717 lpParms
->dwReturn
= TRUE
;
719 case MCI_GETDEVCAPS_CAN_SAVE
:
720 lpParms
->dwReturn
= TRUE
;
722 case MCI_WAVE_GETDEVCAPS_INPUTS
:
723 lpParms
->dwReturn
= 1;
725 case MCI_WAVE_GETDEVCAPS_OUTPUTS
:
726 lpParms
->dwReturn
= 1;
729 return MCIERR_UNRECOGNIZED_COMMAND
;
735 /**************************************************************************
736 * WAVE_mciInfo [internal]
738 static DWORD
WAVE_mciInfo(UINT16 wDevID
, DWORD dwFlags
, LPMCI_INFO_PARMS lpParms
)
740 dprintf_mciwave(stddeb
,
741 "WAVE_mciInfo(%u, %08lX, %p);\n", wDevID
, dwFlags
, lpParms
);
742 if (lpParms
== NULL
) return MCIERR_INTERNAL
;
743 lpParms
->lpstrReturn
= NULL
;
745 case MCI_INFO_PRODUCT
:
746 lpParms
->lpstrReturn
= "Linux Sound System 0.5";
749 lpParms
->lpstrReturn
=
750 (LPSTR
)MCIWavDev
[wDevID
].openParms
.lpstrElementName
;
753 lpParms
->lpstrReturn
= "Linux Sound System 0.5";
755 case MCI_WAVE_OUTPUT
:
756 lpParms
->lpstrReturn
= "Linux Sound System 0.5";
759 return MCIERR_UNRECOGNIZED_COMMAND
;
761 if (lpParms
->lpstrReturn
!= NULL
)
762 lpParms
->dwRetSize
= strlen(lpParms
->lpstrReturn
);
764 lpParms
->dwRetSize
= 0;
769 /*-----------------------------------------------------------------------*/
772 /**************************************************************************
773 * wodGetDevCaps [internal]
775 static DWORD
wodGetDevCaps(WORD wDevID
, LPWAVEOUTCAPS lpCaps
, DWORD dwSize
)
782 dprintf_mciwave(stddeb
,
783 "wodGetDevCaps(%u, %p, %lu);\n", wDevID
, lpCaps
, dwSize
);
784 if (lpCaps
== NULL
) return MMSYSERR_NOTENABLED
;
785 if (access(SOUND_DEV
,0) != 0) return MMSYSERR_NOTENABLED
;
786 audio
= open (SOUND_DEV
, O_WRONLY
, 0);
787 if (audio
== -1) return MMSYSERR_ALLOCATED
;
789 lpCaps
->wMid
= 0x0002;
790 lpCaps
->wPid
= 0x0104;
791 strcpy(lpCaps
->szPname
, "SB16 Wave Out");
793 lpCaps
->wMid
= 0x00FF; /* Manufac ID */
794 lpCaps
->wPid
= 0x0001; /* Product ID */
795 strcpy(lpCaps
->szPname
, "Linux WAVOUT Driver");
797 lpCaps
->dwFormats
= 0x00000000;
798 lpCaps
->dwSupport
= WAVECAPS_VOLUME
;
799 lpCaps
->wChannels
= (IOCTL(audio
, SNDCTL_DSP_STEREO
, dsp_stereo
) != 0) ? 1 : 2;
800 if (lpCaps
->wChannels
> 1) lpCaps
->dwSupport
|= WAVECAPS_LRVOLUME
;
801 bytespersmpl
= (IOCTL(audio
, SNDCTL_DSP_SAMPLESIZE
, samplesize
) != 0) ? 1 : 2;
803 if (IOCTL(audio
, SNDCTL_DSP_SPEED
, smplrate
) == 0) {
804 lpCaps
->dwFormats
|= WAVE_FORMAT_4M08
;
805 if (lpCaps
->wChannels
> 1) lpCaps
->dwFormats
|= WAVE_FORMAT_4S08
;
806 if (bytespersmpl
> 1) {
807 lpCaps
->dwFormats
|= WAVE_FORMAT_4M16
;
808 if (lpCaps
->wChannels
> 1) lpCaps
->dwFormats
|= WAVE_FORMAT_4S16
;
812 if (IOCTL(audio
, SNDCTL_DSP_SPEED
, smplrate
) == 0) {
813 lpCaps
->dwFormats
|= WAVE_FORMAT_2M08
;
814 if (lpCaps
->wChannels
> 1) lpCaps
->dwFormats
|= WAVE_FORMAT_2S08
;
815 if (bytespersmpl
> 1) {
816 lpCaps
->dwFormats
|= WAVE_FORMAT_2M16
;
817 if (lpCaps
->wChannels
> 1) lpCaps
->dwFormats
|= WAVE_FORMAT_2S16
;
821 if (IOCTL(audio
, SNDCTL_DSP_SPEED
, smplrate
) == 0) {
822 lpCaps
->dwFormats
|= WAVE_FORMAT_1M08
;
823 if (lpCaps
->wChannels
> 1) lpCaps
->dwFormats
|= WAVE_FORMAT_1S08
;
824 if (bytespersmpl
> 1) {
825 lpCaps
->dwFormats
|= WAVE_FORMAT_1M16
;
826 if (lpCaps
->wChannels
> 1) lpCaps
->dwFormats
|= WAVE_FORMAT_1S16
;
830 dprintf_mciwave(stddeb
,
831 "wodGetDevCaps // dwFormats = %08lX\n", lpCaps
->dwFormats
);
832 return MMSYSERR_NOERROR
;
836 /**************************************************************************
839 static DWORD
wodOpen(WORD wDevID
, LPWAVEOPENDESC lpDesc
, DWORD dwFlags
)
846 LPWAVEFORMAT lpFormat
;
848 dprintf_mciwave(stddeb
,
849 "wodOpen(%u, %p, %08lX);\n", wDevID
, lpDesc
, dwFlags
);
850 if (lpDesc
== NULL
) {
851 dprintf_mciwave(stddeb
,"Linux 'wodOpen' // Invalid Parameter !\n");
852 return MMSYSERR_INVALPARAM
;
854 if (wDevID
>= MAX_WAVOUTDRV
) {
855 dprintf_mciwave(stddeb
,"Linux 'wodOpen' // MAX_WAVOUTDRV reached !\n");
856 return MMSYSERR_ALLOCATED
;
858 WOutDev
[wDevID
].unixdev
= 0;
859 if (access(SOUND_DEV
,0) != 0) return MMSYSERR_NOTENABLED
;
860 audio
= open (SOUND_DEV
, O_WRONLY
, 0);
862 dprintf_mciwave(stddeb
,"Linux 'wodOpen' // can't open !\n");
863 return MMSYSERR_ALLOCATED
;
865 IOCTL(audio
, SNDCTL_DSP_GETBLKSIZE
, abuf_size
);
866 if (abuf_size
< 1024 || abuf_size
> 65536) {
868 dprintf_mciwave(stddeb
,"Linux 'wodOpen' // IOCTL can't 'SNDCTL_DSP_GETBLKSIZE' !\n");
870 dprintf_mciwave(stddeb
,"Linux 'wodOpen' // SNDCTL_DSP_GETBLKSIZE Invalid bufsize !\n");
871 return MMSYSERR_NOTENABLED
;
873 WOutDev
[wDevID
].wFlags
= HIWORD(dwFlags
& CALLBACK_TYPEMASK
);
874 switch(WOutDev
[wDevID
].wFlags
) {
876 dprintf_mciwave(stddeb
, "Linux 'wodOpen' // CALLBACK_NULL !\n");
879 dprintf_mciwave(stddeb
, "Linux 'wodOpen' // CALLBACK_WINDOW !\n");
882 dprintf_mciwave(stddeb
, "Linux 'wodOpen' // CALLBACK_TASK !\n");
885 dprintf_mciwave(stddeb
, "Linux 'wodOpen' // CALLBACK_FUNCTION !\n");
888 WOutDev
[wDevID
].lpQueueHdr
= NULL
;
889 WOutDev
[wDevID
].unixdev
= audio
;
890 WOutDev
[wDevID
].dwTotalPlayed
= 0;
891 WOutDev
[wDevID
].bufsize
= abuf_size
;
892 memcpy(&WOutDev
[wDevID
].waveDesc
, lpDesc
, sizeof(WAVEOPENDESC
));
893 dprintf_mciwave(stddeb
,"Linux 'wodOpen' // lpDesc->lpFormat = %p\n",lpDesc
->lpFormat
);
894 lpFormat
= (LPWAVEFORMAT
) PTR_SEG_TO_LIN(lpDesc
->lpFormat
);
895 /* lpFormat = lpDesc->lpFormat; */
896 dprintf_mciwave(stddeb
,"Linux 'wodOpen' // lpFormat = %p\n",lpFormat
);
897 if (lpFormat
->wFormatTag
!= WAVE_FORMAT_PCM
) {
898 dprintf_mciwave(stddeb
,"Linux 'wodOpen' // Bad format %04X !\n",
899 lpFormat
->wFormatTag
);
900 dprintf_mciwave(stddeb
,"Linux 'wodOpen' // Bad nChannels %d !\n",
901 lpFormat
->nChannels
);
902 dprintf_mciwave(stddeb
,"Linux 'wodOpen' // Bad nSamplesPerSec %ld !\n",
903 lpFormat
->nSamplesPerSec
);
904 return WAVERR_BADFORMAT
;
906 memcpy(&WOutDev
[wDevID
].Format
, lpFormat
, sizeof(PCMWAVEFORMAT
));
907 if (WOutDev
[wDevID
].Format
.wf
.nChannels
== 0) return WAVERR_BADFORMAT
;
908 if (WOutDev
[wDevID
].Format
.wf
.nSamplesPerSec
== 0) return WAVERR_BADFORMAT
;
909 dprintf_mciwave(stddeb
,"Linux 'wodOpen' // wBitsPerSample=%u !\n",
910 WOutDev
[wDevID
].Format
.wBitsPerSample
);
911 if (WOutDev
[wDevID
].Format
.wBitsPerSample
== 0) {
912 WOutDev
[wDevID
].Format
.wBitsPerSample
= 8 *
913 (WOutDev
[wDevID
].Format
.wf
.nAvgBytesPerSec
/
914 WOutDev
[wDevID
].Format
.wf
.nSamplesPerSec
) /
915 WOutDev
[wDevID
].Format
.wf
.nChannels
;
917 samplesize
= WOutDev
[wDevID
].Format
.wBitsPerSample
;
918 smplrate
= WOutDev
[wDevID
].Format
.wf
.nSamplesPerSec
;
919 dsp_stereo
= (WOutDev
[wDevID
].Format
.wf
.nChannels
> 1) ? TRUE
: FALSE
;
920 IOCTL(audio
, SNDCTL_DSP_SPEED
, smplrate
);
921 IOCTL(audio
, SNDCTL_DSP_SAMPLESIZE
, samplesize
);
922 IOCTL(audio
, SNDCTL_DSP_STEREO
, dsp_stereo
);
923 dprintf_mciwave(stddeb
,"Linux 'wodOpen' // wBitsPerSample=%u !\n",
924 WOutDev
[wDevID
].Format
.wBitsPerSample
);
925 dprintf_mciwave(stddeb
,"Linux 'wodOpen' // nAvgBytesPerSec=%lu !\n",
926 WOutDev
[wDevID
].Format
.wf
.nAvgBytesPerSec
);
927 dprintf_mciwave(stddeb
,"Linux 'wodOpen' // nSamplesPerSec=%lu !\n",
928 WOutDev
[wDevID
].Format
.wf
.nSamplesPerSec
);
929 dprintf_mciwave(stddeb
,"Linux 'wodOpen' // nChannels=%u !\n",
930 WOutDev
[wDevID
].Format
.wf
.nChannels
);
931 if (WAVE_NotifyClient(wDevID
, WOM_OPEN
, 0L, 0L) != MMSYSERR_NOERROR
) {
932 dprintf_mciwave(stddeb
,"Linux 'wodOpen' // can't notify client !\n");
933 return MMSYSERR_INVALPARAM
;
935 return MMSYSERR_NOERROR
;
938 /**************************************************************************
939 * wodClose [internal]
941 static DWORD
wodClose(WORD wDevID
)
943 dprintf_mciwave(stddeb
,"wodClose(%u);\n", wDevID
);
944 if (WOutDev
[wDevID
].unixdev
== 0) {
945 dprintf_mciwave(stddeb
,"Linux 'wodClose' // can't close !\n");
946 return MMSYSERR_NOTENABLED
;
948 close(WOutDev
[wDevID
].unixdev
);
949 WOutDev
[wDevID
].unixdev
= 0;
950 WOutDev
[wDevID
].bufsize
= 0;
951 WOutDev
[wDevID
].lpQueueHdr
= NULL
;
952 if (WAVE_NotifyClient(wDevID
, WOM_CLOSE
, 0L, 0L) != MMSYSERR_NOERROR
) {
953 dprintf_mciwave(stddeb
,"Linux 'wodClose' // can't notify client !\n");
954 return MMSYSERR_INVALPARAM
;
956 return MMSYSERR_NOERROR
;
959 /**************************************************************************
960 * wodWrite [internal]
962 static DWORD
wodWrite(WORD wDevID
, LPWAVEHDR lpWaveHdr
, DWORD dwSize
)
966 dprintf_mciwave(stddeb
,"wodWrite(%u, %p, %08lX);\n", wDevID
, lpWaveHdr
, dwSize
);
967 if (WOutDev
[wDevID
].unixdev
== 0) {
968 dprintf_mciwave(stddeb
,"Linux 'wodWrite' // can't play !\n");
969 return MMSYSERR_NOTENABLED
;
971 if (lpWaveHdr
->lpData
== NULL
) return WAVERR_UNPREPARED
;
972 if (!(lpWaveHdr
->dwFlags
& WHDR_PREPARED
)) return WAVERR_UNPREPARED
;
973 if (lpWaveHdr
->dwFlags
& WHDR_INQUEUE
) return WAVERR_STILLPLAYING
;
974 lpWaveHdr
->dwFlags
&= ~WHDR_DONE
;
975 lpWaveHdr
->dwFlags
|= WHDR_INQUEUE
;
976 dprintf_mciwave(stddeb
,
977 "wodWrite() // dwBufferLength %lu !\n", lpWaveHdr
->dwBufferLength
);
978 dprintf_mciwave(stddeb
,
979 "wodWrite() // WOutDev[%u].unixdev %u !\n", wDevID
, WOutDev
[wDevID
].unixdev
);
980 lpData
= PTR_SEG_TO_LIN(lpWaveHdr
->lpData
);
981 count
= write (WOutDev
[wDevID
].unixdev
, lpData
, lpWaveHdr
->dwBufferLength
);
982 dprintf_mciwave(stddeb
,
983 "wodWrite() // write returned count %u !\n", count
);
984 if (count
!= lpWaveHdr
->dwBufferLength
) {
985 dprintf_mciwave(stddeb
,"Linux 'wodWrite' // error writting !\n");
986 return MMSYSERR_NOTENABLED
;
988 WOutDev
[wDevID
].dwTotalPlayed
+= count
;
989 lpWaveHdr
->dwFlags
&= ~WHDR_INQUEUE
;
990 lpWaveHdr
->dwFlags
|= WHDR_DONE
;
991 if (WAVE_NotifyClient(wDevID
, WOM_DONE
, 0L, 0L) != MMSYSERR_NOERROR
) {
992 dprintf_mciwave(stddeb
,"Linux 'wodWrite' // can't notify client !\n");
993 return MMSYSERR_INVALPARAM
;
995 return MMSYSERR_NOERROR
;
998 /**************************************************************************
999 * wodPrepare [internal]
1001 static DWORD
wodPrepare(WORD wDevID
, LPWAVEHDR lpWaveHdr
, DWORD dwSize
)
1003 dprintf_mciwave(stddeb
,
1004 "wodPrepare(%u, %p, %08lX);\n", wDevID
, lpWaveHdr
, dwSize
);
1005 if (WOutDev
[wDevID
].unixdev
== 0) {
1006 dprintf_mciwave(stddeb
,"Linux 'wodPrepare' // can't prepare !\n");
1007 return MMSYSERR_NOTENABLED
;
1009 /* the COOL waveeditor feels much better without this check...
1010 * someone please have a look at available documentation
1011 if (WOutDev[wDevID].lpQueueHdr != NULL) {
1012 dprintf_mciwave(stddeb,"Linux 'wodPrepare' // already prepare !\n");
1013 return MMSYSERR_NOTENABLED;
1016 WOutDev
[wDevID
].dwTotalPlayed
= 0;
1017 WOutDev
[wDevID
].lpQueueHdr
= lpWaveHdr
;
1018 if (lpWaveHdr
->dwFlags
& WHDR_INQUEUE
) return WAVERR_STILLPLAYING
;
1019 lpWaveHdr
->dwFlags
|= WHDR_PREPARED
;
1020 lpWaveHdr
->dwFlags
&= ~WHDR_DONE
;
1021 return MMSYSERR_NOERROR
;
1024 /**************************************************************************
1025 * wodUnprepare [internal]
1027 static DWORD
wodUnprepare(WORD wDevID
, LPWAVEHDR lpWaveHdr
, DWORD dwSize
)
1029 dprintf_mciwave(stddeb
,
1030 "wodUnprepare(%u, %p, %08lX);\n", wDevID
, lpWaveHdr
, dwSize
);
1031 if (WOutDev
[wDevID
].unixdev
== 0) {
1032 dprintf_mciwave(stddeb
,"Linux 'wodUnprepare' // can't unprepare !\n");
1033 return MMSYSERR_NOTENABLED
;
1035 return MMSYSERR_NOERROR
;
1038 /**************************************************************************
1039 * wodRestart [internal]
1041 static DWORD
wodRestart(WORD wDevID
)
1043 dprintf_mciwave(stddeb
,"wodRestart(%u);\n", wDevID
);
1044 if (WOutDev
[wDevID
].unixdev
== 0) {
1045 dprintf_mciwave(stddeb
,"Linux 'wodRestart' // can't restart !\n");
1046 return MMSYSERR_NOTENABLED
;
1048 return MMSYSERR_NOERROR
;
1051 /**************************************************************************
1052 * wodReset [internal]
1054 static DWORD
wodReset(WORD wDevID
)
1056 dprintf_mciwave(stddeb
,"wodReset(%u);\n", wDevID
);
1057 if (WOutDev
[wDevID
].unixdev
== 0) {
1058 dprintf_mciwave(stddeb
,"Linux 'wodReset' // can't reset !\n");
1059 return MMSYSERR_NOTENABLED
;
1061 return MMSYSERR_NOERROR
;
1065 /**************************************************************************
1066 * wodGetPosition [internal]
1068 static DWORD
wodGetPosition(WORD wDevID
, LPMMTIME lpTime
, DWORD uSize
)
1071 dprintf_mciwave(stddeb
,"wodGetPosition(%u, %p, %lu);\n", wDevID
, lpTime
, uSize
);
1072 if (WOutDev
[wDevID
].unixdev
== 0) {
1073 dprintf_mciwave(stddeb
,"Linux 'wodGetPosition' // can't get pos !\n");
1074 return MMSYSERR_NOTENABLED
;
1076 if (lpTime
== NULL
) return MMSYSERR_INVALPARAM
;
1077 switch(lpTime
->wType
) {
1079 lpTime
->u
.cb
= WOutDev
[wDevID
].dwTotalPlayed
;
1080 dprintf_mciwave(stddeb
,"wodGetPosition // TIME_BYTES=%lu\n", lpTime
->u
.cb
);
1083 dprintf_mciwave(stddeb
,"wodGetPosition // dwTotalPlayed=%lu\n",
1084 WOutDev
[wDevID
].dwTotalPlayed
);
1085 dprintf_mciwave(stddeb
,"wodGetPosition // wBitsPerSample=%u\n",
1086 WOutDev
[wDevID
].Format
.wBitsPerSample
);
1087 lpTime
->u
.sample
= WOutDev
[wDevID
].dwTotalPlayed
* 8 /
1088 WOutDev
[wDevID
].Format
.wBitsPerSample
;
1089 dprintf_mciwave(stddeb
,"wodGetPosition // TIME_SAMPLES=%lu\n", lpTime
->u
.sample
);
1092 time
= WOutDev
[wDevID
].dwTotalPlayed
/
1093 (WOutDev
[wDevID
].Format
.wf
.nAvgBytesPerSec
/ 1000);
1094 lpTime
->u
.smpte
.hour
= time
/ 108000;
1095 time
-= lpTime
->u
.smpte
.hour
* 108000;
1096 lpTime
->u
.smpte
.min
= time
/ 1800;
1097 time
-= lpTime
->u
.smpte
.min
* 1800;
1098 lpTime
->u
.smpte
.sec
= time
/ 30;
1099 time
-= lpTime
->u
.smpte
.sec
* 30;
1100 lpTime
->u
.smpte
.frame
= time
;
1101 lpTime
->u
.smpte
.fps
= 30;
1102 dprintf_mciwave(stddeb
,
1103 "wodGetPosition // TIME_SMPTE=%02u:%02u:%02u:%02u\n",
1104 lpTime
->u
.smpte
.hour
, lpTime
->u
.smpte
.min
,
1105 lpTime
->u
.smpte
.sec
, lpTime
->u
.smpte
.frame
);
1108 dprintf_mciwave(stddeb
,"wodGetPosition() format not supported ! use TIME_MS !\n");
1109 lpTime
->wType
= TIME_MS
;
1111 lpTime
->u
.ms
= WOutDev
[wDevID
].dwTotalPlayed
/
1112 (WOutDev
[wDevID
].Format
.wf
.nAvgBytesPerSec
/ 1000);
1113 dprintf_mciwave(stddeb
,"wodGetPosition // TIME_MS=%lu\n", lpTime
->u
.ms
);
1116 return MMSYSERR_NOERROR
;
1119 /**************************************************************************
1120 * wodGetVolume [internal]
1122 static DWORD
wodGetVolume(WORD wDevID
, LPDWORD lpdwVol
)
1125 int volume
, left
, right
;
1126 dprintf_mciwave(stddeb
,"wodGetVolume(%u, %p);\n", wDevID
, lpdwVol
);
1127 if (lpdwVol
== NULL
) return MMSYSERR_NOTENABLED
;
1128 if ((mixer
= open(MIXER_DEV
, O_RDONLY
)) < 0) {
1129 dprintf_mciwave(stddeb
, "Linux 'wodGetVolume' // mixer device not available !\n");
1130 return MMSYSERR_NOTENABLED
;
1132 if (ioctl(mixer
, SOUND_MIXER_READ_PCM
, &volume
) == -1) {
1133 dprintf_mciwave(stddeb
,"Linux 'wodGetVolume' // unable read mixer !\n");
1134 return MMSYSERR_NOTENABLED
;
1137 left
= volume
& 0x7F;
1138 right
= (volume
>> 8) & 0x7F;
1139 dprintf_mciwave(stddeb
,"Linux 'wodGetVolume' // left=%d right=%d !\n", left
, right
);
1140 *lpdwVol
= MAKELONG(left
<< 9, right
<< 9);
1141 return MMSYSERR_NOERROR
;
1145 /**************************************************************************
1146 * wodSetVolume [internal]
1148 static DWORD
wodSetVolume(WORD wDevID
, DWORD dwParam
)
1152 dprintf_mciwave(stddeb
,"wodSetVolume(%u, %08lX);\n", wDevID
, dwParam
);
1153 volume
= (LOWORD(dwParam
) >> 9 & 0x7F) +
1154 ((HIWORD(dwParam
) >> 9 & 0x7F) << 8);
1155 if ((mixer
= open(MIXER_DEV
, O_WRONLY
)) < 0) {
1156 dprintf_mciwave(stddeb
, "Linux 'wodSetVolume' // mixer device not available !\n");
1157 return MMSYSERR_NOTENABLED
;
1159 if (ioctl(mixer
, SOUND_MIXER_WRITE_PCM
, &volume
) == -1) {
1160 dprintf_mciwave(stddeb
,"Linux 'wodSetVolume' // unable set mixer !\n");
1161 return MMSYSERR_NOTENABLED
;
1164 return MMSYSERR_NOERROR
;
1167 #endif /* linux || __FreeBSD__*/
1169 /**************************************************************************
1170 * wodMessage [sample driver]
1172 DWORD
wodMessage(WORD wDevID
, WORD wMsg
, DWORD dwUser
,
1173 DWORD dwParam1
, DWORD dwParam2
)
1175 dprintf_mciwave(stddeb
,"wodMessage(%u, %04X, %08lX, %08lX, %08lX);\n",
1176 wDevID
, wMsg
, dwUser
, dwParam1
, dwParam2
);
1177 #if defined(linux) || defined(__FreeBSD__)
1180 return wodOpen(wDevID
, (LPWAVEOPENDESC
)PTR_SEG_TO_LIN(dwParam1
), dwParam2
);
1182 return wodClose(wDevID
);
1184 return wodWrite(wDevID
, (LPWAVEHDR
)PTR_SEG_TO_LIN(dwParam1
), dwParam2
);
1188 return wodGetPosition(wDevID
, (LPMMTIME
)PTR_SEG_TO_LIN(dwParam1
), dwParam2
);
1189 case WODM_BREAKLOOP
:
1192 return wodPrepare(wDevID
, (LPWAVEHDR
)PTR_SEG_TO_LIN(dwParam1
), dwParam2
);
1193 case WODM_UNPREPARE
:
1194 return wodUnprepare(wDevID
, (LPWAVEHDR
)PTR_SEG_TO_LIN(dwParam1
), dwParam2
);
1195 case WODM_GETDEVCAPS
:
1196 return wodGetDevCaps(wDevID
, (LPWAVEOUTCAPS
)PTR_SEG_TO_LIN(dwParam1
), dwParam2
);
1197 case WODM_GETNUMDEVS
:
1200 return MMSYSERR_NOTSUPPORTED
;
1202 return MMSYSERR_NOTSUPPORTED
;
1203 case WODM_GETPLAYBACKRATE
:
1204 return MMSYSERR_NOTSUPPORTED
;
1205 case WODM_SETPLAYBACKRATE
:
1206 return MMSYSERR_NOTSUPPORTED
;
1207 case WODM_GETVOLUME
:
1208 return wodGetVolume(wDevID
, (LPDWORD
)PTR_SEG_TO_LIN(dwParam1
));
1209 case WODM_SETVOLUME
:
1210 return wodSetVolume(wDevID
, dwParam1
);
1212 return wodRestart(wDevID
);
1214 return wodReset(wDevID
);
1216 dprintf_mciwave(stddeb
,"wodMessage // unknown message !\n");
1218 return MMSYSERR_NOTSUPPORTED
;
1220 return MMSYSERR_NOTENABLED
;
1225 /*-----------------------------------------------------------------------*/
1227 #if defined(linux) || defined(__FreeBSD__)
1229 /**************************************************************************
1230 * widGetDevCaps [internal]
1232 static DWORD
widGetDevCaps(WORD wDevID
, LPWAVEINCAPS lpCaps
, DWORD dwSize
)
1236 int samplesize
= 16;
1239 dprintf_mciwave(stddeb
,
1240 "widGetDevCaps(%u, %p, %lu);\n", wDevID
, lpCaps
, dwSize
);
1241 if (lpCaps
== NULL
) return MMSYSERR_NOTENABLED
;
1242 if (access(SOUND_DEV
,0) != 0) return MMSYSERR_NOTENABLED
;
1243 audio
= open (SOUND_DEV
, O_RDONLY
, 0);
1244 if (audio
== -1) return MMSYSERR_ALLOCATED
;
1246 lpCaps
->wMid
= 0x0002;
1247 lpCaps
->wPid
= 0x0004;
1248 strcpy(lpCaps
->szPname
, "SB16 Wave In");
1250 lpCaps
->wMid
= 0x00FF; /* Manufac ID */
1251 lpCaps
->wPid
= 0x0001; /* Product ID */
1252 strcpy(lpCaps
->szPname
, "Linux WAVIN Driver");
1254 lpCaps
->dwFormats
= 0x00000000;
1255 lpCaps
->wChannels
= (IOCTL(audio
, SNDCTL_DSP_STEREO
, dsp_stereo
) != 0) ? 1 : 2;
1256 bytespersmpl
= (IOCTL(audio
, SNDCTL_DSP_SAMPLESIZE
, samplesize
) != 0) ? 1 : 2;
1258 if (IOCTL(audio
, SNDCTL_DSP_SPEED
, smplrate
) == 0) {
1259 lpCaps
->dwFormats
|= WAVE_FORMAT_4M08
;
1260 if (lpCaps
->wChannels
> 1) lpCaps
->dwFormats
|= WAVE_FORMAT_4S08
;
1261 if (bytespersmpl
> 1) {
1262 lpCaps
->dwFormats
|= WAVE_FORMAT_4M16
;
1263 if (lpCaps
->wChannels
> 1) lpCaps
->dwFormats
|= WAVE_FORMAT_4S16
;
1267 if (IOCTL(audio
, SNDCTL_DSP_SPEED
, smplrate
) == 0) {
1268 lpCaps
->dwFormats
|= WAVE_FORMAT_2M08
;
1269 if (lpCaps
->wChannels
> 1) lpCaps
->dwFormats
|= WAVE_FORMAT_2S08
;
1270 if (bytespersmpl
> 1) {
1271 lpCaps
->dwFormats
|= WAVE_FORMAT_2M16
;
1272 if (lpCaps
->wChannels
> 1) lpCaps
->dwFormats
|= WAVE_FORMAT_2S16
;
1276 if (IOCTL(audio
, SNDCTL_DSP_SPEED
, smplrate
) == 0) {
1277 lpCaps
->dwFormats
|= WAVE_FORMAT_1M08
;
1278 if (lpCaps
->wChannels
> 1) lpCaps
->dwFormats
|= WAVE_FORMAT_1S08
;
1279 if (bytespersmpl
> 1) {
1280 lpCaps
->dwFormats
|= WAVE_FORMAT_1M16
;
1281 if (lpCaps
->wChannels
> 1) lpCaps
->dwFormats
|= WAVE_FORMAT_1S16
;
1285 dprintf_mciwave(stddeb
,
1286 "widGetDevCaps // dwFormats = %08lX\n", lpCaps
->dwFormats
);
1287 return MMSYSERR_NOERROR
;
1291 /**************************************************************************
1292 * widOpen [internal]
1294 static DWORD
widOpen(WORD wDevID
, LPWAVEOPENDESC lpDesc
, DWORD dwFlags
)
1301 LPWAVEFORMAT lpFormat
;
1302 dprintf_mciwave(stddeb
, "widOpen(%u, %p, %08lX);\n", wDevID
, lpDesc
, dwFlags
);
1303 if (lpDesc
== NULL
) {
1304 dprintf_mciwave(stddeb
,"Linux 'widOpen' // Invalid Parameter !\n");
1305 return MMSYSERR_INVALPARAM
;
1307 if (wDevID
>= MAX_WAVINDRV
) {
1308 dprintf_mciwave(stddeb
,"Linux 'widOpen' // MAX_WAVINDRV reached !\n");
1309 return MMSYSERR_ALLOCATED
;
1311 WInDev
[wDevID
].unixdev
= 0;
1312 if (access(SOUND_DEV
,0) != 0) return MMSYSERR_NOTENABLED
;
1313 audio
= open (SOUND_DEV
, O_RDONLY
, 0);
1315 dprintf_mciwave(stddeb
,"Linux 'widOpen' // can't open !\n");
1316 return MMSYSERR_ALLOCATED
;
1318 IOCTL(audio
, SNDCTL_DSP_GETBLKSIZE
, abuf_size
);
1319 if (abuf_size
< 1024 || abuf_size
> 65536) {
1320 if (abuf_size
== -1)
1321 dprintf_mciwave(stddeb
,"Linux 'widOpen' // IOCTL can't 'SNDCTL_DSP_GETBLKSIZE' !\n");
1323 dprintf_mciwave(stddeb
,"Linux 'widOpen' // SNDCTL_DSP_GETBLKSIZE Invalid bufsize !\n");
1324 return MMSYSERR_NOTENABLED
;
1326 WInDev
[wDevID
].wFlags
= HIWORD(dwFlags
& CALLBACK_TYPEMASK
);
1327 switch(WInDev
[wDevID
].wFlags
) {
1329 dprintf_mciwave(stddeb
, "Linux 'widOpen' // CALLBACK_NULL !\n");
1332 dprintf_mciwave(stddeb
, "Linux 'widOpen' // CALLBACK_WINDOW !\n");
1335 dprintf_mciwave(stddeb
, "Linux 'widOpen' // CALLBACK_TASK !\n");
1338 dprintf_mciwave(stddeb
, "Linux 'widOpen' // CALLBACK_FUNCTION !\n");
1341 WInDev
[wDevID
].lpQueueHdr
= NULL
;
1342 WInDev
[wDevID
].unixdev
= audio
;
1343 WInDev
[wDevID
].bufsize
= abuf_size
;
1344 WInDev
[wDevID
].dwTotalRecorded
= 0;
1345 memcpy(&WInDev
[wDevID
].waveDesc
, lpDesc
, sizeof(WAVEOPENDESC
));
1346 lpFormat
= (LPWAVEFORMAT
) PTR_SEG_TO_LIN(lpDesc
->lpFormat
);
1347 /* lpFormat = lpDesc->lpFormat; */
1348 if (lpFormat
->wFormatTag
!= WAVE_FORMAT_PCM
) {
1349 dprintf_mciwave(stddeb
,"Linux 'widOpen' // Bad format %04X !\n",
1350 lpFormat
->wFormatTag
);
1351 return WAVERR_BADFORMAT
;
1353 memcpy(&WInDev
[wDevID
].Format
, lpFormat
, sizeof(PCMWAVEFORMAT
));
1354 WInDev
[wDevID
].Format
.wBitsPerSample
= 8; /* <-------------- */
1355 if (WInDev
[wDevID
].Format
.wf
.nChannels
== 0) return WAVERR_BADFORMAT
;
1356 if (WInDev
[wDevID
].Format
.wf
.nSamplesPerSec
== 0) return WAVERR_BADFORMAT
;
1357 if (WInDev
[wDevID
].Format
.wBitsPerSample
== 0) {
1358 WInDev
[wDevID
].Format
.wBitsPerSample
= 8 *
1359 (WInDev
[wDevID
].Format
.wf
.nAvgBytesPerSec
/
1360 WInDev
[wDevID
].Format
.wf
.nSamplesPerSec
) /
1361 WInDev
[wDevID
].Format
.wf
.nChannels
;
1363 samplesize
= WInDev
[wDevID
].Format
.wBitsPerSample
;
1364 smplrate
= WInDev
[wDevID
].Format
.wf
.nSamplesPerSec
;
1365 dsp_stereo
= (WInDev
[wDevID
].Format
.wf
.nChannels
> 1) ? TRUE
: FALSE
;
1366 IOCTL(audio
, SNDCTL_DSP_SPEED
, smplrate
);
1367 IOCTL(audio
, SNDCTL_DSP_SAMPLESIZE
, samplesize
);
1368 IOCTL(audio
, SNDCTL_DSP_STEREO
, dsp_stereo
);
1369 dprintf_mciwave(stddeb
,"Linux 'widOpen' // wBitsPerSample=%u !\n",
1370 WInDev
[wDevID
].Format
.wBitsPerSample
);
1371 dprintf_mciwave(stddeb
,"Linux 'widOpen' // nSamplesPerSec=%lu !\n",
1372 WInDev
[wDevID
].Format
.wf
.nSamplesPerSec
);
1373 dprintf_mciwave(stddeb
,"Linux 'widOpen' // nChannels=%u !\n",
1374 WInDev
[wDevID
].Format
.wf
.nChannels
);
1375 dprintf_mciwave(stddeb
,"Linux 'widOpen' // nAvgBytesPerSec=%lu\n",
1376 WInDev
[wDevID
].Format
.wf
.nAvgBytesPerSec
);
1377 if (WAVE_NotifyClient(wDevID
, WIM_OPEN
, 0L, 0L) != MMSYSERR_NOERROR
) {
1378 dprintf_mciwave(stddeb
,"Linux 'widOpen' // can't notify client !\n");
1379 return MMSYSERR_INVALPARAM
;
1381 return MMSYSERR_NOERROR
;
1384 /**************************************************************************
1385 * widClose [internal]
1387 static DWORD
widClose(WORD wDevID
)
1389 dprintf_mciwave(stddeb
,"widClose(%u);\n", wDevID
);
1390 if (WInDev
[wDevID
].unixdev
== 0) {
1391 dprintf_mciwave(stddeb
,"Linux 'widClose' // can't close !\n");
1392 return MMSYSERR_NOTENABLED
;
1394 close(WInDev
[wDevID
].unixdev
);
1395 WInDev
[wDevID
].unixdev
= 0;
1396 WInDev
[wDevID
].bufsize
= 0;
1397 if (WAVE_NotifyClient(wDevID
, WIM_CLOSE
, 0L, 0L) != MMSYSERR_NOERROR
) {
1398 dprintf_mciwave(stddeb
,"Linux 'widClose' // can't notify client !\n");
1399 return MMSYSERR_INVALPARAM
;
1401 return MMSYSERR_NOERROR
;
1404 /**************************************************************************
1405 * widAddBuffer [internal]
1407 static DWORD
widAddBuffer(WORD wDevID
, LPWAVEHDR lpWaveHdr
, DWORD dwSize
)
1411 dprintf_mciwave(stddeb
,
1412 "widAddBuffer(%u, %p, %08lX);\n", wDevID
, lpWaveHdr
, dwSize
);
1413 if (WInDev
[wDevID
].unixdev
== 0) {
1414 dprintf_mciwave(stddeb
,"Linux 'widAddBuffer' // can't do it !\n");
1415 return MMSYSERR_NOTENABLED
;
1417 if (!(lpWaveHdr
->dwFlags
& WHDR_PREPARED
)) {
1418 dprintf_mciwave(stddeb
, "Linux 'widAddBuffer' // never been prepared !\n");
1419 return WAVERR_UNPREPARED
;
1421 if (lpWaveHdr
->dwFlags
& WHDR_INQUEUE
) {
1422 dprintf_mciwave(stddeb
, "Linux 'widAddBuffer' // header already in use !\n");
1423 return WAVERR_STILLPLAYING
;
1425 lpWaveHdr
->dwFlags
|= WHDR_PREPARED
;
1426 lpWaveHdr
->dwFlags
|= WHDR_INQUEUE
;
1427 lpWaveHdr
->dwFlags
&= ~WHDR_DONE
;
1428 lpWaveHdr
->dwBytesRecorded
= 0;
1429 if (WInDev
[wDevID
].lpQueueHdr
== NULL
) {
1430 /* begin the queue with a first header ... */
1431 WInDev
[wDevID
].lpQueueHdr
= lpWaveHdr
;
1432 WInDev
[wDevID
].dwTotalRecorded
= 0;
1435 /* added to the queue, except if it's the one just prepared ... */
1436 lpWIHdr
= WInDev
[wDevID
].lpQueueHdr
;
1437 while (lpWIHdr
->lpNext
!= NULL
) {
1438 lpWIHdr
= lpWIHdr
->lpNext
;
1441 lpWIHdr
->lpNext
= lpWaveHdr
;
1444 dprintf_mciwave(stddeb
,
1445 "widAddBuffer // buffer added ! (now %u in queue)\n", count
);
1446 return MMSYSERR_NOERROR
;
1449 /**************************************************************************
1450 * widPrepare [internal]
1452 static DWORD
widPrepare(WORD wDevID
, LPWAVEHDR lpWaveHdr
, DWORD dwSize
)
1454 dprintf_mciwave(stddeb
,
1455 "widPrepare(%u, %p, %08lX);\n", wDevID
, lpWaveHdr
, dwSize
);
1456 if (WInDev
[wDevID
].unixdev
== 0) {
1457 dprintf_mciwave(stddeb
,"Linux 'widPrepare' // can't prepare !\n");
1458 return MMSYSERR_NOTENABLED
;
1460 if (WInDev
[wDevID
].lpQueueHdr
!= NULL
) {
1461 dprintf_mciwave(stddeb
,"Linux 'widPrepare' // already prepare !\n");
1462 return WAVERR_BADFORMAT
;
1464 if (lpWaveHdr
->dwFlags
& WHDR_INQUEUE
) return WAVERR_STILLPLAYING
;
1465 lpWaveHdr
->dwFlags
|= WHDR_PREPARED
;
1466 lpWaveHdr
->dwFlags
&= ~WHDR_INQUEUE
;
1467 lpWaveHdr
->dwFlags
&= ~WHDR_DONE
;
1468 lpWaveHdr
->dwBytesRecorded
= 0;
1469 dprintf_mciwave(stddeb
,"Linux 'widPrepare' // header prepared !\n");
1470 return MMSYSERR_NOERROR
;
1473 /**************************************************************************
1474 * widUnprepare [internal]
1476 static DWORD
widUnprepare(WORD wDevID
, LPWAVEHDR lpWaveHdr
, DWORD dwSize
)
1478 dprintf_mciwave(stddeb
,
1479 "widUnprepare(%u, %p, %08lX);\n", wDevID
, lpWaveHdr
, dwSize
);
1480 if (WInDev
[wDevID
].unixdev
== 0) {
1481 dprintf_mciwave(stddeb
,"Linux 'widUnprepare' // can't unprepare !\n");
1482 return MMSYSERR_NOTENABLED
;
1484 lpWaveHdr
->dwFlags
&= ~WHDR_PREPARED
;
1485 lpWaveHdr
->dwFlags
&= ~WHDR_INQUEUE
;
1486 lpWaveHdr
->dwFlags
|= WHDR_DONE
;
1487 WInDev
[wDevID
].lpQueueHdr
= NULL
;
1488 dprintf_mciwave(stddeb
,
1489 "Linux 'widUnprepare' // all headers unprepared !\n");
1490 return MMSYSERR_NOERROR
;
1493 /**************************************************************************
1494 * widStart [internal]
1496 static DWORD
widStart(WORD wDevID
)
1500 dprintf_mciwave(stddeb
,"widStart(%u);\n", wDevID
);
1501 if (WInDev
[wDevID
].unixdev
== 0) {
1502 dprintf_mciwave(stddeb
, "Linux 'widStart' // can't start recording !\n");
1503 return MMSYSERR_NOTENABLED
;
1505 if (WInDev
[wDevID
].lpQueueHdr
== NULL
||
1506 WInDev
[wDevID
].lpQueueHdr
->lpData
== NULL
) {
1507 dprintf_mciwave(stddeb
,"Linux 'widStart' // never been prepared !\n");
1508 return WAVERR_UNPREPARED
;
1510 lpWIHdr
= WInDev
[wDevID
].lpQueueHdr
;
1511 while(lpWIHdr
!= NULL
) {
1512 lpWIHdr
->dwBufferLength
&= 0xFFFF;
1513 dprintf_mciwave(stddeb
,
1514 "widStart // recording buf#%u=%p size=%lu \n",
1515 count
, lpWIHdr
->lpData
, lpWIHdr
->dwBufferLength
);
1517 read (WInDev
[wDevID
].unixdev
,
1518 PTR_SEG_TO_LIN(lpWIHdr
->lpData
),
1519 lpWIHdr
->dwBufferLength
);
1520 lpWIHdr
->dwBytesRecorded
= lpWIHdr
->dwBufferLength
;
1521 WInDev
[wDevID
].dwTotalRecorded
+= lpWIHdr
->dwBytesRecorded
;
1522 lpWIHdr
->dwFlags
&= ~WHDR_INQUEUE
;
1523 lpWIHdr
->dwFlags
|= WHDR_DONE
;
1524 if (WAVE_NotifyClient(wDevID
, WIM_DATA
, (DWORD
)lpWIHdr
, 0L) !=
1526 dprintf_mciwave(stddeb
, "Linux 'widStart' // can't notify client !\n");
1527 return MMSYSERR_INVALPARAM
;
1529 lpWIHdr
= lpWIHdr
->lpNext
;
1532 dprintf_mciwave(stddeb
,"widStart // end of recording !\n");
1534 return MMSYSERR_NOERROR
;
1537 /**************************************************************************
1538 * widStop [internal]
1540 static DWORD
widStop(WORD wDevID
)
1542 dprintf_mciwave(stddeb
,"widStop(%u);\n", wDevID
);
1543 if (WInDev
[wDevID
].unixdev
== 0) {
1544 dprintf_mciwave(stddeb
,"Linux 'widStop' // can't stop !\n");
1545 return MMSYSERR_NOTENABLED
;
1547 return MMSYSERR_NOERROR
;
1550 /**************************************************************************
1551 * widReset [internal]
1553 static DWORD
widReset(WORD wDevID
)
1555 dprintf_mciwave(stddeb
,"widReset(%u);\n", wDevID
);
1556 if (WInDev
[wDevID
].unixdev
== 0) {
1557 dprintf_mciwave(stddeb
,"Linux 'widReset' // can't reset !\n");
1558 return MMSYSERR_NOTENABLED
;
1560 return MMSYSERR_NOERROR
;
1563 /**************************************************************************
1564 * widGetPosition [internal]
1566 static DWORD
widGetPosition(WORD wDevID
, LPMMTIME lpTime
, DWORD uSize
)
1570 dprintf_mciwave(stddeb
,
1571 "widGetPosition(%u, %p, %lu);\n", wDevID
, lpTime
, uSize
);
1572 if (WInDev
[wDevID
].unixdev
== 0) {
1573 dprintf_mciwave(stddeb
,"Linux 'widGetPosition' // can't get pos !\n");
1574 return MMSYSERR_NOTENABLED
;
1576 if (lpTime
== NULL
) return MMSYSERR_INVALPARAM
;
1577 dprintf_mciwave(stddeb
,"widGetPosition // wType=%04X !\n",
1579 dprintf_mciwave(stddeb
,"widGetPosition // wBitsPerSample=%u\n",
1580 WInDev
[wDevID
].Format
.wBitsPerSample
);
1581 dprintf_mciwave(stddeb
,"widGetPosition // nSamplesPerSec=%lu\n",
1582 WInDev
[wDevID
].Format
.wf
.nSamplesPerSec
);
1583 dprintf_mciwave(stddeb
,"widGetPosition // nChannels=%u\n",
1584 WInDev
[wDevID
].Format
.wf
.nChannels
);
1585 dprintf_mciwave(stddeb
,"widGetPosition // nAvgBytesPerSec=%lu\n",
1586 WInDev
[wDevID
].Format
.wf
.nAvgBytesPerSec
);
1588 switch(lpTime
->wType
) {
1590 lpTime
->u
.cb
= WInDev
[wDevID
].dwTotalRecorded
;
1591 dprintf_mciwave(stddeb
,
1592 "widGetPosition // TIME_BYTES=%lu\n", lpTime
->u
.cb
);
1595 lpTime
->u
.sample
= WInDev
[wDevID
].dwTotalRecorded
* 8 /
1596 WInDev
[wDevID
].Format
.wBitsPerSample
;
1597 dprintf_mciwave(stddeb
,
1598 "widGetPosition // TIME_SAMPLES=%lu\n",
1602 time
= WInDev
[wDevID
].dwTotalRecorded
/
1603 (WInDev
[wDevID
].Format
.wf
.nAvgBytesPerSec
/ 1000);
1604 lpTime
->u
.smpte
.hour
= time
/ 108000;
1605 time
-= lpTime
->u
.smpte
.hour
* 108000;
1606 lpTime
->u
.smpte
.min
= time
/ 1800;
1607 time
-= lpTime
->u
.smpte
.min
* 1800;
1608 lpTime
->u
.smpte
.sec
= time
/ 30;
1609 time
-= lpTime
->u
.smpte
.sec
* 30;
1610 lpTime
->u
.smpte
.frame
= time
;
1611 lpTime
->u
.smpte
.fps
= 30;
1612 dprintf_mciwave(stddeb
,"widGetPosition // TIME_SMPTE=%02u:%02u:%02u:%02u\n",
1613 lpTime
->u
.smpte
.hour
, lpTime
->u
.smpte
.min
,
1614 lpTime
->u
.smpte
.sec
, lpTime
->u
.smpte
.frame
);
1617 dprintf_mciwave(stddeb
,"widGetPosition() format not supported ! use TIME_MS !\n");
1618 lpTime
->wType
= TIME_MS
;
1620 lpTime
->u
.ms
= WInDev
[wDevID
].dwTotalRecorded
/
1621 (WInDev
[wDevID
].Format
.wf
.nAvgBytesPerSec
/ 1000);
1622 dprintf_mciwave(stddeb
,
1623 "widGetPosition // TIME_MS=%lu\n", lpTime
->u
.ms
);
1626 return MMSYSERR_NOERROR
;
1629 #endif /* linux || __FreeBSD__ */
1631 /**************************************************************************
1632 * widMessage [sample driver]
1634 DWORD
widMessage(WORD wDevID
, WORD wMsg
, DWORD dwUser
,
1635 DWORD dwParam1
, DWORD dwParam2
)
1637 dprintf_mciwave(stddeb
,"widMessage(%u, %04X, %08lX, %08lX, %08lX);\n",
1638 wDevID
, wMsg
, dwUser
, dwParam1
, dwParam2
);
1639 #if defined(linux) || defined(__FreeBSD__)
1642 return widOpen(wDevID
, (LPWAVEOPENDESC
)PTR_SEG_TO_LIN(dwParam1
), dwParam2
);
1644 return widClose(wDevID
);
1645 case WIDM_ADDBUFFER
:
1646 return widAddBuffer(wDevID
, (LPWAVEHDR
)PTR_SEG_TO_LIN(dwParam1
), dwParam2
);
1648 return widPrepare(wDevID
, (LPWAVEHDR
)PTR_SEG_TO_LIN(dwParam1
), dwParam2
);
1649 case WIDM_UNPREPARE
:
1650 return widUnprepare(wDevID
, (LPWAVEHDR
)PTR_SEG_TO_LIN(dwParam1
), dwParam2
);
1651 case WIDM_GETDEVCAPS
:
1652 return widGetDevCaps(wDevID
, (LPWAVEINCAPS
)PTR_SEG_TO_LIN(dwParam1
), dwParam2
);
1653 case WIDM_GETNUMDEVS
:
1656 return widGetPosition(wDevID
, (LPMMTIME
)PTR_SEG_TO_LIN(dwParam1
), dwParam2
);
1658 return widReset(wDevID
);
1660 return widStart(wDevID
);
1662 return widStop(wDevID
);
1664 dprintf_mciwave(stddeb
,"widMessage // unknown message !\n");
1666 return MMSYSERR_NOTSUPPORTED
;
1668 return MMSYSERR_NOTENABLED
;
1673 /**************************************************************************
1674 * AUDIO_DriverProc [sample driver]
1676 LONG
WAVE_DriverProc(DWORD dwDevID
, HDRVR16 hDriv
, WORD wMsg
,
1677 DWORD dwParam1
, DWORD dwParam2
)
1679 #if defined(linux) || defined(__FreeBSD__)
1680 dprintf_mciwave(stddeb
,"WAVE_DriverProc(%08lX, %04X, %04X, %08lX, %08lX)\n",
1681 dwDevID
, hDriv
, wMsg
, dwParam1
, dwParam2
);
1695 case DRV_QUERYCONFIGURE
:
1698 MessageBox16(0, "Sample MultiMedia Linux Driver !",
1699 "MMLinux Driver", MB_OK
);
1702 return DRVCNF_RESTART
;
1704 return DRVCNF_RESTART
;
1705 case MCI_OPEN_DRIVER
:
1707 return WAVE_mciOpen(dwDevID
, dwParam1
, (LPMCI_WAVE_OPEN_PARMS
)PTR_SEG_TO_LIN(dwParam2
));
1709 return WAVE_mciCue(dwDevID
, dwParam1
, (LPMCI_GENERIC_PARMS
)PTR_SEG_TO_LIN(dwParam2
));
1710 case MCI_CLOSE_DRIVER
:
1712 return WAVE_mciClose(dwDevID
, dwParam1
, (LPMCI_GENERIC_PARMS
)PTR_SEG_TO_LIN(dwParam2
));
1714 return WAVE_mciPlay(dwDevID
, dwParam1
, (LPMCI_PLAY_PARMS
)PTR_SEG_TO_LIN(dwParam2
));
1716 return WAVE_mciRecord(dwDevID
, dwParam1
, (LPMCI_RECORD_PARMS
)PTR_SEG_TO_LIN(dwParam2
));
1718 return WAVE_mciStop(dwDevID
, dwParam1
, (LPMCI_GENERIC_PARMS
)PTR_SEG_TO_LIN(dwParam2
));
1720 return WAVE_mciSet(dwDevID
, dwParam1
, (LPMCI_SET_PARMS
)PTR_SEG_TO_LIN(dwParam2
));
1722 return WAVE_mciPause(dwDevID
, dwParam1
, (LPMCI_GENERIC_PARMS
)PTR_SEG_TO_LIN(dwParam2
));
1724 return WAVE_mciResume(dwDevID
, dwParam1
, (LPMCI_GENERIC_PARMS
)PTR_SEG_TO_LIN(dwParam2
));
1726 return WAVE_mciStatus(dwDevID
, dwParam1
, (LPMCI_STATUS_PARMS
)PTR_SEG_TO_LIN(dwParam2
));
1727 case MCI_GETDEVCAPS
:
1728 return WAVE_mciGetDevCaps(dwDevID
, dwParam1
, (LPMCI_GETDEVCAPS_PARMS
)PTR_SEG_TO_LIN(dwParam2
));
1730 return WAVE_mciInfo(dwDevID
, dwParam1
, (LPMCI_INFO_PARMS
)PTR_SEG_TO_LIN(dwParam2
));
1732 return DefDriverProc(dwDevID
, hDriv
, wMsg
, dwParam1
, dwParam2
);
1735 return MMSYSERR_NOTENABLED
;