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 lpParms
->wDeviceID
= wDevID
;
132 dprintf_mciwave(stddeb
,"WAVE_mciOpen // wDevID=%04X\n", wDevID
);
133 dprintf_mciwave(stddeb
,"WAVE_mciOpen // before OPEN_ELEMENT\n");
134 if (dwFlags
& MCI_OPEN_ELEMENT
) {
135 lpstrElementName
= (LPSTR
)PTR_SEG_TO_LIN(lpParms
->lpstrElementName
);
136 dprintf_mciwave(stddeb
,"WAVE_mciOpen // MCI_OPEN_ELEMENT '%s' !\n",
138 if (strlen(lpstrElementName
) > 0) {
139 strcpy(str
, lpstrElementName
);
141 MCIWavDev
[wDevID
].hFile
= mmioOpen(str
, NULL
,
142 MMIO_ALLOCBUF
| MMIO_READWRITE
| MMIO_EXCLUSIVE
);
143 if (MCIWavDev
[wDevID
].hFile
== 0) {
144 dprintf_mciwave(stddeb
,"WAVE_mciOpen // can't find file='%s' !\n", str
);
145 return MCIERR_FILE_NOT_FOUND
;
149 MCIWavDev
[wDevID
].hFile
= 0;
151 dprintf_mciwave(stddeb
,"WAVE_mciOpen // hFile=%u\n", MCIWavDev
[wDevID
].hFile
);
152 memcpy(&MCIWavDev
[wDevID
].openParms
, lpParms
, sizeof(MCI_WAVE_OPEN_PARMS
));
153 MCIWavDev
[wDevID
].wNotifyDeviceID
= lpParms
->wDeviceID
;
154 lpWaveFormat
= &MCIWavDev
[wDevID
].WaveFormat
;
155 hDesc
= USER_HEAP_ALLOC(sizeof(WAVEOPENDESC
));
156 lpDesc
= (LPWAVEOPENDESC
) USER_HEAP_LIN_ADDR(hDesc
);
159 lpWaveFormat->wf.wFormatTag = WAVE_FORMAT_PCM;
160 lpWaveFormat->wBitsPerSample = 8;
161 lpWaveFormat->wf.nChannels = 1;
162 lpWaveFormat->wf.nSamplesPerSec = 11025;
163 lpWaveFormat->wf.nAvgBytesPerSec = 11025;
164 lpWaveFormat->wf.nBlockAlign = 1;
166 if (MCIWavDev
[wDevID
].hFile
!= 0) {
169 if (mmioDescend(MCIWavDev
[wDevID
].hFile
, &ckMainRIFF
, NULL
, 0) != 0) {
170 return MCIERR_INTERNAL
;
172 dprintf_mciwave(stddeb
,
173 "WAVE_mciOpen // ParentChunk ckid=%.4s fccType=%.4s cksize=%08lX \n",
174 (LPSTR
)&ckMainRIFF
.ckid
, (LPSTR
)&ckMainRIFF
.fccType
,
176 if ((ckMainRIFF
.ckid
!= FOURCC_RIFF
) ||
177 (ckMainRIFF
.fccType
!= mmioFOURCC('W', 'A', 'V', 'E'))) {
178 return MCIERR_INTERNAL
;
180 mmckInfo
.ckid
= mmioFOURCC('f', 'm', 't', ' ');
181 if (mmioDescend(MCIWavDev
[wDevID
].hFile
, &mmckInfo
, &ckMainRIFF
, MMIO_FINDCHUNK
) != 0) {
182 return MCIERR_INTERNAL
;
184 dprintf_mciwave(stddeb
,
185 "WAVE_mciOpen // Chunk Found ckid=%.4s fccType=%.4s cksize=%08lX \n",
186 (LPSTR
)&mmckInfo
.ckid
, (LPSTR
)&mmckInfo
.fccType
,
188 if (mmioRead(MCIWavDev
[wDevID
].hFile
, (HPSTR
) lpWaveFormat
,
189 (long) sizeof(PCMWAVEFORMAT
)) != (long) sizeof(PCMWAVEFORMAT
)) {
190 return MCIERR_INTERNAL
;
192 mmckInfo
.ckid
= mmioFOURCC('d', 'a', 't', 'a');
193 if (mmioDescend(MCIWavDev
[wDevID
].hFile
, &mmckInfo
, &ckMainRIFF
, MMIO_FINDCHUNK
) != 0) {
194 return MCIERR_INTERNAL
;
196 dprintf_mciwave(stddeb
,
197 "WAVE_mciOpen // Chunk Found ckid=%.4s fccType=%.4s cksize=%08lX \n",
198 (LPSTR
)&mmckInfo
.ckid
, (LPSTR
)&mmckInfo
.fccType
,
200 dprintf_mciwave(stddeb
,
201 "WAVE_mciOpen // nChannels=%d nSamplesPerSec=%ld\n",
202 lpWaveFormat
->wf
.nChannels
, lpWaveFormat
->wf
.nSamplesPerSec
);
203 lpWaveFormat
->wBitsPerSample
= 0;
205 lpWaveFormat
->wf
.nAvgBytesPerSec
=
206 lpWaveFormat
->wf
.nSamplesPerSec
* lpWaveFormat
->wf
.nBlockAlign
;
207 hFormat
= USER_HEAP_ALLOC(sizeof(PCMWAVEFORMAT
));
208 lpDesc
->lpFormat
= (LPWAVEFORMAT
) USER_HEAP_LIN_ADDR(hFormat
);
209 memcpy(lpDesc
->lpFormat
, lpWaveFormat
, sizeof(PCMWAVEFORMAT
));
210 lpDesc
= (LPWAVEOPENDESC
) USER_HEAP_SEG_ADDR(hDesc
);
211 dwRet
= wodMessage(0, WODM_OPEN
, 0, (DWORD
)lpDesc
, CALLBACK_NULL
);
212 dwRet
= widMessage(0, WIDM_OPEN
, 0, (DWORD
)lpDesc
, CALLBACK_NULL
);
213 USER_HEAP_FREE(hFormat
);
214 USER_HEAP_FREE(hDesc
);
218 /**************************************************************************
219 * WAVE_mciClose [internal]
221 static DWORD
WAVE_mciClose(UINT wDevID
, DWORD dwParam
, LPMCI_GENERIC_PARMS lpParms
)
224 dprintf_mciwave(stddeb
,
225 "WAVE_mciClose(%u, %08lX, %p);\n", wDevID
, dwParam
, lpParms
);
226 MCIWavDev
[wDevID
].nUseCount
--;
227 if (MCIWavDev
[wDevID
].nUseCount
== 0) {
228 if (MCIWavDev
[wDevID
].hFile
!= 0) {
229 mmioClose(MCIWavDev
[wDevID
].hFile
, 0);
230 MCIWavDev
[wDevID
].hFile
= 0;
232 dwRet
= wodMessage(0, WODM_CLOSE
, 0, 0L, 0L);
233 if (dwRet
!= MMSYSERR_NOERROR
) return MCIERR_INTERNAL
;
234 dwRet
= widMessage(0, WIDM_CLOSE
, 0, 0L, 0L);
235 if (dwRet
!= MMSYSERR_NOERROR
) return MCIERR_INTERNAL
;
241 /**************************************************************************
242 * WAVE_mciPlay [internal]
244 static DWORD
WAVE_mciPlay(UINT wDevID
, DWORD dwFlags
, LPMCI_PLAY_PARMS lpParms
)
251 LPWAVEHDR lp16WaveHdr
;
253 dprintf_mciwave(stddeb
,
254 "WAVE_mciPlay(%u, %08lX, %p);\n", wDevID
, dwFlags
, lpParms
);
255 if (MCIWavDev
[wDevID
].hFile
== 0) {
256 dprintf_mciwave(stddeb
,"WAVE_mciPlay // can't find file='%s' !\n",
257 MCIWavDev
[wDevID
].openParms
.lpstrElementName
);
258 return MCIERR_FILE_NOT_FOUND
;
260 start
= 1; end
= 99999;
261 if (dwFlags
& MCI_FROM
) {
262 start
= lpParms
->dwFrom
;
263 dprintf_mciwave(stddeb
,
264 "WAVE_mciPlay // MCI_FROM=%d \n", start
);
266 if (dwFlags
& MCI_TO
) {
268 dprintf_mciwave(stddeb
,"WAVE_mciPlay // MCI_TO=%d \n", end
);
271 if (dwFlags
& MCI_NOTIFY
) {
272 dprintf_mciwave(stddeb
,
273 "WAVE_mciPlay // MCI_NOTIFY %08lX !\n", lpParms
->dwCallback
);
276 dprintf_mciwave(stddeb
,
277 "WAVE_mciPlay // Can't 'fork' process !\n");
282 dprintf_mciwave(stddeb
,"WAVE_mciPlay // process started ! return to caller...\n");
288 lpWaveHdr
= &MCIWavDev
[wDevID
].WaveHdr
;
289 hData
= GlobalAlloc16(GMEM_MOVEABLE
, bufsize
);
290 lpWaveHdr
->lpData
= (LPSTR
) WIN16_GlobalLock16(hData
);
291 lpWaveHdr
->dwUser
= 0L;
292 lpWaveHdr
->dwFlags
= 0L;
293 lpWaveHdr
->dwLoops
= 0L;
294 hWaveHdr
= USER_HEAP_ALLOC(sizeof(WAVEHDR
));
295 lp16WaveHdr
= (LPWAVEHDR
) USER_HEAP_SEG_ADDR(hWaveHdr
);
296 memcpy(PTR_SEG_TO_LIN(lp16WaveHdr
), lpWaveHdr
, sizeof(WAVEHDR
));
297 lpWaveHdr
= PTR_SEG_TO_LIN(lp16WaveHdr
);
298 dwRet
= wodMessage(0, WODM_PREPARE
, 0, (DWORD
)lp16WaveHdr
, sizeof(WAVEHDR
));
300 count
= mmioRead(MCIWavDev
[wDevID
].hFile
,
301 PTR_SEG_TO_LIN(lpWaveHdr
->lpData
), bufsize
);
302 dprintf_mciwave(stddeb
,"WAVE_mciPlay // mmioRead bufsize=%ld count=%ld\n", bufsize
, count
);
303 if (count
< 1) break;
304 lpWaveHdr
->dwBufferLength
= count
;
305 /* lpWaveHdr->dwBytesRecorded = count; */
306 dprintf_mciwave(stddeb
,"WAVE_mciPlay // before WODM_WRITE lpWaveHdr=%p dwBufferLength=%lu dwBytesRecorded=%lu\n",
307 lpWaveHdr
, lpWaveHdr
->dwBufferLength
, lpWaveHdr
->dwBytesRecorded
);
308 dwRet
= wodMessage(0, WODM_WRITE
, 0, (DWORD
)lp16WaveHdr
, sizeof(WAVEHDR
));
310 dwRet
= wodMessage(0, WODM_UNPREPARE
, 0, (DWORD
)lp16WaveHdr
, sizeof(WAVEHDR
));
311 if (lpWaveHdr
->lpData
!= NULL
) {
312 GlobalUnlock16(hData
);
314 lpWaveHdr
->lpData
= NULL
;
316 USER_HEAP_FREE(hWaveHdr
);
317 if (dwFlags
& MCI_NOTIFY
) {
318 dprintf_mciwave(stddeb
,"WAVE_mciPlay // MCI_NOTIFY_SUCCESSFUL %08lX !\n", lpParms
->dwCallback
);
319 mciDriverNotify((HWND
)LOWORD(lpParms
->dwCallback
),
320 MCIWavDev
[wDevID
].wNotifyDeviceID
, MCI_NOTIFY_SUCCESSFUL
);
326 /**************************************************************************
327 * WAVE_mciRecord [internal]
329 static DWORD
WAVE_mciRecord(UINT wDevID
, DWORD dwFlags
, LPMCI_RECORD_PARMS lpParms
)
336 LPWAVEHDR lp16WaveHdr
;
339 dprintf_mciwave(stddeb
,
340 "WAVE_mciRecord(%u, %08lX, %p);\n", wDevID
, dwFlags
, lpParms
);
341 if (MCIWavDev
[wDevID
].hFile
== 0) {
342 dprintf_mciwave(stddeb
,"WAVE_mciRecord // can't find file='%s' !\n",
343 MCIWavDev
[wDevID
].openParms
.lpstrElementName
);
344 return MCIERR_FILE_NOT_FOUND
;
346 start
= 1; end
= 99999;
347 if (dwFlags
& MCI_FROM
) {
348 start
= lpParms
->dwFrom
;
349 dprintf_mciwave(stddeb
,
350 "WAVE_mciRecord // MCI_FROM=%d \n", start
);
352 if (dwFlags
& MCI_TO
) {
354 dprintf_mciwave(stddeb
,"WAVE_mciRecord // MCI_TO=%d \n", end
);
357 lpWaveHdr
= &MCIWavDev
[wDevID
].WaveHdr
;
358 hData
= GlobalAlloc16(GMEM_MOVEABLE
, bufsize
);
359 lpWaveHdr
->lpData
= (LPSTR
) WIN16_GlobalLock16(hData
);
360 lpWaveHdr
->dwBufferLength
= bufsize
;
361 lpWaveHdr
->dwUser
= 0L;
362 lpWaveHdr
->dwFlags
= 0L;
363 lpWaveHdr
->dwLoops
= 0L;
364 hWaveHdr
= USER_HEAP_ALLOC(sizeof(WAVEHDR
));
365 lp16WaveHdr
= (LPWAVEHDR
) USER_HEAP_SEG_ADDR(hWaveHdr
);
366 memcpy(PTR_SEG_TO_LIN(lp16WaveHdr
), lpWaveHdr
, sizeof(WAVEHDR
));
367 lpWaveHdr
= PTR_SEG_TO_LIN(lp16WaveHdr
);
368 dwRet
= widMessage(0, WIDM_PREPARE
, 0, (DWORD
)lp16WaveHdr
, sizeof(WAVEHDR
));
369 dprintf_mciwave(stddeb
,"WAVE_mciRecord // after WIDM_PREPARE \n");
371 lpWaveHdr
->dwBytesRecorded
= 0;
372 dwRet
= widMessage(0, WIDM_START
, 0, 0L, 0L);
373 dprintf_mciwave(stddeb
,
374 "WAVE_mciRecord // after WIDM_START lpWaveHdr=%p dwBytesRecorded=%lu\n",
375 lpWaveHdr
, lpWaveHdr
->dwBytesRecorded
);
376 if (lpWaveHdr
->dwBytesRecorded
== 0) break;
378 dprintf_mciwave(stddeb
,"WAVE_mciRecord // before WIDM_UNPREPARE \n");
379 dwRet
= widMessage(0, WIDM_UNPREPARE
, 0, (DWORD
)lp16WaveHdr
, sizeof(WAVEHDR
));
380 dprintf_mciwave(stddeb
,"WAVE_mciRecord // after WIDM_UNPREPARE \n");
381 if (lpWaveHdr
->lpData
!= NULL
) {
382 GlobalUnlock16(hData
);
384 lpWaveHdr
->lpData
= NULL
;
386 USER_HEAP_FREE(hWaveHdr
);
387 if (dwFlags
& MCI_NOTIFY
) {
388 dprintf_mciwave(stddeb
,"WAVE_mciRecord // MCI_NOTIFY_SUCCESSFUL %08lX !\n", lpParms
->dwCallback
);
389 mciDriverNotify((HWND
)LOWORD(lpParms
->dwCallback
),
390 MCIWavDev
[wDevID
].wNotifyDeviceID
, MCI_NOTIFY_SUCCESSFUL
);
396 /**************************************************************************
397 * WAVE_mciStop [internal]
399 static DWORD
WAVE_mciStop(UINT wDevID
, DWORD dwFlags
, LPMCI_GENERIC_PARMS lpParms
)
401 dprintf_mciwave(stddeb
,
402 "WAVE_mciStop(%u, %08lX, %p);\n", wDevID
, dwFlags
, lpParms
);
403 if (lpParms
== NULL
) return MCIERR_INTERNAL
;
408 /**************************************************************************
409 * WAVE_mciPause [internal]
411 static DWORD
WAVE_mciPause(UINT wDevID
, DWORD dwFlags
, LPMCI_GENERIC_PARMS lpParms
)
413 dprintf_mciwave(stddeb
,
414 "WAVE_mciPause(%u, %08lX, %p);\n", wDevID
, dwFlags
, lpParms
);
415 if (lpParms
== NULL
) return MCIERR_INTERNAL
;
420 /**************************************************************************
421 * WAVE_mciResume [internal]
423 static DWORD
WAVE_mciResume(UINT wDevID
, DWORD dwFlags
, LPMCI_GENERIC_PARMS lpParms
)
425 dprintf_mciwave(stddeb
,
426 "WAVE_mciResume(%u, %08lX, %p);\n", wDevID
, dwFlags
, lpParms
);
427 if (lpParms
== NULL
) return MCIERR_INTERNAL
;
432 /**************************************************************************
433 * WAVE_mciSet [internal]
435 static DWORD
WAVE_mciSet(UINT wDevID
, DWORD dwFlags
, LPMCI_SET_PARMS lpParms
)
437 dprintf_mciwave(stddeb
,
438 "WAVE_mciSet(%u, %08lX, %p);\n", wDevID
, dwFlags
, lpParms
);
439 if (lpParms
== NULL
) return MCIERR_INTERNAL
;
440 dprintf_mciwave(stddeb
,
441 "WAVE_mciSet // dwTimeFormat=%08lX\n", lpParms
->dwTimeFormat
);
442 dprintf_mciwave(stddeb
,
443 "WAVE_mciSet // dwAudio=%08lX\n", lpParms
->dwAudio
);
444 if (dwFlags
& MCI_SET_TIME_FORMAT
) {
445 switch (lpParms
->dwTimeFormat
) {
446 case MCI_FORMAT_MILLISECONDS
:
447 dprintf_mciwave(stddeb
, "WAVE_mciSet // MCI_FORMAT_MILLISECONDS !\n");
449 case MCI_FORMAT_BYTES
:
450 dprintf_mciwave(stddeb
, "WAVE_mciSet // MCI_FORMAT_BYTES !\n");
452 case MCI_FORMAT_SAMPLES
:
453 dprintf_mciwave(stddeb
, "WAVE_mciSet // MCI_FORMAT_SAMPLES !\n");
456 dprintf_mciwave(stddeb
, "WAVE_mciSet // bad time format !\n");
457 return MCIERR_BAD_TIME_FORMAT
;
460 if (dwFlags
& MCI_SET_VIDEO
) return MCIERR_UNSUPPORTED_FUNCTION
;
461 if (dwFlags
& MCI_SET_DOOR_OPEN
) return MCIERR_UNSUPPORTED_FUNCTION
;
462 if (dwFlags
& MCI_SET_DOOR_CLOSED
) return MCIERR_UNSUPPORTED_FUNCTION
;
463 if (dwFlags
& MCI_SET_AUDIO
)
464 dprintf_mciwave(stddeb
,"WAVE_mciSet // MCI_SET_AUDIO !\n");
465 if (dwFlags
&& MCI_SET_ON
) {
466 dprintf_mciwave(stddeb
,"WAVE_mciSet // MCI_SET_ON !\n");
467 if (dwFlags
&& MCI_SET_AUDIO_LEFT
)
468 dprintf_mciwave(stddeb
,"WAVE_mciSet // MCI_SET_AUDIO_LEFT !\n");
469 if (dwFlags
&& MCI_SET_AUDIO_RIGHT
)
470 dprintf_mciwave(stddeb
,"WAVE_mciSet // MCI_SET_AUDIO_RIGHT !\n");
472 if (dwFlags
& MCI_SET_OFF
)
473 dprintf_mciwave(stddeb
,"WAVE_mciSet // MCI_SET_OFF !\n");
474 if (dwFlags
& MCI_WAVE_INPUT
)
475 dprintf_mciwave(stddeb
,"WAVE_mciSet // MCI_WAVE_INPUT !\n");
476 if (dwFlags
& MCI_WAVE_OUTPUT
)
477 dprintf_mciwave(stddeb
,"WAVE_mciSet // MCI_WAVE_OUTPUT !\n");
478 if (dwFlags
& MCI_WAVE_SET_ANYINPUT
)
479 dprintf_mciwave(stddeb
,"WAVE_mciSet // MCI_WAVE_SET_ANYINPUT !\n");
480 if (dwFlags
& MCI_WAVE_SET_ANYOUTPUT
)
481 dprintf_mciwave(stddeb
,"WAVE_mciSet // MCI_WAVE_SET_ANYOUTPUT !\n");
482 if (dwFlags
& MCI_WAVE_SET_AVGBYTESPERSEC
)
483 dprintf_mciwave(stddeb
,
484 "WAVE_mciSet // MCI_WAVE_SET_AVGBYTESPERSEC !\n");
485 if (dwFlags
& MCI_WAVE_SET_BITSPERSAMPLE
)
486 dprintf_mciwave(stddeb
,
487 "WAVE_mciSet // MCI_WAVE_SET_BITSPERSAMPLE !\n");
488 if (dwFlags
& MCI_WAVE_SET_BLOCKALIGN
)
489 dprintf_mciwave(stddeb
,"WAVE_mciSet // MCI_WAVE_SET_BLOCKALIGN !\n");
490 if (dwFlags
& MCI_WAVE_SET_CHANNELS
)
491 dprintf_mciwave(stddeb
,"WAVE_mciSet // MCI_WAVE_SET_CHANNELS !\n");
492 if (dwFlags
& MCI_WAVE_SET_FORMATTAG
)
493 dprintf_mciwave(stddeb
,"WAVE_mciSet // MCI_WAVE_SET_FORMATTAG !\n");
494 if (dwFlags
& MCI_WAVE_SET_SAMPLESPERSEC
)
495 dprintf_mciwave(stddeb
,
496 "WAVE_mciSet // MCI_WAVE_SET_SAMPLESPERSEC !\n");
501 /**************************************************************************
502 * WAVE_mciStatus [internal]
504 static DWORD
WAVE_mciStatus(UINT wDevID
, DWORD dwFlags
, LPMCI_STATUS_PARMS lpParms
)
506 dprintf_mciwave(stddeb
,
507 "WAVE_mciStatus(%u, %08lX, %p);\n", wDevID
, dwFlags
, lpParms
);
508 if (lpParms
== NULL
) return MCIERR_INTERNAL
;
509 if (dwFlags
& MCI_STATUS_ITEM
) {
510 switch(lpParms
->dwItem
) {
511 case MCI_STATUS_CURRENT_TRACK
:
512 lpParms
->dwReturn
= 1;
514 case MCI_STATUS_LENGTH
:
515 lpParms
->dwReturn
= 5555;
516 if (dwFlags
& MCI_TRACK
) {
517 lpParms
->dwTrack
= 1;
518 lpParms
->dwReturn
= 2222;
521 case MCI_STATUS_MODE
:
522 lpParms
->dwReturn
= MCI_MODE_STOP
;
524 case MCI_STATUS_MEDIA_PRESENT
:
525 dprintf_mciwave(stddeb
,"WAVE_mciStatus // MCI_STATUS_MEDIA_PRESENT !\n");
526 lpParms
->dwReturn
= TRUE
;
528 case MCI_STATUS_NUMBER_OF_TRACKS
:
529 lpParms
->dwReturn
= 1;
531 case MCI_STATUS_POSITION
:
532 lpParms
->dwReturn
= 3333;
533 if (dwFlags
& MCI_STATUS_START
) {
536 if (dwFlags
& MCI_TRACK
) {
537 lpParms
->dwTrack
= 1;
538 lpParms
->dwReturn
= 777;
541 case MCI_STATUS_READY
:
542 dprintf_mciwave(stddeb
,"WAVE_mciStatus // MCI_STATUS_READY !\n");
543 lpParms
->dwReturn
= TRUE
;
545 case MCI_STATUS_TIME_FORMAT
:
546 dprintf_mciwave(stddeb
,"WAVE_mciStatus // MCI_STATUS_TIME_FORMAT !\n");
547 lpParms
->dwReturn
= MCI_FORMAT_MILLISECONDS
;
550 dprintf_mciwave(stddeb
,"WAVE_mciStatus // MCI_WAVE_INPUT !\n");
551 lpParms
->dwReturn
= 0;
553 case MCI_WAVE_OUTPUT
:
554 dprintf_mciwave(stddeb
,"WAVE_mciStatus // MCI_WAVE_OUTPUT !\n");
555 lpParms
->dwReturn
= 0;
557 case MCI_WAVE_STATUS_AVGBYTESPERSEC
:
558 dprintf_mciwave(stddeb
,"WAVE_mciStatus // MCI_WAVE_STATUS_AVGBYTESPERSEC !\n");
559 lpParms
->dwReturn
= 22050;
561 case MCI_WAVE_STATUS_BITSPERSAMPLE
:
562 dprintf_mciwave(stddeb
,"WAVE_mciStatus // MCI_WAVE_STATUS_BITSPERSAMPLE !\n");
563 lpParms
->dwReturn
= 8;
565 case MCI_WAVE_STATUS_BLOCKALIGN
:
566 dprintf_mciwave(stddeb
,"WAVE_mciStatus // MCI_WAVE_STATUS_BLOCKALIGN !\n");
567 lpParms
->dwReturn
= 1;
569 case MCI_WAVE_STATUS_CHANNELS
:
570 dprintf_mciwave(stddeb
,"WAVE_mciStatus // MCI_WAVE_STATUS_CHANNELS !\n");
571 lpParms
->dwReturn
= 1;
573 case MCI_WAVE_STATUS_FORMATTAG
:
574 dprintf_mciwave(stddeb
,"WAVE_mciStatus // MCI_WAVE_FORMATTAG !\n");
575 lpParms
->dwReturn
= WAVE_FORMAT_PCM
;
577 case MCI_WAVE_STATUS_LEVEL
:
578 dprintf_mciwave(stddeb
,"WAVE_mciStatus // MCI_WAVE_STATUS_LEVEL !\n");
579 lpParms
->dwReturn
= 0xAAAA5555;
581 case MCI_WAVE_STATUS_SAMPLESPERSEC
:
582 dprintf_mciwave(stddeb
,"WAVE_mciStatus // MCI_WAVE_STATUS_SAMPLESPERSEC !\n");
583 lpParms
->dwReturn
= 22050;
586 dprintf_mciwave(stddeb
,"WAVE_mciStatus // unknown command %08lX !\n", lpParms
->dwItem
);
587 return MCIERR_UNRECOGNIZED_COMMAND
;
590 if (dwFlags
& MCI_NOTIFY
) {
591 dprintf_mciwave(stddeb
,"WAVE_mciStatus // MCI_NOTIFY_SUCCESSFUL %08lX !\n", lpParms
->dwCallback
);
592 mciDriverNotify((HWND
)LOWORD(lpParms
->dwCallback
),
593 MCIWavDev
[wDevID
].wNotifyDeviceID
, MCI_NOTIFY_SUCCESSFUL
);
598 /**************************************************************************
599 * WAVE_mciGetDevCaps [internal]
601 static DWORD
WAVE_mciGetDevCaps(UINT wDevID
, DWORD dwFlags
,
602 LPMCI_GETDEVCAPS_PARMS lpParms
)
604 dprintf_mciwave(stddeb
,
605 "WAVE_mciGetDevCaps(%u, %08lX, %p);\n", wDevID
, dwFlags
, lpParms
);
606 if (lpParms
== NULL
) return MCIERR_INTERNAL
;
607 if (dwFlags
& MCI_GETDEVCAPS_ITEM
) {
608 switch(lpParms
->dwItem
) {
609 case MCI_GETDEVCAPS_CAN_RECORD
:
610 lpParms
->dwReturn
= TRUE
;
612 case MCI_GETDEVCAPS_HAS_AUDIO
:
613 lpParms
->dwReturn
= TRUE
;
615 case MCI_GETDEVCAPS_HAS_VIDEO
:
616 lpParms
->dwReturn
= FALSE
;
618 case MCI_GETDEVCAPS_DEVICE_TYPE
:
619 lpParms
->dwReturn
= MCI_DEVTYPE_WAVEFORM_AUDIO
;
621 case MCI_GETDEVCAPS_USES_FILES
:
622 lpParms
->dwReturn
= TRUE
;
624 case MCI_GETDEVCAPS_COMPOUND_DEVICE
:
625 lpParms
->dwReturn
= TRUE
;
627 case MCI_GETDEVCAPS_CAN_EJECT
:
628 lpParms
->dwReturn
= FALSE
;
630 case MCI_GETDEVCAPS_CAN_PLAY
:
631 lpParms
->dwReturn
= TRUE
;
633 case MCI_GETDEVCAPS_CAN_SAVE
:
634 lpParms
->dwReturn
= TRUE
;
636 case MCI_WAVE_GETDEVCAPS_INPUTS
:
637 lpParms
->dwReturn
= 1;
639 case MCI_WAVE_GETDEVCAPS_OUTPUTS
:
640 lpParms
->dwReturn
= 1;
643 return MCIERR_UNRECOGNIZED_COMMAND
;
649 /**************************************************************************
650 * WAVE_mciInfo [internal]
652 static DWORD
WAVE_mciInfo(UINT wDevID
, DWORD dwFlags
, LPMCI_INFO_PARMS lpParms
)
654 dprintf_mciwave(stddeb
,
655 "WAVE_mciInfo(%u, %08lX, %p);\n", wDevID
, dwFlags
, lpParms
);
656 if (lpParms
== NULL
) return MCIERR_INTERNAL
;
657 lpParms
->lpstrReturn
= NULL
;
659 case MCI_INFO_PRODUCT
:
660 lpParms
->lpstrReturn
= "Linux Sound System 0.5";
663 lpParms
->lpstrReturn
=
664 (LPSTR
)MCIWavDev
[wDevID
].openParms
.lpstrElementName
;
667 lpParms
->lpstrReturn
= "Linux Sound System 0.5";
669 case MCI_WAVE_OUTPUT
:
670 lpParms
->lpstrReturn
= "Linux Sound System 0.5";
673 return MCIERR_UNRECOGNIZED_COMMAND
;
675 if (lpParms
->lpstrReturn
!= NULL
)
676 lpParms
->dwRetSize
= strlen(lpParms
->lpstrReturn
);
678 lpParms
->dwRetSize
= 0;
683 /*-----------------------------------------------------------------------*/
686 /**************************************************************************
687 * wodGetDevCaps [internal]
689 static DWORD
wodGetDevCaps(WORD wDevID
, LPWAVEOUTCAPS lpCaps
, DWORD dwSize
)
696 dprintf_mciwave(stddeb
,
697 "wodGetDevCaps(%u, %p, %lu);\n", wDevID
, lpCaps
, dwSize
);
698 if (lpCaps
== NULL
) return MMSYSERR_NOTENABLED
;
699 audio
= open (SOUND_DEV
, O_WRONLY
, 0);
700 if (audio
== -1) return MMSYSERR_NOTENABLED
;
702 lpCaps
->wMid
= 0x0002;
703 lpCaps
->wPid
= 0x0104;
704 strcpy(lpCaps
->szPname
, "SB16 Wave Out");
706 lpCaps
->wMid
= 0x00FF; /* Manufac ID */
707 lpCaps
->wPid
= 0x0001; /* Product ID */
708 strcpy(lpCaps
->szPname
, "Linux WAVOUT Driver");
710 lpCaps
->dwFormats
= 0x00000000;
711 lpCaps
->dwSupport
= WAVECAPS_VOLUME
;
712 lpCaps
->wChannels
= (IOCTL(audio
, SNDCTL_DSP_STEREO
, dsp_stereo
) != 0) ? 1 : 2;
713 if (lpCaps
->wChannels
> 1) lpCaps
->dwSupport
|= WAVECAPS_LRVOLUME
;
714 bytespersmpl
= (IOCTL(audio
, SNDCTL_DSP_SAMPLESIZE
, samplesize
) != 0) ? 1 : 2;
716 if (IOCTL(audio
, SNDCTL_DSP_SPEED
, smplrate
) == 0) {
717 lpCaps
->dwFormats
|= WAVE_FORMAT_4M08
;
718 if (lpCaps
->wChannels
> 1) lpCaps
->dwFormats
|= WAVE_FORMAT_4S08
;
719 if (bytespersmpl
> 1) {
720 lpCaps
->dwFormats
|= WAVE_FORMAT_4M16
;
721 if (lpCaps
->wChannels
> 1) lpCaps
->dwFormats
|= WAVE_FORMAT_4S16
;
725 if (IOCTL(audio
, SNDCTL_DSP_SPEED
, smplrate
) == 0) {
726 lpCaps
->dwFormats
|= WAVE_FORMAT_2M08
;
727 if (lpCaps
->wChannels
> 1) lpCaps
->dwFormats
|= WAVE_FORMAT_2S08
;
728 if (bytespersmpl
> 1) {
729 lpCaps
->dwFormats
|= WAVE_FORMAT_2M16
;
730 if (lpCaps
->wChannels
> 1) lpCaps
->dwFormats
|= WAVE_FORMAT_2S16
;
734 if (IOCTL(audio
, SNDCTL_DSP_SPEED
, smplrate
) == 0) {
735 lpCaps
->dwFormats
|= WAVE_FORMAT_1M08
;
736 if (lpCaps
->wChannels
> 1) lpCaps
->dwFormats
|= WAVE_FORMAT_1S08
;
737 if (bytespersmpl
> 1) {
738 lpCaps
->dwFormats
|= WAVE_FORMAT_1M16
;
739 if (lpCaps
->wChannels
> 1) lpCaps
->dwFormats
|= WAVE_FORMAT_1S16
;
743 dprintf_mciwave(stddeb
,
744 "wodGetDevCaps // dwFormats = %08lX\n", lpCaps
->dwFormats
);
745 return MMSYSERR_NOERROR
;
749 /**************************************************************************
752 static DWORD
wodOpen(WORD wDevID
, LPWAVEOPENDESC lpDesc
, DWORD dwFlags
)
759 LPWAVEFORMAT lpFormat
;
761 dprintf_mciwave(stddeb
,
762 "wodOpen(%u, %p, %08lX);\n", wDevID
, lpDesc
, dwFlags
);
763 if (lpDesc
== NULL
) {
764 dprintf_mciwave(stddeb
,"Linux 'wodOpen' // Invalid Parameter !\n");
765 return MMSYSERR_INVALPARAM
;
767 if (wDevID
>= MAX_WAVOUTDRV
) {
768 dprintf_mciwave(stddeb
,"Linux 'wodOpen' // MAX_WAVOUTDRV reached !\n");
769 return MMSYSERR_ALLOCATED
;
771 WOutDev
[wDevID
].unixdev
= 0;
772 audio
= open (SOUND_DEV
, O_WRONLY
, 0);
774 dprintf_mciwave(stddeb
,"Linux 'wodOpen' // can't open !\n");
775 return MMSYSERR_NOTENABLED
;
777 IOCTL(audio
, SNDCTL_DSP_GETBLKSIZE
, abuf_size
);
778 if (abuf_size
< 4096 || abuf_size
> 65536) {
780 dprintf_mciwave(stddeb
,"Linux 'wodOpen' // IOCTL can't 'SNDCTL_DSP_GETBLKSIZE' !\n");
782 dprintf_mciwave(stddeb
,"Linux 'wodOpen' // SNDCTL_DSP_GETBLKSIZE Invalid bufsize !\n");
783 return MMSYSERR_NOTENABLED
;
785 WOutDev
[wDevID
].wFlags
= HIWORD(dwFlags
& CALLBACK_TYPEMASK
);
786 switch(WOutDev
[wDevID
].wFlags
) {
788 dprintf_mciwave(stddeb
, "Linux 'wodOpen' // CALLBACK_NULL !\n");
791 dprintf_mciwave(stddeb
, "Linux 'wodOpen' // CALLBACK_WINDOW !\n");
794 dprintf_mciwave(stddeb
, "Linux 'wodOpen' // CALLBACK_TASK !\n");
797 dprintf_mciwave(stddeb
, "Linux 'wodOpen' // CALLBACK_FUNCTION !\n");
800 WOutDev
[wDevID
].lpQueueHdr
= NULL
;
801 WOutDev
[wDevID
].unixdev
= audio
;
802 WOutDev
[wDevID
].dwTotalPlayed
= 0;
803 WOutDev
[wDevID
].bufsize
= abuf_size
;
804 memcpy(&WOutDev
[wDevID
].waveDesc
, lpDesc
, sizeof(WAVEOPENDESC
));
805 /* lpFormat = (LPWAVEFORMAT) PTR_SEG_TO_LIN(lpDesc->lpFormat); */
806 lpFormat
= lpDesc
->lpFormat
;
807 if (lpFormat
->wFormatTag
!= WAVE_FORMAT_PCM
) {
808 dprintf_mciwave(stddeb
,"Linux 'wodOpen' // Bad format %04X !\n",
809 lpFormat
->wFormatTag
);
810 dprintf_mciwave(stddeb
,"Linux 'wodOpen' // Bad nChannels %d !\n",
811 lpFormat
->nChannels
);
812 dprintf_mciwave(stddeb
,"Linux 'wodOpen' // Bad nSamplesPerSec %ld !\n",
813 lpFormat
->nSamplesPerSec
);
814 return WAVERR_BADFORMAT
;
816 memcpy(&WOutDev
[wDevID
].Format
, lpFormat
, sizeof(PCMWAVEFORMAT
));
817 if (WOutDev
[wDevID
].Format
.wf
.nChannels
== 0) return WAVERR_BADFORMAT
;
818 if (WOutDev
[wDevID
].Format
.wf
.nSamplesPerSec
== 0) return WAVERR_BADFORMAT
;
819 dprintf_mciwave(stddeb
,"Linux 'wodOpen' // wBitsPerSample=%u !\n",
820 WOutDev
[wDevID
].Format
.wBitsPerSample
);
821 if (WOutDev
[wDevID
].Format
.wBitsPerSample
== 0) {
822 WOutDev
[wDevID
].Format
.wBitsPerSample
= 8 *
823 (WOutDev
[wDevID
].Format
.wf
.nAvgBytesPerSec
/
824 WOutDev
[wDevID
].Format
.wf
.nSamplesPerSec
) /
825 WOutDev
[wDevID
].Format
.wf
.nChannels
;
827 samplesize
= WOutDev
[wDevID
].Format
.wBitsPerSample
;
828 smplrate
= WOutDev
[wDevID
].Format
.wf
.nSamplesPerSec
;
829 dsp_stereo
= (WOutDev
[wDevID
].Format
.wf
.nChannels
> 1) ? TRUE
: FALSE
;
830 IOCTL(audio
, SNDCTL_DSP_SPEED
, smplrate
);
831 IOCTL(audio
, SNDCTL_DSP_SAMPLESIZE
, samplesize
);
832 IOCTL(audio
, SNDCTL_DSP_STEREO
, dsp_stereo
);
833 dprintf_mciwave(stddeb
,"Linux 'wodOpen' // wBitsPerSample=%u !\n",
834 WOutDev
[wDevID
].Format
.wBitsPerSample
);
835 dprintf_mciwave(stddeb
,"Linux 'wodOpen' // nAvgBytesPerSec=%lu !\n",
836 WOutDev
[wDevID
].Format
.wf
.nAvgBytesPerSec
);
837 dprintf_mciwave(stddeb
,"Linux 'wodOpen' // nSamplesPerSec=%lu !\n",
838 WOutDev
[wDevID
].Format
.wf
.nSamplesPerSec
);
839 dprintf_mciwave(stddeb
,"Linux 'wodOpen' // nChannels=%u !\n",
840 WOutDev
[wDevID
].Format
.wf
.nChannels
);
841 if (WAVE_NotifyClient(wDevID
, WOM_OPEN
, 0L, 0L) != MMSYSERR_NOERROR
) {
842 dprintf_mciwave(stddeb
,"Linux 'wodOpen' // can't notify client !\n");
843 return MMSYSERR_INVALPARAM
;
845 return MMSYSERR_NOERROR
;
848 /**************************************************************************
849 * wodClose [internal]
851 static DWORD
wodClose(WORD wDevID
)
853 dprintf_mciwave(stddeb
,"wodClose(%u);\n", wDevID
);
854 if (WOutDev
[wDevID
].unixdev
== 0) {
855 dprintf_mciwave(stddeb
,"Linux 'wodClose' // can't close !\n");
856 return MMSYSERR_NOTENABLED
;
858 close(WOutDev
[wDevID
].unixdev
);
859 WOutDev
[wDevID
].unixdev
= 0;
860 WOutDev
[wDevID
].bufsize
= 0;
861 WOutDev
[wDevID
].lpQueueHdr
= NULL
;
862 if (WAVE_NotifyClient(wDevID
, WOM_CLOSE
, 0L, 0L) != MMSYSERR_NOERROR
) {
863 dprintf_mciwave(stddeb
,"Linux 'wodClose' // can't notify client !\n");
864 return MMSYSERR_INVALPARAM
;
866 return MMSYSERR_NOERROR
;
869 /**************************************************************************
870 * wodWrite [internal]
872 static DWORD
wodWrite(WORD wDevID
, LPWAVEHDR lpWaveHdr
, DWORD dwSize
)
876 dprintf_mciwave(stddeb
,"wodWrite(%u, %p, %08lX);\n", wDevID
, lpWaveHdr
, dwSize
);
877 if (WOutDev
[wDevID
].unixdev
== 0) {
878 dprintf_mciwave(stddeb
,"Linux 'wodWrite' // can't play !\n");
879 return MMSYSERR_NOTENABLED
;
881 if (lpWaveHdr
->lpData
== NULL
) return WAVERR_UNPREPARED
;
882 if (!(lpWaveHdr
->dwFlags
& WHDR_PREPARED
)) return WAVERR_UNPREPARED
;
883 if (lpWaveHdr
->dwFlags
& WHDR_INQUEUE
) return WAVERR_STILLPLAYING
;
884 lpWaveHdr
->dwFlags
&= ~WHDR_DONE
;
885 lpWaveHdr
->dwFlags
|= WHDR_INQUEUE
;
886 dprintf_mciwave(stddeb
,
887 "wodWrite() // dwBufferLength %lu !\n", lpWaveHdr
->dwBufferLength
);
888 dprintf_mciwave(stddeb
,
889 "wodWrite() // WOutDev[%u].unixdev %u !\n", wDevID
, WOutDev
[wDevID
].unixdev
);
890 lpData
= PTR_SEG_TO_LIN(lpWaveHdr
->lpData
);
891 count
= write (WOutDev
[wDevID
].unixdev
, lpData
, lpWaveHdr
->dwBufferLength
);
892 dprintf_mciwave(stddeb
,
893 "wodWrite() // write returned count %u !\n", count
);
894 if (count
!= lpWaveHdr
->dwBufferLength
) {
895 dprintf_mciwave(stddeb
,"Linux 'wodWrite' // error writting !\n");
896 return MMSYSERR_NOTENABLED
;
898 WOutDev
[wDevID
].dwTotalPlayed
+= count
;
899 lpWaveHdr
->dwFlags
&= ~WHDR_INQUEUE
;
900 lpWaveHdr
->dwFlags
|= WHDR_DONE
;
901 if (WAVE_NotifyClient(wDevID
, WOM_DONE
, 0L, 0L) != MMSYSERR_NOERROR
) {
902 dprintf_mciwave(stddeb
,"Linux 'wodWrite' // can't notify client !\n");
903 return MMSYSERR_INVALPARAM
;
905 return MMSYSERR_NOERROR
;
908 /**************************************************************************
909 * wodPrepare [internal]
911 static DWORD
wodPrepare(WORD wDevID
, LPWAVEHDR lpWaveHdr
, DWORD dwSize
)
913 dprintf_mciwave(stddeb
,
914 "wodPrepare(%u, %p, %08lX);\n", wDevID
, lpWaveHdr
, dwSize
);
915 if (WOutDev
[wDevID
].unixdev
== 0) {
916 dprintf_mciwave(stddeb
,"Linux 'wodPrepare' // can't prepare !\n");
917 return MMSYSERR_NOTENABLED
;
919 /* the COOL waveeditor feels much better without this check...
920 * someone please have a look at available documentation
921 if (WOutDev[wDevID].lpQueueHdr != NULL) {
922 dprintf_mciwave(stddeb,"Linux 'wodPrepare' // already prepare !\n");
923 return MMSYSERR_NOTENABLED;
926 WOutDev
[wDevID
].dwTotalPlayed
= 0;
927 WOutDev
[wDevID
].lpQueueHdr
= lpWaveHdr
;
928 if (lpWaveHdr
->dwFlags
& WHDR_INQUEUE
) return WAVERR_STILLPLAYING
;
929 lpWaveHdr
->dwFlags
|= WHDR_PREPARED
;
930 lpWaveHdr
->dwFlags
&= ~WHDR_DONE
;
931 return MMSYSERR_NOERROR
;
934 /**************************************************************************
935 * wodUnprepare [internal]
937 static DWORD
wodUnprepare(WORD wDevID
, LPWAVEHDR lpWaveHdr
, DWORD dwSize
)
939 dprintf_mciwave(stddeb
,
940 "wodUnprepare(%u, %p, %08lX);\n", wDevID
, lpWaveHdr
, dwSize
);
941 if (WOutDev
[wDevID
].unixdev
== 0) {
942 dprintf_mciwave(stddeb
,"Linux 'wodUnprepare' // can't unprepare !\n");
943 return MMSYSERR_NOTENABLED
;
945 return MMSYSERR_NOERROR
;
948 /**************************************************************************
949 * wodRestart [internal]
951 static DWORD
wodRestart(WORD wDevID
)
953 dprintf_mciwave(stddeb
,"wodRestart(%u);\n", wDevID
);
954 if (WOutDev
[wDevID
].unixdev
== 0) {
955 dprintf_mciwave(stddeb
,"Linux 'wodRestart' // can't restart !\n");
956 return MMSYSERR_NOTENABLED
;
958 return MMSYSERR_NOERROR
;
961 /**************************************************************************
962 * wodReset [internal]
964 static DWORD
wodReset(WORD wDevID
)
966 dprintf_mciwave(stddeb
,"wodReset(%u);\n", wDevID
);
967 if (WOutDev
[wDevID
].unixdev
== 0) {
968 dprintf_mciwave(stddeb
,"Linux 'wodReset' // can't reset !\n");
969 return MMSYSERR_NOTENABLED
;
971 return MMSYSERR_NOERROR
;
975 /**************************************************************************
976 * wodGetPosition [internal]
978 static DWORD
wodGetPosition(WORD wDevID
, LPMMTIME lpTime
, DWORD uSize
)
981 dprintf_mciwave(stddeb
,"wodGetPosition(%u, %p, %lu);\n", wDevID
, lpTime
, uSize
);
982 if (WOutDev
[wDevID
].unixdev
== 0) {
983 dprintf_mciwave(stddeb
,"Linux 'wodGetPosition' // can't get pos !\n");
984 return MMSYSERR_NOTENABLED
;
986 if (lpTime
== NULL
) return MMSYSERR_INVALPARAM
;
987 switch(lpTime
->wType
) {
989 lpTime
->u
.cb
= WOutDev
[wDevID
].dwTotalPlayed
;
990 dprintf_mciwave(stddeb
,"wodGetPosition // TIME_BYTES=%lu\n", lpTime
->u
.cb
);
993 dprintf_mciwave(stddeb
,"wodGetPosition // dwTotalPlayed=%lu\n",
994 WOutDev
[wDevID
].dwTotalPlayed
);
995 dprintf_mciwave(stddeb
,"wodGetPosition // wBitsPerSample=%u\n",
996 WOutDev
[wDevID
].Format
.wBitsPerSample
);
997 lpTime
->u
.sample
= WOutDev
[wDevID
].dwTotalPlayed
* 8 /
998 WOutDev
[wDevID
].Format
.wBitsPerSample
;
999 dprintf_mciwave(stddeb
,"wodGetPosition // TIME_SAMPLES=%lu\n", lpTime
->u
.sample
);
1002 time
= WOutDev
[wDevID
].dwTotalPlayed
/
1003 (WOutDev
[wDevID
].Format
.wf
.nAvgBytesPerSec
/ 1000);
1004 lpTime
->u
.smpte
.hour
= time
/ 108000;
1005 time
-= lpTime
->u
.smpte
.hour
* 108000;
1006 lpTime
->u
.smpte
.min
= time
/ 1800;
1007 time
-= lpTime
->u
.smpte
.min
* 1800;
1008 lpTime
->u
.smpte
.sec
= time
/ 30;
1009 time
-= lpTime
->u
.smpte
.sec
* 30;
1010 lpTime
->u
.smpte
.frame
= time
;
1011 lpTime
->u
.smpte
.fps
= 30;
1012 dprintf_mciwave(stddeb
,
1013 "wodGetPosition // TIME_SMPTE=%02u:%02u:%02u:%02u\n",
1014 lpTime
->u
.smpte
.hour
, lpTime
->u
.smpte
.min
,
1015 lpTime
->u
.smpte
.sec
, lpTime
->u
.smpte
.frame
);
1018 dprintf_mciwave(stddeb
,"wodGetPosition() format not supported ! use TIME_MS !\n");
1019 lpTime
->wType
= TIME_MS
;
1021 lpTime
->u
.ms
= WOutDev
[wDevID
].dwTotalPlayed
/
1022 (WOutDev
[wDevID
].Format
.wf
.nAvgBytesPerSec
/ 1000);
1023 dprintf_mciwave(stddeb
,"wodGetPosition // TIME_MS=%lu\n", lpTime
->u
.ms
);
1026 return MMSYSERR_NOERROR
;
1029 /**************************************************************************
1030 * wodGetVolume [internal]
1032 static DWORD
wodGetVolume(WORD wDevID
, LPDWORD lpdwVol
)
1035 int volume
, left
, right
;
1036 dprintf_mciwave(stddeb
,"wodGetVolume(%u, %p);\n", wDevID
, lpdwVol
);
1037 if (lpdwVol
== NULL
) return MMSYSERR_NOTENABLED
;
1038 if ((mixer
= open("/dev/mixer", O_RDONLY
)) < 0) {
1039 dprintf_mciwave(stddeb
, "Linux 'wodGetVolume' // mixer device not available !\n");
1040 return MMSYSERR_NOTENABLED
;
1042 if (ioctl(mixer
, SOUND_MIXER_READ_PCM
, &volume
) == -1) {
1043 dprintf_mciwave(stddeb
,"Linux 'wodGetVolume' // unable read mixer !\n");
1044 return MMSYSERR_NOTENABLED
;
1047 left
= volume
& 0x7F;
1048 right
= (volume
>> 8) & 0x7F;
1049 printf("Linux 'AUX_GetVolume' // left=%d right=%d !\n", left
, right
);
1050 *lpdwVol
= MAKELONG(left
<< 9, right
<< 9);
1051 return MMSYSERR_NOERROR
;
1055 /**************************************************************************
1056 * wodSetVolume [internal]
1058 static DWORD
wodSetVolume(WORD wDevID
, DWORD dwParam
)
1062 dprintf_mciwave(stddeb
,"wodSetVolume(%u, %08lX);\n", wDevID
, dwParam
);
1063 volume
= (LOWORD(dwParam
) >> 9 & 0x7F) +
1064 ((HIWORD(dwParam
) >> 9 & 0x7F) << 8);
1065 if ((mixer
= open("/dev/mixer", O_WRONLY
)) < 0) {
1066 dprintf_mciwave(stddeb
, "Linux 'wodSetVolume' // mixer device not available !\n");
1067 return MMSYSERR_NOTENABLED
;
1069 if (ioctl(mixer
, SOUND_MIXER_WRITE_PCM
, &volume
) == -1) {
1070 dprintf_mciwave(stddeb
,"Linux 'wodSetVolume' // unable set mixer !\n");
1071 return MMSYSERR_NOTENABLED
;
1074 return MMSYSERR_NOERROR
;
1079 /**************************************************************************
1080 * wodMessage [sample driver]
1082 DWORD
wodMessage(WORD wDevID
, WORD wMsg
, DWORD dwUser
,
1083 DWORD dwParam1
, DWORD dwParam2
)
1085 dprintf_mciwave(stddeb
,"wodMessage(%u, %04X, %08lX, %08lX, %08lX);\n",
1086 wDevID
, wMsg
, dwUser
, dwParam1
, dwParam2
);
1090 return wodOpen(wDevID
, (LPWAVEOPENDESC
)PTR_SEG_TO_LIN(dwParam1
), dwParam2
);
1092 return wodClose(wDevID
);
1094 return wodWrite(wDevID
, (LPWAVEHDR
)PTR_SEG_TO_LIN(dwParam1
), dwParam2
);
1098 return wodGetPosition(wDevID
, (LPMMTIME
)PTR_SEG_TO_LIN(dwParam1
), dwParam2
);
1099 case WODM_BREAKLOOP
:
1102 return wodPrepare(wDevID
, (LPWAVEHDR
)PTR_SEG_TO_LIN(dwParam1
), dwParam2
);
1103 case WODM_UNPREPARE
:
1104 return wodUnprepare(wDevID
, (LPWAVEHDR
)PTR_SEG_TO_LIN(dwParam1
), dwParam2
);
1105 case WODM_GETDEVCAPS
:
1106 return wodGetDevCaps(wDevID
, (LPWAVEOUTCAPS
)PTR_SEG_TO_LIN(dwParam1
), dwParam2
);
1107 case WODM_GETNUMDEVS
:
1113 case WODM_GETPLAYBACKRATE
:
1115 case WODM_SETPLAYBACKRATE
:
1117 case WODM_GETVOLUME
:
1118 return wodGetVolume(wDevID
, (LPDWORD
)PTR_SEG_TO_LIN(dwParam1
));
1119 case WODM_SETVOLUME
:
1120 return wodSetVolume(wDevID
, dwParam1
);
1122 return wodRestart(wDevID
);
1124 return wodReset(wDevID
);
1126 dprintf_mciwave(stddeb
,"wodMessage // unknown message !\n");
1128 return MMSYSERR_NOTSUPPORTED
;
1130 return MMSYSERR_NOTENABLED
;
1135 /*-----------------------------------------------------------------------*/
1139 /**************************************************************************
1140 * widGetDevCaps [internal]
1142 static DWORD
widGetDevCaps(WORD wDevID
, LPWAVEINCAPS lpCaps
, DWORD dwSize
)
1146 int samplesize
= 16;
1149 dprintf_mciwave(stddeb
,
1150 "widGetDevCaps(%u, %p, %lu);\n", wDevID
, lpCaps
, dwSize
);
1151 if (lpCaps
== NULL
) return MMSYSERR_NOTENABLED
;
1152 audio
= open (SOUND_DEV
, O_RDONLY
, 0);
1153 if (audio
== -1) return MMSYSERR_NOTENABLED
;
1155 lpCaps
->wMid
= 0x0002;
1156 lpCaps
->wPid
= 0x0004;
1157 strcpy(lpCaps
->szPname
, "SB16 Wave Out");
1159 lpCaps
->wMid
= 0x00FF; /* Manufac ID */
1160 lpCaps
->wPid
= 0x0001; /* Product ID */
1161 strcpy(lpCaps
->szPname
, "Linux WAVIN Driver");
1163 lpCaps
->dwFormats
= 0x00000000;
1164 lpCaps
->wChannels
= (IOCTL(audio
, SNDCTL_DSP_STEREO
, dsp_stereo
) != 0) ? 1 : 2;
1165 bytespersmpl
= (IOCTL(audio
, SNDCTL_DSP_SAMPLESIZE
, samplesize
) != 0) ? 1 : 2;
1167 if (IOCTL(audio
, SNDCTL_DSP_SPEED
, smplrate
) == 0) {
1168 lpCaps
->dwFormats
|= WAVE_FORMAT_4M08
;
1169 if (lpCaps
->wChannels
> 1) lpCaps
->dwFormats
|= WAVE_FORMAT_4S08
;
1170 if (bytespersmpl
> 1) {
1171 lpCaps
->dwFormats
|= WAVE_FORMAT_4M16
;
1172 if (lpCaps
->wChannels
> 1) lpCaps
->dwFormats
|= WAVE_FORMAT_4S16
;
1176 if (IOCTL(audio
, SNDCTL_DSP_SPEED
, smplrate
) == 0) {
1177 lpCaps
->dwFormats
|= WAVE_FORMAT_2M08
;
1178 if (lpCaps
->wChannels
> 1) lpCaps
->dwFormats
|= WAVE_FORMAT_2S08
;
1179 if (bytespersmpl
> 1) {
1180 lpCaps
->dwFormats
|= WAVE_FORMAT_2M16
;
1181 if (lpCaps
->wChannels
> 1) lpCaps
->dwFormats
|= WAVE_FORMAT_2S16
;
1185 if (IOCTL(audio
, SNDCTL_DSP_SPEED
, smplrate
) == 0) {
1186 lpCaps
->dwFormats
|= WAVE_FORMAT_1M08
;
1187 if (lpCaps
->wChannels
> 1) lpCaps
->dwFormats
|= WAVE_FORMAT_1S08
;
1188 if (bytespersmpl
> 1) {
1189 lpCaps
->dwFormats
|= WAVE_FORMAT_1M16
;
1190 if (lpCaps
->wChannels
> 1) lpCaps
->dwFormats
|= WAVE_FORMAT_1S16
;
1194 dprintf_mciwave(stddeb
,
1195 "widGetDevCaps // dwFormats = %08lX\n", lpCaps
->dwFormats
);
1196 return MMSYSERR_NOERROR
;
1200 /**************************************************************************
1201 * widOpen [internal]
1203 static DWORD
widOpen(WORD wDevID
, LPWAVEOPENDESC lpDesc
, DWORD dwFlags
)
1210 LPWAVEFORMAT lpFormat
;
1211 dprintf_mciwave(stddeb
, "widOpen(%u, %p, %08lX);\n", wDevID
, lpDesc
, dwFlags
);
1212 if (lpDesc
== NULL
) {
1213 dprintf_mciwave(stddeb
,"Linux 'widOpen' // Invalid Parameter !\n");
1214 return MMSYSERR_INVALPARAM
;
1216 if (wDevID
>= MAX_WAVINDRV
) {
1217 dprintf_mciwave(stddeb
,"Linux 'widOpen' // MAX_WAVINDRV reached !\n");
1218 return MMSYSERR_ALLOCATED
;
1220 WInDev
[wDevID
].unixdev
= 0;
1221 audio
= open (SOUND_DEV
, O_RDONLY
, 0);
1223 dprintf_mciwave(stddeb
,"Linux 'widOpen' // can't open !\n");
1224 return MMSYSERR_NOTENABLED
;
1226 IOCTL(audio
, SNDCTL_DSP_GETBLKSIZE
, abuf_size
);
1227 if (abuf_size
< 4096 || abuf_size
> 65536) {
1228 if (abuf_size
== -1)
1229 dprintf_mciwave(stddeb
,"Linux 'widOpen' // IOCTL can't 'SNDCTL_DSP_GETBLKSIZE' !\n");
1231 dprintf_mciwave(stddeb
,"Linux 'widOpen' // SNDCTL_DSP_GETBLKSIZE Invalid bufsize !\n");
1232 return MMSYSERR_NOTENABLED
;
1234 WInDev
[wDevID
].wFlags
= HIWORD(dwFlags
& CALLBACK_TYPEMASK
);
1235 switch(WInDev
[wDevID
].wFlags
) {
1237 dprintf_mciwave(stddeb
, "Linux 'widOpen' // CALLBACK_NULL !\n");
1240 dprintf_mciwave(stddeb
, "Linux 'widOpen' // CALLBACK_WINDOW !\n");
1243 dprintf_mciwave(stddeb
, "Linux 'widOpen' // CALLBACK_TASK !\n");
1246 dprintf_mciwave(stddeb
, "Linux 'widOpen' // CALLBACK_FUNCTION !\n");
1249 WInDev
[wDevID
].lpQueueHdr
= NULL
;
1250 WInDev
[wDevID
].unixdev
= audio
;
1251 WInDev
[wDevID
].bufsize
= abuf_size
;
1252 WInDev
[wDevID
].dwTotalRecorded
= 0;
1253 memcpy(&WInDev
[wDevID
].waveDesc
, lpDesc
, sizeof(WAVEOPENDESC
));
1254 lpFormat
= lpDesc
->lpFormat
;
1255 if (lpFormat
->wFormatTag
!= WAVE_FORMAT_PCM
) {
1256 dprintf_mciwave(stddeb
,"Linux 'widOpen' // Bad format %04X !\n",
1257 lpFormat
->wFormatTag
);
1258 return WAVERR_BADFORMAT
;
1260 memcpy(&WInDev
[wDevID
].Format
, lpFormat
, sizeof(PCMWAVEFORMAT
));
1261 WInDev
[wDevID
].Format
.wBitsPerSample
= 8; /* <-------------- */
1262 if (WInDev
[wDevID
].Format
.wf
.nChannels
== 0) return WAVERR_BADFORMAT
;
1263 if (WInDev
[wDevID
].Format
.wf
.nSamplesPerSec
== 0) return WAVERR_BADFORMAT
;
1264 if (WInDev
[wDevID
].Format
.wBitsPerSample
== 0) {
1265 WInDev
[wDevID
].Format
.wBitsPerSample
= 8 *
1266 (WInDev
[wDevID
].Format
.wf
.nAvgBytesPerSec
/
1267 WInDev
[wDevID
].Format
.wf
.nSamplesPerSec
) /
1268 WInDev
[wDevID
].Format
.wf
.nChannels
;
1270 samplesize
= WInDev
[wDevID
].Format
.wBitsPerSample
;
1271 smplrate
= WInDev
[wDevID
].Format
.wf
.nSamplesPerSec
;
1272 dsp_stereo
= (WInDev
[wDevID
].Format
.wf
.nChannels
> 1) ? TRUE
: FALSE
;
1273 IOCTL(audio
, SNDCTL_DSP_SPEED
, smplrate
);
1274 IOCTL(audio
, SNDCTL_DSP_SAMPLESIZE
, samplesize
);
1275 IOCTL(audio
, SNDCTL_DSP_STEREO
, dsp_stereo
);
1276 dprintf_mciwave(stddeb
,"Linux 'widOpen' // wBitsPerSample=%u !\n",
1277 WInDev
[wDevID
].Format
.wBitsPerSample
);
1278 dprintf_mciwave(stddeb
,"Linux 'widOpen' // nSamplesPerSec=%lu !\n",
1279 WInDev
[wDevID
].Format
.wf
.nSamplesPerSec
);
1280 dprintf_mciwave(stddeb
,"Linux 'widOpen' // nChannels=%u !\n",
1281 WInDev
[wDevID
].Format
.wf
.nChannels
);
1282 dprintf_mciwave(stddeb
,"Linux 'widOpen' // nAvgBytesPerSec=%lu\n",
1283 WInDev
[wDevID
].Format
.wf
.nAvgBytesPerSec
);
1284 if (WAVE_NotifyClient(wDevID
, WIM_OPEN
, 0L, 0L) != MMSYSERR_NOERROR
) {
1285 dprintf_mciwave(stddeb
,"Linux 'widOpen' // can't notify client !\n");
1286 return MMSYSERR_INVALPARAM
;
1288 return MMSYSERR_NOERROR
;
1291 /**************************************************************************
1292 * widClose [internal]
1294 static DWORD
widClose(WORD wDevID
)
1296 dprintf_mciwave(stddeb
,"widClose(%u);\n", wDevID
);
1297 if (WInDev
[wDevID
].unixdev
== 0) {
1298 dprintf_mciwave(stddeb
,"Linux 'widClose' // can't close !\n");
1299 return MMSYSERR_NOTENABLED
;
1301 close(WInDev
[wDevID
].unixdev
);
1302 WInDev
[wDevID
].unixdev
= 0;
1303 WInDev
[wDevID
].bufsize
= 0;
1304 if (WAVE_NotifyClient(wDevID
, WIM_CLOSE
, 0L, 0L) != MMSYSERR_NOERROR
) {
1305 dprintf_mciwave(stddeb
,"Linux 'widClose' // can't notify client !\n");
1306 return MMSYSERR_INVALPARAM
;
1308 return MMSYSERR_NOERROR
;
1311 /**************************************************************************
1312 * widAddBuffer [internal]
1314 static DWORD
widAddBuffer(WORD wDevID
, LPWAVEHDR lpWaveHdr
, DWORD dwSize
)
1318 dprintf_mciwave(stddeb
,
1319 "widAddBuffer(%u, %p, %08lX);\n", wDevID
, lpWaveHdr
, dwSize
);
1320 if (WInDev
[wDevID
].unixdev
== 0) {
1321 dprintf_mciwave(stddeb
,"Linux 'widAddBuffer' // can't do it !\n");
1322 return MMSYSERR_NOTENABLED
;
1324 if (!(lpWaveHdr
->dwFlags
& WHDR_PREPARED
)) {
1325 dprintf_mciwave(stddeb
, "Linux 'widAddBuffer' // never been prepared !\n");
1326 return WAVERR_UNPREPARED
;
1328 if (lpWaveHdr
->dwFlags
& WHDR_INQUEUE
) {
1329 dprintf_mciwave(stddeb
, "Linux 'widAddBuffer' // header already in use !\n");
1330 return WAVERR_STILLPLAYING
;
1332 lpWaveHdr
->dwFlags
|= WHDR_PREPARED
;
1333 lpWaveHdr
->dwFlags
|= WHDR_INQUEUE
;
1334 lpWaveHdr
->dwFlags
&= ~WHDR_DONE
;
1335 lpWaveHdr
->dwBytesRecorded
= 0;
1336 if (WInDev
[wDevID
].lpQueueHdr
== NULL
) {
1337 /* begin the queue with a first header ... */
1338 WInDev
[wDevID
].lpQueueHdr
= lpWaveHdr
;
1339 WInDev
[wDevID
].dwTotalRecorded
= 0;
1342 /* added to the queue, except if it's the one just prepared ... */
1343 lpWIHdr
= WInDev
[wDevID
].lpQueueHdr
;
1344 while (lpWIHdr
->lpNext
!= NULL
) {
1345 lpWIHdr
= lpWIHdr
->lpNext
;
1348 lpWIHdr
->lpNext
= lpWaveHdr
;
1351 dprintf_mciwave(stddeb
,
1352 "widAddBuffer // buffer added ! (now %u in queue)\n", count
);
1353 return MMSYSERR_NOERROR
;
1356 /**************************************************************************
1357 * widPrepare [internal]
1359 static DWORD
widPrepare(WORD wDevID
, LPWAVEHDR lpWaveHdr
, DWORD dwSize
)
1361 dprintf_mciwave(stddeb
,
1362 "widPrepare(%u, %p, %08lX);\n", wDevID
, lpWaveHdr
, dwSize
);
1363 if (WInDev
[wDevID
].unixdev
== 0) {
1364 dprintf_mciwave(stddeb
,"Linux 'widPrepare' // can't prepare !\n");
1365 return MMSYSERR_NOTENABLED
;
1367 if (WInDev
[wDevID
].lpQueueHdr
!= NULL
) {
1368 dprintf_mciwave(stddeb
,"Linux 'widPrepare' // already prepare !\n");
1369 return WAVERR_BADFORMAT
;
1371 if (lpWaveHdr
->dwFlags
& WHDR_INQUEUE
) return WAVERR_STILLPLAYING
;
1372 lpWaveHdr
->dwFlags
|= WHDR_PREPARED
;
1373 lpWaveHdr
->dwFlags
&= ~WHDR_INQUEUE
;
1374 lpWaveHdr
->dwFlags
&= ~WHDR_DONE
;
1375 lpWaveHdr
->dwBytesRecorded
= 0;
1376 dprintf_mciwave(stddeb
,"Linux 'widPrepare' // header prepared !\n");
1377 return MMSYSERR_NOERROR
;
1380 /**************************************************************************
1381 * widUnprepare [internal]
1383 static DWORD
widUnprepare(WORD wDevID
, LPWAVEHDR lpWaveHdr
, DWORD dwSize
)
1385 dprintf_mciwave(stddeb
,
1386 "widUnprepare(%u, %p, %08lX);\n", wDevID
, lpWaveHdr
, dwSize
);
1387 if (WInDev
[wDevID
].unixdev
== 0) {
1388 dprintf_mciwave(stddeb
,"Linux 'widUnprepare' // can't unprepare !\n");
1389 return MMSYSERR_NOTENABLED
;
1391 lpWaveHdr
->dwFlags
&= ~WHDR_PREPARED
;
1392 lpWaveHdr
->dwFlags
&= ~WHDR_INQUEUE
;
1393 lpWaveHdr
->dwFlags
|= WHDR_DONE
;
1394 WInDev
[wDevID
].lpQueueHdr
= NULL
;
1395 dprintf_mciwave(stddeb
,
1396 "Linux 'widUnprepare' // all headers unprepared !\n");
1397 return MMSYSERR_NOERROR
;
1400 /**************************************************************************
1401 * widStart [internal]
1403 static DWORD
widStart(WORD wDevID
)
1407 dprintf_mciwave(stddeb
,"widStart(%u);\n", wDevID
);
1408 if (WInDev
[wDevID
].unixdev
== 0) {
1409 dprintf_mciwave(stddeb
, "Linux 'widStart' // can't start recording !\n");
1410 return MMSYSERR_NOTENABLED
;
1412 if (WInDev
[wDevID
].lpQueueHdr
== NULL
||
1413 WInDev
[wDevID
].lpQueueHdr
->lpData
== NULL
) {
1414 dprintf_mciwave(stddeb
,"Linux 'widStart' // never been prepared !\n");
1415 return WAVERR_UNPREPARED
;
1417 lpWIHdr
= WInDev
[wDevID
].lpQueueHdr
;
1418 while(lpWIHdr
!= NULL
) {
1419 lpWIHdr
->dwBufferLength
&= 0xFFFF;
1420 dprintf_mciwave(stddeb
,
1421 "widStart // recording buf#%u=%p size=%lu \n",
1422 count
, lpWIHdr
->lpData
, lpWIHdr
->dwBufferLength
);
1424 read (WInDev
[wDevID
].unixdev
,
1425 PTR_SEG_TO_LIN(lpWIHdr
->lpData
),
1426 lpWIHdr
->dwBufferLength
);
1427 lpWIHdr
->dwBytesRecorded
= lpWIHdr
->dwBufferLength
;
1428 WInDev
[wDevID
].dwTotalRecorded
+= lpWIHdr
->dwBytesRecorded
;
1429 lpWIHdr
->dwFlags
&= ~WHDR_INQUEUE
;
1430 lpWIHdr
->dwFlags
|= WHDR_DONE
;
1431 if (WAVE_NotifyClient(wDevID
, WIM_DATA
, (DWORD
)lpWIHdr
, 0L) !=
1433 dprintf_mciwave(stddeb
, "Linux 'widStart' // can't notify client !\n");
1434 return MMSYSERR_INVALPARAM
;
1436 lpWIHdr
= lpWIHdr
->lpNext
;
1439 dprintf_mciwave(stddeb
,"widStart // end of recording !\n");
1441 return MMSYSERR_NOERROR
;
1444 /**************************************************************************
1445 * widStop [internal]
1447 static DWORD
widStop(WORD wDevID
)
1449 dprintf_mciwave(stddeb
,"widStop(%u);\n", wDevID
);
1450 if (WInDev
[wDevID
].unixdev
== 0) {
1451 dprintf_mciwave(stddeb
,"Linux 'widStop' // can't stop !\n");
1452 return MMSYSERR_NOTENABLED
;
1454 return MMSYSERR_NOERROR
;
1457 /**************************************************************************
1458 * widReset [internal]
1460 static DWORD
widReset(WORD wDevID
)
1462 dprintf_mciwave(stddeb
,"widReset(%u);\n", wDevID
);
1463 if (WInDev
[wDevID
].unixdev
== 0) {
1464 dprintf_mciwave(stddeb
,"Linux 'widReset' // can't reset !\n");
1465 return MMSYSERR_NOTENABLED
;
1467 return MMSYSERR_NOERROR
;
1470 /**************************************************************************
1471 * widGetPosition [internal]
1473 static DWORD
widGetPosition(WORD wDevID
, LPMMTIME lpTime
, DWORD uSize
)
1477 dprintf_mciwave(stddeb
,
1478 "widGetPosition(%u, %p, %lu);\n", wDevID
, lpTime
, uSize
);
1479 if (WInDev
[wDevID
].unixdev
== 0) {
1480 dprintf_mciwave(stddeb
,"Linux 'widGetPosition' // can't get pos !\n");
1481 return MMSYSERR_NOTENABLED
;
1483 if (lpTime
== NULL
) return MMSYSERR_INVALPARAM
;
1484 dprintf_mciwave(stddeb
,"widGetPosition // wType=%04X !\n",
1486 dprintf_mciwave(stddeb
,"widGetPosition // wBitsPerSample=%u\n",
1487 WInDev
[wDevID
].Format
.wBitsPerSample
);
1488 dprintf_mciwave(stddeb
,"widGetPosition // nSamplesPerSec=%lu\n",
1489 WInDev
[wDevID
].Format
.wf
.nSamplesPerSec
);
1490 dprintf_mciwave(stddeb
,"widGetPosition // nChannels=%u\n",
1491 WInDev
[wDevID
].Format
.wf
.nChannels
);
1492 dprintf_mciwave(stddeb
,"widGetPosition // nAvgBytesPerSec=%lu\n",
1493 WInDev
[wDevID
].Format
.wf
.nAvgBytesPerSec
);
1495 switch(lpTime
->wType
) {
1497 lpTime
->u
.cb
= WInDev
[wDevID
].dwTotalRecorded
;
1498 dprintf_mciwave(stddeb
,
1499 "widGetPosition // TIME_BYTES=%lu\n", lpTime
->u
.cb
);
1502 lpTime
->u
.sample
= WInDev
[wDevID
].dwTotalRecorded
* 8 /
1503 WInDev
[wDevID
].Format
.wBitsPerSample
;
1504 dprintf_mciwave(stddeb
,
1505 "widGetPosition // TIME_SAMPLES=%lu\n",
1509 time
= WInDev
[wDevID
].dwTotalRecorded
/
1510 (WInDev
[wDevID
].Format
.wf
.nAvgBytesPerSec
/ 1000);
1511 lpTime
->u
.smpte
.hour
= time
/ 108000;
1512 time
-= lpTime
->u
.smpte
.hour
* 108000;
1513 lpTime
->u
.smpte
.min
= time
/ 1800;
1514 time
-= lpTime
->u
.smpte
.min
* 1800;
1515 lpTime
->u
.smpte
.sec
= time
/ 30;
1516 time
-= lpTime
->u
.smpte
.sec
* 30;
1517 lpTime
->u
.smpte
.frame
= time
;
1518 lpTime
->u
.smpte
.fps
= 30;
1519 dprintf_mciwave(stddeb
,"widGetPosition // TIME_SMPTE=%02u:%02u:%02u:%02u\n",
1520 lpTime
->u
.smpte
.hour
, lpTime
->u
.smpte
.min
,
1521 lpTime
->u
.smpte
.sec
, lpTime
->u
.smpte
.frame
);
1524 dprintf_mciwave(stddeb
,"widGetPosition() format not supported ! use TIME_MS !\n");
1525 lpTime
->wType
= TIME_MS
;
1527 lpTime
->u
.ms
= WInDev
[wDevID
].dwTotalRecorded
/
1528 (WInDev
[wDevID
].Format
.wf
.nAvgBytesPerSec
/ 1000);
1529 dprintf_mciwave(stddeb
,
1530 "widGetPosition // TIME_MS=%lu\n", lpTime
->u
.ms
);
1533 return MMSYSERR_NOERROR
;
1538 /**************************************************************************
1539 * widMessage [sample driver]
1541 DWORD
widMessage(WORD wDevID
, WORD wMsg
, DWORD dwUser
,
1542 DWORD dwParam1
, DWORD dwParam2
)
1544 dprintf_mciwave(stddeb
,"widMessage(%u, %04X, %08lX, %08lX, %08lX);\n",
1545 wDevID
, wMsg
, dwUser
, dwParam1
, dwParam2
);
1549 return widOpen(wDevID
, (LPWAVEOPENDESC
)PTR_SEG_TO_LIN(dwParam1
), dwParam2
);
1551 return widClose(wDevID
);
1552 case WIDM_ADDBUFFER
:
1553 return widAddBuffer(wDevID
, (LPWAVEHDR
)PTR_SEG_TO_LIN(dwParam1
), dwParam2
);
1555 return widPrepare(wDevID
, (LPWAVEHDR
)PTR_SEG_TO_LIN(dwParam1
), dwParam2
);
1556 case WIDM_UNPREPARE
:
1557 return widUnprepare(wDevID
, (LPWAVEHDR
)PTR_SEG_TO_LIN(dwParam1
), dwParam2
);
1558 case WIDM_GETDEVCAPS
:
1559 return widGetDevCaps(wDevID
, (LPWAVEINCAPS
)PTR_SEG_TO_LIN(dwParam1
), dwParam2
);
1560 case WIDM_GETNUMDEVS
:
1563 return widGetPosition(wDevID
, (LPMMTIME
)PTR_SEG_TO_LIN(dwParam1
), dwParam2
);
1565 return widReset(wDevID
);
1567 return widStart(wDevID
);
1569 return widStop(wDevID
);
1571 dprintf_mciwave(stddeb
,"widMessage // unknown message !\n");
1573 return MMSYSERR_NOTSUPPORTED
;
1575 return MMSYSERR_NOTENABLED
;
1580 /**************************************************************************
1581 * AUDIO_DriverProc [sample driver]
1583 LONG
WAVE_DriverProc(DWORD dwDevID
, HDRVR hDriv
, WORD wMsg
,
1584 DWORD dwParam1
, DWORD dwParam2
)
1587 dprintf_mciwave(stddeb
,"WAVE_DriverProc(%08lX, %04X, %04X, %08lX, %08lX)\n",
1588 dwDevID
, hDriv
, wMsg
, dwParam1
, dwParam2
);
1602 case DRV_QUERYCONFIGURE
:
1605 MessageBox((HWND
)NULL
, "Sample MultiMedia Linux Driver !",
1606 "MMLinux Driver", MB_OK
);
1609 return DRVCNF_RESTART
;
1611 return DRVCNF_RESTART
;
1612 case MCI_OPEN_DRIVER
:
1614 return WAVE_mciOpen(dwDevID
, dwParam1
, (LPMCI_WAVE_OPEN_PARMS
)PTR_SEG_TO_LIN(dwParam2
));
1615 case MCI_CLOSE_DRIVER
:
1617 return WAVE_mciClose(dwDevID
, dwParam1
, (LPMCI_GENERIC_PARMS
)PTR_SEG_TO_LIN(dwParam2
));
1619 return WAVE_mciPlay(dwDevID
, dwParam1
, (LPMCI_PLAY_PARMS
)PTR_SEG_TO_LIN(dwParam2
));
1621 return WAVE_mciRecord(dwDevID
, dwParam1
, (LPMCI_RECORD_PARMS
)PTR_SEG_TO_LIN(dwParam2
));
1623 return WAVE_mciStop(dwDevID
, dwParam1
, (LPMCI_GENERIC_PARMS
)PTR_SEG_TO_LIN(dwParam2
));
1625 return WAVE_mciSet(dwDevID
, dwParam1
, (LPMCI_SET_PARMS
)PTR_SEG_TO_LIN(dwParam2
));
1627 return WAVE_mciPause(dwDevID
, dwParam1
, (LPMCI_GENERIC_PARMS
)PTR_SEG_TO_LIN(dwParam2
));
1629 return WAVE_mciResume(dwDevID
, dwParam1
, (LPMCI_GENERIC_PARMS
)PTR_SEG_TO_LIN(dwParam2
));
1631 return WAVE_mciStatus(dwDevID
, dwParam1
, (LPMCI_STATUS_PARMS
)PTR_SEG_TO_LIN(dwParam2
));
1632 case MCI_GETDEVCAPS
:
1633 return WAVE_mciGetDevCaps(dwDevID
, dwParam1
, (LPMCI_GETDEVCAPS_PARMS
)PTR_SEG_TO_LIN(dwParam2
));
1635 return WAVE_mciInfo(dwDevID
, dwParam1
, (LPMCI_INFO_PARMS
)PTR_SEG_TO_LIN(dwParam2
));
1637 return DefDriverProc(dwDevID
, hDriv
, wMsg
, dwParam1
, dwParam2
);
1640 return MMSYSERR_NOTENABLED
;
1645 #endif /* #ifdef BUILTIN_MMSYSTEM */