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>
29 #include <machine/soundcard.h>
35 #if defined(linux) || defined(__FreeBSD__)
36 #define SOUND_DEV "/dev/dsp"
39 #define IOCTL(a,b,c) ((-1==ioctl(a,b,&c))&&(perror("ioctl:"#b":"#c),0))
41 #define IOCTL(a,b,c) (c = ioctl(a,b,c) )
44 #define MAX_WAVOUTDRV 2
45 #define MAX_WAVINDRV 2
46 #define MAX_MCIWAVDRV 2
52 WAVEOPENDESC waveDesc
;
62 DWORD bufsize
; /* Linux '/dev/dsp' give us that size */
63 WAVEOPENDESC waveDesc
;
67 DWORD dwTotalRecorded
;
71 int nUseCount
; /* Incremented for each shared open */
72 BOOL fShareable
; /* TRUE if first open was shareable */
73 WORD wNotifyDeviceID
; /* MCI device ID with a pending notification */
74 HANDLE16 hCallback
; /* Callback handle for pending notification */
75 HMMIO16 hFile
; /* mmio file handle open as Element */
76 MCI_WAVE_OPEN_PARMS openParms
;
77 PCMWAVEFORMAT WaveFormat
;
81 static LINUX_WAVEOUT WOutDev
[MAX_WAVOUTDRV
];
82 static LINUX_WAVEIN WInDev
[MAX_WAVOUTDRV
];
83 static LINUX_MCIWAVE MCIWavDev
[MAX_MCIWAVDRV
];
86 /**************************************************************************
87 * WAVE_NotifyClient [internal]
89 static DWORD
WAVE_NotifyClient(UINT wDevID
, WORD wMsg
,
90 DWORD dwParam1
, DWORD dwParam2
)
92 if (WInDev
[wDevID
].wFlags
!= DCB_NULL
&& !DriverCallback(
93 WInDev
[wDevID
].waveDesc
.dwCallBack
, WInDev
[wDevID
].wFlags
,
94 WInDev
[wDevID
].waveDesc
.hWave
, wMsg
,
95 WInDev
[wDevID
].waveDesc
.dwInstance
, dwParam1
, dwParam2
)) {
96 dprintf_mciwave(stddeb
,"WAVE_NotifyClient // can't notify client !\n");
97 return MMSYSERR_NOERROR
;
103 /**************************************************************************
105 static DWORD
WAVE_mciOpen(UINT wDevID
, DWORD dwFlags
, LPMCI_WAVE_OPEN_PARMS lpParms
)
108 LPPCMWAVEFORMAT lpWaveFormat
;
110 LPWAVEOPENDESC lpDesc
;
111 LPSTR lpstrElementName
;
115 dprintf_mciwave(stddeb
,"WAVE_mciOpen(%04X, %08lX, %p)\n",
116 wDevID
, dwFlags
, lpParms
);
117 if (lpParms
== NULL
) return MCIERR_INTERNAL
;
118 dprintf_mciwave(stddeb
,"WAVE_mciOpen // wDevID=%04X\n", wDevID
);
119 if (MCIWavDev
[wDevID
].nUseCount
> 0) {
120 /* The driver already open on this channel */
121 /* If the driver was opened shareable before and this open specifies */
122 /* shareable then increment the use count */
123 if (MCIWavDev
[wDevID
].fShareable
&& (dwFlags
& MCI_OPEN_SHAREABLE
))
124 ++MCIWavDev
[wDevID
].nUseCount
;
126 return MCIERR_MUST_USE_SHAREABLE
;
129 MCIWavDev
[wDevID
].nUseCount
= 1;
130 MCIWavDev
[wDevID
].fShareable
= dwFlags
& MCI_OPEN_SHAREABLE
;
132 lpParms
->wDeviceID
= wDevID
;
133 dprintf_mciwave(stddeb
,"WAVE_mciOpen // wDevID=%04X\n", wDevID
);
134 dprintf_mciwave(stddeb
,"WAVE_mciOpen // before OPEN_ELEMENT\n");
135 if (dwFlags
& MCI_OPEN_ELEMENT
) {
136 lpstrElementName
= (LPSTR
)PTR_SEG_TO_LIN(lpParms
->lpstrElementName
);
137 dprintf_mciwave(stddeb
,"WAVE_mciOpen // MCI_OPEN_ELEMENT '%s' !\n",
139 if (strlen(lpstrElementName
) > 0) {
140 strcpy(str
, lpstrElementName
);
142 MCIWavDev
[wDevID
].hFile
= mmioOpen(str
, NULL
,
143 MMIO_ALLOCBUF
| MMIO_READWRITE
| MMIO_EXCLUSIVE
);
144 if (MCIWavDev
[wDevID
].hFile
== 0) {
145 dprintf_mciwave(stddeb
,"WAVE_mciOpen // can't find file='%s' !\n", str
);
146 return MCIERR_FILE_NOT_FOUND
;
150 MCIWavDev
[wDevID
].hFile
= 0;
152 dprintf_mciwave(stddeb
,"WAVE_mciOpen // hFile=%u\n", MCIWavDev
[wDevID
].hFile
);
153 memcpy(&MCIWavDev
[wDevID
].openParms
, lpParms
, sizeof(MCI_WAVE_OPEN_PARMS
));
154 MCIWavDev
[wDevID
].wNotifyDeviceID
= lpParms
->wDeviceID
;
155 lpWaveFormat
= &MCIWavDev
[wDevID
].WaveFormat
;
156 hDesc
= USER_HEAP_ALLOC(sizeof(WAVEOPENDESC
));
157 lpDesc
= (LPWAVEOPENDESC
) USER_HEAP_LIN_ADDR(hDesc
);
160 lpWaveFormat->wf.wFormatTag = WAVE_FORMAT_PCM;
161 lpWaveFormat->wBitsPerSample = 8;
162 lpWaveFormat->wf.nChannels = 1;
163 lpWaveFormat->wf.nSamplesPerSec = 11025;
164 lpWaveFormat->wf.nAvgBytesPerSec = 11025;
165 lpWaveFormat->wf.nBlockAlign = 1;
167 if (MCIWavDev
[wDevID
].hFile
!= 0) {
170 if (mmioDescend(MCIWavDev
[wDevID
].hFile
, &ckMainRIFF
, NULL
, 0) != 0) {
171 return MCIERR_INTERNAL
;
173 dprintf_mciwave(stddeb
,
174 "WAVE_mciOpen // ParentChunk ckid=%.4s fccType=%.4s cksize=%08lX \n",
175 (LPSTR
)&ckMainRIFF
.ckid
, (LPSTR
)&ckMainRIFF
.fccType
,
177 if ((ckMainRIFF
.ckid
!= FOURCC_RIFF
) ||
178 (ckMainRIFF
.fccType
!= mmioFOURCC('W', 'A', 'V', 'E'))) {
179 return MCIERR_INTERNAL
;
181 mmckInfo
.ckid
= mmioFOURCC('f', 'm', 't', ' ');
182 if (mmioDescend(MCIWavDev
[wDevID
].hFile
, &mmckInfo
, &ckMainRIFF
, MMIO_FINDCHUNK
) != 0) {
183 return MCIERR_INTERNAL
;
185 dprintf_mciwave(stddeb
,
186 "WAVE_mciOpen // Chunk Found ckid=%.4s fccType=%.4s cksize=%08lX \n",
187 (LPSTR
)&mmckInfo
.ckid
, (LPSTR
)&mmckInfo
.fccType
,
189 if (mmioRead(MCIWavDev
[wDevID
].hFile
, (HPSTR
) lpWaveFormat
,
190 (long) sizeof(PCMWAVEFORMAT
)) != (long) sizeof(PCMWAVEFORMAT
)) {
191 return MCIERR_INTERNAL
;
193 mmckInfo
.ckid
= mmioFOURCC('d', 'a', 't', 'a');
194 if (mmioDescend(MCIWavDev
[wDevID
].hFile
, &mmckInfo
, &ckMainRIFF
, MMIO_FINDCHUNK
) != 0) {
195 return MCIERR_INTERNAL
;
197 dprintf_mciwave(stddeb
,
198 "WAVE_mciOpen // Chunk Found ckid=%.4s fccType=%.4s cksize=%08lX \n",
199 (LPSTR
)&mmckInfo
.ckid
, (LPSTR
)&mmckInfo
.fccType
,
201 dprintf_mciwave(stddeb
,
202 "WAVE_mciOpen // nChannels=%d nSamplesPerSec=%ld\n",
203 lpWaveFormat
->wf
.nChannels
, lpWaveFormat
->wf
.nSamplesPerSec
);
204 lpWaveFormat
->wBitsPerSample
= 0;
206 lpWaveFormat
->wf
.nAvgBytesPerSec
=
207 lpWaveFormat
->wf
.nSamplesPerSec
* lpWaveFormat
->wf
.nBlockAlign
;
208 hFormat
= USER_HEAP_ALLOC(sizeof(PCMWAVEFORMAT
));
209 lpDesc
->lpFormat
= (LPWAVEFORMAT
) USER_HEAP_LIN_ADDR(hFormat
);
210 memcpy(lpDesc
->lpFormat
, lpWaveFormat
, sizeof(PCMWAVEFORMAT
));
211 lpDesc
= (LPWAVEOPENDESC
) USER_HEAP_SEG_ADDR(hDesc
);
212 dwRet
= wodMessage(0, WODM_OPEN
, 0, (DWORD
)lpDesc
, CALLBACK_NULL
);
213 dwRet
= widMessage(0, WIDM_OPEN
, 0, (DWORD
)lpDesc
, CALLBACK_NULL
);
214 USER_HEAP_FREE(hFormat
);
215 USER_HEAP_FREE(hDesc
);
219 /**************************************************************************
220 * WAVE_mciClose [internal]
222 static DWORD
WAVE_mciClose(UINT wDevID
, DWORD dwParam
, LPMCI_GENERIC_PARMS lpParms
)
225 dprintf_mciwave(stddeb
,
226 "WAVE_mciClose(%u, %08lX, %p);\n", wDevID
, dwParam
, lpParms
);
227 MCIWavDev
[wDevID
].nUseCount
--;
228 if (MCIWavDev
[wDevID
].nUseCount
== 0) {
229 if (MCIWavDev
[wDevID
].hFile
!= 0) {
230 mmioClose(MCIWavDev
[wDevID
].hFile
, 0);
231 MCIWavDev
[wDevID
].hFile
= 0;
233 dwRet
= wodMessage(0, WODM_CLOSE
, 0, 0L, 0L);
234 if (dwRet
!= MMSYSERR_NOERROR
) return MCIERR_INTERNAL
;
235 dwRet
= widMessage(0, WIDM_CLOSE
, 0, 0L, 0L);
236 if (dwRet
!= MMSYSERR_NOERROR
) return MCIERR_INTERNAL
;
242 /**************************************************************************
243 * WAVE_mciPlay [internal]
245 static DWORD
WAVE_mciPlay(UINT wDevID
, DWORD dwFlags
, LPMCI_PLAY_PARMS lpParms
)
252 LPWAVEHDR lp16WaveHdr
;
254 dprintf_mciwave(stddeb
,
255 "WAVE_mciPlay(%u, %08lX, %p);\n", wDevID
, dwFlags
, lpParms
);
256 if (MCIWavDev
[wDevID
].hFile
== 0) {
257 dprintf_mciwave(stddeb
,"WAVE_mciPlay // can't find file='%s' !\n",
258 MCIWavDev
[wDevID
].openParms
.lpstrElementName
);
259 return MCIERR_FILE_NOT_FOUND
;
261 start
= 1; end
= 99999;
262 if (dwFlags
& MCI_FROM
) {
263 start
= lpParms
->dwFrom
;
264 dprintf_mciwave(stddeb
,
265 "WAVE_mciPlay // MCI_FROM=%d \n", start
);
267 if (dwFlags
& MCI_TO
) {
269 dprintf_mciwave(stddeb
,"WAVE_mciPlay // MCI_TO=%d \n", end
);
272 if (dwFlags
& MCI_NOTIFY
) {
273 dprintf_mciwave(stddeb
,
274 "WAVE_mciPlay // MCI_NOTIFY %08lX !\n", lpParms
->dwCallback
);
277 dprintf_mciwave(stddeb
,
278 "WAVE_mciPlay // Can't 'fork' process !\n");
283 dprintf_mciwave(stddeb
,"WAVE_mciPlay // process started ! return to caller...\n");
289 lpWaveHdr
= &MCIWavDev
[wDevID
].WaveHdr
;
290 hData
= GlobalAlloc16(GMEM_MOVEABLE
, bufsize
);
291 lpWaveHdr
->lpData
= (LPSTR
) WIN16_GlobalLock16(hData
);
292 lpWaveHdr
->dwUser
= 0L;
293 lpWaveHdr
->dwFlags
= 0L;
294 lpWaveHdr
->dwLoops
= 0L;
295 hWaveHdr
= USER_HEAP_ALLOC(sizeof(WAVEHDR
));
296 lp16WaveHdr
= (LPWAVEHDR
) USER_HEAP_SEG_ADDR(hWaveHdr
);
297 memcpy(PTR_SEG_TO_LIN(lp16WaveHdr
), lpWaveHdr
, sizeof(WAVEHDR
));
298 lpWaveHdr
= PTR_SEG_TO_LIN(lp16WaveHdr
);
299 dwRet
= wodMessage(0, WODM_PREPARE
, 0, (DWORD
)lp16WaveHdr
, sizeof(WAVEHDR
));
301 count
= mmioRead(MCIWavDev
[wDevID
].hFile
,
302 PTR_SEG_TO_LIN(lpWaveHdr
->lpData
), bufsize
);
303 dprintf_mciwave(stddeb
,"WAVE_mciPlay // mmioRead bufsize=%ld count=%ld\n", bufsize
, count
);
304 if (count
< 1) break;
305 lpWaveHdr
->dwBufferLength
= count
;
306 /* lpWaveHdr->dwBytesRecorded = count; */
307 dprintf_mciwave(stddeb
,"WAVE_mciPlay // before WODM_WRITE lpWaveHdr=%p dwBufferLength=%lu dwBytesRecorded=%lu\n",
308 lpWaveHdr
, lpWaveHdr
->dwBufferLength
, lpWaveHdr
->dwBytesRecorded
);
309 dwRet
= wodMessage(0, WODM_WRITE
, 0, (DWORD
)lp16WaveHdr
, sizeof(WAVEHDR
));
311 dwRet
= wodMessage(0, WODM_UNPREPARE
, 0, (DWORD
)lp16WaveHdr
, sizeof(WAVEHDR
));
312 if (lpWaveHdr
->lpData
!= NULL
) {
313 GlobalUnlock16(hData
);
315 lpWaveHdr
->lpData
= NULL
;
317 USER_HEAP_FREE(hWaveHdr
);
318 if (dwFlags
& MCI_NOTIFY
) {
319 dprintf_mciwave(stddeb
,"WAVE_mciPlay // MCI_NOTIFY_SUCCESSFUL %08lX !\n", lpParms
->dwCallback
);
320 mciDriverNotify((HWND
)LOWORD(lpParms
->dwCallback
),
321 MCIWavDev
[wDevID
].wNotifyDeviceID
, MCI_NOTIFY_SUCCESSFUL
);
327 /**************************************************************************
328 * WAVE_mciRecord [internal]
330 static DWORD
WAVE_mciRecord(UINT wDevID
, DWORD dwFlags
, LPMCI_RECORD_PARMS lpParms
)
337 LPWAVEHDR lp16WaveHdr
;
340 dprintf_mciwave(stddeb
,
341 "WAVE_mciRecord(%u, %08lX, %p);\n", wDevID
, dwFlags
, lpParms
);
342 if (MCIWavDev
[wDevID
].hFile
== 0) {
343 dprintf_mciwave(stddeb
,"WAVE_mciRecord // can't find file='%s' !\n",
344 MCIWavDev
[wDevID
].openParms
.lpstrElementName
);
345 return MCIERR_FILE_NOT_FOUND
;
347 start
= 1; end
= 99999;
348 if (dwFlags
& MCI_FROM
) {
349 start
= lpParms
->dwFrom
;
350 dprintf_mciwave(stddeb
,
351 "WAVE_mciRecord // MCI_FROM=%d \n", start
);
353 if (dwFlags
& MCI_TO
) {
355 dprintf_mciwave(stddeb
,"WAVE_mciRecord // MCI_TO=%d \n", end
);
358 lpWaveHdr
= &MCIWavDev
[wDevID
].WaveHdr
;
359 hData
= GlobalAlloc16(GMEM_MOVEABLE
, bufsize
);
360 lpWaveHdr
->lpData
= (LPSTR
) WIN16_GlobalLock16(hData
);
361 lpWaveHdr
->dwBufferLength
= bufsize
;
362 lpWaveHdr
->dwUser
= 0L;
363 lpWaveHdr
->dwFlags
= 0L;
364 lpWaveHdr
->dwLoops
= 0L;
365 hWaveHdr
= USER_HEAP_ALLOC(sizeof(WAVEHDR
));
366 lp16WaveHdr
= (LPWAVEHDR
) USER_HEAP_SEG_ADDR(hWaveHdr
);
367 memcpy(PTR_SEG_TO_LIN(lp16WaveHdr
), lpWaveHdr
, sizeof(WAVEHDR
));
368 lpWaveHdr
= PTR_SEG_TO_LIN(lp16WaveHdr
);
369 dwRet
= widMessage(0, WIDM_PREPARE
, 0, (DWORD
)lp16WaveHdr
, sizeof(WAVEHDR
));
370 dprintf_mciwave(stddeb
,"WAVE_mciRecord // after WIDM_PREPARE \n");
372 lpWaveHdr
->dwBytesRecorded
= 0;
373 dwRet
= widMessage(0, WIDM_START
, 0, 0L, 0L);
374 dprintf_mciwave(stddeb
,
375 "WAVE_mciRecord // after WIDM_START lpWaveHdr=%p dwBytesRecorded=%lu\n",
376 lpWaveHdr
, lpWaveHdr
->dwBytesRecorded
);
377 if (lpWaveHdr
->dwBytesRecorded
== 0) break;
379 dprintf_mciwave(stddeb
,"WAVE_mciRecord // before WIDM_UNPREPARE \n");
380 dwRet
= widMessage(0, WIDM_UNPREPARE
, 0, (DWORD
)lp16WaveHdr
, sizeof(WAVEHDR
));
381 dprintf_mciwave(stddeb
,"WAVE_mciRecord // after WIDM_UNPREPARE \n");
382 if (lpWaveHdr
->lpData
!= NULL
) {
383 GlobalUnlock16(hData
);
385 lpWaveHdr
->lpData
= NULL
;
387 USER_HEAP_FREE(hWaveHdr
);
388 if (dwFlags
& MCI_NOTIFY
) {
389 dprintf_mciwave(stddeb
,"WAVE_mciRecord // MCI_NOTIFY_SUCCESSFUL %08lX !\n", lpParms
->dwCallback
);
390 mciDriverNotify((HWND
)LOWORD(lpParms
->dwCallback
),
391 MCIWavDev
[wDevID
].wNotifyDeviceID
, MCI_NOTIFY_SUCCESSFUL
);
397 /**************************************************************************
398 * WAVE_mciStop [internal]
400 static DWORD
WAVE_mciStop(UINT wDevID
, DWORD dwFlags
, LPMCI_GENERIC_PARMS lpParms
)
402 dprintf_mciwave(stddeb
,
403 "WAVE_mciStop(%u, %08lX, %p);\n", wDevID
, dwFlags
, lpParms
);
404 if (lpParms
== NULL
) return MCIERR_INTERNAL
;
409 /**************************************************************************
410 * WAVE_mciPause [internal]
412 static DWORD
WAVE_mciPause(UINT wDevID
, DWORD dwFlags
, LPMCI_GENERIC_PARMS lpParms
)
414 dprintf_mciwave(stddeb
,
415 "WAVE_mciPause(%u, %08lX, %p);\n", wDevID
, dwFlags
, lpParms
);
416 if (lpParms
== NULL
) return MCIERR_INTERNAL
;
421 /**************************************************************************
422 * WAVE_mciResume [internal]
424 static DWORD
WAVE_mciResume(UINT wDevID
, DWORD dwFlags
, LPMCI_GENERIC_PARMS lpParms
)
426 dprintf_mciwave(stddeb
,
427 "WAVE_mciResume(%u, %08lX, %p);\n", wDevID
, dwFlags
, lpParms
);
428 if (lpParms
== NULL
) return MCIERR_INTERNAL
;
433 /**************************************************************************
434 * WAVE_mciSet [internal]
436 static DWORD
WAVE_mciSet(UINT wDevID
, DWORD dwFlags
, LPMCI_SET_PARMS lpParms
)
438 dprintf_mciwave(stddeb
,
439 "WAVE_mciSet(%u, %08lX, %p);\n", wDevID
, dwFlags
, lpParms
);
440 if (lpParms
== NULL
) return MCIERR_INTERNAL
;
441 dprintf_mciwave(stddeb
,
442 "WAVE_mciSet // dwTimeFormat=%08lX\n", lpParms
->dwTimeFormat
);
443 dprintf_mciwave(stddeb
,
444 "WAVE_mciSet // dwAudio=%08lX\n", lpParms
->dwAudio
);
445 if (dwFlags
& MCI_SET_TIME_FORMAT
) {
446 switch (lpParms
->dwTimeFormat
) {
447 case MCI_FORMAT_MILLISECONDS
:
448 dprintf_mciwave(stddeb
, "WAVE_mciSet // MCI_FORMAT_MILLISECONDS !\n");
450 case MCI_FORMAT_BYTES
:
451 dprintf_mciwave(stddeb
, "WAVE_mciSet // MCI_FORMAT_BYTES !\n");
453 case MCI_FORMAT_SAMPLES
:
454 dprintf_mciwave(stddeb
, "WAVE_mciSet // MCI_FORMAT_SAMPLES !\n");
457 dprintf_mciwave(stddeb
, "WAVE_mciSet // bad time format !\n");
458 return MCIERR_BAD_TIME_FORMAT
;
461 if (dwFlags
& MCI_SET_VIDEO
) return MCIERR_UNSUPPORTED_FUNCTION
;
462 if (dwFlags
& MCI_SET_DOOR_OPEN
) return MCIERR_UNSUPPORTED_FUNCTION
;
463 if (dwFlags
& MCI_SET_DOOR_CLOSED
) return MCIERR_UNSUPPORTED_FUNCTION
;
464 if (dwFlags
& MCI_SET_AUDIO
)
465 dprintf_mciwave(stddeb
,"WAVE_mciSet // MCI_SET_AUDIO !\n");
466 if (dwFlags
&& MCI_SET_ON
) {
467 dprintf_mciwave(stddeb
,"WAVE_mciSet // MCI_SET_ON !\n");
468 if (dwFlags
&& MCI_SET_AUDIO_LEFT
)
469 dprintf_mciwave(stddeb
,"WAVE_mciSet // MCI_SET_AUDIO_LEFT !\n");
470 if (dwFlags
&& MCI_SET_AUDIO_RIGHT
)
471 dprintf_mciwave(stddeb
,"WAVE_mciSet // MCI_SET_AUDIO_RIGHT !\n");
473 if (dwFlags
& MCI_SET_OFF
)
474 dprintf_mciwave(stddeb
,"WAVE_mciSet // MCI_SET_OFF !\n");
475 if (dwFlags
& MCI_WAVE_INPUT
)
476 dprintf_mciwave(stddeb
,"WAVE_mciSet // MCI_WAVE_INPUT !\n");
477 if (dwFlags
& MCI_WAVE_OUTPUT
)
478 dprintf_mciwave(stddeb
,"WAVE_mciSet // MCI_WAVE_OUTPUT !\n");
479 if (dwFlags
& MCI_WAVE_SET_ANYINPUT
)
480 dprintf_mciwave(stddeb
,"WAVE_mciSet // MCI_WAVE_SET_ANYINPUT !\n");
481 if (dwFlags
& MCI_WAVE_SET_ANYOUTPUT
)
482 dprintf_mciwave(stddeb
,"WAVE_mciSet // MCI_WAVE_SET_ANYOUTPUT !\n");
483 if (dwFlags
& MCI_WAVE_SET_AVGBYTESPERSEC
)
484 dprintf_mciwave(stddeb
,
485 "WAVE_mciSet // MCI_WAVE_SET_AVGBYTESPERSEC !\n");
486 if (dwFlags
& MCI_WAVE_SET_BITSPERSAMPLE
)
487 dprintf_mciwave(stddeb
,
488 "WAVE_mciSet // MCI_WAVE_SET_BITSPERSAMPLE !\n");
489 if (dwFlags
& MCI_WAVE_SET_BLOCKALIGN
)
490 dprintf_mciwave(stddeb
,"WAVE_mciSet // MCI_WAVE_SET_BLOCKALIGN !\n");
491 if (dwFlags
& MCI_WAVE_SET_CHANNELS
)
492 dprintf_mciwave(stddeb
,"WAVE_mciSet // MCI_WAVE_SET_CHANNELS !\n");
493 if (dwFlags
& MCI_WAVE_SET_FORMATTAG
)
494 dprintf_mciwave(stddeb
,"WAVE_mciSet // MCI_WAVE_SET_FORMATTAG !\n");
495 if (dwFlags
& MCI_WAVE_SET_SAMPLESPERSEC
)
496 dprintf_mciwave(stddeb
,
497 "WAVE_mciSet // MCI_WAVE_SET_SAMPLESPERSEC !\n");
502 /**************************************************************************
503 * WAVE_mciStatus [internal]
505 static DWORD
WAVE_mciStatus(UINT wDevID
, DWORD dwFlags
, LPMCI_STATUS_PARMS lpParms
)
507 dprintf_mciwave(stddeb
,
508 "WAVE_mciStatus(%u, %08lX, %p);\n", wDevID
, dwFlags
, lpParms
);
509 if (lpParms
== NULL
) return MCIERR_INTERNAL
;
510 if (dwFlags
& MCI_STATUS_ITEM
) {
511 switch(lpParms
->dwItem
) {
512 case MCI_STATUS_CURRENT_TRACK
:
513 lpParms
->dwReturn
= 1;
515 case MCI_STATUS_LENGTH
:
516 lpParms
->dwReturn
= 5555;
517 if (dwFlags
& MCI_TRACK
) {
518 lpParms
->dwTrack
= 1;
519 lpParms
->dwReturn
= 2222;
522 case MCI_STATUS_MODE
:
523 lpParms
->dwReturn
= MCI_MODE_STOP
;
525 case MCI_STATUS_MEDIA_PRESENT
:
526 dprintf_mciwave(stddeb
,"WAVE_mciStatus // MCI_STATUS_MEDIA_PRESENT !\n");
527 lpParms
->dwReturn
= TRUE
;
529 case MCI_STATUS_NUMBER_OF_TRACKS
:
530 lpParms
->dwReturn
= 1;
532 case MCI_STATUS_POSITION
:
533 lpParms
->dwReturn
= 3333;
534 if (dwFlags
& MCI_STATUS_START
) {
537 if (dwFlags
& MCI_TRACK
) {
538 lpParms
->dwTrack
= 1;
539 lpParms
->dwReturn
= 777;
542 case MCI_STATUS_READY
:
543 dprintf_mciwave(stddeb
,"WAVE_mciStatus // MCI_STATUS_READY !\n");
544 lpParms
->dwReturn
= TRUE
;
546 case MCI_STATUS_TIME_FORMAT
:
547 dprintf_mciwave(stddeb
,"WAVE_mciStatus // MCI_STATUS_TIME_FORMAT !\n");
548 lpParms
->dwReturn
= MCI_FORMAT_MILLISECONDS
;
551 dprintf_mciwave(stddeb
,"WAVE_mciStatus // MCI_WAVE_INPUT !\n");
552 lpParms
->dwReturn
= 0;
554 case MCI_WAVE_OUTPUT
:
555 dprintf_mciwave(stddeb
,"WAVE_mciStatus // MCI_WAVE_OUTPUT !\n");
556 lpParms
->dwReturn
= 0;
558 case MCI_WAVE_STATUS_AVGBYTESPERSEC
:
559 dprintf_mciwave(stddeb
,"WAVE_mciStatus // MCI_WAVE_STATUS_AVGBYTESPERSEC !\n");
560 lpParms
->dwReturn
= 22050;
562 case MCI_WAVE_STATUS_BITSPERSAMPLE
:
563 dprintf_mciwave(stddeb
,"WAVE_mciStatus // MCI_WAVE_STATUS_BITSPERSAMPLE !\n");
564 lpParms
->dwReturn
= 8;
566 case MCI_WAVE_STATUS_BLOCKALIGN
:
567 dprintf_mciwave(stddeb
,"WAVE_mciStatus // MCI_WAVE_STATUS_BLOCKALIGN !\n");
568 lpParms
->dwReturn
= 1;
570 case MCI_WAVE_STATUS_CHANNELS
:
571 dprintf_mciwave(stddeb
,"WAVE_mciStatus // MCI_WAVE_STATUS_CHANNELS !\n");
572 lpParms
->dwReturn
= 1;
574 case MCI_WAVE_STATUS_FORMATTAG
:
575 dprintf_mciwave(stddeb
,"WAVE_mciStatus // MCI_WAVE_FORMATTAG !\n");
576 lpParms
->dwReturn
= WAVE_FORMAT_PCM
;
578 case MCI_WAVE_STATUS_LEVEL
:
579 dprintf_mciwave(stddeb
,"WAVE_mciStatus // MCI_WAVE_STATUS_LEVEL !\n");
580 lpParms
->dwReturn
= 0xAAAA5555;
582 case MCI_WAVE_STATUS_SAMPLESPERSEC
:
583 dprintf_mciwave(stddeb
,"WAVE_mciStatus // MCI_WAVE_STATUS_SAMPLESPERSEC !\n");
584 lpParms
->dwReturn
= 22050;
587 dprintf_mciwave(stddeb
,"WAVE_mciStatus // unknown command %08lX !\n", lpParms
->dwItem
);
588 return MCIERR_UNRECOGNIZED_COMMAND
;
591 if (dwFlags
& MCI_NOTIFY
) {
592 dprintf_mciwave(stddeb
,"WAVE_mciStatus // MCI_NOTIFY_SUCCESSFUL %08lX !\n", lpParms
->dwCallback
);
593 mciDriverNotify((HWND
)LOWORD(lpParms
->dwCallback
),
594 MCIWavDev
[wDevID
].wNotifyDeviceID
, MCI_NOTIFY_SUCCESSFUL
);
599 /**************************************************************************
600 * WAVE_mciGetDevCaps [internal]
602 static DWORD
WAVE_mciGetDevCaps(UINT wDevID
, DWORD dwFlags
,
603 LPMCI_GETDEVCAPS_PARMS lpParms
)
605 dprintf_mciwave(stddeb
,
606 "WAVE_mciGetDevCaps(%u, %08lX, %p);\n", wDevID
, dwFlags
, lpParms
);
607 if (lpParms
== NULL
) return MCIERR_INTERNAL
;
608 if (dwFlags
& MCI_GETDEVCAPS_ITEM
) {
609 switch(lpParms
->dwItem
) {
610 case MCI_GETDEVCAPS_CAN_RECORD
:
611 lpParms
->dwReturn
= TRUE
;
613 case MCI_GETDEVCAPS_HAS_AUDIO
:
614 lpParms
->dwReturn
= TRUE
;
616 case MCI_GETDEVCAPS_HAS_VIDEO
:
617 lpParms
->dwReturn
= FALSE
;
619 case MCI_GETDEVCAPS_DEVICE_TYPE
:
620 lpParms
->dwReturn
= MCI_DEVTYPE_WAVEFORM_AUDIO
;
622 case MCI_GETDEVCAPS_USES_FILES
:
623 lpParms
->dwReturn
= TRUE
;
625 case MCI_GETDEVCAPS_COMPOUND_DEVICE
:
626 lpParms
->dwReturn
= TRUE
;
628 case MCI_GETDEVCAPS_CAN_EJECT
:
629 lpParms
->dwReturn
= FALSE
;
631 case MCI_GETDEVCAPS_CAN_PLAY
:
632 lpParms
->dwReturn
= TRUE
;
634 case MCI_GETDEVCAPS_CAN_SAVE
:
635 lpParms
->dwReturn
= TRUE
;
637 case MCI_WAVE_GETDEVCAPS_INPUTS
:
638 lpParms
->dwReturn
= 1;
640 case MCI_WAVE_GETDEVCAPS_OUTPUTS
:
641 lpParms
->dwReturn
= 1;
644 return MCIERR_UNRECOGNIZED_COMMAND
;
650 /**************************************************************************
651 * WAVE_mciInfo [internal]
653 static DWORD
WAVE_mciInfo(UINT wDevID
, DWORD dwFlags
, LPMCI_INFO_PARMS lpParms
)
655 dprintf_mciwave(stddeb
,
656 "WAVE_mciInfo(%u, %08lX, %p);\n", wDevID
, dwFlags
, lpParms
);
657 if (lpParms
== NULL
) return MCIERR_INTERNAL
;
658 lpParms
->lpstrReturn
= NULL
;
660 case MCI_INFO_PRODUCT
:
661 lpParms
->lpstrReturn
= "Linux Sound System 0.5";
664 lpParms
->lpstrReturn
=
665 (LPSTR
)MCIWavDev
[wDevID
].openParms
.lpstrElementName
;
668 lpParms
->lpstrReturn
= "Linux Sound System 0.5";
670 case MCI_WAVE_OUTPUT
:
671 lpParms
->lpstrReturn
= "Linux Sound System 0.5";
674 return MCIERR_UNRECOGNIZED_COMMAND
;
676 if (lpParms
->lpstrReturn
!= NULL
)
677 lpParms
->dwRetSize
= strlen(lpParms
->lpstrReturn
);
679 lpParms
->dwRetSize
= 0;
684 /*-----------------------------------------------------------------------*/
687 /**************************************************************************
688 * wodGetDevCaps [internal]
690 static DWORD
wodGetDevCaps(WORD wDevID
, LPWAVEOUTCAPS lpCaps
, DWORD dwSize
)
697 dprintf_mciwave(stddeb
,
698 "wodGetDevCaps(%u, %p, %lu);\n", wDevID
, lpCaps
, dwSize
);
699 if (lpCaps
== NULL
) return MMSYSERR_NOTENABLED
;
700 audio
= open (SOUND_DEV
, O_WRONLY
, 0);
701 if (audio
== -1) return MMSYSERR_NOTENABLED
;
703 lpCaps
->wMid
= 0x0002;
704 lpCaps
->wPid
= 0x0104;
705 strcpy(lpCaps
->szPname
, "SB16 Wave Out");
707 lpCaps
->wMid
= 0x00FF; /* Manufac ID */
708 lpCaps
->wPid
= 0x0001; /* Product ID */
709 strcpy(lpCaps
->szPname
, "Linux WAVOUT Driver");
711 lpCaps
->dwFormats
= 0x00000000;
712 lpCaps
->dwSupport
= WAVECAPS_VOLUME
;
713 lpCaps
->wChannels
= (IOCTL(audio
, SNDCTL_DSP_STEREO
, dsp_stereo
) != 0) ? 1 : 2;
714 if (lpCaps
->wChannels
> 1) lpCaps
->dwSupport
|= WAVECAPS_LRVOLUME
;
715 bytespersmpl
= (IOCTL(audio
, SNDCTL_DSP_SAMPLESIZE
, samplesize
) != 0) ? 1 : 2;
717 if (IOCTL(audio
, SNDCTL_DSP_SPEED
, smplrate
) == 0) {
718 lpCaps
->dwFormats
|= WAVE_FORMAT_4M08
;
719 if (lpCaps
->wChannels
> 1) lpCaps
->dwFormats
|= WAVE_FORMAT_4S08
;
720 if (bytespersmpl
> 1) {
721 lpCaps
->dwFormats
|= WAVE_FORMAT_4M16
;
722 if (lpCaps
->wChannels
> 1) lpCaps
->dwFormats
|= WAVE_FORMAT_4S16
;
726 if (IOCTL(audio
, SNDCTL_DSP_SPEED
, smplrate
) == 0) {
727 lpCaps
->dwFormats
|= WAVE_FORMAT_2M08
;
728 if (lpCaps
->wChannels
> 1) lpCaps
->dwFormats
|= WAVE_FORMAT_2S08
;
729 if (bytespersmpl
> 1) {
730 lpCaps
->dwFormats
|= WAVE_FORMAT_2M16
;
731 if (lpCaps
->wChannels
> 1) lpCaps
->dwFormats
|= WAVE_FORMAT_2S16
;
735 if (IOCTL(audio
, SNDCTL_DSP_SPEED
, smplrate
) == 0) {
736 lpCaps
->dwFormats
|= WAVE_FORMAT_1M08
;
737 if (lpCaps
->wChannels
> 1) lpCaps
->dwFormats
|= WAVE_FORMAT_1S08
;
738 if (bytespersmpl
> 1) {
739 lpCaps
->dwFormats
|= WAVE_FORMAT_1M16
;
740 if (lpCaps
->wChannels
> 1) lpCaps
->dwFormats
|= WAVE_FORMAT_1S16
;
744 dprintf_mciwave(stddeb
,
745 "wodGetDevCaps // dwFormats = %08lX\n", lpCaps
->dwFormats
);
746 return MMSYSERR_NOERROR
;
750 /**************************************************************************
753 static DWORD
wodOpen(WORD wDevID
, LPWAVEOPENDESC lpDesc
, DWORD dwFlags
)
760 LPWAVEFORMAT lpFormat
;
762 dprintf_mciwave(stddeb
,
763 "wodOpen(%u, %p, %08lX);\n", wDevID
, lpDesc
, dwFlags
);
764 if (lpDesc
== NULL
) {
765 dprintf_mciwave(stddeb
,"Linux 'wodOpen' // Invalid Parameter !\n");
766 return MMSYSERR_INVALPARAM
;
768 if (wDevID
>= MAX_WAVOUTDRV
) {
769 dprintf_mciwave(stddeb
,"Linux 'wodOpen' // MAX_WAVOUTDRV reached !\n");
770 return MMSYSERR_ALLOCATED
;
772 WOutDev
[wDevID
].unixdev
= 0;
773 audio
= open (SOUND_DEV
, O_WRONLY
, 0);
775 dprintf_mciwave(stddeb
,"Linux 'wodOpen' // can't open !\n");
776 return MMSYSERR_NOTENABLED
;
778 IOCTL(audio
, SNDCTL_DSP_GETBLKSIZE
, abuf_size
);
779 if (abuf_size
< 1024 || abuf_size
> 65536) {
781 dprintf_mciwave(stddeb
,"Linux 'wodOpen' // IOCTL can't 'SNDCTL_DSP_GETBLKSIZE' !\n");
783 dprintf_mciwave(stddeb
,"Linux 'wodOpen' // SNDCTL_DSP_GETBLKSIZE Invalid bufsize !\n");
784 return MMSYSERR_NOTENABLED
;
786 WOutDev
[wDevID
].wFlags
= HIWORD(dwFlags
& CALLBACK_TYPEMASK
);
787 switch(WOutDev
[wDevID
].wFlags
) {
789 dprintf_mciwave(stddeb
, "Linux 'wodOpen' // CALLBACK_NULL !\n");
792 dprintf_mciwave(stddeb
, "Linux 'wodOpen' // CALLBACK_WINDOW !\n");
795 dprintf_mciwave(stddeb
, "Linux 'wodOpen' // CALLBACK_TASK !\n");
798 dprintf_mciwave(stddeb
, "Linux 'wodOpen' // CALLBACK_FUNCTION !\n");
801 WOutDev
[wDevID
].lpQueueHdr
= NULL
;
802 WOutDev
[wDevID
].unixdev
= audio
;
803 WOutDev
[wDevID
].dwTotalPlayed
= 0;
804 WOutDev
[wDevID
].bufsize
= abuf_size
;
805 memcpy(&WOutDev
[wDevID
].waveDesc
, lpDesc
, sizeof(WAVEOPENDESC
));
806 /* lpFormat = (LPWAVEFORMAT) PTR_SEG_TO_LIN(lpDesc->lpFormat); */
807 lpFormat
= lpDesc
->lpFormat
;
808 if (lpFormat
->wFormatTag
!= WAVE_FORMAT_PCM
) {
809 dprintf_mciwave(stddeb
,"Linux 'wodOpen' // Bad format %04X !\n",
810 lpFormat
->wFormatTag
);
811 dprintf_mciwave(stddeb
,"Linux 'wodOpen' // Bad nChannels %d !\n",
812 lpFormat
->nChannels
);
813 dprintf_mciwave(stddeb
,"Linux 'wodOpen' // Bad nSamplesPerSec %ld !\n",
814 lpFormat
->nSamplesPerSec
);
815 return WAVERR_BADFORMAT
;
817 memcpy(&WOutDev
[wDevID
].Format
, lpFormat
, sizeof(PCMWAVEFORMAT
));
818 if (WOutDev
[wDevID
].Format
.wf
.nChannels
== 0) return WAVERR_BADFORMAT
;
819 if (WOutDev
[wDevID
].Format
.wf
.nSamplesPerSec
== 0) return WAVERR_BADFORMAT
;
820 dprintf_mciwave(stddeb
,"Linux 'wodOpen' // wBitsPerSample=%u !\n",
821 WOutDev
[wDevID
].Format
.wBitsPerSample
);
822 if (WOutDev
[wDevID
].Format
.wBitsPerSample
== 0) {
823 WOutDev
[wDevID
].Format
.wBitsPerSample
= 8 *
824 (WOutDev
[wDevID
].Format
.wf
.nAvgBytesPerSec
/
825 WOutDev
[wDevID
].Format
.wf
.nSamplesPerSec
) /
826 WOutDev
[wDevID
].Format
.wf
.nChannels
;
828 samplesize
= WOutDev
[wDevID
].Format
.wBitsPerSample
;
829 smplrate
= WOutDev
[wDevID
].Format
.wf
.nSamplesPerSec
;
830 dsp_stereo
= (WOutDev
[wDevID
].Format
.wf
.nChannels
> 1) ? TRUE
: FALSE
;
831 IOCTL(audio
, SNDCTL_DSP_SPEED
, smplrate
);
832 IOCTL(audio
, SNDCTL_DSP_SAMPLESIZE
, samplesize
);
833 IOCTL(audio
, SNDCTL_DSP_STEREO
, dsp_stereo
);
834 dprintf_mciwave(stddeb
,"Linux 'wodOpen' // wBitsPerSample=%u !\n",
835 WOutDev
[wDevID
].Format
.wBitsPerSample
);
836 dprintf_mciwave(stddeb
,"Linux 'wodOpen' // nAvgBytesPerSec=%lu !\n",
837 WOutDev
[wDevID
].Format
.wf
.nAvgBytesPerSec
);
838 dprintf_mciwave(stddeb
,"Linux 'wodOpen' // nSamplesPerSec=%lu !\n",
839 WOutDev
[wDevID
].Format
.wf
.nSamplesPerSec
);
840 dprintf_mciwave(stddeb
,"Linux 'wodOpen' // nChannels=%u !\n",
841 WOutDev
[wDevID
].Format
.wf
.nChannels
);
842 if (WAVE_NotifyClient(wDevID
, WOM_OPEN
, 0L, 0L) != MMSYSERR_NOERROR
) {
843 dprintf_mciwave(stddeb
,"Linux 'wodOpen' // can't notify client !\n");
844 return MMSYSERR_INVALPARAM
;
846 return MMSYSERR_NOERROR
;
849 /**************************************************************************
850 * wodClose [internal]
852 static DWORD
wodClose(WORD wDevID
)
854 dprintf_mciwave(stddeb
,"wodClose(%u);\n", wDevID
);
855 if (WOutDev
[wDevID
].unixdev
== 0) {
856 dprintf_mciwave(stddeb
,"Linux 'wodClose' // can't close !\n");
857 return MMSYSERR_NOTENABLED
;
859 close(WOutDev
[wDevID
].unixdev
);
860 WOutDev
[wDevID
].unixdev
= 0;
861 WOutDev
[wDevID
].bufsize
= 0;
862 WOutDev
[wDevID
].lpQueueHdr
= NULL
;
863 if (WAVE_NotifyClient(wDevID
, WOM_CLOSE
, 0L, 0L) != MMSYSERR_NOERROR
) {
864 dprintf_mciwave(stddeb
,"Linux 'wodClose' // can't notify client !\n");
865 return MMSYSERR_INVALPARAM
;
867 return MMSYSERR_NOERROR
;
870 /**************************************************************************
871 * wodWrite [internal]
873 static DWORD
wodWrite(WORD wDevID
, LPWAVEHDR lpWaveHdr
, DWORD dwSize
)
877 dprintf_mciwave(stddeb
,"wodWrite(%u, %p, %08lX);\n", wDevID
, lpWaveHdr
, dwSize
);
878 if (WOutDev
[wDevID
].unixdev
== 0) {
879 dprintf_mciwave(stddeb
,"Linux 'wodWrite' // can't play !\n");
880 return MMSYSERR_NOTENABLED
;
882 if (lpWaveHdr
->lpData
== NULL
) return WAVERR_UNPREPARED
;
883 if (!(lpWaveHdr
->dwFlags
& WHDR_PREPARED
)) return WAVERR_UNPREPARED
;
884 if (lpWaveHdr
->dwFlags
& WHDR_INQUEUE
) return WAVERR_STILLPLAYING
;
885 lpWaveHdr
->dwFlags
&= ~WHDR_DONE
;
886 lpWaveHdr
->dwFlags
|= WHDR_INQUEUE
;
887 dprintf_mciwave(stddeb
,
888 "wodWrite() // dwBufferLength %lu !\n", lpWaveHdr
->dwBufferLength
);
889 dprintf_mciwave(stddeb
,
890 "wodWrite() // WOutDev[%u].unixdev %u !\n", wDevID
, WOutDev
[wDevID
].unixdev
);
891 lpData
= PTR_SEG_TO_LIN(lpWaveHdr
->lpData
);
892 count
= write (WOutDev
[wDevID
].unixdev
, lpData
, lpWaveHdr
->dwBufferLength
);
893 dprintf_mciwave(stddeb
,
894 "wodWrite() // write returned count %u !\n", count
);
895 if (count
!= lpWaveHdr
->dwBufferLength
) {
896 dprintf_mciwave(stddeb
,"Linux 'wodWrite' // error writting !\n");
897 return MMSYSERR_NOTENABLED
;
899 WOutDev
[wDevID
].dwTotalPlayed
+= count
;
900 lpWaveHdr
->dwFlags
&= ~WHDR_INQUEUE
;
901 lpWaveHdr
->dwFlags
|= WHDR_DONE
;
902 if (WAVE_NotifyClient(wDevID
, WOM_DONE
, 0L, 0L) != MMSYSERR_NOERROR
) {
903 dprintf_mciwave(stddeb
,"Linux 'wodWrite' // can't notify client !\n");
904 return MMSYSERR_INVALPARAM
;
906 return MMSYSERR_NOERROR
;
909 /**************************************************************************
910 * wodPrepare [internal]
912 static DWORD
wodPrepare(WORD wDevID
, LPWAVEHDR lpWaveHdr
, DWORD dwSize
)
914 dprintf_mciwave(stddeb
,
915 "wodPrepare(%u, %p, %08lX);\n", wDevID
, lpWaveHdr
, dwSize
);
916 if (WOutDev
[wDevID
].unixdev
== 0) {
917 dprintf_mciwave(stddeb
,"Linux 'wodPrepare' // can't prepare !\n");
918 return MMSYSERR_NOTENABLED
;
920 /* the COOL waveeditor feels much better without this check...
921 * someone please have a look at available documentation
922 if (WOutDev[wDevID].lpQueueHdr != NULL) {
923 dprintf_mciwave(stddeb,"Linux 'wodPrepare' // already prepare !\n");
924 return MMSYSERR_NOTENABLED;
927 WOutDev
[wDevID
].dwTotalPlayed
= 0;
928 WOutDev
[wDevID
].lpQueueHdr
= lpWaveHdr
;
929 if (lpWaveHdr
->dwFlags
& WHDR_INQUEUE
) return WAVERR_STILLPLAYING
;
930 lpWaveHdr
->dwFlags
|= WHDR_PREPARED
;
931 lpWaveHdr
->dwFlags
&= ~WHDR_DONE
;
932 return MMSYSERR_NOERROR
;
935 /**************************************************************************
936 * wodUnprepare [internal]
938 static DWORD
wodUnprepare(WORD wDevID
, LPWAVEHDR lpWaveHdr
, DWORD dwSize
)
940 dprintf_mciwave(stddeb
,
941 "wodUnprepare(%u, %p, %08lX);\n", wDevID
, lpWaveHdr
, dwSize
);
942 if (WOutDev
[wDevID
].unixdev
== 0) {
943 dprintf_mciwave(stddeb
,"Linux 'wodUnprepare' // can't unprepare !\n");
944 return MMSYSERR_NOTENABLED
;
946 return MMSYSERR_NOERROR
;
949 /**************************************************************************
950 * wodRestart [internal]
952 static DWORD
wodRestart(WORD wDevID
)
954 dprintf_mciwave(stddeb
,"wodRestart(%u);\n", wDevID
);
955 if (WOutDev
[wDevID
].unixdev
== 0) {
956 dprintf_mciwave(stddeb
,"Linux 'wodRestart' // can't restart !\n");
957 return MMSYSERR_NOTENABLED
;
959 return MMSYSERR_NOERROR
;
962 /**************************************************************************
963 * wodReset [internal]
965 static DWORD
wodReset(WORD wDevID
)
967 dprintf_mciwave(stddeb
,"wodReset(%u);\n", wDevID
);
968 if (WOutDev
[wDevID
].unixdev
== 0) {
969 dprintf_mciwave(stddeb
,"Linux 'wodReset' // can't reset !\n");
970 return MMSYSERR_NOTENABLED
;
972 return MMSYSERR_NOERROR
;
976 /**************************************************************************
977 * wodGetPosition [internal]
979 static DWORD
wodGetPosition(WORD wDevID
, LPMMTIME lpTime
, DWORD uSize
)
982 dprintf_mciwave(stddeb
,"wodGetPosition(%u, %p, %lu);\n", wDevID
, lpTime
, uSize
);
983 if (WOutDev
[wDevID
].unixdev
== 0) {
984 dprintf_mciwave(stddeb
,"Linux 'wodGetPosition' // can't get pos !\n");
985 return MMSYSERR_NOTENABLED
;
987 if (lpTime
== NULL
) return MMSYSERR_INVALPARAM
;
988 switch(lpTime
->wType
) {
990 lpTime
->u
.cb
= WOutDev
[wDevID
].dwTotalPlayed
;
991 dprintf_mciwave(stddeb
,"wodGetPosition // TIME_BYTES=%lu\n", lpTime
->u
.cb
);
994 dprintf_mciwave(stddeb
,"wodGetPosition // dwTotalPlayed=%lu\n",
995 WOutDev
[wDevID
].dwTotalPlayed
);
996 dprintf_mciwave(stddeb
,"wodGetPosition // wBitsPerSample=%u\n",
997 WOutDev
[wDevID
].Format
.wBitsPerSample
);
998 lpTime
->u
.sample
= WOutDev
[wDevID
].dwTotalPlayed
* 8 /
999 WOutDev
[wDevID
].Format
.wBitsPerSample
;
1000 dprintf_mciwave(stddeb
,"wodGetPosition // TIME_SAMPLES=%lu\n", lpTime
->u
.sample
);
1003 time
= WOutDev
[wDevID
].dwTotalPlayed
/
1004 (WOutDev
[wDevID
].Format
.wf
.nAvgBytesPerSec
/ 1000);
1005 lpTime
->u
.smpte
.hour
= time
/ 108000;
1006 time
-= lpTime
->u
.smpte
.hour
* 108000;
1007 lpTime
->u
.smpte
.min
= time
/ 1800;
1008 time
-= lpTime
->u
.smpte
.min
* 1800;
1009 lpTime
->u
.smpte
.sec
= time
/ 30;
1010 time
-= lpTime
->u
.smpte
.sec
* 30;
1011 lpTime
->u
.smpte
.frame
= time
;
1012 lpTime
->u
.smpte
.fps
= 30;
1013 dprintf_mciwave(stddeb
,
1014 "wodGetPosition // TIME_SMPTE=%02u:%02u:%02u:%02u\n",
1015 lpTime
->u
.smpte
.hour
, lpTime
->u
.smpte
.min
,
1016 lpTime
->u
.smpte
.sec
, lpTime
->u
.smpte
.frame
);
1019 dprintf_mciwave(stddeb
,"wodGetPosition() format not supported ! use TIME_MS !\n");
1020 lpTime
->wType
= TIME_MS
;
1022 lpTime
->u
.ms
= WOutDev
[wDevID
].dwTotalPlayed
/
1023 (WOutDev
[wDevID
].Format
.wf
.nAvgBytesPerSec
/ 1000);
1024 dprintf_mciwave(stddeb
,"wodGetPosition // TIME_MS=%lu\n", lpTime
->u
.ms
);
1027 return MMSYSERR_NOERROR
;
1030 /**************************************************************************
1031 * wodGetVolume [internal]
1033 static DWORD
wodGetVolume(WORD wDevID
, LPDWORD lpdwVol
)
1036 int volume
, left
, right
;
1037 dprintf_mciwave(stddeb
,"wodGetVolume(%u, %p);\n", wDevID
, lpdwVol
);
1038 if (lpdwVol
== NULL
) return MMSYSERR_NOTENABLED
;
1039 if ((mixer
= open("/dev/mixer", O_RDONLY
)) < 0) {
1040 dprintf_mciwave(stddeb
, "Linux 'wodGetVolume' // mixer device not available !\n");
1041 return MMSYSERR_NOTENABLED
;
1043 if (ioctl(mixer
, SOUND_MIXER_READ_PCM
, &volume
) == -1) {
1044 dprintf_mciwave(stddeb
,"Linux 'wodGetVolume' // unable read mixer !\n");
1045 return MMSYSERR_NOTENABLED
;
1048 left
= volume
& 0x7F;
1049 right
= (volume
>> 8) & 0x7F;
1050 printf("Linux 'AUX_GetVolume' // left=%d right=%d !\n", left
, right
);
1051 *lpdwVol
= MAKELONG(left
<< 9, right
<< 9);
1052 return MMSYSERR_NOERROR
;
1056 /**************************************************************************
1057 * wodSetVolume [internal]
1059 static DWORD
wodSetVolume(WORD wDevID
, DWORD dwParam
)
1063 dprintf_mciwave(stddeb
,"wodSetVolume(%u, %08lX);\n", wDevID
, dwParam
);
1064 volume
= (LOWORD(dwParam
) >> 9 & 0x7F) +
1065 ((HIWORD(dwParam
) >> 9 & 0x7F) << 8);
1066 if ((mixer
= open("/dev/mixer", O_WRONLY
)) < 0) {
1067 dprintf_mciwave(stddeb
, "Linux 'wodSetVolume' // mixer device not available !\n");
1068 return MMSYSERR_NOTENABLED
;
1070 if (ioctl(mixer
, SOUND_MIXER_WRITE_PCM
, &volume
) == -1) {
1071 dprintf_mciwave(stddeb
,"Linux 'wodSetVolume' // unable set mixer !\n");
1072 return MMSYSERR_NOTENABLED
;
1075 return MMSYSERR_NOERROR
;
1078 #endif /* linux || __FreeBSD__*/
1080 /**************************************************************************
1081 * wodMessage [sample driver]
1083 DWORD
wodMessage(WORD wDevID
, WORD wMsg
, DWORD dwUser
,
1084 DWORD dwParam1
, DWORD dwParam2
)
1086 dprintf_mciwave(stddeb
,"wodMessage(%u, %04X, %08lX, %08lX, %08lX);\n",
1087 wDevID
, wMsg
, dwUser
, dwParam1
, dwParam2
);
1088 #if defined(linux) || defined(__FreeBSD__)
1091 return wodOpen(wDevID
, (LPWAVEOPENDESC
)PTR_SEG_TO_LIN(dwParam1
), dwParam2
);
1093 return wodClose(wDevID
);
1095 return wodWrite(wDevID
, (LPWAVEHDR
)PTR_SEG_TO_LIN(dwParam1
), dwParam2
);
1099 return wodGetPosition(wDevID
, (LPMMTIME
)PTR_SEG_TO_LIN(dwParam1
), dwParam2
);
1100 case WODM_BREAKLOOP
:
1103 return wodPrepare(wDevID
, (LPWAVEHDR
)PTR_SEG_TO_LIN(dwParam1
), dwParam2
);
1104 case WODM_UNPREPARE
:
1105 return wodUnprepare(wDevID
, (LPWAVEHDR
)PTR_SEG_TO_LIN(dwParam1
), dwParam2
);
1106 case WODM_GETDEVCAPS
:
1107 return wodGetDevCaps(wDevID
, (LPWAVEOUTCAPS
)PTR_SEG_TO_LIN(dwParam1
), dwParam2
);
1108 case WODM_GETNUMDEVS
:
1114 case WODM_GETPLAYBACKRATE
:
1116 case WODM_SETPLAYBACKRATE
:
1118 case WODM_GETVOLUME
:
1119 return wodGetVolume(wDevID
, (LPDWORD
)PTR_SEG_TO_LIN(dwParam1
));
1120 case WODM_SETVOLUME
:
1121 return wodSetVolume(wDevID
, dwParam1
);
1123 return wodRestart(wDevID
);
1125 return wodReset(wDevID
);
1127 dprintf_mciwave(stddeb
,"wodMessage // unknown message !\n");
1129 return MMSYSERR_NOTSUPPORTED
;
1131 return MMSYSERR_NOTENABLED
;
1136 /*-----------------------------------------------------------------------*/
1138 #if defined(linux) || defined(__FreeBSD__)
1140 /**************************************************************************
1141 * widGetDevCaps [internal]
1143 static DWORD
widGetDevCaps(WORD wDevID
, LPWAVEINCAPS lpCaps
, DWORD dwSize
)
1147 int samplesize
= 16;
1150 dprintf_mciwave(stddeb
,
1151 "widGetDevCaps(%u, %p, %lu);\n", wDevID
, lpCaps
, dwSize
);
1152 if (lpCaps
== NULL
) return MMSYSERR_NOTENABLED
;
1153 audio
= open (SOUND_DEV
, O_RDONLY
, 0);
1154 if (audio
== -1) return MMSYSERR_NOTENABLED
;
1156 lpCaps
->wMid
= 0x0002;
1157 lpCaps
->wPid
= 0x0004;
1158 strcpy(lpCaps
->szPname
, "SB16 Wave Out");
1160 lpCaps
->wMid
= 0x00FF; /* Manufac ID */
1161 lpCaps
->wPid
= 0x0001; /* Product ID */
1162 strcpy(lpCaps
->szPname
, "Linux WAVIN Driver");
1164 lpCaps
->dwFormats
= 0x00000000;
1165 lpCaps
->wChannels
= (IOCTL(audio
, SNDCTL_DSP_STEREO
, dsp_stereo
) != 0) ? 1 : 2;
1166 bytespersmpl
= (IOCTL(audio
, SNDCTL_DSP_SAMPLESIZE
, samplesize
) != 0) ? 1 : 2;
1168 if (IOCTL(audio
, SNDCTL_DSP_SPEED
, smplrate
) == 0) {
1169 lpCaps
->dwFormats
|= WAVE_FORMAT_4M08
;
1170 if (lpCaps
->wChannels
> 1) lpCaps
->dwFormats
|= WAVE_FORMAT_4S08
;
1171 if (bytespersmpl
> 1) {
1172 lpCaps
->dwFormats
|= WAVE_FORMAT_4M16
;
1173 if (lpCaps
->wChannels
> 1) lpCaps
->dwFormats
|= WAVE_FORMAT_4S16
;
1177 if (IOCTL(audio
, SNDCTL_DSP_SPEED
, smplrate
) == 0) {
1178 lpCaps
->dwFormats
|= WAVE_FORMAT_2M08
;
1179 if (lpCaps
->wChannels
> 1) lpCaps
->dwFormats
|= WAVE_FORMAT_2S08
;
1180 if (bytespersmpl
> 1) {
1181 lpCaps
->dwFormats
|= WAVE_FORMAT_2M16
;
1182 if (lpCaps
->wChannels
> 1) lpCaps
->dwFormats
|= WAVE_FORMAT_2S16
;
1186 if (IOCTL(audio
, SNDCTL_DSP_SPEED
, smplrate
) == 0) {
1187 lpCaps
->dwFormats
|= WAVE_FORMAT_1M08
;
1188 if (lpCaps
->wChannels
> 1) lpCaps
->dwFormats
|= WAVE_FORMAT_1S08
;
1189 if (bytespersmpl
> 1) {
1190 lpCaps
->dwFormats
|= WAVE_FORMAT_1M16
;
1191 if (lpCaps
->wChannels
> 1) lpCaps
->dwFormats
|= WAVE_FORMAT_1S16
;
1195 dprintf_mciwave(stddeb
,
1196 "widGetDevCaps // dwFormats = %08lX\n", lpCaps
->dwFormats
);
1197 return MMSYSERR_NOERROR
;
1201 /**************************************************************************
1202 * widOpen [internal]
1204 static DWORD
widOpen(WORD wDevID
, LPWAVEOPENDESC lpDesc
, DWORD dwFlags
)
1211 LPWAVEFORMAT lpFormat
;
1212 dprintf_mciwave(stddeb
, "widOpen(%u, %p, %08lX);\n", wDevID
, lpDesc
, dwFlags
);
1213 if (lpDesc
== NULL
) {
1214 dprintf_mciwave(stddeb
,"Linux 'widOpen' // Invalid Parameter !\n");
1215 return MMSYSERR_INVALPARAM
;
1217 if (wDevID
>= MAX_WAVINDRV
) {
1218 dprintf_mciwave(stddeb
,"Linux 'widOpen' // MAX_WAVINDRV reached !\n");
1219 return MMSYSERR_ALLOCATED
;
1221 WInDev
[wDevID
].unixdev
= 0;
1222 audio
= open (SOUND_DEV
, O_RDONLY
, 0);
1224 dprintf_mciwave(stddeb
,"Linux 'widOpen' // can't open !\n");
1225 return MMSYSERR_NOTENABLED
;
1227 IOCTL(audio
, SNDCTL_DSP_GETBLKSIZE
, abuf_size
);
1228 if (abuf_size
< 1024 || abuf_size
> 65536) {
1229 if (abuf_size
== -1)
1230 dprintf_mciwave(stddeb
,"Linux 'widOpen' // IOCTL can't 'SNDCTL_DSP_GETBLKSIZE' !\n");
1232 dprintf_mciwave(stddeb
,"Linux 'widOpen' // SNDCTL_DSP_GETBLKSIZE Invalid bufsize !\n");
1233 return MMSYSERR_NOTENABLED
;
1235 WInDev
[wDevID
].wFlags
= HIWORD(dwFlags
& CALLBACK_TYPEMASK
);
1236 switch(WInDev
[wDevID
].wFlags
) {
1238 dprintf_mciwave(stddeb
, "Linux 'widOpen' // CALLBACK_NULL !\n");
1241 dprintf_mciwave(stddeb
, "Linux 'widOpen' // CALLBACK_WINDOW !\n");
1244 dprintf_mciwave(stddeb
, "Linux 'widOpen' // CALLBACK_TASK !\n");
1247 dprintf_mciwave(stddeb
, "Linux 'widOpen' // CALLBACK_FUNCTION !\n");
1250 WInDev
[wDevID
].lpQueueHdr
= NULL
;
1251 WInDev
[wDevID
].unixdev
= audio
;
1252 WInDev
[wDevID
].bufsize
= abuf_size
;
1253 WInDev
[wDevID
].dwTotalRecorded
= 0;
1254 memcpy(&WInDev
[wDevID
].waveDesc
, lpDesc
, sizeof(WAVEOPENDESC
));
1255 lpFormat
= lpDesc
->lpFormat
;
1256 if (lpFormat
->wFormatTag
!= WAVE_FORMAT_PCM
) {
1257 dprintf_mciwave(stddeb
,"Linux 'widOpen' // Bad format %04X !\n",
1258 lpFormat
->wFormatTag
);
1259 return WAVERR_BADFORMAT
;
1261 memcpy(&WInDev
[wDevID
].Format
, lpFormat
, sizeof(PCMWAVEFORMAT
));
1262 WInDev
[wDevID
].Format
.wBitsPerSample
= 8; /* <-------------- */
1263 if (WInDev
[wDevID
].Format
.wf
.nChannels
== 0) return WAVERR_BADFORMAT
;
1264 if (WInDev
[wDevID
].Format
.wf
.nSamplesPerSec
== 0) return WAVERR_BADFORMAT
;
1265 if (WInDev
[wDevID
].Format
.wBitsPerSample
== 0) {
1266 WInDev
[wDevID
].Format
.wBitsPerSample
= 8 *
1267 (WInDev
[wDevID
].Format
.wf
.nAvgBytesPerSec
/
1268 WInDev
[wDevID
].Format
.wf
.nSamplesPerSec
) /
1269 WInDev
[wDevID
].Format
.wf
.nChannels
;
1271 samplesize
= WInDev
[wDevID
].Format
.wBitsPerSample
;
1272 smplrate
= WInDev
[wDevID
].Format
.wf
.nSamplesPerSec
;
1273 dsp_stereo
= (WInDev
[wDevID
].Format
.wf
.nChannels
> 1) ? TRUE
: FALSE
;
1274 IOCTL(audio
, SNDCTL_DSP_SPEED
, smplrate
);
1275 IOCTL(audio
, SNDCTL_DSP_SAMPLESIZE
, samplesize
);
1276 IOCTL(audio
, SNDCTL_DSP_STEREO
, dsp_stereo
);
1277 dprintf_mciwave(stddeb
,"Linux 'widOpen' // wBitsPerSample=%u !\n",
1278 WInDev
[wDevID
].Format
.wBitsPerSample
);
1279 dprintf_mciwave(stddeb
,"Linux 'widOpen' // nSamplesPerSec=%lu !\n",
1280 WInDev
[wDevID
].Format
.wf
.nSamplesPerSec
);
1281 dprintf_mciwave(stddeb
,"Linux 'widOpen' // nChannels=%u !\n",
1282 WInDev
[wDevID
].Format
.wf
.nChannels
);
1283 dprintf_mciwave(stddeb
,"Linux 'widOpen' // nAvgBytesPerSec=%lu\n",
1284 WInDev
[wDevID
].Format
.wf
.nAvgBytesPerSec
);
1285 if (WAVE_NotifyClient(wDevID
, WIM_OPEN
, 0L, 0L) != MMSYSERR_NOERROR
) {
1286 dprintf_mciwave(stddeb
,"Linux 'widOpen' // can't notify client !\n");
1287 return MMSYSERR_INVALPARAM
;
1289 return MMSYSERR_NOERROR
;
1292 /**************************************************************************
1293 * widClose [internal]
1295 static DWORD
widClose(WORD wDevID
)
1297 dprintf_mciwave(stddeb
,"widClose(%u);\n", wDevID
);
1298 if (WInDev
[wDevID
].unixdev
== 0) {
1299 dprintf_mciwave(stddeb
,"Linux 'widClose' // can't close !\n");
1300 return MMSYSERR_NOTENABLED
;
1302 close(WInDev
[wDevID
].unixdev
);
1303 WInDev
[wDevID
].unixdev
= 0;
1304 WInDev
[wDevID
].bufsize
= 0;
1305 if (WAVE_NotifyClient(wDevID
, WIM_CLOSE
, 0L, 0L) != MMSYSERR_NOERROR
) {
1306 dprintf_mciwave(stddeb
,"Linux 'widClose' // can't notify client !\n");
1307 return MMSYSERR_INVALPARAM
;
1309 return MMSYSERR_NOERROR
;
1312 /**************************************************************************
1313 * widAddBuffer [internal]
1315 static DWORD
widAddBuffer(WORD wDevID
, LPWAVEHDR lpWaveHdr
, DWORD dwSize
)
1319 dprintf_mciwave(stddeb
,
1320 "widAddBuffer(%u, %p, %08lX);\n", wDevID
, lpWaveHdr
, dwSize
);
1321 if (WInDev
[wDevID
].unixdev
== 0) {
1322 dprintf_mciwave(stddeb
,"Linux 'widAddBuffer' // can't do it !\n");
1323 return MMSYSERR_NOTENABLED
;
1325 if (!(lpWaveHdr
->dwFlags
& WHDR_PREPARED
)) {
1326 dprintf_mciwave(stddeb
, "Linux 'widAddBuffer' // never been prepared !\n");
1327 return WAVERR_UNPREPARED
;
1329 if (lpWaveHdr
->dwFlags
& WHDR_INQUEUE
) {
1330 dprintf_mciwave(stddeb
, "Linux 'widAddBuffer' // header already in use !\n");
1331 return WAVERR_STILLPLAYING
;
1333 lpWaveHdr
->dwFlags
|= WHDR_PREPARED
;
1334 lpWaveHdr
->dwFlags
|= WHDR_INQUEUE
;
1335 lpWaveHdr
->dwFlags
&= ~WHDR_DONE
;
1336 lpWaveHdr
->dwBytesRecorded
= 0;
1337 if (WInDev
[wDevID
].lpQueueHdr
== NULL
) {
1338 /* begin the queue with a first header ... */
1339 WInDev
[wDevID
].lpQueueHdr
= lpWaveHdr
;
1340 WInDev
[wDevID
].dwTotalRecorded
= 0;
1343 /* added to the queue, except if it's the one just prepared ... */
1344 lpWIHdr
= WInDev
[wDevID
].lpQueueHdr
;
1345 while (lpWIHdr
->lpNext
!= NULL
) {
1346 lpWIHdr
= lpWIHdr
->lpNext
;
1349 lpWIHdr
->lpNext
= lpWaveHdr
;
1352 dprintf_mciwave(stddeb
,
1353 "widAddBuffer // buffer added ! (now %u in queue)\n", count
);
1354 return MMSYSERR_NOERROR
;
1357 /**************************************************************************
1358 * widPrepare [internal]
1360 static DWORD
widPrepare(WORD wDevID
, LPWAVEHDR lpWaveHdr
, DWORD dwSize
)
1362 dprintf_mciwave(stddeb
,
1363 "widPrepare(%u, %p, %08lX);\n", wDevID
, lpWaveHdr
, dwSize
);
1364 if (WInDev
[wDevID
].unixdev
== 0) {
1365 dprintf_mciwave(stddeb
,"Linux 'widPrepare' // can't prepare !\n");
1366 return MMSYSERR_NOTENABLED
;
1368 if (WInDev
[wDevID
].lpQueueHdr
!= NULL
) {
1369 dprintf_mciwave(stddeb
,"Linux 'widPrepare' // already prepare !\n");
1370 return WAVERR_BADFORMAT
;
1372 if (lpWaveHdr
->dwFlags
& WHDR_INQUEUE
) return WAVERR_STILLPLAYING
;
1373 lpWaveHdr
->dwFlags
|= WHDR_PREPARED
;
1374 lpWaveHdr
->dwFlags
&= ~WHDR_INQUEUE
;
1375 lpWaveHdr
->dwFlags
&= ~WHDR_DONE
;
1376 lpWaveHdr
->dwBytesRecorded
= 0;
1377 dprintf_mciwave(stddeb
,"Linux 'widPrepare' // header prepared !\n");
1378 return MMSYSERR_NOERROR
;
1381 /**************************************************************************
1382 * widUnprepare [internal]
1384 static DWORD
widUnprepare(WORD wDevID
, LPWAVEHDR lpWaveHdr
, DWORD dwSize
)
1386 dprintf_mciwave(stddeb
,
1387 "widUnprepare(%u, %p, %08lX);\n", wDevID
, lpWaveHdr
, dwSize
);
1388 if (WInDev
[wDevID
].unixdev
== 0) {
1389 dprintf_mciwave(stddeb
,"Linux 'widUnprepare' // can't unprepare !\n");
1390 return MMSYSERR_NOTENABLED
;
1392 lpWaveHdr
->dwFlags
&= ~WHDR_PREPARED
;
1393 lpWaveHdr
->dwFlags
&= ~WHDR_INQUEUE
;
1394 lpWaveHdr
->dwFlags
|= WHDR_DONE
;
1395 WInDev
[wDevID
].lpQueueHdr
= NULL
;
1396 dprintf_mciwave(stddeb
,
1397 "Linux 'widUnprepare' // all headers unprepared !\n");
1398 return MMSYSERR_NOERROR
;
1401 /**************************************************************************
1402 * widStart [internal]
1404 static DWORD
widStart(WORD wDevID
)
1408 dprintf_mciwave(stddeb
,"widStart(%u);\n", wDevID
);
1409 if (WInDev
[wDevID
].unixdev
== 0) {
1410 dprintf_mciwave(stddeb
, "Linux 'widStart' // can't start recording !\n");
1411 return MMSYSERR_NOTENABLED
;
1413 if (WInDev
[wDevID
].lpQueueHdr
== NULL
||
1414 WInDev
[wDevID
].lpQueueHdr
->lpData
== NULL
) {
1415 dprintf_mciwave(stddeb
,"Linux 'widStart' // never been prepared !\n");
1416 return WAVERR_UNPREPARED
;
1418 lpWIHdr
= WInDev
[wDevID
].lpQueueHdr
;
1419 while(lpWIHdr
!= NULL
) {
1420 lpWIHdr
->dwBufferLength
&= 0xFFFF;
1421 dprintf_mciwave(stddeb
,
1422 "widStart // recording buf#%u=%p size=%lu \n",
1423 count
, lpWIHdr
->lpData
, lpWIHdr
->dwBufferLength
);
1425 read (WInDev
[wDevID
].unixdev
,
1426 PTR_SEG_TO_LIN(lpWIHdr
->lpData
),
1427 lpWIHdr
->dwBufferLength
);
1428 lpWIHdr
->dwBytesRecorded
= lpWIHdr
->dwBufferLength
;
1429 WInDev
[wDevID
].dwTotalRecorded
+= lpWIHdr
->dwBytesRecorded
;
1430 lpWIHdr
->dwFlags
&= ~WHDR_INQUEUE
;
1431 lpWIHdr
->dwFlags
|= WHDR_DONE
;
1432 if (WAVE_NotifyClient(wDevID
, WIM_DATA
, (DWORD
)lpWIHdr
, 0L) !=
1434 dprintf_mciwave(stddeb
, "Linux 'widStart' // can't notify client !\n");
1435 return MMSYSERR_INVALPARAM
;
1437 lpWIHdr
= lpWIHdr
->lpNext
;
1440 dprintf_mciwave(stddeb
,"widStart // end of recording !\n");
1442 return MMSYSERR_NOERROR
;
1445 /**************************************************************************
1446 * widStop [internal]
1448 static DWORD
widStop(WORD wDevID
)
1450 dprintf_mciwave(stddeb
,"widStop(%u);\n", wDevID
);
1451 if (WInDev
[wDevID
].unixdev
== 0) {
1452 dprintf_mciwave(stddeb
,"Linux 'widStop' // can't stop !\n");
1453 return MMSYSERR_NOTENABLED
;
1455 return MMSYSERR_NOERROR
;
1458 /**************************************************************************
1459 * widReset [internal]
1461 static DWORD
widReset(WORD wDevID
)
1463 dprintf_mciwave(stddeb
,"widReset(%u);\n", wDevID
);
1464 if (WInDev
[wDevID
].unixdev
== 0) {
1465 dprintf_mciwave(stddeb
,"Linux 'widReset' // can't reset !\n");
1466 return MMSYSERR_NOTENABLED
;
1468 return MMSYSERR_NOERROR
;
1471 /**************************************************************************
1472 * widGetPosition [internal]
1474 static DWORD
widGetPosition(WORD wDevID
, LPMMTIME lpTime
, DWORD uSize
)
1478 dprintf_mciwave(stddeb
,
1479 "widGetPosition(%u, %p, %lu);\n", wDevID
, lpTime
, uSize
);
1480 if (WInDev
[wDevID
].unixdev
== 0) {
1481 dprintf_mciwave(stddeb
,"Linux 'widGetPosition' // can't get pos !\n");
1482 return MMSYSERR_NOTENABLED
;
1484 if (lpTime
== NULL
) return MMSYSERR_INVALPARAM
;
1485 dprintf_mciwave(stddeb
,"widGetPosition // wType=%04X !\n",
1487 dprintf_mciwave(stddeb
,"widGetPosition // wBitsPerSample=%u\n",
1488 WInDev
[wDevID
].Format
.wBitsPerSample
);
1489 dprintf_mciwave(stddeb
,"widGetPosition // nSamplesPerSec=%lu\n",
1490 WInDev
[wDevID
].Format
.wf
.nSamplesPerSec
);
1491 dprintf_mciwave(stddeb
,"widGetPosition // nChannels=%u\n",
1492 WInDev
[wDevID
].Format
.wf
.nChannels
);
1493 dprintf_mciwave(stddeb
,"widGetPosition // nAvgBytesPerSec=%lu\n",
1494 WInDev
[wDevID
].Format
.wf
.nAvgBytesPerSec
);
1496 switch(lpTime
->wType
) {
1498 lpTime
->u
.cb
= WInDev
[wDevID
].dwTotalRecorded
;
1499 dprintf_mciwave(stddeb
,
1500 "widGetPosition // TIME_BYTES=%lu\n", lpTime
->u
.cb
);
1503 lpTime
->u
.sample
= WInDev
[wDevID
].dwTotalRecorded
* 8 /
1504 WInDev
[wDevID
].Format
.wBitsPerSample
;
1505 dprintf_mciwave(stddeb
,
1506 "widGetPosition // TIME_SAMPLES=%lu\n",
1510 time
= WInDev
[wDevID
].dwTotalRecorded
/
1511 (WInDev
[wDevID
].Format
.wf
.nAvgBytesPerSec
/ 1000);
1512 lpTime
->u
.smpte
.hour
= time
/ 108000;
1513 time
-= lpTime
->u
.smpte
.hour
* 108000;
1514 lpTime
->u
.smpte
.min
= time
/ 1800;
1515 time
-= lpTime
->u
.smpte
.min
* 1800;
1516 lpTime
->u
.smpte
.sec
= time
/ 30;
1517 time
-= lpTime
->u
.smpte
.sec
* 30;
1518 lpTime
->u
.smpte
.frame
= time
;
1519 lpTime
->u
.smpte
.fps
= 30;
1520 dprintf_mciwave(stddeb
,"widGetPosition // TIME_SMPTE=%02u:%02u:%02u:%02u\n",
1521 lpTime
->u
.smpte
.hour
, lpTime
->u
.smpte
.min
,
1522 lpTime
->u
.smpte
.sec
, lpTime
->u
.smpte
.frame
);
1525 dprintf_mciwave(stddeb
,"widGetPosition() format not supported ! use TIME_MS !\n");
1526 lpTime
->wType
= TIME_MS
;
1528 lpTime
->u
.ms
= WInDev
[wDevID
].dwTotalRecorded
/
1529 (WInDev
[wDevID
].Format
.wf
.nAvgBytesPerSec
/ 1000);
1530 dprintf_mciwave(stddeb
,
1531 "widGetPosition // TIME_MS=%lu\n", lpTime
->u
.ms
);
1534 return MMSYSERR_NOERROR
;
1537 #endif /* linux || __FreeBSD__ */
1539 /**************************************************************************
1540 * widMessage [sample driver]
1542 DWORD
widMessage(WORD wDevID
, WORD wMsg
, DWORD dwUser
,
1543 DWORD dwParam1
, DWORD dwParam2
)
1545 dprintf_mciwave(stddeb
,"widMessage(%u, %04X, %08lX, %08lX, %08lX);\n",
1546 wDevID
, wMsg
, dwUser
, dwParam1
, dwParam2
);
1547 #if defined(linux) || defined(__FreeBSD__)
1550 return widOpen(wDevID
, (LPWAVEOPENDESC
)PTR_SEG_TO_LIN(dwParam1
), dwParam2
);
1552 return widClose(wDevID
);
1553 case WIDM_ADDBUFFER
:
1554 return widAddBuffer(wDevID
, (LPWAVEHDR
)PTR_SEG_TO_LIN(dwParam1
), dwParam2
);
1556 return widPrepare(wDevID
, (LPWAVEHDR
)PTR_SEG_TO_LIN(dwParam1
), dwParam2
);
1557 case WIDM_UNPREPARE
:
1558 return widUnprepare(wDevID
, (LPWAVEHDR
)PTR_SEG_TO_LIN(dwParam1
), dwParam2
);
1559 case WIDM_GETDEVCAPS
:
1560 return widGetDevCaps(wDevID
, (LPWAVEINCAPS
)PTR_SEG_TO_LIN(dwParam1
), dwParam2
);
1561 case WIDM_GETNUMDEVS
:
1564 return widGetPosition(wDevID
, (LPMMTIME
)PTR_SEG_TO_LIN(dwParam1
), dwParam2
);
1566 return widReset(wDevID
);
1568 return widStart(wDevID
);
1570 return widStop(wDevID
);
1572 dprintf_mciwave(stddeb
,"widMessage // unknown message !\n");
1574 return MMSYSERR_NOTSUPPORTED
;
1576 return MMSYSERR_NOTENABLED
;
1581 /**************************************************************************
1582 * AUDIO_DriverProc [sample driver]
1584 LONG
WAVE_DriverProc(DWORD dwDevID
, HDRVR16 hDriv
, WORD wMsg
,
1585 DWORD dwParam1
, DWORD dwParam2
)
1587 #if defined(linux) || defined(__FreeBSD__)
1588 dprintf_mciwave(stddeb
,"WAVE_DriverProc(%08lX, %04X, %04X, %08lX, %08lX)\n",
1589 dwDevID
, hDriv
, wMsg
, dwParam1
, dwParam2
);
1603 case DRV_QUERYCONFIGURE
:
1606 MessageBox16((HWND
)NULL
, "Sample MultiMedia Linux Driver !",
1607 "MMLinux Driver", MB_OK
);
1610 return DRVCNF_RESTART
;
1612 return DRVCNF_RESTART
;
1613 case MCI_OPEN_DRIVER
:
1615 return WAVE_mciOpen(dwDevID
, dwParam1
, (LPMCI_WAVE_OPEN_PARMS
)PTR_SEG_TO_LIN(dwParam2
));
1616 case MCI_CLOSE_DRIVER
:
1618 return WAVE_mciClose(dwDevID
, dwParam1
, (LPMCI_GENERIC_PARMS
)PTR_SEG_TO_LIN(dwParam2
));
1620 return WAVE_mciPlay(dwDevID
, dwParam1
, (LPMCI_PLAY_PARMS
)PTR_SEG_TO_LIN(dwParam2
));
1622 return WAVE_mciRecord(dwDevID
, dwParam1
, (LPMCI_RECORD_PARMS
)PTR_SEG_TO_LIN(dwParam2
));
1624 return WAVE_mciStop(dwDevID
, dwParam1
, (LPMCI_GENERIC_PARMS
)PTR_SEG_TO_LIN(dwParam2
));
1626 return WAVE_mciSet(dwDevID
, dwParam1
, (LPMCI_SET_PARMS
)PTR_SEG_TO_LIN(dwParam2
));
1628 return WAVE_mciPause(dwDevID
, dwParam1
, (LPMCI_GENERIC_PARMS
)PTR_SEG_TO_LIN(dwParam2
));
1630 return WAVE_mciResume(dwDevID
, dwParam1
, (LPMCI_GENERIC_PARMS
)PTR_SEG_TO_LIN(dwParam2
));
1632 return WAVE_mciStatus(dwDevID
, dwParam1
, (LPMCI_STATUS_PARMS
)PTR_SEG_TO_LIN(dwParam2
));
1633 case MCI_GETDEVCAPS
:
1634 return WAVE_mciGetDevCaps(dwDevID
, dwParam1
, (LPMCI_GETDEVCAPS_PARMS
)PTR_SEG_TO_LIN(dwParam2
));
1636 return WAVE_mciInfo(dwDevID
, dwParam1
, (LPMCI_INFO_PARMS
)PTR_SEG_TO_LIN(dwParam2
));
1638 return DefDriverProc(dwDevID
, hDriv
, wMsg
, dwParam1
, dwParam2
);
1641 return MMSYSERR_NOTENABLED
;
1646 #endif /* #ifdef BUILTIN_MMSYSTEM */