2 * Sample Wine Driver for Linux
4 * Copyright 1994 Martin Ayotte
13 #include <sys/ioctl.h>
21 #include <linux/soundcard.h>
23 #include <machine/soundcard.h>
29 int MMSYSTEM_DevIDToIndex(UINT16
);
31 #if defined(linux) || defined(__FreeBSD__)
32 #define SOUND_DEV "/dev/dsp"
35 #define IOCTL(a,b,c) ((-1==ioctl(a,b,&c))&&(perror("ioctl:"#b":"#c),0))
37 #define IOCTL(a,b,c) (c = ioctl(a,b,c) )
40 #define MAX_WAVOUTDRV 2
41 #define MAX_WAVINDRV 2
42 #define MAX_MCIWAVDRV 2
48 WAVEOPENDESC waveDesc
;
58 DWORD bufsize
; /* Linux '/dev/dsp' give us that size */
59 WAVEOPENDESC waveDesc
;
63 DWORD dwTotalRecorded
;
67 int nUseCount
; /* Incremented for each shared open */
68 BOOL16 fShareable
; /* TRUE if first open was shareable */
69 WORD wNotifyDeviceID
; /* MCI device ID with a pending notification */
70 HANDLE16 hCallback
; /* Callback handle for pending notification */
71 HMMIO16 hFile
; /* mmio file handle open as Element */
72 MCI_WAVE_OPEN_PARMS openParms
;
73 PCMWAVEFORMAT WaveFormat
;
77 static LINUX_WAVEOUT WOutDev
[MAX_WAVOUTDRV
];
78 static LINUX_WAVEIN WInDev
[MAX_WAVOUTDRV
];
79 static LINUX_MCIWAVE MCIWavDev
[MAX_MCIWAVDRV
];
82 /**************************************************************************
83 * WAVE_NotifyClient [internal]
85 static DWORD
WAVE_NotifyClient(UINT16 wDevID
, WORD wMsg
,
86 DWORD dwParam1
, DWORD dwParam2
)
88 int index
= MMSYSTEM_DevIDToIndex(wDevID
);
90 if (WInDev
[index
].wFlags
!= DCB_NULL
&& !DriverCallback(
91 WInDev
[index
].waveDesc
.dwCallBack
, WInDev
[index
].wFlags
,
92 WInDev
[index
].waveDesc
.hWave
, wMsg
,
93 WInDev
[index
].waveDesc
.dwInstance
, dwParam1
, dwParam2
)) {
94 dprintf_mciwave(stddeb
,"WAVE_NotifyClient // can't notify client !\n");
95 return MMSYSERR_NOERROR
;
101 /**************************************************************************
103 static DWORD
WAVE_mciOpen(UINT16 wDevID
, DWORD dwFlags
, LPMCI_WAVE_OPEN_PARMS lpParms
)
105 int index
= MMSYSTEM_DevIDToIndex(wDevID
);
107 LPPCMWAVEFORMAT lpWaveFormat
;
109 LPWAVEOPENDESC lpDesc
;
110 LPSTR lpstrElementName
;
114 dprintf_mciwave(stddeb
,"WAVE_mciOpen(%04X, %08lX, %p)\n",
115 wDevID
, dwFlags
, lpParms
);
116 if (lpParms
== NULL
) return MCIERR_INTERNAL
;
118 wDevID
= lpParms
->wDeviceID
;
119 index
= MMSYSTEM_DevIDToIndex(wDevID
);
121 if (MCIWavDev
[index
].nUseCount
> 0) {
122 /* The driver already open on this channel */
123 /* If the driver was opened shareable before and this open specifies */
124 /* shareable then increment the use count */
125 if (MCIWavDev
[index
].fShareable
&& (dwFlags
& MCI_OPEN_SHAREABLE
))
126 ++MCIWavDev
[index
].nUseCount
;
128 return MCIERR_MUST_USE_SHAREABLE
;
131 MCIWavDev
[index
].nUseCount
= 1;
132 MCIWavDev
[index
].fShareable
= dwFlags
& MCI_OPEN_SHAREABLE
;
134 lpParms
->wDeviceID
= wDevID
;
135 dprintf_mciwave(stddeb
,"WAVE_mciOpen // wDevID=%04X\n", wDevID
);
136 dprintf_mciwave(stddeb
,"WAVE_mciOpen // before OPEN_ELEMENT\n");
137 if (dwFlags
& MCI_OPEN_ELEMENT
) {
138 lpstrElementName
= (LPSTR
)PTR_SEG_TO_LIN(lpParms
->lpstrElementName
);
139 dprintf_mciwave(stddeb
,"WAVE_mciOpen // MCI_OPEN_ELEMENT '%s' !\n",
141 if (strlen(lpstrElementName
) > 0) {
142 strcpy(str
, lpstrElementName
);
144 MCIWavDev
[index
].hFile
= mmioOpen(str
, NULL
,
145 MMIO_ALLOCBUF
| MMIO_READWRITE
| MMIO_EXCLUSIVE
);
146 if (MCIWavDev
[index
].hFile
== 0) {
147 dprintf_mciwave(stddeb
,"WAVE_mciOpen // can't find file='%s' !\n", str
);
148 return MCIERR_FILE_NOT_FOUND
;
152 MCIWavDev
[index
].hFile
= 0;
154 dprintf_mciwave(stddeb
,"WAVE_mciOpen // hFile=%u\n", MCIWavDev
[index
].hFile
);
155 memcpy(&MCIWavDev
[index
].openParms
, lpParms
, sizeof(MCI_WAVE_OPEN_PARMS
));
156 MCIWavDev
[index
].wNotifyDeviceID
= lpParms
->wDeviceID
;
157 lpWaveFormat
= &MCIWavDev
[index
].WaveFormat
;
158 hDesc
= USER_HEAP_ALLOC(sizeof(WAVEOPENDESC
));
159 lpDesc
= (LPWAVEOPENDESC
) USER_HEAP_LIN_ADDR(hDesc
);
162 lpWaveFormat->wf.wFormatTag = WAVE_FORMAT_PCM;
163 lpWaveFormat->wBitsPerSample = 8;
164 lpWaveFormat->wf.nChannels = 1;
165 lpWaveFormat->wf.nSamplesPerSec = 11025;
166 lpWaveFormat->wf.nAvgBytesPerSec = 11025;
167 lpWaveFormat->wf.nBlockAlign = 1;
169 if (MCIWavDev
[index
].hFile
!= 0) {
172 if (mmioDescend(MCIWavDev
[index
].hFile
, &ckMainRIFF
, NULL
, 0) != 0) {
173 return MCIERR_INTERNAL
;
175 dprintf_mciwave(stddeb
,
176 "WAVE_mciOpen // ParentChunk ckid=%.4s fccType=%.4s cksize=%08lX \n",
177 (LPSTR
)&ckMainRIFF
.ckid
, (LPSTR
)&ckMainRIFF
.fccType
,
179 if ((ckMainRIFF
.ckid
!= FOURCC_RIFF
) ||
180 (ckMainRIFF
.fccType
!= mmioFOURCC('W', 'A', 'V', 'E'))) {
181 return MCIERR_INTERNAL
;
183 mmckInfo
.ckid
= mmioFOURCC('f', 'm', 't', ' ');
184 if (mmioDescend(MCIWavDev
[index
].hFile
, &mmckInfo
, &ckMainRIFF
, MMIO_FINDCHUNK
) != 0) {
185 return MCIERR_INTERNAL
;
187 dprintf_mciwave(stddeb
,
188 "WAVE_mciOpen // Chunk Found ckid=%.4s fccType=%.4s cksize=%08lX \n",
189 (LPSTR
)&mmckInfo
.ckid
, (LPSTR
)&mmckInfo
.fccType
,
191 if (mmioRead(MCIWavDev
[index
].hFile
, (HPSTR
) lpWaveFormat
,
192 (long) sizeof(PCMWAVEFORMAT
)) != (long) sizeof(PCMWAVEFORMAT
)) {
193 return MCIERR_INTERNAL
;
195 mmckInfo
.ckid
= mmioFOURCC('d', 'a', 't', 'a');
196 if (mmioDescend(MCIWavDev
[index
].hFile
, &mmckInfo
, &ckMainRIFF
, MMIO_FINDCHUNK
) != 0) {
197 return MCIERR_INTERNAL
;
199 dprintf_mciwave(stddeb
,
200 "WAVE_mciOpen // Chunk Found ckid=%.4s fccType=%.4s cksize=%08lX \n",
201 (LPSTR
)&mmckInfo
.ckid
, (LPSTR
)&mmckInfo
.fccType
,
203 dprintf_mciwave(stddeb
,
204 "WAVE_mciOpen // nChannels=%d nSamplesPerSec=%ld\n",
205 lpWaveFormat
->wf
.nChannels
, lpWaveFormat
->wf
.nSamplesPerSec
);
206 lpWaveFormat
->wBitsPerSample
= 0;
208 lpWaveFormat
->wf
.nAvgBytesPerSec
=
209 lpWaveFormat
->wf
.nSamplesPerSec
* lpWaveFormat
->wf
.nBlockAlign
;
210 hFormat
= USER_HEAP_ALLOC(sizeof(PCMWAVEFORMAT
));
211 lpDesc
->lpFormat
= (LPWAVEFORMAT
) USER_HEAP_LIN_ADDR(hFormat
);
212 memcpy(lpDesc
->lpFormat
, lpWaveFormat
, sizeof(PCMWAVEFORMAT
));
213 lpDesc
= (LPWAVEOPENDESC
) USER_HEAP_SEG_ADDR(hDesc
);
214 dwRet
= wodMessage(index
, WODM_OPEN
, 0, (DWORD
)lpDesc
, CALLBACK_NULL
);
215 dwRet
= widMessage(index
, WIDM_OPEN
, 0, (DWORD
)lpDesc
, CALLBACK_NULL
);
216 USER_HEAP_FREE(hFormat
);
217 USER_HEAP_FREE(hDesc
);
221 /**************************************************************************
222 * WAVE_mciClose [internal]
224 static DWORD
WAVE_mciClose(UINT16 wDevID
, DWORD dwParam
, LPMCI_GENERIC_PARMS lpParms
)
226 int index
= MMSYSTEM_DevIDToIndex(wDevID
);
228 dprintf_mciwave(stddeb
,
229 "WAVE_mciClose(%u, %08lX, %p);\n", wDevID
, dwParam
, lpParms
);
230 MCIWavDev
[index
].nUseCount
--;
231 if (MCIWavDev
[index
].nUseCount
== 0) {
232 if (MCIWavDev
[index
].hFile
!= 0) {
233 mmioClose(MCIWavDev
[index
].hFile
, 0);
234 MCIWavDev
[index
].hFile
= 0;
236 dwRet
= wodMessage(index
, WODM_CLOSE
, 0, 0L, 0L);
237 if (dwRet
!= MMSYSERR_NOERROR
) return MCIERR_INTERNAL
;
238 dwRet
= widMessage(index
, WIDM_CLOSE
, 0, 0L, 0L);
239 if (dwRet
!= MMSYSERR_NOERROR
) return MCIERR_INTERNAL
;
245 /**************************************************************************
246 * WAVE_mciPlay [internal]
248 static DWORD
WAVE_mciPlay(UINT16 wDevID
, DWORD dwFlags
, LPMCI_PLAY_PARMS lpParms
)
250 int index
= MMSYSTEM_DevIDToIndex(wDevID
);
256 LPWAVEHDR lp16WaveHdr
;
258 dprintf_mciwave(stddeb
,
259 "WAVE_mciPlay(%u, %08lX, %p);\n", wDevID
, dwFlags
, lpParms
);
260 if (MCIWavDev
[index
].hFile
== 0) {
261 dprintf_mciwave(stddeb
,"WAVE_mciPlay // can't find file='%08lx' !\n",
262 MCIWavDev
[index
].openParms
.lpstrElementName
);
263 return MCIERR_FILE_NOT_FOUND
;
265 start
= 1; end
= 99999;
266 if (dwFlags
& MCI_FROM
) {
267 start
= lpParms
->dwFrom
;
268 dprintf_mciwave(stddeb
,
269 "WAVE_mciPlay // MCI_FROM=%d \n", start
);
271 if (dwFlags
& MCI_TO
) {
273 dprintf_mciwave(stddeb
,"WAVE_mciPlay // MCI_TO=%d \n", end
);
276 if (dwFlags
& MCI_NOTIFY
) {
277 dprintf_mciwave(stddeb
,
278 "WAVE_mciPlay // MCI_NOTIFY %08lX !\n", lpParms
->dwCallback
);
281 dprintf_mciwave(stddeb
,
282 "WAVE_mciPlay // Can't 'fork' process !\n");
287 dprintf_mciwave(stddeb
,"WAVE_mciPlay // process started ! return to caller...\n");
293 lpWaveHdr
= &MCIWavDev
[index
].WaveHdr
;
294 hData
= GlobalAlloc16(GMEM_MOVEABLE
, bufsize
);
295 lpWaveHdr
->lpData
= (LPSTR
) WIN16_GlobalLock16(hData
);
296 lpWaveHdr
->dwUser
= 0L;
297 lpWaveHdr
->dwFlags
= 0L;
298 lpWaveHdr
->dwLoops
= 0L;
299 hWaveHdr
= USER_HEAP_ALLOC(sizeof(WAVEHDR
));
300 lp16WaveHdr
= (LPWAVEHDR
) USER_HEAP_SEG_ADDR(hWaveHdr
);
301 memcpy(PTR_SEG_TO_LIN(lp16WaveHdr
), lpWaveHdr
, sizeof(WAVEHDR
));
302 lpWaveHdr
= PTR_SEG_TO_LIN(lp16WaveHdr
);
303 dwRet
= wodMessage(index
, WODM_PREPARE
, 0, (DWORD
)lp16WaveHdr
, sizeof(WAVEHDR
));
305 count
= mmioRead(MCIWavDev
[index
].hFile
,
306 PTR_SEG_TO_LIN(lpWaveHdr
->lpData
), bufsize
);
307 dprintf_mciwave(stddeb
,"WAVE_mciPlay // mmioRead bufsize=%ld count=%ld\n", bufsize
, count
);
308 if (count
< 1) break;
309 lpWaveHdr
->dwBufferLength
= count
;
310 /* lpWaveHdr->dwBytesRecorded = count; */
311 dprintf_mciwave(stddeb
,"WAVE_mciPlay // before WODM_WRITE lpWaveHdr=%p dwBufferLength=%lu dwBytesRecorded=%lu\n",
312 lpWaveHdr
, lpWaveHdr
->dwBufferLength
, lpWaveHdr
->dwBytesRecorded
);
313 dwRet
= wodMessage(index
, WODM_WRITE
, 0, (DWORD
)lp16WaveHdr
, sizeof(WAVEHDR
));
315 dwRet
= wodMessage(index
, WODM_UNPREPARE
, 0, (DWORD
)lp16WaveHdr
, sizeof(WAVEHDR
));
316 if (lpWaveHdr
->lpData
!= NULL
) {
317 GlobalUnlock16(hData
);
319 lpWaveHdr
->lpData
= NULL
;
321 USER_HEAP_FREE(hWaveHdr
);
322 if (dwFlags
& MCI_NOTIFY
) {
323 dprintf_mciwave(stddeb
,"WAVE_mciPlay // MCI_NOTIFY_SUCCESSFUL %08lX !\n", lpParms
->dwCallback
);
324 mciDriverNotify((HWND16
)LOWORD(lpParms
->dwCallback
),
325 MCIWavDev
[index
].wNotifyDeviceID
, MCI_NOTIFY_SUCCESSFUL
);
331 /**************************************************************************
332 * WAVE_mciRecord [internal]
334 static DWORD
WAVE_mciRecord(UINT16 wDevID
, DWORD dwFlags
, LPMCI_RECORD_PARMS lpParms
)
336 int index
= MMSYSTEM_DevIDToIndex(wDevID
);
342 LPWAVEHDR lp16WaveHdr
;
345 dprintf_mciwave(stddeb
,
346 "WAVE_mciRecord(%u, %08lX, %p);\n", wDevID
, dwFlags
, lpParms
);
347 if (MCIWavDev
[index
].hFile
== 0) {
348 dprintf_mciwave(stddeb
,"WAVE_mciRecord // can't find file='%08lx' !\n",
349 MCIWavDev
[index
].openParms
.lpstrElementName
);
350 return MCIERR_FILE_NOT_FOUND
;
352 start
= 1; end
= 99999;
353 if (dwFlags
& MCI_FROM
) {
354 start
= lpParms
->dwFrom
;
355 dprintf_mciwave(stddeb
,
356 "WAVE_mciRecord // MCI_FROM=%d \n", start
);
358 if (dwFlags
& MCI_TO
) {
360 dprintf_mciwave(stddeb
,"WAVE_mciRecord // MCI_TO=%d \n", end
);
363 lpWaveHdr
= &MCIWavDev
[index
].WaveHdr
;
364 hData
= GlobalAlloc16(GMEM_MOVEABLE
, bufsize
);
365 lpWaveHdr
->lpData
= (LPSTR
) WIN16_GlobalLock16(hData
);
366 lpWaveHdr
->dwBufferLength
= bufsize
;
367 lpWaveHdr
->dwUser
= 0L;
368 lpWaveHdr
->dwFlags
= 0L;
369 lpWaveHdr
->dwLoops
= 0L;
370 hWaveHdr
= USER_HEAP_ALLOC(sizeof(WAVEHDR
));
371 lp16WaveHdr
= (LPWAVEHDR
) USER_HEAP_SEG_ADDR(hWaveHdr
);
372 memcpy(PTR_SEG_TO_LIN(lp16WaveHdr
), lpWaveHdr
, sizeof(WAVEHDR
));
373 lpWaveHdr
= PTR_SEG_TO_LIN(lp16WaveHdr
);
374 dwRet
= widMessage(index
, WIDM_PREPARE
, 0, (DWORD
)lp16WaveHdr
, sizeof(WAVEHDR
));
375 dprintf_mciwave(stddeb
,"WAVE_mciRecord // after WIDM_PREPARE \n");
377 lpWaveHdr
->dwBytesRecorded
= 0;
378 dwRet
= widMessage(index
, WIDM_START
, 0, 0L, 0L);
379 dprintf_mciwave(stddeb
,
380 "WAVE_mciRecord // after WIDM_START lpWaveHdr=%p dwBytesRecorded=%lu\n",
381 lpWaveHdr
, lpWaveHdr
->dwBytesRecorded
);
382 if (lpWaveHdr
->dwBytesRecorded
== 0) break;
384 dprintf_mciwave(stddeb
,"WAVE_mciRecord // before WIDM_UNPREPARE \n");
385 dwRet
= widMessage(index
, WIDM_UNPREPARE
, 0, (DWORD
)lp16WaveHdr
, sizeof(WAVEHDR
));
386 dprintf_mciwave(stddeb
,"WAVE_mciRecord // after WIDM_UNPREPARE \n");
387 if (lpWaveHdr
->lpData
!= NULL
) {
388 GlobalUnlock16(hData
);
390 lpWaveHdr
->lpData
= NULL
;
392 USER_HEAP_FREE(hWaveHdr
);
393 if (dwFlags
& MCI_NOTIFY
) {
394 dprintf_mciwave(stddeb
,"WAVE_mciRecord // MCI_NOTIFY_SUCCESSFUL %08lX !\n", lpParms
->dwCallback
);
395 mciDriverNotify((HWND16
)LOWORD(lpParms
->dwCallback
),
396 MCIWavDev
[index
].wNotifyDeviceID
, MCI_NOTIFY_SUCCESSFUL
);
402 /**************************************************************************
403 * WAVE_mciStop [internal]
405 static DWORD
WAVE_mciStop(UINT16 wDevID
, DWORD dwFlags
, LPMCI_GENERIC_PARMS lpParms
)
407 dprintf_mciwave(stddeb
,
408 "WAVE_mciStop(%u, %08lX, %p);\n", wDevID
, dwFlags
, lpParms
);
409 if (lpParms
== NULL
) return MCIERR_INTERNAL
;
414 /**************************************************************************
415 * WAVE_mciPause [internal]
417 static DWORD
WAVE_mciPause(UINT16 wDevID
, DWORD dwFlags
, LPMCI_GENERIC_PARMS lpParms
)
419 dprintf_mciwave(stddeb
,
420 "WAVE_mciPause(%u, %08lX, %p);\n", wDevID
, dwFlags
, lpParms
);
421 if (lpParms
== NULL
) return MCIERR_INTERNAL
;
426 /**************************************************************************
427 * WAVE_mciResume [internal]
429 static DWORD
WAVE_mciResume(UINT16 wDevID
, DWORD dwFlags
, LPMCI_GENERIC_PARMS lpParms
)
431 dprintf_mciwave(stddeb
,
432 "WAVE_mciResume(%u, %08lX, %p);\n", wDevID
, dwFlags
, lpParms
);
433 if (lpParms
== NULL
) return MCIERR_INTERNAL
;
438 /**************************************************************************
439 * WAVE_mciSet [internal]
441 static DWORD
WAVE_mciSet(UINT16 wDevID
, DWORD dwFlags
, LPMCI_SET_PARMS lpParms
)
443 dprintf_mciwave(stddeb
,
444 "WAVE_mciSet(%u, %08lX, %p);\n", wDevID
, dwFlags
, lpParms
);
445 if (lpParms
== NULL
) return MCIERR_INTERNAL
;
446 dprintf_mciwave(stddeb
,
447 "WAVE_mciSet // dwTimeFormat=%08lX\n", lpParms
->dwTimeFormat
);
448 dprintf_mciwave(stddeb
,
449 "WAVE_mciSet // dwAudio=%08lX\n", lpParms
->dwAudio
);
450 if (dwFlags
& MCI_SET_TIME_FORMAT
) {
451 switch (lpParms
->dwTimeFormat
) {
452 case MCI_FORMAT_MILLISECONDS
:
453 dprintf_mciwave(stddeb
, "WAVE_mciSet // MCI_FORMAT_MILLISECONDS !\n");
455 case MCI_FORMAT_BYTES
:
456 dprintf_mciwave(stddeb
, "WAVE_mciSet // MCI_FORMAT_BYTES !\n");
458 case MCI_FORMAT_SAMPLES
:
459 dprintf_mciwave(stddeb
, "WAVE_mciSet // MCI_FORMAT_SAMPLES !\n");
462 dprintf_mciwave(stddeb
, "WAVE_mciSet // bad time format !\n");
463 return MCIERR_BAD_TIME_FORMAT
;
466 if (dwFlags
& MCI_SET_VIDEO
) return MCIERR_UNSUPPORTED_FUNCTION
;
467 if (dwFlags
& MCI_SET_DOOR_OPEN
) return MCIERR_UNSUPPORTED_FUNCTION
;
468 if (dwFlags
& MCI_SET_DOOR_CLOSED
) return MCIERR_UNSUPPORTED_FUNCTION
;
469 if (dwFlags
& MCI_SET_AUDIO
)
470 dprintf_mciwave(stddeb
,"WAVE_mciSet // MCI_SET_AUDIO !\n");
471 if (dwFlags
&& MCI_SET_ON
) {
472 dprintf_mciwave(stddeb
,"WAVE_mciSet // MCI_SET_ON !\n");
473 if (dwFlags
&& MCI_SET_AUDIO_LEFT
)
474 dprintf_mciwave(stddeb
,"WAVE_mciSet // MCI_SET_AUDIO_LEFT !\n");
475 if (dwFlags
&& MCI_SET_AUDIO_RIGHT
)
476 dprintf_mciwave(stddeb
,"WAVE_mciSet // MCI_SET_AUDIO_RIGHT !\n");
478 if (dwFlags
& MCI_SET_OFF
)
479 dprintf_mciwave(stddeb
,"WAVE_mciSet // MCI_SET_OFF !\n");
480 if (dwFlags
& MCI_WAVE_INPUT
)
481 dprintf_mciwave(stddeb
,"WAVE_mciSet // MCI_WAVE_INPUT !\n");
482 if (dwFlags
& MCI_WAVE_OUTPUT
)
483 dprintf_mciwave(stddeb
,"WAVE_mciSet // MCI_WAVE_OUTPUT !\n");
484 if (dwFlags
& MCI_WAVE_SET_ANYINPUT
)
485 dprintf_mciwave(stddeb
,"WAVE_mciSet // MCI_WAVE_SET_ANYINPUT !\n");
486 if (dwFlags
& MCI_WAVE_SET_ANYOUTPUT
)
487 dprintf_mciwave(stddeb
,"WAVE_mciSet // MCI_WAVE_SET_ANYOUTPUT !\n");
488 if (dwFlags
& MCI_WAVE_SET_AVGBYTESPERSEC
)
489 dprintf_mciwave(stddeb
,
490 "WAVE_mciSet // MCI_WAVE_SET_AVGBYTESPERSEC !\n");
491 if (dwFlags
& MCI_WAVE_SET_BITSPERSAMPLE
)
492 dprintf_mciwave(stddeb
,
493 "WAVE_mciSet // MCI_WAVE_SET_BITSPERSAMPLE !\n");
494 if (dwFlags
& MCI_WAVE_SET_BLOCKALIGN
)
495 dprintf_mciwave(stddeb
,"WAVE_mciSet // MCI_WAVE_SET_BLOCKALIGN !\n");
496 if (dwFlags
& MCI_WAVE_SET_CHANNELS
)
497 dprintf_mciwave(stddeb
,"WAVE_mciSet // MCI_WAVE_SET_CHANNELS !\n");
498 if (dwFlags
& MCI_WAVE_SET_FORMATTAG
)
499 dprintf_mciwave(stddeb
,"WAVE_mciSet // MCI_WAVE_SET_FORMATTAG !\n");
500 if (dwFlags
& MCI_WAVE_SET_SAMPLESPERSEC
)
501 dprintf_mciwave(stddeb
,
502 "WAVE_mciSet // MCI_WAVE_SET_SAMPLESPERSEC !\n");
507 /**************************************************************************
508 * WAVE_mciStatus [internal]
510 static DWORD
WAVE_mciStatus(UINT16 wDevID
, DWORD dwFlags
, LPMCI_STATUS_PARMS lpParms
)
512 int index
= MMSYSTEM_DevIDToIndex(wDevID
);
513 dprintf_mciwave(stddeb
,
514 "WAVE_mciStatus(%u, %08lX, %p);\n", wDevID
, dwFlags
, lpParms
);
515 if (lpParms
== NULL
) return MCIERR_INTERNAL
;
516 if (dwFlags
& MCI_STATUS_ITEM
) {
517 switch(lpParms
->dwItem
) {
518 case MCI_STATUS_CURRENT_TRACK
:
519 lpParms
->dwReturn
= 1;
521 case MCI_STATUS_LENGTH
:
522 lpParms
->dwReturn
= 5555;
523 if (dwFlags
& MCI_TRACK
) {
524 lpParms
->dwTrack
= 1;
525 lpParms
->dwReturn
= 2222;
528 case MCI_STATUS_MODE
:
529 lpParms
->dwReturn
= MCI_MODE_STOP
;
531 case MCI_STATUS_MEDIA_PRESENT
:
532 dprintf_mciwave(stddeb
,"WAVE_mciStatus // MCI_STATUS_MEDIA_PRESENT !\n");
533 lpParms
->dwReturn
= TRUE
;
535 case MCI_STATUS_NUMBER_OF_TRACKS
:
536 lpParms
->dwReturn
= 1;
538 case MCI_STATUS_POSITION
:
539 lpParms
->dwReturn
= 3333;
540 if (dwFlags
& MCI_STATUS_START
) {
543 if (dwFlags
& MCI_TRACK
) {
544 lpParms
->dwTrack
= 1;
545 lpParms
->dwReturn
= 777;
548 case MCI_STATUS_READY
:
549 dprintf_mciwave(stddeb
,"WAVE_mciStatus // MCI_STATUS_READY !\n");
550 lpParms
->dwReturn
= TRUE
;
552 case MCI_STATUS_TIME_FORMAT
:
553 dprintf_mciwave(stddeb
,"WAVE_mciStatus // MCI_STATUS_TIME_FORMAT !\n");
554 lpParms
->dwReturn
= MCI_FORMAT_MILLISECONDS
;
557 dprintf_mciwave(stddeb
,"WAVE_mciStatus // MCI_WAVE_INPUT !\n");
558 lpParms
->dwReturn
= 0;
560 case MCI_WAVE_OUTPUT
:
561 dprintf_mciwave(stddeb
,"WAVE_mciStatus // MCI_WAVE_OUTPUT !\n");
562 lpParms
->dwReturn
= 0;
564 case MCI_WAVE_STATUS_AVGBYTESPERSEC
:
565 dprintf_mciwave(stddeb
,"WAVE_mciStatus // MCI_WAVE_STATUS_AVGBYTESPERSEC !\n");
566 lpParms
->dwReturn
= 22050;
568 case MCI_WAVE_STATUS_BITSPERSAMPLE
:
569 dprintf_mciwave(stddeb
,"WAVE_mciStatus // MCI_WAVE_STATUS_BITSPERSAMPLE !\n");
570 lpParms
->dwReturn
= 8;
572 case MCI_WAVE_STATUS_BLOCKALIGN
:
573 dprintf_mciwave(stddeb
,"WAVE_mciStatus // MCI_WAVE_STATUS_BLOCKALIGN !\n");
574 lpParms
->dwReturn
= 1;
576 case MCI_WAVE_STATUS_CHANNELS
:
577 dprintf_mciwave(stddeb
,"WAVE_mciStatus // MCI_WAVE_STATUS_CHANNELS !\n");
578 lpParms
->dwReturn
= 1;
580 case MCI_WAVE_STATUS_FORMATTAG
:
581 dprintf_mciwave(stddeb
,"WAVE_mciStatus // MCI_WAVE_FORMATTAG !\n");
582 lpParms
->dwReturn
= WAVE_FORMAT_PCM
;
584 case MCI_WAVE_STATUS_LEVEL
:
585 dprintf_mciwave(stddeb
,"WAVE_mciStatus // MCI_WAVE_STATUS_LEVEL !\n");
586 lpParms
->dwReturn
= 0xAAAA5555;
588 case MCI_WAVE_STATUS_SAMPLESPERSEC
:
589 dprintf_mciwave(stddeb
,"WAVE_mciStatus // MCI_WAVE_STATUS_SAMPLESPERSEC !\n");
590 lpParms
->dwReturn
= 22050;
593 dprintf_mciwave(stddeb
,"WAVE_mciStatus // unknown command %08lX !\n", lpParms
->dwItem
);
594 return MCIERR_UNRECOGNIZED_COMMAND
;
597 if (dwFlags
& MCI_NOTIFY
) {
598 dprintf_mciwave(stddeb
,"WAVE_mciStatus // MCI_NOTIFY_SUCCESSFUL %08lX !\n", lpParms
->dwCallback
);
599 mciDriverNotify((HWND16
)LOWORD(lpParms
->dwCallback
),
600 MCIWavDev
[index
].wNotifyDeviceID
, MCI_NOTIFY_SUCCESSFUL
);
605 /**************************************************************************
606 * WAVE_mciGetDevCaps [internal]
608 static DWORD
WAVE_mciGetDevCaps(UINT16 wDevID
, DWORD dwFlags
,
609 LPMCI_GETDEVCAPS_PARMS lpParms
)
611 dprintf_mciwave(stddeb
,
612 "WAVE_mciGetDevCaps(%u, %08lX, %p);\n", wDevID
, dwFlags
, lpParms
);
613 if (lpParms
== NULL
) return MCIERR_INTERNAL
;
614 if (dwFlags
& MCI_GETDEVCAPS_ITEM
) {
615 switch(lpParms
->dwItem
) {
616 case MCI_GETDEVCAPS_CAN_RECORD
:
617 lpParms
->dwReturn
= TRUE
;
619 case MCI_GETDEVCAPS_HAS_AUDIO
:
620 lpParms
->dwReturn
= TRUE
;
622 case MCI_GETDEVCAPS_HAS_VIDEO
:
623 lpParms
->dwReturn
= FALSE
;
625 case MCI_GETDEVCAPS_DEVICE_TYPE
:
626 lpParms
->dwReturn
= MCI_DEVTYPE_WAVEFORM_AUDIO
;
628 case MCI_GETDEVCAPS_USES_FILES
:
629 lpParms
->dwReturn
= TRUE
;
631 case MCI_GETDEVCAPS_COMPOUND_DEVICE
:
632 lpParms
->dwReturn
= TRUE
;
634 case MCI_GETDEVCAPS_CAN_EJECT
:
635 lpParms
->dwReturn
= FALSE
;
637 case MCI_GETDEVCAPS_CAN_PLAY
:
638 lpParms
->dwReturn
= TRUE
;
640 case MCI_GETDEVCAPS_CAN_SAVE
:
641 lpParms
->dwReturn
= TRUE
;
643 case MCI_WAVE_GETDEVCAPS_INPUTS
:
644 lpParms
->dwReturn
= 1;
646 case MCI_WAVE_GETDEVCAPS_OUTPUTS
:
647 lpParms
->dwReturn
= 1;
650 return MCIERR_UNRECOGNIZED_COMMAND
;
656 /**************************************************************************
657 * WAVE_mciInfo [internal]
659 static DWORD
WAVE_mciInfo(UINT16 wDevID
, DWORD dwFlags
, LPMCI_INFO_PARMS lpParms
)
661 int index
= MMSYSTEM_DevIDToIndex(wDevID
);
662 dprintf_mciwave(stddeb
,
663 "WAVE_mciInfo(%u, %08lX, %p);\n", wDevID
, dwFlags
, lpParms
);
664 if (lpParms
== NULL
) return MCIERR_INTERNAL
;
665 lpParms
->lpstrReturn
= NULL
;
667 case MCI_INFO_PRODUCT
:
668 lpParms
->lpstrReturn
= "Linux Sound System 0.5";
671 lpParms
->lpstrReturn
=
672 (LPSTR
)MCIWavDev
[index
].openParms
.lpstrElementName
;
675 lpParms
->lpstrReturn
= "Linux Sound System 0.5";
677 case MCI_WAVE_OUTPUT
:
678 lpParms
->lpstrReturn
= "Linux Sound System 0.5";
681 return MCIERR_UNRECOGNIZED_COMMAND
;
683 if (lpParms
->lpstrReturn
!= NULL
)
684 lpParms
->dwRetSize
= strlen(lpParms
->lpstrReturn
);
686 lpParms
->dwRetSize
= 0;
691 /*-----------------------------------------------------------------------*/
694 /**************************************************************************
695 * wodGetDevCaps [internal]
697 static DWORD
wodGetDevCaps(WORD wDevID
, LPWAVEOUTCAPS lpCaps
, DWORD dwSize
)
704 dprintf_mciwave(stddeb
,
705 "wodGetDevCaps(%u, %p, %lu);\n", wDevID
, lpCaps
, dwSize
);
706 if (lpCaps
== NULL
) return MMSYSERR_NOTENABLED
;
707 audio
= open (SOUND_DEV
, O_WRONLY
, 0);
708 if (audio
== -1) return MMSYSERR_NOTENABLED
;
710 lpCaps
->wMid
= 0x0002;
711 lpCaps
->wPid
= 0x0104;
712 strcpy(lpCaps
->szPname
, "SB16 Wave Out");
714 lpCaps
->wMid
= 0x00FF; /* Manufac ID */
715 lpCaps
->wPid
= 0x0001; /* Product ID */
716 strcpy(lpCaps
->szPname
, "Linux WAVOUT Driver");
718 lpCaps
->dwFormats
= 0x00000000;
719 lpCaps
->dwSupport
= WAVECAPS_VOLUME
;
720 lpCaps
->wChannels
= (IOCTL(audio
, SNDCTL_DSP_STEREO
, dsp_stereo
) != 0) ? 1 : 2;
721 if (lpCaps
->wChannels
> 1) lpCaps
->dwSupport
|= WAVECAPS_LRVOLUME
;
722 bytespersmpl
= (IOCTL(audio
, SNDCTL_DSP_SAMPLESIZE
, samplesize
) != 0) ? 1 : 2;
724 if (IOCTL(audio
, SNDCTL_DSP_SPEED
, smplrate
) == 0) {
725 lpCaps
->dwFormats
|= WAVE_FORMAT_4M08
;
726 if (lpCaps
->wChannels
> 1) lpCaps
->dwFormats
|= WAVE_FORMAT_4S08
;
727 if (bytespersmpl
> 1) {
728 lpCaps
->dwFormats
|= WAVE_FORMAT_4M16
;
729 if (lpCaps
->wChannels
> 1) lpCaps
->dwFormats
|= WAVE_FORMAT_4S16
;
733 if (IOCTL(audio
, SNDCTL_DSP_SPEED
, smplrate
) == 0) {
734 lpCaps
->dwFormats
|= WAVE_FORMAT_2M08
;
735 if (lpCaps
->wChannels
> 1) lpCaps
->dwFormats
|= WAVE_FORMAT_2S08
;
736 if (bytespersmpl
> 1) {
737 lpCaps
->dwFormats
|= WAVE_FORMAT_2M16
;
738 if (lpCaps
->wChannels
> 1) lpCaps
->dwFormats
|= WAVE_FORMAT_2S16
;
742 if (IOCTL(audio
, SNDCTL_DSP_SPEED
, smplrate
) == 0) {
743 lpCaps
->dwFormats
|= WAVE_FORMAT_1M08
;
744 if (lpCaps
->wChannels
> 1) lpCaps
->dwFormats
|= WAVE_FORMAT_1S08
;
745 if (bytespersmpl
> 1) {
746 lpCaps
->dwFormats
|= WAVE_FORMAT_1M16
;
747 if (lpCaps
->wChannels
> 1) lpCaps
->dwFormats
|= WAVE_FORMAT_1S16
;
751 dprintf_mciwave(stddeb
,
752 "wodGetDevCaps // dwFormats = %08lX\n", lpCaps
->dwFormats
);
753 return MMSYSERR_NOERROR
;
757 /**************************************************************************
760 static DWORD
wodOpen(WORD wDevID
, LPWAVEOPENDESC lpDesc
, DWORD dwFlags
)
767 LPWAVEFORMAT lpFormat
;
769 dprintf_mciwave(stddeb
,
770 "wodOpen(%u, %p, %08lX);\n", wDevID
, lpDesc
, dwFlags
);
771 if (lpDesc
== NULL
) {
772 dprintf_mciwave(stddeb
,"Linux 'wodOpen' // Invalid Parameter !\n");
773 return MMSYSERR_INVALPARAM
;
775 if (wDevID
>= MAX_WAVOUTDRV
) {
776 dprintf_mciwave(stddeb
,"Linux 'wodOpen' // MAX_WAVOUTDRV reached !\n");
777 return MMSYSERR_ALLOCATED
;
779 WOutDev
[wDevID
].unixdev
= 0;
780 audio
= open (SOUND_DEV
, O_WRONLY
, 0);
782 dprintf_mciwave(stddeb
,"Linux 'wodOpen' // can't open !\n");
783 return MMSYSERR_NOTENABLED
;
785 IOCTL(audio
, SNDCTL_DSP_GETBLKSIZE
, abuf_size
);
786 if (abuf_size
< 1024 || abuf_size
> 65536) {
788 dprintf_mciwave(stddeb
,"Linux 'wodOpen' // IOCTL can't 'SNDCTL_DSP_GETBLKSIZE' !\n");
790 dprintf_mciwave(stddeb
,"Linux 'wodOpen' // SNDCTL_DSP_GETBLKSIZE Invalid bufsize !\n");
791 return MMSYSERR_NOTENABLED
;
793 WOutDev
[wDevID
].wFlags
= HIWORD(dwFlags
& CALLBACK_TYPEMASK
);
794 switch(WOutDev
[wDevID
].wFlags
) {
796 dprintf_mciwave(stddeb
, "Linux 'wodOpen' // CALLBACK_NULL !\n");
799 dprintf_mciwave(stddeb
, "Linux 'wodOpen' // CALLBACK_WINDOW !\n");
802 dprintf_mciwave(stddeb
, "Linux 'wodOpen' // CALLBACK_TASK !\n");
805 dprintf_mciwave(stddeb
, "Linux 'wodOpen' // CALLBACK_FUNCTION !\n");
808 WOutDev
[wDevID
].lpQueueHdr
= NULL
;
809 WOutDev
[wDevID
].unixdev
= audio
;
810 WOutDev
[wDevID
].dwTotalPlayed
= 0;
811 WOutDev
[wDevID
].bufsize
= abuf_size
;
812 memcpy(&WOutDev
[wDevID
].waveDesc
, lpDesc
, sizeof(WAVEOPENDESC
));
813 lpFormat
= (LPWAVEFORMAT
) PTR_SEG_TO_LIN(lpDesc
->lpFormat
);
814 if (lpFormat
->wFormatTag
!= WAVE_FORMAT_PCM
) {
815 dprintf_mciwave(stddeb
,"Linux 'wodOpen' // Bad format %04X !\n",
816 lpFormat
->wFormatTag
);
817 dprintf_mciwave(stddeb
,"Linux 'wodOpen' // Bad nChannels %d !\n",
818 lpFormat
->nChannels
);
819 dprintf_mciwave(stddeb
,"Linux 'wodOpen' // Bad nSamplesPerSec %ld !\n",
820 lpFormat
->nSamplesPerSec
);
821 return WAVERR_BADFORMAT
;
823 memcpy(&WOutDev
[wDevID
].Format
, lpFormat
, sizeof(PCMWAVEFORMAT
));
824 if (WOutDev
[wDevID
].Format
.wf
.nChannels
== 0) return WAVERR_BADFORMAT
;
825 if (WOutDev
[wDevID
].Format
.wf
.nSamplesPerSec
== 0) return WAVERR_BADFORMAT
;
826 dprintf_mciwave(stddeb
,"Linux 'wodOpen' // wBitsPerSample=%u !\n",
827 WOutDev
[wDevID
].Format
.wBitsPerSample
);
828 if (WOutDev
[wDevID
].Format
.wBitsPerSample
== 0) {
829 WOutDev
[wDevID
].Format
.wBitsPerSample
= 8 *
830 (WOutDev
[wDevID
].Format
.wf
.nAvgBytesPerSec
/
831 WOutDev
[wDevID
].Format
.wf
.nSamplesPerSec
) /
832 WOutDev
[wDevID
].Format
.wf
.nChannels
;
834 samplesize
= WOutDev
[wDevID
].Format
.wBitsPerSample
;
835 smplrate
= WOutDev
[wDevID
].Format
.wf
.nSamplesPerSec
;
836 dsp_stereo
= (WOutDev
[wDevID
].Format
.wf
.nChannels
> 1) ? TRUE
: FALSE
;
837 IOCTL(audio
, SNDCTL_DSP_SPEED
, smplrate
);
838 IOCTL(audio
, SNDCTL_DSP_SAMPLESIZE
, samplesize
);
839 IOCTL(audio
, SNDCTL_DSP_STEREO
, dsp_stereo
);
840 dprintf_mciwave(stddeb
,"Linux 'wodOpen' // wBitsPerSample=%u !\n",
841 WOutDev
[wDevID
].Format
.wBitsPerSample
);
842 dprintf_mciwave(stddeb
,"Linux 'wodOpen' // nAvgBytesPerSec=%lu !\n",
843 WOutDev
[wDevID
].Format
.wf
.nAvgBytesPerSec
);
844 dprintf_mciwave(stddeb
,"Linux 'wodOpen' // nSamplesPerSec=%lu !\n",
845 WOutDev
[wDevID
].Format
.wf
.nSamplesPerSec
);
846 dprintf_mciwave(stddeb
,"Linux 'wodOpen' // nChannels=%u !\n",
847 WOutDev
[wDevID
].Format
.wf
.nChannels
);
848 if (WAVE_NotifyClient(wDevID
, WOM_OPEN
, 0L, 0L) != MMSYSERR_NOERROR
) {
849 dprintf_mciwave(stddeb
,"Linux 'wodOpen' // can't notify client !\n");
850 return MMSYSERR_INVALPARAM
;
852 return MMSYSERR_NOERROR
;
855 /**************************************************************************
856 * wodClose [internal]
858 static DWORD
wodClose(WORD wDevID
)
860 dprintf_mciwave(stddeb
,"wodClose(%u);\n", wDevID
);
861 if (WOutDev
[wDevID
].unixdev
== 0) {
862 dprintf_mciwave(stddeb
,"Linux 'wodClose' // can't close !\n");
863 return MMSYSERR_NOTENABLED
;
865 close(WOutDev
[wDevID
].unixdev
);
866 WOutDev
[wDevID
].unixdev
= 0;
867 WOutDev
[wDevID
].bufsize
= 0;
868 WOutDev
[wDevID
].lpQueueHdr
= NULL
;
869 if (WAVE_NotifyClient(wDevID
, WOM_CLOSE
, 0L, 0L) != MMSYSERR_NOERROR
) {
870 dprintf_mciwave(stddeb
,"Linux 'wodClose' // can't notify client !\n");
871 return MMSYSERR_INVALPARAM
;
873 return MMSYSERR_NOERROR
;
876 /**************************************************************************
877 * wodWrite [internal]
879 static DWORD
wodWrite(WORD wDevID
, LPWAVEHDR lpWaveHdr
, DWORD dwSize
)
883 dprintf_mciwave(stddeb
,"wodWrite(%u, %p, %08lX);\n", wDevID
, lpWaveHdr
, dwSize
);
884 if (WOutDev
[wDevID
].unixdev
== 0) {
885 dprintf_mciwave(stddeb
,"Linux 'wodWrite' // can't play !\n");
886 return MMSYSERR_NOTENABLED
;
888 if (lpWaveHdr
->lpData
== NULL
) return WAVERR_UNPREPARED
;
889 if (!(lpWaveHdr
->dwFlags
& WHDR_PREPARED
)) return WAVERR_UNPREPARED
;
890 if (lpWaveHdr
->dwFlags
& WHDR_INQUEUE
) return WAVERR_STILLPLAYING
;
891 lpWaveHdr
->dwFlags
&= ~WHDR_DONE
;
892 lpWaveHdr
->dwFlags
|= WHDR_INQUEUE
;
893 dprintf_mciwave(stddeb
,
894 "wodWrite() // dwBufferLength %lu !\n", lpWaveHdr
->dwBufferLength
);
895 dprintf_mciwave(stddeb
,
896 "wodWrite() // WOutDev[%u].unixdev %u !\n", wDevID
, WOutDev
[wDevID
].unixdev
);
897 lpData
= PTR_SEG_TO_LIN(lpWaveHdr
->lpData
);
898 count
= write (WOutDev
[wDevID
].unixdev
, lpData
, lpWaveHdr
->dwBufferLength
);
899 dprintf_mciwave(stddeb
,
900 "wodWrite() // write returned count %u !\n", count
);
901 if (count
!= lpWaveHdr
->dwBufferLength
) {
902 dprintf_mciwave(stddeb
,"Linux 'wodWrite' // error writting !\n");
903 return MMSYSERR_NOTENABLED
;
905 WOutDev
[wDevID
].dwTotalPlayed
+= count
;
906 lpWaveHdr
->dwFlags
&= ~WHDR_INQUEUE
;
907 lpWaveHdr
->dwFlags
|= WHDR_DONE
;
908 if (WAVE_NotifyClient(wDevID
, WOM_DONE
, 0L, 0L) != MMSYSERR_NOERROR
) {
909 dprintf_mciwave(stddeb
,"Linux 'wodWrite' // can't notify client !\n");
910 return MMSYSERR_INVALPARAM
;
912 return MMSYSERR_NOERROR
;
915 /**************************************************************************
916 * wodPrepare [internal]
918 static DWORD
wodPrepare(WORD wDevID
, LPWAVEHDR lpWaveHdr
, DWORD dwSize
)
920 dprintf_mciwave(stddeb
,
921 "wodPrepare(%u, %p, %08lX);\n", wDevID
, lpWaveHdr
, dwSize
);
922 if (WOutDev
[wDevID
].unixdev
== 0) {
923 dprintf_mciwave(stddeb
,"Linux 'wodPrepare' // can't prepare !\n");
924 return MMSYSERR_NOTENABLED
;
926 /* the COOL waveeditor feels much better without this check...
927 * someone please have a look at available documentation
928 if (WOutDev[wDevID].lpQueueHdr != NULL) {
929 dprintf_mciwave(stddeb,"Linux 'wodPrepare' // already prepare !\n");
930 return MMSYSERR_NOTENABLED;
933 WOutDev
[wDevID
].dwTotalPlayed
= 0;
934 WOutDev
[wDevID
].lpQueueHdr
= lpWaveHdr
;
935 if (lpWaveHdr
->dwFlags
& WHDR_INQUEUE
) return WAVERR_STILLPLAYING
;
936 lpWaveHdr
->dwFlags
|= WHDR_PREPARED
;
937 lpWaveHdr
->dwFlags
&= ~WHDR_DONE
;
938 return MMSYSERR_NOERROR
;
941 /**************************************************************************
942 * wodUnprepare [internal]
944 static DWORD
wodUnprepare(WORD wDevID
, LPWAVEHDR lpWaveHdr
, DWORD dwSize
)
946 dprintf_mciwave(stddeb
,
947 "wodUnprepare(%u, %p, %08lX);\n", wDevID
, lpWaveHdr
, dwSize
);
948 if (WOutDev
[wDevID
].unixdev
== 0) {
949 dprintf_mciwave(stddeb
,"Linux 'wodUnprepare' // can't unprepare !\n");
950 return MMSYSERR_NOTENABLED
;
952 return MMSYSERR_NOERROR
;
955 /**************************************************************************
956 * wodRestart [internal]
958 static DWORD
wodRestart(WORD wDevID
)
960 dprintf_mciwave(stddeb
,"wodRestart(%u);\n", wDevID
);
961 if (WOutDev
[wDevID
].unixdev
== 0) {
962 dprintf_mciwave(stddeb
,"Linux 'wodRestart' // can't restart !\n");
963 return MMSYSERR_NOTENABLED
;
965 return MMSYSERR_NOERROR
;
968 /**************************************************************************
969 * wodReset [internal]
971 static DWORD
wodReset(WORD wDevID
)
973 dprintf_mciwave(stddeb
,"wodReset(%u);\n", wDevID
);
974 if (WOutDev
[wDevID
].unixdev
== 0) {
975 dprintf_mciwave(stddeb
,"Linux 'wodReset' // can't reset !\n");
976 return MMSYSERR_NOTENABLED
;
978 return MMSYSERR_NOERROR
;
982 /**************************************************************************
983 * wodGetPosition [internal]
985 static DWORD
wodGetPosition(WORD wDevID
, LPMMTIME lpTime
, DWORD uSize
)
988 dprintf_mciwave(stddeb
,"wodGetPosition(%u, %p, %lu);\n", wDevID
, lpTime
, uSize
);
989 if (WOutDev
[wDevID
].unixdev
== 0) {
990 dprintf_mciwave(stddeb
,"Linux 'wodGetPosition' // can't get pos !\n");
991 return MMSYSERR_NOTENABLED
;
993 if (lpTime
== NULL
) return MMSYSERR_INVALPARAM
;
994 switch(lpTime
->wType
) {
996 lpTime
->u
.cb
= WOutDev
[wDevID
].dwTotalPlayed
;
997 dprintf_mciwave(stddeb
,"wodGetPosition // TIME_BYTES=%lu\n", lpTime
->u
.cb
);
1000 dprintf_mciwave(stddeb
,"wodGetPosition // dwTotalPlayed=%lu\n",
1001 WOutDev
[wDevID
].dwTotalPlayed
);
1002 dprintf_mciwave(stddeb
,"wodGetPosition // wBitsPerSample=%u\n",
1003 WOutDev
[wDevID
].Format
.wBitsPerSample
);
1004 lpTime
->u
.sample
= WOutDev
[wDevID
].dwTotalPlayed
* 8 /
1005 WOutDev
[wDevID
].Format
.wBitsPerSample
;
1006 dprintf_mciwave(stddeb
,"wodGetPosition // TIME_SAMPLES=%lu\n", lpTime
->u
.sample
);
1009 time
= WOutDev
[wDevID
].dwTotalPlayed
/
1010 (WOutDev
[wDevID
].Format
.wf
.nAvgBytesPerSec
/ 1000);
1011 lpTime
->u
.smpte
.hour
= time
/ 108000;
1012 time
-= lpTime
->u
.smpte
.hour
* 108000;
1013 lpTime
->u
.smpte
.min
= time
/ 1800;
1014 time
-= lpTime
->u
.smpte
.min
* 1800;
1015 lpTime
->u
.smpte
.sec
= time
/ 30;
1016 time
-= lpTime
->u
.smpte
.sec
* 30;
1017 lpTime
->u
.smpte
.frame
= time
;
1018 lpTime
->u
.smpte
.fps
= 30;
1019 dprintf_mciwave(stddeb
,
1020 "wodGetPosition // TIME_SMPTE=%02u:%02u:%02u:%02u\n",
1021 lpTime
->u
.smpte
.hour
, lpTime
->u
.smpte
.min
,
1022 lpTime
->u
.smpte
.sec
, lpTime
->u
.smpte
.frame
);
1025 dprintf_mciwave(stddeb
,"wodGetPosition() format not supported ! use TIME_MS !\n");
1026 lpTime
->wType
= TIME_MS
;
1028 lpTime
->u
.ms
= WOutDev
[wDevID
].dwTotalPlayed
/
1029 (WOutDev
[wDevID
].Format
.wf
.nAvgBytesPerSec
/ 1000);
1030 dprintf_mciwave(stddeb
,"wodGetPosition // TIME_MS=%lu\n", lpTime
->u
.ms
);
1033 return MMSYSERR_NOERROR
;
1036 /**************************************************************************
1037 * wodGetVolume [internal]
1039 static DWORD
wodGetVolume(WORD wDevID
, LPDWORD lpdwVol
)
1042 int volume
, left
, right
;
1043 dprintf_mciwave(stddeb
,"wodGetVolume(%u, %p);\n", wDevID
, lpdwVol
);
1044 if (lpdwVol
== NULL
) return MMSYSERR_NOTENABLED
;
1045 if ((mixer
= open("/dev/mixer", O_RDONLY
)) < 0) {
1046 dprintf_mciwave(stddeb
, "Linux 'wodGetVolume' // mixer device not available !\n");
1047 return MMSYSERR_NOTENABLED
;
1049 if (ioctl(mixer
, SOUND_MIXER_READ_PCM
, &volume
) == -1) {
1050 dprintf_mciwave(stddeb
,"Linux 'wodGetVolume' // unable read mixer !\n");
1051 return MMSYSERR_NOTENABLED
;
1054 left
= volume
& 0x7F;
1055 right
= (volume
>> 8) & 0x7F;
1056 printf("Linux 'AUX_GetVolume' // left=%d right=%d !\n", left
, right
);
1057 *lpdwVol
= MAKELONG(left
<< 9, right
<< 9);
1058 return MMSYSERR_NOERROR
;
1062 /**************************************************************************
1063 * wodSetVolume [internal]
1065 static DWORD
wodSetVolume(WORD wDevID
, DWORD dwParam
)
1069 dprintf_mciwave(stddeb
,"wodSetVolume(%u, %08lX);\n", wDevID
, dwParam
);
1070 volume
= (LOWORD(dwParam
) >> 9 & 0x7F) +
1071 ((HIWORD(dwParam
) >> 9 & 0x7F) << 8);
1072 if ((mixer
= open("/dev/mixer", O_WRONLY
)) < 0) {
1073 dprintf_mciwave(stddeb
, "Linux 'wodSetVolume' // mixer device not available !\n");
1074 return MMSYSERR_NOTENABLED
;
1076 if (ioctl(mixer
, SOUND_MIXER_WRITE_PCM
, &volume
) == -1) {
1077 dprintf_mciwave(stddeb
,"Linux 'wodSetVolume' // unable set mixer !\n");
1078 return MMSYSERR_NOTENABLED
;
1081 return MMSYSERR_NOERROR
;
1084 #endif /* linux || __FreeBSD__*/
1086 /**************************************************************************
1087 * wodMessage [sample driver]
1089 DWORD
wodMessage(WORD wDevID
, WORD wMsg
, DWORD dwUser
,
1090 DWORD dwParam1
, DWORD dwParam2
)
1092 dprintf_mciwave(stddeb
,"wodMessage(%u, %04X, %08lX, %08lX, %08lX);\n",
1093 wDevID
, wMsg
, dwUser
, dwParam1
, dwParam2
);
1094 #if defined(linux) || defined(__FreeBSD__)
1097 return wodOpen(wDevID
, (LPWAVEOPENDESC
)PTR_SEG_TO_LIN(dwParam1
), dwParam2
);
1099 return wodClose(wDevID
);
1101 return wodWrite(wDevID
, (LPWAVEHDR
)PTR_SEG_TO_LIN(dwParam1
), dwParam2
);
1105 return wodGetPosition(wDevID
, (LPMMTIME
)PTR_SEG_TO_LIN(dwParam1
), dwParam2
);
1106 case WODM_BREAKLOOP
:
1109 return wodPrepare(wDevID
, (LPWAVEHDR
)PTR_SEG_TO_LIN(dwParam1
), dwParam2
);
1110 case WODM_UNPREPARE
:
1111 return wodUnprepare(wDevID
, (LPWAVEHDR
)PTR_SEG_TO_LIN(dwParam1
), dwParam2
);
1112 case WODM_GETDEVCAPS
:
1113 return wodGetDevCaps(wDevID
, (LPWAVEOUTCAPS
)PTR_SEG_TO_LIN(dwParam1
), dwParam2
);
1114 case WODM_GETNUMDEVS
:
1120 case WODM_GETPLAYBACKRATE
:
1122 case WODM_SETPLAYBACKRATE
:
1124 case WODM_GETVOLUME
:
1125 return wodGetVolume(wDevID
, (LPDWORD
)PTR_SEG_TO_LIN(dwParam1
));
1126 case WODM_SETVOLUME
:
1127 return wodSetVolume(wDevID
, dwParam1
);
1129 return wodRestart(wDevID
);
1131 return wodReset(wDevID
);
1133 dprintf_mciwave(stddeb
,"wodMessage // unknown message !\n");
1135 return MMSYSERR_NOTSUPPORTED
;
1137 return MMSYSERR_NOTENABLED
;
1142 /*-----------------------------------------------------------------------*/
1144 #if defined(linux) || defined(__FreeBSD__)
1146 /**************************************************************************
1147 * widGetDevCaps [internal]
1149 static DWORD
widGetDevCaps(WORD wDevID
, LPWAVEINCAPS lpCaps
, DWORD dwSize
)
1153 int samplesize
= 16;
1156 dprintf_mciwave(stddeb
,
1157 "widGetDevCaps(%u, %p, %lu);\n", wDevID
, lpCaps
, dwSize
);
1158 if (lpCaps
== NULL
) return MMSYSERR_NOTENABLED
;
1159 audio
= open (SOUND_DEV
, O_RDONLY
, 0);
1160 if (audio
== -1) return MMSYSERR_NOTENABLED
;
1162 lpCaps
->wMid
= 0x0002;
1163 lpCaps
->wPid
= 0x0004;
1164 strcpy(lpCaps
->szPname
, "SB16 Wave Out");
1166 lpCaps
->wMid
= 0x00FF; /* Manufac ID */
1167 lpCaps
->wPid
= 0x0001; /* Product ID */
1168 strcpy(lpCaps
->szPname
, "Linux WAVIN Driver");
1170 lpCaps
->dwFormats
= 0x00000000;
1171 lpCaps
->wChannels
= (IOCTL(audio
, SNDCTL_DSP_STEREO
, dsp_stereo
) != 0) ? 1 : 2;
1172 bytespersmpl
= (IOCTL(audio
, SNDCTL_DSP_SAMPLESIZE
, samplesize
) != 0) ? 1 : 2;
1174 if (IOCTL(audio
, SNDCTL_DSP_SPEED
, smplrate
) == 0) {
1175 lpCaps
->dwFormats
|= WAVE_FORMAT_4M08
;
1176 if (lpCaps
->wChannels
> 1) lpCaps
->dwFormats
|= WAVE_FORMAT_4S08
;
1177 if (bytespersmpl
> 1) {
1178 lpCaps
->dwFormats
|= WAVE_FORMAT_4M16
;
1179 if (lpCaps
->wChannels
> 1) lpCaps
->dwFormats
|= WAVE_FORMAT_4S16
;
1183 if (IOCTL(audio
, SNDCTL_DSP_SPEED
, smplrate
) == 0) {
1184 lpCaps
->dwFormats
|= WAVE_FORMAT_2M08
;
1185 if (lpCaps
->wChannels
> 1) lpCaps
->dwFormats
|= WAVE_FORMAT_2S08
;
1186 if (bytespersmpl
> 1) {
1187 lpCaps
->dwFormats
|= WAVE_FORMAT_2M16
;
1188 if (lpCaps
->wChannels
> 1) lpCaps
->dwFormats
|= WAVE_FORMAT_2S16
;
1192 if (IOCTL(audio
, SNDCTL_DSP_SPEED
, smplrate
) == 0) {
1193 lpCaps
->dwFormats
|= WAVE_FORMAT_1M08
;
1194 if (lpCaps
->wChannels
> 1) lpCaps
->dwFormats
|= WAVE_FORMAT_1S08
;
1195 if (bytespersmpl
> 1) {
1196 lpCaps
->dwFormats
|= WAVE_FORMAT_1M16
;
1197 if (lpCaps
->wChannels
> 1) lpCaps
->dwFormats
|= WAVE_FORMAT_1S16
;
1201 dprintf_mciwave(stddeb
,
1202 "widGetDevCaps // dwFormats = %08lX\n", lpCaps
->dwFormats
);
1203 return MMSYSERR_NOERROR
;
1207 /**************************************************************************
1208 * widOpen [internal]
1210 static DWORD
widOpen(WORD wDevID
, LPWAVEOPENDESC lpDesc
, DWORD dwFlags
)
1217 LPWAVEFORMAT lpFormat
;
1218 dprintf_mciwave(stddeb
, "widOpen(%u, %p, %08lX);\n", wDevID
, lpDesc
, dwFlags
);
1219 if (lpDesc
== NULL
) {
1220 dprintf_mciwave(stddeb
,"Linux 'widOpen' // Invalid Parameter !\n");
1221 return MMSYSERR_INVALPARAM
;
1223 if (wDevID
>= MAX_WAVINDRV
) {
1224 dprintf_mciwave(stddeb
,"Linux 'widOpen' // MAX_WAVINDRV reached !\n");
1225 return MMSYSERR_ALLOCATED
;
1227 WInDev
[wDevID
].unixdev
= 0;
1228 audio
= open (SOUND_DEV
, O_RDONLY
, 0);
1230 dprintf_mciwave(stddeb
,"Linux 'widOpen' // can't open !\n");
1231 return MMSYSERR_NOTENABLED
;
1233 IOCTL(audio
, SNDCTL_DSP_GETBLKSIZE
, abuf_size
);
1234 if (abuf_size
< 1024 || abuf_size
> 65536) {
1235 if (abuf_size
== -1)
1236 dprintf_mciwave(stddeb
,"Linux 'widOpen' // IOCTL can't 'SNDCTL_DSP_GETBLKSIZE' !\n");
1238 dprintf_mciwave(stddeb
,"Linux 'widOpen' // SNDCTL_DSP_GETBLKSIZE Invalid bufsize !\n");
1239 return MMSYSERR_NOTENABLED
;
1241 WInDev
[wDevID
].wFlags
= HIWORD(dwFlags
& CALLBACK_TYPEMASK
);
1242 switch(WInDev
[wDevID
].wFlags
) {
1244 dprintf_mciwave(stddeb
, "Linux 'widOpen' // CALLBACK_NULL !\n");
1247 dprintf_mciwave(stddeb
, "Linux 'widOpen' // CALLBACK_WINDOW !\n");
1250 dprintf_mciwave(stddeb
, "Linux 'widOpen' // CALLBACK_TASK !\n");
1253 dprintf_mciwave(stddeb
, "Linux 'widOpen' // CALLBACK_FUNCTION !\n");
1256 WInDev
[wDevID
].lpQueueHdr
= NULL
;
1257 WInDev
[wDevID
].unixdev
= audio
;
1258 WInDev
[wDevID
].bufsize
= abuf_size
;
1259 WInDev
[wDevID
].dwTotalRecorded
= 0;
1260 memcpy(&WInDev
[wDevID
].waveDesc
, lpDesc
, sizeof(WAVEOPENDESC
));
1261 lpFormat
= lpDesc
->lpFormat
;
1262 if (lpFormat
->wFormatTag
!= WAVE_FORMAT_PCM
) {
1263 dprintf_mciwave(stddeb
,"Linux 'widOpen' // Bad format %04X !\n",
1264 lpFormat
->wFormatTag
);
1265 return WAVERR_BADFORMAT
;
1267 memcpy(&WInDev
[wDevID
].Format
, lpFormat
, sizeof(PCMWAVEFORMAT
));
1268 WInDev
[wDevID
].Format
.wBitsPerSample
= 8; /* <-------------- */
1269 if (WInDev
[wDevID
].Format
.wf
.nChannels
== 0) return WAVERR_BADFORMAT
;
1270 if (WInDev
[wDevID
].Format
.wf
.nSamplesPerSec
== 0) return WAVERR_BADFORMAT
;
1271 if (WInDev
[wDevID
].Format
.wBitsPerSample
== 0) {
1272 WInDev
[wDevID
].Format
.wBitsPerSample
= 8 *
1273 (WInDev
[wDevID
].Format
.wf
.nAvgBytesPerSec
/
1274 WInDev
[wDevID
].Format
.wf
.nSamplesPerSec
) /
1275 WInDev
[wDevID
].Format
.wf
.nChannels
;
1277 samplesize
= WInDev
[wDevID
].Format
.wBitsPerSample
;
1278 smplrate
= WInDev
[wDevID
].Format
.wf
.nSamplesPerSec
;
1279 dsp_stereo
= (WInDev
[wDevID
].Format
.wf
.nChannels
> 1) ? TRUE
: FALSE
;
1280 IOCTL(audio
, SNDCTL_DSP_SPEED
, smplrate
);
1281 IOCTL(audio
, SNDCTL_DSP_SAMPLESIZE
, samplesize
);
1282 IOCTL(audio
, SNDCTL_DSP_STEREO
, dsp_stereo
);
1283 dprintf_mciwave(stddeb
,"Linux 'widOpen' // wBitsPerSample=%u !\n",
1284 WInDev
[wDevID
].Format
.wBitsPerSample
);
1285 dprintf_mciwave(stddeb
,"Linux 'widOpen' // nSamplesPerSec=%lu !\n",
1286 WInDev
[wDevID
].Format
.wf
.nSamplesPerSec
);
1287 dprintf_mciwave(stddeb
,"Linux 'widOpen' // nChannels=%u !\n",
1288 WInDev
[wDevID
].Format
.wf
.nChannels
);
1289 dprintf_mciwave(stddeb
,"Linux 'widOpen' // nAvgBytesPerSec=%lu\n",
1290 WInDev
[wDevID
].Format
.wf
.nAvgBytesPerSec
);
1291 if (WAVE_NotifyClient(wDevID
, WIM_OPEN
, 0L, 0L) != MMSYSERR_NOERROR
) {
1292 dprintf_mciwave(stddeb
,"Linux 'widOpen' // can't notify client !\n");
1293 return MMSYSERR_INVALPARAM
;
1295 return MMSYSERR_NOERROR
;
1298 /**************************************************************************
1299 * widClose [internal]
1301 static DWORD
widClose(WORD wDevID
)
1303 dprintf_mciwave(stddeb
,"widClose(%u);\n", wDevID
);
1304 if (WInDev
[wDevID
].unixdev
== 0) {
1305 dprintf_mciwave(stddeb
,"Linux 'widClose' // can't close !\n");
1306 return MMSYSERR_NOTENABLED
;
1308 close(WInDev
[wDevID
].unixdev
);
1309 WInDev
[wDevID
].unixdev
= 0;
1310 WInDev
[wDevID
].bufsize
= 0;
1311 if (WAVE_NotifyClient(wDevID
, WIM_CLOSE
, 0L, 0L) != MMSYSERR_NOERROR
) {
1312 dprintf_mciwave(stddeb
,"Linux 'widClose' // can't notify client !\n");
1313 return MMSYSERR_INVALPARAM
;
1315 return MMSYSERR_NOERROR
;
1318 /**************************************************************************
1319 * widAddBuffer [internal]
1321 static DWORD
widAddBuffer(WORD wDevID
, LPWAVEHDR lpWaveHdr
, DWORD dwSize
)
1325 dprintf_mciwave(stddeb
,
1326 "widAddBuffer(%u, %p, %08lX);\n", wDevID
, lpWaveHdr
, dwSize
);
1327 if (WInDev
[wDevID
].unixdev
== 0) {
1328 dprintf_mciwave(stddeb
,"Linux 'widAddBuffer' // can't do it !\n");
1329 return MMSYSERR_NOTENABLED
;
1331 if (!(lpWaveHdr
->dwFlags
& WHDR_PREPARED
)) {
1332 dprintf_mciwave(stddeb
, "Linux 'widAddBuffer' // never been prepared !\n");
1333 return WAVERR_UNPREPARED
;
1335 if (lpWaveHdr
->dwFlags
& WHDR_INQUEUE
) {
1336 dprintf_mciwave(stddeb
, "Linux 'widAddBuffer' // header already in use !\n");
1337 return WAVERR_STILLPLAYING
;
1339 lpWaveHdr
->dwFlags
|= WHDR_PREPARED
;
1340 lpWaveHdr
->dwFlags
|= WHDR_INQUEUE
;
1341 lpWaveHdr
->dwFlags
&= ~WHDR_DONE
;
1342 lpWaveHdr
->dwBytesRecorded
= 0;
1343 if (WInDev
[wDevID
].lpQueueHdr
== NULL
) {
1344 /* begin the queue with a first header ... */
1345 WInDev
[wDevID
].lpQueueHdr
= lpWaveHdr
;
1346 WInDev
[wDevID
].dwTotalRecorded
= 0;
1349 /* added to the queue, except if it's the one just prepared ... */
1350 lpWIHdr
= WInDev
[wDevID
].lpQueueHdr
;
1351 while (lpWIHdr
->lpNext
!= NULL
) {
1352 lpWIHdr
= lpWIHdr
->lpNext
;
1355 lpWIHdr
->lpNext
= lpWaveHdr
;
1358 dprintf_mciwave(stddeb
,
1359 "widAddBuffer // buffer added ! (now %u in queue)\n", count
);
1360 return MMSYSERR_NOERROR
;
1363 /**************************************************************************
1364 * widPrepare [internal]
1366 static DWORD
widPrepare(WORD wDevID
, LPWAVEHDR lpWaveHdr
, DWORD dwSize
)
1368 dprintf_mciwave(stddeb
,
1369 "widPrepare(%u, %p, %08lX);\n", wDevID
, lpWaveHdr
, dwSize
);
1370 if (WInDev
[wDevID
].unixdev
== 0) {
1371 dprintf_mciwave(stddeb
,"Linux 'widPrepare' // can't prepare !\n");
1372 return MMSYSERR_NOTENABLED
;
1374 if (WInDev
[wDevID
].lpQueueHdr
!= NULL
) {
1375 dprintf_mciwave(stddeb
,"Linux 'widPrepare' // already prepare !\n");
1376 return WAVERR_BADFORMAT
;
1378 if (lpWaveHdr
->dwFlags
& WHDR_INQUEUE
) return WAVERR_STILLPLAYING
;
1379 lpWaveHdr
->dwFlags
|= WHDR_PREPARED
;
1380 lpWaveHdr
->dwFlags
&= ~WHDR_INQUEUE
;
1381 lpWaveHdr
->dwFlags
&= ~WHDR_DONE
;
1382 lpWaveHdr
->dwBytesRecorded
= 0;
1383 dprintf_mciwave(stddeb
,"Linux 'widPrepare' // header prepared !\n");
1384 return MMSYSERR_NOERROR
;
1387 /**************************************************************************
1388 * widUnprepare [internal]
1390 static DWORD
widUnprepare(WORD wDevID
, LPWAVEHDR lpWaveHdr
, DWORD dwSize
)
1392 dprintf_mciwave(stddeb
,
1393 "widUnprepare(%u, %p, %08lX);\n", wDevID
, lpWaveHdr
, dwSize
);
1394 if (WInDev
[wDevID
].unixdev
== 0) {
1395 dprintf_mciwave(stddeb
,"Linux 'widUnprepare' // can't unprepare !\n");
1396 return MMSYSERR_NOTENABLED
;
1398 lpWaveHdr
->dwFlags
&= ~WHDR_PREPARED
;
1399 lpWaveHdr
->dwFlags
&= ~WHDR_INQUEUE
;
1400 lpWaveHdr
->dwFlags
|= WHDR_DONE
;
1401 WInDev
[wDevID
].lpQueueHdr
= NULL
;
1402 dprintf_mciwave(stddeb
,
1403 "Linux 'widUnprepare' // all headers unprepared !\n");
1404 return MMSYSERR_NOERROR
;
1407 /**************************************************************************
1408 * widStart [internal]
1410 static DWORD
widStart(WORD wDevID
)
1414 dprintf_mciwave(stddeb
,"widStart(%u);\n", wDevID
);
1415 if (WInDev
[wDevID
].unixdev
== 0) {
1416 dprintf_mciwave(stddeb
, "Linux 'widStart' // can't start recording !\n");
1417 return MMSYSERR_NOTENABLED
;
1419 if (WInDev
[wDevID
].lpQueueHdr
== NULL
||
1420 WInDev
[wDevID
].lpQueueHdr
->lpData
== NULL
) {
1421 dprintf_mciwave(stddeb
,"Linux 'widStart' // never been prepared !\n");
1422 return WAVERR_UNPREPARED
;
1424 lpWIHdr
= WInDev
[wDevID
].lpQueueHdr
;
1425 while(lpWIHdr
!= NULL
) {
1426 lpWIHdr
->dwBufferLength
&= 0xFFFF;
1427 dprintf_mciwave(stddeb
,
1428 "widStart // recording buf#%u=%p size=%lu \n",
1429 count
, lpWIHdr
->lpData
, lpWIHdr
->dwBufferLength
);
1431 read (WInDev
[wDevID
].unixdev
,
1432 PTR_SEG_TO_LIN(lpWIHdr
->lpData
),
1433 lpWIHdr
->dwBufferLength
);
1434 lpWIHdr
->dwBytesRecorded
= lpWIHdr
->dwBufferLength
;
1435 WInDev
[wDevID
].dwTotalRecorded
+= lpWIHdr
->dwBytesRecorded
;
1436 lpWIHdr
->dwFlags
&= ~WHDR_INQUEUE
;
1437 lpWIHdr
->dwFlags
|= WHDR_DONE
;
1438 if (WAVE_NotifyClient(wDevID
, WIM_DATA
, (DWORD
)lpWIHdr
, 0L) !=
1440 dprintf_mciwave(stddeb
, "Linux 'widStart' // can't notify client !\n");
1441 return MMSYSERR_INVALPARAM
;
1443 lpWIHdr
= lpWIHdr
->lpNext
;
1446 dprintf_mciwave(stddeb
,"widStart // end of recording !\n");
1448 return MMSYSERR_NOERROR
;
1451 /**************************************************************************
1452 * widStop [internal]
1454 static DWORD
widStop(WORD wDevID
)
1456 dprintf_mciwave(stddeb
,"widStop(%u);\n", wDevID
);
1457 if (WInDev
[wDevID
].unixdev
== 0) {
1458 dprintf_mciwave(stddeb
,"Linux 'widStop' // can't stop !\n");
1459 return MMSYSERR_NOTENABLED
;
1461 return MMSYSERR_NOERROR
;
1464 /**************************************************************************
1465 * widReset [internal]
1467 static DWORD
widReset(WORD wDevID
)
1469 dprintf_mciwave(stddeb
,"widReset(%u);\n", wDevID
);
1470 if (WInDev
[wDevID
].unixdev
== 0) {
1471 dprintf_mciwave(stddeb
,"Linux 'widReset' // can't reset !\n");
1472 return MMSYSERR_NOTENABLED
;
1474 return MMSYSERR_NOERROR
;
1477 /**************************************************************************
1478 * widGetPosition [internal]
1480 static DWORD
widGetPosition(WORD wDevID
, LPMMTIME lpTime
, DWORD uSize
)
1484 dprintf_mciwave(stddeb
,
1485 "widGetPosition(%u, %p, %lu);\n", wDevID
, lpTime
, uSize
);
1486 if (WInDev
[wDevID
].unixdev
== 0) {
1487 dprintf_mciwave(stddeb
,"Linux 'widGetPosition' // can't get pos !\n");
1488 return MMSYSERR_NOTENABLED
;
1490 if (lpTime
== NULL
) return MMSYSERR_INVALPARAM
;
1491 dprintf_mciwave(stddeb
,"widGetPosition // wType=%04X !\n",
1493 dprintf_mciwave(stddeb
,"widGetPosition // wBitsPerSample=%u\n",
1494 WInDev
[wDevID
].Format
.wBitsPerSample
);
1495 dprintf_mciwave(stddeb
,"widGetPosition // nSamplesPerSec=%lu\n",
1496 WInDev
[wDevID
].Format
.wf
.nSamplesPerSec
);
1497 dprintf_mciwave(stddeb
,"widGetPosition // nChannels=%u\n",
1498 WInDev
[wDevID
].Format
.wf
.nChannels
);
1499 dprintf_mciwave(stddeb
,"widGetPosition // nAvgBytesPerSec=%lu\n",
1500 WInDev
[wDevID
].Format
.wf
.nAvgBytesPerSec
);
1502 switch(lpTime
->wType
) {
1504 lpTime
->u
.cb
= WInDev
[wDevID
].dwTotalRecorded
;
1505 dprintf_mciwave(stddeb
,
1506 "widGetPosition // TIME_BYTES=%lu\n", lpTime
->u
.cb
);
1509 lpTime
->u
.sample
= WInDev
[wDevID
].dwTotalRecorded
* 8 /
1510 WInDev
[wDevID
].Format
.wBitsPerSample
;
1511 dprintf_mciwave(stddeb
,
1512 "widGetPosition // TIME_SAMPLES=%lu\n",
1516 time
= WInDev
[wDevID
].dwTotalRecorded
/
1517 (WInDev
[wDevID
].Format
.wf
.nAvgBytesPerSec
/ 1000);
1518 lpTime
->u
.smpte
.hour
= time
/ 108000;
1519 time
-= lpTime
->u
.smpte
.hour
* 108000;
1520 lpTime
->u
.smpte
.min
= time
/ 1800;
1521 time
-= lpTime
->u
.smpte
.min
* 1800;
1522 lpTime
->u
.smpte
.sec
= time
/ 30;
1523 time
-= lpTime
->u
.smpte
.sec
* 30;
1524 lpTime
->u
.smpte
.frame
= time
;
1525 lpTime
->u
.smpte
.fps
= 30;
1526 dprintf_mciwave(stddeb
,"widGetPosition // TIME_SMPTE=%02u:%02u:%02u:%02u\n",
1527 lpTime
->u
.smpte
.hour
, lpTime
->u
.smpte
.min
,
1528 lpTime
->u
.smpte
.sec
, lpTime
->u
.smpte
.frame
);
1531 dprintf_mciwave(stddeb
,"widGetPosition() format not supported ! use TIME_MS !\n");
1532 lpTime
->wType
= TIME_MS
;
1534 lpTime
->u
.ms
= WInDev
[wDevID
].dwTotalRecorded
/
1535 (WInDev
[wDevID
].Format
.wf
.nAvgBytesPerSec
/ 1000);
1536 dprintf_mciwave(stddeb
,
1537 "widGetPosition // TIME_MS=%lu\n", lpTime
->u
.ms
);
1540 return MMSYSERR_NOERROR
;
1543 #endif /* linux || __FreeBSD__ */
1545 /**************************************************************************
1546 * widMessage [sample driver]
1548 DWORD
widMessage(WORD wDevID
, WORD wMsg
, DWORD dwUser
,
1549 DWORD dwParam1
, DWORD dwParam2
)
1551 dprintf_mciwave(stddeb
,"widMessage(%u, %04X, %08lX, %08lX, %08lX);\n",
1552 wDevID
, wMsg
, dwUser
, dwParam1
, dwParam2
);
1553 #if defined(linux) || defined(__FreeBSD__)
1556 return widOpen(wDevID
, (LPWAVEOPENDESC
)PTR_SEG_TO_LIN(dwParam1
), dwParam2
);
1558 return widClose(wDevID
);
1559 case WIDM_ADDBUFFER
:
1560 return widAddBuffer(wDevID
, (LPWAVEHDR
)PTR_SEG_TO_LIN(dwParam1
), dwParam2
);
1562 return widPrepare(wDevID
, (LPWAVEHDR
)PTR_SEG_TO_LIN(dwParam1
), dwParam2
);
1563 case WIDM_UNPREPARE
:
1564 return widUnprepare(wDevID
, (LPWAVEHDR
)PTR_SEG_TO_LIN(dwParam1
), dwParam2
);
1565 case WIDM_GETDEVCAPS
:
1566 return widGetDevCaps(wDevID
, (LPWAVEINCAPS
)PTR_SEG_TO_LIN(dwParam1
), dwParam2
);
1567 case WIDM_GETNUMDEVS
:
1570 return widGetPosition(wDevID
, (LPMMTIME
)PTR_SEG_TO_LIN(dwParam1
), dwParam2
);
1572 return widReset(wDevID
);
1574 return widStart(wDevID
);
1576 return widStop(wDevID
);
1578 dprintf_mciwave(stddeb
,"widMessage // unknown message !\n");
1580 return MMSYSERR_NOTSUPPORTED
;
1582 return MMSYSERR_NOTENABLED
;
1587 /**************************************************************************
1588 * AUDIO_DriverProc [sample driver]
1590 LONG
WAVE_DriverProc(DWORD dwDevID
, HDRVR16 hDriv
, WORD wMsg
,
1591 DWORD dwParam1
, DWORD dwParam2
)
1593 #if defined(linux) || defined(__FreeBSD__)
1594 dprintf_mciwave(stddeb
,"WAVE_DriverProc(%08lX, %04X, %04X, %08lX, %08lX)\n",
1595 dwDevID
, hDriv
, wMsg
, dwParam1
, dwParam2
);
1609 case DRV_QUERYCONFIGURE
:
1612 MessageBox16(0, "Sample MultiMedia Linux Driver !",
1613 "MMLinux Driver", MB_OK
);
1616 return DRVCNF_RESTART
;
1618 return DRVCNF_RESTART
;
1619 case MCI_OPEN_DRIVER
:
1621 return WAVE_mciOpen(dwDevID
, dwParam1
, (LPMCI_WAVE_OPEN_PARMS
)PTR_SEG_TO_LIN(dwParam2
));
1622 case MCI_CLOSE_DRIVER
:
1624 return WAVE_mciClose(dwDevID
, dwParam1
, (LPMCI_GENERIC_PARMS
)PTR_SEG_TO_LIN(dwParam2
));
1626 return WAVE_mciPlay(dwDevID
, dwParam1
, (LPMCI_PLAY_PARMS
)PTR_SEG_TO_LIN(dwParam2
));
1628 return WAVE_mciRecord(dwDevID
, dwParam1
, (LPMCI_RECORD_PARMS
)PTR_SEG_TO_LIN(dwParam2
));
1630 return WAVE_mciStop(dwDevID
, dwParam1
, (LPMCI_GENERIC_PARMS
)PTR_SEG_TO_LIN(dwParam2
));
1632 return WAVE_mciSet(dwDevID
, dwParam1
, (LPMCI_SET_PARMS
)PTR_SEG_TO_LIN(dwParam2
));
1634 return WAVE_mciPause(dwDevID
, dwParam1
, (LPMCI_GENERIC_PARMS
)PTR_SEG_TO_LIN(dwParam2
));
1636 return WAVE_mciResume(dwDevID
, dwParam1
, (LPMCI_GENERIC_PARMS
)PTR_SEG_TO_LIN(dwParam2
));
1638 return WAVE_mciStatus(dwDevID
, dwParam1
, (LPMCI_STATUS_PARMS
)PTR_SEG_TO_LIN(dwParam2
));
1639 case MCI_GETDEVCAPS
:
1640 return WAVE_mciGetDevCaps(dwDevID
, dwParam1
, (LPMCI_GETDEVCAPS_PARMS
)PTR_SEG_TO_LIN(dwParam2
));
1642 return WAVE_mciInfo(dwDevID
, dwParam1
, (LPMCI_INFO_PARMS
)PTR_SEG_TO_LIN(dwParam2
));
1644 return DefDriverProc(dwDevID
, hDriv
, wMsg
, dwParam1
, dwParam2
);
1647 return MMSYSERR_NOTENABLED
;