2 * Sample Wine Driver for Linux
4 * Copyright 1994 Martin Ayotte
8 #define BUILTIN_MMSYSTEM
11 #ifdef BUILTIN_MMSYSTEM
19 #include <sys/ioctl.h>
27 #include <linux/soundcard.h>
34 #define SOUND_DEV "/dev/dsp"
37 #define IOCTL(a,b,c) ((-1==ioctl(a,b,&c))&&(perror("ioctl:"#b":"#c),0))
39 #define IOCTL(a,b,c) (c = ioctl(a,b,c) )
42 #define MAX_WAVOUTDRV 2
43 #define MAX_WAVINDRV 2
44 #define MAX_MCIWAVDRV 2
50 WAVEOPENDESC waveDesc
;
60 DWORD bufsize
; /* Linux '/dev/dsp' give us that size */
61 WAVEOPENDESC waveDesc
;
65 DWORD dwTotalRecorded
;
69 int nUseCount
; /* Incremented for each shared open */
70 BOOL fShareable
; /* TRUE if first open was shareable */
71 WORD wNotifyDeviceID
; /* MCI device ID with a pending notification */
72 HANDLE hCallback
; /* Callback handle for pending notification */
73 HMMIO16 hFile
; /* mmio file handle open as Element */
74 MCI_WAVE_OPEN_PARMS openParms
;
75 PCMWAVEFORMAT WaveFormat
;
79 static LINUX_WAVEOUT WOutDev
[MAX_WAVOUTDRV
];
80 static LINUX_WAVEIN WInDev
[MAX_WAVOUTDRV
];
81 static LINUX_MCIWAVE MCIWavDev
[MAX_MCIWAVDRV
];
84 /**************************************************************************
85 * WAVE_NotifyClient [internal]
87 static DWORD
WAVE_NotifyClient(UINT wDevID
, WORD wMsg
,
88 DWORD dwParam1
, DWORD dwParam2
)
90 if (WInDev
[wDevID
].wFlags
!= DCB_NULL
&& !DriverCallback(
91 WInDev
[wDevID
].waveDesc
.dwCallBack
, WInDev
[wDevID
].wFlags
,
92 WInDev
[wDevID
].waveDesc
.hWave
, wMsg
,
93 WInDev
[wDevID
].waveDesc
.dwInstance
, dwParam1
, dwParam2
)) {
94 dprintf_mciwave(stddeb
,"WAVE_NotifyClient // can't notify client !\n");
95 return MMSYSERR_NOERROR
;
101 /**************************************************************************
103 static DWORD
WAVE_mciOpen(UINT wDevID
, DWORD dwFlags
, LPMCI_WAVE_OPEN_PARMS lpParms
)
106 LPPCMWAVEFORMAT lpWaveFormat
;
108 LPWAVEOPENDESC lpDesc
;
109 LPSTR lpstrElementName
;
113 dprintf_mciwave(stddeb
,"WAVE_mciOpen(%04X, %08lX, %p)\n",
114 wDevID
, dwFlags
, lpParms
);
115 if (lpParms
== NULL
) return MCIERR_INTERNAL
;
116 dprintf_mciwave(stddeb
,"WAVE_mciOpen // wDevID=%04X\n", wDevID
);
117 if (MCIWavDev
[wDevID
].nUseCount
> 0) {
118 /* The driver already open on this channel */
119 /* If the driver was opened shareable before and this open specifies */
120 /* shareable then increment the use count */
121 if (MCIWavDev
[wDevID
].fShareable
&& (dwFlags
& MCI_OPEN_SHAREABLE
))
122 ++MCIWavDev
[wDevID
].nUseCount
;
124 return MCIERR_MUST_USE_SHAREABLE
;
127 MCIWavDev
[wDevID
].nUseCount
= 1;
128 MCIWavDev
[wDevID
].fShareable
= dwFlags
& MCI_OPEN_SHAREABLE
;
130 lpParms
->wDeviceID
= wDevID
;
131 dprintf_mciwave(stddeb
,"WAVE_mciOpen // wDevID=%04X\n", wDevID
);
132 dprintf_mciwave(stddeb
,"WAVE_mciOpen // before OPEN_ELEMENT\n");
133 if (dwFlags
& MCI_OPEN_ELEMENT
) {
134 lpstrElementName
= (LPSTR
)PTR_SEG_TO_LIN(lpParms
->lpstrElementName
);
135 dprintf_mciwave(stddeb
,"WAVE_mciOpen // MCI_OPEN_ELEMENT '%s' !\n",
137 if (strlen(lpstrElementName
) > 0) {
138 strcpy(str
, lpstrElementName
);
140 MCIWavDev
[wDevID
].hFile
= mmioOpen(str
, NULL
,
141 MMIO_ALLOCBUF
| MMIO_READWRITE
| MMIO_EXCLUSIVE
);
142 if (MCIWavDev
[wDevID
].hFile
== 0) {
143 dprintf_mciwave(stddeb
,"WAVE_mciOpen // can't find file='%s' !\n", str
);
144 return MCIERR_FILE_NOT_FOUND
;
148 MCIWavDev
[wDevID
].hFile
= 0;
150 dprintf_mciwave(stddeb
,"WAVE_mciOpen // hFile=%u\n", MCIWavDev
[wDevID
].hFile
);
151 memcpy(&MCIWavDev
[wDevID
].openParms
, lpParms
, sizeof(MCI_WAVE_OPEN_PARMS
));
152 MCIWavDev
[wDevID
].wNotifyDeviceID
= lpParms
->wDeviceID
;
153 lpWaveFormat
= &MCIWavDev
[wDevID
].WaveFormat
;
154 hDesc
= USER_HEAP_ALLOC(sizeof(WAVEOPENDESC
));
155 lpDesc
= (LPWAVEOPENDESC
) USER_HEAP_LIN_ADDR(hDesc
);
158 lpWaveFormat->wf.wFormatTag = WAVE_FORMAT_PCM;
159 lpWaveFormat->wBitsPerSample = 8;
160 lpWaveFormat->wf.nChannels = 1;
161 lpWaveFormat->wf.nSamplesPerSec = 11025;
162 lpWaveFormat->wf.nAvgBytesPerSec = 11025;
163 lpWaveFormat->wf.nBlockAlign = 1;
165 if (MCIWavDev
[wDevID
].hFile
!= 0) {
168 if (mmioDescend(MCIWavDev
[wDevID
].hFile
, &ckMainRIFF
, NULL
, 0) != 0) {
169 return MCIERR_INTERNAL
;
171 dprintf_mciwave(stddeb
,
172 "WAVE_mciOpen // ParentChunk ckid=%.4s fccType=%.4s cksize=%08lX \n",
173 (LPSTR
)&ckMainRIFF
.ckid
, (LPSTR
)&ckMainRIFF
.fccType
,
175 if ((ckMainRIFF
.ckid
!= FOURCC_RIFF
) ||
176 (ckMainRIFF
.fccType
!= mmioFOURCC('W', 'A', 'V', 'E'))) {
177 return MCIERR_INTERNAL
;
179 mmckInfo
.ckid
= mmioFOURCC('f', 'm', 't', ' ');
180 if (mmioDescend(MCIWavDev
[wDevID
].hFile
, &mmckInfo
, &ckMainRIFF
, MMIO_FINDCHUNK
) != 0) {
181 return MCIERR_INTERNAL
;
183 dprintf_mciwave(stddeb
,
184 "WAVE_mciOpen // Chunk Found ckid=%.4s fccType=%.4s cksize=%08lX \n",
185 (LPSTR
)&mmckInfo
.ckid
, (LPSTR
)&mmckInfo
.fccType
,
187 if (mmioRead(MCIWavDev
[wDevID
].hFile
, (HPSTR
) lpWaveFormat
,
188 (long) sizeof(PCMWAVEFORMAT
)) != (long) sizeof(PCMWAVEFORMAT
)) {
189 return MCIERR_INTERNAL
;
191 mmckInfo
.ckid
= mmioFOURCC('d', 'a', 't', 'a');
192 if (mmioDescend(MCIWavDev
[wDevID
].hFile
, &mmckInfo
, &ckMainRIFF
, MMIO_FINDCHUNK
) != 0) {
193 return MCIERR_INTERNAL
;
195 dprintf_mciwave(stddeb
,
196 "WAVE_mciOpen // Chunk Found ckid=%.4s fccType=%.4s cksize=%08lX \n",
197 (LPSTR
)&mmckInfo
.ckid
, (LPSTR
)&mmckInfo
.fccType
,
199 dprintf_mciwave(stddeb
,
200 "WAVE_mciOpen // nChannels=%d nSamplesPerSec=%ld\n",
201 lpWaveFormat
->wf
.nChannels
, lpWaveFormat
->wf
.nSamplesPerSec
);
202 lpWaveFormat
->wBitsPerSample
= 0;
204 lpWaveFormat
->wf
.nAvgBytesPerSec
=
205 lpWaveFormat
->wf
.nSamplesPerSec
* lpWaveFormat
->wf
.nBlockAlign
;
206 hFormat
= USER_HEAP_ALLOC(sizeof(PCMWAVEFORMAT
));
207 lpDesc
->lpFormat
= (LPWAVEFORMAT
) USER_HEAP_LIN_ADDR(hFormat
);
208 memcpy(lpDesc
->lpFormat
, lpWaveFormat
, sizeof(PCMWAVEFORMAT
));
209 lpDesc
= (LPWAVEOPENDESC
) USER_HEAP_SEG_ADDR(hDesc
);
210 dwRet
= wodMessage(0, WODM_OPEN
, 0, (DWORD
)lpDesc
, CALLBACK_NULL
);
211 dwRet
= widMessage(0, WIDM_OPEN
, 0, (DWORD
)lpDesc
, CALLBACK_NULL
);
212 USER_HEAP_FREE(hFormat
);
213 USER_HEAP_FREE(hDesc
);
217 /**************************************************************************
218 * WAVE_mciClose [internal]
220 static DWORD
WAVE_mciClose(UINT wDevID
, DWORD dwParam
, LPMCI_GENERIC_PARMS lpParms
)
223 dprintf_mciwave(stddeb
,
224 "WAVE_mciClose(%u, %08lX, %p);\n", wDevID
, dwParam
, lpParms
);
225 MCIWavDev
[wDevID
].nUseCount
--;
226 if (MCIWavDev
[wDevID
].nUseCount
== 0) {
227 if (MCIWavDev
[wDevID
].hFile
!= 0) {
228 mmioClose(MCIWavDev
[wDevID
].hFile
, 0);
229 MCIWavDev
[wDevID
].hFile
= 0;
231 dwRet
= wodMessage(0, WODM_CLOSE
, 0, 0L, 0L);
232 if (dwRet
!= MMSYSERR_NOERROR
) return MCIERR_INTERNAL
;
233 dwRet
= widMessage(0, WIDM_CLOSE
, 0, 0L, 0L);
234 if (dwRet
!= MMSYSERR_NOERROR
) return MCIERR_INTERNAL
;
240 /**************************************************************************
241 * WAVE_mciPlay [internal]
243 static DWORD
WAVE_mciPlay(UINT wDevID
, DWORD dwFlags
, LPMCI_PLAY_PARMS lpParms
)
250 LPWAVEHDR lp16WaveHdr
;
252 dprintf_mciwave(stddeb
,
253 "WAVE_mciPlay(%u, %08lX, %p);\n", wDevID
, dwFlags
, lpParms
);
254 if (MCIWavDev
[wDevID
].hFile
== 0) {
255 dprintf_mciwave(stddeb
,"WAVE_mciPlay // can't find file='%s' !\n",
256 MCIWavDev
[wDevID
].openParms
.lpstrElementName
);
257 return MCIERR_FILE_NOT_FOUND
;
259 start
= 1; end
= 99999;
260 if (dwFlags
& MCI_FROM
) {
261 start
= lpParms
->dwFrom
;
262 dprintf_mciwave(stddeb
,
263 "WAVE_mciPlay // MCI_FROM=%d \n", start
);
265 if (dwFlags
& MCI_TO
) {
267 dprintf_mciwave(stddeb
,"WAVE_mciPlay // MCI_TO=%d \n", end
);
270 if (dwFlags
& MCI_NOTIFY
) {
271 dprintf_mciwave(stddeb
,
272 "WAVE_mciPlay // MCI_NOTIFY %08lX !\n", lpParms
->dwCallback
);
275 dprintf_mciwave(stddeb
,
276 "WAVE_mciPlay // Can't 'fork' process !\n");
281 dprintf_mciwave(stddeb
,"WAVE_mciPlay // process started ! return to caller...\n");
287 lpWaveHdr
= &MCIWavDev
[wDevID
].WaveHdr
;
288 hData
= GlobalAlloc16(GMEM_MOVEABLE
, bufsize
);
289 lpWaveHdr
->lpData
= (LPSTR
) WIN16_GlobalLock16(hData
);
290 lpWaveHdr
->dwUser
= 0L;
291 lpWaveHdr
->dwFlags
= 0L;
292 lpWaveHdr
->dwLoops
= 0L;
293 hWaveHdr
= USER_HEAP_ALLOC(sizeof(WAVEHDR
));
294 lp16WaveHdr
= (LPWAVEHDR
) USER_HEAP_SEG_ADDR(hWaveHdr
);
295 memcpy(PTR_SEG_TO_LIN(lp16WaveHdr
), lpWaveHdr
, sizeof(WAVEHDR
));
296 lpWaveHdr
= PTR_SEG_TO_LIN(lp16WaveHdr
);
297 dwRet
= wodMessage(0, WODM_PREPARE
, 0, (DWORD
)lp16WaveHdr
, sizeof(WAVEHDR
));
299 count
= mmioRead(MCIWavDev
[wDevID
].hFile
,
300 PTR_SEG_TO_LIN(lpWaveHdr
->lpData
), bufsize
);
301 dprintf_mciwave(stddeb
,"WAVE_mciPlay // mmioRead bufsize=%ld count=%ld\n", bufsize
, count
);
302 if (count
< 1) break;
303 lpWaveHdr
->dwBufferLength
= count
;
304 /* lpWaveHdr->dwBytesRecorded = count; */
305 dprintf_mciwave(stddeb
,"WAVE_mciPlay // before WODM_WRITE lpWaveHdr=%p dwBufferLength=%lu dwBytesRecorded=%lu\n",
306 lpWaveHdr
, lpWaveHdr
->dwBufferLength
, lpWaveHdr
->dwBytesRecorded
);
307 dwRet
= wodMessage(0, WODM_WRITE
, 0, (DWORD
)lp16WaveHdr
, sizeof(WAVEHDR
));
309 dwRet
= wodMessage(0, WODM_UNPREPARE
, 0, (DWORD
)lp16WaveHdr
, sizeof(WAVEHDR
));
310 if (lpWaveHdr
->lpData
!= NULL
) {
311 GlobalUnlock16(hData
);
313 lpWaveHdr
->lpData
= NULL
;
315 USER_HEAP_FREE(hWaveHdr
);
316 if (dwFlags
& MCI_NOTIFY
) {
317 dprintf_mciwave(stddeb
,"WAVE_mciPlay // MCI_NOTIFY_SUCCESSFUL %08lX !\n", lpParms
->dwCallback
);
318 mciDriverNotify((HWND
)LOWORD(lpParms
->dwCallback
),
319 MCIWavDev
[wDevID
].wNotifyDeviceID
, MCI_NOTIFY_SUCCESSFUL
);
325 /**************************************************************************
326 * WAVE_mciRecord [internal]
328 static DWORD
WAVE_mciRecord(UINT wDevID
, DWORD dwFlags
, LPMCI_RECORD_PARMS lpParms
)
335 LPWAVEHDR lp16WaveHdr
;
338 dprintf_mciwave(stddeb
,
339 "WAVE_mciRecord(%u, %08lX, %p);\n", wDevID
, dwFlags
, lpParms
);
340 if (MCIWavDev
[wDevID
].hFile
== 0) {
341 dprintf_mciwave(stddeb
,"WAVE_mciRecord // can't find file='%s' !\n",
342 MCIWavDev
[wDevID
].openParms
.lpstrElementName
);
343 return MCIERR_FILE_NOT_FOUND
;
345 start
= 1; end
= 99999;
346 if (dwFlags
& MCI_FROM
) {
347 start
= lpParms
->dwFrom
;
348 dprintf_mciwave(stddeb
,
349 "WAVE_mciRecord // MCI_FROM=%d \n", start
);
351 if (dwFlags
& MCI_TO
) {
353 dprintf_mciwave(stddeb
,"WAVE_mciRecord // MCI_TO=%d \n", end
);
356 lpWaveHdr
= &MCIWavDev
[wDevID
].WaveHdr
;
357 hData
= GlobalAlloc16(GMEM_MOVEABLE
, bufsize
);
358 lpWaveHdr
->lpData
= (LPSTR
) WIN16_GlobalLock16(hData
);
359 lpWaveHdr
->dwBufferLength
= bufsize
;
360 lpWaveHdr
->dwUser
= 0L;
361 lpWaveHdr
->dwFlags
= 0L;
362 lpWaveHdr
->dwLoops
= 0L;
363 hWaveHdr
= USER_HEAP_ALLOC(sizeof(WAVEHDR
));
364 lp16WaveHdr
= (LPWAVEHDR
) USER_HEAP_SEG_ADDR(hWaveHdr
);
365 memcpy(PTR_SEG_TO_LIN(lp16WaveHdr
), lpWaveHdr
, sizeof(WAVEHDR
));
366 lpWaveHdr
= PTR_SEG_TO_LIN(lp16WaveHdr
);
367 dwRet
= widMessage(0, WIDM_PREPARE
, 0, (DWORD
)lp16WaveHdr
, sizeof(WAVEHDR
));
368 dprintf_mciwave(stddeb
,"WAVE_mciRecord // after WIDM_PREPARE \n");
370 lpWaveHdr
->dwBytesRecorded
= 0;
371 dwRet
= widMessage(0, WIDM_START
, 0, 0L, 0L);
372 dprintf_mciwave(stddeb
,
373 "WAVE_mciRecord // after WIDM_START lpWaveHdr=%p dwBytesRecorded=%lu\n",
374 lpWaveHdr
, lpWaveHdr
->dwBytesRecorded
);
375 if (lpWaveHdr
->dwBytesRecorded
== 0) break;
377 dprintf_mciwave(stddeb
,"WAVE_mciRecord // before WIDM_UNPREPARE \n");
378 dwRet
= widMessage(0, WIDM_UNPREPARE
, 0, (DWORD
)lp16WaveHdr
, sizeof(WAVEHDR
));
379 dprintf_mciwave(stddeb
,"WAVE_mciRecord // after WIDM_UNPREPARE \n");
380 if (lpWaveHdr
->lpData
!= NULL
) {
381 GlobalUnlock16(hData
);
383 lpWaveHdr
->lpData
= NULL
;
385 USER_HEAP_FREE(hWaveHdr
);
386 if (dwFlags
& MCI_NOTIFY
) {
387 dprintf_mciwave(stddeb
,"WAVE_mciRecord // MCI_NOTIFY_SUCCESSFUL %08lX !\n", lpParms
->dwCallback
);
388 mciDriverNotify((HWND
)LOWORD(lpParms
->dwCallback
),
389 MCIWavDev
[wDevID
].wNotifyDeviceID
, MCI_NOTIFY_SUCCESSFUL
);
395 /**************************************************************************
396 * WAVE_mciStop [internal]
398 static DWORD
WAVE_mciStop(UINT wDevID
, DWORD dwFlags
, LPMCI_GENERIC_PARMS lpParms
)
400 dprintf_mciwave(stddeb
,
401 "WAVE_mciStop(%u, %08lX, %p);\n", wDevID
, dwFlags
, lpParms
);
402 if (lpParms
== NULL
) return MCIERR_INTERNAL
;
407 /**************************************************************************
408 * WAVE_mciPause [internal]
410 static DWORD
WAVE_mciPause(UINT wDevID
, DWORD dwFlags
, LPMCI_GENERIC_PARMS lpParms
)
412 dprintf_mciwave(stddeb
,
413 "WAVE_mciPause(%u, %08lX, %p);\n", wDevID
, dwFlags
, lpParms
);
414 if (lpParms
== NULL
) return MCIERR_INTERNAL
;
419 /**************************************************************************
420 * WAVE_mciResume [internal]
422 static DWORD
WAVE_mciResume(UINT wDevID
, DWORD dwFlags
, LPMCI_GENERIC_PARMS lpParms
)
424 dprintf_mciwave(stddeb
,
425 "WAVE_mciResume(%u, %08lX, %p);\n", wDevID
, dwFlags
, lpParms
);
426 if (lpParms
== NULL
) return MCIERR_INTERNAL
;
431 /**************************************************************************
432 * WAVE_mciSet [internal]
434 static DWORD
WAVE_mciSet(UINT wDevID
, DWORD dwFlags
, LPMCI_SET_PARMS lpParms
)
436 dprintf_mciwave(stddeb
,
437 "WAVE_mciSet(%u, %08lX, %p);\n", wDevID
, dwFlags
, lpParms
);
438 if (lpParms
== NULL
) return MCIERR_INTERNAL
;
439 dprintf_mciwave(stddeb
,
440 "WAVE_mciSet // dwTimeFormat=%08lX\n", lpParms
->dwTimeFormat
);
441 dprintf_mciwave(stddeb
,
442 "WAVE_mciSet // dwAudio=%08lX\n", lpParms
->dwAudio
);
443 if (dwFlags
& MCI_SET_TIME_FORMAT
) {
444 switch (lpParms
->dwTimeFormat
) {
445 case MCI_FORMAT_MILLISECONDS
:
446 dprintf_mciwave(stddeb
, "WAVE_mciSet // MCI_FORMAT_MILLISECONDS !\n");
448 case MCI_FORMAT_BYTES
:
449 dprintf_mciwave(stddeb
, "WAVE_mciSet // MCI_FORMAT_BYTES !\n");
451 case MCI_FORMAT_SAMPLES
:
452 dprintf_mciwave(stddeb
, "WAVE_mciSet // MCI_FORMAT_SAMPLES !\n");
455 dprintf_mciwave(stddeb
, "WAVE_mciSet // bad time format !\n");
456 return MCIERR_BAD_TIME_FORMAT
;
459 if (dwFlags
& MCI_SET_VIDEO
) return MCIERR_UNSUPPORTED_FUNCTION
;
460 if (dwFlags
& MCI_SET_DOOR_OPEN
) return MCIERR_UNSUPPORTED_FUNCTION
;
461 if (dwFlags
& MCI_SET_DOOR_CLOSED
) return MCIERR_UNSUPPORTED_FUNCTION
;
462 if (dwFlags
& MCI_SET_AUDIO
)
463 dprintf_mciwave(stddeb
,"WAVE_mciSet // MCI_SET_AUDIO !\n");
464 if (dwFlags
&& MCI_SET_ON
) {
465 dprintf_mciwave(stddeb
,"WAVE_mciSet // MCI_SET_ON !\n");
466 if (dwFlags
&& MCI_SET_AUDIO_LEFT
)
467 dprintf_mciwave(stddeb
,"WAVE_mciSet // MCI_SET_AUDIO_LEFT !\n");
468 if (dwFlags
&& MCI_SET_AUDIO_RIGHT
)
469 dprintf_mciwave(stddeb
,"WAVE_mciSet // MCI_SET_AUDIO_RIGHT !\n");
471 if (dwFlags
& MCI_SET_OFF
)
472 dprintf_mciwave(stddeb
,"WAVE_mciSet // MCI_SET_OFF !\n");
473 if (dwFlags
& MCI_WAVE_INPUT
)
474 dprintf_mciwave(stddeb
,"WAVE_mciSet // MCI_WAVE_INPUT !\n");
475 if (dwFlags
& MCI_WAVE_OUTPUT
)
476 dprintf_mciwave(stddeb
,"WAVE_mciSet // MCI_WAVE_OUTPUT !\n");
477 if (dwFlags
& MCI_WAVE_SET_ANYINPUT
)
478 dprintf_mciwave(stddeb
,"WAVE_mciSet // MCI_WAVE_SET_ANYINPUT !\n");
479 if (dwFlags
& MCI_WAVE_SET_ANYOUTPUT
)
480 dprintf_mciwave(stddeb
,"WAVE_mciSet // MCI_WAVE_SET_ANYOUTPUT !\n");
481 if (dwFlags
& MCI_WAVE_SET_AVGBYTESPERSEC
)
482 dprintf_mciwave(stddeb
,
483 "WAVE_mciSet // MCI_WAVE_SET_AVGBYTESPERSEC !\n");
484 if (dwFlags
& MCI_WAVE_SET_BITSPERSAMPLE
)
485 dprintf_mciwave(stddeb
,
486 "WAVE_mciSet // MCI_WAVE_SET_BITSPERSAMPLE !\n");
487 if (dwFlags
& MCI_WAVE_SET_BLOCKALIGN
)
488 dprintf_mciwave(stddeb
,"WAVE_mciSet // MCI_WAVE_SET_BLOCKALIGN !\n");
489 if (dwFlags
& MCI_WAVE_SET_CHANNELS
)
490 dprintf_mciwave(stddeb
,"WAVE_mciSet // MCI_WAVE_SET_CHANNELS !\n");
491 if (dwFlags
& MCI_WAVE_SET_FORMATTAG
)
492 dprintf_mciwave(stddeb
,"WAVE_mciSet // MCI_WAVE_SET_FORMATTAG !\n");
493 if (dwFlags
& MCI_WAVE_SET_SAMPLESPERSEC
)
494 dprintf_mciwave(stddeb
,
495 "WAVE_mciSet // MCI_WAVE_SET_SAMPLESPERSEC !\n");
500 /**************************************************************************
501 * WAVE_mciStatus [internal]
503 static DWORD
WAVE_mciStatus(UINT wDevID
, DWORD dwFlags
, LPMCI_STATUS_PARMS lpParms
)
505 dprintf_mciwave(stddeb
,
506 "WAVE_mciStatus(%u, %08lX, %p);\n", wDevID
, dwFlags
, lpParms
);
507 if (lpParms
== NULL
) return MCIERR_INTERNAL
;
508 if (dwFlags
& MCI_STATUS_ITEM
) {
509 switch(lpParms
->dwItem
) {
510 case MCI_STATUS_CURRENT_TRACK
:
511 lpParms
->dwReturn
= 1;
513 case MCI_STATUS_LENGTH
:
514 lpParms
->dwReturn
= 5555;
515 if (dwFlags
& MCI_TRACK
) {
516 lpParms
->dwTrack
= 1;
517 lpParms
->dwReturn
= 2222;
520 case MCI_STATUS_MODE
:
521 lpParms
->dwReturn
= MCI_MODE_STOP
;
523 case MCI_STATUS_MEDIA_PRESENT
:
524 dprintf_mciwave(stddeb
,"WAVE_mciStatus // MCI_STATUS_MEDIA_PRESENT !\n");
525 lpParms
->dwReturn
= TRUE
;
527 case MCI_STATUS_NUMBER_OF_TRACKS
:
528 lpParms
->dwReturn
= 1;
530 case MCI_STATUS_POSITION
:
531 lpParms
->dwReturn
= 3333;
532 if (dwFlags
& MCI_STATUS_START
) {
535 if (dwFlags
& MCI_TRACK
) {
536 lpParms
->dwTrack
= 1;
537 lpParms
->dwReturn
= 777;
540 case MCI_STATUS_READY
:
541 dprintf_mciwave(stddeb
,"WAVE_mciStatus // MCI_STATUS_READY !\n");
542 lpParms
->dwReturn
= TRUE
;
544 case MCI_STATUS_TIME_FORMAT
:
545 dprintf_mciwave(stddeb
,"WAVE_mciStatus // MCI_STATUS_TIME_FORMAT !\n");
546 lpParms
->dwReturn
= MCI_FORMAT_MILLISECONDS
;
549 dprintf_mciwave(stddeb
,"WAVE_mciStatus // MCI_WAVE_INPUT !\n");
550 lpParms
->dwReturn
= 0;
552 case MCI_WAVE_OUTPUT
:
553 dprintf_mciwave(stddeb
,"WAVE_mciStatus // MCI_WAVE_OUTPUT !\n");
554 lpParms
->dwReturn
= 0;
556 case MCI_WAVE_STATUS_AVGBYTESPERSEC
:
557 dprintf_mciwave(stddeb
,"WAVE_mciStatus // MCI_WAVE_STATUS_AVGBYTESPERSEC !\n");
558 lpParms
->dwReturn
= 22050;
560 case MCI_WAVE_STATUS_BITSPERSAMPLE
:
561 dprintf_mciwave(stddeb
,"WAVE_mciStatus // MCI_WAVE_STATUS_BITSPERSAMPLE !\n");
562 lpParms
->dwReturn
= 8;
564 case MCI_WAVE_STATUS_BLOCKALIGN
:
565 dprintf_mciwave(stddeb
,"WAVE_mciStatus // MCI_WAVE_STATUS_BLOCKALIGN !\n");
566 lpParms
->dwReturn
= 1;
568 case MCI_WAVE_STATUS_CHANNELS
:
569 dprintf_mciwave(stddeb
,"WAVE_mciStatus // MCI_WAVE_STATUS_CHANNELS !\n");
570 lpParms
->dwReturn
= 1;
572 case MCI_WAVE_STATUS_FORMATTAG
:
573 dprintf_mciwave(stddeb
,"WAVE_mciStatus // MCI_WAVE_FORMATTAG !\n");
574 lpParms
->dwReturn
= WAVE_FORMAT_PCM
;
576 case MCI_WAVE_STATUS_LEVEL
:
577 dprintf_mciwave(stddeb
,"WAVE_mciStatus // MCI_WAVE_STATUS_LEVEL !\n");
578 lpParms
->dwReturn
= 0xAAAA5555;
580 case MCI_WAVE_STATUS_SAMPLESPERSEC
:
581 dprintf_mciwave(stddeb
,"WAVE_mciStatus // MCI_WAVE_STATUS_SAMPLESPERSEC !\n");
582 lpParms
->dwReturn
= 22050;
585 dprintf_mciwave(stddeb
,"WAVE_mciStatus // unknown command %08lX !\n", lpParms
->dwItem
);
586 return MCIERR_UNRECOGNIZED_COMMAND
;
589 if (dwFlags
& MCI_NOTIFY
) {
590 dprintf_mciwave(stddeb
,"WAVE_mciStatus // MCI_NOTIFY_SUCCESSFUL %08lX !\n", lpParms
->dwCallback
);
591 mciDriverNotify((HWND
)LOWORD(lpParms
->dwCallback
),
592 MCIWavDev
[wDevID
].wNotifyDeviceID
, MCI_NOTIFY_SUCCESSFUL
);
597 /**************************************************************************
598 * WAVE_mciGetDevCaps [internal]
600 static DWORD
WAVE_mciGetDevCaps(UINT wDevID
, DWORD dwFlags
,
601 LPMCI_GETDEVCAPS_PARMS lpParms
)
603 dprintf_mciwave(stddeb
,
604 "WAVE_mciGetDevCaps(%u, %08lX, %p);\n", wDevID
, dwFlags
, lpParms
);
605 if (lpParms
== NULL
) return MCIERR_INTERNAL
;
606 if (dwFlags
& MCI_GETDEVCAPS_ITEM
) {
607 switch(lpParms
->dwItem
) {
608 case MCI_GETDEVCAPS_CAN_RECORD
:
609 lpParms
->dwReturn
= TRUE
;
611 case MCI_GETDEVCAPS_HAS_AUDIO
:
612 lpParms
->dwReturn
= TRUE
;
614 case MCI_GETDEVCAPS_HAS_VIDEO
:
615 lpParms
->dwReturn
= FALSE
;
617 case MCI_GETDEVCAPS_DEVICE_TYPE
:
618 lpParms
->dwReturn
= MCI_DEVTYPE_WAVEFORM_AUDIO
;
620 case MCI_GETDEVCAPS_USES_FILES
:
621 lpParms
->dwReturn
= TRUE
;
623 case MCI_GETDEVCAPS_COMPOUND_DEVICE
:
624 lpParms
->dwReturn
= TRUE
;
626 case MCI_GETDEVCAPS_CAN_EJECT
:
627 lpParms
->dwReturn
= FALSE
;
629 case MCI_GETDEVCAPS_CAN_PLAY
:
630 lpParms
->dwReturn
= TRUE
;
632 case MCI_GETDEVCAPS_CAN_SAVE
:
633 lpParms
->dwReturn
= TRUE
;
635 case MCI_WAVE_GETDEVCAPS_INPUTS
:
636 lpParms
->dwReturn
= 1;
638 case MCI_WAVE_GETDEVCAPS_OUTPUTS
:
639 lpParms
->dwReturn
= 1;
642 return MCIERR_UNRECOGNIZED_COMMAND
;
648 /**************************************************************************
649 * WAVE_mciInfo [internal]
651 static DWORD
WAVE_mciInfo(UINT wDevID
, DWORD dwFlags
, LPMCI_INFO_PARMS lpParms
)
653 dprintf_mciwave(stddeb
,
654 "WAVE_mciInfo(%u, %08lX, %p);\n", wDevID
, dwFlags
, lpParms
);
655 if (lpParms
== NULL
) return MCIERR_INTERNAL
;
656 lpParms
->lpstrReturn
= NULL
;
658 case MCI_INFO_PRODUCT
:
659 lpParms
->lpstrReturn
= "Linux Sound System 0.5";
662 lpParms
->lpstrReturn
=
663 (LPSTR
)MCIWavDev
[wDevID
].openParms
.lpstrElementName
;
666 lpParms
->lpstrReturn
= "Linux Sound System 0.5";
668 case MCI_WAVE_OUTPUT
:
669 lpParms
->lpstrReturn
= "Linux Sound System 0.5";
672 return MCIERR_UNRECOGNIZED_COMMAND
;
674 if (lpParms
->lpstrReturn
!= NULL
)
675 lpParms
->dwRetSize
= strlen(lpParms
->lpstrReturn
);
677 lpParms
->dwRetSize
= 0;
682 /*-----------------------------------------------------------------------*/
685 /**************************************************************************
686 * wodGetDevCaps [internal]
688 static DWORD
wodGetDevCaps(WORD wDevID
, LPWAVEOUTCAPS lpCaps
, DWORD dwSize
)
695 dprintf_mciwave(stddeb
,
696 "wodGetDevCaps(%u, %p, %lu);\n", wDevID
, lpCaps
, dwSize
);
697 if (lpCaps
== NULL
) return MMSYSERR_NOTENABLED
;
698 audio
= open (SOUND_DEV
, O_WRONLY
, 0);
699 if (audio
== -1) return MMSYSERR_NOTENABLED
;
701 lpCaps
->wMid
= 0x0002;
702 lpCaps
->wPid
= 0x0104;
703 strcpy(lpCaps
->szPname
, "SB16 Wave Out");
705 lpCaps
->wMid
= 0x00FF; /* Manufac ID */
706 lpCaps
->wPid
= 0x0001; /* Product ID */
707 strcpy(lpCaps
->szPname
, "Linux WAVOUT Driver");
709 lpCaps
->dwFormats
= 0x00000000;
710 lpCaps
->dwSupport
= WAVECAPS_VOLUME
;
711 lpCaps
->wChannels
= (IOCTL(audio
, SNDCTL_DSP_STEREO
, dsp_stereo
) != 0) ? 1 : 2;
712 if (lpCaps
->wChannels
> 1) lpCaps
->dwSupport
|= WAVECAPS_LRVOLUME
;
713 bytespersmpl
= (IOCTL(audio
, SNDCTL_DSP_SAMPLESIZE
, samplesize
) != 0) ? 1 : 2;
715 if (IOCTL(audio
, SNDCTL_DSP_SPEED
, smplrate
) == 0) {
716 lpCaps
->dwFormats
|= WAVE_FORMAT_4M08
;
717 if (lpCaps
->wChannels
> 1) lpCaps
->dwFormats
|= WAVE_FORMAT_4S08
;
718 if (bytespersmpl
> 1) {
719 lpCaps
->dwFormats
|= WAVE_FORMAT_4M16
;
720 if (lpCaps
->wChannels
> 1) lpCaps
->dwFormats
|= WAVE_FORMAT_4S16
;
724 if (IOCTL(audio
, SNDCTL_DSP_SPEED
, smplrate
) == 0) {
725 lpCaps
->dwFormats
|= WAVE_FORMAT_2M08
;
726 if (lpCaps
->wChannels
> 1) lpCaps
->dwFormats
|= WAVE_FORMAT_2S08
;
727 if (bytespersmpl
> 1) {
728 lpCaps
->dwFormats
|= WAVE_FORMAT_2M16
;
729 if (lpCaps
->wChannels
> 1) lpCaps
->dwFormats
|= WAVE_FORMAT_2S16
;
733 if (IOCTL(audio
, SNDCTL_DSP_SPEED
, smplrate
) == 0) {
734 lpCaps
->dwFormats
|= WAVE_FORMAT_1M08
;
735 if (lpCaps
->wChannels
> 1) lpCaps
->dwFormats
|= WAVE_FORMAT_1S08
;
736 if (bytespersmpl
> 1) {
737 lpCaps
->dwFormats
|= WAVE_FORMAT_1M16
;
738 if (lpCaps
->wChannels
> 1) lpCaps
->dwFormats
|= WAVE_FORMAT_1S16
;
742 dprintf_mciwave(stddeb
,
743 "wodGetDevCaps // dwFormats = %08lX\n", lpCaps
->dwFormats
);
744 return MMSYSERR_NOERROR
;
748 /**************************************************************************
751 static DWORD
wodOpen(WORD wDevID
, LPWAVEOPENDESC lpDesc
, DWORD dwFlags
)
758 LPWAVEFORMAT lpFormat
;
760 dprintf_mciwave(stddeb
,
761 "wodOpen(%u, %p, %08lX);\n", wDevID
, lpDesc
, dwFlags
);
762 if (lpDesc
== NULL
) {
763 dprintf_mciwave(stddeb
,"Linux 'wodOpen' // Invalid Parameter !\n");
764 return MMSYSERR_INVALPARAM
;
766 if (wDevID
>= MAX_WAVOUTDRV
) {
767 dprintf_mciwave(stddeb
,"Linux 'wodOpen' // MAX_WAVOUTDRV reached !\n");
768 return MMSYSERR_ALLOCATED
;
770 WOutDev
[wDevID
].unixdev
= 0;
771 audio
= open (SOUND_DEV
, O_WRONLY
, 0);
773 dprintf_mciwave(stddeb
,"Linux 'wodOpen' // can't open !\n");
774 return MMSYSERR_NOTENABLED
;
776 IOCTL(audio
, SNDCTL_DSP_GETBLKSIZE
, abuf_size
);
777 if (abuf_size
< 4096 || abuf_size
> 65536) {
779 dprintf_mciwave(stddeb
,"Linux 'wodOpen' // IOCTL can't 'SNDCTL_DSP_GETBLKSIZE' !\n");
781 dprintf_mciwave(stddeb
,"Linux 'wodOpen' // SNDCTL_DSP_GETBLKSIZE Invalid bufsize !\n");
782 return MMSYSERR_NOTENABLED
;
784 WOutDev
[wDevID
].wFlags
= HIWORD(dwFlags
& CALLBACK_TYPEMASK
);
785 switch(WOutDev
[wDevID
].wFlags
) {
787 dprintf_mciwave(stddeb
, "Linux 'wodOpen' // CALLBACK_NULL !\n");
790 dprintf_mciwave(stddeb
, "Linux 'wodOpen' // CALLBACK_WINDOW !\n");
793 dprintf_mciwave(stddeb
, "Linux 'wodOpen' // CALLBACK_TASK !\n");
796 dprintf_mciwave(stddeb
, "Linux 'wodOpen' // CALLBACK_FUNCTION !\n");
799 WOutDev
[wDevID
].lpQueueHdr
= NULL
;
800 WOutDev
[wDevID
].unixdev
= audio
;
801 WOutDev
[wDevID
].dwTotalPlayed
= 0;
802 WOutDev
[wDevID
].bufsize
= abuf_size
;
803 memcpy(&WOutDev
[wDevID
].waveDesc
, lpDesc
, sizeof(WAVEOPENDESC
));
804 /* lpFormat = (LPWAVEFORMAT) PTR_SEG_TO_LIN(lpDesc->lpFormat); */
805 lpFormat
= lpDesc
->lpFormat
;
806 if (lpFormat
->wFormatTag
!= WAVE_FORMAT_PCM
) {
807 dprintf_mciwave(stddeb
,"Linux 'wodOpen' // Bad format %04X !\n",
808 lpFormat
->wFormatTag
);
809 dprintf_mciwave(stddeb
,"Linux 'wodOpen' // Bad nChannels %d !\n",
810 lpFormat
->nChannels
);
811 dprintf_mciwave(stddeb
,"Linux 'wodOpen' // Bad nSamplesPerSec %ld !\n",
812 lpFormat
->nSamplesPerSec
);
813 return WAVERR_BADFORMAT
;
815 memcpy(&WOutDev
[wDevID
].Format
, lpFormat
, sizeof(PCMWAVEFORMAT
));
816 if (WOutDev
[wDevID
].Format
.wf
.nChannels
== 0) return WAVERR_BADFORMAT
;
817 if (WOutDev
[wDevID
].Format
.wf
.nSamplesPerSec
== 0) return WAVERR_BADFORMAT
;
818 dprintf_mciwave(stddeb
,"Linux 'wodOpen' // wBitsPerSample=%u !\n",
819 WOutDev
[wDevID
].Format
.wBitsPerSample
);
820 if (WOutDev
[wDevID
].Format
.wBitsPerSample
== 0) {
821 WOutDev
[wDevID
].Format
.wBitsPerSample
= 8 *
822 (WOutDev
[wDevID
].Format
.wf
.nAvgBytesPerSec
/
823 WOutDev
[wDevID
].Format
.wf
.nSamplesPerSec
) /
824 WOutDev
[wDevID
].Format
.wf
.nChannels
;
826 samplesize
= WOutDev
[wDevID
].Format
.wBitsPerSample
;
827 smplrate
= WOutDev
[wDevID
].Format
.wf
.nSamplesPerSec
;
828 dsp_stereo
= (WOutDev
[wDevID
].Format
.wf
.nChannels
> 1) ? TRUE
: FALSE
;
829 IOCTL(audio
, SNDCTL_DSP_SPEED
, smplrate
);
830 IOCTL(audio
, SNDCTL_DSP_SAMPLESIZE
, samplesize
);
831 IOCTL(audio
, SNDCTL_DSP_STEREO
, dsp_stereo
);
832 dprintf_mciwave(stddeb
,"Linux 'wodOpen' // wBitsPerSample=%u !\n",
833 WOutDev
[wDevID
].Format
.wBitsPerSample
);
834 dprintf_mciwave(stddeb
,"Linux 'wodOpen' // nAvgBytesPerSec=%lu !\n",
835 WOutDev
[wDevID
].Format
.wf
.nAvgBytesPerSec
);
836 dprintf_mciwave(stddeb
,"Linux 'wodOpen' // nSamplesPerSec=%lu !\n",
837 WOutDev
[wDevID
].Format
.wf
.nSamplesPerSec
);
838 dprintf_mciwave(stddeb
,"Linux 'wodOpen' // nChannels=%u !\n",
839 WOutDev
[wDevID
].Format
.wf
.nChannels
);
840 if (WAVE_NotifyClient(wDevID
, WOM_OPEN
, 0L, 0L) != MMSYSERR_NOERROR
) {
841 dprintf_mciwave(stddeb
,"Linux 'wodOpen' // can't notify client !\n");
842 return MMSYSERR_INVALPARAM
;
844 return MMSYSERR_NOERROR
;
847 /**************************************************************************
848 * wodClose [internal]
850 static DWORD
wodClose(WORD wDevID
)
852 dprintf_mciwave(stddeb
,"wodClose(%u);\n", wDevID
);
853 if (WOutDev
[wDevID
].unixdev
== 0) {
854 dprintf_mciwave(stddeb
,"Linux 'wodClose' // can't close !\n");
855 return MMSYSERR_NOTENABLED
;
857 close(WOutDev
[wDevID
].unixdev
);
858 WOutDev
[wDevID
].unixdev
= 0;
859 WOutDev
[wDevID
].bufsize
= 0;
860 WOutDev
[wDevID
].lpQueueHdr
= NULL
;
861 if (WAVE_NotifyClient(wDevID
, WOM_CLOSE
, 0L, 0L) != MMSYSERR_NOERROR
) {
862 dprintf_mciwave(stddeb
,"Linux 'wodClose' // can't notify client !\n");
863 return MMSYSERR_INVALPARAM
;
865 return MMSYSERR_NOERROR
;
868 /**************************************************************************
869 * wodWrite [internal]
871 static DWORD
wodWrite(WORD wDevID
, LPWAVEHDR lpWaveHdr
, DWORD dwSize
)
875 dprintf_mciwave(stddeb
,"wodWrite(%u, %p, %08lX);\n", wDevID
, lpWaveHdr
, dwSize
);
876 if (WOutDev
[wDevID
].unixdev
== 0) {
877 dprintf_mciwave(stddeb
,"Linux 'wodWrite' // can't play !\n");
878 return MMSYSERR_NOTENABLED
;
880 if (lpWaveHdr
->lpData
== NULL
) return WAVERR_UNPREPARED
;
881 if (!(lpWaveHdr
->dwFlags
& WHDR_PREPARED
)) return WAVERR_UNPREPARED
;
882 if (lpWaveHdr
->dwFlags
& WHDR_INQUEUE
) return WAVERR_STILLPLAYING
;
883 lpWaveHdr
->dwFlags
&= ~WHDR_DONE
;
884 lpWaveHdr
->dwFlags
|= WHDR_INQUEUE
;
885 dprintf_mciwave(stddeb
,
886 "wodWrite() // dwBufferLength %lu !\n", lpWaveHdr
->dwBufferLength
);
887 dprintf_mciwave(stddeb
,
888 "wodWrite() // WOutDev[%u].unixdev %u !\n", wDevID
, WOutDev
[wDevID
].unixdev
);
889 lpData
= PTR_SEG_TO_LIN(lpWaveHdr
->lpData
);
890 count
= write (WOutDev
[wDevID
].unixdev
, lpData
, lpWaveHdr
->dwBufferLength
);
891 dprintf_mciwave(stddeb
,
892 "wodWrite() // write returned count %u !\n", count
);
893 if (count
!= lpWaveHdr
->dwBufferLength
) {
894 dprintf_mciwave(stddeb
,"Linux 'wodWrite' // error writting !\n");
895 return MMSYSERR_NOTENABLED
;
897 WOutDev
[wDevID
].dwTotalPlayed
+= count
;
898 lpWaveHdr
->dwFlags
&= ~WHDR_INQUEUE
;
899 lpWaveHdr
->dwFlags
|= WHDR_DONE
;
900 if (WAVE_NotifyClient(wDevID
, WOM_DONE
, 0L, 0L) != MMSYSERR_NOERROR
) {
901 dprintf_mciwave(stddeb
,"Linux 'wodWrite' // can't notify client !\n");
902 return MMSYSERR_INVALPARAM
;
904 return MMSYSERR_NOERROR
;
907 /**************************************************************************
908 * wodPrepare [internal]
910 static DWORD
wodPrepare(WORD wDevID
, LPWAVEHDR lpWaveHdr
, DWORD dwSize
)
912 dprintf_mciwave(stddeb
,
913 "wodPrepare(%u, %p, %08lX);\n", wDevID
, lpWaveHdr
, dwSize
);
914 if (WOutDev
[wDevID
].unixdev
== 0) {
915 dprintf_mciwave(stddeb
,"Linux 'wodPrepare' // can't prepare !\n");
916 return MMSYSERR_NOTENABLED
;
918 /* the COOL waveeditor feels much better without this check...
919 * someone please have a look at available documentation
920 if (WOutDev[wDevID].lpQueueHdr != NULL) {
921 dprintf_mciwave(stddeb,"Linux 'wodPrepare' // already prepare !\n");
922 return MMSYSERR_NOTENABLED;
925 WOutDev
[wDevID
].dwTotalPlayed
= 0;
926 WOutDev
[wDevID
].lpQueueHdr
= lpWaveHdr
;
927 if (lpWaveHdr
->dwFlags
& WHDR_INQUEUE
) return WAVERR_STILLPLAYING
;
928 lpWaveHdr
->dwFlags
|= WHDR_PREPARED
;
929 lpWaveHdr
->dwFlags
&= ~WHDR_DONE
;
930 return MMSYSERR_NOERROR
;
933 /**************************************************************************
934 * wodUnprepare [internal]
936 static DWORD
wodUnprepare(WORD wDevID
, LPWAVEHDR lpWaveHdr
, DWORD dwSize
)
938 dprintf_mciwave(stddeb
,
939 "wodUnprepare(%u, %p, %08lX);\n", wDevID
, lpWaveHdr
, dwSize
);
940 if (WOutDev
[wDevID
].unixdev
== 0) {
941 dprintf_mciwave(stddeb
,"Linux 'wodUnprepare' // can't unprepare !\n");
942 return MMSYSERR_NOTENABLED
;
944 return MMSYSERR_NOERROR
;
947 /**************************************************************************
948 * wodRestart [internal]
950 static DWORD
wodRestart(WORD wDevID
)
952 dprintf_mciwave(stddeb
,"wodRestart(%u);\n", wDevID
);
953 if (WOutDev
[wDevID
].unixdev
== 0) {
954 dprintf_mciwave(stddeb
,"Linux 'wodRestart' // can't restart !\n");
955 return MMSYSERR_NOTENABLED
;
957 return MMSYSERR_NOERROR
;
960 /**************************************************************************
961 * wodReset [internal]
963 static DWORD
wodReset(WORD wDevID
)
965 dprintf_mciwave(stddeb
,"wodReset(%u);\n", wDevID
);
966 if (WOutDev
[wDevID
].unixdev
== 0) {
967 dprintf_mciwave(stddeb
,"Linux 'wodReset' // can't reset !\n");
968 return MMSYSERR_NOTENABLED
;
970 return MMSYSERR_NOERROR
;
974 /**************************************************************************
975 * wodGetPosition [internal]
977 static DWORD
wodGetPosition(WORD wDevID
, LPMMTIME lpTime
, DWORD uSize
)
980 dprintf_mciwave(stddeb
,"wodGetPosition(%u, %p, %lu);\n", wDevID
, lpTime
, uSize
);
981 if (WOutDev
[wDevID
].unixdev
== 0) {
982 dprintf_mciwave(stddeb
,"Linux 'wodGetPosition' // can't get pos !\n");
983 return MMSYSERR_NOTENABLED
;
985 if (lpTime
== NULL
) return MMSYSERR_INVALPARAM
;
986 switch(lpTime
->wType
) {
988 lpTime
->u
.cb
= WOutDev
[wDevID
].dwTotalPlayed
;
989 dprintf_mciwave(stddeb
,"wodGetPosition // TIME_BYTES=%lu\n", lpTime
->u
.cb
);
992 dprintf_mciwave(stddeb
,"wodGetPosition // dwTotalPlayed=%lu\n",
993 WOutDev
[wDevID
].dwTotalPlayed
);
994 dprintf_mciwave(stddeb
,"wodGetPosition // wBitsPerSample=%u\n",
995 WOutDev
[wDevID
].Format
.wBitsPerSample
);
996 lpTime
->u
.sample
= WOutDev
[wDevID
].dwTotalPlayed
* 8 /
997 WOutDev
[wDevID
].Format
.wBitsPerSample
;
998 dprintf_mciwave(stddeb
,"wodGetPosition // TIME_SAMPLES=%lu\n", lpTime
->u
.sample
);
1001 time
= WOutDev
[wDevID
].dwTotalPlayed
/
1002 (WOutDev
[wDevID
].Format
.wf
.nAvgBytesPerSec
/ 1000);
1003 lpTime
->u
.smpte
.hour
= time
/ 108000;
1004 time
-= lpTime
->u
.smpte
.hour
* 108000;
1005 lpTime
->u
.smpte
.min
= time
/ 1800;
1006 time
-= lpTime
->u
.smpte
.min
* 1800;
1007 lpTime
->u
.smpte
.sec
= time
/ 30;
1008 time
-= lpTime
->u
.smpte
.sec
* 30;
1009 lpTime
->u
.smpte
.frame
= time
;
1010 lpTime
->u
.smpte
.fps
= 30;
1011 dprintf_mciwave(stddeb
,
1012 "wodGetPosition // TIME_SMPTE=%02u:%02u:%02u:%02u\n",
1013 lpTime
->u
.smpte
.hour
, lpTime
->u
.smpte
.min
,
1014 lpTime
->u
.smpte
.sec
, lpTime
->u
.smpte
.frame
);
1017 dprintf_mciwave(stddeb
,"wodGetPosition() format not supported ! use TIME_MS !\n");
1018 lpTime
->wType
= TIME_MS
;
1020 lpTime
->u
.ms
= WOutDev
[wDevID
].dwTotalPlayed
/
1021 (WOutDev
[wDevID
].Format
.wf
.nAvgBytesPerSec
/ 1000);
1022 dprintf_mciwave(stddeb
,"wodGetPosition // TIME_MS=%lu\n", lpTime
->u
.ms
);
1025 return MMSYSERR_NOERROR
;
1028 /**************************************************************************
1029 * wodGetVolume [internal]
1031 static DWORD
wodGetVolume(WORD wDevID
, LPDWORD lpdwVol
)
1034 int volume
, left
, right
;
1035 dprintf_mciwave(stddeb
,"wodGetVolume(%u, %p);\n", wDevID
, lpdwVol
);
1036 if (lpdwVol
== NULL
) return MMSYSERR_NOTENABLED
;
1037 if ((mixer
= open("/dev/mixer", O_RDONLY
)) < 0) {
1038 dprintf_mciwave(stddeb
, "Linux 'wodGetVolume' // mixer device not available !\n");
1039 return MMSYSERR_NOTENABLED
;
1041 if (ioctl(mixer
, SOUND_MIXER_READ_PCM
, &volume
) == -1) {
1042 dprintf_mciwave(stddeb
,"Linux 'wodGetVolume' // unable read mixer !\n");
1043 return MMSYSERR_NOTENABLED
;
1046 left
= volume
& 0x7F;
1047 right
= (volume
>> 8) & 0x7F;
1048 printf("Linux 'AUX_GetVolume' // left=%d right=%d !\n", left
, right
);
1049 *lpdwVol
= MAKELONG(left
<< 9, right
<< 9);
1050 return MMSYSERR_NOERROR
;
1054 /**************************************************************************
1055 * wodSetVolume [internal]
1057 static DWORD
wodSetVolume(WORD wDevID
, DWORD dwParam
)
1061 dprintf_mciwave(stddeb
,"wodSetVolume(%u, %08lX);\n", wDevID
, dwParam
);
1062 volume
= (LOWORD(dwParam
) >> 9 & 0x7F) +
1063 ((HIWORD(dwParam
) >> 9 & 0x7F) << 8);
1064 if ((mixer
= open("/dev/mixer", O_WRONLY
)) < 0) {
1065 dprintf_mciwave(stddeb
, "Linux 'wodSetVolume' // mixer device not available !\n");
1066 return MMSYSERR_NOTENABLED
;
1068 if (ioctl(mixer
, SOUND_MIXER_WRITE_PCM
, &volume
) == -1) {
1069 dprintf_mciwave(stddeb
,"Linux 'wodSetVolume' // unable set mixer !\n");
1070 return MMSYSERR_NOTENABLED
;
1073 return MMSYSERR_NOERROR
;
1078 /**************************************************************************
1079 * wodMessage [sample driver]
1081 DWORD
wodMessage(WORD wDevID
, WORD wMsg
, DWORD dwUser
,
1082 DWORD dwParam1
, DWORD dwParam2
)
1084 dprintf_mciwave(stddeb
,"wodMessage(%u, %04X, %08lX, %08lX, %08lX);\n",
1085 wDevID
, wMsg
, dwUser
, dwParam1
, dwParam2
);
1089 return wodOpen(wDevID
, (LPWAVEOPENDESC
)PTR_SEG_TO_LIN(dwParam1
), dwParam2
);
1091 return wodClose(wDevID
);
1093 return wodWrite(wDevID
, (LPWAVEHDR
)PTR_SEG_TO_LIN(dwParam1
), dwParam2
);
1097 return wodGetPosition(wDevID
, (LPMMTIME
)PTR_SEG_TO_LIN(dwParam1
), dwParam2
);
1098 case WODM_BREAKLOOP
:
1101 return wodPrepare(wDevID
, (LPWAVEHDR
)PTR_SEG_TO_LIN(dwParam1
), dwParam2
);
1102 case WODM_UNPREPARE
:
1103 return wodUnprepare(wDevID
, (LPWAVEHDR
)PTR_SEG_TO_LIN(dwParam1
), dwParam2
);
1104 case WODM_GETDEVCAPS
:
1105 return wodGetDevCaps(wDevID
, (LPWAVEOUTCAPS
)PTR_SEG_TO_LIN(dwParam1
), dwParam2
);
1106 case WODM_GETNUMDEVS
:
1112 case WODM_GETPLAYBACKRATE
:
1114 case WODM_SETPLAYBACKRATE
:
1116 case WODM_GETVOLUME
:
1117 return wodGetVolume(wDevID
, (LPDWORD
)PTR_SEG_TO_LIN(dwParam1
));
1118 case WODM_SETVOLUME
:
1119 return wodSetVolume(wDevID
, dwParam1
);
1121 return wodRestart(wDevID
);
1123 return wodReset(wDevID
);
1125 dprintf_mciwave(stddeb
,"wodMessage // unknown message !\n");
1127 return MMSYSERR_NOTSUPPORTED
;
1129 return MMSYSERR_NOTENABLED
;
1134 /*-----------------------------------------------------------------------*/
1138 /**************************************************************************
1139 * widGetDevCaps [internal]
1141 static DWORD
widGetDevCaps(WORD wDevID
, LPWAVEINCAPS lpCaps
, DWORD dwSize
)
1145 int samplesize
= 16;
1148 dprintf_mciwave(stddeb
,
1149 "widGetDevCaps(%u, %p, %lu);\n", wDevID
, lpCaps
, dwSize
);
1150 if (lpCaps
== NULL
) return MMSYSERR_NOTENABLED
;
1151 audio
= open (SOUND_DEV
, O_RDONLY
, 0);
1152 if (audio
== -1) return MMSYSERR_NOTENABLED
;
1154 lpCaps
->wMid
= 0x0002;
1155 lpCaps
->wPid
= 0x0004;
1156 strcpy(lpCaps
->szPname
, "SB16 Wave Out");
1158 lpCaps
->wMid
= 0x00FF; /* Manufac ID */
1159 lpCaps
->wPid
= 0x0001; /* Product ID */
1160 strcpy(lpCaps
->szPname
, "Linux WAVIN Driver");
1162 lpCaps
->dwFormats
= 0x00000000;
1163 lpCaps
->wChannels
= (IOCTL(audio
, SNDCTL_DSP_STEREO
, dsp_stereo
) != 0) ? 1 : 2;
1164 bytespersmpl
= (IOCTL(audio
, SNDCTL_DSP_SAMPLESIZE
, samplesize
) != 0) ? 1 : 2;
1166 if (IOCTL(audio
, SNDCTL_DSP_SPEED
, smplrate
) == 0) {
1167 lpCaps
->dwFormats
|= WAVE_FORMAT_4M08
;
1168 if (lpCaps
->wChannels
> 1) lpCaps
->dwFormats
|= WAVE_FORMAT_4S08
;
1169 if (bytespersmpl
> 1) {
1170 lpCaps
->dwFormats
|= WAVE_FORMAT_4M16
;
1171 if (lpCaps
->wChannels
> 1) lpCaps
->dwFormats
|= WAVE_FORMAT_4S16
;
1175 if (IOCTL(audio
, SNDCTL_DSP_SPEED
, smplrate
) == 0) {
1176 lpCaps
->dwFormats
|= WAVE_FORMAT_2M08
;
1177 if (lpCaps
->wChannels
> 1) lpCaps
->dwFormats
|= WAVE_FORMAT_2S08
;
1178 if (bytespersmpl
> 1) {
1179 lpCaps
->dwFormats
|= WAVE_FORMAT_2M16
;
1180 if (lpCaps
->wChannels
> 1) lpCaps
->dwFormats
|= WAVE_FORMAT_2S16
;
1184 if (IOCTL(audio
, SNDCTL_DSP_SPEED
, smplrate
) == 0) {
1185 lpCaps
->dwFormats
|= WAVE_FORMAT_1M08
;
1186 if (lpCaps
->wChannels
> 1) lpCaps
->dwFormats
|= WAVE_FORMAT_1S08
;
1187 if (bytespersmpl
> 1) {
1188 lpCaps
->dwFormats
|= WAVE_FORMAT_1M16
;
1189 if (lpCaps
->wChannels
> 1) lpCaps
->dwFormats
|= WAVE_FORMAT_1S16
;
1193 dprintf_mciwave(stddeb
,
1194 "widGetDevCaps // dwFormats = %08lX\n", lpCaps
->dwFormats
);
1195 return MMSYSERR_NOERROR
;
1199 /**************************************************************************
1200 * widOpen [internal]
1202 static DWORD
widOpen(WORD wDevID
, LPWAVEOPENDESC lpDesc
, DWORD dwFlags
)
1209 LPWAVEFORMAT lpFormat
;
1210 dprintf_mciwave(stddeb
, "widOpen(%u, %p, %08lX);\n", wDevID
, lpDesc
, dwFlags
);
1211 if (lpDesc
== NULL
) {
1212 dprintf_mciwave(stddeb
,"Linux 'widOpen' // Invalid Parameter !\n");
1213 return MMSYSERR_INVALPARAM
;
1215 if (wDevID
>= MAX_WAVINDRV
) {
1216 dprintf_mciwave(stddeb
,"Linux 'widOpen' // MAX_WAVINDRV reached !\n");
1217 return MMSYSERR_ALLOCATED
;
1219 WInDev
[wDevID
].unixdev
= 0;
1220 audio
= open (SOUND_DEV
, O_RDONLY
, 0);
1222 dprintf_mciwave(stddeb
,"Linux 'widOpen' // can't open !\n");
1223 return MMSYSERR_NOTENABLED
;
1225 IOCTL(audio
, SNDCTL_DSP_GETBLKSIZE
, abuf_size
);
1226 if (abuf_size
< 4096 || abuf_size
> 65536) {
1227 if (abuf_size
== -1)
1228 dprintf_mciwave(stddeb
,"Linux 'widOpen' // IOCTL can't 'SNDCTL_DSP_GETBLKSIZE' !\n");
1230 dprintf_mciwave(stddeb
,"Linux 'widOpen' // SNDCTL_DSP_GETBLKSIZE Invalid bufsize !\n");
1231 return MMSYSERR_NOTENABLED
;
1233 WInDev
[wDevID
].wFlags
= HIWORD(dwFlags
& CALLBACK_TYPEMASK
);
1234 switch(WInDev
[wDevID
].wFlags
) {
1236 dprintf_mciwave(stddeb
, "Linux 'widOpen' // CALLBACK_NULL !\n");
1239 dprintf_mciwave(stddeb
, "Linux 'widOpen' // CALLBACK_WINDOW !\n");
1242 dprintf_mciwave(stddeb
, "Linux 'widOpen' // CALLBACK_TASK !\n");
1245 dprintf_mciwave(stddeb
, "Linux 'widOpen' // CALLBACK_FUNCTION !\n");
1248 WInDev
[wDevID
].lpQueueHdr
= NULL
;
1249 WInDev
[wDevID
].unixdev
= audio
;
1250 WInDev
[wDevID
].bufsize
= abuf_size
;
1251 WInDev
[wDevID
].dwTotalRecorded
= 0;
1252 memcpy(&WInDev
[wDevID
].waveDesc
, lpDesc
, sizeof(WAVEOPENDESC
));
1253 lpFormat
= lpDesc
->lpFormat
;
1254 if (lpFormat
->wFormatTag
!= WAVE_FORMAT_PCM
) {
1255 dprintf_mciwave(stddeb
,"Linux 'widOpen' // Bad format %04X !\n",
1256 lpFormat
->wFormatTag
);
1257 return WAVERR_BADFORMAT
;
1259 memcpy(&WInDev
[wDevID
].Format
, lpFormat
, sizeof(PCMWAVEFORMAT
));
1260 WInDev
[wDevID
].Format
.wBitsPerSample
= 8; /* <-------------- */
1261 if (WInDev
[wDevID
].Format
.wf
.nChannels
== 0) return WAVERR_BADFORMAT
;
1262 if (WInDev
[wDevID
].Format
.wf
.nSamplesPerSec
== 0) return WAVERR_BADFORMAT
;
1263 if (WInDev
[wDevID
].Format
.wBitsPerSample
== 0) {
1264 WInDev
[wDevID
].Format
.wBitsPerSample
= 8 *
1265 (WInDev
[wDevID
].Format
.wf
.nAvgBytesPerSec
/
1266 WInDev
[wDevID
].Format
.wf
.nSamplesPerSec
) /
1267 WInDev
[wDevID
].Format
.wf
.nChannels
;
1269 samplesize
= WInDev
[wDevID
].Format
.wBitsPerSample
;
1270 smplrate
= WInDev
[wDevID
].Format
.wf
.nSamplesPerSec
;
1271 dsp_stereo
= (WInDev
[wDevID
].Format
.wf
.nChannels
> 1) ? TRUE
: FALSE
;
1272 IOCTL(audio
, SNDCTL_DSP_SPEED
, smplrate
);
1273 IOCTL(audio
, SNDCTL_DSP_SAMPLESIZE
, samplesize
);
1274 IOCTL(audio
, SNDCTL_DSP_STEREO
, dsp_stereo
);
1275 dprintf_mciwave(stddeb
,"Linux 'widOpen' // wBitsPerSample=%u !\n",
1276 WInDev
[wDevID
].Format
.wBitsPerSample
);
1277 dprintf_mciwave(stddeb
,"Linux 'widOpen' // nSamplesPerSec=%lu !\n",
1278 WInDev
[wDevID
].Format
.wf
.nSamplesPerSec
);
1279 dprintf_mciwave(stddeb
,"Linux 'widOpen' // nChannels=%u !\n",
1280 WInDev
[wDevID
].Format
.wf
.nChannels
);
1281 dprintf_mciwave(stddeb
,"Linux 'widOpen' // nAvgBytesPerSec=%lu\n",
1282 WInDev
[wDevID
].Format
.wf
.nAvgBytesPerSec
);
1283 if (WAVE_NotifyClient(wDevID
, WIM_OPEN
, 0L, 0L) != MMSYSERR_NOERROR
) {
1284 dprintf_mciwave(stddeb
,"Linux 'widOpen' // can't notify client !\n");
1285 return MMSYSERR_INVALPARAM
;
1287 return MMSYSERR_NOERROR
;
1290 /**************************************************************************
1291 * widClose [internal]
1293 static DWORD
widClose(WORD wDevID
)
1295 dprintf_mciwave(stddeb
,"widClose(%u);\n", wDevID
);
1296 if (WInDev
[wDevID
].unixdev
== 0) {
1297 dprintf_mciwave(stddeb
,"Linux 'widClose' // can't close !\n");
1298 return MMSYSERR_NOTENABLED
;
1300 close(WInDev
[wDevID
].unixdev
);
1301 WInDev
[wDevID
].unixdev
= 0;
1302 WInDev
[wDevID
].bufsize
= 0;
1303 if (WAVE_NotifyClient(wDevID
, WIM_CLOSE
, 0L, 0L) != MMSYSERR_NOERROR
) {
1304 dprintf_mciwave(stddeb
,"Linux 'widClose' // can't notify client !\n");
1305 return MMSYSERR_INVALPARAM
;
1307 return MMSYSERR_NOERROR
;
1310 /**************************************************************************
1311 * widAddBuffer [internal]
1313 static DWORD
widAddBuffer(WORD wDevID
, LPWAVEHDR lpWaveHdr
, DWORD dwSize
)
1317 dprintf_mciwave(stddeb
,
1318 "widAddBuffer(%u, %p, %08lX);\n", wDevID
, lpWaveHdr
, dwSize
);
1319 if (WInDev
[wDevID
].unixdev
== 0) {
1320 dprintf_mciwave(stddeb
,"Linux 'widAddBuffer' // can't do it !\n");
1321 return MMSYSERR_NOTENABLED
;
1323 if (!(lpWaveHdr
->dwFlags
& WHDR_PREPARED
)) {
1324 dprintf_mciwave(stddeb
, "Linux 'widAddBuffer' // never been prepared !\n");
1325 return WAVERR_UNPREPARED
;
1327 if (lpWaveHdr
->dwFlags
& WHDR_INQUEUE
) {
1328 dprintf_mciwave(stddeb
, "Linux 'widAddBuffer' // header already in use !\n");
1329 return WAVERR_STILLPLAYING
;
1331 lpWaveHdr
->dwFlags
|= WHDR_PREPARED
;
1332 lpWaveHdr
->dwFlags
|= WHDR_INQUEUE
;
1333 lpWaveHdr
->dwFlags
&= ~WHDR_DONE
;
1334 lpWaveHdr
->dwBytesRecorded
= 0;
1335 if (WInDev
[wDevID
].lpQueueHdr
== NULL
) {
1336 /* begin the queue with a first header ... */
1337 WInDev
[wDevID
].lpQueueHdr
= lpWaveHdr
;
1338 WInDev
[wDevID
].dwTotalRecorded
= 0;
1341 /* added to the queue, except if it's the one just prepared ... */
1342 lpWIHdr
= WInDev
[wDevID
].lpQueueHdr
;
1343 while (lpWIHdr
->lpNext
!= NULL
) {
1344 lpWIHdr
= lpWIHdr
->lpNext
;
1347 lpWIHdr
->lpNext
= lpWaveHdr
;
1350 dprintf_mciwave(stddeb
,
1351 "widAddBuffer // buffer added ! (now %u in queue)\n", count
);
1352 return MMSYSERR_NOERROR
;
1355 /**************************************************************************
1356 * widPrepare [internal]
1358 static DWORD
widPrepare(WORD wDevID
, LPWAVEHDR lpWaveHdr
, DWORD dwSize
)
1360 dprintf_mciwave(stddeb
,
1361 "widPrepare(%u, %p, %08lX);\n", wDevID
, lpWaveHdr
, dwSize
);
1362 if (WInDev
[wDevID
].unixdev
== 0) {
1363 dprintf_mciwave(stddeb
,"Linux 'widPrepare' // can't prepare !\n");
1364 return MMSYSERR_NOTENABLED
;
1366 if (WInDev
[wDevID
].lpQueueHdr
!= NULL
) {
1367 dprintf_mciwave(stddeb
,"Linux 'widPrepare' // already prepare !\n");
1368 return WAVERR_BADFORMAT
;
1370 if (lpWaveHdr
->dwFlags
& WHDR_INQUEUE
) return WAVERR_STILLPLAYING
;
1371 lpWaveHdr
->dwFlags
|= WHDR_PREPARED
;
1372 lpWaveHdr
->dwFlags
&= ~WHDR_INQUEUE
;
1373 lpWaveHdr
->dwFlags
&= ~WHDR_DONE
;
1374 lpWaveHdr
->dwBytesRecorded
= 0;
1375 dprintf_mciwave(stddeb
,"Linux 'widPrepare' // header prepared !\n");
1376 return MMSYSERR_NOERROR
;
1379 /**************************************************************************
1380 * widUnprepare [internal]
1382 static DWORD
widUnprepare(WORD wDevID
, LPWAVEHDR lpWaveHdr
, DWORD dwSize
)
1384 dprintf_mciwave(stddeb
,
1385 "widUnprepare(%u, %p, %08lX);\n", wDevID
, lpWaveHdr
, dwSize
);
1386 if (WInDev
[wDevID
].unixdev
== 0) {
1387 dprintf_mciwave(stddeb
,"Linux 'widUnprepare' // can't unprepare !\n");
1388 return MMSYSERR_NOTENABLED
;
1390 lpWaveHdr
->dwFlags
&= ~WHDR_PREPARED
;
1391 lpWaveHdr
->dwFlags
&= ~WHDR_INQUEUE
;
1392 lpWaveHdr
->dwFlags
|= WHDR_DONE
;
1393 WInDev
[wDevID
].lpQueueHdr
= NULL
;
1394 dprintf_mciwave(stddeb
,
1395 "Linux 'widUnprepare' // all headers unprepared !\n");
1396 return MMSYSERR_NOERROR
;
1399 /**************************************************************************
1400 * widStart [internal]
1402 static DWORD
widStart(WORD wDevID
)
1406 dprintf_mciwave(stddeb
,"widStart(%u);\n", wDevID
);
1407 if (WInDev
[wDevID
].unixdev
== 0) {
1408 dprintf_mciwave(stddeb
, "Linux 'widStart' // can't start recording !\n");
1409 return MMSYSERR_NOTENABLED
;
1411 if (WInDev
[wDevID
].lpQueueHdr
== NULL
||
1412 WInDev
[wDevID
].lpQueueHdr
->lpData
== NULL
) {
1413 dprintf_mciwave(stddeb
,"Linux 'widStart' // never been prepared !\n");
1414 return WAVERR_UNPREPARED
;
1416 lpWIHdr
= WInDev
[wDevID
].lpQueueHdr
;
1417 while(lpWIHdr
!= NULL
) {
1418 lpWIHdr
->dwBufferLength
&= 0xFFFF;
1419 dprintf_mciwave(stddeb
,
1420 "widStart // recording buf#%u=%p size=%lu \n",
1421 count
, lpWIHdr
->lpData
, lpWIHdr
->dwBufferLength
);
1423 read (WInDev
[wDevID
].unixdev
,
1424 PTR_SEG_TO_LIN(lpWIHdr
->lpData
),
1425 lpWIHdr
->dwBufferLength
);
1426 lpWIHdr
->dwBytesRecorded
= lpWIHdr
->dwBufferLength
;
1427 WInDev
[wDevID
].dwTotalRecorded
+= lpWIHdr
->dwBytesRecorded
;
1428 lpWIHdr
->dwFlags
&= ~WHDR_INQUEUE
;
1429 lpWIHdr
->dwFlags
|= WHDR_DONE
;
1430 if (WAVE_NotifyClient(wDevID
, WIM_DATA
, (DWORD
)lpWIHdr
, 0L) !=
1432 dprintf_mciwave(stddeb
, "Linux 'widStart' // can't notify client !\n");
1433 return MMSYSERR_INVALPARAM
;
1435 lpWIHdr
= lpWIHdr
->lpNext
;
1438 dprintf_mciwave(stddeb
,"widStart // end of recording !\n");
1440 return MMSYSERR_NOERROR
;
1443 /**************************************************************************
1444 * widStop [internal]
1446 static DWORD
widStop(WORD wDevID
)
1448 dprintf_mciwave(stddeb
,"widStop(%u);\n", wDevID
);
1449 if (WInDev
[wDevID
].unixdev
== 0) {
1450 dprintf_mciwave(stddeb
,"Linux 'widStop' // can't stop !\n");
1451 return MMSYSERR_NOTENABLED
;
1453 return MMSYSERR_NOERROR
;
1456 /**************************************************************************
1457 * widReset [internal]
1459 static DWORD
widReset(WORD wDevID
)
1461 dprintf_mciwave(stddeb
,"widReset(%u);\n", wDevID
);
1462 if (WInDev
[wDevID
].unixdev
== 0) {
1463 dprintf_mciwave(stddeb
,"Linux 'widReset' // can't reset !\n");
1464 return MMSYSERR_NOTENABLED
;
1466 return MMSYSERR_NOERROR
;
1469 /**************************************************************************
1470 * widGetPosition [internal]
1472 static DWORD
widGetPosition(WORD wDevID
, LPMMTIME lpTime
, DWORD uSize
)
1476 dprintf_mciwave(stddeb
,
1477 "widGetPosition(%u, %p, %lu);\n", wDevID
, lpTime
, uSize
);
1478 if (WInDev
[wDevID
].unixdev
== 0) {
1479 dprintf_mciwave(stddeb
,"Linux 'widGetPosition' // can't get pos !\n");
1480 return MMSYSERR_NOTENABLED
;
1482 if (lpTime
== NULL
) return MMSYSERR_INVALPARAM
;
1483 dprintf_mciwave(stddeb
,"widGetPosition // wType=%04X !\n",
1485 dprintf_mciwave(stddeb
,"widGetPosition // wBitsPerSample=%u\n",
1486 WInDev
[wDevID
].Format
.wBitsPerSample
);
1487 dprintf_mciwave(stddeb
,"widGetPosition // nSamplesPerSec=%lu\n",
1488 WInDev
[wDevID
].Format
.wf
.nSamplesPerSec
);
1489 dprintf_mciwave(stddeb
,"widGetPosition // nChannels=%u\n",
1490 WInDev
[wDevID
].Format
.wf
.nChannels
);
1491 dprintf_mciwave(stddeb
,"widGetPosition // nAvgBytesPerSec=%lu\n",
1492 WInDev
[wDevID
].Format
.wf
.nAvgBytesPerSec
);
1494 switch(lpTime
->wType
) {
1496 lpTime
->u
.cb
= WInDev
[wDevID
].dwTotalRecorded
;
1497 dprintf_mciwave(stddeb
,
1498 "widGetPosition // TIME_BYTES=%lu\n", lpTime
->u
.cb
);
1501 lpTime
->u
.sample
= WInDev
[wDevID
].dwTotalRecorded
* 8 /
1502 WInDev
[wDevID
].Format
.wBitsPerSample
;
1503 dprintf_mciwave(stddeb
,
1504 "widGetPosition // TIME_SAMPLES=%lu\n",
1508 time
= WInDev
[wDevID
].dwTotalRecorded
/
1509 (WInDev
[wDevID
].Format
.wf
.nAvgBytesPerSec
/ 1000);
1510 lpTime
->u
.smpte
.hour
= time
/ 108000;
1511 time
-= lpTime
->u
.smpte
.hour
* 108000;
1512 lpTime
->u
.smpte
.min
= time
/ 1800;
1513 time
-= lpTime
->u
.smpte
.min
* 1800;
1514 lpTime
->u
.smpte
.sec
= time
/ 30;
1515 time
-= lpTime
->u
.smpte
.sec
* 30;
1516 lpTime
->u
.smpte
.frame
= time
;
1517 lpTime
->u
.smpte
.fps
= 30;
1518 dprintf_mciwave(stddeb
,"widGetPosition // TIME_SMPTE=%02u:%02u:%02u:%02u\n",
1519 lpTime
->u
.smpte
.hour
, lpTime
->u
.smpte
.min
,
1520 lpTime
->u
.smpte
.sec
, lpTime
->u
.smpte
.frame
);
1523 dprintf_mciwave(stddeb
,"widGetPosition() format not supported ! use TIME_MS !\n");
1524 lpTime
->wType
= TIME_MS
;
1526 lpTime
->u
.ms
= WInDev
[wDevID
].dwTotalRecorded
/
1527 (WInDev
[wDevID
].Format
.wf
.nAvgBytesPerSec
/ 1000);
1528 dprintf_mciwave(stddeb
,
1529 "widGetPosition // TIME_MS=%lu\n", lpTime
->u
.ms
);
1532 return MMSYSERR_NOERROR
;
1537 /**************************************************************************
1538 * widMessage [sample driver]
1540 DWORD
widMessage(WORD wDevID
, WORD wMsg
, DWORD dwUser
,
1541 DWORD dwParam1
, DWORD dwParam2
)
1543 dprintf_mciwave(stddeb
,"widMessage(%u, %04X, %08lX, %08lX, %08lX);\n",
1544 wDevID
, wMsg
, dwUser
, dwParam1
, dwParam2
);
1548 return widOpen(wDevID
, (LPWAVEOPENDESC
)PTR_SEG_TO_LIN(dwParam1
), dwParam2
);
1550 return widClose(wDevID
);
1551 case WIDM_ADDBUFFER
:
1552 return widAddBuffer(wDevID
, (LPWAVEHDR
)PTR_SEG_TO_LIN(dwParam1
), dwParam2
);
1554 return widPrepare(wDevID
, (LPWAVEHDR
)PTR_SEG_TO_LIN(dwParam1
), dwParam2
);
1555 case WIDM_UNPREPARE
:
1556 return widUnprepare(wDevID
, (LPWAVEHDR
)PTR_SEG_TO_LIN(dwParam1
), dwParam2
);
1557 case WIDM_GETDEVCAPS
:
1558 return widGetDevCaps(wDevID
, (LPWAVEINCAPS
)PTR_SEG_TO_LIN(dwParam1
), dwParam2
);
1559 case WIDM_GETNUMDEVS
:
1562 return widGetPosition(wDevID
, (LPMMTIME
)PTR_SEG_TO_LIN(dwParam1
), dwParam2
);
1564 return widReset(wDevID
);
1566 return widStart(wDevID
);
1568 return widStop(wDevID
);
1570 dprintf_mciwave(stddeb
,"widMessage // unknown message !\n");
1572 return MMSYSERR_NOTSUPPORTED
;
1574 return MMSYSERR_NOTENABLED
;
1579 /**************************************************************************
1580 * AUDIO_DriverProc [sample driver]
1582 LONG
WAVE_DriverProc(DWORD dwDevID
, HDRVR16 hDriv
, WORD wMsg
,
1583 DWORD dwParam1
, DWORD dwParam2
)
1586 dprintf_mciwave(stddeb
,"WAVE_DriverProc(%08lX, %04X, %04X, %08lX, %08lX)\n",
1587 dwDevID
, hDriv
, wMsg
, dwParam1
, dwParam2
);
1601 case DRV_QUERYCONFIGURE
:
1604 MessageBox((HWND
)NULL
, "Sample MultiMedia Linux Driver !",
1605 "MMLinux Driver", MB_OK
);
1608 return DRVCNF_RESTART
;
1610 return DRVCNF_RESTART
;
1611 case MCI_OPEN_DRIVER
:
1613 return WAVE_mciOpen(dwDevID
, dwParam1
, (LPMCI_WAVE_OPEN_PARMS
)PTR_SEG_TO_LIN(dwParam2
));
1614 case MCI_CLOSE_DRIVER
:
1616 return WAVE_mciClose(dwDevID
, dwParam1
, (LPMCI_GENERIC_PARMS
)PTR_SEG_TO_LIN(dwParam2
));
1618 return WAVE_mciPlay(dwDevID
, dwParam1
, (LPMCI_PLAY_PARMS
)PTR_SEG_TO_LIN(dwParam2
));
1620 return WAVE_mciRecord(dwDevID
, dwParam1
, (LPMCI_RECORD_PARMS
)PTR_SEG_TO_LIN(dwParam2
));
1622 return WAVE_mciStop(dwDevID
, dwParam1
, (LPMCI_GENERIC_PARMS
)PTR_SEG_TO_LIN(dwParam2
));
1624 return WAVE_mciSet(dwDevID
, dwParam1
, (LPMCI_SET_PARMS
)PTR_SEG_TO_LIN(dwParam2
));
1626 return WAVE_mciPause(dwDevID
, dwParam1
, (LPMCI_GENERIC_PARMS
)PTR_SEG_TO_LIN(dwParam2
));
1628 return WAVE_mciResume(dwDevID
, dwParam1
, (LPMCI_GENERIC_PARMS
)PTR_SEG_TO_LIN(dwParam2
));
1630 return WAVE_mciStatus(dwDevID
, dwParam1
, (LPMCI_STATUS_PARMS
)PTR_SEG_TO_LIN(dwParam2
));
1631 case MCI_GETDEVCAPS
:
1632 return WAVE_mciGetDevCaps(dwDevID
, dwParam1
, (LPMCI_GETDEVCAPS_PARMS
)PTR_SEG_TO_LIN(dwParam2
));
1634 return WAVE_mciInfo(dwDevID
, dwParam1
, (LPMCI_INFO_PARMS
)PTR_SEG_TO_LIN(dwParam2
));
1636 return DefDriverProc(dwDevID
, hDriv
, wMsg
, dwParam1
, dwParam2
);
1639 return MMSYSERR_NOTENABLED
;
1644 #endif /* #ifdef BUILTIN_MMSYSTEM */