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
;
50 SEGPTR lp16QueueHdr
; /* Segmented LPWAVEHDR */
57 DWORD bufsize
; /* Linux '/dev/dsp' give us that size */
58 WAVEOPENDESC waveDesc
;
61 SEGPTR lp16QueueHdr
; /* Segmented LPWAVEHDR */
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
);
94 if (wDevID
> MAX_WAVOUTDRV
) return MCIERR_INTERNAL
;
96 if (WOutDev
[wDevID
].wFlags
!= DCB_NULL
&& !DriverCallback(
97 WOutDev
[wDevID
].waveDesc
.dwCallBack
,
98 WOutDev
[wDevID
].wFlags
,
99 WOutDev
[wDevID
].waveDesc
.hWave
,
101 WOutDev
[wDevID
].waveDesc
.dwInstance
,
104 dprintf_mciwave(stddeb
,"WAVE_NotifyClient // can't notify client !\n");
105 return MMSYSERR_NOERROR
;
112 if (wDevID
> MAX_WAVINDRV
) return MCIERR_INTERNAL
;
114 if (WInDev
[wDevID
].wFlags
!= DCB_NULL
&& !DriverCallback(
115 WInDev
[wDevID
].waveDesc
.dwCallBack
, WInDev
[wDevID
].wFlags
,
116 WInDev
[wDevID
].waveDesc
.hWave
, wMsg
,
117 WInDev
[wDevID
].waveDesc
.dwInstance
, dwParam1
, dwParam2
)) {
118 dprintf_mciwave(stddeb
,"WAVE_NotifyClient // can't notify client !\n");
119 return MMSYSERR_NOERROR
;
127 /**************************************************************************
128 * WAVE_mciOpen [internal]*/
129 static DWORD
WAVE_mciOpen(UINT16 wDevID
, DWORD dwFlags
, LPMCI_WAVE_OPEN_PARMS lpParms
)
132 LPWAVEFORMAT lpFormat
;
133 LPPCMWAVEFORMAT lpWaveFormat
;
135 LPWAVEOPENDESC lpDesc
;
136 LPSTR lpstrElementName
;
140 dprintf_mciwave(stddeb
,"WAVE_mciOpen(%04X, %08lX, %p)\n",
141 wDevID
, dwFlags
, lpParms
);
142 if (lpParms
== NULL
) return MCIERR_INTERNAL
;
144 if (MCIWavDev
[wDevID
].nUseCount
> 0) {
145 /* The driver already open on this channel */
146 /* If the driver was opened shareable before and this open specifies */
147 /* shareable then increment the use count */
148 if (MCIWavDev
[wDevID
].fShareable
&& (dwFlags
& MCI_OPEN_SHAREABLE
))
149 ++MCIWavDev
[wDevID
].nUseCount
;
151 return MCIERR_MUST_USE_SHAREABLE
;
154 MCIWavDev
[wDevID
].nUseCount
= 1;
155 MCIWavDev
[wDevID
].fShareable
= dwFlags
& MCI_OPEN_SHAREABLE
;
158 MCIWavDev
[wDevID
].fInput
= FALSE
;
160 dprintf_mciwave(stddeb
,"WAVE_mciOpen // wDevID=%04X\n", wDevID
);
161 dprintf_mciwave(stddeb
,"WAVE_mciOpen // before OPEN_ELEMENT\n");
162 if (dwFlags
& MCI_OPEN_ELEMENT
) {
163 lpstrElementName
= (LPSTR
)PTR_SEG_TO_LIN(lpParms
->lpstrElementName
);
164 dprintf_mciwave(stddeb
,"WAVE_mciOpen // MCI_OPEN_ELEMENT '%s' !\n",
166 if ( lpstrElementName
&& (strlen(lpstrElementName
) > 0)) {
167 strcpy(str
, lpstrElementName
);
169 MCIWavDev
[wDevID
].hFile
= mmioOpen(str
, NULL
,
170 MMIO_ALLOCBUF
| MMIO_READWRITE
| MMIO_EXCLUSIVE
);
171 if (MCIWavDev
[wDevID
].hFile
== 0) {
172 dprintf_mciwave(stddeb
,"WAVE_mciOpen // can't find file='%s' !\n", str
);
173 return MCIERR_FILE_NOT_FOUND
;
177 MCIWavDev
[wDevID
].hFile
= 0;
179 dprintf_mciwave(stddeb
,"WAVE_mciOpen // hFile=%u\n", MCIWavDev
[wDevID
].hFile
);
180 memcpy(&MCIWavDev
[wDevID
].openParms
, lpParms
, sizeof(MCI_WAVE_OPEN_PARMS
));
181 MCIWavDev
[wDevID
].wNotifyDeviceID
= lpParms
->wDeviceID
;
182 lpWaveFormat
= &MCIWavDev
[wDevID
].WaveFormat
;
184 hDesc
= USER_HEAP_ALLOC(sizeof(WAVEOPENDESC
));
185 if (hDesc
== 0) return MCIERR_INTERNAL
; /* is this right ? */
186 lpDesc
= (LPWAVEOPENDESC
) USER_HEAP_LIN_ADDR(hDesc
);
189 lpWaveFormat->wf.wFormatTag = WAVE_FORMAT_PCM;
190 lpWaveFormat->wBitsPerSample = 8;
191 lpWaveFormat->wf.nChannels = 1;
192 lpWaveFormat->wf.nSamplesPerSec = 11025;
193 lpWaveFormat->wf.nAvgBytesPerSec = 11025;
194 lpWaveFormat->wf.nBlockAlign = 1;
196 if (MCIWavDev
[wDevID
].hFile
!= 0) {
199 if (mmioDescend(MCIWavDev
[wDevID
].hFile
, &ckMainRIFF
, NULL
, 0) != 0) {
200 return MCIERR_INTERNAL
;
202 dprintf_mciwave(stddeb
,
203 "WAVE_mciOpen // ParentChunk ckid=%.4s fccType=%.4s cksize=%08lX \n",
204 (LPSTR
)&ckMainRIFF
.ckid
, (LPSTR
)&ckMainRIFF
.fccType
,
206 if ((ckMainRIFF
.ckid
!= FOURCC_RIFF
) ||
207 (ckMainRIFF
.fccType
!= mmioFOURCC('W', 'A', 'V', 'E'))) {
208 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
;
214 dprintf_mciwave(stddeb
,
215 "WAVE_mciOpen // Chunk Found ckid=%.4s fccType=%.4s cksize=%08lX \n",
216 (LPSTR
)&mmckInfo
.ckid
, (LPSTR
)&mmckInfo
.fccType
,
218 if (mmioRead(MCIWavDev
[wDevID
].hFile
, (HPSTR
) lpWaveFormat
,
219 (long) sizeof(PCMWAVEFORMAT
)) != (long) sizeof(PCMWAVEFORMAT
)) {
220 return MCIERR_INTERNAL
;
222 mmckInfo
.ckid
= mmioFOURCC('d', 'a', 't', 'a');
223 if (mmioDescend(MCIWavDev
[wDevID
].hFile
, &mmckInfo
, &ckMainRIFF
, MMIO_FINDCHUNK
) != 0) {
224 return MCIERR_INTERNAL
;
226 dprintf_mciwave(stddeb
,
227 "WAVE_mciOpen // Chunk Found ckid=%.4s fccType=%.4s cksize=%08lX \n",
228 (LPSTR
)&mmckInfo
.ckid
, (LPSTR
)&mmckInfo
.fccType
,
230 dprintf_mciwave(stddeb
,
231 "WAVE_mciOpen // nChannels=%d nSamplesPerSec=%ld\n",
232 lpWaveFormat
->wf
.nChannels
, lpWaveFormat
->wf
.nSamplesPerSec
);
233 lpWaveFormat
->wBitsPerSample
= 0;
236 lpWaveFormat
->wf
.nAvgBytesPerSec
=
237 lpWaveFormat
->wf
.nSamplesPerSec
* lpWaveFormat
->wf
.nBlockAlign
;
238 hFormat
= USER_HEAP_ALLOC(sizeof(PCMWAVEFORMAT
));
239 lpFormat
= (LPWAVEFORMAT
) USER_HEAP_LIN_ADDR(hFormat
);
240 memcpy(lpFormat
, lpWaveFormat
, sizeof(PCMWAVEFORMAT
));
241 lpDesc
->lpFormat
= (LPWAVEFORMAT
)USER_HEAP_SEG_ADDR(hFormat
);
242 lpDesc
= (LPWAVEOPENDESC
) USER_HEAP_SEG_ADDR(hDesc
);
245 By default the device will be opened for output, the MCI_CUE function is there to
246 change from output to input and back
249 dwRet
= wodMessage(wDevID
, WODM_OPEN
, 0, (DWORD
)lpDesc
, CALLBACK_NULL
);
251 USER_HEAP_FREE(hFormat
);
252 USER_HEAP_FREE(hDesc
);
256 /**************************************************************************
257 * WAVE_mciCue [internal]
260 static DWORD
WAVE_mciCue(UINT16 wDevID
, DWORD dwParam
, LPMCI_GENERIC_PARMS lpParms
)
265 This routine is far from complete. At the moment only a check is done on the
266 MCI_WAVE_INPUT flag. No explicit check on MCI_WAVE_OUTPUT is done since that
269 The flags MCI_NOTIFY (and the callback parameter in lpParms) and MCI_WAIT
275 LPWAVEOPENDESC lpDesc
;
277 dprintf_mciwave(stddeb
,"WAVE_mciCue(%u, %08lX, %p);\n", wDevID
, dwParam
, lpParms
);
279 /* always close elements ? */
281 if (MCIWavDev
[wDevID
].hFile
!= 0) {
282 mmioClose(MCIWavDev
[wDevID
].hFile
, 0);
283 MCIWavDev
[wDevID
].hFile
= 0;
286 hDesc
= USER_HEAP_ALLOC(sizeof(WAVEOPENDESC
));
287 lpDesc
= (LPWAVEOPENDESC
) USER_HEAP_LIN_ADDR(hDesc
);
289 dwRet
= MMSYSERR_NOERROR
; /* assume success */
291 if ((dwParam
& MCI_WAVE_INPUT
) && !MCIWavDev
[wDevID
].fInput
) {
293 /* FIXME this is just a hack WOutDev should be hidden here */
294 memcpy(lpDesc
,&WOutDev
[wDevID
].waveDesc
,sizeof(WAVEOPENDESC
));
296 dwRet
= wodMessage(wDevID
, WODM_CLOSE
, 0, 0L, 0L);
297 if (dwRet
!= MMSYSERR_NOERROR
) return MCIERR_INTERNAL
;
298 dwRet
= widMessage(wDevID
, WIDM_OPEN
, 0, (DWORD
)lpDesc
, CALLBACK_NULL
);
299 MCIWavDev
[wDevID
].fInput
= TRUE
;
301 else if (MCIWavDev
[wDevID
].fInput
) {
302 /* FIXME this is just a hack WInDev should be hidden here */
303 memcpy(lpDesc
,&WInDev
[wDevID
].waveDesc
,sizeof(WAVEOPENDESC
));
305 dwRet
= widMessage(wDevID
, WIDM_CLOSE
, 0, 0L, 0L);
306 if (dwRet
!= MMSYSERR_NOERROR
) return MCIERR_INTERNAL
;
307 dwRet
= wodMessage(wDevID
, WODM_OPEN
, 0, (DWORD
)lpDesc
, CALLBACK_NULL
);
308 MCIWavDev
[wDevID
].fInput
= FALSE
;
311 USER_HEAP_FREE(hDesc
);
316 /**************************************************************************
317 * WAVE_mciClose [internal]
319 static DWORD
WAVE_mciClose(UINT16 wDevID
, DWORD dwParam
, LPMCI_GENERIC_PARMS lpParms
)
323 dprintf_mciwave(stddeb
,
324 "WAVE_mciClose(%u, %08lX, %p);\n", wDevID
, dwParam
, lpParms
);
325 MCIWavDev
[wDevID
].nUseCount
--;
326 if (MCIWavDev
[wDevID
].nUseCount
== 0) {
327 if (MCIWavDev
[wDevID
].hFile
!= 0) {
328 mmioClose(MCIWavDev
[wDevID
].hFile
, 0);
329 MCIWavDev
[wDevID
].hFile
= 0;
331 if (MCIWavDev
[wDevID
].fInput
)
332 dwRet
= widMessage(wDevID
, WIDM_CLOSE
, 0, 0L, 0L);
334 dwRet
= wodMessage(wDevID
, WODM_CLOSE
, 0, 0L, 0L);
336 if (dwRet
!= MMSYSERR_NOERROR
) return MCIERR_INTERNAL
;
342 /**************************************************************************
343 * WAVE_mciPlay [internal]
345 static DWORD
WAVE_mciPlay(UINT16 wDevID
, DWORD dwFlags
, LPMCI_PLAY_PARMS lpParms
)
355 dprintf_mciwave(stddeb
,
356 "WAVE_mciPlay(%u, %08lX, %p);\n", wDevID
, dwFlags
, lpParms
);
358 if (MCIWavDev
[wDevID
].fInput
) {
359 dprintf_mciwave(stddeb
,"WAVE_mciPlay // cannot play on input device\n");
360 return MCIERR_NONAPPLICABLE_FUNCTION
;
363 if (MCIWavDev
[wDevID
].hFile
== 0) {
364 dprintf_mciwave(stddeb
,"WAVE_mciPlay // can't find file='%08lx' !\n",
365 MCIWavDev
[wDevID
].openParms
.lpstrElementName
);
366 return MCIERR_FILE_NOT_FOUND
;
368 start
= 1; end
= 99999;
369 if (dwFlags
& MCI_FROM
) {
370 start
= lpParms
->dwFrom
;
371 dprintf_mciwave(stddeb
,
372 "WAVE_mciPlay // MCI_FROM=%d \n", start
);
374 if (dwFlags
& MCI_TO
) {
376 dprintf_mciwave(stddeb
,"WAVE_mciPlay // MCI_TO=%d \n", end
);
379 if (dwFlags
& MCI_NOTIFY
) {
380 dprintf_mciwave(stddeb
,
381 "WAVE_mciPlay // MCI_NOTIFY %08lX !\n", lpParms
->dwCallback
);
384 dprintf_mciwave(stddeb
,
385 "WAVE_mciPlay // Can't 'fork' process !\n");
390 dprintf_mciwave(stddeb
,"WAVE_mciPlay // process started ! return to caller...\n");
396 lpWaveHdr
= &MCIWavDev
[wDevID
].WaveHdr
;
397 hData
= GlobalAlloc16(GMEM_MOVEABLE
, bufsize
);
398 lpWaveHdr
->lpData
= (LPSTR
) WIN16_GlobalLock16(hData
);
399 lpWaveHdr
->dwUser
= 0L;
400 lpWaveHdr
->dwFlags
= 0L;
401 lpWaveHdr
->dwLoops
= 0L;
402 hWaveHdr
= USER_HEAP_ALLOC(sizeof(WAVEHDR
));
403 lp16WaveHdr
= USER_HEAP_SEG_ADDR(hWaveHdr
);
404 memcpy(PTR_SEG_TO_LIN(lp16WaveHdr
), lpWaveHdr
, sizeof(WAVEHDR
));
405 lpWaveHdr
= PTR_SEG_TO_LIN(lp16WaveHdr
);
406 dwRet
= wodMessage(wDevID
, WODM_PREPARE
, 0, lp16WaveHdr
, sizeof(WAVEHDR
));
408 count
= mmioRead(MCIWavDev
[wDevID
].hFile
,
409 PTR_SEG_TO_LIN(lpWaveHdr
->lpData
), bufsize
);
410 dprintf_mciwave(stddeb
,"WAVE_mciPlay // mmioRead bufsize=%ld count=%ld\n", bufsize
, count
);
411 if (count
< 1) break;
412 lpWaveHdr
->dwBufferLength
= count
;
413 /* lpWaveHdr->dwBytesRecorded = count; */
414 dprintf_mciwave(stddeb
,"WAVE_mciPlay // before WODM_WRITE lpWaveHdr=%p dwBufferLength=%lu dwBytesRecorded=%lu\n",
415 lpWaveHdr
, lpWaveHdr
->dwBufferLength
, lpWaveHdr
->dwBytesRecorded
);
416 dwRet
= wodMessage(wDevID
, WODM_WRITE
, 0, lp16WaveHdr
, sizeof(WAVEHDR
));
418 dwRet
= wodMessage(wDevID
, WODM_UNPREPARE
, 0, lp16WaveHdr
, sizeof(WAVEHDR
));
419 if (lpWaveHdr
->lpData
!= NULL
) {
420 GlobalUnlock16(hData
);
422 lpWaveHdr
->lpData
= NULL
;
424 USER_HEAP_FREE(hWaveHdr
);
425 if (dwFlags
& MCI_NOTIFY
) {
426 dprintf_mciwave(stddeb
,"WAVE_mciPlay // MCI_NOTIFY_SUCCESSFUL %08lX !\n", lpParms
->dwCallback
);
427 mciDriverNotify((HWND16
)LOWORD(lpParms
->dwCallback
),
428 MCIWavDev
[wDevID
].wNotifyDeviceID
, MCI_NOTIFY_SUCCESSFUL
);
434 /**************************************************************************
435 * WAVE_mciRecord [internal]
437 static DWORD
WAVE_mciRecord(UINT16 wDevID
, DWORD dwFlags
, LPMCI_RECORD_PARMS lpParms
)
447 dprintf_mciwave(stddeb
,
448 "WAVE_mciRecord(%u, %08lX, %p);\n", wDevID
, dwFlags
, lpParms
);
450 if (!MCIWavDev
[wDevID
].fInput
) {
451 dprintf_mciwave(stddeb
,"WAVE_mciPlay // cannot record on output device\n");
452 return MCIERR_NONAPPLICABLE_FUNCTION
;
455 if (MCIWavDev
[wDevID
].hFile
== 0) {
456 dprintf_mciwave(stddeb
,"WAVE_mciRecord // can't find file='%08lx' !\n",
457 MCIWavDev
[wDevID
].openParms
.lpstrElementName
);
458 return MCIERR_FILE_NOT_FOUND
;
460 start
= 1; end
= 99999;
461 if (dwFlags
& MCI_FROM
) {
462 start
= lpParms
->dwFrom
;
463 dprintf_mciwave(stddeb
,
464 "WAVE_mciRecord // MCI_FROM=%d \n", start
);
466 if (dwFlags
& MCI_TO
) {
468 dprintf_mciwave(stddeb
,"WAVE_mciRecord // MCI_TO=%d \n", end
);
471 lpWaveHdr
= &MCIWavDev
[wDevID
].WaveHdr
;
472 hData
= GlobalAlloc16(GMEM_MOVEABLE
, bufsize
);
473 lpWaveHdr
->lpData
= (LPSTR
) WIN16_GlobalLock16(hData
);
474 lpWaveHdr
->dwBufferLength
= bufsize
;
475 lpWaveHdr
->dwUser
= 0L;
476 lpWaveHdr
->dwFlags
= 0L;
477 lpWaveHdr
->dwLoops
= 0L;
478 hWaveHdr
= USER_HEAP_ALLOC(sizeof(WAVEHDR
));
479 lp16WaveHdr
= USER_HEAP_SEG_ADDR(hWaveHdr
);
480 memcpy(PTR_SEG_TO_LIN(lp16WaveHdr
), lpWaveHdr
, sizeof(WAVEHDR
));
481 lpWaveHdr
= PTR_SEG_TO_LIN(lp16WaveHdr
);
482 dwRet
= widMessage(wDevID
, WIDM_PREPARE
, 0, (DWORD
)lp16WaveHdr
, sizeof(WAVEHDR
));
483 dprintf_mciwave(stddeb
,"WAVE_mciRecord // after WIDM_PREPARE \n");
485 lpWaveHdr
->dwBytesRecorded
= 0;
486 dwRet
= widMessage(wDevID
, WIDM_START
, 0, 0L, 0L);
487 dprintf_mciwave(stddeb
,
488 "WAVE_mciRecord // after WIDM_START lpWaveHdr=%p dwBytesRecorded=%lu\n",
489 lpWaveHdr
, lpWaveHdr
->dwBytesRecorded
);
490 if (lpWaveHdr
->dwBytesRecorded
== 0) break;
492 dprintf_mciwave(stddeb
,"WAVE_mciRecord // before WIDM_UNPREPARE \n");
493 dwRet
= widMessage(wDevID
, WIDM_UNPREPARE
, 0, (DWORD
)lp16WaveHdr
, sizeof(WAVEHDR
));
494 dprintf_mciwave(stddeb
,"WAVE_mciRecord // after WIDM_UNPREPARE \n");
495 if (lpWaveHdr
->lpData
!= NULL
) {
496 GlobalUnlock16(hData
);
498 lpWaveHdr
->lpData
= NULL
;
500 USER_HEAP_FREE(hWaveHdr
);
501 if (dwFlags
& MCI_NOTIFY
) {
502 dprintf_mciwave(stddeb
,"WAVE_mciRecord // MCI_NOTIFY_SUCCESSFUL %08lX !\n", lpParms
->dwCallback
);
503 mciDriverNotify((HWND16
)LOWORD(lpParms
->dwCallback
),
504 MCIWavDev
[wDevID
].wNotifyDeviceID
, MCI_NOTIFY_SUCCESSFUL
);
510 /**************************************************************************
511 * WAVE_mciStop [internal]
513 static DWORD
WAVE_mciStop(UINT16 wDevID
, DWORD dwFlags
, LPMCI_GENERIC_PARMS lpParms
)
517 dprintf_mciwave(stddeb
,
518 "WAVE_mciStop(%u, %08lX, %p);\n", wDevID
, dwFlags
, lpParms
);
519 if (lpParms
== NULL
) return MCIERR_INTERNAL
;
520 if (MCIWavDev
[wDevID
].fInput
)
521 dwRet
= widMessage(wDevID
, WIDM_STOP
, 0, dwFlags
, (DWORD
)lpParms
);
523 dwRet
= wodMessage(wDevID
, WODM_STOP
, 0, dwFlags
, (DWORD
)lpParms
);
529 /**************************************************************************
530 * WAVE_mciPause [internal]
532 static DWORD
WAVE_mciPause(UINT16 wDevID
, DWORD dwFlags
, LPMCI_GENERIC_PARMS lpParms
)
536 dprintf_mciwave(stddeb
,
537 "WAVE_mciPause(%u, %08lX, %p);\n", wDevID
, dwFlags
, lpParms
);
538 if (lpParms
== NULL
) return MCIERR_INTERNAL
;
539 if (MCIWavDev
[wDevID
].fInput
)
540 dwRet
= widMessage(wDevID
, WIDM_PAUSE
, 0, dwFlags
, (DWORD
)lpParms
);
542 dwRet
= wodMessage(wDevID
, WODM_PAUSE
, 0, dwFlags
, (DWORD
)lpParms
);
548 /**************************************************************************
549 * WAVE_mciResume [internal]
551 static DWORD
WAVE_mciResume(UINT16 wDevID
, DWORD dwFlags
, LPMCI_GENERIC_PARMS lpParms
)
553 dprintf_mciwave(stddeb
,
554 "WAVE_mciResume(%u, %08lX, %p);\n", wDevID
, dwFlags
, lpParms
);
555 if (lpParms
== NULL
) return MCIERR_INTERNAL
;
560 /**************************************************************************
561 * WAVE_mciSet [internal]
563 static DWORD
WAVE_mciSet(UINT16 wDevID
, DWORD dwFlags
, LPMCI_SET_PARMS lpParms
)
565 dprintf_mciwave(stddeb
,
566 "WAVE_mciSet(%u, %08lX, %p);\n", wDevID
, dwFlags
, lpParms
);
567 if (lpParms
== NULL
) return MCIERR_INTERNAL
;
568 dprintf_mciwave(stddeb
,
569 "WAVE_mciSet // dwTimeFormat=%08lX\n", lpParms
->dwTimeFormat
);
570 dprintf_mciwave(stddeb
,
571 "WAVE_mciSet // dwAudio=%08lX\n", lpParms
->dwAudio
);
572 if (dwFlags
& MCI_SET_TIME_FORMAT
) {
573 switch (lpParms
->dwTimeFormat
) {
574 case MCI_FORMAT_MILLISECONDS
:
575 dprintf_mciwave(stddeb
, "WAVE_mciSet // MCI_FORMAT_MILLISECONDS !\n");
577 case MCI_FORMAT_BYTES
:
578 dprintf_mciwave(stddeb
, "WAVE_mciSet // MCI_FORMAT_BYTES !\n");
580 case MCI_FORMAT_SAMPLES
:
581 dprintf_mciwave(stddeb
, "WAVE_mciSet // MCI_FORMAT_SAMPLES !\n");
584 dprintf_mciwave(stddeb
, "WAVE_mciSet // bad time format !\n");
585 return MCIERR_BAD_TIME_FORMAT
;
588 if (dwFlags
& MCI_SET_VIDEO
) return MCIERR_UNSUPPORTED_FUNCTION
;
589 if (dwFlags
& MCI_SET_DOOR_OPEN
) return MCIERR_UNSUPPORTED_FUNCTION
;
590 if (dwFlags
& MCI_SET_DOOR_CLOSED
) return MCIERR_UNSUPPORTED_FUNCTION
;
591 if (dwFlags
& MCI_SET_AUDIO
)
592 dprintf_mciwave(stddeb
,"WAVE_mciSet // MCI_SET_AUDIO !\n");
593 if (dwFlags
&& MCI_SET_ON
) {
594 dprintf_mciwave(stddeb
,"WAVE_mciSet // MCI_SET_ON !\n");
595 if (dwFlags
&& MCI_SET_AUDIO_LEFT
)
596 dprintf_mciwave(stddeb
,"WAVE_mciSet // MCI_SET_AUDIO_LEFT !\n");
597 if (dwFlags
&& MCI_SET_AUDIO_RIGHT
)
598 dprintf_mciwave(stddeb
,"WAVE_mciSet // MCI_SET_AUDIO_RIGHT !\n");
600 if (dwFlags
& MCI_SET_OFF
)
601 dprintf_mciwave(stddeb
,"WAVE_mciSet // MCI_SET_OFF !\n");
602 if (dwFlags
& MCI_WAVE_INPUT
)
603 dprintf_mciwave(stddeb
,"WAVE_mciSet // MCI_WAVE_INPUT !\n");
604 if (dwFlags
& MCI_WAVE_OUTPUT
)
605 dprintf_mciwave(stddeb
,"WAVE_mciSet // MCI_WAVE_OUTPUT !\n");
606 if (dwFlags
& MCI_WAVE_SET_ANYINPUT
)
607 dprintf_mciwave(stddeb
,"WAVE_mciSet // MCI_WAVE_SET_ANYINPUT !\n");
608 if (dwFlags
& MCI_WAVE_SET_ANYOUTPUT
)
609 dprintf_mciwave(stddeb
,"WAVE_mciSet // MCI_WAVE_SET_ANYOUTPUT !\n");
610 if (dwFlags
& MCI_WAVE_SET_AVGBYTESPERSEC
)
611 dprintf_mciwave(stddeb
,
612 "WAVE_mciSet // MCI_WAVE_SET_AVGBYTESPERSEC !\n");
613 if (dwFlags
& MCI_WAVE_SET_BITSPERSAMPLE
)
614 dprintf_mciwave(stddeb
,
615 "WAVE_mciSet // MCI_WAVE_SET_BITSPERSAMPLE !\n");
616 if (dwFlags
& MCI_WAVE_SET_BLOCKALIGN
)
617 dprintf_mciwave(stddeb
,"WAVE_mciSet // MCI_WAVE_SET_BLOCKALIGN !\n");
618 if (dwFlags
& MCI_WAVE_SET_CHANNELS
)
619 dprintf_mciwave(stddeb
,"WAVE_mciSet // MCI_WAVE_SET_CHANNELS !\n");
620 if (dwFlags
& MCI_WAVE_SET_FORMATTAG
)
621 dprintf_mciwave(stddeb
,"WAVE_mciSet // MCI_WAVE_SET_FORMATTAG !\n");
622 if (dwFlags
& MCI_WAVE_SET_SAMPLESPERSEC
)
623 dprintf_mciwave(stddeb
,
624 "WAVE_mciSet // MCI_WAVE_SET_SAMPLESPERSEC !\n");
629 /**************************************************************************
630 * WAVE_mciStatus [internal]
632 static DWORD
WAVE_mciStatus(UINT16 wDevID
, DWORD dwFlags
, LPMCI_STATUS_PARMS lpParms
)
634 dprintf_mciwave(stddeb
,
635 "WAVE_mciStatus(%u, %08lX, %p);\n", wDevID
, dwFlags
, lpParms
);
636 if (lpParms
== NULL
) return MCIERR_INTERNAL
;
637 if (dwFlags
& MCI_STATUS_ITEM
) {
638 switch(lpParms
->dwItem
) {
639 case MCI_STATUS_CURRENT_TRACK
:
640 lpParms
->dwReturn
= 1;
642 case MCI_STATUS_LENGTH
:
643 lpParms
->dwReturn
= 5555;
644 if (dwFlags
& MCI_TRACK
) {
645 lpParms
->dwTrack
= 1;
646 lpParms
->dwReturn
= 2222;
649 case MCI_STATUS_MODE
:
650 lpParms
->dwReturn
= MCI_MODE_STOP
;
652 case MCI_STATUS_MEDIA_PRESENT
:
653 dprintf_mciwave(stddeb
,"WAVE_mciStatus // MCI_STATUS_MEDIA_PRESENT !\n");
654 lpParms
->dwReturn
= TRUE
;
656 case MCI_STATUS_NUMBER_OF_TRACKS
:
657 lpParms
->dwReturn
= 1;
659 case MCI_STATUS_POSITION
:
660 lpParms
->dwReturn
= 3333;
661 if (dwFlags
& MCI_STATUS_START
) {
664 if (dwFlags
& MCI_TRACK
) {
665 lpParms
->dwTrack
= 1;
666 lpParms
->dwReturn
= 777;
669 case MCI_STATUS_READY
:
670 dprintf_mciwave(stddeb
,"WAVE_mciStatus // MCI_STATUS_READY !\n");
671 lpParms
->dwReturn
= TRUE
;
673 case MCI_STATUS_TIME_FORMAT
:
674 dprintf_mciwave(stddeb
,"WAVE_mciStatus // MCI_STATUS_TIME_FORMAT !\n");
675 lpParms
->dwReturn
= MCI_FORMAT_MILLISECONDS
;
678 dprintf_mciwave(stddeb
,"WAVE_mciStatus // MCI_WAVE_INPUT !\n");
679 lpParms
->dwReturn
= 0;
681 case MCI_WAVE_OUTPUT
:
682 dprintf_mciwave(stddeb
,"WAVE_mciStatus // MCI_WAVE_OUTPUT !\n");
683 lpParms
->dwReturn
= 0;
685 case MCI_WAVE_STATUS_AVGBYTESPERSEC
:
686 dprintf_mciwave(stddeb
,"WAVE_mciStatus // MCI_WAVE_STATUS_AVGBYTESPERSEC !\n");
687 lpParms
->dwReturn
= 22050;
689 case MCI_WAVE_STATUS_BITSPERSAMPLE
:
690 dprintf_mciwave(stddeb
,"WAVE_mciStatus // MCI_WAVE_STATUS_BITSPERSAMPLE !\n");
691 lpParms
->dwReturn
= 8;
693 case MCI_WAVE_STATUS_BLOCKALIGN
:
694 dprintf_mciwave(stddeb
,"WAVE_mciStatus // MCI_WAVE_STATUS_BLOCKALIGN !\n");
695 lpParms
->dwReturn
= 1;
697 case MCI_WAVE_STATUS_CHANNELS
:
698 dprintf_mciwave(stddeb
,"WAVE_mciStatus // MCI_WAVE_STATUS_CHANNELS !\n");
699 lpParms
->dwReturn
= 1;
701 case MCI_WAVE_STATUS_FORMATTAG
:
702 dprintf_mciwave(stddeb
,"WAVE_mciStatus // MCI_WAVE_FORMATTAG !\n");
703 lpParms
->dwReturn
= WAVE_FORMAT_PCM
;
705 case MCI_WAVE_STATUS_LEVEL
:
706 dprintf_mciwave(stddeb
,"WAVE_mciStatus // MCI_WAVE_STATUS_LEVEL !\n");
707 lpParms
->dwReturn
= 0xAAAA5555;
709 case MCI_WAVE_STATUS_SAMPLESPERSEC
:
710 dprintf_mciwave(stddeb
,"WAVE_mciStatus // MCI_WAVE_STATUS_SAMPLESPERSEC !\n");
711 lpParms
->dwReturn
= 22050;
714 dprintf_mciwave(stddeb
,"WAVE_mciStatus // unknown command %08lX !\n", lpParms
->dwItem
);
715 return MCIERR_UNRECOGNIZED_COMMAND
;
718 if (dwFlags
& MCI_NOTIFY
) {
719 dprintf_mciwave(stddeb
,"WAVE_mciStatus // MCI_NOTIFY_SUCCESSFUL %08lX !\n", lpParms
->dwCallback
);
720 mciDriverNotify((HWND16
)LOWORD(lpParms
->dwCallback
),
721 MCIWavDev
[wDevID
].wNotifyDeviceID
, MCI_NOTIFY_SUCCESSFUL
);
726 /**************************************************************************
727 * WAVE_mciGetDevCaps [internal]
729 static DWORD
WAVE_mciGetDevCaps(UINT16 wDevID
, DWORD dwFlags
,
730 LPMCI_GETDEVCAPS_PARMS lpParms
)
732 dprintf_mciwave(stddeb
,
733 "WAVE_mciGetDevCaps(%u, %08lX, %p);\n", wDevID
, dwFlags
, lpParms
);
734 if (lpParms
== NULL
) return MCIERR_INTERNAL
;
735 if (dwFlags
& MCI_GETDEVCAPS_ITEM
) {
736 switch(lpParms
->dwItem
) {
737 case MCI_GETDEVCAPS_CAN_RECORD
:
738 lpParms
->dwReturn
= TRUE
;
740 case MCI_GETDEVCAPS_HAS_AUDIO
:
741 lpParms
->dwReturn
= TRUE
;
743 case MCI_GETDEVCAPS_HAS_VIDEO
:
744 lpParms
->dwReturn
= FALSE
;
746 case MCI_GETDEVCAPS_DEVICE_TYPE
:
747 lpParms
->dwReturn
= MCI_DEVTYPE_WAVEFORM_AUDIO
;
749 case MCI_GETDEVCAPS_USES_FILES
:
750 lpParms
->dwReturn
= TRUE
;
752 case MCI_GETDEVCAPS_COMPOUND_DEVICE
:
753 lpParms
->dwReturn
= TRUE
;
755 case MCI_GETDEVCAPS_CAN_EJECT
:
756 lpParms
->dwReturn
= FALSE
;
758 case MCI_GETDEVCAPS_CAN_PLAY
:
759 lpParms
->dwReturn
= TRUE
;
761 case MCI_GETDEVCAPS_CAN_SAVE
:
762 lpParms
->dwReturn
= TRUE
;
764 case MCI_WAVE_GETDEVCAPS_INPUTS
:
765 lpParms
->dwReturn
= 1;
767 case MCI_WAVE_GETDEVCAPS_OUTPUTS
:
768 lpParms
->dwReturn
= 1;
771 return MCIERR_UNRECOGNIZED_COMMAND
;
777 /**************************************************************************
778 * WAVE_mciInfo [internal]
780 static DWORD
WAVE_mciInfo(UINT16 wDevID
, DWORD dwFlags
, LPMCI_INFO_PARMS lpParms
)
782 dprintf_mciwave(stddeb
,
783 "WAVE_mciInfo(%u, %08lX, %p);\n", wDevID
, dwFlags
, lpParms
);
784 if (lpParms
== NULL
) return MCIERR_INTERNAL
;
785 lpParms
->lpstrReturn
= NULL
;
787 case MCI_INFO_PRODUCT
:
788 lpParms
->lpstrReturn
= "Linux Sound System 0.5";
791 lpParms
->lpstrReturn
=
792 (LPSTR
)MCIWavDev
[wDevID
].openParms
.lpstrElementName
;
795 lpParms
->lpstrReturn
= "Linux Sound System 0.5";
797 case MCI_WAVE_OUTPUT
:
798 lpParms
->lpstrReturn
= "Linux Sound System 0.5";
801 return MCIERR_UNRECOGNIZED_COMMAND
;
803 if (lpParms
->lpstrReturn
!= NULL
)
804 lpParms
->dwRetSize
= strlen(lpParms
->lpstrReturn
);
806 lpParms
->dwRetSize
= 0;
811 /*-----------------------------------------------------------------------*/
814 /**************************************************************************
815 * wodGetDevCaps [internal]
817 static DWORD
wodGetDevCaps(WORD wDevID
, LPWAVEOUTCAPS lpCaps
, DWORD dwSize
)
824 dprintf_mciwave(stddeb
,
825 "wodGetDevCaps(%u, %p, %lu);\n", wDevID
, lpCaps
, dwSize
);
826 if (lpCaps
== NULL
) return MMSYSERR_NOTENABLED
;
827 if (access(SOUND_DEV
,0) != 0) return MMSYSERR_NOTENABLED
;
828 audio
= open (SOUND_DEV
, O_WRONLY
, 0);
829 if (audio
== -1) return MMSYSERR_ALLOCATED
;
831 lpCaps
->wMid
= 0x0002;
832 lpCaps
->wPid
= 0x0104;
833 strcpy(lpCaps
->szPname
, "SB16 Wave Out");
835 lpCaps
->wMid
= 0x00FF; /* Manufac ID */
836 lpCaps
->wPid
= 0x0001; /* Product ID */
837 strcpy(lpCaps
->szPname
, "Linux WAVOUT Driver");
839 lpCaps
->vDriverVersion
= 0x0100;
840 lpCaps
->dwFormats
= 0x00000000;
841 lpCaps
->dwSupport
= WAVECAPS_VOLUME
;
842 lpCaps
->wChannels
= (IOCTL(audio
, SNDCTL_DSP_STEREO
, dsp_stereo
) != 0) ? 1 : 2;
843 if (lpCaps
->wChannels
> 1) lpCaps
->dwSupport
|= WAVECAPS_LRVOLUME
;
844 bytespersmpl
= (IOCTL(audio
, SNDCTL_DSP_SAMPLESIZE
, samplesize
) != 0) ? 1 : 2;
846 if (IOCTL(audio
, SNDCTL_DSP_SPEED
, smplrate
) == 0) {
847 lpCaps
->dwFormats
|= WAVE_FORMAT_4M08
;
848 if (lpCaps
->wChannels
> 1) lpCaps
->dwFormats
|= WAVE_FORMAT_4S08
;
849 if (bytespersmpl
> 1) {
850 lpCaps
->dwFormats
|= WAVE_FORMAT_4M16
;
851 if (lpCaps
->wChannels
> 1) lpCaps
->dwFormats
|= WAVE_FORMAT_4S16
;
855 if (IOCTL(audio
, SNDCTL_DSP_SPEED
, smplrate
) == 0) {
856 lpCaps
->dwFormats
|= WAVE_FORMAT_2M08
;
857 if (lpCaps
->wChannels
> 1) lpCaps
->dwFormats
|= WAVE_FORMAT_2S08
;
858 if (bytespersmpl
> 1) {
859 lpCaps
->dwFormats
|= WAVE_FORMAT_2M16
;
860 if (lpCaps
->wChannels
> 1) lpCaps
->dwFormats
|= WAVE_FORMAT_2S16
;
864 if (IOCTL(audio
, SNDCTL_DSP_SPEED
, smplrate
) == 0) {
865 lpCaps
->dwFormats
|= WAVE_FORMAT_1M08
;
866 if (lpCaps
->wChannels
> 1) lpCaps
->dwFormats
|= WAVE_FORMAT_1S08
;
867 if (bytespersmpl
> 1) {
868 lpCaps
->dwFormats
|= WAVE_FORMAT_1M16
;
869 if (lpCaps
->wChannels
> 1) lpCaps
->dwFormats
|= WAVE_FORMAT_1S16
;
873 dprintf_mciwave(stddeb
,
874 "wodGetDevCaps // dwFormats = %08lX\n", lpCaps
->dwFormats
);
875 return MMSYSERR_NOERROR
;
879 /**************************************************************************
882 static DWORD
wodOpen(WORD wDevID
, LPWAVEOPENDESC lpDesc
, DWORD dwFlags
)
889 LPWAVEFORMAT lpFormat
;
891 dprintf_mciwave(stddeb
,
892 "wodOpen(%u, %p, %08lX);\n", wDevID
, lpDesc
, dwFlags
);
893 if (lpDesc
== NULL
) {
894 dprintf_mciwave(stddeb
,"Linux 'wodOpen' // Invalid Parameter !\n");
895 return MMSYSERR_INVALPARAM
;
897 if (wDevID
>= MAX_WAVOUTDRV
) {
898 dprintf_mciwave(stddeb
,"Linux 'wodOpen' // MAX_WAVOUTDRV reached !\n");
899 return MMSYSERR_ALLOCATED
;
901 WOutDev
[wDevID
].unixdev
= 0;
902 if (access(SOUND_DEV
,0) != 0) return MMSYSERR_NOTENABLED
;
903 audio
= open (SOUND_DEV
, O_WRONLY
, 0);
905 dprintf_mciwave(stddeb
,"Linux 'wodOpen' // can't open !\n");
906 return MMSYSERR_ALLOCATED
;
908 IOCTL(audio
, SNDCTL_DSP_GETBLKSIZE
, abuf_size
);
909 if (abuf_size
< 1024 || abuf_size
> 65536) {
911 dprintf_mciwave(stddeb
,"Linux 'wodOpen' // IOCTL can't 'SNDCTL_DSP_GETBLKSIZE' !\n");
913 dprintf_mciwave(stddeb
,"Linux 'wodOpen' // SNDCTL_DSP_GETBLKSIZE Invalid bufsize !\n");
914 return MMSYSERR_NOTENABLED
;
916 WOutDev
[wDevID
].wFlags
= HIWORD(dwFlags
& CALLBACK_TYPEMASK
);
917 switch(WOutDev
[wDevID
].wFlags
) {
919 dprintf_mciwave(stddeb
, "Linux 'wodOpen' // CALLBACK_NULL !\n");
922 dprintf_mciwave(stddeb
, "Linux 'wodOpen' // CALLBACK_WINDOW !\n");
925 dprintf_mciwave(stddeb
, "Linux 'wodOpen' // CALLBACK_TASK !\n");
928 dprintf_mciwave(stddeb
, "Linux 'wodOpen' // CALLBACK_FUNCTION !\n");
931 WOutDev
[wDevID
].lp16QueueHdr
= NULL
;
932 WOutDev
[wDevID
].unixdev
= audio
;
933 WOutDev
[wDevID
].dwTotalPlayed
= 0;
934 WOutDev
[wDevID
].bufsize
= abuf_size
;
935 memcpy(&WOutDev
[wDevID
].waveDesc
, lpDesc
, sizeof(WAVEOPENDESC
));
936 dprintf_mciwave(stddeb
,"Linux 'wodOpen' // lpDesc->lpFormat = %p\n",lpDesc
->lpFormat
);
937 lpFormat
= (LPWAVEFORMAT
) PTR_SEG_TO_LIN(lpDesc
->lpFormat
);
938 dprintf_mciwave(stddeb
,"Linux 'wodOpen' // lpFormat = %p\n",lpFormat
);
939 if (lpFormat
->wFormatTag
!= WAVE_FORMAT_PCM
) {
940 dprintf_mciwave(stddeb
,"Linux 'wodOpen' // Bad format %04X !\n",
941 lpFormat
->wFormatTag
);
942 dprintf_mciwave(stddeb
,"Linux 'wodOpen' // Bad nChannels %d !\n",
943 lpFormat
->nChannels
);
944 dprintf_mciwave(stddeb
,"Linux 'wodOpen' // Bad nSamplesPerSec %ld !\n",
945 lpFormat
->nSamplesPerSec
);
946 return WAVERR_BADFORMAT
;
948 memcpy(&WOutDev
[wDevID
].Format
, lpFormat
, sizeof(PCMWAVEFORMAT
));
949 if (WOutDev
[wDevID
].Format
.wf
.nChannels
== 0) return WAVERR_BADFORMAT
;
950 if (WOutDev
[wDevID
].Format
.wf
.nSamplesPerSec
== 0) return WAVERR_BADFORMAT
;
951 dprintf_mciwave(stddeb
,"Linux 'wodOpen' // wBitsPerSample=%u !\n",
952 WOutDev
[wDevID
].Format
.wBitsPerSample
);
953 if (WOutDev
[wDevID
].Format
.wBitsPerSample
== 0) {
954 WOutDev
[wDevID
].Format
.wBitsPerSample
= 8 *
955 (WOutDev
[wDevID
].Format
.wf
.nAvgBytesPerSec
/
956 WOutDev
[wDevID
].Format
.wf
.nSamplesPerSec
) /
957 WOutDev
[wDevID
].Format
.wf
.nChannels
;
959 samplesize
= WOutDev
[wDevID
].Format
.wBitsPerSample
;
960 smplrate
= WOutDev
[wDevID
].Format
.wf
.nSamplesPerSec
;
961 dsp_stereo
= (WOutDev
[wDevID
].Format
.wf
.nChannels
> 1) ? TRUE
: FALSE
;
962 IOCTL(audio
, SNDCTL_DSP_SPEED
, smplrate
);
963 IOCTL(audio
, SNDCTL_DSP_SAMPLESIZE
, samplesize
);
964 IOCTL(audio
, SNDCTL_DSP_STEREO
, dsp_stereo
);
965 dprintf_mciwave(stddeb
,"Linux 'wodOpen' // wBitsPerSample=%u !\n",
966 WOutDev
[wDevID
].Format
.wBitsPerSample
);
967 dprintf_mciwave(stddeb
,"Linux 'wodOpen' // nAvgBytesPerSec=%lu !\n",
968 WOutDev
[wDevID
].Format
.wf
.nAvgBytesPerSec
);
969 dprintf_mciwave(stddeb
,"Linux 'wodOpen' // nSamplesPerSec=%lu !\n",
970 WOutDev
[wDevID
].Format
.wf
.nSamplesPerSec
);
971 dprintf_mciwave(stddeb
,"Linux 'wodOpen' // nChannels=%u !\n",
972 WOutDev
[wDevID
].Format
.wf
.nChannels
);
973 if (WAVE_NotifyClient(wDevID
, WOM_OPEN
, 0L, 0L) != MMSYSERR_NOERROR
) {
974 dprintf_mciwave(stddeb
,"Linux 'wodOpen' // can't notify client !\n");
975 return MMSYSERR_INVALPARAM
;
977 return MMSYSERR_NOERROR
;
980 /**************************************************************************
981 * wodClose [internal]
983 static DWORD
wodClose(WORD wDevID
)
985 dprintf_mciwave(stddeb
,"wodClose(%u);\n", wDevID
);
986 if (wDevID
> MAX_WAVOUTDRV
) return MMSYSERR_INVALPARAM
;
987 if (WOutDev
[wDevID
].unixdev
== 0) {
988 dprintf_mciwave(stddeb
,"Linux 'wodClose' // can't close !\n");
989 return MMSYSERR_NOTENABLED
;
991 if (WOutDev
[wDevID
].lp16QueueHdr
!= NULL
) {
992 dprintf_mciwave(stddeb
,"linux 'wodclose' // still buffers open !\n");
993 return WAVERR_STILLPLAYING
;
995 close(WOutDev
[wDevID
].unixdev
);
996 WOutDev
[wDevID
].unixdev
= 0;
997 WOutDev
[wDevID
].bufsize
= 0;
998 WOutDev
[wDevID
].lp16QueueHdr
= NULL
;
999 if (WAVE_NotifyClient(wDevID
, WOM_CLOSE
, 0L, 0L) != MMSYSERR_NOERROR
) {
1000 dprintf_mciwave(stddeb
,"Linux 'wodClose' // can't notify client !\n");
1001 return MMSYSERR_INVALPARAM
;
1003 return MMSYSERR_NOERROR
;
1006 /**************************************************************************
1007 * wodWrite [internal]
1009 static DWORD
wodWrite(WORD wDevID
, SEGPTR lp16WaveHdr
, DWORD dwSize
)
1013 LPWAVEHDR lpWaveHdr
= (LPWAVEHDR
)PTR_SEG_TO_LIN(lp16WaveHdr
);
1015 dprintf_mciwave(stddeb
,"wodWrite(%u, %p, %08lX);\n", wDevID
, lpWaveHdr
, dwSize
);
1016 if (WOutDev
[wDevID
].unixdev
== 0) {
1017 dprintf_mciwave(stddeb
,"Linux 'wodWrite' // can't play !\n");
1018 return MMSYSERR_NOTENABLED
;
1020 if (lpWaveHdr
->lpData
== NULL
) return WAVERR_UNPREPARED
;
1021 if (!(lpWaveHdr
->dwFlags
& WHDR_PREPARED
)) return WAVERR_UNPREPARED
;
1022 if (lpWaveHdr
->dwFlags
& WHDR_INQUEUE
) return WAVERR_STILLPLAYING
;
1023 lpWaveHdr
->dwFlags
&= ~WHDR_DONE
;
1024 lpWaveHdr
->dwFlags
|= WHDR_INQUEUE
;
1025 dprintf_mciwave(stddeb
,
1026 "wodWrite() // dwBufferLength %lu !\n", lpWaveHdr
->dwBufferLength
);
1027 dprintf_mciwave(stddeb
,
1028 "wodWrite() // WOutDev[%u].unixdev %u !\n", wDevID
, WOutDev
[wDevID
].unixdev
);
1029 lpData
= PTR_SEG_TO_LIN(lpWaveHdr
->lpData
);
1030 count
= write (WOutDev
[wDevID
].unixdev
, lpData
, lpWaveHdr
->dwBufferLength
);
1031 dprintf_mciwave(stddeb
,
1032 "wodWrite() // write returned count %u !\n", count
);
1033 if (count
!= lpWaveHdr
->dwBufferLength
) {
1034 dprintf_mciwave(stddeb
,"Linux 'wodWrite' // error writting !\n");
1035 return MMSYSERR_NOTENABLED
;
1037 WOutDev
[wDevID
].dwTotalPlayed
+= count
;
1038 lpWaveHdr
->dwFlags
&= ~WHDR_INQUEUE
;
1039 lpWaveHdr
->dwFlags
|= WHDR_DONE
;
1040 if (WAVE_NotifyClient(wDevID
, WOM_DONE
, lp16WaveHdr
, count
) != MMSYSERR_NOERROR
) {
1041 dprintf_mciwave(stddeb
,"Linux 'wodWrite' // can't notify client !\n");
1042 return MMSYSERR_INVALPARAM
;
1044 return MMSYSERR_NOERROR
;
1047 /**************************************************************************
1048 * wodPrepare [internal]
1050 static DWORD
wodPrepare(WORD wDevID
, SEGPTR lp16WaveHdr
, DWORD dwSize
)
1052 LPWAVEHDR lpWaveHdr
;
1054 dprintf_mciwave(stddeb
,
1055 "wodPrepare(%u, %p, %08lX);\n", wDevID
, (void *)lp16WaveHdr
, dwSize
);
1056 if (WOutDev
[wDevID
].unixdev
== 0) {
1057 dprintf_mciwave(stddeb
,"Linux 'wodPrepare' // can't prepare !\n");
1058 return MMSYSERR_NOTENABLED
;
1061 lpWaveHdr
= PTR_SEG_TO_LIN(lp16WaveHdr
);
1063 /* the COOL waveeditor feels much better without this check...
1064 * someone please have a look at available documentation
1065 if (WOutDev[wDevID].lpQueueHdr != NULL) {
1066 dprintf_mciwave(stddeb,"Linux 'wodPrepare' // already prepare !\n");
1067 return MMSYSERR_NOTENABLED;
1070 WOutDev
[wDevID
].dwTotalPlayed
= 0;
1071 WOutDev
[wDevID
].lp16QueueHdr
= lp16WaveHdr
;
1072 if (lpWaveHdr
->dwFlags
& WHDR_INQUEUE
) return WAVERR_STILLPLAYING
;
1073 lpWaveHdr
->dwFlags
|= WHDR_PREPARED
;
1074 lpWaveHdr
->dwFlags
&= ~WHDR_DONE
;
1075 return MMSYSERR_NOERROR
;
1078 /**************************************************************************
1079 * wodUnprepare [internal]
1081 static DWORD
wodUnprepare(WORD wDevID
, LPWAVEHDR lpWaveHdr
, DWORD dwSize
)
1083 dprintf_mciwave(stddeb
,
1084 "wodUnprepare(%u, %p, %08lX);\n", wDevID
, lpWaveHdr
, dwSize
);
1085 if (WOutDev
[wDevID
].unixdev
== 0) {
1086 dprintf_mciwave(stddeb
,"Linux 'wodUnprepare' // can't unprepare !\n");
1087 return MMSYSERR_NOTENABLED
;
1090 lpWaveHdr
->dwFlags
&= ~WHDR_PREPARED
;
1091 lpWaveHdr
->dwFlags
&= ~WHDR_INQUEUE
;
1092 lpWaveHdr
->dwFlags
|= WHDR_DONE
;
1093 WOutDev
[wDevID
].lp16QueueHdr
= NULL
;
1094 dprintf_mciwave(stddeb
,
1095 "Linux 'wodUnprepare' // all headers unprepared !\n");
1096 return MMSYSERR_NOERROR
;
1099 /**************************************************************************
1100 * wodRestart [internal]
1102 static DWORD
wodRestart(WORD wDevID
)
1104 dprintf_mciwave(stddeb
,"wodRestart(%u);\n", wDevID
);
1105 if (WOutDev
[wDevID
].unixdev
== 0) {
1106 dprintf_mciwave(stddeb
,"Linux 'wodRestart' // can't restart !\n");
1107 return MMSYSERR_NOTENABLED
;
1109 /* FIXME: is NotifyClient with WOM_DONE right ? (Comet Busters 1.3.3 needs this notification) */
1110 if (WAVE_NotifyClient(wDevID
, WOM_DONE
, 0L, 0L) != MMSYSERR_NOERROR
) {
1111 dprintf_mciwave(stddeb
,"Linux 'wodRestart' // can't notify client !\n");
1112 return MMSYSERR_INVALPARAM
;
1115 return MMSYSERR_NOERROR
;
1118 /**************************************************************************
1119 * wodReset [internal]
1121 static DWORD
wodReset(WORD wDevID
)
1123 dprintf_mciwave(stddeb
,"wodReset(%u);\n", wDevID
);
1124 if (WOutDev
[wDevID
].unixdev
== 0) {
1125 dprintf_mciwave(stddeb
,"Linux 'wodReset' // can't reset !\n");
1126 return MMSYSERR_NOTENABLED
;
1128 return MMSYSERR_NOERROR
;
1132 /**************************************************************************
1133 * wodGetPosition [internal]
1135 static DWORD
wodGetPosition(WORD wDevID
, LPMMTIME lpTime
, DWORD uSize
)
1138 dprintf_mciwave(stddeb
,"wodGetPosition(%u, %p, %lu);\n", wDevID
, lpTime
, uSize
);
1139 if (WOutDev
[wDevID
].unixdev
== 0) {
1140 dprintf_mciwave(stddeb
,"Linux 'wodGetPosition' // can't get pos !\n");
1141 return MMSYSERR_NOTENABLED
;
1143 if (lpTime
== NULL
) return MMSYSERR_INVALPARAM
;
1144 dprintf_mciwave(stddeb
,"wodGetPosition // wType=%04X !\n",
1146 dprintf_mciwave(stddeb
,"wodGetPosition // wBitsPerSample=%u\n",
1147 WOutDev
[wDevID
].Format
.wBitsPerSample
);
1148 dprintf_mciwave(stddeb
,"wodGetPosition // nSamplesPerSec=%lu\n",
1149 WOutDev
[wDevID
].Format
.wf
.nSamplesPerSec
);
1150 dprintf_mciwave(stddeb
,"wodGetPosition // nChannels=%u\n",
1151 WOutDev
[wDevID
].Format
.wf
.nChannels
);
1152 dprintf_mciwave(stddeb
,"wodGetPosition // nAvgBytesPerSec=%lu\n",
1153 WOutDev
[wDevID
].Format
.wf
.nAvgBytesPerSec
);
1154 switch(lpTime
->wType
) {
1156 lpTime
->u
.cb
= WOutDev
[wDevID
].dwTotalPlayed
;
1157 dprintf_mciwave(stddeb
,"wodGetPosition // TIME_BYTES=%lu\n", lpTime
->u
.cb
);
1160 dprintf_mciwave(stddeb
,"wodGetPosition // dwTotalPlayed=%lu\n",
1161 WOutDev
[wDevID
].dwTotalPlayed
);
1162 dprintf_mciwave(stddeb
,"wodGetPosition // wBitsPerSample=%u\n",
1163 WOutDev
[wDevID
].Format
.wBitsPerSample
);
1164 lpTime
->u
.sample
= WOutDev
[wDevID
].dwTotalPlayed
* 8 /
1165 WOutDev
[wDevID
].Format
.wBitsPerSample
;
1166 dprintf_mciwave(stddeb
,"wodGetPosition // TIME_SAMPLES=%lu\n", lpTime
->u
.sample
);
1169 time
= WOutDev
[wDevID
].dwTotalPlayed
/
1170 (WOutDev
[wDevID
].Format
.wf
.nAvgBytesPerSec
/ 1000);
1171 lpTime
->u
.smpte
.hour
= time
/ 108000;
1172 time
-= lpTime
->u
.smpte
.hour
* 108000;
1173 lpTime
->u
.smpte
.min
= time
/ 1800;
1174 time
-= lpTime
->u
.smpte
.min
* 1800;
1175 lpTime
->u
.smpte
.sec
= time
/ 30;
1176 time
-= lpTime
->u
.smpte
.sec
* 30;
1177 lpTime
->u
.smpte
.frame
= time
;
1178 lpTime
->u
.smpte
.fps
= 30;
1179 dprintf_mciwave(stddeb
,
1180 "wodGetPosition // TIME_SMPTE=%02u:%02u:%02u:%02u\n",
1181 lpTime
->u
.smpte
.hour
, lpTime
->u
.smpte
.min
,
1182 lpTime
->u
.smpte
.sec
, lpTime
->u
.smpte
.frame
);
1185 dprintf_mciwave(stddeb
,"wodGetPosition() format not supported ! use TIME_MS !\n");
1186 lpTime
->wType
= TIME_MS
;
1188 lpTime
->u
.ms
= WOutDev
[wDevID
].dwTotalPlayed
/
1189 (WOutDev
[wDevID
].Format
.wf
.nAvgBytesPerSec
/ 1000);
1190 dprintf_mciwave(stddeb
,"wodGetPosition // TIME_MS=%lu\n", lpTime
->u
.ms
);
1193 return MMSYSERR_NOERROR
;
1196 /**************************************************************************
1197 * wodGetVolume [internal]
1199 static DWORD
wodGetVolume(WORD wDevID
, LPDWORD lpdwVol
)
1202 int volume
, left
, right
;
1203 dprintf_mciwave(stddeb
,"wodGetVolume(%u, %p);\n", wDevID
, lpdwVol
);
1204 if (lpdwVol
== NULL
) return MMSYSERR_NOTENABLED
;
1205 if ((mixer
= open(MIXER_DEV
, O_RDONLY
)) < 0) {
1206 dprintf_mciwave(stddeb
, "Linux 'wodGetVolume' // mixer device not available !\n");
1207 return MMSYSERR_NOTENABLED
;
1209 if (ioctl(mixer
, SOUND_MIXER_READ_PCM
, &volume
) == -1) {
1210 dprintf_mciwave(stddeb
,"Linux 'wodGetVolume' // unable read mixer !\n");
1211 return MMSYSERR_NOTENABLED
;
1214 left
= volume
& 0x7F;
1215 right
= (volume
>> 8) & 0x7F;
1216 dprintf_mciwave(stddeb
,"Linux 'wodGetVolume' // left=%d right=%d !\n", left
, right
);
1217 *lpdwVol
= MAKELONG(left
<< 9, right
<< 9);
1218 return MMSYSERR_NOERROR
;
1222 /**************************************************************************
1223 * wodSetVolume [internal]
1225 static DWORD
wodSetVolume(WORD wDevID
, DWORD dwParam
)
1229 dprintf_mciwave(stddeb
,"wodSetVolume(%u, %08lX);\n", wDevID
, dwParam
);
1230 volume
= (LOWORD(dwParam
) >> 9 & 0x7F) +
1231 ((HIWORD(dwParam
) >> 9 & 0x7F) << 8);
1232 if ((mixer
= open(MIXER_DEV
, O_WRONLY
)) < 0) {
1233 dprintf_mciwave(stddeb
, "Linux 'wodSetVolume' // mixer device not available !\n");
1234 return MMSYSERR_NOTENABLED
;
1236 if (ioctl(mixer
, SOUND_MIXER_WRITE_PCM
, &volume
) == -1) {
1237 dprintf_mciwave(stddeb
,"Linux 'wodSetVolume' // unable set mixer !\n");
1238 return MMSYSERR_NOTENABLED
;
1241 return MMSYSERR_NOERROR
;
1244 #endif /* linux || __FreeBSD__*/
1246 /**************************************************************************
1247 * wodMessage [sample driver]
1249 DWORD
wodMessage(WORD wDevID
, WORD wMsg
, DWORD dwUser
,
1250 DWORD dwParam1
, DWORD dwParam2
)
1252 dprintf_mciwave(stddeb
,"wodMessage(%u, %04X, %08lX, %08lX, %08lX);\n",
1253 wDevID
, wMsg
, dwUser
, dwParam1
, dwParam2
);
1254 #if defined(linux) || defined(__FreeBSD__)
1257 return wodOpen(wDevID
, (LPWAVEOPENDESC
)PTR_SEG_TO_LIN(dwParam1
), dwParam2
);
1259 return wodClose(wDevID
);
1261 return wodWrite(wDevID
, dwParam1
, dwParam2
);
1263 return MMSYSERR_NOTSUPPORTED
;
1265 return MMSYSERR_NOTSUPPORTED
;
1267 return wodGetPosition(wDevID
, (LPMMTIME
)PTR_SEG_TO_LIN(dwParam1
), dwParam2
);
1268 case WODM_BREAKLOOP
:
1269 return MMSYSERR_NOTSUPPORTED
;
1271 return wodPrepare(wDevID
, dwParam1
, dwParam2
);
1272 case WODM_UNPREPARE
:
1273 return wodUnprepare(wDevID
, (LPWAVEHDR
)PTR_SEG_TO_LIN(dwParam1
), dwParam2
);
1274 case WODM_GETDEVCAPS
:
1275 return wodGetDevCaps(wDevID
, (LPWAVEOUTCAPS
)PTR_SEG_TO_LIN(dwParam1
), dwParam2
);
1276 case WODM_GETNUMDEVS
:
1279 return MMSYSERR_NOTSUPPORTED
;
1281 return MMSYSERR_NOTSUPPORTED
;
1282 case WODM_GETPLAYBACKRATE
:
1283 return MMSYSERR_NOTSUPPORTED
;
1284 case WODM_SETPLAYBACKRATE
:
1285 return MMSYSERR_NOTSUPPORTED
;
1286 case WODM_GETVOLUME
:
1287 return wodGetVolume(wDevID
, (LPDWORD
)PTR_SEG_TO_LIN(dwParam1
));
1288 case WODM_SETVOLUME
:
1289 return wodSetVolume(wDevID
, dwParam1
);
1291 return wodRestart(wDevID
);
1293 return wodReset(wDevID
);
1295 dprintf_mciwave(stddeb
,"wodMessage // unknown message !\n");
1297 return MMSYSERR_NOTSUPPORTED
;
1299 return MMSYSERR_NOTENABLED
;
1304 /*-----------------------------------------------------------------------*/
1306 #if defined(linux) || defined(__FreeBSD__)
1308 /**************************************************************************
1309 * widGetDevCaps [internal]
1311 static DWORD
widGetDevCaps(WORD wDevID
, LPWAVEINCAPS lpCaps
, DWORD dwSize
)
1315 int samplesize
= 16;
1318 dprintf_mciwave(stddeb
,
1319 "widGetDevCaps(%u, %p, %lu);\n", wDevID
, lpCaps
, dwSize
);
1320 if (lpCaps
== NULL
) return MMSYSERR_NOTENABLED
;
1321 if (access(SOUND_DEV
,0) != 0) return MMSYSERR_NOTENABLED
;
1322 audio
= open (SOUND_DEV
, O_RDONLY
, 0);
1323 if (audio
== -1) return MMSYSERR_ALLOCATED
;
1325 lpCaps
->wMid
= 0x0002;
1326 lpCaps
->wPid
= 0x0004;
1327 strcpy(lpCaps
->szPname
, "SB16 Wave In");
1329 lpCaps
->wMid
= 0x00FF; /* Manufac ID */
1330 lpCaps
->wPid
= 0x0001; /* Product ID */
1331 strcpy(lpCaps
->szPname
, "Linux WAVIN Driver");
1333 lpCaps
->dwFormats
= 0x00000000;
1334 lpCaps
->wChannels
= (IOCTL(audio
, SNDCTL_DSP_STEREO
, dsp_stereo
) != 0) ? 1 : 2;
1335 bytespersmpl
= (IOCTL(audio
, SNDCTL_DSP_SAMPLESIZE
, samplesize
) != 0) ? 1 : 2;
1337 if (IOCTL(audio
, SNDCTL_DSP_SPEED
, smplrate
) == 0) {
1338 lpCaps
->dwFormats
|= WAVE_FORMAT_4M08
;
1339 if (lpCaps
->wChannels
> 1) lpCaps
->dwFormats
|= WAVE_FORMAT_4S08
;
1340 if (bytespersmpl
> 1) {
1341 lpCaps
->dwFormats
|= WAVE_FORMAT_4M16
;
1342 if (lpCaps
->wChannels
> 1) lpCaps
->dwFormats
|= WAVE_FORMAT_4S16
;
1346 if (IOCTL(audio
, SNDCTL_DSP_SPEED
, smplrate
) == 0) {
1347 lpCaps
->dwFormats
|= WAVE_FORMAT_2M08
;
1348 if (lpCaps
->wChannels
> 1) lpCaps
->dwFormats
|= WAVE_FORMAT_2S08
;
1349 if (bytespersmpl
> 1) {
1350 lpCaps
->dwFormats
|= WAVE_FORMAT_2M16
;
1351 if (lpCaps
->wChannels
> 1) lpCaps
->dwFormats
|= WAVE_FORMAT_2S16
;
1355 if (IOCTL(audio
, SNDCTL_DSP_SPEED
, smplrate
) == 0) {
1356 lpCaps
->dwFormats
|= WAVE_FORMAT_1M08
;
1357 if (lpCaps
->wChannels
> 1) lpCaps
->dwFormats
|= WAVE_FORMAT_1S08
;
1358 if (bytespersmpl
> 1) {
1359 lpCaps
->dwFormats
|= WAVE_FORMAT_1M16
;
1360 if (lpCaps
->wChannels
> 1) lpCaps
->dwFormats
|= WAVE_FORMAT_1S16
;
1364 dprintf_mciwave(stddeb
,
1365 "widGetDevCaps // dwFormats = %08lX\n", lpCaps
->dwFormats
);
1366 return MMSYSERR_NOERROR
;
1370 /**************************************************************************
1371 * widOpen [internal]
1373 static DWORD
widOpen(WORD wDevID
, LPWAVEOPENDESC lpDesc
, DWORD dwFlags
)
1380 LPWAVEFORMAT lpFormat
;
1381 dprintf_mciwave(stddeb
, "widOpen(%u, %p, %08lX);\n", wDevID
, lpDesc
, dwFlags
);
1382 if (lpDesc
== NULL
) {
1383 dprintf_mciwave(stddeb
,"Linux 'widOpen' // Invalid Parameter !\n");
1384 return MMSYSERR_INVALPARAM
;
1386 if (wDevID
>= MAX_WAVINDRV
) {
1387 dprintf_mciwave(stddeb
,"Linux 'widOpen' // MAX_WAVINDRV reached !\n");
1388 return MMSYSERR_ALLOCATED
;
1390 WInDev
[wDevID
].unixdev
= 0;
1391 if (access(SOUND_DEV
,0) != 0) return MMSYSERR_NOTENABLED
;
1392 audio
= open (SOUND_DEV
, O_RDONLY
, 0);
1394 dprintf_mciwave(stddeb
,"Linux 'widOpen' // can't open !\n");
1395 return MMSYSERR_ALLOCATED
;
1397 IOCTL(audio
, SNDCTL_DSP_GETBLKSIZE
, abuf_size
);
1398 if (abuf_size
< 1024 || abuf_size
> 65536) {
1399 if (abuf_size
== -1)
1400 dprintf_mciwave(stddeb
,"Linux 'widOpen' // IOCTL can't 'SNDCTL_DSP_GETBLKSIZE' !\n");
1402 dprintf_mciwave(stddeb
,"Linux 'widOpen' // SNDCTL_DSP_GETBLKSIZE Invalid bufsize !\n");
1403 return MMSYSERR_NOTENABLED
;
1405 WInDev
[wDevID
].wFlags
= HIWORD(dwFlags
& CALLBACK_TYPEMASK
);
1406 switch(WInDev
[wDevID
].wFlags
) {
1408 dprintf_mciwave(stddeb
, "Linux 'widOpen' // CALLBACK_NULL !\n");
1411 dprintf_mciwave(stddeb
, "Linux 'widOpen' // CALLBACK_WINDOW !\n");
1414 dprintf_mciwave(stddeb
, "Linux 'widOpen' // CALLBACK_TASK !\n");
1417 dprintf_mciwave(stddeb
, "Linux 'widOpen' // CALLBACK_FUNCTION !\n");
1420 WInDev
[wDevID
].lp16QueueHdr
= NULL
;
1421 WInDev
[wDevID
].unixdev
= audio
;
1422 WInDev
[wDevID
].bufsize
= abuf_size
;
1423 WInDev
[wDevID
].dwTotalRecorded
= 0;
1424 memcpy(&WInDev
[wDevID
].waveDesc
, lpDesc
, sizeof(WAVEOPENDESC
));
1425 lpFormat
= (LPWAVEFORMAT
) PTR_SEG_TO_LIN(lpDesc
->lpFormat
);
1426 if (lpFormat
->wFormatTag
!= WAVE_FORMAT_PCM
) {
1427 dprintf_mciwave(stddeb
,"Linux 'widOpen' // Bad format %04X !\n",
1428 lpFormat
->wFormatTag
);
1429 return WAVERR_BADFORMAT
;
1431 memcpy(&WInDev
[wDevID
].Format
, lpFormat
, sizeof(PCMWAVEFORMAT
));
1432 WInDev
[wDevID
].Format
.wBitsPerSample
= 8; /* <-------------- */
1433 if (WInDev
[wDevID
].Format
.wf
.nChannels
== 0) return WAVERR_BADFORMAT
;
1434 if (WInDev
[wDevID
].Format
.wf
.nSamplesPerSec
== 0) return WAVERR_BADFORMAT
;
1435 if (WInDev
[wDevID
].Format
.wBitsPerSample
== 0) {
1436 WInDev
[wDevID
].Format
.wBitsPerSample
= 8 *
1437 (WInDev
[wDevID
].Format
.wf
.nAvgBytesPerSec
/
1438 WInDev
[wDevID
].Format
.wf
.nSamplesPerSec
) /
1439 WInDev
[wDevID
].Format
.wf
.nChannels
;
1441 samplesize
= WInDev
[wDevID
].Format
.wBitsPerSample
;
1442 smplrate
= WInDev
[wDevID
].Format
.wf
.nSamplesPerSec
;
1443 dsp_stereo
= (WInDev
[wDevID
].Format
.wf
.nChannels
> 1) ? TRUE
: FALSE
;
1444 IOCTL(audio
, SNDCTL_DSP_SPEED
, smplrate
);
1445 IOCTL(audio
, SNDCTL_DSP_SAMPLESIZE
, samplesize
);
1446 IOCTL(audio
, SNDCTL_DSP_STEREO
, dsp_stereo
);
1447 dprintf_mciwave(stddeb
,"Linux 'widOpen' // wBitsPerSample=%u !\n",
1448 WInDev
[wDevID
].Format
.wBitsPerSample
);
1449 dprintf_mciwave(stddeb
,"Linux 'widOpen' // nSamplesPerSec=%lu !\n",
1450 WInDev
[wDevID
].Format
.wf
.nSamplesPerSec
);
1451 dprintf_mciwave(stddeb
,"Linux 'widOpen' // nChannels=%u !\n",
1452 WInDev
[wDevID
].Format
.wf
.nChannels
);
1453 dprintf_mciwave(stddeb
,"Linux 'widOpen' // nAvgBytesPerSec=%lu\n",
1454 WInDev
[wDevID
].Format
.wf
.nAvgBytesPerSec
);
1455 if (WAVE_NotifyClient(wDevID
, WIM_OPEN
, 0L, 0L) != MMSYSERR_NOERROR
) {
1456 dprintf_mciwave(stddeb
,"Linux 'widOpen' // can't notify client !\n");
1457 return MMSYSERR_INVALPARAM
;
1459 return MMSYSERR_NOERROR
;
1462 /**************************************************************************
1463 * widClose [internal]
1465 static DWORD
widClose(WORD wDevID
)
1467 dprintf_mciwave(stddeb
,"widClose(%u);\n", wDevID
);
1468 if (wDevID
> MAX_WAVINDRV
) return MMSYSERR_INVALPARAM
;
1469 if (WInDev
[wDevID
].unixdev
== 0) {
1470 dprintf_mciwave(stddeb
,"Linux 'widClose' // can't close !\n");
1471 return MMSYSERR_NOTENABLED
;
1473 if (WInDev
[wDevID
].lp16QueueHdr
!= NULL
) {
1474 dprintf_mciwave(stddeb
,"linux 'widclose' // still buffers open !\n");
1475 return WAVERR_STILLPLAYING
;
1477 close(WInDev
[wDevID
].unixdev
);
1478 WInDev
[wDevID
].unixdev
= 0;
1479 WInDev
[wDevID
].bufsize
= 0;
1480 if (WAVE_NotifyClient(wDevID
, WIM_CLOSE
, 0L, 0L) != MMSYSERR_NOERROR
) {
1481 dprintf_mciwave(stddeb
,"Linux 'widClose' // can't notify client !\n");
1482 return MMSYSERR_INVALPARAM
;
1484 return MMSYSERR_NOERROR
;
1487 /**************************************************************************
1488 * widAddBuffer [internal]
1490 static DWORD
widAddBuffer(WORD wDevID
, SEGPTR lp16WaveHdr
, DWORD dwSize
)
1494 LPWAVEHDR lpWaveHdr
= (LPWAVEHDR
)PTR_SEG_TO_LIN(lp16WaveHdr
);
1496 dprintf_mciwave(stddeb
,
1497 "widAddBuffer(%u, %p, %08lX);\n", wDevID
, lpWaveHdr
, dwSize
);
1498 if (WInDev
[wDevID
].unixdev
== 0) {
1499 dprintf_mciwave(stddeb
,"Linux 'widAddBuffer' // can't do it !\n");
1500 return MMSYSERR_NOTENABLED
;
1502 if (!(lpWaveHdr
->dwFlags
& WHDR_PREPARED
)) {
1503 dprintf_mciwave(stddeb
, "Linux 'widAddBuffer' // never been prepared !\n");
1504 return WAVERR_UNPREPARED
;
1506 if (lpWaveHdr
->dwFlags
& WHDR_INQUEUE
) {
1507 dprintf_mciwave(stddeb
, "Linux 'widAddBuffer' // header already in use !\n");
1508 return WAVERR_STILLPLAYING
;
1510 lpWaveHdr
->dwFlags
|= WHDR_PREPARED
;
1511 lpWaveHdr
->dwFlags
|= WHDR_INQUEUE
;
1512 lpWaveHdr
->dwFlags
&= ~WHDR_DONE
;
1513 lpWaveHdr
->dwBytesRecorded
= 0;
1514 if (WInDev
[wDevID
].lp16QueueHdr
== NULL
) {
1515 /* begin the queue with a first header ... */
1516 WInDev
[wDevID
].lp16QueueHdr
= lp16WaveHdr
;
1517 WInDev
[wDevID
].dwTotalRecorded
= 0;
1520 /* added to the queue, except if it's the one just prepared ... */
1521 lpWIHdr
= (LPWAVEHDR
)PTR_SEG_TO_LIN(WInDev
[wDevID
].lp16QueueHdr
);
1522 while (lpWIHdr
->lp16Next
!= NULL
) {
1523 lpWIHdr
= (LPWAVEHDR
)PTR_SEG_TO_LIN(lpWIHdr
->lp16Next
);
1526 lpWIHdr
->lp16Next
= lp16WaveHdr
;
1529 dprintf_mciwave(stddeb
,
1530 "widAddBuffer // buffer added ! (now %u in queue)\n", count
);
1531 return MMSYSERR_NOERROR
;
1534 /**************************************************************************
1535 * widPrepare [internal]
1537 static DWORD
widPrepare(WORD wDevID
, LPWAVEHDR lpWaveHdr
, DWORD dwSize
)
1539 dprintf_mciwave(stddeb
,
1540 "widPrepare(%u, %p, %08lX);\n", wDevID
, lpWaveHdr
, dwSize
);
1541 if (WInDev
[wDevID
].unixdev
== 0) {
1542 dprintf_mciwave(stddeb
,"Linux 'widPrepare' // can't prepare !\n");
1543 return MMSYSERR_NOTENABLED
;
1545 if (WInDev
[wDevID
].lp16QueueHdr
!= NULL
) {
1546 dprintf_mciwave(stddeb
,"Linux 'widPrepare' // already prepare !\n");
1547 return WAVERR_BADFORMAT
;
1549 if (lpWaveHdr
->dwFlags
& WHDR_INQUEUE
) return WAVERR_STILLPLAYING
;
1550 lpWaveHdr
->dwFlags
|= WHDR_PREPARED
;
1551 lpWaveHdr
->dwFlags
&= ~WHDR_INQUEUE
;
1552 lpWaveHdr
->dwFlags
&= ~WHDR_DONE
;
1553 lpWaveHdr
->dwBytesRecorded
= 0;
1554 dprintf_mciwave(stddeb
,"Linux 'widPrepare' // header prepared !\n");
1555 return MMSYSERR_NOERROR
;
1558 /**************************************************************************
1559 * widUnprepare [internal]
1561 static DWORD
widUnprepare(WORD wDevID
, LPWAVEHDR lpWaveHdr
, DWORD dwSize
)
1563 dprintf_mciwave(stddeb
,
1564 "widUnprepare(%u, %p, %08lX);\n", wDevID
, lpWaveHdr
, dwSize
);
1565 if (WInDev
[wDevID
].unixdev
== 0) {
1566 dprintf_mciwave(stddeb
,"Linux 'widUnprepare' // can't unprepare !\n");
1567 return MMSYSERR_NOTENABLED
;
1569 lpWaveHdr
->dwFlags
&= ~WHDR_PREPARED
;
1570 lpWaveHdr
->dwFlags
&= ~WHDR_INQUEUE
;
1571 lpWaveHdr
->dwFlags
|= WHDR_DONE
;
1572 WInDev
[wDevID
].lp16QueueHdr
= NULL
;
1573 dprintf_mciwave(stddeb
,
1574 "Linux 'widUnprepare' // all headers unprepared !\n");
1575 return MMSYSERR_NOERROR
;
1578 /**************************************************************************
1579 * widStart [internal]
1581 static DWORD
widStart(WORD wDevID
)
1588 dprintf_mciwave(stddeb
,"widStart(%u);\n", wDevID
);
1589 if (WInDev
[wDevID
].unixdev
== 0) {
1590 dprintf_mciwave(stddeb
, "Linux 'widStart' // can't start recording !\n");
1591 return MMSYSERR_NOTENABLED
;
1594 lp16WaveHdr
= WInDev
[wDevID
].lp16QueueHdr
;
1595 dprintf_mciwave(stddeb
,"Linux 'widstart'// lp16WaveHdr = %08lx\n",(DWORD
)lp16WaveHdr
);
1596 if (lp16WaveHdr
== NULL
||
1597 ((LPWAVEHDR
)PTR_SEG_TO_LIN(lp16WaveHdr
))->lpData
== NULL
) {
1598 dprintf_mciwave(stddeb
,"Linux 'widStart' // never been prepared !\n");
1599 return WAVERR_UNPREPARED
;
1602 while(lp16WaveHdr
!= NULL
) {
1603 lpWIHdr
= (LPWAVEHDR
)PTR_SEG_TO_LIN(lp16WaveHdr
);
1604 lpWIHdr
->dwBufferLength
&= 0xFFFF;
1605 dprintf_mciwave(stddeb
,
1606 "widStart // recording buf#%u=%p size=%lu \n",
1607 count
, lpWIHdr
->lpData
, lpWIHdr
->dwBufferLength
);
1609 bytesRead
= read (WInDev
[wDevID
].unixdev
,
1610 PTR_SEG_TO_LIN(lpWIHdr
->lpData
),
1611 lpWIHdr
->dwBufferLength
);
1612 lpWIHdr
->dwBytesRecorded
= bytesRead
;
1613 WInDev
[wDevID
].dwTotalRecorded
+= lpWIHdr
->dwBytesRecorded
;
1614 lpWIHdr
->dwFlags
&= ~WHDR_INQUEUE
;
1615 lpWIHdr
->dwFlags
|= WHDR_DONE
;
1617 if (WAVE_NotifyClient(wDevID
, WIM_DATA
, (DWORD
)lp16WaveHdr
, lpWIHdr
->dwBytesRecorded
) !=
1619 dprintf_mciwave(stddeb
, "Linux 'widStart' // can't notify client !\n");
1620 return MMSYSERR_INVALPARAM
;
1622 lp16WaveHdr
= lpWIHdr
->lp16Next
;
1625 dprintf_mciwave(stddeb
,"widStart // end of recording !\n");
1627 return MMSYSERR_NOERROR
;
1630 /**************************************************************************
1631 * widStop [internal]
1633 static DWORD
widStop(WORD wDevID
)
1635 dprintf_mciwave(stddeb
,"widStop(%u);\n", wDevID
);
1636 if (WInDev
[wDevID
].unixdev
== 0) {
1637 dprintf_mciwave(stddeb
,"Linux 'widStop' // can't stop !\n");
1638 return MMSYSERR_NOTENABLED
;
1640 return MMSYSERR_NOERROR
;
1643 /**************************************************************************
1644 * widReset [internal]
1646 static DWORD
widReset(WORD wDevID
)
1648 dprintf_mciwave(stddeb
,"widReset(%u);\n", wDevID
);
1649 if (WInDev
[wDevID
].unixdev
== 0) {
1650 dprintf_mciwave(stddeb
,"Linux 'widReset' // can't reset !\n");
1651 return MMSYSERR_NOTENABLED
;
1653 return MMSYSERR_NOERROR
;
1656 /**************************************************************************
1657 * widGetPosition [internal]
1659 static DWORD
widGetPosition(WORD wDevID
, LPMMTIME lpTime
, DWORD uSize
)
1663 dprintf_mciwave(stddeb
,
1664 "widGetPosition(%u, %p, %lu);\n", wDevID
, lpTime
, uSize
);
1665 if (WInDev
[wDevID
].unixdev
== 0) {
1666 dprintf_mciwave(stddeb
,"Linux 'widGetPosition' // can't get pos !\n");
1667 return MMSYSERR_NOTENABLED
;
1669 if (lpTime
== NULL
) return MMSYSERR_INVALPARAM
;
1670 dprintf_mciwave(stddeb
,"widGetPosition // wType=%04X !\n",
1672 dprintf_mciwave(stddeb
,"widGetPosition // wBitsPerSample=%u\n",
1673 WInDev
[wDevID
].Format
.wBitsPerSample
);
1674 dprintf_mciwave(stddeb
,"widGetPosition // nSamplesPerSec=%lu\n",
1675 WInDev
[wDevID
].Format
.wf
.nSamplesPerSec
);
1676 dprintf_mciwave(stddeb
,"widGetPosition // nChannels=%u\n",
1677 WInDev
[wDevID
].Format
.wf
.nChannels
);
1678 dprintf_mciwave(stddeb
,"widGetPosition // nAvgBytesPerSec=%lu\n",
1679 WInDev
[wDevID
].Format
.wf
.nAvgBytesPerSec
);
1681 switch(lpTime
->wType
) {
1683 lpTime
->u
.cb
= WInDev
[wDevID
].dwTotalRecorded
;
1684 dprintf_mciwave(stddeb
,
1685 "widGetPosition // TIME_BYTES=%lu\n", lpTime
->u
.cb
);
1688 lpTime
->u
.sample
= WInDev
[wDevID
].dwTotalRecorded
* 8 /
1689 WInDev
[wDevID
].Format
.wBitsPerSample
;
1690 dprintf_mciwave(stddeb
,
1691 "widGetPosition // TIME_SAMPLES=%lu\n",
1695 time
= WInDev
[wDevID
].dwTotalRecorded
/
1696 (WInDev
[wDevID
].Format
.wf
.nAvgBytesPerSec
/ 1000);
1697 lpTime
->u
.smpte
.hour
= time
/ 108000;
1698 time
-= lpTime
->u
.smpte
.hour
* 108000;
1699 lpTime
->u
.smpte
.min
= time
/ 1800;
1700 time
-= lpTime
->u
.smpte
.min
* 1800;
1701 lpTime
->u
.smpte
.sec
= time
/ 30;
1702 time
-= lpTime
->u
.smpte
.sec
* 30;
1703 lpTime
->u
.smpte
.frame
= time
;
1704 lpTime
->u
.smpte
.fps
= 30;
1705 dprintf_mciwave(stddeb
,"widGetPosition // TIME_SMPTE=%02u:%02u:%02u:%02u\n",
1706 lpTime
->u
.smpte
.hour
, lpTime
->u
.smpte
.min
,
1707 lpTime
->u
.smpte
.sec
, lpTime
->u
.smpte
.frame
);
1710 dprintf_mciwave(stddeb
,"widGetPosition() format not supported ! use TIME_MS !\n");
1711 lpTime
->wType
= TIME_MS
;
1713 lpTime
->u
.ms
= WInDev
[wDevID
].dwTotalRecorded
/
1714 (WInDev
[wDevID
].Format
.wf
.nAvgBytesPerSec
/ 1000);
1715 dprintf_mciwave(stddeb
,
1716 "widGetPosition // TIME_MS=%lu\n", lpTime
->u
.ms
);
1719 return MMSYSERR_NOERROR
;
1722 #endif /* linux || __FreeBSD__ */
1724 /**************************************************************************
1725 * widMessage [sample driver]
1727 DWORD
widMessage(WORD wDevID
, WORD wMsg
, DWORD dwUser
,
1728 DWORD dwParam1
, DWORD dwParam2
)
1730 dprintf_mciwave(stddeb
,"widMessage(%u, %04X, %08lX, %08lX, %08lX);\n",
1731 wDevID
, wMsg
, dwUser
, dwParam1
, dwParam2
);
1732 #if defined(linux) || defined(__FreeBSD__)
1735 return widOpen(wDevID
, (LPWAVEOPENDESC
)PTR_SEG_TO_LIN(dwParam1
), dwParam2
);
1737 return widClose(wDevID
);
1738 case WIDM_ADDBUFFER
:
1739 return widAddBuffer(wDevID
, dwParam1
, dwParam2
);
1741 return widPrepare(wDevID
, (LPWAVEHDR
)PTR_SEG_TO_LIN(dwParam1
), dwParam2
);
1742 case WIDM_UNPREPARE
:
1743 return widUnprepare(wDevID
, (LPWAVEHDR
)PTR_SEG_TO_LIN(dwParam1
), dwParam2
);
1744 case WIDM_GETDEVCAPS
:
1745 return widGetDevCaps(wDevID
, (LPWAVEINCAPS
)PTR_SEG_TO_LIN(dwParam1
), dwParam2
);
1746 case WIDM_GETNUMDEVS
:
1749 return widGetPosition(wDevID
, (LPMMTIME
)PTR_SEG_TO_LIN(dwParam1
), dwParam2
);
1751 return widReset(wDevID
);
1753 return widStart(wDevID
);
1755 return widStop(wDevID
);
1757 return widStop(wDevID
);
1759 dprintf_mciwave(stddeb
,"widMessage // unknown message !\n");
1761 return MMSYSERR_NOTSUPPORTED
;
1763 return MMSYSERR_NOTENABLED
;
1768 /**************************************************************************
1769 * AUDIO_DriverProc [sample driver]
1771 LONG
WAVE_DriverProc(DWORD dwDevID
, HDRVR16 hDriv
, WORD wMsg
,
1772 DWORD dwParam1
, DWORD dwParam2
)
1774 #if defined(linux) || defined(__FreeBSD__)
1775 dprintf_mciwave(stddeb
,"WAVE_DriverProc(%08lX, %04X, %04X, %08lX, %08lX)\n",
1776 dwDevID
, hDriv
, wMsg
, dwParam1
, dwParam2
);
1790 case DRV_QUERYCONFIGURE
:
1793 MessageBox16(0, "Sample MultiMedia Linux Driver !",
1794 "MMLinux Driver", MB_OK
);
1797 return DRVCNF_RESTART
;
1799 return DRVCNF_RESTART
;
1800 case MCI_OPEN_DRIVER
:
1802 return WAVE_mciOpen(dwDevID
, dwParam1
, (LPMCI_WAVE_OPEN_PARMS
)PTR_SEG_TO_LIN(dwParam2
));
1804 return WAVE_mciCue(dwDevID
, dwParam1
, (LPMCI_GENERIC_PARMS
)PTR_SEG_TO_LIN(dwParam2
));
1805 case MCI_CLOSE_DRIVER
:
1807 return WAVE_mciClose(dwDevID
, dwParam1
, (LPMCI_GENERIC_PARMS
)PTR_SEG_TO_LIN(dwParam2
));
1809 return WAVE_mciPlay(dwDevID
, dwParam1
, (LPMCI_PLAY_PARMS
)PTR_SEG_TO_LIN(dwParam2
));
1811 return WAVE_mciRecord(dwDevID
, dwParam1
, (LPMCI_RECORD_PARMS
)PTR_SEG_TO_LIN(dwParam2
));
1813 return WAVE_mciStop(dwDevID
, dwParam1
, (LPMCI_GENERIC_PARMS
)PTR_SEG_TO_LIN(dwParam2
));
1815 return WAVE_mciSet(dwDevID
, dwParam1
, (LPMCI_SET_PARMS
)PTR_SEG_TO_LIN(dwParam2
));
1817 return WAVE_mciPause(dwDevID
, dwParam1
, (LPMCI_GENERIC_PARMS
)PTR_SEG_TO_LIN(dwParam2
));
1819 return WAVE_mciResume(dwDevID
, dwParam1
, (LPMCI_GENERIC_PARMS
)PTR_SEG_TO_LIN(dwParam2
));
1821 return WAVE_mciStatus(dwDevID
, dwParam1
, (LPMCI_STATUS_PARMS
)PTR_SEG_TO_LIN(dwParam2
));
1822 case MCI_GETDEVCAPS
:
1823 return WAVE_mciGetDevCaps(dwDevID
, dwParam1
, (LPMCI_GETDEVCAPS_PARMS
)PTR_SEG_TO_LIN(dwParam2
));
1825 return WAVE_mciInfo(dwDevID
, dwParam1
, (LPMCI_INFO_PARMS
)PTR_SEG_TO_LIN(dwParam2
));
1828 return MMSYSERR_NOTSUPPORTED
;
1830 return MMSYSERR_NOTSUPPORTED
;
1832 return MMSYSERR_NOTSUPPORTED
;
1834 return MMSYSERR_NOTSUPPORTED
;
1836 return MMSYSERR_NOTSUPPORTED
;
1838 return MMSYSERR_NOTSUPPORTED
;
1840 return MMSYSERR_NOTSUPPORTED
;
1842 return MMSYSERR_NOTSUPPORTED
;
1844 return MMSYSERR_NOTSUPPORTED
;
1846 return MMSYSERR_NOTSUPPORTED
;
1848 return MMSYSERR_NOTSUPPORTED
;
1850 return MMSYSERR_NOTSUPPORTED
;
1852 return MMSYSERR_NOTSUPPORTED
;
1854 return MMSYSERR_NOTSUPPORTED
;
1856 return MMSYSERR_NOTSUPPORTED
;
1858 return MMSYSERR_NOTSUPPORTED
;
1860 return MMSYSERR_NOTSUPPORTED
;
1863 return DefDriverProc(dwDevID
, hDriv
, wMsg
, dwParam1
, dwParam2
);
1866 return MMSYSERR_NOTENABLED
;