2 * Sample Wine Driver for Linux
4 * Copyright 1994 Martin Ayotte
6 static char Copyright
[] = "Copyright Martin Ayotte, 1994";
9 #define BUILTIN_MMSYSTEM
12 #ifdef BUILTIN_MMSYSTEM
20 #include <sys/ioctl.h>
27 #include <linux/soundcard.h>
31 /* #define DEBUG_MCIWAVE /* */
32 /* #undef DEBUG_MCIWAVE /* */
36 #define SOUND_DEV "/dev/dsp"
39 #define IOCTL(a,b,c) ioctl(a,b,&c)
41 #define IOCTL(a,b,c) (c = ioctl(a,b,c) )
44 #define MAX_WAVOUTDRV 2
45 #define MAX_WAVINDRV 2
46 #define MAX_MCIWAVDRV 2
52 WAVEOPENDESC waveDesc
;
62 DWORD bufsize
; /* Linux '/dev/dsp' give us that size */
63 WAVEOPENDESC waveDesc
;
67 DWORD dwTotalRecorded
;
71 int nUseCount
; /* Incremented for each shared open */
72 BOOL fShareable
; /* TRUE if first open was shareable */
73 WORD wNotifyDeviceID
; /* MCI device ID with a pending notification */
74 HANDLE hCallback
; /* Callback handle for pending notification */
75 HMMIO hFile
; /* mmio file handle open as Element */
76 MCI_WAVE_OPEN_PARMS openParms
;
77 PCMWAVEFORMAT WaveFormat
;
81 static LINUX_WAVEOUT WOutDev
[MAX_WAVOUTDRV
];
82 static LINUX_WAVEIN WInDev
[MAX_WAVOUTDRV
];
83 static LINUX_MCIWAVE MCIWavDev
[MAX_MCIWAVDRV
];
86 DWORD
WAVE_mciOpen(DWORD dwFlags
, LPMCI_WAVE_OPEN_PARMS lpParms
);
87 DWORD
WAVE_mciClose(UINT wDevID
, DWORD dwParam
, LPMCI_GENERIC_PARMS lpParms
);
88 DWORD
WAVE_mciPlay(UINT wDevID
, DWORD dwFlags
, LPMCI_PLAY_PARMS lpParms
);
89 DWORD
WAVE_mciRecord(UINT wDevID
, DWORD dwFlags
, LPMCI_RECORD_PARMS lpParms
);
90 DWORD
WAVE_mciStop(UINT wDevID
, DWORD dwFlags
, LPMCI_GENERIC_PARMS lpParms
);
91 DWORD
WAVE_mciPause(UINT wDevID
, DWORD dwFlags
, LPMCI_GENERIC_PARMS lpParms
);
92 DWORD
WAVE_mciResume(UINT wDevID
, DWORD dwFlags
, LPMCI_GENERIC_PARMS lpParms
);
93 DWORD
WAVE_mciSet(UINT wDevID
, DWORD dwFlags
, LPMCI_SET_PARMS lpParms
);
94 DWORD
WAVE_mciStatus(UINT wDevID
, DWORD dwFlags
, LPMCI_STATUS_PARMS lpParms
);
95 DWORD
WAVE_mciGetDevCaps(UINT wDevID
, DWORD dwFlags
, LPMCI_GETDEVCAPS_PARMS lpParms
);
96 DWORD
WAVE_mciInfo(UINT wDevID
, DWORD dwFlags
, LPMCI_INFO_PARMS lpParms
);
98 DWORD
wodGetDevCaps(WORD wDevID
, LPWAVEOUTCAPS lpCaps
, DWORD dwSize
);
99 DWORD
wodOpen(WORD wDevID
, LPWAVEOPENDESC lpDesc
, DWORD dwFlags
);
100 DWORD
wodClose(WORD wDevID
);
101 DWORD
wodWrite(WORD wDevID
, LPWAVEHDR lpWaveHdr
, DWORD dwSize
);
102 DWORD
wodPrepare(WORD wDevID
, LPWAVEHDR lpWaveHdr
, DWORD dwSize
);
103 DWORD
wodUnprepare(WORD wDevID
, LPWAVEHDR lpWaveHdr
, DWORD dwSize
);
106 /**************************************************************************
107 * WAVE_NotifyClient [internal]
109 DWORD
WAVE_NotifyClient(UINT wDevID
, WORD wMsg
,
110 DWORD dwParam1
, DWORD dwParam2
)
113 if (WInDev
[wDevID
].wFlags
!= DCB_NULL
&& !DriverCallback(
114 WInDev
[wDevID
].waveDesc
.dwCallBack
, WInDev
[wDevID
].wFlags
,
115 WInDev
[wDevID
].waveDesc
.hWave
, wMsg
,
116 WInDev
[wDevID
].waveDesc
.dwInstance
, dwParam1
, dwParam2
)) {
117 fprintf(stderr
,"WAVE_NotifyClient // can't notify client !\n");
118 return MMSYSERR_NOERROR
;
121 return MMSYSERR_NOTENABLED
;
126 /**************************************************************************
127 * AUDIO_DriverProc [sample driver]
129 LRESULT
WAVE_DriverProc(DWORD dwDevID
, HDRVR hDriv
, WORD wMsg
,
130 DWORD dwParam1
, DWORD dwParam2
)
146 case DRV_QUERYCONFIGURE
:
149 MessageBox((HWND
)NULL
, "Sample MultiMedia Linux Driver !",
150 "MMLinux Driver", MB_OK
);
153 return (LRESULT
)DRVCNF_RESTART
;
155 return (LRESULT
)DRVCNF_RESTART
;
156 case MCI_OPEN_DRIVER
:
158 return WAVE_mciOpen(dwParam1
, (LPMCI_WAVE_OPEN_PARMS
)dwParam2
);
159 case MCI_CLOSE_DRIVER
:
161 return WAVE_mciClose(dwDevID
, dwParam1
, (LPMCI_GENERIC_PARMS
)dwParam2
);
163 return WAVE_mciPlay(dwDevID
, dwParam1
, (LPMCI_PLAY_PARMS
)dwParam2
);
165 return WAVE_mciRecord(dwDevID
, dwParam1
, (LPMCI_RECORD_PARMS
)dwParam2
);
167 return WAVE_mciStop(dwDevID
, dwParam1
, (LPMCI_GENERIC_PARMS
)dwParam2
);
169 return WAVE_mciSet(dwDevID
, dwParam1
, (LPMCI_SET_PARMS
)dwParam2
);
171 return WAVE_mciPause(dwDevID
, dwParam1
, (LPMCI_GENERIC_PARMS
)dwParam2
);
173 return WAVE_mciResume(dwDevID
, dwParam1
, (LPMCI_GENERIC_PARMS
)dwParam2
);
175 return WAVE_mciStatus(dwDevID
, dwParam1
, (LPMCI_STATUS_PARMS
)dwParam2
);
177 return WAVE_mciGetDevCaps(dwDevID
, dwParam1
, (LPMCI_GETDEVCAPS_PARMS
)dwParam2
);
179 return WAVE_mciInfo(dwDevID
, dwParam1
, (LPMCI_INFO_PARMS
)dwParam2
);
181 return DefDriverProc(dwDevID
, hDriv
, wMsg
, dwParam1
, dwParam2
);
184 return MMSYSERR_NOTENABLED
;
188 /**************************************************************************
190 DWORD
WAVE_mciOpen(DWORD dwFlags
, LPMCI_WAVE_OPEN_PARMS lpParms
)
196 LPPCMWAVEFORMAT lpWaveFormat
;
197 WAVEOPENDESC WaveDesc
;
201 dprintf_mciwave(stddeb
,"WAVE_mciOpen(%08X, %08X)\n", dwFlags
, lpParms
);
202 if (lpParms
== NULL
) return MCIERR_INTERNAL
;
203 wDevID
= lpParms
->wDeviceID
;
204 if (MCIWavDev
[wDevID
].nUseCount
> 0) {
205 /* The driver already open on this channel */
206 /* If the driver was opened shareable before and this open specifies */
207 /* shareable then increment the use count */
208 if (MCIWavDev
[wDevID
].fShareable
&& (dwFlags
& MCI_OPEN_SHAREABLE
))
209 ++MCIWavDev
[wDevID
].nUseCount
;
211 return MCIERR_MUST_USE_SHAREABLE
;
214 MCIWavDev
[wDevID
].nUseCount
= 1;
215 MCIWavDev
[wDevID
].fShareable
= dwFlags
& MCI_OPEN_SHAREABLE
;
217 if (dwFlags
& MCI_OPEN_ELEMENT
) {
218 dprintf_mciwave(stddeb
,"WAVE_mciOpen // MCI_OPEN_ELEMENT '%s' !\n",
219 lpParms
->lpstrElementName
);
220 /* printf("WAVE_mciOpen // cdw='%s'\n", DOS_GetCurrentDir(DOS_GetDefaultDrive())); */
221 if (strlen(lpParms
->lpstrElementName
) > 0) {
222 strcpy(str
, lpParms
->lpstrElementName
);
224 MCIWavDev
[wDevID
].hFile
= mmioOpen(str
, NULL
,
225 MMIO_ALLOCBUF
| MMIO_READWRITE
| MMIO_EXCLUSIVE
);
226 if (MCIWavDev
[wDevID
].hFile
== 0) {
227 fprintf(stderr
,"WAVE_mciOpen // can't find file='%s' !\n", str
);
228 return MCIERR_FILE_NOT_FOUND
;
232 MCIWavDev
[wDevID
].hFile
= 0;
234 dprintf_mciwave(stddeb
,"WAVE_mciOpen // hFile=%u\n", MCIWavDev
[wDevID
].hFile
);
235 memcpy(&MCIWavDev
[wDevID
].openParms
, lpParms
, sizeof(MCI_WAVE_OPEN_PARMS
));
236 MCIWavDev
[wDevID
].wNotifyDeviceID
= lpParms
->wDeviceID
;
237 lpWaveFormat
= &MCIWavDev
[wDevID
].WaveFormat
;
239 WaveDesc
.lpFormat
= (LPWAVEFORMAT
)lpWaveFormat
;
240 lpWaveFormat
->wf
.wFormatTag
= WAVE_FORMAT_PCM
;
241 lpWaveFormat
->wBitsPerSample
= 8;
242 lpWaveFormat
->wf
.nChannels
= 1;
243 lpWaveFormat
->wf
.nSamplesPerSec
= 11025;
244 lpWaveFormat
->wf
.nAvgBytesPerSec
= 11025;
245 lpWaveFormat
->wf
.nBlockAlign
= 1;
246 if (MCIWavDev
[wDevID
].hFile
!= 0) {
249 if (mmioDescend(MCIWavDev
[wDevID
].hFile
, &ckMainRIFF
, NULL
, 0) != 0) {
250 return MCIERR_INTERNAL
;
252 dprintf_mciwave(stddeb
,
253 "WAVE_mciOpen // ParentChunk ckid=%.4s fccType=%.4s cksize=%08lX \n",
254 (LPSTR
)&ckMainRIFF
.ckid
, (LPSTR
)&ckMainRIFF
.fccType
,
256 if ((ckMainRIFF
.ckid
!= FOURCC_RIFF
) ||
257 (ckMainRIFF
.fccType
!= mmioFOURCC('W', 'A', 'V', 'E'))) {
258 return MCIERR_INTERNAL
;
260 mmckInfo
.ckid
= mmioFOURCC('f', 'm', 't', ' ');
261 if (mmioDescend(MCIWavDev
[wDevID
].hFile
, &mmckInfo
, &ckMainRIFF
, MMIO_FINDCHUNK
) != 0) {
262 return MCIERR_INTERNAL
;
264 dprintf_mciwave(stddeb
,
265 "WAVE_mciOpen // Chunk Found ckid=%.4s fccType=%.4s cksize=%08lX \n",
266 (LPSTR
)&mmckInfo
.ckid
, (LPSTR
)&mmckInfo
.fccType
,
268 if (mmioRead(MCIWavDev
[wDevID
].hFile
, (HPSTR
) lpWaveFormat
,
269 (long) sizeof(PCMWAVEFORMAT
)) != (long) sizeof(PCMWAVEFORMAT
)) {
270 return MCIERR_INTERNAL
;
272 mmckInfo
.ckid
= mmioFOURCC('d', 'a', 't', 'a');
273 if (mmioDescend(MCIWavDev
[wDevID
].hFile
, &mmckInfo
, &ckMainRIFF
, MMIO_FINDCHUNK
) != 0) {
274 return MCIERR_INTERNAL
;
276 dprintf_mciwave(stddeb
,
277 "WAVE_mciOpen // Chunk Found ckid=%.4s fccType=%.4s cksize=%08lX \n",
278 (LPSTR
)&mmckInfo
.ckid
, (LPSTR
)&mmckInfo
.fccType
,
280 dprintf_mciwave(stddeb
,
281 "WAVE_mciOpen // nChannels=%d nSamplesPerSec=%d\n",
282 lpWaveFormat
->wf
.nChannels
, lpWaveFormat
->wf
.nSamplesPerSec
);
283 lpWaveFormat
->wBitsPerSample
= 0;
285 lpWaveFormat
->wf
.nAvgBytesPerSec
=
286 lpWaveFormat
->wf
.nSamplesPerSec
* lpWaveFormat
->wf
.nBlockAlign
;
287 dwRet
= wodMessage(0, WODM_OPEN
, 0, (DWORD
)&WaveDesc
, CALLBACK_NULL
);
288 dwRet
= widMessage(0, WIDM_OPEN
, 0, (DWORD
)&WaveDesc
, CALLBACK_NULL
);
291 return MMSYSERR_NOTENABLED
;
295 /**************************************************************************
296 * WAVE_mciClose [internal]
298 DWORD
WAVE_mciClose(UINT wDevID
, DWORD dwParam
, LPMCI_GENERIC_PARMS lpParms
)
302 dprintf_mciwave(stddeb
,
303 "WAVE_mciClose(%u, %08X, %08X);\n", wDevID
, dwParam
, lpParms
);
304 MCIWavDev
[wDevID
].nUseCount
--;
305 if (MCIWavDev
[wDevID
].nUseCount
== 0) {
306 if (MCIWavDev
[wDevID
].hFile
!= 0) {
307 mmioClose(MCIWavDev
[wDevID
].hFile
, 0);
308 MCIWavDev
[wDevID
].hFile
= 0;
310 dwRet
= wodMessage(0, WODM_CLOSE
, 0, 0L, 0L);
311 if (dwRet
!= MMSYSERR_NOERROR
) return MCIERR_INTERNAL
;
312 dwRet
= widMessage(0, WIDM_CLOSE
, 0, 0L, 0L);
313 if (dwRet
!= MMSYSERR_NOERROR
) return MCIERR_INTERNAL
;
322 /**************************************************************************
323 * WAVE_mciPlay [internal]
325 DWORD
WAVE_mciPlay(UINT wDevID
, DWORD dwFlags
, LPMCI_PLAY_PARMS lpParms
)
332 dprintf_mciwave(stddeb
,
333 "WAVE_mciPlay(%u, %08X, %08X);\n", wDevID
, dwFlags
, lpParms
);
334 if (MCIWavDev
[wDevID
].hFile
== 0) {
335 fprintf(stderr
,"WAVE_mciPlay // can't find file='%s' !\n",
336 MCIWavDev
[wDevID
].openParms
.lpstrElementName
);
337 return MCIERR_FILE_NOT_FOUND
;
339 start
= 1; end
= 99999;
340 if (dwFlags
& MCI_FROM
) {
341 start
= lpParms
->dwFrom
;
342 dprintf_mciwave(stddeb
,
343 "WAVE_mciPlay // MCI_FROM=%d \n", start
);
345 if (dwFlags
& MCI_TO
) {
347 dprintf_mciwave(stddeb
,"WAVE_mciPlay // MCI_TO=%d \n", end
);
350 if (dwFlags
& MCI_NOTIFY
) {
351 dprintf_mciwave(stddeb
,
352 "WAVE_mciPlay // MCI_NOTIFY %08X !\n", lpParms
->dwCallback
);
356 "WAVE_mciPlay // Can't 'fork' process !\n");
361 dprintf_mciwave(stddeb
,"WAVE_mciPlay // process started ! return to caller...\n");
366 lpWaveHdr
= &MCIWavDev
[wDevID
].WaveHdr
;
367 lpWaveHdr
->lpData
= (LPSTR
) malloc(64000);
368 lpWaveHdr
->dwBufferLength
= 32000;
369 lpWaveHdr
->dwUser
= 0L;
370 lpWaveHdr
->dwFlags
= 0L;
371 lpWaveHdr
->dwLoops
= 0L;
372 dwRet
= wodMessage(0, WODM_PREPARE
, 0, (DWORD
)lpWaveHdr
, sizeof(WAVEHDR
));
373 /* printf("WAVE_mciPlay // after WODM_PREPARE \n"); */
375 count
= mmioRead(MCIWavDev
[wDevID
].hFile
, lpWaveHdr
->lpData
, lpWaveHdr
->dwBufferLength
);
376 if (count
< 1) break;
377 lpWaveHdr
->dwBytesRecorded
= count
;
378 dprintf_mciwave(stddeb
,"WAVE_mciPlay // before WODM_WRITE lpWaveHdr=%08X dwBytesRecorded=%u\n",
379 lpWaveHdr
, lpWaveHdr
->dwBytesRecorded
);
380 dwRet
= wodMessage(0, WODM_WRITE
, 0, (DWORD
)lpWaveHdr
, sizeof(WAVEHDR
));
382 dwRet
= wodMessage(0, WODM_UNPREPARE
, 0, (DWORD
)lpWaveHdr
, sizeof(WAVEHDR
));
383 if (lpWaveHdr
->lpData
!= NULL
) {
384 free(lpWaveHdr
->lpData
);
385 lpWaveHdr
->lpData
= NULL
;
387 if (dwFlags
& MCI_NOTIFY
) {
388 dprintf_mciwave(stddeb
,"WAVE_mciPlay // MCI_NOTIFY_SUCCESSFUL %08X !\n", lpParms
->dwCallback
);
389 mciDriverNotify((HWND
)LOWORD(lpParms
->dwCallback
),
390 MCIWavDev
[wDevID
].wNotifyDeviceID
, MCI_NOTIFY_SUCCESSFUL
);
395 return MMSYSERR_NOTENABLED
;
400 /**************************************************************************
401 * WAVE_mciRecord [internal]
403 DWORD
WAVE_mciRecord(UINT wDevID
, DWORD dwFlags
, LPMCI_RECORD_PARMS lpParms
)
410 dprintf_mciwave(stddeb
,
411 "WAVE_mciRecord(%u, %08X, %08X);\n", wDevID
, dwFlags
, lpParms
);
412 if (MCIWavDev
[wDevID
].hFile
== 0) {
413 fprintf(stderr
,"WAVE_mciRecord // can't find file='%s' !\n",
414 MCIWavDev
[wDevID
].openParms
.lpstrElementName
);
415 return MCIERR_FILE_NOT_FOUND
;
417 start
= 1; end
= 99999;
418 if (dwFlags
& MCI_FROM
) {
419 start
= lpParms
->dwFrom
;
420 dprintf_mciwave(stddeb
,
421 "WAVE_mciRecord // MCI_FROM=%d \n", start
);
423 if (dwFlags
& MCI_TO
) {
425 dprintf_mciwave(stddeb
,"WAVE_mciRecord // MCI_TO=%d \n", end
);
427 lpWaveHdr
= &MCIWavDev
[wDevID
].WaveHdr
;
428 lpWaveHdr
->lpData
= (LPSTR
) malloc(64000);
429 lpWaveHdr
->dwBufferLength
= 32000;
430 lpWaveHdr
->dwUser
= 0L;
431 lpWaveHdr
->dwFlags
= 0L;
432 lpWaveHdr
->dwLoops
= 0L;
433 dwRet
= widMessage(0, WIDM_PREPARE
, 0, (DWORD
)lpWaveHdr
, sizeof(WAVEHDR
));
434 dprintf_mciwave(stddeb
,"WAVE_mciRecord // after WIDM_PREPARE \n");
436 lpWaveHdr
->dwBytesRecorded
= 0;
437 dwRet
= widMessage(0, WIDM_START
, 0, 0L, 0L);
438 dprintf_mciwave(stddeb
,
439 "WAVE_mciRecord // after WIDM_START lpWaveHdr=%08X dwBytesRecorded=%u\n",
440 lpWaveHdr
, lpWaveHdr
->dwBytesRecorded
);
441 if (lpWaveHdr
->dwBytesRecorded
== 0) break;
443 dprintf_mciwave(stddeb
,"WAVE_mciRecord // before WIDM_UNPREPARE \n");
444 dwRet
= widMessage(0, WIDM_UNPREPARE
, 0, (DWORD
)lpWaveHdr
, sizeof(WAVEHDR
));
445 dprintf_mciwave(stddeb
,"WAVE_mciRecord // after WIDM_UNPREPARE \n");
446 if (lpWaveHdr
->lpData
!= NULL
) {
447 free(lpWaveHdr
->lpData
);
448 lpWaveHdr
->lpData
= NULL
;
450 if (dwFlags
& MCI_NOTIFY
) {
451 dprintf_mciwave(stddeb
,"WAVE_mciRecord // MCI_NOTIFY_SUCCESSFUL %08X !\n", lpParms
->dwCallback
);
452 mciDriverNotify((HWND
)LOWORD(lpParms
->dwCallback
),
453 MCIWavDev
[wDevID
].wNotifyDeviceID
, MCI_NOTIFY_SUCCESSFUL
);
457 return MMSYSERR_NOTENABLED
;
462 /**************************************************************************
463 * WAVE_mciStop [internal]
465 DWORD
WAVE_mciStop(UINT wDevID
, DWORD dwFlags
, LPMCI_GENERIC_PARMS lpParms
)
468 dprintf_mciwave(stddeb
,
469 "WAVE_mciStop(%u, %08X, %08X);\n", wDevID
, dwFlags
, lpParms
);
470 if (lpParms
== NULL
) return MCIERR_INTERNAL
;
473 return MCIERR_INTERNAL
;
478 /**************************************************************************
479 * WAVE_mciPause [internal]
481 DWORD
WAVE_mciPause(UINT wDevID
, DWORD dwFlags
, LPMCI_GENERIC_PARMS lpParms
)
484 dprintf_mciwave(stddeb
,
485 "WAVE_mciPause(%u, %08X, %08X);\n", wDevID
, dwFlags
, lpParms
);
486 if (lpParms
== NULL
) return MCIERR_INTERNAL
;
489 return MCIERR_INTERNAL
;
494 /**************************************************************************
495 * WAVE_mciResume [internal]
497 DWORD
WAVE_mciResume(UINT wDevID
, DWORD dwFlags
, LPMCI_GENERIC_PARMS lpParms
)
500 dprintf_mciwave(stddeb
,
501 "WAVE_mciResume(%u, %08X, %08X);\n", wDevID
, dwFlags
, lpParms
);
502 if (lpParms
== NULL
) return MCIERR_INTERNAL
;
505 return MCIERR_INTERNAL
;
510 /**************************************************************************
511 * WAVE_mciSet [internal]
513 DWORD
WAVE_mciSet(UINT wDevID
, DWORD dwFlags
, LPMCI_SET_PARMS lpParms
)
516 dprintf_mciwave(stddeb
,
517 "WAVE_mciSet(%u, %08X, %08X);\n", wDevID
, dwFlags
, lpParms
);
518 if (lpParms
== NULL
) return MCIERR_INTERNAL
;
519 dprintf_mciwave(stddeb
,
520 "WAVE_mciSet // dwTimeFormat=%08X\n", lpParms
->dwTimeFormat
);
521 dprintf_mciwave(stddeb
,
522 "WAVE_mciSet // dwAudio=%08X\n", lpParms
->dwAudio
);
523 if (dwFlags
& MCI_SET_TIME_FORMAT
) {
524 switch (lpParms
->dwTimeFormat
) {
525 case MCI_FORMAT_MILLISECONDS
:
526 dprintf_mciwave(stddeb
,
527 "WAVE_mciSet // MCI_FORMAT_MILLISECONDS !\n");
529 case MCI_FORMAT_BYTES
:
530 dprintf_mciwave(stddeb
,
531 "WAVE_mciSet // MCI_FORMAT_BYTES !\n");
533 case MCI_FORMAT_SAMPLES
:
534 dprintf_mciwave(stddeb
,
535 "WAVE_mciSet // MCI_FORMAT_SAMPLES !\n");
539 "WAVE_mciSet // bad time format !\n");
540 return MCIERR_BAD_TIME_FORMAT
;
543 if (dwFlags
& MCI_SET_VIDEO
) return MCIERR_UNSUPPORTED_FUNCTION
;
544 if (dwFlags
& MCI_SET_DOOR_OPEN
) return MCIERR_UNSUPPORTED_FUNCTION
;
545 if (dwFlags
& MCI_SET_DOOR_CLOSED
) return MCIERR_UNSUPPORTED_FUNCTION
;
546 if (dwFlags
& MCI_SET_AUDIO
)
547 dprintf_mciwave(stddeb
,"WAVE_mciSet // MCI_SET_AUDIO !\n");
548 if (dwFlags
&& MCI_SET_ON
) {
549 dprintf_mciwave(stddeb
,"WAVE_mciSet // MCI_SET_ON !\n");
550 if (dwFlags
&& MCI_SET_AUDIO_LEFT
)
551 dprintf_mciwave(stddeb
,"WAVE_mciSet // MCI_SET_AUDIO_LEFT !\n");
552 if (dwFlags
&& MCI_SET_AUDIO_RIGHT
)
553 dprintf_mciwave(stddeb
,"WAVE_mciSet // MCI_SET_AUDIO_RIGHT !\n");
555 if (dwFlags
& MCI_SET_OFF
)
556 dprintf_mciwave(stddeb
,"WAVE_mciSet // MCI_SET_OFF !\n");
557 if (dwFlags
& MCI_WAVE_INPUT
)
558 dprintf_mciwave(stddeb
,"WAVE_mciSet // MCI_WAVE_INPUT !\n");
559 if (dwFlags
& MCI_WAVE_OUTPUT
)
560 dprintf_mciwave(stddeb
,"WAVE_mciSet // MCI_WAVE_OUTPUT !\n");
561 if (dwFlags
& MCI_WAVE_SET_ANYINPUT
)
562 dprintf_mciwave(stddeb
,"WAVE_mciSet // MCI_WAVE_SET_ANYINPUT !\n");
563 if (dwFlags
& MCI_WAVE_SET_ANYOUTPUT
)
564 dprintf_mciwave(stddeb
,"WAVE_mciSet // MCI_WAVE_SET_ANYOUTPUT !\n");
565 if (dwFlags
& MCI_WAVE_SET_AVGBYTESPERSEC
)
566 dprintf_mciwave(stddeb
,
567 "WAVE_mciSet // MCI_WAVE_SET_AVGBYTESPERSEC !\n");
568 if (dwFlags
& MCI_WAVE_SET_BITSPERSAMPLE
)
569 dprintf_mciwave(stddeb
,
570 "WAVE_mciSet // MCI_WAVE_SET_BITSPERSAMPLE !\n");
571 if (dwFlags
& MCI_WAVE_SET_BLOCKALIGN
)
572 dprintf_mciwave(stddeb
,"WAVE_mciSet // MCI_WAVE_SET_BLOCKALIGN !\n");
573 if (dwFlags
& MCI_WAVE_SET_CHANNELS
)
574 dprintf_mciwave(stddeb
,"WAVE_mciSet // MCI_WAVE_SET_CHANNELS !\n");
575 if (dwFlags
& MCI_WAVE_SET_FORMATTAG
)
576 dprintf_mciwave(stddeb
,"WAVE_mciSet // MCI_WAVE_SET_FORMATTAG !\n");
577 if (dwFlags
& MCI_WAVE_SET_SAMPLESPERSEC
)
578 dprintf_mciwave(stddeb
,
579 "WAVE_mciSet // MCI_WAVE_SET_SAMPLESPERSEC !\n");
582 return MCIERR_INTERNAL
;
587 /**************************************************************************
588 * WAVE_mciStatus [internal]
590 DWORD
WAVE_mciStatus(UINT wDevID
, DWORD dwFlags
, LPMCI_STATUS_PARMS lpParms
)
593 dprintf_mciwave(stddeb
,
594 "WAVE_mciStatus(%u, %08X, %08X);\n", wDevID
, dwFlags
, lpParms
);
595 if (lpParms
== NULL
) return MCIERR_INTERNAL
;
596 if (dwFlags
& MCI_STATUS_ITEM
) {
597 switch(lpParms
->dwItem
) {
598 case MCI_STATUS_CURRENT_TRACK
:
599 lpParms
->dwReturn
= 1;
601 case MCI_STATUS_LENGTH
:
602 lpParms
->dwReturn
= 5555;
603 if (dwFlags
& MCI_TRACK
) {
604 lpParms
->dwTrack
= 1;
605 lpParms
->dwReturn
= 2222;
608 case MCI_STATUS_MODE
:
609 lpParms
->dwReturn
= MCI_MODE_STOP
;
611 case MCI_STATUS_MEDIA_PRESENT
:
612 dprintf_mciwave(stddeb
,"WAVE_mciStatus // MCI_STATUS_MEDIA_PRESENT !\n");
613 lpParms
->dwReturn
= TRUE
;
615 case MCI_STATUS_NUMBER_OF_TRACKS
:
616 lpParms
->dwReturn
= 1;
618 case MCI_STATUS_POSITION
:
619 lpParms
->dwReturn
= 3333;
620 if (dwFlags
& MCI_STATUS_START
) {
623 if (dwFlags
& MCI_TRACK
) {
624 lpParms
->dwTrack
= 1;
625 lpParms
->dwReturn
= 777;
628 case MCI_STATUS_READY
:
629 dprintf_mciwave(stddeb
,"WAVE_mciStatus // MCI_STATUS_READY !\n");
630 lpParms
->dwReturn
= TRUE
;
632 case MCI_STATUS_TIME_FORMAT
:
633 dprintf_mciwave(stddeb
,"WAVE_mciStatus // MCI_STATUS_TIME_FORMAT !\n");
634 lpParms
->dwReturn
= MCI_FORMAT_MILLISECONDS
;
637 dprintf_mciwave(stddeb
,"WAVE_mciStatus // MCI_WAVE_INPUT !\n");
638 lpParms
->dwReturn
= 0;
640 case MCI_WAVE_OUTPUT
:
641 dprintf_mciwave(stddeb
,"WAVE_mciStatus // MCI_WAVE_OUTPUT !\n");
642 lpParms
->dwReturn
= 0;
644 case MCI_WAVE_STATUS_AVGBYTESPERSEC
:
645 dprintf_mciwave(stddeb
,"WAVE_mciStatus // MCI_WAVE_STATUS_AVGBYTESPERSEC !\n");
646 lpParms
->dwReturn
= 22050;
648 case MCI_WAVE_STATUS_BITSPERSAMPLE
:
649 dprintf_mciwave(stddeb
,"WAVE_mciStatus // MCI_WAVE_STATUS_BITSPERSAMPLE !\n");
650 lpParms
->dwReturn
= 8;
652 case MCI_WAVE_STATUS_BLOCKALIGN
:
653 dprintf_mciwave(stddeb
,"WAVE_mciStatus // MCI_WAVE_STATUS_BLOCKALIGN !\n");
654 lpParms
->dwReturn
= 1;
656 case MCI_WAVE_STATUS_CHANNELS
:
657 dprintf_mciwave(stddeb
,"WAVE_mciStatus // MCI_WAVE_STATUS_CHANNELS !\n");
658 lpParms
->dwReturn
= 1;
660 case MCI_WAVE_STATUS_FORMATTAG
:
661 dprintf_mciwave(stddeb
,"WAVE_mciStatus // MCI_WAVE_FORMATTAG !\n");
662 lpParms
->dwReturn
= WAVE_FORMAT_PCM
;
664 case MCI_WAVE_STATUS_LEVEL
:
665 dprintf_mciwave(stddeb
,"WAVE_mciStatus // MCI_WAVE_STATUS_LEVEL !\n");
666 lpParms
->dwReturn
= 0xAAAA5555;
668 case MCI_WAVE_STATUS_SAMPLESPERSEC
:
669 dprintf_mciwave(stddeb
,"WAVE_mciStatus // MCI_WAVE_STATUS_SAMPLESPERSEC !\n");
670 lpParms
->dwReturn
= 22050;
673 fprintf(stderr
,"WAVE_mciStatus // unknown command %04X !\n", lpParms
->dwItem
);
674 return MCIERR_UNRECOGNIZED_COMMAND
;
677 if (dwFlags
& MCI_NOTIFY
) {
678 dprintf_mciwave(stddeb
,"WAVE_mciStatus // MCI_NOTIFY_SUCCESSFUL %08X !\n", lpParms
->dwCallback
);
679 mciDriverNotify((HWND
)LOWORD(lpParms
->dwCallback
),
680 MCIWavDev
[wDevID
].wNotifyDeviceID
, MCI_NOTIFY_SUCCESSFUL
);
684 return MCIERR_INTERNAL
;
688 /**************************************************************************
689 * WAVE_mciGetDevCaps [internal]
691 DWORD
WAVE_mciGetDevCaps(UINT wDevID
, DWORD dwFlags
,
692 LPMCI_GETDEVCAPS_PARMS lpParms
)
695 dprintf_mciwave(stddeb
,
696 "WAVE_mciGetDevCaps(%u, %08X, %08X);\n", wDevID
, dwFlags
, lpParms
);
697 if (lpParms
== NULL
) return MCIERR_INTERNAL
;
698 if (dwFlags
& MCI_GETDEVCAPS_ITEM
) {
699 switch(lpParms
->dwItem
) {
700 case MCI_GETDEVCAPS_CAN_RECORD
:
701 lpParms
->dwReturn
= TRUE
;
703 case MCI_GETDEVCAPS_HAS_AUDIO
:
704 lpParms
->dwReturn
= TRUE
;
706 case MCI_GETDEVCAPS_HAS_VIDEO
:
707 lpParms
->dwReturn
= FALSE
;
709 case MCI_GETDEVCAPS_DEVICE_TYPE
:
710 lpParms
->dwReturn
= MCI_DEVTYPE_WAVEFORM_AUDIO
;
712 case MCI_GETDEVCAPS_USES_FILES
:
713 lpParms
->dwReturn
= TRUE
;
715 case MCI_GETDEVCAPS_COMPOUND_DEVICE
:
716 lpParms
->dwReturn
= TRUE
;
718 case MCI_GETDEVCAPS_CAN_EJECT
:
719 lpParms
->dwReturn
= FALSE
;
721 case MCI_GETDEVCAPS_CAN_PLAY
:
722 lpParms
->dwReturn
= TRUE
;
724 case MCI_GETDEVCAPS_CAN_SAVE
:
725 lpParms
->dwReturn
= TRUE
;
727 case MCI_WAVE_GETDEVCAPS_INPUTS
:
728 lpParms
->dwReturn
= 1;
730 case MCI_WAVE_GETDEVCAPS_OUTPUTS
:
731 lpParms
->dwReturn
= 1;
734 return MCIERR_UNRECOGNIZED_COMMAND
;
739 return MCIERR_INTERNAL
;
743 /**************************************************************************
744 * WAVE_mciInfo [internal]
746 DWORD
WAVE_mciInfo(UINT wDevID
, DWORD dwFlags
, LPMCI_INFO_PARMS lpParms
)
749 dprintf_mciwave(stddeb
,
750 "WAVE_mciInfo(%u, %08X, %08X);\n", wDevID
, dwFlags
, lpParms
);
751 if (lpParms
== NULL
) return MCIERR_INTERNAL
;
752 lpParms
->lpstrReturn
= NULL
;
754 case MCI_INFO_PRODUCT
:
755 lpParms
->lpstrReturn
= "Linux Sound System 0.5";
758 lpParms
->lpstrReturn
=
759 (LPSTR
)MCIWavDev
[wDevID
].openParms
.lpstrElementName
;
762 lpParms
->lpstrReturn
= "Linux Sound System 0.5";
764 case MCI_WAVE_OUTPUT
:
765 lpParms
->lpstrReturn
= "Linux Sound System 0.5";
768 return MCIERR_UNRECOGNIZED_COMMAND
;
770 if (lpParms
->lpstrReturn
!= NULL
)
771 lpParms
->dwRetSize
= strlen(lpParms
->lpstrReturn
);
773 lpParms
->dwRetSize
= 0;
776 return MCIERR_INTERNAL
;
781 /*-----------------------------------------------------------------------*/
784 /**************************************************************************
785 * wodGetDevCaps [internal]
787 DWORD
wodGetDevCaps(WORD wDevID
, LPWAVEOUTCAPS lpCaps
, DWORD dwSize
)
795 dprintf_mciwave(stddeb
,
796 "wodGetDevCaps(%u, %08X, %u);\n", wDevID
, lpCaps
, dwSize
);
797 if (lpCaps
== NULL
) return MMSYSERR_NOTENABLED
;
798 audio
= open (SOUND_DEV
, O_WRONLY
, 0);
799 if (audio
== -1) return MMSYSERR_NOTENABLED
;
801 lpCaps
->wMid
= 0x0002;
802 lpCaps
->wPid
= 0x0104;
803 strcpy(lpCaps
->szPname
, "SB16 Wave Out");
805 lpCaps
->wMid
= 0x00FF; /* Manufac ID */
806 lpCaps
->wPid
= 0x0001; /* Product ID */
807 strcpy(lpCaps
->szPname
, "Linux WAVOUT Driver");
809 lpCaps
->dwFormats
= 0x00000000;
810 lpCaps
->dwSupport
= WAVECAPS_VOLUME
;
811 lpCaps
->wChannels
= (IOCTL(audio
, SNDCTL_DSP_STEREO
, dsp_stereo
) != 0) ? 1 : 2;
812 if (lpCaps
->wChannels
> 1) lpCaps
->dwSupport
|= WAVECAPS_LRVOLUME
;
813 bytespersmpl
= (IOCTL(audio
, SNDCTL_DSP_SAMPLESIZE
, samplesize
) != 0) ? 1 : 2;
815 if (IOCTL(audio
, SNDCTL_DSP_SPEED
, smplrate
) == 0) {
816 lpCaps
->dwFormats
|= WAVE_FORMAT_4M08
;
817 if (lpCaps
->wChannels
> 1) lpCaps
->dwFormats
|= WAVE_FORMAT_4S08
;
818 if (bytespersmpl
> 1) {
819 lpCaps
->dwFormats
|= WAVE_FORMAT_4M16
;
820 if (lpCaps
->wChannels
> 1) lpCaps
->dwFormats
|= WAVE_FORMAT_4S16
;
824 if (IOCTL(audio
, SNDCTL_DSP_SPEED
, smplrate
) == 0) {
825 lpCaps
->dwFormats
|= WAVE_FORMAT_2M08
;
826 if (lpCaps
->wChannels
> 1) lpCaps
->dwFormats
|= WAVE_FORMAT_2S08
;
827 if (bytespersmpl
> 1) {
828 lpCaps
->dwFormats
|= WAVE_FORMAT_2M16
;
829 if (lpCaps
->wChannels
> 1) lpCaps
->dwFormats
|= WAVE_FORMAT_2S16
;
833 if (IOCTL(audio
, SNDCTL_DSP_SPEED
, smplrate
) == 0) {
834 lpCaps
->dwFormats
|= WAVE_FORMAT_1M08
;
835 if (lpCaps
->wChannels
> 1) lpCaps
->dwFormats
|= WAVE_FORMAT_1S08
;
836 if (bytespersmpl
> 1) {
837 lpCaps
->dwFormats
|= WAVE_FORMAT_1M16
;
838 if (lpCaps
->wChannels
> 1) lpCaps
->dwFormats
|= WAVE_FORMAT_1S16
;
842 dprintf_mciwave(stddeb
,
843 "wodGetDevCaps // dwFormats = %08X\n", lpCaps
->dwFormats
);
844 return MMSYSERR_NOERROR
;
846 return MMSYSERR_NOTENABLED
;
851 /**************************************************************************
854 DWORD
wodOpen(WORD wDevID
, LPWAVEOPENDESC lpDesc
, DWORD dwFlags
)
862 dprintf_mciwave(stddeb
,
863 "wodOpen(%u, %08X, %08X);\n", wDevID
, lpDesc
, dwFlags
);
864 if (lpDesc
== NULL
) {
865 fprintf(stderr
,"Linux 'wodOpen' // Invalid Parameter !\n");
866 return MMSYSERR_INVALPARAM
;
868 if (wDevID
>= MAX_WAVOUTDRV
) {
869 fprintf(stderr
,"Linux 'wodOpen' // MAX_WAVOUTDRV reached !\n");
870 return MMSYSERR_ALLOCATED
;
872 WOutDev
[wDevID
].unixdev
= 0;
873 audio
= open (SOUND_DEV
, O_WRONLY
, 0);
875 fprintf(stderr
,"Linux 'wodOpen' // can't open !\n");
876 return MMSYSERR_NOTENABLED
;
878 IOCTL(audio
, SNDCTL_DSP_GETBLKSIZE
, abuf_size
);
879 if (abuf_size
< 4096 || abuf_size
> 65536) {
881 fprintf(stderr
,"Linux 'wodOpen' // IOCTL can't 'SNDCTL_DSP_GETBLKSIZE' !\n");
883 fprintf(stderr
,"Linux 'wodOpen' // SNDCTL_DSP_GETBLKSIZE Invalid bufsize !\n");
884 return MMSYSERR_NOTENABLED
;
886 WOutDev
[wDevID
].wFlags
= HIWORD(dwFlags
& CALLBACK_TYPEMASK
);
887 switch(WOutDev
[wDevID
].wFlags
) {
889 fprintf(stderr
,"Linux 'wodOpen' // CALLBACK_NULL !\n");
892 dprintf_mciwave(stddeb
,
893 "Linux 'wodOpen' // CALLBACK_WINDOW !\n");
896 dprintf_mciwave(stddeb
,
897 "Linux 'wodOpen' // CALLBACK_TASK !\n");
900 dprintf_mciwave(stddeb
,
901 "Linux 'wodOpen' // CALLBACK_FUNCTION !\n");
904 WOutDev
[wDevID
].lpQueueHdr
= NULL
;
905 WOutDev
[wDevID
].unixdev
= audio
;
906 WOutDev
[wDevID
].dwTotalPlayed
= 0;
907 WOutDev
[wDevID
].bufsize
= abuf_size
;
908 memcpy(&WOutDev
[wDevID
].waveDesc
, lpDesc
, sizeof(WAVEOPENDESC
));
909 if (lpDesc
->lpFormat
->wFormatTag
!= WAVE_FORMAT_PCM
) {
910 fprintf(stderr
,"Linux 'wodOpen' // Bad format %04X !\n",
911 lpDesc
->lpFormat
->wFormatTag
);
912 return WAVERR_BADFORMAT
;
914 memcpy(&WOutDev
[wDevID
].Format
, lpDesc
->lpFormat
, sizeof(PCMWAVEFORMAT
));
915 if (WOutDev
[wDevID
].Format
.wf
.nChannels
== 0) return WAVERR_BADFORMAT
;
916 if (WOutDev
[wDevID
].Format
.wf
.nSamplesPerSec
== 0) return WAVERR_BADFORMAT
;
917 if (WOutDev
[wDevID
].Format
.wBitsPerSample
== 0) {
918 WOutDev
[wDevID
].Format
.wBitsPerSample
= 8 *
919 (WOutDev
[wDevID
].Format
.wf
.nAvgBytesPerSec
/
920 WOutDev
[wDevID
].Format
.wf
.nSamplesPerSec
) /
921 WOutDev
[wDevID
].Format
.wf
.nChannels
;
923 samplesize
= WOutDev
[wDevID
].Format
.wBitsPerSample
;
924 smplrate
= WOutDev
[wDevID
].Format
.wf
.nSamplesPerSec
;
925 dsp_stereo
= (WOutDev
[wDevID
].Format
.wf
.nChannels
> 1) ? TRUE
: FALSE
;
926 IOCTL(audio
, SNDCTL_DSP_SPEED
, smplrate
);
927 IOCTL(audio
, SNDCTL_DSP_SAMPLESIZE
, samplesize
);
928 IOCTL(audio
, SNDCTL_DSP_STEREO
, dsp_stereo
);
929 dprintf_mciwave(stddeb
,"Linux 'wodOpen' // wBitsPerSample=%u !\n",
930 WOutDev
[wDevID
].Format
.wBitsPerSample
);
931 dprintf_mciwave(stddeb
,"Linux 'wodOpen' // nSamplesPerSec=%u !\n",
932 WOutDev
[wDevID
].Format
.wf
.nSamplesPerSec
);
933 dprintf_mciwave(stddeb
,"Linux 'wodOpen' // nChannels=%u !\n",
934 WOutDev
[wDevID
].Format
.wf
.nChannels
);
935 if (WAVE_NotifyClient(wDevID
, WOM_OPEN
, 0L, 0L) != MMSYSERR_NOERROR
) {
936 fprintf(stderr
,"Linux 'wodOpen' // can't notify client !\n");
937 return MMSYSERR_INVALPARAM
;
939 return MMSYSERR_NOERROR
;
941 return MMSYSERR_NOTENABLED
;
945 /**************************************************************************
946 * wodClose [internal]
948 DWORD
wodClose(WORD wDevID
)
951 dprintf_mciwave(stddeb
,"wodClose(%u);\n", wDevID
);
952 if (WOutDev
[wDevID
].unixdev
== 0) {
953 fprintf(stderr
,"Linux 'wodClose' // can't close !\n");
954 return MMSYSERR_NOTENABLED
;
956 close(WOutDev
[wDevID
].unixdev
);
957 WOutDev
[wDevID
].unixdev
= 0;
958 WOutDev
[wDevID
].bufsize
= 0;
959 if (WAVE_NotifyClient(wDevID
, WOM_CLOSE
, 0L, 0L) != MMSYSERR_NOERROR
) {
960 fprintf(stderr
,"Linux 'wodClose' // can't notify client !\n");
961 return MMSYSERR_INVALPARAM
;
963 return MMSYSERR_NOERROR
;
965 return MMSYSERR_NOTENABLED
;
969 /**************************************************************************
970 * wodWrite [internal]
972 DWORD
wodWrite(WORD wDevID
, LPWAVEHDR lpWaveHdr
, DWORD dwSize
)
975 dprintf_mciwave(stddeb
,"wodWrite(%u, %08X, %08X);\n", wDevID
, lpWaveHdr
, dwSize
);
976 if (WOutDev
[wDevID
].unixdev
== 0) {
977 fprintf(stderr
,"Linux 'wodWrite' // can't play !\n");
978 return MMSYSERR_NOTENABLED
;
980 if (lpWaveHdr
->lpData
== NULL
) return WAVERR_UNPREPARED
;
981 if (!(lpWaveHdr
->dwFlags
& WHDR_PREPARED
)) return WAVERR_UNPREPARED
;
982 if (lpWaveHdr
->dwFlags
& WHDR_INQUEUE
) return WAVERR_STILLPLAYING
;
983 lpWaveHdr
->dwFlags
&= ~WHDR_DONE
;
984 lpWaveHdr
->dwFlags
|= WHDR_INQUEUE
;
985 dprintf_mciwave(stddeb
,
986 "wodWrite() // dwBytesRecorded %u !\n", lpWaveHdr
->dwBytesRecorded
);
987 if (write (WOutDev
[wDevID
].unixdev
, lpWaveHdr
->lpData
,
988 lpWaveHdr
->dwBytesRecorded
) != lpWaveHdr
->dwBytesRecorded
) {
989 return MMSYSERR_NOTENABLED
;
991 lpWaveHdr
->dwFlags
&= ~WHDR_INQUEUE
;
992 lpWaveHdr
->dwFlags
|= WHDR_DONE
;
993 if (WAVE_NotifyClient(wDevID
, WOM_DONE
, 0L, 0L) != MMSYSERR_NOERROR
) {
994 fprintf(stderr
,"Linux 'wodWrite' // can't notify client !\n");
995 return MMSYSERR_INVALPARAM
;
997 return MMSYSERR_NOERROR
;
999 return MMSYSERR_NOTENABLED
;
1003 /**************************************************************************
1004 * wodPrepare [internal]
1006 DWORD
wodPrepare(WORD wDevID
, LPWAVEHDR lpWaveHdr
, DWORD dwSize
)
1009 dprintf_mciwave(stddeb
,
1010 "wodPrepare(%u, %08X, %08X);\n", wDevID
, lpWaveHdr
, dwSize
);
1011 if (WOutDev
[wDevID
].unixdev
== 0) {
1012 fprintf(stderr
,"Linux 'wodPrepare' // can't prepare !\n");
1013 return MMSYSERR_NOTENABLED
;
1015 if (WOutDev
[wDevID
].lpQueueHdr
!= NULL
) {
1016 fprintf(stderr
,"Linux 'wodPrepare' // already prepare !\n");
1017 return MMSYSERR_NOTENABLED
;
1019 WOutDev
[wDevID
].dwTotalPlayed
= 0;
1020 WOutDev
[wDevID
].lpQueueHdr
= lpWaveHdr
;
1021 if (lpWaveHdr
->dwFlags
& WHDR_INQUEUE
) return WAVERR_STILLPLAYING
;
1022 lpWaveHdr
->dwFlags
|= WHDR_PREPARED
;
1023 lpWaveHdr
->dwFlags
&= ~WHDR_DONE
;
1024 return MMSYSERR_NOERROR
;
1026 return MMSYSERR_NOTENABLED
;
1030 /**************************************************************************
1031 * wodUnprepare [internal]
1033 DWORD
wodUnprepare(WORD wDevID
, LPWAVEHDR lpWaveHdr
, DWORD dwSize
)
1036 dprintf_mciwave(stddeb
,
1037 "wodUnprepare(%u, %08X, %08X);\n", wDevID
, lpWaveHdr
, dwSize
);
1038 if (WOutDev
[wDevID
].unixdev
== 0) {
1039 fprintf(stderr
,"Linux 'wodUnprepare' // can't unprepare !\n");
1040 return MMSYSERR_NOTENABLED
;
1042 return MMSYSERR_NOERROR
;
1044 return MMSYSERR_NOTENABLED
;
1048 /**************************************************************************
1049 * wodRestart [internal]
1051 DWORD
wodRestart(WORD wDevID
)
1054 dprintf_mciwave(stddeb
,"wodRestart(%u);\n", wDevID
);
1055 if (WOutDev
[wDevID
].unixdev
== 0) {
1056 fprintf(stderr
,"Linux 'wodRestart' // can't restart !\n");
1057 return MMSYSERR_NOTENABLED
;
1059 return MMSYSERR_NOERROR
;
1061 return MMSYSERR_NOTENABLED
;
1065 /**************************************************************************
1066 * wodReset [internal]
1068 DWORD
wodReset(WORD wDevID
)
1071 dprintf_mciwave(stddeb
,"wodReset(%u);\n", wDevID
);
1072 if (WOutDev
[wDevID
].unixdev
== 0) {
1073 fprintf(stderr
,"Linux 'wodReset' // can't reset !\n");
1074 return MMSYSERR_NOTENABLED
;
1076 return MMSYSERR_NOERROR
;
1078 return MMSYSERR_NOTENABLED
;
1083 /**************************************************************************
1084 * wodGetPosition [internal]
1086 DWORD
wodGetPosition(WORD wDevID
, LPMMTIME lpTime
, DWORD uSize
)
1090 dprintf_mciwave(stddeb
,"wodGetPosition(%u, %08X, %u);\n", wDevID
, lpTime
, uSize
);
1091 if (WOutDev
[wDevID
].unixdev
== 0) {
1092 fprintf(stderr
,"Linux 'wodGetPosition' // can't get pos !\n");
1093 return MMSYSERR_NOTENABLED
;
1095 if (lpTime
== NULL
) return MMSYSERR_INVALPARAM
;
1097 switch(lpTime
->wType
) {
1099 lpTime
->u
.cb
= WOutDev
[wDevID
].dwTotalPlayed
;
1100 dprintf_mciwave(stddeb
,"wodGetPosition // TIME_BYTES=%u\n", lpTime
->u
.cb
);
1103 lpTime
->u
.sample
= WOutDev
[wDevID
].dwTotalPlayed
* 8 /
1104 WOutDev
[wDevID
].Format
.wBitsPerSample
;
1105 dprintf_mciwave(stddeb
,"wodGetPosition // TIME_SAMPLES=%u\n", lpTime
->u
.sample
);
1108 lpTime
->u
.ms
= WOutDev
[wDevID
].dwTotalPlayed
/
1109 (WOutDev
[wDevID
].Format
.wf
.nAvgBytesPerSec
/ 1000);
1110 dprintf_mciwave(stddeb
,"wodGetPosition // TIME_MS=%u\n", lpTime
->u
.ms
);
1113 time
= WOutDev
[wDevID
].dwTotalPlayed
/
1114 (WOutDev
[wDevID
].Format
.wf
.nAvgBytesPerSec
/ 1000);
1115 lpTime
->u
.smpte
.hour
= time
/ 108000;
1116 time
-= lpTime
->u
.smpte
.hour
* 108000;
1117 lpTime
->u
.smpte
.min
= time
/ 1800;
1118 time
-= lpTime
->u
.smpte
.min
* 1800;
1119 lpTime
->u
.smpte
.sec
= time
/ 30;
1120 time
-= lpTime
->u
.smpte
.sec
* 30;
1121 lpTime
->u
.smpte
.frame
= time
;
1122 lpTime
->u
.smpte
.fps
= 30;
1123 dprintf_mciwave(stddeb
,
1124 "wodGetPosition // TIME_SMPTE=%02u:%02u:%02u:%02u\n",
1125 lpTime
->u
.smpte
.hour
, lpTime
->u
.smpte
.min
,
1126 lpTime
->u
.smpte
.sec
, lpTime
->u
.smpte
.frame
);
1129 fprintf(stderr
,"wodGetPosition() format not supported ! use TIME_MS !\n");
1130 lpTime
->wType
= TIME_MS
;
1133 return MMSYSERR_NOERROR
;
1135 return MMSYSERR_NOTENABLED
;
1139 /**************************************************************************
1140 * wodGetVolume [internal]
1142 DWORD
wodGetVolume(WORD wDevID
, LPDWORD lpdwVol
)
1147 dprintf_mciwave(stddeb
,"wodGetVolume(%u, %08X);\n", wDevID
, lpdwVol
);
1148 if (lpdwVol
== NULL
) return MMSYSERR_NOTENABLED
;
1149 if (WOutDev
[wDevID
].unixdev
== 0) {
1150 fprintf(stderr
,"Linux 'wodGetVolume' // can't read volume !\n");
1151 return MMSYSERR_NOTENABLED
;
1153 if ((mixer
= open("/dev/mixer", O_RDONLY
)) < 0) {
1154 fprintf(stderr
, "Linux 'wodGetVolume' // mixer device not available !\n");
1155 return MMSYSERR_NOTENABLED
;
1157 if (ioctl(mixer
, SOUND_MIXER_READ_PCM
, &volume
) == -1) {
1158 fprintf(stderr
,"Linux 'wodGetVolume' // unable read mixer !\n");
1159 return MMSYSERR_NOTENABLED
;
1162 *lpdwVol
= MAKELONG(volume
, volume
);
1163 return MMSYSERR_NOERROR
;
1165 return MMSYSERR_NOTENABLED
;
1170 /**************************************************************************
1171 * wodSetVolume [internal]
1173 DWORD
wodSetVolume(WORD wDevID
, DWORD dwParam
)
1178 dprintf_mciwave(stddeb
,"wodSetVolume(%u, %08X);\n", wDevID
, dwParam
);
1179 volume
= LOWORD(dwParam
);
1180 if (WOutDev
[wDevID
].unixdev
== 0) {
1181 fprintf(stderr
,"Linux 'wodSetVolume' // can't set volume !\n");
1182 return MMSYSERR_NOTENABLED
;
1184 if ((mixer
= open("/dev/mixer", O_WRONLY
)) < 0) {
1185 fprintf(stderr
, "Linux 'wodSetVolume' // mixer device not available !\n");
1186 return MMSYSERR_NOTENABLED
;
1188 if (ioctl(mixer
, SOUND_MIXER_WRITE_PCM
, &volume
) == -1) {
1189 fprintf(stderr
,"Linux 'wodSetVolume' // unable set mixer !\n");
1190 return MMSYSERR_NOTENABLED
;
1193 return MMSYSERR_NOERROR
;
1195 return MMSYSERR_NOTENABLED
;
1200 /**************************************************************************
1201 * wodMessage [sample driver]
1203 DWORD
wodMessage(WORD wDevID
, WORD wMsg
, DWORD dwUser
,
1204 DWORD dwParam1
, DWORD dwParam2
)
1206 dprintf_mciwave(stddeb
,"wodMessage(%u, %04X, %08X, %08X, %08X);\n",
1207 wDevID
, wMsg
, dwUser
, dwParam1
, dwParam2
);
1210 return wodOpen(wDevID
, (LPWAVEOPENDESC
)dwParam1
, dwParam2
);
1212 return wodClose(wDevID
);
1214 return wodWrite(wDevID
, (LPWAVEHDR
)dwParam1
, dwParam2
);
1218 return wodGetPosition(wDevID
, (LPMMTIME
)dwParam1
, dwParam2
);
1219 case WODM_BREAKLOOP
:
1222 return wodPrepare(wDevID
, (LPWAVEHDR
)dwParam1
, dwParam2
);
1223 case WODM_UNPREPARE
:
1224 return wodUnprepare(wDevID
, (LPWAVEHDR
)dwParam1
, dwParam2
);
1225 case WODM_GETDEVCAPS
:
1226 return wodGetDevCaps(wDevID
, (LPWAVEOUTCAPS
)dwParam1
, dwParam2
);
1227 case WODM_GETNUMDEVS
:
1233 case WODM_GETPLAYBACKRATE
:
1235 case WODM_SETPLAYBACKRATE
:
1237 case WODM_GETVOLUME
:
1238 return wodGetVolume(wDevID
, (LPDWORD
)dwParam1
);
1239 case WODM_SETVOLUME
:
1240 return wodSetVolume(wDevID
, dwParam1
);
1242 return wodRestart(wDevID
);
1244 return wodReset(wDevID
);
1246 return MMSYSERR_NOTSUPPORTED
;
1250 /*-----------------------------------------------------------------------*/
1252 /**************************************************************************
1253 * widGetDevCaps [internal]
1255 DWORD
widGetDevCaps(WORD wDevID
, LPWAVEINCAPS lpCaps
, DWORD dwSize
)
1260 int samplesize
= 16;
1263 dprintf_mciwave(stddeb
,
1264 "widGetDevCaps(%u, %08X, %u);\n", wDevID
, lpCaps
, dwSize
);
1265 if (lpCaps
== NULL
) return MMSYSERR_NOTENABLED
;
1266 audio
= open (SOUND_DEV
, O_RDONLY
, 0);
1267 if (audio
== -1) return MMSYSERR_NOTENABLED
;
1269 lpCaps
->wMid
= 0x0002;
1270 lpCaps
->wPid
= 0x0004;
1271 strcpy(lpCaps
->szPname
, "SB16 Wave Out");
1273 lpCaps
->wMid
= 0x00FF; /* Manufac ID */
1274 lpCaps
->wPid
= 0x0001; /* Product ID */
1275 strcpy(lpCaps
->szPname
, "Linux WAVIN Driver");
1277 lpCaps
->dwFormats
= 0x00000000;
1278 lpCaps
->wChannels
= (IOCTL(audio
, SNDCTL_DSP_STEREO
, dsp_stereo
) != 0) ? 1 : 2;
1279 bytespersmpl
= (IOCTL(audio
, SNDCTL_DSP_SAMPLESIZE
, samplesize
) != 0) ? 1 : 2;
1281 if (IOCTL(audio
, SNDCTL_DSP_SPEED
, smplrate
) == 0) {
1282 lpCaps
->dwFormats
|= WAVE_FORMAT_4M08
;
1283 if (lpCaps
->wChannels
> 1) lpCaps
->dwFormats
|= WAVE_FORMAT_4S08
;
1284 if (bytespersmpl
> 1) {
1285 lpCaps
->dwFormats
|= WAVE_FORMAT_4M16
;
1286 if (lpCaps
->wChannels
> 1) lpCaps
->dwFormats
|= WAVE_FORMAT_4S16
;
1290 if (IOCTL(audio
, SNDCTL_DSP_SPEED
, smplrate
) == 0) {
1291 lpCaps
->dwFormats
|= WAVE_FORMAT_2M08
;
1292 if (lpCaps
->wChannels
> 1) lpCaps
->dwFormats
|= WAVE_FORMAT_2S08
;
1293 if (bytespersmpl
> 1) {
1294 lpCaps
->dwFormats
|= WAVE_FORMAT_2M16
;
1295 if (lpCaps
->wChannels
> 1) lpCaps
->dwFormats
|= WAVE_FORMAT_2S16
;
1299 if (IOCTL(audio
, SNDCTL_DSP_SPEED
, smplrate
) == 0) {
1300 lpCaps
->dwFormats
|= WAVE_FORMAT_1M08
;
1301 if (lpCaps
->wChannels
> 1) lpCaps
->dwFormats
|= WAVE_FORMAT_1S08
;
1302 if (bytespersmpl
> 1) {
1303 lpCaps
->dwFormats
|= WAVE_FORMAT_1M16
;
1304 if (lpCaps
->wChannels
> 1) lpCaps
->dwFormats
|= WAVE_FORMAT_1S16
;
1308 dprintf_mciwave(stddeb
,
1309 "widGetDevCaps // dwFormats = %08X\n", lpCaps
->dwFormats
);
1310 return MMSYSERR_NOERROR
;
1312 return MMSYSERR_NOTENABLED
;
1317 /**************************************************************************
1318 * widOpen [internal]
1320 DWORD
widOpen(WORD wDevID
, LPWAVEOPENDESC lpDesc
, DWORD dwFlags
)
1328 dprintf_mciwave(stddeb
,
1329 "widOpen(%u, %08X, %08X);\n", wDevID
, lpDesc
, dwFlags
);
1330 if (lpDesc
== NULL
) {
1331 fprintf(stderr
,"Linux 'widOpen' // Invalid Parameter !\n");
1332 return MMSYSERR_INVALPARAM
;
1334 if (wDevID
>= MAX_WAVINDRV
) {
1335 fprintf(stderr
,"Linux 'widOpen' // MAX_WAVINDRV reached !\n");
1336 return MMSYSERR_ALLOCATED
;
1338 WInDev
[wDevID
].unixdev
= 0;
1339 audio
= open (SOUND_DEV
, O_RDONLY
, 0);
1341 fprintf(stderr
,"Linux 'widOpen' // can't open !\n");
1342 return MMSYSERR_NOTENABLED
;
1344 IOCTL(audio
, SNDCTL_DSP_GETBLKSIZE
, abuf_size
);
1345 if (abuf_size
< 4096 || abuf_size
> 65536) {
1346 if (abuf_size
== -1)
1347 fprintf(stderr
,"Linux 'widOpen' // IOCTL can't 'SNDCTL_DSP_GETBLKSIZE' !\n");
1349 fprintf(stderr
,"Linux 'widOpen' // SNDCTL_DSP_GETBLKSIZE Invalid bufsize !\n");
1350 return MMSYSERR_NOTENABLED
;
1352 WInDev
[wDevID
].wFlags
= HIWORD(dwFlags
& CALLBACK_TYPEMASK
);
1353 switch(WInDev
[wDevID
].wFlags
) {
1355 dprintf_mciwave(stddeb
,
1356 "Linux 'widOpen' // CALLBACK_NULL !\n");
1359 dprintf_mciwave(stddeb
,
1360 "Linux 'widOpen' // CALLBACK_WINDOW !\n");
1363 dprintf_mciwave(stddeb
,
1364 "Linux 'widOpen' // CALLBACK_TASK !\n");
1367 dprintf_mciwave(stddeb
,
1368 "Linux 'widOpen' // CALLBACK_FUNCTION !\n");
1371 WInDev
[wDevID
].lpQueueHdr
= NULL
;
1372 WInDev
[wDevID
].unixdev
= audio
;
1373 WInDev
[wDevID
].bufsize
= abuf_size
;
1374 WInDev
[wDevID
].dwTotalRecorded
= 0;
1375 memcpy(&WInDev
[wDevID
].waveDesc
, lpDesc
, sizeof(WAVEOPENDESC
));
1376 if (lpDesc
->lpFormat
->wFormatTag
!= WAVE_FORMAT_PCM
) {
1377 fprintf(stderr
,"Linux 'widOpen' // Bad format %04X !\n",
1378 lpDesc
->lpFormat
->wFormatTag
);
1379 return WAVERR_BADFORMAT
;
1381 memcpy(&WInDev
[wDevID
].Format
, lpDesc
->lpFormat
, sizeof(PCMWAVEFORMAT
));
1382 WInDev
[wDevID
].Format
.wBitsPerSample
= 8; /* <-------------- */
1383 if (WInDev
[wDevID
].Format
.wf
.nChannels
== 0) return WAVERR_BADFORMAT
;
1384 if (WInDev
[wDevID
].Format
.wf
.nSamplesPerSec
== 0) return WAVERR_BADFORMAT
;
1385 if (WInDev
[wDevID
].Format
.wBitsPerSample
== 0) {
1386 WInDev
[wDevID
].Format
.wBitsPerSample
= 8 *
1387 (WInDev
[wDevID
].Format
.wf
.nAvgBytesPerSec
/
1388 WInDev
[wDevID
].Format
.wf
.nSamplesPerSec
) /
1389 WInDev
[wDevID
].Format
.wf
.nChannels
;
1391 samplesize
= WInDev
[wDevID
].Format
.wBitsPerSample
;
1392 smplrate
= WInDev
[wDevID
].Format
.wf
.nSamplesPerSec
;
1393 dsp_stereo
= (WInDev
[wDevID
].Format
.wf
.nChannels
> 1) ? TRUE
: FALSE
;
1394 IOCTL(audio
, SNDCTL_DSP_SPEED
, smplrate
);
1395 IOCTL(audio
, SNDCTL_DSP_SAMPLESIZE
, samplesize
);
1396 IOCTL(audio
, SNDCTL_DSP_STEREO
, dsp_stereo
);
1397 dprintf_mciwave(stddeb
,"Linux 'widOpen' // wBitsPerSample=%u !\n",
1398 WInDev
[wDevID
].Format
.wBitsPerSample
);
1399 dprintf_mciwave(stddeb
,"Linux 'widOpen' // nSamplesPerSec=%u !\n",
1400 WInDev
[wDevID
].Format
.wf
.nSamplesPerSec
);
1401 dprintf_mciwave(stddeb
,"Linux 'widOpen' // nChannels=%u !\n",
1402 WInDev
[wDevID
].Format
.wf
.nChannels
);
1403 dprintf_mciwave(stddeb
,"Linux 'widOpen' // nAvgBytesPerSec=%u\n",
1404 WInDev
[wDevID
].Format
.wf
.nAvgBytesPerSec
);
1405 if (WAVE_NotifyClient(wDevID
, WIM_OPEN
, 0L, 0L) != MMSYSERR_NOERROR
) {
1406 fprintf(stderr
,"Linux 'widOpen' // can't notify client !\n");
1407 return MMSYSERR_INVALPARAM
;
1409 return MMSYSERR_NOERROR
;
1411 return MMSYSERR_NOTENABLED
;
1415 /**************************************************************************
1416 * widClose [internal]
1418 DWORD
widClose(WORD wDevID
)
1421 dprintf_mciwave(stddeb
,"widClose(%u);\n", wDevID
);
1422 if (WInDev
[wDevID
].unixdev
== 0) {
1423 fprintf(stderr
,"Linux 'widClose' // can't close !\n");
1424 return MMSYSERR_NOTENABLED
;
1426 close(WInDev
[wDevID
].unixdev
);
1427 WInDev
[wDevID
].unixdev
= 0;
1428 WInDev
[wDevID
].bufsize
= 0;
1429 if (WAVE_NotifyClient(wDevID
, WIM_CLOSE
, 0L, 0L) != MMSYSERR_NOERROR
) {
1430 fprintf(stderr
,"Linux 'widClose' // can't notify client !\n");
1431 return MMSYSERR_INVALPARAM
;
1433 return MMSYSERR_NOERROR
;
1435 return MMSYSERR_NOTENABLED
;
1439 /**************************************************************************
1440 * widAddBuffer [internal]
1442 DWORD
widAddBuffer(WORD wDevID
, LPWAVEHDR lpWaveHdr
, DWORD dwSize
)
1447 dprintf_mciwave(stddeb
,
1448 "widAddBuffer(%u, %08X, %08X);\n", wDevID
, lpWaveHdr
, dwSize
);
1449 if (WInDev
[wDevID
].unixdev
== 0) {
1450 fprintf(stderr
,"Linux 'widAddBuffer' // can't do it !\n");
1451 return MMSYSERR_NOTENABLED
;
1453 if (WInDev
[wDevID
].lpQueueHdr
== NULL
||
1454 !(lpWaveHdr
->dwFlags
& WHDR_PREPARED
)) {
1456 "Linux 'widAddBuffer' // never been prepared !\n");
1457 return WAVERR_UNPREPARED
;
1459 if ((lpWaveHdr
->dwFlags
& WHDR_INQUEUE
) &&
1460 (WInDev
[wDevID
].lpQueueHdr
!= lpWaveHdr
)) {
1461 /* except if it's the one just prepared ... */
1463 "Linux 'widAddBuffer' // header already in use !\n");
1464 return WAVERR_STILLPLAYING
;
1466 lpWaveHdr
->dwFlags
|= WHDR_PREPARED
;
1467 lpWaveHdr
->dwFlags
|= WHDR_INQUEUE
;
1468 lpWaveHdr
->dwFlags
&= ~WHDR_DONE
;
1469 lpWaveHdr
->dwBytesRecorded
= 0;
1470 /* added to the queue, except if it's the one just prepared ... */
1471 if (WInDev
[wDevID
].lpQueueHdr
!= lpWaveHdr
) {
1472 lpWIHdr
= WInDev
[wDevID
].lpQueueHdr
;
1473 while (lpWIHdr
->lpNext
!= NULL
) {
1474 lpWIHdr
= lpWIHdr
->lpNext
;
1477 lpWIHdr
->lpNext
= lpWaveHdr
;
1480 dprintf_mciwave(stddeb
,
1481 "widAddBuffer // buffer added ! (now %u in queue)\n", count
);
1482 return MMSYSERR_NOERROR
;
1484 return MMSYSERR_NOTENABLED
;
1488 /**************************************************************************
1489 * widPrepare [internal]
1491 DWORD
widPrepare(WORD wDevID
, LPWAVEHDR lpWaveHdr
, DWORD dwSize
)
1494 dprintf_mciwave(stddeb
,
1495 "widPrepare(%u, %08X, %08X);\n", wDevID
, lpWaveHdr
, dwSize
);
1496 if (WInDev
[wDevID
].unixdev
== 0) {
1497 fprintf(stderr
,"Linux 'widPrepare' // can't prepare !\n");
1498 return MMSYSERR_NOTENABLED
;
1500 if (WInDev
[wDevID
].lpQueueHdr
!= NULL
) {
1501 fprintf(stderr
,"Linux 'widPrepare' // already prepare !\n");
1502 return WAVERR_BADFORMAT
;
1504 WInDev
[wDevID
].dwTotalRecorded
= 0;
1505 WInDev
[wDevID
].lpQueueHdr
= lpWaveHdr
;
1506 if (lpWaveHdr
->dwFlags
& WHDR_INQUEUE
) return WAVERR_STILLPLAYING
;
1507 lpWaveHdr
->dwFlags
|= WHDR_PREPARED
;
1508 lpWaveHdr
->dwFlags
|= WHDR_INQUEUE
;
1509 lpWaveHdr
->dwFlags
&= ~WHDR_DONE
;
1510 lpWaveHdr
->dwBytesRecorded
= 0;
1511 dprintf_mciwave(stddeb
,"Linux 'widPrepare' // header prepared !\n");
1512 return MMSYSERR_NOERROR
;
1514 return MMSYSERR_NOTENABLED
;
1518 /**************************************************************************
1519 * widUnprepare [internal]
1521 DWORD
widUnprepare(WORD wDevID
, LPWAVEHDR lpWaveHdr
, DWORD dwSize
)
1524 dprintf_mciwave(stddeb
,
1525 "widUnprepare(%u, %08X, %08X);\n", wDevID
, lpWaveHdr
, dwSize
);
1526 if (WInDev
[wDevID
].unixdev
== 0) {
1527 fprintf(stderr
,"Linux 'widUnprepare' // can't unprepare !\n");
1528 return MMSYSERR_NOTENABLED
;
1530 lpWaveHdr
->dwFlags
&= ~WHDR_PREPARED
;
1531 lpWaveHdr
->dwFlags
&= ~WHDR_INQUEUE
;
1532 lpWaveHdr
->dwFlags
|= WHDR_DONE
;
1533 WInDev
[wDevID
].lpQueueHdr
= NULL
;
1534 dprintf_mciwave(stddeb
,
1535 "Linux 'widUnprepare' // all headers unprepared !\n");
1536 return MMSYSERR_NOERROR
;
1538 return MMSYSERR_NOTENABLED
;
1542 /**************************************************************************
1543 * widStart [internal]
1545 DWORD
widStart(WORD wDevID
)
1550 dprintf_mciwave(stddeb
,"widStart(%u);\n", wDevID
);
1551 if (WInDev
[wDevID
].unixdev
== 0) {
1553 "Linux 'widStart' // can't start recording !\n");
1554 return MMSYSERR_NOTENABLED
;
1556 if (WInDev
[wDevID
].lpQueueHdr
== NULL
||
1557 WInDev
[wDevID
].lpQueueHdr
->lpData
== NULL
) {
1558 fprintf(stderr
,"Linux 'widStart' // never been prepared !\n");
1559 return WAVERR_UNPREPARED
;
1561 lpWIHdr
= WInDev
[wDevID
].lpQueueHdr
;
1562 while(lpWIHdr
!= NULL
) {
1563 lpWIHdr
->dwBufferLength
&= 0xFFFF;
1564 dprintf_mciwave(stddeb
,
1565 "widStart // recording buf#%u=%08X size=%u \n",
1566 count
, lpWIHdr
->lpData
, lpWIHdr
->dwBufferLength
);
1568 read (WInDev
[wDevID
].unixdev
, lpWIHdr
->lpData
,
1569 lpWIHdr
->dwBufferLength
);
1570 lpWIHdr
->dwBytesRecorded
= lpWIHdr
->dwBufferLength
;
1571 WInDev
[wDevID
].dwTotalRecorded
+= lpWIHdr
->dwBytesRecorded
;
1572 lpWIHdr
->dwFlags
&= ~WHDR_INQUEUE
;
1573 lpWIHdr
->dwFlags
|= WHDR_DONE
;
1574 if (WAVE_NotifyClient(wDevID
, WIM_DATA
, (DWORD
)lpWIHdr
, 0L) !=
1577 "Linux 'widStart' // can't notify client !\n");
1578 return MMSYSERR_INVALPARAM
;
1580 lpWIHdr
= lpWIHdr
->lpNext
;
1583 dprintf_mciwave(stddeb
,"widStart // end of recording !\n");
1585 return MMSYSERR_NOERROR
;
1587 return MMSYSERR_NOTENABLED
;
1591 /**************************************************************************
1592 * widStop [internal]
1594 DWORD
widStop(WORD wDevID
)
1597 dprintf_mciwave(stddeb
,"widStop(%u);\n", wDevID
);
1598 if (WInDev
[wDevID
].unixdev
== 0) {
1599 fprintf(stderr
,"Linux 'widStop' // can't stop !\n");
1600 return MMSYSERR_NOTENABLED
;
1602 return MMSYSERR_NOERROR
;
1604 return MMSYSERR_NOTENABLED
;
1608 /**************************************************************************
1609 * widReset [internal]
1611 DWORD
widReset(WORD wDevID
)
1614 dprintf_mciwave(stddeb
,"widReset(%u);\n", wDevID
);
1615 if (WInDev
[wDevID
].unixdev
== 0) {
1616 fprintf(stderr
,"Linux 'widReset' // can't reset !\n");
1617 return MMSYSERR_NOTENABLED
;
1619 return MMSYSERR_NOERROR
;
1621 return MMSYSERR_NOTENABLED
;
1625 /**************************************************************************
1626 * widGetPosition [internal]
1628 DWORD
widGetPosition(WORD wDevID
, LPMMTIME lpTime
, DWORD uSize
)
1632 dprintf_mciwave(stddeb
,
1633 "widGetPosition(%u, %08X, %u);\n", wDevID
, lpTime
, uSize
);
1634 if (WInDev
[wDevID
].unixdev
== 0) {
1635 fprintf(stderr
,"Linux 'widGetPosition' // can't get pos !\n");
1636 return MMSYSERR_NOTENABLED
;
1638 if (lpTime
== NULL
) return MMSYSERR_INVALPARAM
;
1640 dprintf_mciwave(stddeb
,"widGetPosition // wType=%04X !\n",
1642 dprintf_mciwave(stddeb
,"widGetPosition // wBitsPerSample=%u\n",
1643 WInDev
[wDevID
].Format
.wBitsPerSample
);
1644 dprintf_mciwave(stddeb
,"widGetPosition // nSamplesPerSec=%u\n",
1645 WInDev
[wDevID
].Format
.wf
.nSamplesPerSec
);
1646 dprintf_mciwave(stddeb
,"widGetPosition // nChannels=%u\n",
1647 WInDev
[wDevID
].Format
.wf
.nChannels
);
1648 dprintf_mciwave(stddeb
,"widGetPosition // nAvgBytesPerSec=%u\n",
1649 WInDev
[wDevID
].Format
.wf
.nAvgBytesPerSec
);
1651 switch(lpTime
->wType
) {
1653 lpTime
->u
.cb
= WInDev
[wDevID
].dwTotalRecorded
;
1654 dprintf_mciwave(stddeb
,
1655 "widGetPosition // TIME_BYTES=%u\n", lpTime
->u
.cb
);
1658 lpTime
->u
.sample
= WInDev
[wDevID
].dwTotalRecorded
* 8 /
1659 WInDev
[wDevID
].Format
.wBitsPerSample
;
1660 dprintf_mciwave(stddeb
,
1661 "widGetPosition // TIME_SAMPLES=%u\n",
1665 lpTime
->u
.ms
= WInDev
[wDevID
].dwTotalRecorded
/
1666 (WInDev
[wDevID
].Format
.wf
.nAvgBytesPerSec
/ 1000);
1667 dprintf_mciwave(stddeb
,
1668 "widGetPosition // TIME_MS=%u\n", lpTime
->u
.ms
);
1671 time
= WInDev
[wDevID
].dwTotalRecorded
/
1672 (WInDev
[wDevID
].Format
.wf
.nAvgBytesPerSec
/ 1000);
1673 lpTime
->u
.smpte
.hour
= time
/ 108000;
1674 time
-= lpTime
->u
.smpte
.hour
* 108000;
1675 lpTime
->u
.smpte
.min
= time
/ 1800;
1676 time
-= lpTime
->u
.smpte
.min
* 1800;
1677 lpTime
->u
.smpte
.sec
= time
/ 30;
1678 time
-= lpTime
->u
.smpte
.sec
* 30;
1679 lpTime
->u
.smpte
.frame
= time
;
1680 lpTime
->u
.smpte
.fps
= 30;
1681 dprintf_mciwave(stddeb
,"widGetPosition // TIME_SMPTE=%02u:%02u:%02u:%02u\n",
1682 lpTime
->u
.smpte
.hour
, lpTime
->u
.smpte
.min
,
1683 lpTime
->u
.smpte
.sec
, lpTime
->u
.smpte
.frame
);
1686 fprintf(stderr
,"widGetPosition() format not supported ! use TIME_MS !\n");
1687 lpTime
->wType
= TIME_MS
;
1690 return MMSYSERR_NOERROR
;
1692 return MMSYSERR_NOTENABLED
;
1696 /**************************************************************************
1697 * widMessage [sample driver]
1699 DWORD
widMessage(WORD wDevID
, WORD wMsg
, DWORD dwUser
,
1700 DWORD dwParam1
, DWORD dwParam2
)
1702 dprintf_mciwave(stddeb
,"widMessage(%u, %04X, %08X, %08X, %08X);\n",
1703 wDevID
, wMsg
, dwUser
, dwParam1
, dwParam2
);
1706 return widOpen(wDevID
, (LPWAVEOPENDESC
)dwParam1
, dwParam2
);
1708 return widClose(wDevID
);
1709 case WIDM_ADDBUFFER
:
1710 return widAddBuffer(wDevID
, (LPWAVEHDR
)dwParam1
, dwParam2
);
1712 return widPrepare(wDevID
, (LPWAVEHDR
)dwParam1
, dwParam2
);
1713 case WIDM_UNPREPARE
:
1714 return widUnprepare(wDevID
, (LPWAVEHDR
)dwParam1
, dwParam2
);
1715 case WIDM_GETDEVCAPS
:
1716 return widGetDevCaps(wDevID
, (LPWAVEINCAPS
)dwParam1
, dwParam2
);
1717 case WIDM_GETNUMDEVS
:
1720 return widGetPosition(wDevID
, (LPMMTIME
)dwParam1
, dwParam2
);
1722 return widReset(wDevID
);
1724 return widStart(wDevID
);
1726 return widStop(wDevID
);
1728 return MMSYSERR_NOTSUPPORTED
;
1732 #endif /* #ifdef BUILTIN_MMSYSTEM */