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>
34 #define SOUND_DEV "/dev/dsp"
37 #define IOCTL(a,b,c) ioctl(a,b,&c)
39 #define IOCTL(a,b,c) (c = ioctl(a,b,c) )
42 #define MAX_WAVOUTDRV 2
43 #define MAX_WAVINDRV 2
44 #define MAX_MCIWAVDRV 2
50 WAVEOPENDESC waveDesc
;
60 DWORD bufsize
; /* Linux '/dev/dsp' give us that size */
61 WAVEOPENDESC waveDesc
;
65 DWORD dwTotalRecorded
;
69 int nUseCount
; /* Incremented for each shared open */
70 BOOL fShareable
; /* TRUE if first open was shareable */
71 WORD wNotifyDeviceID
; /* MCI device ID with a pending notification */
72 HANDLE hCallback
; /* Callback handle for pending notification */
73 HMMIO hFile
; /* mmio file handle open as Element */
74 MCI_WAVE_OPEN_PARMS openParms
;
75 PCMWAVEFORMAT WaveFormat
;
79 static LINUX_WAVEOUT WOutDev
[MAX_WAVOUTDRV
];
80 static LINUX_WAVEIN WInDev
[MAX_WAVOUTDRV
];
81 static LINUX_MCIWAVE MCIWavDev
[MAX_MCIWAVDRV
];
84 DWORD
WAVE_mciOpen(DWORD dwFlags
, LPMCI_WAVE_OPEN_PARMS lpParms
);
85 DWORD
WAVE_mciClose(UINT wDevID
, DWORD dwParam
, LPMCI_GENERIC_PARMS lpParms
);
86 DWORD
WAVE_mciPlay(UINT wDevID
, DWORD dwFlags
, LPMCI_PLAY_PARMS lpParms
);
87 DWORD
WAVE_mciRecord(UINT wDevID
, DWORD dwFlags
, LPMCI_RECORD_PARMS lpParms
);
88 DWORD
WAVE_mciStop(UINT wDevID
, DWORD dwFlags
, LPMCI_GENERIC_PARMS lpParms
);
89 DWORD
WAVE_mciPause(UINT wDevID
, DWORD dwFlags
, LPMCI_GENERIC_PARMS lpParms
);
90 DWORD
WAVE_mciResume(UINT wDevID
, DWORD dwFlags
, LPMCI_GENERIC_PARMS lpParms
);
91 DWORD
WAVE_mciSet(UINT wDevID
, DWORD dwFlags
, LPMCI_SET_PARMS lpParms
);
92 DWORD
WAVE_mciStatus(UINT wDevID
, DWORD dwFlags
, LPMCI_STATUS_PARMS lpParms
);
93 DWORD
WAVE_mciGetDevCaps(UINT wDevID
, DWORD dwFlags
, LPMCI_GETDEVCAPS_PARMS lpParms
);
94 DWORD
WAVE_mciInfo(UINT wDevID
, DWORD dwFlags
, LPMCI_INFO_PARMS lpParms
);
96 DWORD
wodGetDevCaps(WORD wDevID
, LPWAVEOUTCAPS lpCaps
, DWORD dwSize
);
97 DWORD
wodOpen(WORD wDevID
, LPWAVEOPENDESC lpDesc
, DWORD dwFlags
);
98 DWORD
wodClose(WORD wDevID
);
99 DWORD
wodWrite(WORD wDevID
, LPWAVEHDR lpWaveHdr
, DWORD dwSize
);
100 DWORD
wodPrepare(WORD wDevID
, LPWAVEHDR lpWaveHdr
, DWORD dwSize
);
101 DWORD
wodUnprepare(WORD wDevID
, LPWAVEHDR lpWaveHdr
, DWORD dwSize
);
104 /**************************************************************************
105 * WAVE_NotifyClient [internal]
107 DWORD
WAVE_NotifyClient(UINT wDevID
, WORD wMsg
,
108 DWORD dwParam1
, DWORD dwParam2
)
111 if (WInDev
[wDevID
].wFlags
!= DCB_NULL
&& !DriverCallback(
112 WInDev
[wDevID
].waveDesc
.dwCallBack
, WInDev
[wDevID
].wFlags
,
113 WInDev
[wDevID
].waveDesc
.hWave
, wMsg
,
114 WInDev
[wDevID
].waveDesc
.dwInstance
, dwParam1
, dwParam2
)) {
115 fprintf(stderr
,"WAVE_NotifyClient // can't notify client !\n");
116 return MMSYSERR_NOERROR
;
120 return MMSYSERR_NOTENABLED
;
125 /**************************************************************************
126 * AUDIO_DriverProc [sample driver]
128 LRESULT
WAVE_DriverProc(DWORD dwDevID
, HDRVR hDriv
, WORD wMsg
,
129 DWORD dwParam1
, DWORD dwParam2
)
145 case DRV_QUERYCONFIGURE
:
148 MessageBox((HWND
)NULL
, "Sample MultiMedia Linux Driver !",
149 "MMLinux Driver", MB_OK
);
152 return (LRESULT
)DRVCNF_RESTART
;
154 return (LRESULT
)DRVCNF_RESTART
;
155 case MCI_OPEN_DRIVER
:
157 return WAVE_mciOpen(dwParam1
, (LPMCI_WAVE_OPEN_PARMS
)dwParam2
);
158 case MCI_CLOSE_DRIVER
:
160 return WAVE_mciClose(dwDevID
, dwParam1
, (LPMCI_GENERIC_PARMS
)dwParam2
);
162 return WAVE_mciPlay(dwDevID
, dwParam1
, (LPMCI_PLAY_PARMS
)dwParam2
);
164 return WAVE_mciRecord(dwDevID
, dwParam1
, (LPMCI_RECORD_PARMS
)dwParam2
);
166 return WAVE_mciStop(dwDevID
, dwParam1
, (LPMCI_GENERIC_PARMS
)dwParam2
);
168 return WAVE_mciSet(dwDevID
, dwParam1
, (LPMCI_SET_PARMS
)dwParam2
);
170 return WAVE_mciPause(dwDevID
, dwParam1
, (LPMCI_GENERIC_PARMS
)dwParam2
);
172 return WAVE_mciResume(dwDevID
, dwParam1
, (LPMCI_GENERIC_PARMS
)dwParam2
);
174 return WAVE_mciStatus(dwDevID
, dwParam1
, (LPMCI_STATUS_PARMS
)dwParam2
);
176 return WAVE_mciGetDevCaps(dwDevID
, dwParam1
, (LPMCI_GETDEVCAPS_PARMS
)dwParam2
);
178 return WAVE_mciInfo(dwDevID
, dwParam1
, (LPMCI_INFO_PARMS
)dwParam2
);
180 return DefDriverProc(dwDevID
, hDriv
, wMsg
, dwParam1
, dwParam2
);
183 return MMSYSERR_NOTENABLED
;
187 /**************************************************************************
189 DWORD
WAVE_mciOpen(DWORD dwFlags
, LPMCI_WAVE_OPEN_PARMS lpParms
)
193 LPPCMWAVEFORMAT lpWaveFormat
;
194 WAVEOPENDESC WaveDesc
;
198 dprintf_mciwave(stddeb
,"WAVE_mciOpen(%08lX, %p)\n", dwFlags
, lpParms
);
199 if (lpParms
== NULL
) return MCIERR_INTERNAL
;
200 wDevID
= lpParms
->wDeviceID
;
201 if (MCIWavDev
[wDevID
].nUseCount
> 0) {
202 /* The driver already open on this channel */
203 /* If the driver was opened shareable before and this open specifies */
204 /* shareable then increment the use count */
205 if (MCIWavDev
[wDevID
].fShareable
&& (dwFlags
& MCI_OPEN_SHAREABLE
))
206 ++MCIWavDev
[wDevID
].nUseCount
;
208 return MCIERR_MUST_USE_SHAREABLE
;
211 MCIWavDev
[wDevID
].nUseCount
= 1;
212 MCIWavDev
[wDevID
].fShareable
= dwFlags
& MCI_OPEN_SHAREABLE
;
214 if (dwFlags
& MCI_OPEN_ELEMENT
) {
215 dprintf_mciwave(stddeb
,"WAVE_mciOpen // MCI_OPEN_ELEMENT '%s' !\n",
216 lpParms
->lpstrElementName
);
217 /* printf("WAVE_mciOpen // cdw='%s'\n", DOS_GetCurrentDir(DOS_GetDefaultDrive())); */
218 if (strlen(lpParms
->lpstrElementName
) > 0) {
219 strcpy(str
, lpParms
->lpstrElementName
);
221 MCIWavDev
[wDevID
].hFile
= mmioOpen(str
, NULL
,
222 MMIO_ALLOCBUF
| MMIO_READWRITE
| MMIO_EXCLUSIVE
);
223 if (MCIWavDev
[wDevID
].hFile
== 0) {
224 fprintf(stderr
,"WAVE_mciOpen // can't find file='%s' !\n", str
);
225 return MCIERR_FILE_NOT_FOUND
;
229 MCIWavDev
[wDevID
].hFile
= 0;
231 dprintf_mciwave(stddeb
,"WAVE_mciOpen // hFile=%u\n", MCIWavDev
[wDevID
].hFile
);
232 memcpy(&MCIWavDev
[wDevID
].openParms
, lpParms
, sizeof(MCI_WAVE_OPEN_PARMS
));
233 MCIWavDev
[wDevID
].wNotifyDeviceID
= lpParms
->wDeviceID
;
234 lpWaveFormat
= &MCIWavDev
[wDevID
].WaveFormat
;
236 WaveDesc
.lpFormat
= (LPWAVEFORMAT
)lpWaveFormat
;
237 lpWaveFormat
->wf
.wFormatTag
= WAVE_FORMAT_PCM
;
238 lpWaveFormat
->wBitsPerSample
= 8;
239 lpWaveFormat
->wf
.nChannels
= 1;
240 lpWaveFormat
->wf
.nSamplesPerSec
= 11025;
241 lpWaveFormat
->wf
.nAvgBytesPerSec
= 11025;
242 lpWaveFormat
->wf
.nBlockAlign
= 1;
243 if (MCIWavDev
[wDevID
].hFile
!= 0) {
246 if (mmioDescend(MCIWavDev
[wDevID
].hFile
, &ckMainRIFF
, NULL
, 0) != 0) {
247 return MCIERR_INTERNAL
;
249 dprintf_mciwave(stddeb
,
250 "WAVE_mciOpen // ParentChunk ckid=%.4s fccType=%.4s cksize=%08lX \n",
251 (LPSTR
)&ckMainRIFF
.ckid
, (LPSTR
)&ckMainRIFF
.fccType
,
253 if ((ckMainRIFF
.ckid
!= FOURCC_RIFF
) ||
254 (ckMainRIFF
.fccType
!= mmioFOURCC('W', 'A', 'V', 'E'))) {
255 return MCIERR_INTERNAL
;
257 mmckInfo
.ckid
= mmioFOURCC('f', 'm', 't', ' ');
258 if (mmioDescend(MCIWavDev
[wDevID
].hFile
, &mmckInfo
, &ckMainRIFF
, MMIO_FINDCHUNK
) != 0) {
259 return MCIERR_INTERNAL
;
261 dprintf_mciwave(stddeb
,
262 "WAVE_mciOpen // Chunk Found ckid=%.4s fccType=%.4s cksize=%08lX \n",
263 (LPSTR
)&mmckInfo
.ckid
, (LPSTR
)&mmckInfo
.fccType
,
265 if (mmioRead(MCIWavDev
[wDevID
].hFile
, (HPSTR
) lpWaveFormat
,
266 (long) sizeof(PCMWAVEFORMAT
)) != (long) sizeof(PCMWAVEFORMAT
)) {
267 return MCIERR_INTERNAL
;
269 mmckInfo
.ckid
= mmioFOURCC('d', 'a', 't', 'a');
270 if (mmioDescend(MCIWavDev
[wDevID
].hFile
, &mmckInfo
, &ckMainRIFF
, MMIO_FINDCHUNK
) != 0) {
271 return MCIERR_INTERNAL
;
273 dprintf_mciwave(stddeb
,
274 "WAVE_mciOpen // Chunk Found ckid=%.4s fccType=%.4s cksize=%08lX \n",
275 (LPSTR
)&mmckInfo
.ckid
, (LPSTR
)&mmckInfo
.fccType
,
277 dprintf_mciwave(stddeb
,
278 "WAVE_mciOpen // nChannels=%d nSamplesPerSec=%ld\n",
279 lpWaveFormat
->wf
.nChannels
, lpWaveFormat
->wf
.nSamplesPerSec
);
280 lpWaveFormat
->wBitsPerSample
= 0;
282 lpWaveFormat
->wf
.nAvgBytesPerSec
=
283 lpWaveFormat
->wf
.nSamplesPerSec
* lpWaveFormat
->wf
.nBlockAlign
;
284 dwRet
= wodMessage(0, WODM_OPEN
, 0, (DWORD
)&WaveDesc
, CALLBACK_NULL
);
285 dwRet
= widMessage(0, WIDM_OPEN
, 0, (DWORD
)&WaveDesc
, CALLBACK_NULL
);
288 return MMSYSERR_NOTENABLED
;
292 /**************************************************************************
293 * WAVE_mciClose [internal]
295 DWORD
WAVE_mciClose(UINT wDevID
, DWORD dwParam
, LPMCI_GENERIC_PARMS lpParms
)
299 dprintf_mciwave(stddeb
,
300 "WAVE_mciClose(%u, %08lX, %p);\n", wDevID
, dwParam
, lpParms
);
301 MCIWavDev
[wDevID
].nUseCount
--;
302 if (MCIWavDev
[wDevID
].nUseCount
== 0) {
303 if (MCIWavDev
[wDevID
].hFile
!= 0) {
304 mmioClose(MCIWavDev
[wDevID
].hFile
, 0);
305 MCIWavDev
[wDevID
].hFile
= 0;
307 dwRet
= wodMessage(0, WODM_CLOSE
, 0, 0L, 0L);
308 if (dwRet
!= MMSYSERR_NOERROR
) return MCIERR_INTERNAL
;
309 dwRet
= widMessage(0, WIDM_CLOSE
, 0, 0L, 0L);
310 if (dwRet
!= MMSYSERR_NOERROR
) return MCIERR_INTERNAL
;
319 /**************************************************************************
320 * WAVE_mciPlay [internal]
322 DWORD
WAVE_mciPlay(UINT wDevID
, DWORD dwFlags
, LPMCI_PLAY_PARMS lpParms
)
329 dprintf_mciwave(stddeb
,
330 "WAVE_mciPlay(%u, %08lX, %p);\n", wDevID
, dwFlags
, lpParms
);
331 if (MCIWavDev
[wDevID
].hFile
== 0) {
332 fprintf(stderr
,"WAVE_mciPlay // can't find file='%s' !\n",
333 MCIWavDev
[wDevID
].openParms
.lpstrElementName
);
334 return MCIERR_FILE_NOT_FOUND
;
336 start
= 1; end
= 99999;
337 if (dwFlags
& MCI_FROM
) {
338 start
= lpParms
->dwFrom
;
339 dprintf_mciwave(stddeb
,
340 "WAVE_mciPlay // MCI_FROM=%d \n", start
);
342 if (dwFlags
& MCI_TO
) {
344 dprintf_mciwave(stddeb
,"WAVE_mciPlay // MCI_TO=%d \n", end
);
347 if (dwFlags
& MCI_NOTIFY
) {
348 dprintf_mciwave(stddeb
,
349 "WAVE_mciPlay // MCI_NOTIFY %08lX !\n", lpParms
->dwCallback
);
353 "WAVE_mciPlay // Can't 'fork' process !\n");
358 dprintf_mciwave(stddeb
,"WAVE_mciPlay // process started ! return to caller...\n");
363 lpWaveHdr
= &MCIWavDev
[wDevID
].WaveHdr
;
364 lpWaveHdr
->lpData
= (LPSTR
) malloc(64000);
365 lpWaveHdr
->dwBufferLength
= 32000;
366 lpWaveHdr
->dwUser
= 0L;
367 lpWaveHdr
->dwFlags
= 0L;
368 lpWaveHdr
->dwLoops
= 0L;
369 dwRet
= wodMessage(0, WODM_PREPARE
, 0, (DWORD
)lpWaveHdr
, sizeof(WAVEHDR
));
370 /* printf("WAVE_mciPlay // after WODM_PREPARE \n"); */
372 count
= mmioRead(MCIWavDev
[wDevID
].hFile
, lpWaveHdr
->lpData
, lpWaveHdr
->dwBufferLength
);
373 if (count
< 1) break;
374 lpWaveHdr
->dwBytesRecorded
= count
;
375 dprintf_mciwave(stddeb
,"WAVE_mciPlay // before WODM_WRITE lpWaveHdr=%p dwBytesRecorded=%lu\n",
376 lpWaveHdr
, lpWaveHdr
->dwBytesRecorded
);
377 dwRet
= wodMessage(0, WODM_WRITE
, 0, (DWORD
)lpWaveHdr
, sizeof(WAVEHDR
));
379 dwRet
= wodMessage(0, WODM_UNPREPARE
, 0, (DWORD
)lpWaveHdr
, sizeof(WAVEHDR
));
380 if (lpWaveHdr
->lpData
!= NULL
) {
381 free(lpWaveHdr
->lpData
);
382 lpWaveHdr
->lpData
= NULL
;
384 if (dwFlags
& MCI_NOTIFY
) {
385 dprintf_mciwave(stddeb
,"WAVE_mciPlay // MCI_NOTIFY_SUCCESSFUL %08lX !\n", lpParms
->dwCallback
);
386 mciDriverNotify((HWND
)LOWORD(lpParms
->dwCallback
),
387 MCIWavDev
[wDevID
].wNotifyDeviceID
, MCI_NOTIFY_SUCCESSFUL
);
392 return MMSYSERR_NOTENABLED
;
397 /**************************************************************************
398 * WAVE_mciRecord [internal]
400 DWORD
WAVE_mciRecord(UINT wDevID
, DWORD dwFlags
, LPMCI_RECORD_PARMS lpParms
)
407 dprintf_mciwave(stddeb
,
408 "WAVE_mciRecord(%u, %08lX, %p);\n", wDevID
, dwFlags
, lpParms
);
409 if (MCIWavDev
[wDevID
].hFile
== 0) {
410 fprintf(stderr
,"WAVE_mciRecord // can't find file='%s' !\n",
411 MCIWavDev
[wDevID
].openParms
.lpstrElementName
);
412 return MCIERR_FILE_NOT_FOUND
;
414 start
= 1; end
= 99999;
415 if (dwFlags
& MCI_FROM
) {
416 start
= lpParms
->dwFrom
;
417 dprintf_mciwave(stddeb
,
418 "WAVE_mciRecord // MCI_FROM=%d \n", start
);
420 if (dwFlags
& MCI_TO
) {
422 dprintf_mciwave(stddeb
,"WAVE_mciRecord // MCI_TO=%d \n", end
);
424 lpWaveHdr
= &MCIWavDev
[wDevID
].WaveHdr
;
425 lpWaveHdr
->lpData
= (LPSTR
) malloc(64000);
426 lpWaveHdr
->dwBufferLength
= 32000;
427 lpWaveHdr
->dwUser
= 0L;
428 lpWaveHdr
->dwFlags
= 0L;
429 lpWaveHdr
->dwLoops
= 0L;
430 dwRet
= widMessage(0, WIDM_PREPARE
, 0, (DWORD
)lpWaveHdr
, sizeof(WAVEHDR
));
431 dprintf_mciwave(stddeb
,"WAVE_mciRecord // after WIDM_PREPARE \n");
433 lpWaveHdr
->dwBytesRecorded
= 0;
434 dwRet
= widMessage(0, WIDM_START
, 0, 0L, 0L);
435 dprintf_mciwave(stddeb
,
436 "WAVE_mciRecord // after WIDM_START lpWaveHdr=%p dwBytesRecorded=%lu\n",
437 lpWaveHdr
, lpWaveHdr
->dwBytesRecorded
);
438 if (lpWaveHdr
->dwBytesRecorded
== 0) break;
440 dprintf_mciwave(stddeb
,"WAVE_mciRecord // before WIDM_UNPREPARE \n");
441 dwRet
= widMessage(0, WIDM_UNPREPARE
, 0, (DWORD
)lpWaveHdr
, sizeof(WAVEHDR
));
442 dprintf_mciwave(stddeb
,"WAVE_mciRecord // after WIDM_UNPREPARE \n");
443 if (lpWaveHdr
->lpData
!= NULL
) {
444 free(lpWaveHdr
->lpData
);
445 lpWaveHdr
->lpData
= NULL
;
447 if (dwFlags
& MCI_NOTIFY
) {
448 dprintf_mciwave(stddeb
,"WAVE_mciRecord // MCI_NOTIFY_SUCCESSFUL %08lX !\n", lpParms
->dwCallback
);
449 mciDriverNotify((HWND
)LOWORD(lpParms
->dwCallback
),
450 MCIWavDev
[wDevID
].wNotifyDeviceID
, MCI_NOTIFY_SUCCESSFUL
);
454 return MMSYSERR_NOTENABLED
;
459 /**************************************************************************
460 * WAVE_mciStop [internal]
462 DWORD
WAVE_mciStop(UINT wDevID
, DWORD dwFlags
, LPMCI_GENERIC_PARMS lpParms
)
465 dprintf_mciwave(stddeb
,
466 "WAVE_mciStop(%u, %08lX, %p);\n", wDevID
, dwFlags
, lpParms
);
467 if (lpParms
== NULL
) return MCIERR_INTERNAL
;
470 return MCIERR_INTERNAL
;
475 /**************************************************************************
476 * WAVE_mciPause [internal]
478 DWORD
WAVE_mciPause(UINT wDevID
, DWORD dwFlags
, LPMCI_GENERIC_PARMS lpParms
)
481 dprintf_mciwave(stddeb
,
482 "WAVE_mciPause(%u, %08lX, %p);\n", wDevID
, dwFlags
, lpParms
);
483 if (lpParms
== NULL
) return MCIERR_INTERNAL
;
486 return MCIERR_INTERNAL
;
491 /**************************************************************************
492 * WAVE_mciResume [internal]
494 DWORD
WAVE_mciResume(UINT wDevID
, DWORD dwFlags
, LPMCI_GENERIC_PARMS lpParms
)
497 dprintf_mciwave(stddeb
,
498 "WAVE_mciResume(%u, %08lX, %p);\n", wDevID
, dwFlags
, lpParms
);
499 if (lpParms
== NULL
) return MCIERR_INTERNAL
;
502 return MCIERR_INTERNAL
;
507 /**************************************************************************
508 * WAVE_mciSet [internal]
510 DWORD
WAVE_mciSet(UINT wDevID
, DWORD dwFlags
, LPMCI_SET_PARMS lpParms
)
513 dprintf_mciwave(stddeb
,
514 "WAVE_mciSet(%u, %08lX, %p);\n", wDevID
, dwFlags
, lpParms
);
515 if (lpParms
== NULL
) return MCIERR_INTERNAL
;
516 dprintf_mciwave(stddeb
,
517 "WAVE_mciSet // dwTimeFormat=%08lX\n", lpParms
->dwTimeFormat
);
518 dprintf_mciwave(stddeb
,
519 "WAVE_mciSet // dwAudio=%08lX\n", lpParms
->dwAudio
);
520 if (dwFlags
& MCI_SET_TIME_FORMAT
) {
521 switch (lpParms
->dwTimeFormat
) {
522 case MCI_FORMAT_MILLISECONDS
:
523 dprintf_mciwave(stddeb
,
524 "WAVE_mciSet // MCI_FORMAT_MILLISECONDS !\n");
526 case MCI_FORMAT_BYTES
:
527 dprintf_mciwave(stddeb
,
528 "WAVE_mciSet // MCI_FORMAT_BYTES !\n");
530 case MCI_FORMAT_SAMPLES
:
531 dprintf_mciwave(stddeb
,
532 "WAVE_mciSet // MCI_FORMAT_SAMPLES !\n");
536 "WAVE_mciSet // bad time format !\n");
537 return MCIERR_BAD_TIME_FORMAT
;
540 if (dwFlags
& MCI_SET_VIDEO
) return MCIERR_UNSUPPORTED_FUNCTION
;
541 if (dwFlags
& MCI_SET_DOOR_OPEN
) return MCIERR_UNSUPPORTED_FUNCTION
;
542 if (dwFlags
& MCI_SET_DOOR_CLOSED
) return MCIERR_UNSUPPORTED_FUNCTION
;
543 if (dwFlags
& MCI_SET_AUDIO
)
544 dprintf_mciwave(stddeb
,"WAVE_mciSet // MCI_SET_AUDIO !\n");
545 if (dwFlags
&& MCI_SET_ON
) {
546 dprintf_mciwave(stddeb
,"WAVE_mciSet // MCI_SET_ON !\n");
547 if (dwFlags
&& MCI_SET_AUDIO_LEFT
)
548 dprintf_mciwave(stddeb
,"WAVE_mciSet // MCI_SET_AUDIO_LEFT !\n");
549 if (dwFlags
&& MCI_SET_AUDIO_RIGHT
)
550 dprintf_mciwave(stddeb
,"WAVE_mciSet // MCI_SET_AUDIO_RIGHT !\n");
552 if (dwFlags
& MCI_SET_OFF
)
553 dprintf_mciwave(stddeb
,"WAVE_mciSet // MCI_SET_OFF !\n");
554 if (dwFlags
& MCI_WAVE_INPUT
)
555 dprintf_mciwave(stddeb
,"WAVE_mciSet // MCI_WAVE_INPUT !\n");
556 if (dwFlags
& MCI_WAVE_OUTPUT
)
557 dprintf_mciwave(stddeb
,"WAVE_mciSet // MCI_WAVE_OUTPUT !\n");
558 if (dwFlags
& MCI_WAVE_SET_ANYINPUT
)
559 dprintf_mciwave(stddeb
,"WAVE_mciSet // MCI_WAVE_SET_ANYINPUT !\n");
560 if (dwFlags
& MCI_WAVE_SET_ANYOUTPUT
)
561 dprintf_mciwave(stddeb
,"WAVE_mciSet // MCI_WAVE_SET_ANYOUTPUT !\n");
562 if (dwFlags
& MCI_WAVE_SET_AVGBYTESPERSEC
)
563 dprintf_mciwave(stddeb
,
564 "WAVE_mciSet // MCI_WAVE_SET_AVGBYTESPERSEC !\n");
565 if (dwFlags
& MCI_WAVE_SET_BITSPERSAMPLE
)
566 dprintf_mciwave(stddeb
,
567 "WAVE_mciSet // MCI_WAVE_SET_BITSPERSAMPLE !\n");
568 if (dwFlags
& MCI_WAVE_SET_BLOCKALIGN
)
569 dprintf_mciwave(stddeb
,"WAVE_mciSet // MCI_WAVE_SET_BLOCKALIGN !\n");
570 if (dwFlags
& MCI_WAVE_SET_CHANNELS
)
571 dprintf_mciwave(stddeb
,"WAVE_mciSet // MCI_WAVE_SET_CHANNELS !\n");
572 if (dwFlags
& MCI_WAVE_SET_FORMATTAG
)
573 dprintf_mciwave(stddeb
,"WAVE_mciSet // MCI_WAVE_SET_FORMATTAG !\n");
574 if (dwFlags
& MCI_WAVE_SET_SAMPLESPERSEC
)
575 dprintf_mciwave(stddeb
,
576 "WAVE_mciSet // MCI_WAVE_SET_SAMPLESPERSEC !\n");
579 return MCIERR_INTERNAL
;
584 /**************************************************************************
585 * WAVE_mciStatus [internal]
587 DWORD
WAVE_mciStatus(UINT wDevID
, DWORD dwFlags
, LPMCI_STATUS_PARMS lpParms
)
590 dprintf_mciwave(stddeb
,
591 "WAVE_mciStatus(%u, %08lX, %p);\n", wDevID
, dwFlags
, lpParms
);
592 if (lpParms
== NULL
) return MCIERR_INTERNAL
;
593 if (dwFlags
& MCI_STATUS_ITEM
) {
594 switch(lpParms
->dwItem
) {
595 case MCI_STATUS_CURRENT_TRACK
:
596 lpParms
->dwReturn
= 1;
598 case MCI_STATUS_LENGTH
:
599 lpParms
->dwReturn
= 5555;
600 if (dwFlags
& MCI_TRACK
) {
601 lpParms
->dwTrack
= 1;
602 lpParms
->dwReturn
= 2222;
605 case MCI_STATUS_MODE
:
606 lpParms
->dwReturn
= MCI_MODE_STOP
;
608 case MCI_STATUS_MEDIA_PRESENT
:
609 dprintf_mciwave(stddeb
,"WAVE_mciStatus // MCI_STATUS_MEDIA_PRESENT !\n");
610 lpParms
->dwReturn
= TRUE
;
612 case MCI_STATUS_NUMBER_OF_TRACKS
:
613 lpParms
->dwReturn
= 1;
615 case MCI_STATUS_POSITION
:
616 lpParms
->dwReturn
= 3333;
617 if (dwFlags
& MCI_STATUS_START
) {
620 if (dwFlags
& MCI_TRACK
) {
621 lpParms
->dwTrack
= 1;
622 lpParms
->dwReturn
= 777;
625 case MCI_STATUS_READY
:
626 dprintf_mciwave(stddeb
,"WAVE_mciStatus // MCI_STATUS_READY !\n");
627 lpParms
->dwReturn
= TRUE
;
629 case MCI_STATUS_TIME_FORMAT
:
630 dprintf_mciwave(stddeb
,"WAVE_mciStatus // MCI_STATUS_TIME_FORMAT !\n");
631 lpParms
->dwReturn
= MCI_FORMAT_MILLISECONDS
;
634 dprintf_mciwave(stddeb
,"WAVE_mciStatus // MCI_WAVE_INPUT !\n");
635 lpParms
->dwReturn
= 0;
637 case MCI_WAVE_OUTPUT
:
638 dprintf_mciwave(stddeb
,"WAVE_mciStatus // MCI_WAVE_OUTPUT !\n");
639 lpParms
->dwReturn
= 0;
641 case MCI_WAVE_STATUS_AVGBYTESPERSEC
:
642 dprintf_mciwave(stddeb
,"WAVE_mciStatus // MCI_WAVE_STATUS_AVGBYTESPERSEC !\n");
643 lpParms
->dwReturn
= 22050;
645 case MCI_WAVE_STATUS_BITSPERSAMPLE
:
646 dprintf_mciwave(stddeb
,"WAVE_mciStatus // MCI_WAVE_STATUS_BITSPERSAMPLE !\n");
647 lpParms
->dwReturn
= 8;
649 case MCI_WAVE_STATUS_BLOCKALIGN
:
650 dprintf_mciwave(stddeb
,"WAVE_mciStatus // MCI_WAVE_STATUS_BLOCKALIGN !\n");
651 lpParms
->dwReturn
= 1;
653 case MCI_WAVE_STATUS_CHANNELS
:
654 dprintf_mciwave(stddeb
,"WAVE_mciStatus // MCI_WAVE_STATUS_CHANNELS !\n");
655 lpParms
->dwReturn
= 1;
657 case MCI_WAVE_STATUS_FORMATTAG
:
658 dprintf_mciwave(stddeb
,"WAVE_mciStatus // MCI_WAVE_FORMATTAG !\n");
659 lpParms
->dwReturn
= WAVE_FORMAT_PCM
;
661 case MCI_WAVE_STATUS_LEVEL
:
662 dprintf_mciwave(stddeb
,"WAVE_mciStatus // MCI_WAVE_STATUS_LEVEL !\n");
663 lpParms
->dwReturn
= 0xAAAA5555;
665 case MCI_WAVE_STATUS_SAMPLESPERSEC
:
666 dprintf_mciwave(stddeb
,"WAVE_mciStatus // MCI_WAVE_STATUS_SAMPLESPERSEC !\n");
667 lpParms
->dwReturn
= 22050;
670 fprintf(stderr
,"WAVE_mciStatus // unknown command %08lX !\n", lpParms
->dwItem
);
671 return MCIERR_UNRECOGNIZED_COMMAND
;
674 if (dwFlags
& MCI_NOTIFY
) {
675 dprintf_mciwave(stddeb
,"WAVE_mciStatus // MCI_NOTIFY_SUCCESSFUL %08lX !\n", lpParms
->dwCallback
);
676 mciDriverNotify((HWND
)LOWORD(lpParms
->dwCallback
),
677 MCIWavDev
[wDevID
].wNotifyDeviceID
, MCI_NOTIFY_SUCCESSFUL
);
681 return MCIERR_INTERNAL
;
685 /**************************************************************************
686 * WAVE_mciGetDevCaps [internal]
688 DWORD
WAVE_mciGetDevCaps(UINT wDevID
, DWORD dwFlags
,
689 LPMCI_GETDEVCAPS_PARMS lpParms
)
692 dprintf_mciwave(stddeb
,
693 "WAVE_mciGetDevCaps(%u, %08lX, %p);\n", wDevID
, dwFlags
, lpParms
);
694 if (lpParms
== NULL
) return MCIERR_INTERNAL
;
695 if (dwFlags
& MCI_GETDEVCAPS_ITEM
) {
696 switch(lpParms
->dwItem
) {
697 case MCI_GETDEVCAPS_CAN_RECORD
:
698 lpParms
->dwReturn
= TRUE
;
700 case MCI_GETDEVCAPS_HAS_AUDIO
:
701 lpParms
->dwReturn
= TRUE
;
703 case MCI_GETDEVCAPS_HAS_VIDEO
:
704 lpParms
->dwReturn
= FALSE
;
706 case MCI_GETDEVCAPS_DEVICE_TYPE
:
707 lpParms
->dwReturn
= MCI_DEVTYPE_WAVEFORM_AUDIO
;
709 case MCI_GETDEVCAPS_USES_FILES
:
710 lpParms
->dwReturn
= TRUE
;
712 case MCI_GETDEVCAPS_COMPOUND_DEVICE
:
713 lpParms
->dwReturn
= TRUE
;
715 case MCI_GETDEVCAPS_CAN_EJECT
:
716 lpParms
->dwReturn
= FALSE
;
718 case MCI_GETDEVCAPS_CAN_PLAY
:
719 lpParms
->dwReturn
= TRUE
;
721 case MCI_GETDEVCAPS_CAN_SAVE
:
722 lpParms
->dwReturn
= TRUE
;
724 case MCI_WAVE_GETDEVCAPS_INPUTS
:
725 lpParms
->dwReturn
= 1;
727 case MCI_WAVE_GETDEVCAPS_OUTPUTS
:
728 lpParms
->dwReturn
= 1;
731 return MCIERR_UNRECOGNIZED_COMMAND
;
736 return MCIERR_INTERNAL
;
740 /**************************************************************************
741 * WAVE_mciInfo [internal]
743 DWORD
WAVE_mciInfo(UINT wDevID
, DWORD dwFlags
, LPMCI_INFO_PARMS lpParms
)
746 dprintf_mciwave(stddeb
,
747 "WAVE_mciInfo(%u, %08lX, %p);\n", wDevID
, dwFlags
, lpParms
);
748 if (lpParms
== NULL
) return MCIERR_INTERNAL
;
749 lpParms
->lpstrReturn
= NULL
;
751 case MCI_INFO_PRODUCT
:
752 lpParms
->lpstrReturn
= "Linux Sound System 0.5";
755 lpParms
->lpstrReturn
=
756 (LPSTR
)MCIWavDev
[wDevID
].openParms
.lpstrElementName
;
759 lpParms
->lpstrReturn
= "Linux Sound System 0.5";
761 case MCI_WAVE_OUTPUT
:
762 lpParms
->lpstrReturn
= "Linux Sound System 0.5";
765 return MCIERR_UNRECOGNIZED_COMMAND
;
767 if (lpParms
->lpstrReturn
!= NULL
)
768 lpParms
->dwRetSize
= strlen(lpParms
->lpstrReturn
);
770 lpParms
->dwRetSize
= 0;
773 return MCIERR_INTERNAL
;
778 /*-----------------------------------------------------------------------*/
781 /**************************************************************************
782 * wodGetDevCaps [internal]
784 DWORD
wodGetDevCaps(WORD wDevID
, LPWAVEOUTCAPS lpCaps
, DWORD dwSize
)
792 dprintf_mciwave(stddeb
,
793 "wodGetDevCaps(%u, %p, %lu);\n", wDevID
, lpCaps
, dwSize
);
794 if (lpCaps
== NULL
) return MMSYSERR_NOTENABLED
;
795 audio
= open (SOUND_DEV
, O_WRONLY
, 0);
796 if (audio
== -1) return MMSYSERR_NOTENABLED
;
798 lpCaps
->wMid
= 0x0002;
799 lpCaps
->wPid
= 0x0104;
800 strcpy(lpCaps
->szPname
, "SB16 Wave Out");
802 lpCaps
->wMid
= 0x00FF; /* Manufac ID */
803 lpCaps
->wPid
= 0x0001; /* Product ID */
804 strcpy(lpCaps
->szPname
, "Linux WAVOUT Driver");
806 lpCaps
->dwFormats
= 0x00000000;
807 lpCaps
->dwSupport
= WAVECAPS_VOLUME
;
808 lpCaps
->wChannels
= (IOCTL(audio
, SNDCTL_DSP_STEREO
, dsp_stereo
) != 0) ? 1 : 2;
809 if (lpCaps
->wChannels
> 1) lpCaps
->dwSupport
|= WAVECAPS_LRVOLUME
;
810 bytespersmpl
= (IOCTL(audio
, SNDCTL_DSP_SAMPLESIZE
, samplesize
) != 0) ? 1 : 2;
812 if (IOCTL(audio
, SNDCTL_DSP_SPEED
, smplrate
) == 0) {
813 lpCaps
->dwFormats
|= WAVE_FORMAT_4M08
;
814 if (lpCaps
->wChannels
> 1) lpCaps
->dwFormats
|= WAVE_FORMAT_4S08
;
815 if (bytespersmpl
> 1) {
816 lpCaps
->dwFormats
|= WAVE_FORMAT_4M16
;
817 if (lpCaps
->wChannels
> 1) lpCaps
->dwFormats
|= WAVE_FORMAT_4S16
;
821 if (IOCTL(audio
, SNDCTL_DSP_SPEED
, smplrate
) == 0) {
822 lpCaps
->dwFormats
|= WAVE_FORMAT_2M08
;
823 if (lpCaps
->wChannels
> 1) lpCaps
->dwFormats
|= WAVE_FORMAT_2S08
;
824 if (bytespersmpl
> 1) {
825 lpCaps
->dwFormats
|= WAVE_FORMAT_2M16
;
826 if (lpCaps
->wChannels
> 1) lpCaps
->dwFormats
|= WAVE_FORMAT_2S16
;
830 if (IOCTL(audio
, SNDCTL_DSP_SPEED
, smplrate
) == 0) {
831 lpCaps
->dwFormats
|= WAVE_FORMAT_1M08
;
832 if (lpCaps
->wChannels
> 1) lpCaps
->dwFormats
|= WAVE_FORMAT_1S08
;
833 if (bytespersmpl
> 1) {
834 lpCaps
->dwFormats
|= WAVE_FORMAT_1M16
;
835 if (lpCaps
->wChannels
> 1) lpCaps
->dwFormats
|= WAVE_FORMAT_1S16
;
839 dprintf_mciwave(stddeb
,
840 "wodGetDevCaps // dwFormats = %08lX\n", lpCaps
->dwFormats
);
841 return MMSYSERR_NOERROR
;
843 return MMSYSERR_NOTENABLED
;
848 /**************************************************************************
851 DWORD
wodOpen(WORD wDevID
, LPWAVEOPENDESC lpDesc
, DWORD dwFlags
)
859 dprintf_mciwave(stddeb
,
860 "wodOpen(%u, %p, %08lX);\n", wDevID
, lpDesc
, dwFlags
);
861 if (lpDesc
== NULL
) {
862 fprintf(stderr
,"Linux 'wodOpen' // Invalid Parameter !\n");
863 return MMSYSERR_INVALPARAM
;
865 if (wDevID
>= MAX_WAVOUTDRV
) {
866 fprintf(stderr
,"Linux 'wodOpen' // MAX_WAVOUTDRV reached !\n");
867 return MMSYSERR_ALLOCATED
;
869 WOutDev
[wDevID
].unixdev
= 0;
870 audio
= open (SOUND_DEV
, O_WRONLY
, 0);
872 fprintf(stderr
,"Linux 'wodOpen' // can't open !\n");
873 return MMSYSERR_NOTENABLED
;
875 IOCTL(audio
, SNDCTL_DSP_GETBLKSIZE
, abuf_size
);
876 if (abuf_size
< 4096 || abuf_size
> 65536) {
878 fprintf(stderr
,"Linux 'wodOpen' // IOCTL can't 'SNDCTL_DSP_GETBLKSIZE' !\n");
880 fprintf(stderr
,"Linux 'wodOpen' // SNDCTL_DSP_GETBLKSIZE Invalid bufsize !\n");
881 return MMSYSERR_NOTENABLED
;
883 WOutDev
[wDevID
].wFlags
= HIWORD(dwFlags
& CALLBACK_TYPEMASK
);
884 switch(WOutDev
[wDevID
].wFlags
) {
886 fprintf(stderr
,"Linux 'wodOpen' // CALLBACK_NULL !\n");
889 dprintf_mciwave(stddeb
,
890 "Linux 'wodOpen' // CALLBACK_WINDOW !\n");
893 dprintf_mciwave(stddeb
,
894 "Linux 'wodOpen' // CALLBACK_TASK !\n");
897 dprintf_mciwave(stddeb
,
898 "Linux 'wodOpen' // CALLBACK_FUNCTION !\n");
901 WOutDev
[wDevID
].lpQueueHdr
= NULL
;
902 WOutDev
[wDevID
].unixdev
= audio
;
903 WOutDev
[wDevID
].dwTotalPlayed
= 0;
904 WOutDev
[wDevID
].bufsize
= abuf_size
;
905 memcpy(&WOutDev
[wDevID
].waveDesc
, lpDesc
, sizeof(WAVEOPENDESC
));
906 if (lpDesc
->lpFormat
->wFormatTag
!= WAVE_FORMAT_PCM
) {
907 fprintf(stderr
,"Linux 'wodOpen' // Bad format %04X !\n",
908 lpDesc
->lpFormat
->wFormatTag
);
909 return WAVERR_BADFORMAT
;
911 memcpy(&WOutDev
[wDevID
].Format
, lpDesc
->lpFormat
, sizeof(PCMWAVEFORMAT
));
912 if (WOutDev
[wDevID
].Format
.wf
.nChannels
== 0) return WAVERR_BADFORMAT
;
913 if (WOutDev
[wDevID
].Format
.wf
.nSamplesPerSec
== 0) return WAVERR_BADFORMAT
;
914 if (WOutDev
[wDevID
].Format
.wBitsPerSample
== 0) {
915 WOutDev
[wDevID
].Format
.wBitsPerSample
= 8 *
916 (WOutDev
[wDevID
].Format
.wf
.nAvgBytesPerSec
/
917 WOutDev
[wDevID
].Format
.wf
.nSamplesPerSec
) /
918 WOutDev
[wDevID
].Format
.wf
.nChannels
;
920 samplesize
= WOutDev
[wDevID
].Format
.wBitsPerSample
;
921 smplrate
= WOutDev
[wDevID
].Format
.wf
.nSamplesPerSec
;
922 dsp_stereo
= (WOutDev
[wDevID
].Format
.wf
.nChannels
> 1) ? TRUE
: FALSE
;
923 IOCTL(audio
, SNDCTL_DSP_SPEED
, smplrate
);
924 IOCTL(audio
, SNDCTL_DSP_SAMPLESIZE
, samplesize
);
925 IOCTL(audio
, SNDCTL_DSP_STEREO
, dsp_stereo
);
926 dprintf_mciwave(stddeb
,"Linux 'wodOpen' // wBitsPerSample=%u !\n",
927 WOutDev
[wDevID
].Format
.wBitsPerSample
);
928 dprintf_mciwave(stddeb
,"Linux 'wodOpen' // nSamplesPerSec=%lu !\n",
929 WOutDev
[wDevID
].Format
.wf
.nSamplesPerSec
);
930 dprintf_mciwave(stddeb
,"Linux 'wodOpen' // nChannels=%u !\n",
931 WOutDev
[wDevID
].Format
.wf
.nChannels
);
932 if (WAVE_NotifyClient(wDevID
, WOM_OPEN
, 0L, 0L) != MMSYSERR_NOERROR
) {
933 fprintf(stderr
,"Linux 'wodOpen' // can't notify client !\n");
934 return MMSYSERR_INVALPARAM
;
936 return MMSYSERR_NOERROR
;
938 return MMSYSERR_NOTENABLED
;
942 /**************************************************************************
943 * wodClose [internal]
945 DWORD
wodClose(WORD wDevID
)
948 dprintf_mciwave(stddeb
,"wodClose(%u);\n", wDevID
);
949 if (WOutDev
[wDevID
].unixdev
== 0) {
950 fprintf(stderr
,"Linux 'wodClose' // can't close !\n");
951 return MMSYSERR_NOTENABLED
;
953 close(WOutDev
[wDevID
].unixdev
);
954 WOutDev
[wDevID
].unixdev
= 0;
955 WOutDev
[wDevID
].bufsize
= 0;
956 if (WAVE_NotifyClient(wDevID
, WOM_CLOSE
, 0L, 0L) != MMSYSERR_NOERROR
) {
957 fprintf(stderr
,"Linux 'wodClose' // can't notify client !\n");
958 return MMSYSERR_INVALPARAM
;
960 return MMSYSERR_NOERROR
;
962 return MMSYSERR_NOTENABLED
;
966 /**************************************************************************
967 * wodWrite [internal]
969 DWORD
wodWrite(WORD wDevID
, LPWAVEHDR lpWaveHdr
, DWORD dwSize
)
972 dprintf_mciwave(stddeb
,"wodWrite(%u, %p, %08lX);\n", wDevID
, lpWaveHdr
, dwSize
);
973 if (WOutDev
[wDevID
].unixdev
== 0) {
974 fprintf(stderr
,"Linux 'wodWrite' // can't play !\n");
975 return MMSYSERR_NOTENABLED
;
977 if (lpWaveHdr
->lpData
== NULL
) return WAVERR_UNPREPARED
;
978 if (!(lpWaveHdr
->dwFlags
& WHDR_PREPARED
)) return WAVERR_UNPREPARED
;
979 if (lpWaveHdr
->dwFlags
& WHDR_INQUEUE
) return WAVERR_STILLPLAYING
;
980 lpWaveHdr
->dwFlags
&= ~WHDR_DONE
;
981 lpWaveHdr
->dwFlags
|= WHDR_INQUEUE
;
982 dprintf_mciwave(stddeb
,
983 "wodWrite() // dwBytesRecorded %lu !\n", lpWaveHdr
->dwBytesRecorded
);
984 if (write (WOutDev
[wDevID
].unixdev
, lpWaveHdr
->lpData
,
985 lpWaveHdr
->dwBytesRecorded
) != lpWaveHdr
->dwBytesRecorded
) {
986 return MMSYSERR_NOTENABLED
;
988 lpWaveHdr
->dwFlags
&= ~WHDR_INQUEUE
;
989 lpWaveHdr
->dwFlags
|= WHDR_DONE
;
990 if (WAVE_NotifyClient(wDevID
, WOM_DONE
, 0L, 0L) != MMSYSERR_NOERROR
) {
991 fprintf(stderr
,"Linux 'wodWrite' // can't notify client !\n");
992 return MMSYSERR_INVALPARAM
;
994 return MMSYSERR_NOERROR
;
996 return MMSYSERR_NOTENABLED
;
1000 /**************************************************************************
1001 * wodPrepare [internal]
1003 DWORD
wodPrepare(WORD wDevID
, LPWAVEHDR lpWaveHdr
, DWORD dwSize
)
1006 dprintf_mciwave(stddeb
,
1007 "wodPrepare(%u, %p, %08lX);\n", wDevID
, lpWaveHdr
, dwSize
);
1008 if (WOutDev
[wDevID
].unixdev
== 0) {
1009 fprintf(stderr
,"Linux 'wodPrepare' // can't prepare !\n");
1010 return MMSYSERR_NOTENABLED
;
1012 if (WOutDev
[wDevID
].lpQueueHdr
!= NULL
) {
1013 fprintf(stderr
,"Linux 'wodPrepare' // already prepare !\n");
1014 return MMSYSERR_NOTENABLED
;
1016 WOutDev
[wDevID
].dwTotalPlayed
= 0;
1017 WOutDev
[wDevID
].lpQueueHdr
= lpWaveHdr
;
1018 if (lpWaveHdr
->dwFlags
& WHDR_INQUEUE
) return WAVERR_STILLPLAYING
;
1019 lpWaveHdr
->dwFlags
|= WHDR_PREPARED
;
1020 lpWaveHdr
->dwFlags
&= ~WHDR_DONE
;
1021 return MMSYSERR_NOERROR
;
1023 return MMSYSERR_NOTENABLED
;
1027 /**************************************************************************
1028 * wodUnprepare [internal]
1030 DWORD
wodUnprepare(WORD wDevID
, LPWAVEHDR lpWaveHdr
, DWORD dwSize
)
1033 dprintf_mciwave(stddeb
,
1034 "wodUnprepare(%u, %p, %08lX);\n", wDevID
, lpWaveHdr
, dwSize
);
1035 if (WOutDev
[wDevID
].unixdev
== 0) {
1036 fprintf(stderr
,"Linux 'wodUnprepare' // can't unprepare !\n");
1037 return MMSYSERR_NOTENABLED
;
1039 return MMSYSERR_NOERROR
;
1041 return MMSYSERR_NOTENABLED
;
1045 /**************************************************************************
1046 * wodRestart [internal]
1048 DWORD
wodRestart(WORD wDevID
)
1051 dprintf_mciwave(stddeb
,"wodRestart(%u);\n", wDevID
);
1052 if (WOutDev
[wDevID
].unixdev
== 0) {
1053 fprintf(stderr
,"Linux 'wodRestart' // can't restart !\n");
1054 return MMSYSERR_NOTENABLED
;
1056 return MMSYSERR_NOERROR
;
1058 return MMSYSERR_NOTENABLED
;
1062 /**************************************************************************
1063 * wodReset [internal]
1065 DWORD
wodReset(WORD wDevID
)
1068 dprintf_mciwave(stddeb
,"wodReset(%u);\n", wDevID
);
1069 if (WOutDev
[wDevID
].unixdev
== 0) {
1070 fprintf(stderr
,"Linux 'wodReset' // can't reset !\n");
1071 return MMSYSERR_NOTENABLED
;
1073 return MMSYSERR_NOERROR
;
1075 return MMSYSERR_NOTENABLED
;
1080 /**************************************************************************
1081 * wodGetPosition [internal]
1083 DWORD
wodGetPosition(WORD wDevID
, LPMMTIME lpTime
, DWORD uSize
)
1087 dprintf_mciwave(stddeb
,"wodGetPosition(%u, %p, %lu);\n", wDevID
, lpTime
, uSize
);
1088 if (WOutDev
[wDevID
].unixdev
== 0) {
1089 fprintf(stderr
,"Linux 'wodGetPosition' // can't get pos !\n");
1090 return MMSYSERR_NOTENABLED
;
1092 if (lpTime
== NULL
) return MMSYSERR_INVALPARAM
;
1094 switch(lpTime
->wType
) {
1096 lpTime
->u
.cb
= WOutDev
[wDevID
].dwTotalPlayed
;
1097 dprintf_mciwave(stddeb
,"wodGetPosition // TIME_BYTES=%lu\n", lpTime
->u
.cb
);
1100 lpTime
->u
.sample
= WOutDev
[wDevID
].dwTotalPlayed
* 8 /
1101 WOutDev
[wDevID
].Format
.wBitsPerSample
;
1102 dprintf_mciwave(stddeb
,"wodGetPosition // TIME_SAMPLES=%lu\n", lpTime
->u
.sample
);
1105 lpTime
->u
.ms
= WOutDev
[wDevID
].dwTotalPlayed
/
1106 (WOutDev
[wDevID
].Format
.wf
.nAvgBytesPerSec
/ 1000);
1107 dprintf_mciwave(stddeb
,"wodGetPosition // TIME_MS=%lu\n", lpTime
->u
.ms
);
1110 time
= WOutDev
[wDevID
].dwTotalPlayed
/
1111 (WOutDev
[wDevID
].Format
.wf
.nAvgBytesPerSec
/ 1000);
1112 lpTime
->u
.smpte
.hour
= time
/ 108000;
1113 time
-= lpTime
->u
.smpte
.hour
* 108000;
1114 lpTime
->u
.smpte
.min
= time
/ 1800;
1115 time
-= lpTime
->u
.smpte
.min
* 1800;
1116 lpTime
->u
.smpte
.sec
= time
/ 30;
1117 time
-= lpTime
->u
.smpte
.sec
* 30;
1118 lpTime
->u
.smpte
.frame
= time
;
1119 lpTime
->u
.smpte
.fps
= 30;
1120 dprintf_mciwave(stddeb
,
1121 "wodGetPosition // TIME_SMPTE=%02u:%02u:%02u:%02u\n",
1122 lpTime
->u
.smpte
.hour
, lpTime
->u
.smpte
.min
,
1123 lpTime
->u
.smpte
.sec
, lpTime
->u
.smpte
.frame
);
1126 fprintf(stderr
,"wodGetPosition() format not supported ! use TIME_MS !\n");
1127 lpTime
->wType
= TIME_MS
;
1130 return MMSYSERR_NOERROR
;
1132 return MMSYSERR_NOTENABLED
;
1136 /**************************************************************************
1137 * wodGetVolume [internal]
1139 DWORD
wodGetVolume(WORD wDevID
, LPDWORD lpdwVol
)
1144 dprintf_mciwave(stddeb
,"wodGetVolume(%u, %p);\n", wDevID
, lpdwVol
);
1145 if (lpdwVol
== NULL
) return MMSYSERR_NOTENABLED
;
1146 if (WOutDev
[wDevID
].unixdev
== 0) {
1147 fprintf(stderr
,"Linux 'wodGetVolume' // can't read volume !\n");
1148 return MMSYSERR_NOTENABLED
;
1150 if ((mixer
= open("/dev/mixer", O_RDONLY
)) < 0) {
1151 fprintf(stderr
, "Linux 'wodGetVolume' // mixer device not available !\n");
1152 return MMSYSERR_NOTENABLED
;
1154 if (ioctl(mixer
, SOUND_MIXER_READ_PCM
, &volume
) == -1) {
1155 fprintf(stderr
,"Linux 'wodGetVolume' // unable read mixer !\n");
1156 return MMSYSERR_NOTENABLED
;
1159 *lpdwVol
= MAKELONG(volume
, volume
);
1160 return MMSYSERR_NOERROR
;
1162 return MMSYSERR_NOTENABLED
;
1167 /**************************************************************************
1168 * wodSetVolume [internal]
1170 DWORD
wodSetVolume(WORD wDevID
, DWORD dwParam
)
1175 dprintf_mciwave(stddeb
,"wodSetVolume(%u, %08lX);\n", wDevID
, dwParam
);
1176 volume
= LOWORD(dwParam
);
1177 if (WOutDev
[wDevID
].unixdev
== 0) {
1178 fprintf(stderr
,"Linux 'wodSetVolume' // can't set volume !\n");
1179 return MMSYSERR_NOTENABLED
;
1181 if ((mixer
= open("/dev/mixer", O_WRONLY
)) < 0) {
1182 fprintf(stderr
, "Linux 'wodSetVolume' // mixer device not available !\n");
1183 return MMSYSERR_NOTENABLED
;
1185 if (ioctl(mixer
, SOUND_MIXER_WRITE_PCM
, &volume
) == -1) {
1186 fprintf(stderr
,"Linux 'wodSetVolume' // unable set mixer !\n");
1187 return MMSYSERR_NOTENABLED
;
1190 return MMSYSERR_NOERROR
;
1192 return MMSYSERR_NOTENABLED
;
1197 /**************************************************************************
1198 * wodMessage [sample driver]
1200 DWORD
wodMessage(WORD wDevID
, WORD wMsg
, DWORD dwUser
,
1201 DWORD dwParam1
, DWORD dwParam2
)
1203 dprintf_mciwave(stddeb
,"wodMessage(%u, %04X, %08lX, %08lX, %08lX);\n",
1204 wDevID
, wMsg
, dwUser
, dwParam1
, dwParam2
);
1207 return wodOpen(wDevID
, (LPWAVEOPENDESC
)dwParam1
, dwParam2
);
1209 return wodClose(wDevID
);
1211 return wodWrite(wDevID
, (LPWAVEHDR
)dwParam1
, dwParam2
);
1215 return wodGetPosition(wDevID
, (LPMMTIME
)dwParam1
, dwParam2
);
1216 case WODM_BREAKLOOP
:
1219 return wodPrepare(wDevID
, (LPWAVEHDR
)dwParam1
, dwParam2
);
1220 case WODM_UNPREPARE
:
1221 return wodUnprepare(wDevID
, (LPWAVEHDR
)dwParam1
, dwParam2
);
1222 case WODM_GETDEVCAPS
:
1223 return wodGetDevCaps(wDevID
, (LPWAVEOUTCAPS
)dwParam1
, dwParam2
);
1224 case WODM_GETNUMDEVS
:
1230 case WODM_GETPLAYBACKRATE
:
1232 case WODM_SETPLAYBACKRATE
:
1234 case WODM_GETVOLUME
:
1235 return wodGetVolume(wDevID
, (LPDWORD
)dwParam1
);
1236 case WODM_SETVOLUME
:
1237 return wodSetVolume(wDevID
, dwParam1
);
1239 return wodRestart(wDevID
);
1241 return wodReset(wDevID
);
1243 return MMSYSERR_NOTSUPPORTED
;
1247 /*-----------------------------------------------------------------------*/
1249 /**************************************************************************
1250 * widGetDevCaps [internal]
1252 DWORD
widGetDevCaps(WORD wDevID
, LPWAVEINCAPS lpCaps
, DWORD dwSize
)
1257 int samplesize
= 16;
1260 dprintf_mciwave(stddeb
,
1261 "widGetDevCaps(%u, %p, %lu);\n", wDevID
, lpCaps
, dwSize
);
1262 if (lpCaps
== NULL
) return MMSYSERR_NOTENABLED
;
1263 audio
= open (SOUND_DEV
, O_RDONLY
, 0);
1264 if (audio
== -1) return MMSYSERR_NOTENABLED
;
1266 lpCaps
->wMid
= 0x0002;
1267 lpCaps
->wPid
= 0x0004;
1268 strcpy(lpCaps
->szPname
, "SB16 Wave Out");
1270 lpCaps
->wMid
= 0x00FF; /* Manufac ID */
1271 lpCaps
->wPid
= 0x0001; /* Product ID */
1272 strcpy(lpCaps
->szPname
, "Linux WAVIN Driver");
1274 lpCaps
->dwFormats
= 0x00000000;
1275 lpCaps
->wChannels
= (IOCTL(audio
, SNDCTL_DSP_STEREO
, dsp_stereo
) != 0) ? 1 : 2;
1276 bytespersmpl
= (IOCTL(audio
, SNDCTL_DSP_SAMPLESIZE
, samplesize
) != 0) ? 1 : 2;
1278 if (IOCTL(audio
, SNDCTL_DSP_SPEED
, smplrate
) == 0) {
1279 lpCaps
->dwFormats
|= WAVE_FORMAT_4M08
;
1280 if (lpCaps
->wChannels
> 1) lpCaps
->dwFormats
|= WAVE_FORMAT_4S08
;
1281 if (bytespersmpl
> 1) {
1282 lpCaps
->dwFormats
|= WAVE_FORMAT_4M16
;
1283 if (lpCaps
->wChannels
> 1) lpCaps
->dwFormats
|= WAVE_FORMAT_4S16
;
1287 if (IOCTL(audio
, SNDCTL_DSP_SPEED
, smplrate
) == 0) {
1288 lpCaps
->dwFormats
|= WAVE_FORMAT_2M08
;
1289 if (lpCaps
->wChannels
> 1) lpCaps
->dwFormats
|= WAVE_FORMAT_2S08
;
1290 if (bytespersmpl
> 1) {
1291 lpCaps
->dwFormats
|= WAVE_FORMAT_2M16
;
1292 if (lpCaps
->wChannels
> 1) lpCaps
->dwFormats
|= WAVE_FORMAT_2S16
;
1296 if (IOCTL(audio
, SNDCTL_DSP_SPEED
, smplrate
) == 0) {
1297 lpCaps
->dwFormats
|= WAVE_FORMAT_1M08
;
1298 if (lpCaps
->wChannels
> 1) lpCaps
->dwFormats
|= WAVE_FORMAT_1S08
;
1299 if (bytespersmpl
> 1) {
1300 lpCaps
->dwFormats
|= WAVE_FORMAT_1M16
;
1301 if (lpCaps
->wChannels
> 1) lpCaps
->dwFormats
|= WAVE_FORMAT_1S16
;
1305 dprintf_mciwave(stddeb
,
1306 "widGetDevCaps // dwFormats = %08lX\n", lpCaps
->dwFormats
);
1307 return MMSYSERR_NOERROR
;
1309 return MMSYSERR_NOTENABLED
;
1314 /**************************************************************************
1315 * widOpen [internal]
1317 DWORD
widOpen(WORD wDevID
, LPWAVEOPENDESC lpDesc
, DWORD dwFlags
)
1325 dprintf_mciwave(stddeb
,
1326 "widOpen(%u, %p, %08lX);\n", wDevID
, lpDesc
, dwFlags
);
1327 if (lpDesc
== NULL
) {
1328 fprintf(stderr
,"Linux 'widOpen' // Invalid Parameter !\n");
1329 return MMSYSERR_INVALPARAM
;
1331 if (wDevID
>= MAX_WAVINDRV
) {
1332 fprintf(stderr
,"Linux 'widOpen' // MAX_WAVINDRV reached !\n");
1333 return MMSYSERR_ALLOCATED
;
1335 WInDev
[wDevID
].unixdev
= 0;
1336 audio
= open (SOUND_DEV
, O_RDONLY
, 0);
1338 fprintf(stderr
,"Linux 'widOpen' // can't open !\n");
1339 return MMSYSERR_NOTENABLED
;
1341 IOCTL(audio
, SNDCTL_DSP_GETBLKSIZE
, abuf_size
);
1342 if (abuf_size
< 4096 || abuf_size
> 65536) {
1343 if (abuf_size
== -1)
1344 fprintf(stderr
,"Linux 'widOpen' // IOCTL can't 'SNDCTL_DSP_GETBLKSIZE' !\n");
1346 fprintf(stderr
,"Linux 'widOpen' // SNDCTL_DSP_GETBLKSIZE Invalid bufsize !\n");
1347 return MMSYSERR_NOTENABLED
;
1349 WInDev
[wDevID
].wFlags
= HIWORD(dwFlags
& CALLBACK_TYPEMASK
);
1350 switch(WInDev
[wDevID
].wFlags
) {
1352 dprintf_mciwave(stddeb
,
1353 "Linux 'widOpen' // CALLBACK_NULL !\n");
1356 dprintf_mciwave(stddeb
,
1357 "Linux 'widOpen' // CALLBACK_WINDOW !\n");
1360 dprintf_mciwave(stddeb
,
1361 "Linux 'widOpen' // CALLBACK_TASK !\n");
1364 dprintf_mciwave(stddeb
,
1365 "Linux 'widOpen' // CALLBACK_FUNCTION !\n");
1368 WInDev
[wDevID
].lpQueueHdr
= NULL
;
1369 WInDev
[wDevID
].unixdev
= audio
;
1370 WInDev
[wDevID
].bufsize
= abuf_size
;
1371 WInDev
[wDevID
].dwTotalRecorded
= 0;
1372 memcpy(&WInDev
[wDevID
].waveDesc
, lpDesc
, sizeof(WAVEOPENDESC
));
1373 if (lpDesc
->lpFormat
->wFormatTag
!= WAVE_FORMAT_PCM
) {
1374 fprintf(stderr
,"Linux 'widOpen' // Bad format %04X !\n",
1375 lpDesc
->lpFormat
->wFormatTag
);
1376 return WAVERR_BADFORMAT
;
1378 memcpy(&WInDev
[wDevID
].Format
, lpDesc
->lpFormat
, sizeof(PCMWAVEFORMAT
));
1379 WInDev
[wDevID
].Format
.wBitsPerSample
= 8; /* <-------------- */
1380 if (WInDev
[wDevID
].Format
.wf
.nChannels
== 0) return WAVERR_BADFORMAT
;
1381 if (WInDev
[wDevID
].Format
.wf
.nSamplesPerSec
== 0) return WAVERR_BADFORMAT
;
1382 if (WInDev
[wDevID
].Format
.wBitsPerSample
== 0) {
1383 WInDev
[wDevID
].Format
.wBitsPerSample
= 8 *
1384 (WInDev
[wDevID
].Format
.wf
.nAvgBytesPerSec
/
1385 WInDev
[wDevID
].Format
.wf
.nSamplesPerSec
) /
1386 WInDev
[wDevID
].Format
.wf
.nChannels
;
1388 samplesize
= WInDev
[wDevID
].Format
.wBitsPerSample
;
1389 smplrate
= WInDev
[wDevID
].Format
.wf
.nSamplesPerSec
;
1390 dsp_stereo
= (WInDev
[wDevID
].Format
.wf
.nChannels
> 1) ? TRUE
: FALSE
;
1391 IOCTL(audio
, SNDCTL_DSP_SPEED
, smplrate
);
1392 IOCTL(audio
, SNDCTL_DSP_SAMPLESIZE
, samplesize
);
1393 IOCTL(audio
, SNDCTL_DSP_STEREO
, dsp_stereo
);
1394 dprintf_mciwave(stddeb
,"Linux 'widOpen' // wBitsPerSample=%u !\n",
1395 WInDev
[wDevID
].Format
.wBitsPerSample
);
1396 dprintf_mciwave(stddeb
,"Linux 'widOpen' // nSamplesPerSec=%lu !\n",
1397 WInDev
[wDevID
].Format
.wf
.nSamplesPerSec
);
1398 dprintf_mciwave(stddeb
,"Linux 'widOpen' // nChannels=%u !\n",
1399 WInDev
[wDevID
].Format
.wf
.nChannels
);
1400 dprintf_mciwave(stddeb
,"Linux 'widOpen' // nAvgBytesPerSec=%lu\n",
1401 WInDev
[wDevID
].Format
.wf
.nAvgBytesPerSec
);
1402 if (WAVE_NotifyClient(wDevID
, WIM_OPEN
, 0L, 0L) != MMSYSERR_NOERROR
) {
1403 fprintf(stderr
,"Linux 'widOpen' // can't notify client !\n");
1404 return MMSYSERR_INVALPARAM
;
1406 return MMSYSERR_NOERROR
;
1408 return MMSYSERR_NOTENABLED
;
1412 /**************************************************************************
1413 * widClose [internal]
1415 DWORD
widClose(WORD wDevID
)
1418 dprintf_mciwave(stddeb
,"widClose(%u);\n", wDevID
);
1419 if (WInDev
[wDevID
].unixdev
== 0) {
1420 fprintf(stderr
,"Linux 'widClose' // can't close !\n");
1421 return MMSYSERR_NOTENABLED
;
1423 close(WInDev
[wDevID
].unixdev
);
1424 WInDev
[wDevID
].unixdev
= 0;
1425 WInDev
[wDevID
].bufsize
= 0;
1426 if (WAVE_NotifyClient(wDevID
, WIM_CLOSE
, 0L, 0L) != MMSYSERR_NOERROR
) {
1427 fprintf(stderr
,"Linux 'widClose' // can't notify client !\n");
1428 return MMSYSERR_INVALPARAM
;
1430 return MMSYSERR_NOERROR
;
1432 return MMSYSERR_NOTENABLED
;
1436 /**************************************************************************
1437 * widAddBuffer [internal]
1439 DWORD
widAddBuffer(WORD wDevID
, LPWAVEHDR lpWaveHdr
, DWORD dwSize
)
1444 dprintf_mciwave(stddeb
,
1445 "widAddBuffer(%u, %p, %08lX);\n", wDevID
, lpWaveHdr
, dwSize
);
1446 if (WInDev
[wDevID
].unixdev
== 0) {
1447 fprintf(stderr
,"Linux 'widAddBuffer' // can't do it !\n");
1448 return MMSYSERR_NOTENABLED
;
1450 if (WInDev
[wDevID
].lpQueueHdr
== NULL
||
1451 !(lpWaveHdr
->dwFlags
& WHDR_PREPARED
)) {
1453 "Linux 'widAddBuffer' // never been prepared !\n");
1454 return WAVERR_UNPREPARED
;
1456 if ((lpWaveHdr
->dwFlags
& WHDR_INQUEUE
) &&
1457 (WInDev
[wDevID
].lpQueueHdr
!= lpWaveHdr
)) {
1458 /* except if it's the one just prepared ... */
1460 "Linux 'widAddBuffer' // header already in use !\n");
1461 return WAVERR_STILLPLAYING
;
1463 lpWaveHdr
->dwFlags
|= WHDR_PREPARED
;
1464 lpWaveHdr
->dwFlags
|= WHDR_INQUEUE
;
1465 lpWaveHdr
->dwFlags
&= ~WHDR_DONE
;
1466 lpWaveHdr
->dwBytesRecorded
= 0;
1467 /* added to the queue, except if it's the one just prepared ... */
1468 if (WInDev
[wDevID
].lpQueueHdr
!= lpWaveHdr
) {
1469 lpWIHdr
= WInDev
[wDevID
].lpQueueHdr
;
1470 while (lpWIHdr
->lpNext
!= NULL
) {
1471 lpWIHdr
= lpWIHdr
->lpNext
;
1474 lpWIHdr
->lpNext
= lpWaveHdr
;
1477 dprintf_mciwave(stddeb
,
1478 "widAddBuffer // buffer added ! (now %u in queue)\n", count
);
1479 return MMSYSERR_NOERROR
;
1481 return MMSYSERR_NOTENABLED
;
1485 /**************************************************************************
1486 * widPrepare [internal]
1488 DWORD
widPrepare(WORD wDevID
, LPWAVEHDR lpWaveHdr
, DWORD dwSize
)
1491 dprintf_mciwave(stddeb
,
1492 "widPrepare(%u, %p, %08lX);\n", wDevID
, lpWaveHdr
, dwSize
);
1493 if (WInDev
[wDevID
].unixdev
== 0) {
1494 fprintf(stderr
,"Linux 'widPrepare' // can't prepare !\n");
1495 return MMSYSERR_NOTENABLED
;
1497 if (WInDev
[wDevID
].lpQueueHdr
!= NULL
) {
1498 fprintf(stderr
,"Linux 'widPrepare' // already prepare !\n");
1499 return WAVERR_BADFORMAT
;
1501 WInDev
[wDevID
].dwTotalRecorded
= 0;
1502 WInDev
[wDevID
].lpQueueHdr
= lpWaveHdr
;
1503 if (lpWaveHdr
->dwFlags
& WHDR_INQUEUE
) return WAVERR_STILLPLAYING
;
1504 lpWaveHdr
->dwFlags
|= WHDR_PREPARED
;
1505 lpWaveHdr
->dwFlags
|= WHDR_INQUEUE
;
1506 lpWaveHdr
->dwFlags
&= ~WHDR_DONE
;
1507 lpWaveHdr
->dwBytesRecorded
= 0;
1508 dprintf_mciwave(stddeb
,"Linux 'widPrepare' // header prepared !\n");
1509 return MMSYSERR_NOERROR
;
1511 return MMSYSERR_NOTENABLED
;
1515 /**************************************************************************
1516 * widUnprepare [internal]
1518 DWORD
widUnprepare(WORD wDevID
, LPWAVEHDR lpWaveHdr
, DWORD dwSize
)
1521 dprintf_mciwave(stddeb
,
1522 "widUnprepare(%u, %p, %08lX);\n", wDevID
, lpWaveHdr
, dwSize
);
1523 if (WInDev
[wDevID
].unixdev
== 0) {
1524 fprintf(stderr
,"Linux 'widUnprepare' // can't unprepare !\n");
1525 return MMSYSERR_NOTENABLED
;
1527 lpWaveHdr
->dwFlags
&= ~WHDR_PREPARED
;
1528 lpWaveHdr
->dwFlags
&= ~WHDR_INQUEUE
;
1529 lpWaveHdr
->dwFlags
|= WHDR_DONE
;
1530 WInDev
[wDevID
].lpQueueHdr
= NULL
;
1531 dprintf_mciwave(stddeb
,
1532 "Linux 'widUnprepare' // all headers unprepared !\n");
1533 return MMSYSERR_NOERROR
;
1535 return MMSYSERR_NOTENABLED
;
1539 /**************************************************************************
1540 * widStart [internal]
1542 DWORD
widStart(WORD wDevID
)
1547 dprintf_mciwave(stddeb
,"widStart(%u);\n", wDevID
);
1548 if (WInDev
[wDevID
].unixdev
== 0) {
1550 "Linux 'widStart' // can't start recording !\n");
1551 return MMSYSERR_NOTENABLED
;
1553 if (WInDev
[wDevID
].lpQueueHdr
== NULL
||
1554 WInDev
[wDevID
].lpQueueHdr
->lpData
== NULL
) {
1555 fprintf(stderr
,"Linux 'widStart' // never been prepared !\n");
1556 return WAVERR_UNPREPARED
;
1558 lpWIHdr
= WInDev
[wDevID
].lpQueueHdr
;
1559 while(lpWIHdr
!= NULL
) {
1560 lpWIHdr
->dwBufferLength
&= 0xFFFF;
1561 dprintf_mciwave(stddeb
,
1562 "widStart // recording buf#%u=%p size=%lu \n",
1563 count
, lpWIHdr
->lpData
, lpWIHdr
->dwBufferLength
);
1565 read (WInDev
[wDevID
].unixdev
, lpWIHdr
->lpData
,
1566 lpWIHdr
->dwBufferLength
);
1567 lpWIHdr
->dwBytesRecorded
= lpWIHdr
->dwBufferLength
;
1568 WInDev
[wDevID
].dwTotalRecorded
+= lpWIHdr
->dwBytesRecorded
;
1569 lpWIHdr
->dwFlags
&= ~WHDR_INQUEUE
;
1570 lpWIHdr
->dwFlags
|= WHDR_DONE
;
1571 if (WAVE_NotifyClient(wDevID
, WIM_DATA
, (DWORD
)lpWIHdr
, 0L) !=
1574 "Linux 'widStart' // can't notify client !\n");
1575 return MMSYSERR_INVALPARAM
;
1577 lpWIHdr
= lpWIHdr
->lpNext
;
1580 dprintf_mciwave(stddeb
,"widStart // end of recording !\n");
1582 return MMSYSERR_NOERROR
;
1584 return MMSYSERR_NOTENABLED
;
1588 /**************************************************************************
1589 * widStop [internal]
1591 DWORD
widStop(WORD wDevID
)
1594 dprintf_mciwave(stddeb
,"widStop(%u);\n", wDevID
);
1595 if (WInDev
[wDevID
].unixdev
== 0) {
1596 fprintf(stderr
,"Linux 'widStop' // can't stop !\n");
1597 return MMSYSERR_NOTENABLED
;
1599 return MMSYSERR_NOERROR
;
1601 return MMSYSERR_NOTENABLED
;
1605 /**************************************************************************
1606 * widReset [internal]
1608 DWORD
widReset(WORD wDevID
)
1611 dprintf_mciwave(stddeb
,"widReset(%u);\n", wDevID
);
1612 if (WInDev
[wDevID
].unixdev
== 0) {
1613 fprintf(stderr
,"Linux 'widReset' // can't reset !\n");
1614 return MMSYSERR_NOTENABLED
;
1616 return MMSYSERR_NOERROR
;
1618 return MMSYSERR_NOTENABLED
;
1622 /**************************************************************************
1623 * widGetPosition [internal]
1625 DWORD
widGetPosition(WORD wDevID
, LPMMTIME lpTime
, DWORD uSize
)
1629 dprintf_mciwave(stddeb
,
1630 "widGetPosition(%u, %p, %lu);\n", wDevID
, lpTime
, uSize
);
1631 if (WInDev
[wDevID
].unixdev
== 0) {
1632 fprintf(stderr
,"Linux 'widGetPosition' // can't get pos !\n");
1633 return MMSYSERR_NOTENABLED
;
1635 if (lpTime
== NULL
) return MMSYSERR_INVALPARAM
;
1637 dprintf_mciwave(stddeb
,"widGetPosition // wType=%04X !\n",
1639 dprintf_mciwave(stddeb
,"widGetPosition // wBitsPerSample=%u\n",
1640 WInDev
[wDevID
].Format
.wBitsPerSample
);
1641 dprintf_mciwave(stddeb
,"widGetPosition // nSamplesPerSec=%lu\n",
1642 WInDev
[wDevID
].Format
.wf
.nSamplesPerSec
);
1643 dprintf_mciwave(stddeb
,"widGetPosition // nChannels=%u\n",
1644 WInDev
[wDevID
].Format
.wf
.nChannels
);
1645 dprintf_mciwave(stddeb
,"widGetPosition // nAvgBytesPerSec=%lu\n",
1646 WInDev
[wDevID
].Format
.wf
.nAvgBytesPerSec
);
1648 switch(lpTime
->wType
) {
1650 lpTime
->u
.cb
= WInDev
[wDevID
].dwTotalRecorded
;
1651 dprintf_mciwave(stddeb
,
1652 "widGetPosition // TIME_BYTES=%lu\n", lpTime
->u
.cb
);
1655 lpTime
->u
.sample
= WInDev
[wDevID
].dwTotalRecorded
* 8 /
1656 WInDev
[wDevID
].Format
.wBitsPerSample
;
1657 dprintf_mciwave(stddeb
,
1658 "widGetPosition // TIME_SAMPLES=%lu\n",
1662 lpTime
->u
.ms
= WInDev
[wDevID
].dwTotalRecorded
/
1663 (WInDev
[wDevID
].Format
.wf
.nAvgBytesPerSec
/ 1000);
1664 dprintf_mciwave(stddeb
,
1665 "widGetPosition // TIME_MS=%lu\n", lpTime
->u
.ms
);
1668 time
= WInDev
[wDevID
].dwTotalRecorded
/
1669 (WInDev
[wDevID
].Format
.wf
.nAvgBytesPerSec
/ 1000);
1670 lpTime
->u
.smpte
.hour
= time
/ 108000;
1671 time
-= lpTime
->u
.smpte
.hour
* 108000;
1672 lpTime
->u
.smpte
.min
= time
/ 1800;
1673 time
-= lpTime
->u
.smpte
.min
* 1800;
1674 lpTime
->u
.smpte
.sec
= time
/ 30;
1675 time
-= lpTime
->u
.smpte
.sec
* 30;
1676 lpTime
->u
.smpte
.frame
= time
;
1677 lpTime
->u
.smpte
.fps
= 30;
1678 dprintf_mciwave(stddeb
,"widGetPosition // TIME_SMPTE=%02u:%02u:%02u:%02u\n",
1679 lpTime
->u
.smpte
.hour
, lpTime
->u
.smpte
.min
,
1680 lpTime
->u
.smpte
.sec
, lpTime
->u
.smpte
.frame
);
1683 fprintf(stderr
,"widGetPosition() format not supported ! use TIME_MS !\n");
1684 lpTime
->wType
= TIME_MS
;
1687 return MMSYSERR_NOERROR
;
1689 return MMSYSERR_NOTENABLED
;
1693 /**************************************************************************
1694 * widMessage [sample driver]
1696 DWORD
widMessage(WORD wDevID
, WORD wMsg
, DWORD dwUser
,
1697 DWORD dwParam1
, DWORD dwParam2
)
1699 dprintf_mciwave(stddeb
,"widMessage(%u, %04X, %08lX, %08lX, %08lX);\n",
1700 wDevID
, wMsg
, dwUser
, dwParam1
, dwParam2
);
1703 return widOpen(wDevID
, (LPWAVEOPENDESC
)dwParam1
, dwParam2
);
1705 return widClose(wDevID
);
1706 case WIDM_ADDBUFFER
:
1707 return widAddBuffer(wDevID
, (LPWAVEHDR
)dwParam1
, dwParam2
);
1709 return widPrepare(wDevID
, (LPWAVEHDR
)dwParam1
, dwParam2
);
1710 case WIDM_UNPREPARE
:
1711 return widUnprepare(wDevID
, (LPWAVEHDR
)dwParam1
, dwParam2
);
1712 case WIDM_GETDEVCAPS
:
1713 return widGetDevCaps(wDevID
, (LPWAVEINCAPS
)dwParam1
, dwParam2
);
1714 case WIDM_GETNUMDEVS
:
1717 return widGetPosition(wDevID
, (LPMMTIME
)dwParam1
, dwParam2
);
1719 return widReset(wDevID
);
1721 return widStart(wDevID
);
1723 return widStop(wDevID
);
1725 return MMSYSERR_NOTSUPPORTED
;
1729 #endif /* #ifdef BUILTIN_MMSYSTEM */