2 * Sample Wine Driver for Linux
4 * Copyright 1994 Martin Ayotte
8 #define BUILTIN_MMSYSTEM
11 #ifdef BUILTIN_MMSYSTEM
19 #include <sys/ioctl.h>
25 #include "stackframe.h"
28 #include <linux/soundcard.h>
35 #define SOUND_DEV "/dev/dsp"
38 #define IOCTL(a,b,c) ((-1==ioctl(a,b,&c))&&(perror("ioctl:"#b":"#c),0))
40 #define IOCTL(a,b,c) (c = ioctl(a,b,c) )
43 #define MAX_WAVOUTDRV 2
44 #define MAX_WAVINDRV 2
45 #define MAX_MCIWAVDRV 2
51 WAVEOPENDESC waveDesc
;
61 DWORD bufsize
; /* Linux '/dev/dsp' give us that size */
62 WAVEOPENDESC waveDesc
;
66 DWORD dwTotalRecorded
;
70 int nUseCount
; /* Incremented for each shared open */
71 BOOL fShareable
; /* TRUE if first open was shareable */
72 WORD wNotifyDeviceID
; /* MCI device ID with a pending notification */
73 HANDLE hCallback
; /* Callback handle for pending notification */
74 HMMIO hFile
; /* mmio file handle open as Element */
75 MCI_WAVE_OPEN_PARMS openParms
;
76 PCMWAVEFORMAT WaveFormat
;
80 static LINUX_WAVEOUT WOutDev
[MAX_WAVOUTDRV
];
81 static LINUX_WAVEIN WInDev
[MAX_WAVOUTDRV
];
82 static LINUX_MCIWAVE MCIWavDev
[MAX_MCIWAVDRV
];
85 /**************************************************************************
86 * WAVE_NotifyClient [internal]
88 static DWORD
WAVE_NotifyClient(UINT wDevID
, WORD wMsg
,
89 DWORD dwParam1
, DWORD dwParam2
)
91 if (WInDev
[wDevID
].wFlags
!= DCB_NULL
&& !DriverCallback(
92 WInDev
[wDevID
].waveDesc
.dwCallBack
, WInDev
[wDevID
].wFlags
,
93 WInDev
[wDevID
].waveDesc
.hWave
, wMsg
,
94 WInDev
[wDevID
].waveDesc
.dwInstance
, dwParam1
, dwParam2
)) {
95 dprintf_mciwave(stddeb
,"WAVE_NotifyClient // can't notify client !\n");
96 return MMSYSERR_NOERROR
;
102 /**************************************************************************
104 static DWORD
WAVE_mciOpen(UINT wDevID
, DWORD dwFlags
, LPMCI_WAVE_OPEN_PARMS lpParms
)
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
;
117 dprintf_mciwave(stddeb
,"WAVE_mciOpen // wDevID=%04X\n", wDevID
);
118 if (MCIWavDev
[wDevID
].nUseCount
> 0) {
119 /* The driver already open on this channel */
120 /* If the driver was opened shareable before and this open specifies */
121 /* shareable then increment the use count */
122 if (MCIWavDev
[wDevID
].fShareable
&& (dwFlags
& MCI_OPEN_SHAREABLE
))
123 ++MCIWavDev
[wDevID
].nUseCount
;
125 return MCIERR_MUST_USE_SHAREABLE
;
128 MCIWavDev
[wDevID
].nUseCount
= 1;
129 MCIWavDev
[wDevID
].fShareable
= dwFlags
& MCI_OPEN_SHAREABLE
;
131 dprintf_mciwave(stddeb
,"WAVE_mciOpen // before setting lParams->wDeviceID // winstack=%p ds=%04X ss=%04X sp=%04X\n",
132 (BYTE
*)CURRENT_STACK16
->args
,
133 CURRENT_STACK16
->ds
, IF1632_Saved16_ss
, IF1632_Saved16_sp
);
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
[wDevID
].hFile
= mmioOpen(str
, NULL
,
145 MMIO_ALLOCBUF
| MMIO_READWRITE
| MMIO_EXCLUSIVE
);
146 if (MCIWavDev
[wDevID
].hFile
== 0) {
147 dprintf_mciwave(stddeb
,"WAVE_mciOpen // can't find file='%s' !\n", str
);
148 return MCIERR_FILE_NOT_FOUND
;
152 MCIWavDev
[wDevID
].hFile
= 0;
154 dprintf_mciwave(stddeb
,"WAVE_mciOpen // hFile=%u\n", MCIWavDev
[wDevID
].hFile
);
155 memcpy(&MCIWavDev
[wDevID
].openParms
, lpParms
, sizeof(MCI_WAVE_OPEN_PARMS
));
156 MCIWavDev
[wDevID
].wNotifyDeviceID
= lpParms
->wDeviceID
;
157 lpWaveFormat
= &MCIWavDev
[wDevID
].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
[wDevID
].hFile
!= 0) {
172 if (mmioDescend(MCIWavDev
[wDevID
].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
[wDevID
].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
[wDevID
].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
[wDevID
].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(0, WODM_OPEN
, 0, (DWORD
)lpDesc
, CALLBACK_NULL
);
215 dwRet
= widMessage(0, 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(UINT wDevID
, DWORD dwParam
, LPMCI_GENERIC_PARMS lpParms
)
227 dprintf_mciwave(stddeb
,
228 "WAVE_mciClose(%u, %08lX, %p);\n", wDevID
, dwParam
, lpParms
);
229 MCIWavDev
[wDevID
].nUseCount
--;
230 if (MCIWavDev
[wDevID
].nUseCount
== 0) {
231 if (MCIWavDev
[wDevID
].hFile
!= 0) {
232 mmioClose(MCIWavDev
[wDevID
].hFile
, 0);
233 MCIWavDev
[wDevID
].hFile
= 0;
235 dwRet
= wodMessage(0, WODM_CLOSE
, 0, 0L, 0L);
236 if (dwRet
!= MMSYSERR_NOERROR
) return MCIERR_INTERNAL
;
237 dwRet
= widMessage(0, WIDM_CLOSE
, 0, 0L, 0L);
238 if (dwRet
!= MMSYSERR_NOERROR
) return MCIERR_INTERNAL
;
244 /**************************************************************************
245 * WAVE_mciPlay [internal]
247 static DWORD
WAVE_mciPlay(UINT wDevID
, DWORD dwFlags
, LPMCI_PLAY_PARMS lpParms
)
254 LPWAVEHDR lp16WaveHdr
;
256 dprintf_mciwave(stddeb
,
257 "WAVE_mciPlay(%u, %08lX, %p);\n", wDevID
, dwFlags
, lpParms
);
258 if (MCIWavDev
[wDevID
].hFile
== 0) {
259 dprintf_mciwave(stddeb
,"WAVE_mciPlay // can't find file='%s' !\n",
260 MCIWavDev
[wDevID
].openParms
.lpstrElementName
);
261 return MCIERR_FILE_NOT_FOUND
;
263 start
= 1; end
= 99999;
264 if (dwFlags
& MCI_FROM
) {
265 start
= lpParms
->dwFrom
;
266 dprintf_mciwave(stddeb
,
267 "WAVE_mciPlay // MCI_FROM=%d \n", start
);
269 if (dwFlags
& MCI_TO
) {
271 dprintf_mciwave(stddeb
,"WAVE_mciPlay // MCI_TO=%d \n", end
);
274 if (dwFlags
& MCI_NOTIFY
) {
275 dprintf_mciwave(stddeb
,
276 "WAVE_mciPlay // MCI_NOTIFY %08lX !\n", lpParms
->dwCallback
);
279 dprintf_mciwave(stddeb
,
280 "WAVE_mciPlay // Can't 'fork' process !\n");
285 dprintf_mciwave(stddeb
,"WAVE_mciPlay // process started ! return to caller...\n");
291 lpWaveHdr
= &MCIWavDev
[wDevID
].WaveHdr
;
292 hData
= GlobalAlloc16(GMEM_MOVEABLE
, bufsize
);
293 lpWaveHdr
->lpData
= (LPSTR
) WIN16_GlobalLock16(hData
);
294 lpWaveHdr
->dwUser
= 0L;
295 lpWaveHdr
->dwFlags
= 0L;
296 lpWaveHdr
->dwLoops
= 0L;
297 hWaveHdr
= USER_HEAP_ALLOC(sizeof(WAVEHDR
));
298 lp16WaveHdr
= (LPWAVEHDR
) USER_HEAP_SEG_ADDR(hWaveHdr
);
299 memcpy(PTR_SEG_TO_LIN(lp16WaveHdr
), lpWaveHdr
, sizeof(WAVEHDR
));
300 lpWaveHdr
= PTR_SEG_TO_LIN(lp16WaveHdr
);
301 dwRet
= wodMessage(0, WODM_PREPARE
, 0, (DWORD
)lp16WaveHdr
, sizeof(WAVEHDR
));
303 count
= mmioRead(MCIWavDev
[wDevID
].hFile
,
304 PTR_SEG_TO_LIN(lpWaveHdr
->lpData
), bufsize
);
305 dprintf_mciwave(stddeb
,"WAVE_mciPlay // mmioRead bufsize=%ld count=%ld\n", bufsize
, count
);
306 if (count
< 1) break;
307 lpWaveHdr
->dwBufferLength
= count
;
308 /* lpWaveHdr->dwBytesRecorded = count; */
309 dprintf_mciwave(stddeb
,"WAVE_mciPlay // before WODM_WRITE lpWaveHdr=%p dwBufferLength=%lu dwBytesRecorded=%lu\n",
310 lpWaveHdr
, lpWaveHdr
->dwBufferLength
, lpWaveHdr
->dwBytesRecorded
);
311 dwRet
= wodMessage(0, WODM_WRITE
, 0, (DWORD
)lp16WaveHdr
, sizeof(WAVEHDR
));
313 dwRet
= wodMessage(0, WODM_UNPREPARE
, 0, (DWORD
)lp16WaveHdr
, sizeof(WAVEHDR
));
314 if (lpWaveHdr
->lpData
!= NULL
) {
315 GlobalUnlock16(hData
);
317 lpWaveHdr
->lpData
= NULL
;
319 USER_HEAP_FREE(hWaveHdr
);
320 if (dwFlags
& MCI_NOTIFY
) {
321 dprintf_mciwave(stddeb
,"WAVE_mciPlay // MCI_NOTIFY_SUCCESSFUL %08lX !\n", lpParms
->dwCallback
);
322 mciDriverNotify((HWND
)LOWORD(lpParms
->dwCallback
),
323 MCIWavDev
[wDevID
].wNotifyDeviceID
, MCI_NOTIFY_SUCCESSFUL
);
329 /**************************************************************************
330 * WAVE_mciRecord [internal]
332 static DWORD
WAVE_mciRecord(UINT wDevID
, DWORD dwFlags
, LPMCI_RECORD_PARMS lpParms
)
339 LPWAVEHDR lp16WaveHdr
;
342 dprintf_mciwave(stddeb
,
343 "WAVE_mciRecord(%u, %08lX, %p);\n", wDevID
, dwFlags
, lpParms
);
344 if (MCIWavDev
[wDevID
].hFile
== 0) {
345 dprintf_mciwave(stddeb
,"WAVE_mciRecord // can't find file='%s' !\n",
346 MCIWavDev
[wDevID
].openParms
.lpstrElementName
);
347 return MCIERR_FILE_NOT_FOUND
;
349 start
= 1; end
= 99999;
350 if (dwFlags
& MCI_FROM
) {
351 start
= lpParms
->dwFrom
;
352 dprintf_mciwave(stddeb
,
353 "WAVE_mciRecord // MCI_FROM=%d \n", start
);
355 if (dwFlags
& MCI_TO
) {
357 dprintf_mciwave(stddeb
,"WAVE_mciRecord // MCI_TO=%d \n", end
);
360 lpWaveHdr
= &MCIWavDev
[wDevID
].WaveHdr
;
361 hData
= GlobalAlloc16(GMEM_MOVEABLE
, bufsize
);
362 lpWaveHdr
->lpData
= (LPSTR
) WIN16_GlobalLock16(hData
);
363 lpWaveHdr
->dwBufferLength
= bufsize
;
364 lpWaveHdr
->dwUser
= 0L;
365 lpWaveHdr
->dwFlags
= 0L;
366 lpWaveHdr
->dwLoops
= 0L;
367 hWaveHdr
= USER_HEAP_ALLOC(sizeof(WAVEHDR
));
368 lp16WaveHdr
= (LPWAVEHDR
) USER_HEAP_SEG_ADDR(hWaveHdr
);
369 memcpy(PTR_SEG_TO_LIN(lp16WaveHdr
), lpWaveHdr
, sizeof(WAVEHDR
));
370 lpWaveHdr
= PTR_SEG_TO_LIN(lp16WaveHdr
);
371 dwRet
= widMessage(0, WIDM_PREPARE
, 0, (DWORD
)lp16WaveHdr
, sizeof(WAVEHDR
));
372 dprintf_mciwave(stddeb
,"WAVE_mciRecord // after WIDM_PREPARE \n");
374 lpWaveHdr
->dwBytesRecorded
= 0;
375 dwRet
= widMessage(0, WIDM_START
, 0, 0L, 0L);
376 dprintf_mciwave(stddeb
,
377 "WAVE_mciRecord // after WIDM_START lpWaveHdr=%p dwBytesRecorded=%lu\n",
378 lpWaveHdr
, lpWaveHdr
->dwBytesRecorded
);
379 if (lpWaveHdr
->dwBytesRecorded
== 0) break;
381 dprintf_mciwave(stddeb
,"WAVE_mciRecord // before WIDM_UNPREPARE \n");
382 dwRet
= widMessage(0, WIDM_UNPREPARE
, 0, (DWORD
)lp16WaveHdr
, sizeof(WAVEHDR
));
383 dprintf_mciwave(stddeb
,"WAVE_mciRecord // after WIDM_UNPREPARE \n");
384 if (lpWaveHdr
->lpData
!= NULL
) {
385 GlobalUnlock16(hData
);
387 lpWaveHdr
->lpData
= NULL
;
389 USER_HEAP_FREE(hWaveHdr
);
390 if (dwFlags
& MCI_NOTIFY
) {
391 dprintf_mciwave(stddeb
,"WAVE_mciRecord // MCI_NOTIFY_SUCCESSFUL %08lX !\n", lpParms
->dwCallback
);
392 mciDriverNotify((HWND
)LOWORD(lpParms
->dwCallback
),
393 MCIWavDev
[wDevID
].wNotifyDeviceID
, MCI_NOTIFY_SUCCESSFUL
);
399 /**************************************************************************
400 * WAVE_mciStop [internal]
402 static DWORD
WAVE_mciStop(UINT wDevID
, DWORD dwFlags
, LPMCI_GENERIC_PARMS lpParms
)
404 dprintf_mciwave(stddeb
,
405 "WAVE_mciStop(%u, %08lX, %p);\n", wDevID
, dwFlags
, lpParms
);
406 if (lpParms
== NULL
) return MCIERR_INTERNAL
;
411 /**************************************************************************
412 * WAVE_mciPause [internal]
414 static DWORD
WAVE_mciPause(UINT wDevID
, DWORD dwFlags
, LPMCI_GENERIC_PARMS lpParms
)
416 dprintf_mciwave(stddeb
,
417 "WAVE_mciPause(%u, %08lX, %p);\n", wDevID
, dwFlags
, lpParms
);
418 if (lpParms
== NULL
) return MCIERR_INTERNAL
;
423 /**************************************************************************
424 * WAVE_mciResume [internal]
426 static DWORD
WAVE_mciResume(UINT wDevID
, DWORD dwFlags
, LPMCI_GENERIC_PARMS lpParms
)
428 dprintf_mciwave(stddeb
,
429 "WAVE_mciResume(%u, %08lX, %p);\n", wDevID
, dwFlags
, lpParms
);
430 if (lpParms
== NULL
) return MCIERR_INTERNAL
;
435 /**************************************************************************
436 * WAVE_mciSet [internal]
438 static DWORD
WAVE_mciSet(UINT wDevID
, DWORD dwFlags
, LPMCI_SET_PARMS lpParms
)
440 dprintf_mciwave(stddeb
,
441 "WAVE_mciSet(%u, %08lX, %p);\n", wDevID
, dwFlags
, lpParms
);
442 if (lpParms
== NULL
) return MCIERR_INTERNAL
;
443 dprintf_mciwave(stddeb
,
444 "WAVE_mciSet // dwTimeFormat=%08lX\n", lpParms
->dwTimeFormat
);
445 dprintf_mciwave(stddeb
,
446 "WAVE_mciSet // dwAudio=%08lX\n", lpParms
->dwAudio
);
447 if (dwFlags
& MCI_SET_TIME_FORMAT
) {
448 switch (lpParms
->dwTimeFormat
) {
449 case MCI_FORMAT_MILLISECONDS
:
450 dprintf_mciwave(stddeb
, "WAVE_mciSet // MCI_FORMAT_MILLISECONDS !\n");
452 case MCI_FORMAT_BYTES
:
453 dprintf_mciwave(stddeb
, "WAVE_mciSet // MCI_FORMAT_BYTES !\n");
455 case MCI_FORMAT_SAMPLES
:
456 dprintf_mciwave(stddeb
, "WAVE_mciSet // MCI_FORMAT_SAMPLES !\n");
459 dprintf_mciwave(stddeb
, "WAVE_mciSet // bad time format !\n");
460 return MCIERR_BAD_TIME_FORMAT
;
463 if (dwFlags
& MCI_SET_VIDEO
) return MCIERR_UNSUPPORTED_FUNCTION
;
464 if (dwFlags
& MCI_SET_DOOR_OPEN
) return MCIERR_UNSUPPORTED_FUNCTION
;
465 if (dwFlags
& MCI_SET_DOOR_CLOSED
) return MCIERR_UNSUPPORTED_FUNCTION
;
466 if (dwFlags
& MCI_SET_AUDIO
)
467 dprintf_mciwave(stddeb
,"WAVE_mciSet // MCI_SET_AUDIO !\n");
468 if (dwFlags
&& MCI_SET_ON
) {
469 dprintf_mciwave(stddeb
,"WAVE_mciSet // MCI_SET_ON !\n");
470 if (dwFlags
&& MCI_SET_AUDIO_LEFT
)
471 dprintf_mciwave(stddeb
,"WAVE_mciSet // MCI_SET_AUDIO_LEFT !\n");
472 if (dwFlags
&& MCI_SET_AUDIO_RIGHT
)
473 dprintf_mciwave(stddeb
,"WAVE_mciSet // MCI_SET_AUDIO_RIGHT !\n");
475 if (dwFlags
& MCI_SET_OFF
)
476 dprintf_mciwave(stddeb
,"WAVE_mciSet // MCI_SET_OFF !\n");
477 if (dwFlags
& MCI_WAVE_INPUT
)
478 dprintf_mciwave(stddeb
,"WAVE_mciSet // MCI_WAVE_INPUT !\n");
479 if (dwFlags
& MCI_WAVE_OUTPUT
)
480 dprintf_mciwave(stddeb
,"WAVE_mciSet // MCI_WAVE_OUTPUT !\n");
481 if (dwFlags
& MCI_WAVE_SET_ANYINPUT
)
482 dprintf_mciwave(stddeb
,"WAVE_mciSet // MCI_WAVE_SET_ANYINPUT !\n");
483 if (dwFlags
& MCI_WAVE_SET_ANYOUTPUT
)
484 dprintf_mciwave(stddeb
,"WAVE_mciSet // MCI_WAVE_SET_ANYOUTPUT !\n");
485 if (dwFlags
& MCI_WAVE_SET_AVGBYTESPERSEC
)
486 dprintf_mciwave(stddeb
,
487 "WAVE_mciSet // MCI_WAVE_SET_AVGBYTESPERSEC !\n");
488 if (dwFlags
& MCI_WAVE_SET_BITSPERSAMPLE
)
489 dprintf_mciwave(stddeb
,
490 "WAVE_mciSet // MCI_WAVE_SET_BITSPERSAMPLE !\n");
491 if (dwFlags
& MCI_WAVE_SET_BLOCKALIGN
)
492 dprintf_mciwave(stddeb
,"WAVE_mciSet // MCI_WAVE_SET_BLOCKALIGN !\n");
493 if (dwFlags
& MCI_WAVE_SET_CHANNELS
)
494 dprintf_mciwave(stddeb
,"WAVE_mciSet // MCI_WAVE_SET_CHANNELS !\n");
495 if (dwFlags
& MCI_WAVE_SET_FORMATTAG
)
496 dprintf_mciwave(stddeb
,"WAVE_mciSet // MCI_WAVE_SET_FORMATTAG !\n");
497 if (dwFlags
& MCI_WAVE_SET_SAMPLESPERSEC
)
498 dprintf_mciwave(stddeb
,
499 "WAVE_mciSet // MCI_WAVE_SET_SAMPLESPERSEC !\n");
504 /**************************************************************************
505 * WAVE_mciStatus [internal]
507 static DWORD
WAVE_mciStatus(UINT wDevID
, DWORD dwFlags
, LPMCI_STATUS_PARMS lpParms
)
509 dprintf_mciwave(stddeb
,
510 "WAVE_mciStatus(%u, %08lX, %p);\n", wDevID
, dwFlags
, lpParms
);
511 if (lpParms
== NULL
) return MCIERR_INTERNAL
;
512 if (dwFlags
& MCI_STATUS_ITEM
) {
513 switch(lpParms
->dwItem
) {
514 case MCI_STATUS_CURRENT_TRACK
:
515 lpParms
->dwReturn
= 1;
517 case MCI_STATUS_LENGTH
:
518 lpParms
->dwReturn
= 5555;
519 if (dwFlags
& MCI_TRACK
) {
520 lpParms
->dwTrack
= 1;
521 lpParms
->dwReturn
= 2222;
524 case MCI_STATUS_MODE
:
525 lpParms
->dwReturn
= MCI_MODE_STOP
;
527 case MCI_STATUS_MEDIA_PRESENT
:
528 dprintf_mciwave(stddeb
,"WAVE_mciStatus // MCI_STATUS_MEDIA_PRESENT !\n");
529 lpParms
->dwReturn
= TRUE
;
531 case MCI_STATUS_NUMBER_OF_TRACKS
:
532 lpParms
->dwReturn
= 1;
534 case MCI_STATUS_POSITION
:
535 lpParms
->dwReturn
= 3333;
536 if (dwFlags
& MCI_STATUS_START
) {
539 if (dwFlags
& MCI_TRACK
) {
540 lpParms
->dwTrack
= 1;
541 lpParms
->dwReturn
= 777;
544 case MCI_STATUS_READY
:
545 dprintf_mciwave(stddeb
,"WAVE_mciStatus // MCI_STATUS_READY !\n");
546 lpParms
->dwReturn
= TRUE
;
548 case MCI_STATUS_TIME_FORMAT
:
549 dprintf_mciwave(stddeb
,"WAVE_mciStatus // MCI_STATUS_TIME_FORMAT !\n");
550 lpParms
->dwReturn
= MCI_FORMAT_MILLISECONDS
;
553 dprintf_mciwave(stddeb
,"WAVE_mciStatus // MCI_WAVE_INPUT !\n");
554 lpParms
->dwReturn
= 0;
556 case MCI_WAVE_OUTPUT
:
557 dprintf_mciwave(stddeb
,"WAVE_mciStatus // MCI_WAVE_OUTPUT !\n");
558 lpParms
->dwReturn
= 0;
560 case MCI_WAVE_STATUS_AVGBYTESPERSEC
:
561 dprintf_mciwave(stddeb
,"WAVE_mciStatus // MCI_WAVE_STATUS_AVGBYTESPERSEC !\n");
562 lpParms
->dwReturn
= 22050;
564 case MCI_WAVE_STATUS_BITSPERSAMPLE
:
565 dprintf_mciwave(stddeb
,"WAVE_mciStatus // MCI_WAVE_STATUS_BITSPERSAMPLE !\n");
566 lpParms
->dwReturn
= 8;
568 case MCI_WAVE_STATUS_BLOCKALIGN
:
569 dprintf_mciwave(stddeb
,"WAVE_mciStatus // MCI_WAVE_STATUS_BLOCKALIGN !\n");
570 lpParms
->dwReturn
= 1;
572 case MCI_WAVE_STATUS_CHANNELS
:
573 dprintf_mciwave(stddeb
,"WAVE_mciStatus // MCI_WAVE_STATUS_CHANNELS !\n");
574 lpParms
->dwReturn
= 1;
576 case MCI_WAVE_STATUS_FORMATTAG
:
577 dprintf_mciwave(stddeb
,"WAVE_mciStatus // MCI_WAVE_FORMATTAG !\n");
578 lpParms
->dwReturn
= WAVE_FORMAT_PCM
;
580 case MCI_WAVE_STATUS_LEVEL
:
581 dprintf_mciwave(stddeb
,"WAVE_mciStatus // MCI_WAVE_STATUS_LEVEL !\n");
582 lpParms
->dwReturn
= 0xAAAA5555;
584 case MCI_WAVE_STATUS_SAMPLESPERSEC
:
585 dprintf_mciwave(stddeb
,"WAVE_mciStatus // MCI_WAVE_STATUS_SAMPLESPERSEC !\n");
586 lpParms
->dwReturn
= 22050;
589 dprintf_mciwave(stddeb
,"WAVE_mciStatus // unknown command %08lX !\n", lpParms
->dwItem
);
590 return MCIERR_UNRECOGNIZED_COMMAND
;
593 if (dwFlags
& MCI_NOTIFY
) {
594 dprintf_mciwave(stddeb
,"WAVE_mciStatus // MCI_NOTIFY_SUCCESSFUL %08lX !\n", lpParms
->dwCallback
);
595 mciDriverNotify((HWND
)LOWORD(lpParms
->dwCallback
),
596 MCIWavDev
[wDevID
].wNotifyDeviceID
, MCI_NOTIFY_SUCCESSFUL
);
601 /**************************************************************************
602 * WAVE_mciGetDevCaps [internal]
604 static DWORD
WAVE_mciGetDevCaps(UINT wDevID
, DWORD dwFlags
,
605 LPMCI_GETDEVCAPS_PARMS lpParms
)
607 dprintf_mciwave(stddeb
,
608 "WAVE_mciGetDevCaps(%u, %08lX, %p);\n", wDevID
, dwFlags
, lpParms
);
609 if (lpParms
== NULL
) return MCIERR_INTERNAL
;
610 if (dwFlags
& MCI_GETDEVCAPS_ITEM
) {
611 switch(lpParms
->dwItem
) {
612 case MCI_GETDEVCAPS_CAN_RECORD
:
613 lpParms
->dwReturn
= TRUE
;
615 case MCI_GETDEVCAPS_HAS_AUDIO
:
616 lpParms
->dwReturn
= TRUE
;
618 case MCI_GETDEVCAPS_HAS_VIDEO
:
619 lpParms
->dwReturn
= FALSE
;
621 case MCI_GETDEVCAPS_DEVICE_TYPE
:
622 lpParms
->dwReturn
= MCI_DEVTYPE_WAVEFORM_AUDIO
;
624 case MCI_GETDEVCAPS_USES_FILES
:
625 lpParms
->dwReturn
= TRUE
;
627 case MCI_GETDEVCAPS_COMPOUND_DEVICE
:
628 lpParms
->dwReturn
= TRUE
;
630 case MCI_GETDEVCAPS_CAN_EJECT
:
631 lpParms
->dwReturn
= FALSE
;
633 case MCI_GETDEVCAPS_CAN_PLAY
:
634 lpParms
->dwReturn
= TRUE
;
636 case MCI_GETDEVCAPS_CAN_SAVE
:
637 lpParms
->dwReturn
= TRUE
;
639 case MCI_WAVE_GETDEVCAPS_INPUTS
:
640 lpParms
->dwReturn
= 1;
642 case MCI_WAVE_GETDEVCAPS_OUTPUTS
:
643 lpParms
->dwReturn
= 1;
646 return MCIERR_UNRECOGNIZED_COMMAND
;
652 /**************************************************************************
653 * WAVE_mciInfo [internal]
655 static DWORD
WAVE_mciInfo(UINT wDevID
, DWORD dwFlags
, LPMCI_INFO_PARMS lpParms
)
657 dprintf_mciwave(stddeb
,
658 "WAVE_mciInfo(%u, %08lX, %p);\n", wDevID
, dwFlags
, lpParms
);
659 if (lpParms
== NULL
) return MCIERR_INTERNAL
;
660 lpParms
->lpstrReturn
= NULL
;
662 case MCI_INFO_PRODUCT
:
663 lpParms
->lpstrReturn
= "Linux Sound System 0.5";
666 lpParms
->lpstrReturn
=
667 (LPSTR
)MCIWavDev
[wDevID
].openParms
.lpstrElementName
;
670 lpParms
->lpstrReturn
= "Linux Sound System 0.5";
672 case MCI_WAVE_OUTPUT
:
673 lpParms
->lpstrReturn
= "Linux Sound System 0.5";
676 return MCIERR_UNRECOGNIZED_COMMAND
;
678 if (lpParms
->lpstrReturn
!= NULL
)
679 lpParms
->dwRetSize
= strlen(lpParms
->lpstrReturn
);
681 lpParms
->dwRetSize
= 0;
686 /*-----------------------------------------------------------------------*/
689 /**************************************************************************
690 * wodGetDevCaps [internal]
692 static DWORD
wodGetDevCaps(WORD wDevID
, LPWAVEOUTCAPS lpCaps
, DWORD dwSize
)
699 dprintf_mciwave(stddeb
,
700 "wodGetDevCaps(%u, %p, %lu);\n", wDevID
, lpCaps
, dwSize
);
701 if (lpCaps
== NULL
) return MMSYSERR_NOTENABLED
;
702 audio
= open (SOUND_DEV
, O_WRONLY
, 0);
703 if (audio
== -1) return MMSYSERR_NOTENABLED
;
705 lpCaps
->wMid
= 0x0002;
706 lpCaps
->wPid
= 0x0104;
707 strcpy(lpCaps
->szPname
, "SB16 Wave Out");
709 lpCaps
->wMid
= 0x00FF; /* Manufac ID */
710 lpCaps
->wPid
= 0x0001; /* Product ID */
711 strcpy(lpCaps
->szPname
, "Linux WAVOUT Driver");
713 lpCaps
->dwFormats
= 0x00000000;
714 lpCaps
->dwSupport
= WAVECAPS_VOLUME
;
715 lpCaps
->wChannels
= (IOCTL(audio
, SNDCTL_DSP_STEREO
, dsp_stereo
) != 0) ? 1 : 2;
716 if (lpCaps
->wChannels
> 1) lpCaps
->dwSupport
|= WAVECAPS_LRVOLUME
;
717 bytespersmpl
= (IOCTL(audio
, SNDCTL_DSP_SAMPLESIZE
, samplesize
) != 0) ? 1 : 2;
719 if (IOCTL(audio
, SNDCTL_DSP_SPEED
, smplrate
) == 0) {
720 lpCaps
->dwFormats
|= WAVE_FORMAT_4M08
;
721 if (lpCaps
->wChannels
> 1) lpCaps
->dwFormats
|= WAVE_FORMAT_4S08
;
722 if (bytespersmpl
> 1) {
723 lpCaps
->dwFormats
|= WAVE_FORMAT_4M16
;
724 if (lpCaps
->wChannels
> 1) lpCaps
->dwFormats
|= WAVE_FORMAT_4S16
;
728 if (IOCTL(audio
, SNDCTL_DSP_SPEED
, smplrate
) == 0) {
729 lpCaps
->dwFormats
|= WAVE_FORMAT_2M08
;
730 if (lpCaps
->wChannels
> 1) lpCaps
->dwFormats
|= WAVE_FORMAT_2S08
;
731 if (bytespersmpl
> 1) {
732 lpCaps
->dwFormats
|= WAVE_FORMAT_2M16
;
733 if (lpCaps
->wChannels
> 1) lpCaps
->dwFormats
|= WAVE_FORMAT_2S16
;
737 if (IOCTL(audio
, SNDCTL_DSP_SPEED
, smplrate
) == 0) {
738 lpCaps
->dwFormats
|= WAVE_FORMAT_1M08
;
739 if (lpCaps
->wChannels
> 1) lpCaps
->dwFormats
|= WAVE_FORMAT_1S08
;
740 if (bytespersmpl
> 1) {
741 lpCaps
->dwFormats
|= WAVE_FORMAT_1M16
;
742 if (lpCaps
->wChannels
> 1) lpCaps
->dwFormats
|= WAVE_FORMAT_1S16
;
746 dprintf_mciwave(stddeb
,
747 "wodGetDevCaps // dwFormats = %08lX\n", lpCaps
->dwFormats
);
748 return MMSYSERR_NOERROR
;
752 /**************************************************************************
755 static DWORD
wodOpen(WORD wDevID
, LPWAVEOPENDESC lpDesc
, DWORD dwFlags
)
762 LPWAVEFORMAT lpFormat
;
764 dprintf_mciwave(stddeb
,
765 "wodOpen(%u, %p, %08lX);\n", wDevID
, lpDesc
, dwFlags
);
766 if (lpDesc
== NULL
) {
767 dprintf_mciwave(stddeb
,"Linux 'wodOpen' // Invalid Parameter !\n");
768 return MMSYSERR_INVALPARAM
;
770 if (wDevID
>= MAX_WAVOUTDRV
) {
771 dprintf_mciwave(stddeb
,"Linux 'wodOpen' // MAX_WAVOUTDRV reached !\n");
772 return MMSYSERR_ALLOCATED
;
774 WOutDev
[wDevID
].unixdev
= 0;
775 audio
= open (SOUND_DEV
, O_WRONLY
, 0);
777 dprintf_mciwave(stddeb
,"Linux 'wodOpen' // can't open !\n");
778 return MMSYSERR_NOTENABLED
;
780 IOCTL(audio
, SNDCTL_DSP_GETBLKSIZE
, abuf_size
);
781 if (abuf_size
< 4096 || abuf_size
> 65536) {
783 dprintf_mciwave(stddeb
,"Linux 'wodOpen' // IOCTL can't 'SNDCTL_DSP_GETBLKSIZE' !\n");
785 dprintf_mciwave(stddeb
,"Linux 'wodOpen' // SNDCTL_DSP_GETBLKSIZE Invalid bufsize !\n");
786 return MMSYSERR_NOTENABLED
;
788 WOutDev
[wDevID
].wFlags
= HIWORD(dwFlags
& CALLBACK_TYPEMASK
);
789 switch(WOutDev
[wDevID
].wFlags
) {
791 dprintf_mciwave(stddeb
, "Linux 'wodOpen' // CALLBACK_NULL !\n");
794 dprintf_mciwave(stddeb
, "Linux 'wodOpen' // CALLBACK_WINDOW !\n");
797 dprintf_mciwave(stddeb
, "Linux 'wodOpen' // CALLBACK_TASK !\n");
800 dprintf_mciwave(stddeb
, "Linux 'wodOpen' // CALLBACK_FUNCTION !\n");
803 WOutDev
[wDevID
].lpQueueHdr
= NULL
;
804 WOutDev
[wDevID
].unixdev
= audio
;
805 WOutDev
[wDevID
].dwTotalPlayed
= 0;
806 WOutDev
[wDevID
].bufsize
= abuf_size
;
807 memcpy(&WOutDev
[wDevID
].waveDesc
, lpDesc
, sizeof(WAVEOPENDESC
));
808 /* lpFormat = (LPWAVEFORMAT) PTR_SEG_TO_LIN(lpDesc->lpFormat); */
809 lpFormat
= lpDesc
->lpFormat
;
810 if (lpFormat
->wFormatTag
!= WAVE_FORMAT_PCM
) {
811 dprintf_mciwave(stddeb
,"Linux 'wodOpen' // Bad format %04X !\n",
812 lpFormat
->wFormatTag
);
813 dprintf_mciwave(stddeb
,"Linux 'wodOpen' // Bad nChannels %d !\n",
814 lpFormat
->nChannels
);
815 dprintf_mciwave(stddeb
,"Linux 'wodOpen' // Bad nSamplesPerSec %ld !\n",
816 lpFormat
->nSamplesPerSec
);
817 return WAVERR_BADFORMAT
;
819 memcpy(&WOutDev
[wDevID
].Format
, lpFormat
, sizeof(PCMWAVEFORMAT
));
820 if (WOutDev
[wDevID
].Format
.wf
.nChannels
== 0) return WAVERR_BADFORMAT
;
821 if (WOutDev
[wDevID
].Format
.wf
.nSamplesPerSec
== 0) return WAVERR_BADFORMAT
;
822 dprintf_mciwave(stddeb
,"Linux 'wodOpen' // wBitsPerSample=%u !\n",
823 WOutDev
[wDevID
].Format
.wBitsPerSample
);
824 if (WOutDev
[wDevID
].Format
.wBitsPerSample
== 0) {
825 WOutDev
[wDevID
].Format
.wBitsPerSample
= 8 *
826 (WOutDev
[wDevID
].Format
.wf
.nAvgBytesPerSec
/
827 WOutDev
[wDevID
].Format
.wf
.nSamplesPerSec
) /
828 WOutDev
[wDevID
].Format
.wf
.nChannels
;
830 samplesize
= WOutDev
[wDevID
].Format
.wBitsPerSample
;
831 smplrate
= WOutDev
[wDevID
].Format
.wf
.nSamplesPerSec
;
832 dsp_stereo
= (WOutDev
[wDevID
].Format
.wf
.nChannels
> 1) ? TRUE
: FALSE
;
833 IOCTL(audio
, SNDCTL_DSP_SPEED
, smplrate
);
834 IOCTL(audio
, SNDCTL_DSP_SAMPLESIZE
, samplesize
);
835 IOCTL(audio
, SNDCTL_DSP_STEREO
, dsp_stereo
);
836 dprintf_mciwave(stddeb
,"Linux 'wodOpen' // wBitsPerSample=%u !\n",
837 WOutDev
[wDevID
].Format
.wBitsPerSample
);
838 dprintf_mciwave(stddeb
,"Linux 'wodOpen' // nAvgBytesPerSec=%lu !\n",
839 WOutDev
[wDevID
].Format
.wf
.nAvgBytesPerSec
);
840 dprintf_mciwave(stddeb
,"Linux 'wodOpen' // nSamplesPerSec=%lu !\n",
841 WOutDev
[wDevID
].Format
.wf
.nSamplesPerSec
);
842 dprintf_mciwave(stddeb
,"Linux 'wodOpen' // nChannels=%u !\n",
843 WOutDev
[wDevID
].Format
.wf
.nChannels
);
844 if (WAVE_NotifyClient(wDevID
, WOM_OPEN
, 0L, 0L) != MMSYSERR_NOERROR
) {
845 dprintf_mciwave(stddeb
,"Linux 'wodOpen' // can't notify client !\n");
846 return MMSYSERR_INVALPARAM
;
848 return MMSYSERR_NOERROR
;
851 /**************************************************************************
852 * wodClose [internal]
854 static DWORD
wodClose(WORD wDevID
)
856 dprintf_mciwave(stddeb
,"wodClose(%u);\n", wDevID
);
857 if (WOutDev
[wDevID
].unixdev
== 0) {
858 dprintf_mciwave(stddeb
,"Linux 'wodClose' // can't close !\n");
859 return MMSYSERR_NOTENABLED
;
861 close(WOutDev
[wDevID
].unixdev
);
862 WOutDev
[wDevID
].unixdev
= 0;
863 WOutDev
[wDevID
].bufsize
= 0;
864 WOutDev
[wDevID
].lpQueueHdr
= NULL
;
865 if (WAVE_NotifyClient(wDevID
, WOM_CLOSE
, 0L, 0L) != MMSYSERR_NOERROR
) {
866 dprintf_mciwave(stddeb
,"Linux 'wodClose' // can't notify client !\n");
867 return MMSYSERR_INVALPARAM
;
869 return MMSYSERR_NOERROR
;
872 /**************************************************************************
873 * wodWrite [internal]
875 static DWORD
wodWrite(WORD wDevID
, LPWAVEHDR lpWaveHdr
, DWORD dwSize
)
879 dprintf_mciwave(stddeb
,"wodWrite(%u, %p, %08lX);\n", wDevID
, lpWaveHdr
, dwSize
);
880 if (WOutDev
[wDevID
].unixdev
== 0) {
881 dprintf_mciwave(stddeb
,"Linux 'wodWrite' // can't play !\n");
882 return MMSYSERR_NOTENABLED
;
884 if (lpWaveHdr
->lpData
== NULL
) return WAVERR_UNPREPARED
;
885 if (!(lpWaveHdr
->dwFlags
& WHDR_PREPARED
)) return WAVERR_UNPREPARED
;
886 if (lpWaveHdr
->dwFlags
& WHDR_INQUEUE
) return WAVERR_STILLPLAYING
;
887 lpWaveHdr
->dwFlags
&= ~WHDR_DONE
;
888 lpWaveHdr
->dwFlags
|= WHDR_INQUEUE
;
889 dprintf_mciwave(stddeb
,
890 "wodWrite() // dwBufferLength %lu !\n", lpWaveHdr
->dwBufferLength
);
891 dprintf_mciwave(stddeb
,
892 "wodWrite() // WOutDev[%u].unixdev %u !\n", wDevID
, WOutDev
[wDevID
].unixdev
);
893 lpData
= PTR_SEG_TO_LIN(lpWaveHdr
->lpData
);
894 count
= write (WOutDev
[wDevID
].unixdev
, lpData
, lpWaveHdr
->dwBufferLength
);
895 dprintf_mciwave(stddeb
,
896 "wodWrite() // write returned count %u !\n", count
);
897 if (count
!= lpWaveHdr
->dwBufferLength
) {
898 dprintf_mciwave(stddeb
,"Linux 'wodWrite' // error writting !\n");
899 return MMSYSERR_NOTENABLED
;
901 WOutDev
[wDevID
].dwTotalPlayed
+= count
;
902 lpWaveHdr
->dwFlags
&= ~WHDR_INQUEUE
;
903 lpWaveHdr
->dwFlags
|= WHDR_DONE
;
904 if (WAVE_NotifyClient(wDevID
, WOM_DONE
, 0L, 0L) != MMSYSERR_NOERROR
) {
905 dprintf_mciwave(stddeb
,"Linux 'wodWrite' // can't notify client !\n");
906 return MMSYSERR_INVALPARAM
;
908 return MMSYSERR_NOERROR
;
911 /**************************************************************************
912 * wodPrepare [internal]
914 static DWORD
wodPrepare(WORD wDevID
, LPWAVEHDR lpWaveHdr
, DWORD dwSize
)
916 dprintf_mciwave(stddeb
,
917 "wodPrepare(%u, %p, %08lX);\n", wDevID
, lpWaveHdr
, dwSize
);
918 if (WOutDev
[wDevID
].unixdev
== 0) {
919 dprintf_mciwave(stddeb
,"Linux 'wodPrepare' // can't prepare !\n");
920 return MMSYSERR_NOTENABLED
;
922 /* the COOL waveeditor feels much better without this check...
923 * someone please have a look at available documentation
924 if (WOutDev[wDevID].lpQueueHdr != NULL) {
925 dprintf_mciwave(stddeb,"Linux 'wodPrepare' // already prepare !\n");
926 return MMSYSERR_NOTENABLED;
929 WOutDev
[wDevID
].dwTotalPlayed
= 0;
930 WOutDev
[wDevID
].lpQueueHdr
= lpWaveHdr
;
931 if (lpWaveHdr
->dwFlags
& WHDR_INQUEUE
) return WAVERR_STILLPLAYING
;
932 lpWaveHdr
->dwFlags
|= WHDR_PREPARED
;
933 lpWaveHdr
->dwFlags
&= ~WHDR_DONE
;
934 return MMSYSERR_NOERROR
;
937 /**************************************************************************
938 * wodUnprepare [internal]
940 static DWORD
wodUnprepare(WORD wDevID
, LPWAVEHDR lpWaveHdr
, DWORD dwSize
)
942 dprintf_mciwave(stddeb
,
943 "wodUnprepare(%u, %p, %08lX);\n", wDevID
, lpWaveHdr
, dwSize
);
944 if (WOutDev
[wDevID
].unixdev
== 0) {
945 dprintf_mciwave(stddeb
,"Linux 'wodUnprepare' // can't unprepare !\n");
946 return MMSYSERR_NOTENABLED
;
948 return MMSYSERR_NOERROR
;
951 /**************************************************************************
952 * wodRestart [internal]
954 static DWORD
wodRestart(WORD wDevID
)
956 dprintf_mciwave(stddeb
,"wodRestart(%u);\n", wDevID
);
957 if (WOutDev
[wDevID
].unixdev
== 0) {
958 dprintf_mciwave(stddeb
,"Linux 'wodRestart' // can't restart !\n");
959 return MMSYSERR_NOTENABLED
;
961 return MMSYSERR_NOERROR
;
964 /**************************************************************************
965 * wodReset [internal]
967 static DWORD
wodReset(WORD wDevID
)
969 dprintf_mciwave(stddeb
,"wodReset(%u);\n", wDevID
);
970 if (WOutDev
[wDevID
].unixdev
== 0) {
971 dprintf_mciwave(stddeb
,"Linux 'wodReset' // can't reset !\n");
972 return MMSYSERR_NOTENABLED
;
974 return MMSYSERR_NOERROR
;
978 /**************************************************************************
979 * wodGetPosition [internal]
981 static DWORD
wodGetPosition(WORD wDevID
, LPMMTIME lpTime
, DWORD uSize
)
984 dprintf_mciwave(stddeb
,"wodGetPosition(%u, %p, %lu);\n", wDevID
, lpTime
, uSize
);
985 if (WOutDev
[wDevID
].unixdev
== 0) {
986 dprintf_mciwave(stddeb
,"Linux 'wodGetPosition' // can't get pos !\n");
987 return MMSYSERR_NOTENABLED
;
989 if (lpTime
== NULL
) return MMSYSERR_INVALPARAM
;
990 switch(lpTime
->wType
) {
992 lpTime
->u
.cb
= WOutDev
[wDevID
].dwTotalPlayed
;
993 dprintf_mciwave(stddeb
,"wodGetPosition // TIME_BYTES=%lu\n", lpTime
->u
.cb
);
996 dprintf_mciwave(stddeb
,"wodGetPosition // dwTotalPlayed=%lu\n",
997 WOutDev
[wDevID
].dwTotalPlayed
);
998 dprintf_mciwave(stddeb
,"wodGetPosition // wBitsPerSample=%u\n",
999 WOutDev
[wDevID
].Format
.wBitsPerSample
);
1000 lpTime
->u
.sample
= WOutDev
[wDevID
].dwTotalPlayed
* 8 /
1001 WOutDev
[wDevID
].Format
.wBitsPerSample
;
1002 dprintf_mciwave(stddeb
,"wodGetPosition // TIME_SAMPLES=%lu\n", lpTime
->u
.sample
);
1005 time
= WOutDev
[wDevID
].dwTotalPlayed
/
1006 (WOutDev
[wDevID
].Format
.wf
.nAvgBytesPerSec
/ 1000);
1007 lpTime
->u
.smpte
.hour
= time
/ 108000;
1008 time
-= lpTime
->u
.smpte
.hour
* 108000;
1009 lpTime
->u
.smpte
.min
= time
/ 1800;
1010 time
-= lpTime
->u
.smpte
.min
* 1800;
1011 lpTime
->u
.smpte
.sec
= time
/ 30;
1012 time
-= lpTime
->u
.smpte
.sec
* 30;
1013 lpTime
->u
.smpte
.frame
= time
;
1014 lpTime
->u
.smpte
.fps
= 30;
1015 dprintf_mciwave(stddeb
,
1016 "wodGetPosition // TIME_SMPTE=%02u:%02u:%02u:%02u\n",
1017 lpTime
->u
.smpte
.hour
, lpTime
->u
.smpte
.min
,
1018 lpTime
->u
.smpte
.sec
, lpTime
->u
.smpte
.frame
);
1021 dprintf_mciwave(stddeb
,"wodGetPosition() format not supported ! use TIME_MS !\n");
1022 lpTime
->wType
= TIME_MS
;
1024 lpTime
->u
.ms
= WOutDev
[wDevID
].dwTotalPlayed
/
1025 (WOutDev
[wDevID
].Format
.wf
.nAvgBytesPerSec
/ 1000);
1026 dprintf_mciwave(stddeb
,"wodGetPosition // TIME_MS=%lu\n", lpTime
->u
.ms
);
1029 return MMSYSERR_NOERROR
;
1032 /**************************************************************************
1033 * wodGetVolume [internal]
1035 static DWORD
wodGetVolume(WORD wDevID
, LPDWORD lpdwVol
)
1038 int volume
, left
, right
;
1039 dprintf_mciwave(stddeb
,"wodGetVolume(%u, %p);\n", wDevID
, lpdwVol
);
1040 if (lpdwVol
== NULL
) return MMSYSERR_NOTENABLED
;
1041 if ((mixer
= open("/dev/mixer", O_RDONLY
)) < 0) {
1042 dprintf_mciwave(stddeb
, "Linux 'wodGetVolume' // mixer device not available !\n");
1043 return MMSYSERR_NOTENABLED
;
1045 if (ioctl(mixer
, SOUND_MIXER_READ_PCM
, &volume
) == -1) {
1046 dprintf_mciwave(stddeb
,"Linux 'wodGetVolume' // unable read mixer !\n");
1047 return MMSYSERR_NOTENABLED
;
1050 left
= volume
& 0x7F;
1051 right
= (volume
>> 8) & 0x7F;
1052 printf("Linux 'AUX_GetVolume' // left=%d right=%d !\n", left
, right
);
1053 *lpdwVol
= MAKELONG(left
<< 9, right
<< 9);
1054 return MMSYSERR_NOERROR
;
1058 /**************************************************************************
1059 * wodSetVolume [internal]
1061 static DWORD
wodSetVolume(WORD wDevID
, DWORD dwParam
)
1065 dprintf_mciwave(stddeb
,"wodSetVolume(%u, %08lX);\n", wDevID
, dwParam
);
1066 volume
= (LOWORD(dwParam
) >> 9 & 0x7F) +
1067 ((HIWORD(dwParam
) >> 9 & 0x7F) << 8);
1068 if ((mixer
= open("/dev/mixer", O_WRONLY
)) < 0) {
1069 dprintf_mciwave(stddeb
, "Linux 'wodSetVolume' // mixer device not available !\n");
1070 return MMSYSERR_NOTENABLED
;
1072 if (ioctl(mixer
, SOUND_MIXER_WRITE_PCM
, &volume
) == -1) {
1073 dprintf_mciwave(stddeb
,"Linux 'wodSetVolume' // unable set mixer !\n");
1074 return MMSYSERR_NOTENABLED
;
1077 return MMSYSERR_NOERROR
;
1082 /**************************************************************************
1083 * wodMessage [sample driver]
1085 DWORD
wodMessage(WORD wDevID
, WORD wMsg
, DWORD dwUser
,
1086 DWORD dwParam1
, DWORD dwParam2
)
1088 dprintf_mciwave(stddeb
,"wodMessage(%u, %04X, %08lX, %08lX, %08lX);\n",
1089 wDevID
, wMsg
, dwUser
, dwParam1
, dwParam2
);
1093 return wodOpen(wDevID
, (LPWAVEOPENDESC
)PTR_SEG_TO_LIN(dwParam1
), dwParam2
);
1095 return wodClose(wDevID
);
1097 return wodWrite(wDevID
, (LPWAVEHDR
)PTR_SEG_TO_LIN(dwParam1
), dwParam2
);
1101 return wodGetPosition(wDevID
, (LPMMTIME
)PTR_SEG_TO_LIN(dwParam1
), dwParam2
);
1102 case WODM_BREAKLOOP
:
1105 return wodPrepare(wDevID
, (LPWAVEHDR
)PTR_SEG_TO_LIN(dwParam1
), dwParam2
);
1106 case WODM_UNPREPARE
:
1107 return wodUnprepare(wDevID
, (LPWAVEHDR
)PTR_SEG_TO_LIN(dwParam1
), dwParam2
);
1108 case WODM_GETDEVCAPS
:
1109 return wodGetDevCaps(wDevID
, (LPWAVEOUTCAPS
)PTR_SEG_TO_LIN(dwParam1
), dwParam2
);
1110 case WODM_GETNUMDEVS
:
1116 case WODM_GETPLAYBACKRATE
:
1118 case WODM_SETPLAYBACKRATE
:
1120 case WODM_GETVOLUME
:
1121 return wodGetVolume(wDevID
, (LPDWORD
)PTR_SEG_TO_LIN(dwParam1
));
1122 case WODM_SETVOLUME
:
1123 return wodSetVolume(wDevID
, dwParam1
);
1125 return wodRestart(wDevID
);
1127 return wodReset(wDevID
);
1129 dprintf_mciwave(stddeb
,"wodMessage // unknown message !\n");
1131 return MMSYSERR_NOTSUPPORTED
;
1133 return MMSYSERR_NOTENABLED
;
1138 /*-----------------------------------------------------------------------*/
1142 /**************************************************************************
1143 * widGetDevCaps [internal]
1145 static DWORD
widGetDevCaps(WORD wDevID
, LPWAVEINCAPS lpCaps
, DWORD dwSize
)
1149 int samplesize
= 16;
1152 dprintf_mciwave(stddeb
,
1153 "widGetDevCaps(%u, %p, %lu);\n", wDevID
, lpCaps
, dwSize
);
1154 if (lpCaps
== NULL
) return MMSYSERR_NOTENABLED
;
1155 audio
= open (SOUND_DEV
, O_RDONLY
, 0);
1156 if (audio
== -1) return MMSYSERR_NOTENABLED
;
1158 lpCaps
->wMid
= 0x0002;
1159 lpCaps
->wPid
= 0x0004;
1160 strcpy(lpCaps
->szPname
, "SB16 Wave Out");
1162 lpCaps
->wMid
= 0x00FF; /* Manufac ID */
1163 lpCaps
->wPid
= 0x0001; /* Product ID */
1164 strcpy(lpCaps
->szPname
, "Linux WAVIN Driver");
1166 lpCaps
->dwFormats
= 0x00000000;
1167 lpCaps
->wChannels
= (IOCTL(audio
, SNDCTL_DSP_STEREO
, dsp_stereo
) != 0) ? 1 : 2;
1168 bytespersmpl
= (IOCTL(audio
, SNDCTL_DSP_SAMPLESIZE
, samplesize
) != 0) ? 1 : 2;
1170 if (IOCTL(audio
, SNDCTL_DSP_SPEED
, smplrate
) == 0) {
1171 lpCaps
->dwFormats
|= WAVE_FORMAT_4M08
;
1172 if (lpCaps
->wChannels
> 1) lpCaps
->dwFormats
|= WAVE_FORMAT_4S08
;
1173 if (bytespersmpl
> 1) {
1174 lpCaps
->dwFormats
|= WAVE_FORMAT_4M16
;
1175 if (lpCaps
->wChannels
> 1) lpCaps
->dwFormats
|= WAVE_FORMAT_4S16
;
1179 if (IOCTL(audio
, SNDCTL_DSP_SPEED
, smplrate
) == 0) {
1180 lpCaps
->dwFormats
|= WAVE_FORMAT_2M08
;
1181 if (lpCaps
->wChannels
> 1) lpCaps
->dwFormats
|= WAVE_FORMAT_2S08
;
1182 if (bytespersmpl
> 1) {
1183 lpCaps
->dwFormats
|= WAVE_FORMAT_2M16
;
1184 if (lpCaps
->wChannels
> 1) lpCaps
->dwFormats
|= WAVE_FORMAT_2S16
;
1188 if (IOCTL(audio
, SNDCTL_DSP_SPEED
, smplrate
) == 0) {
1189 lpCaps
->dwFormats
|= WAVE_FORMAT_1M08
;
1190 if (lpCaps
->wChannels
> 1) lpCaps
->dwFormats
|= WAVE_FORMAT_1S08
;
1191 if (bytespersmpl
> 1) {
1192 lpCaps
->dwFormats
|= WAVE_FORMAT_1M16
;
1193 if (lpCaps
->wChannels
> 1) lpCaps
->dwFormats
|= WAVE_FORMAT_1S16
;
1197 dprintf_mciwave(stddeb
,
1198 "widGetDevCaps // dwFormats = %08lX\n", lpCaps
->dwFormats
);
1199 return MMSYSERR_NOERROR
;
1203 /**************************************************************************
1204 * widOpen [internal]
1206 static DWORD
widOpen(WORD wDevID
, LPWAVEOPENDESC lpDesc
, DWORD dwFlags
)
1213 LPWAVEFORMAT lpFormat
;
1214 dprintf_mciwave(stddeb
, "widOpen(%u, %p, %08lX);\n", wDevID
, lpDesc
, dwFlags
);
1215 if (lpDesc
== NULL
) {
1216 dprintf_mciwave(stddeb
,"Linux 'widOpen' // Invalid Parameter !\n");
1217 return MMSYSERR_INVALPARAM
;
1219 if (wDevID
>= MAX_WAVINDRV
) {
1220 dprintf_mciwave(stddeb
,"Linux 'widOpen' // MAX_WAVINDRV reached !\n");
1221 return MMSYSERR_ALLOCATED
;
1223 WInDev
[wDevID
].unixdev
= 0;
1224 audio
= open (SOUND_DEV
, O_RDONLY
, 0);
1226 dprintf_mciwave(stddeb
,"Linux 'widOpen' // can't open !\n");
1227 return MMSYSERR_NOTENABLED
;
1229 IOCTL(audio
, SNDCTL_DSP_GETBLKSIZE
, abuf_size
);
1230 if (abuf_size
< 4096 || abuf_size
> 65536) {
1231 if (abuf_size
== -1)
1232 dprintf_mciwave(stddeb
,"Linux 'widOpen' // IOCTL can't 'SNDCTL_DSP_GETBLKSIZE' !\n");
1234 dprintf_mciwave(stddeb
,"Linux 'widOpen' // SNDCTL_DSP_GETBLKSIZE Invalid bufsize !\n");
1235 return MMSYSERR_NOTENABLED
;
1237 WInDev
[wDevID
].wFlags
= HIWORD(dwFlags
& CALLBACK_TYPEMASK
);
1238 switch(WInDev
[wDevID
].wFlags
) {
1240 dprintf_mciwave(stddeb
, "Linux 'widOpen' // CALLBACK_NULL !\n");
1243 dprintf_mciwave(stddeb
, "Linux 'widOpen' // CALLBACK_WINDOW !\n");
1246 dprintf_mciwave(stddeb
, "Linux 'widOpen' // CALLBACK_TASK !\n");
1249 dprintf_mciwave(stddeb
, "Linux 'widOpen' // CALLBACK_FUNCTION !\n");
1252 WInDev
[wDevID
].lpQueueHdr
= NULL
;
1253 WInDev
[wDevID
].unixdev
= audio
;
1254 WInDev
[wDevID
].bufsize
= abuf_size
;
1255 WInDev
[wDevID
].dwTotalRecorded
= 0;
1256 memcpy(&WInDev
[wDevID
].waveDesc
, lpDesc
, sizeof(WAVEOPENDESC
));
1257 lpFormat
= lpDesc
->lpFormat
;
1258 if (lpFormat
->wFormatTag
!= WAVE_FORMAT_PCM
) {
1259 dprintf_mciwave(stddeb
,"Linux 'widOpen' // Bad format %04X !\n",
1260 lpFormat
->wFormatTag
);
1261 return WAVERR_BADFORMAT
;
1263 memcpy(&WInDev
[wDevID
].Format
, lpFormat
, sizeof(PCMWAVEFORMAT
));
1264 WInDev
[wDevID
].Format
.wBitsPerSample
= 8; /* <-------------- */
1265 if (WInDev
[wDevID
].Format
.wf
.nChannels
== 0) return WAVERR_BADFORMAT
;
1266 if (WInDev
[wDevID
].Format
.wf
.nSamplesPerSec
== 0) return WAVERR_BADFORMAT
;
1267 if (WInDev
[wDevID
].Format
.wBitsPerSample
== 0) {
1268 WInDev
[wDevID
].Format
.wBitsPerSample
= 8 *
1269 (WInDev
[wDevID
].Format
.wf
.nAvgBytesPerSec
/
1270 WInDev
[wDevID
].Format
.wf
.nSamplesPerSec
) /
1271 WInDev
[wDevID
].Format
.wf
.nChannels
;
1273 samplesize
= WInDev
[wDevID
].Format
.wBitsPerSample
;
1274 smplrate
= WInDev
[wDevID
].Format
.wf
.nSamplesPerSec
;
1275 dsp_stereo
= (WInDev
[wDevID
].Format
.wf
.nChannels
> 1) ? TRUE
: FALSE
;
1276 IOCTL(audio
, SNDCTL_DSP_SPEED
, smplrate
);
1277 IOCTL(audio
, SNDCTL_DSP_SAMPLESIZE
, samplesize
);
1278 IOCTL(audio
, SNDCTL_DSP_STEREO
, dsp_stereo
);
1279 dprintf_mciwave(stddeb
,"Linux 'widOpen' // wBitsPerSample=%u !\n",
1280 WInDev
[wDevID
].Format
.wBitsPerSample
);
1281 dprintf_mciwave(stddeb
,"Linux 'widOpen' // nSamplesPerSec=%lu !\n",
1282 WInDev
[wDevID
].Format
.wf
.nSamplesPerSec
);
1283 dprintf_mciwave(stddeb
,"Linux 'widOpen' // nChannels=%u !\n",
1284 WInDev
[wDevID
].Format
.wf
.nChannels
);
1285 dprintf_mciwave(stddeb
,"Linux 'widOpen' // nAvgBytesPerSec=%lu\n",
1286 WInDev
[wDevID
].Format
.wf
.nAvgBytesPerSec
);
1287 if (WAVE_NotifyClient(wDevID
, WIM_OPEN
, 0L, 0L) != MMSYSERR_NOERROR
) {
1288 dprintf_mciwave(stddeb
,"Linux 'widOpen' // can't notify client !\n");
1289 return MMSYSERR_INVALPARAM
;
1291 return MMSYSERR_NOERROR
;
1294 /**************************************************************************
1295 * widClose [internal]
1297 static DWORD
widClose(WORD wDevID
)
1299 dprintf_mciwave(stddeb
,"widClose(%u);\n", wDevID
);
1300 if (WInDev
[wDevID
].unixdev
== 0) {
1301 dprintf_mciwave(stddeb
,"Linux 'widClose' // can't close !\n");
1302 return MMSYSERR_NOTENABLED
;
1304 close(WInDev
[wDevID
].unixdev
);
1305 WInDev
[wDevID
].unixdev
= 0;
1306 WInDev
[wDevID
].bufsize
= 0;
1307 if (WAVE_NotifyClient(wDevID
, WIM_CLOSE
, 0L, 0L) != MMSYSERR_NOERROR
) {
1308 dprintf_mciwave(stddeb
,"Linux 'widClose' // can't notify client !\n");
1309 return MMSYSERR_INVALPARAM
;
1311 return MMSYSERR_NOERROR
;
1314 /**************************************************************************
1315 * widAddBuffer [internal]
1317 static DWORD
widAddBuffer(WORD wDevID
, LPWAVEHDR lpWaveHdr
, DWORD dwSize
)
1321 dprintf_mciwave(stddeb
,
1322 "widAddBuffer(%u, %p, %08lX);\n", wDevID
, lpWaveHdr
, dwSize
);
1323 if (WInDev
[wDevID
].unixdev
== 0) {
1324 dprintf_mciwave(stddeb
,"Linux 'widAddBuffer' // can't do it !\n");
1325 return MMSYSERR_NOTENABLED
;
1327 if (!(lpWaveHdr
->dwFlags
& WHDR_PREPARED
)) {
1328 dprintf_mciwave(stddeb
, "Linux 'widAddBuffer' // never been prepared !\n");
1329 return WAVERR_UNPREPARED
;
1331 if (lpWaveHdr
->dwFlags
& WHDR_INQUEUE
) {
1332 dprintf_mciwave(stddeb
, "Linux 'widAddBuffer' // header already in use !\n");
1333 return WAVERR_STILLPLAYING
;
1335 lpWaveHdr
->dwFlags
|= WHDR_PREPARED
;
1336 lpWaveHdr
->dwFlags
|= WHDR_INQUEUE
;
1337 lpWaveHdr
->dwFlags
&= ~WHDR_DONE
;
1338 lpWaveHdr
->dwBytesRecorded
= 0;
1339 if (WInDev
[wDevID
].lpQueueHdr
== NULL
) {
1340 /* begin the queue with a first header ... */
1341 WInDev
[wDevID
].lpQueueHdr
= lpWaveHdr
;
1342 WInDev
[wDevID
].dwTotalRecorded
= 0;
1345 /* added to the queue, except if it's the one just prepared ... */
1346 lpWIHdr
= WInDev
[wDevID
].lpQueueHdr
;
1347 while (lpWIHdr
->lpNext
!= NULL
) {
1348 lpWIHdr
= lpWIHdr
->lpNext
;
1351 lpWIHdr
->lpNext
= lpWaveHdr
;
1354 dprintf_mciwave(stddeb
,
1355 "widAddBuffer // buffer added ! (now %u in queue)\n", count
);
1356 return MMSYSERR_NOERROR
;
1359 /**************************************************************************
1360 * widPrepare [internal]
1362 static DWORD
widPrepare(WORD wDevID
, LPWAVEHDR lpWaveHdr
, DWORD dwSize
)
1364 dprintf_mciwave(stddeb
,
1365 "widPrepare(%u, %p, %08lX);\n", wDevID
, lpWaveHdr
, dwSize
);
1366 if (WInDev
[wDevID
].unixdev
== 0) {
1367 dprintf_mciwave(stddeb
,"Linux 'widPrepare' // can't prepare !\n");
1368 return MMSYSERR_NOTENABLED
;
1370 if (WInDev
[wDevID
].lpQueueHdr
!= NULL
) {
1371 dprintf_mciwave(stddeb
,"Linux 'widPrepare' // already prepare !\n");
1372 return WAVERR_BADFORMAT
;
1374 if (lpWaveHdr
->dwFlags
& WHDR_INQUEUE
) return WAVERR_STILLPLAYING
;
1375 lpWaveHdr
->dwFlags
|= WHDR_PREPARED
;
1376 lpWaveHdr
->dwFlags
&= ~WHDR_INQUEUE
;
1377 lpWaveHdr
->dwFlags
&= ~WHDR_DONE
;
1378 lpWaveHdr
->dwBytesRecorded
= 0;
1379 dprintf_mciwave(stddeb
,"Linux 'widPrepare' // header prepared !\n");
1380 return MMSYSERR_NOERROR
;
1383 /**************************************************************************
1384 * widUnprepare [internal]
1386 static DWORD
widUnprepare(WORD wDevID
, LPWAVEHDR lpWaveHdr
, DWORD dwSize
)
1388 dprintf_mciwave(stddeb
,
1389 "widUnprepare(%u, %p, %08lX);\n", wDevID
, lpWaveHdr
, dwSize
);
1390 if (WInDev
[wDevID
].unixdev
== 0) {
1391 dprintf_mciwave(stddeb
,"Linux 'widUnprepare' // can't unprepare !\n");
1392 return MMSYSERR_NOTENABLED
;
1394 lpWaveHdr
->dwFlags
&= ~WHDR_PREPARED
;
1395 lpWaveHdr
->dwFlags
&= ~WHDR_INQUEUE
;
1396 lpWaveHdr
->dwFlags
|= WHDR_DONE
;
1397 WInDev
[wDevID
].lpQueueHdr
= NULL
;
1398 dprintf_mciwave(stddeb
,
1399 "Linux 'widUnprepare' // all headers unprepared !\n");
1400 return MMSYSERR_NOERROR
;
1403 /**************************************************************************
1404 * widStart [internal]
1406 static DWORD
widStart(WORD wDevID
)
1410 dprintf_mciwave(stddeb
,"widStart(%u);\n", wDevID
);
1411 if (WInDev
[wDevID
].unixdev
== 0) {
1412 dprintf_mciwave(stddeb
, "Linux 'widStart' // can't start recording !\n");
1413 return MMSYSERR_NOTENABLED
;
1415 if (WInDev
[wDevID
].lpQueueHdr
== NULL
||
1416 WInDev
[wDevID
].lpQueueHdr
->lpData
== NULL
) {
1417 dprintf_mciwave(stddeb
,"Linux 'widStart' // never been prepared !\n");
1418 return WAVERR_UNPREPARED
;
1420 lpWIHdr
= WInDev
[wDevID
].lpQueueHdr
;
1421 while(lpWIHdr
!= NULL
) {
1422 lpWIHdr
->dwBufferLength
&= 0xFFFF;
1423 dprintf_mciwave(stddeb
,
1424 "widStart // recording buf#%u=%p size=%lu \n",
1425 count
, lpWIHdr
->lpData
, lpWIHdr
->dwBufferLength
);
1427 read (WInDev
[wDevID
].unixdev
,
1428 PTR_SEG_TO_LIN(lpWIHdr
->lpData
),
1429 lpWIHdr
->dwBufferLength
);
1430 lpWIHdr
->dwBytesRecorded
= lpWIHdr
->dwBufferLength
;
1431 WInDev
[wDevID
].dwTotalRecorded
+= lpWIHdr
->dwBytesRecorded
;
1432 lpWIHdr
->dwFlags
&= ~WHDR_INQUEUE
;
1433 lpWIHdr
->dwFlags
|= WHDR_DONE
;
1434 if (WAVE_NotifyClient(wDevID
, WIM_DATA
, (DWORD
)lpWIHdr
, 0L) !=
1436 dprintf_mciwave(stddeb
, "Linux 'widStart' // can't notify client !\n");
1437 return MMSYSERR_INVALPARAM
;
1439 lpWIHdr
= lpWIHdr
->lpNext
;
1442 dprintf_mciwave(stddeb
,"widStart // end of recording !\n");
1444 return MMSYSERR_NOERROR
;
1447 /**************************************************************************
1448 * widStop [internal]
1450 static DWORD
widStop(WORD wDevID
)
1452 dprintf_mciwave(stddeb
,"widStop(%u);\n", wDevID
);
1453 if (WInDev
[wDevID
].unixdev
== 0) {
1454 dprintf_mciwave(stddeb
,"Linux 'widStop' // can't stop !\n");
1455 return MMSYSERR_NOTENABLED
;
1457 return MMSYSERR_NOERROR
;
1460 /**************************************************************************
1461 * widReset [internal]
1463 static DWORD
widReset(WORD wDevID
)
1465 dprintf_mciwave(stddeb
,"widReset(%u);\n", wDevID
);
1466 if (WInDev
[wDevID
].unixdev
== 0) {
1467 dprintf_mciwave(stddeb
,"Linux 'widReset' // can't reset !\n");
1468 return MMSYSERR_NOTENABLED
;
1470 return MMSYSERR_NOERROR
;
1473 /**************************************************************************
1474 * widGetPosition [internal]
1476 static DWORD
widGetPosition(WORD wDevID
, LPMMTIME lpTime
, DWORD uSize
)
1480 dprintf_mciwave(stddeb
,
1481 "widGetPosition(%u, %p, %lu);\n", wDevID
, lpTime
, uSize
);
1482 if (WInDev
[wDevID
].unixdev
== 0) {
1483 dprintf_mciwave(stddeb
,"Linux 'widGetPosition' // can't get pos !\n");
1484 return MMSYSERR_NOTENABLED
;
1486 if (lpTime
== NULL
) return MMSYSERR_INVALPARAM
;
1487 dprintf_mciwave(stddeb
,"widGetPosition // wType=%04X !\n",
1489 dprintf_mciwave(stddeb
,"widGetPosition // wBitsPerSample=%u\n",
1490 WInDev
[wDevID
].Format
.wBitsPerSample
);
1491 dprintf_mciwave(stddeb
,"widGetPosition // nSamplesPerSec=%lu\n",
1492 WInDev
[wDevID
].Format
.wf
.nSamplesPerSec
);
1493 dprintf_mciwave(stddeb
,"widGetPosition // nChannels=%u\n",
1494 WInDev
[wDevID
].Format
.wf
.nChannels
);
1495 dprintf_mciwave(stddeb
,"widGetPosition // nAvgBytesPerSec=%lu\n",
1496 WInDev
[wDevID
].Format
.wf
.nAvgBytesPerSec
);
1498 switch(lpTime
->wType
) {
1500 lpTime
->u
.cb
= WInDev
[wDevID
].dwTotalRecorded
;
1501 dprintf_mciwave(stddeb
,
1502 "widGetPosition // TIME_BYTES=%lu\n", lpTime
->u
.cb
);
1505 lpTime
->u
.sample
= WInDev
[wDevID
].dwTotalRecorded
* 8 /
1506 WInDev
[wDevID
].Format
.wBitsPerSample
;
1507 dprintf_mciwave(stddeb
,
1508 "widGetPosition // TIME_SAMPLES=%lu\n",
1512 time
= WInDev
[wDevID
].dwTotalRecorded
/
1513 (WInDev
[wDevID
].Format
.wf
.nAvgBytesPerSec
/ 1000);
1514 lpTime
->u
.smpte
.hour
= time
/ 108000;
1515 time
-= lpTime
->u
.smpte
.hour
* 108000;
1516 lpTime
->u
.smpte
.min
= time
/ 1800;
1517 time
-= lpTime
->u
.smpte
.min
* 1800;
1518 lpTime
->u
.smpte
.sec
= time
/ 30;
1519 time
-= lpTime
->u
.smpte
.sec
* 30;
1520 lpTime
->u
.smpte
.frame
= time
;
1521 lpTime
->u
.smpte
.fps
= 30;
1522 dprintf_mciwave(stddeb
,"widGetPosition // TIME_SMPTE=%02u:%02u:%02u:%02u\n",
1523 lpTime
->u
.smpte
.hour
, lpTime
->u
.smpte
.min
,
1524 lpTime
->u
.smpte
.sec
, lpTime
->u
.smpte
.frame
);
1527 dprintf_mciwave(stddeb
,"widGetPosition() format not supported ! use TIME_MS !\n");
1528 lpTime
->wType
= TIME_MS
;
1530 lpTime
->u
.ms
= WInDev
[wDevID
].dwTotalRecorded
/
1531 (WInDev
[wDevID
].Format
.wf
.nAvgBytesPerSec
/ 1000);
1532 dprintf_mciwave(stddeb
,
1533 "widGetPosition // TIME_MS=%lu\n", lpTime
->u
.ms
);
1536 return MMSYSERR_NOERROR
;
1541 /**************************************************************************
1542 * widMessage [sample driver]
1544 DWORD
widMessage(WORD wDevID
, WORD wMsg
, DWORD dwUser
,
1545 DWORD dwParam1
, DWORD dwParam2
)
1547 dprintf_mciwave(stddeb
,"widMessage(%u, %04X, %08lX, %08lX, %08lX);\n",
1548 wDevID
, wMsg
, dwUser
, dwParam1
, dwParam2
);
1552 return widOpen(wDevID
, (LPWAVEOPENDESC
)PTR_SEG_TO_LIN(dwParam1
), dwParam2
);
1554 return widClose(wDevID
);
1555 case WIDM_ADDBUFFER
:
1556 return widAddBuffer(wDevID
, (LPWAVEHDR
)PTR_SEG_TO_LIN(dwParam1
), dwParam2
);
1558 return widPrepare(wDevID
, (LPWAVEHDR
)PTR_SEG_TO_LIN(dwParam1
), dwParam2
);
1559 case WIDM_UNPREPARE
:
1560 return widUnprepare(wDevID
, (LPWAVEHDR
)PTR_SEG_TO_LIN(dwParam1
), dwParam2
);
1561 case WIDM_GETDEVCAPS
:
1562 return widGetDevCaps(wDevID
, (LPWAVEINCAPS
)PTR_SEG_TO_LIN(dwParam1
), dwParam2
);
1563 case WIDM_GETNUMDEVS
:
1566 return widGetPosition(wDevID
, (LPMMTIME
)PTR_SEG_TO_LIN(dwParam1
), dwParam2
);
1568 return widReset(wDevID
);
1570 return widStart(wDevID
);
1572 return widStop(wDevID
);
1574 dprintf_mciwave(stddeb
,"widMessage // unknown message !\n");
1576 return MMSYSERR_NOTSUPPORTED
;
1578 return MMSYSERR_NOTENABLED
;
1583 /**************************************************************************
1584 * AUDIO_DriverProc [sample driver]
1586 LONG
WAVE_DriverProc(DWORD dwDevID
, HDRVR hDriv
, WORD wMsg
,
1587 DWORD dwParam1
, DWORD dwParam2
)
1590 dprintf_mciwave(stddeb
,"WAVE_DriverProc(%08lX, %04X, %04X, %08lX, %08lX)\n",
1591 dwDevID
, hDriv
, wMsg
, dwParam1
, dwParam2
);
1605 case DRV_QUERYCONFIGURE
:
1608 MessageBox((HWND
)NULL
, "Sample MultiMedia Linux Driver !",
1609 "MMLinux Driver", MB_OK
);
1612 return DRVCNF_RESTART
;
1614 return DRVCNF_RESTART
;
1615 case MCI_OPEN_DRIVER
:
1617 return WAVE_mciOpen(dwDevID
, dwParam1
, (LPMCI_WAVE_OPEN_PARMS
)PTR_SEG_TO_LIN(dwParam2
));
1618 case MCI_CLOSE_DRIVER
:
1620 return WAVE_mciClose(dwDevID
, dwParam1
, (LPMCI_GENERIC_PARMS
)PTR_SEG_TO_LIN(dwParam2
));
1622 return WAVE_mciPlay(dwDevID
, dwParam1
, (LPMCI_PLAY_PARMS
)PTR_SEG_TO_LIN(dwParam2
));
1624 return WAVE_mciRecord(dwDevID
, dwParam1
, (LPMCI_RECORD_PARMS
)PTR_SEG_TO_LIN(dwParam2
));
1626 return WAVE_mciStop(dwDevID
, dwParam1
, (LPMCI_GENERIC_PARMS
)PTR_SEG_TO_LIN(dwParam2
));
1628 return WAVE_mciSet(dwDevID
, dwParam1
, (LPMCI_SET_PARMS
)PTR_SEG_TO_LIN(dwParam2
));
1630 return WAVE_mciPause(dwDevID
, dwParam1
, (LPMCI_GENERIC_PARMS
)PTR_SEG_TO_LIN(dwParam2
));
1632 return WAVE_mciResume(dwDevID
, dwParam1
, (LPMCI_GENERIC_PARMS
)PTR_SEG_TO_LIN(dwParam2
));
1634 return WAVE_mciStatus(dwDevID
, dwParam1
, (LPMCI_STATUS_PARMS
)PTR_SEG_TO_LIN(dwParam2
));
1635 case MCI_GETDEVCAPS
:
1636 return WAVE_mciGetDevCaps(dwDevID
, dwParam1
, (LPMCI_GETDEVCAPS_PARMS
)PTR_SEG_TO_LIN(dwParam2
));
1638 return WAVE_mciInfo(dwDevID
, dwParam1
, (LPMCI_INFO_PARMS
)PTR_SEG_TO_LIN(dwParam2
));
1640 return DefDriverProc(dwDevID
, hDriv
, wMsg
, dwParam1
, dwParam2
);
1643 return MMSYSERR_NOTENABLED
;
1648 #endif /* #ifdef BUILTIN_MMSYSTEM */