2 * Sample Wine Driver for Open Sound System (featured in Linux and FreeBSD)
4 * Copyright 1994 Martin Ayotte
8 * - record/play should and must be done asynchronous
9 * - segmented/linear pointer problems (lpData in waveheaders,W*_DONE cbs)
20 #include <sys/ioctl.h>
31 #include <sys/soundcard.h>
33 #define SOUND_DEV "/dev/dsp"
34 #define MIXER_DEV "/dev/mixer"
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 (1)
43 #define MAX_WAVINDRV (1)
44 #define MAX_MCIWAVDRV (1)
50 WAVEOPENDESC waveDesc;
60 DWORD bufsize; /* OpenSound '/dev/dsp' give us that size */
61 WAVEOPENDESC waveDesc;
65 DWORD dwTotalRecorded;
69 int nUseCount; /* Incremented for each shared open */
70 BOOL16 fShareable; /* TRUE if first open was shareable */
71 WORD wNotifyDeviceID;/* MCI device ID with a pending notification */
72 HANDLE16 hCallback; /* Callback handle for pending notification */
73 HMMIO16 hFile; /* mmio file handle open as Element */
74 MCI_WAVE_OPEN_PARMS16 openParms;
75 PCMWAVEFORMAT WaveFormat;
77 BOOL16 fInput; /* FALSE = Output, TRUE = Input */
80 static LINUX_WAVEOUT WOutDev[MAX_WAVOUTDRV];
81 static LINUX_WAVEIN WInDev[MAX_WAVOUTDRV];
82 static LINUX_MCIWAVE MCIWavDev[MAX_MCIWAVDRV];
85 /**************************************************************************
86 * WAVE_NotifyClient [internal]
88 static DWORD WAVE_NotifyClient(UINT16 wDevID, WORD wMsg,
89 DWORD dwParam1, DWORD dwParam2)
91 dprintf_mciwave(stddeb,"WAVE_NotifyClient // wDevID = %04X wMsg = %d dwParm1 = %04lX dwParam2 = %04lX\n",wDevID, wMsg, dwParam1, dwParam2);
97 if (wDevID > MAX_WAVOUTDRV) return MCIERR_INTERNAL;
99 if (WOutDev[wDevID].wFlags != DCB_NULL && !DriverCallback(
100 WOutDev[wDevID].waveDesc.dwCallBack,
101 WOutDev[wDevID].wFlags,
102 WOutDev[wDevID].waveDesc.hWave,
104 WOutDev[wDevID].waveDesc.dwInstance,
107 dprintf_mciwave(stddeb,"WAVE_NotifyClient // can't notify client !\n");
108 return MMSYSERR_NOERROR;
115 if (wDevID > MAX_WAVINDRV) return MCIERR_INTERNAL;
117 if (WInDev[wDevID].wFlags != DCB_NULL && !DriverCallback(
118 WInDev[wDevID].waveDesc.dwCallBack, WInDev[wDevID].wFlags,
119 WInDev[wDevID].waveDesc.hWave, wMsg,
120 WInDev[wDevID].waveDesc.dwInstance, dwParam1, dwParam2)) {
121 dprintf_mciwave(stddeb,"WAVE_NotifyClient // can't notify client !\n");
122 return MMSYSERR_NOERROR;
130 /**************************************************************************
131 * WAVE_mciOpen [internal]
133 static DWORD WAVE_mciOpen(UINT16 wDevID, DWORD dwFlags, LPMCI_WAVE_OPEN_PARMS16 lpParms)
135 LPPCMWAVEFORMAT lpWaveFormat;
136 WAVEOPENDESC waveDesc;
137 LPSTR lpstrElementName;
141 dprintf_mciwave(stddeb,"WAVE_mciOpen(%04X, %08lX, %p)\n",
142 wDevID, dwFlags, lpParms);
143 if (lpParms == NULL) return MCIERR_INTERNAL;
145 if (MCIWavDev[wDevID].nUseCount > 0) {
146 /* The driver already open on this channel */
147 /* If the driver was opened shareable before and this open specifies */
148 /* shareable then increment the use count */
149 if (MCIWavDev[wDevID].fShareable && (dwFlags & MCI_OPEN_SHAREABLE))
150 ++MCIWavDev[wDevID].nUseCount;
152 return MCIERR_MUST_USE_SHAREABLE;
154 MCIWavDev[wDevID].nUseCount = 1;
155 MCIWavDev[wDevID].fShareable = dwFlags & MCI_OPEN_SHAREABLE;
158 MCIWavDev[wDevID].fInput = FALSE;
160 dprintf_mciwave(stddeb,"WAVE_mciOpen // wDevID=%04X\n", wDevID);
161 dprintf_mciwave(stddeb,"WAVE_mciOpen // before OPEN_ELEMENT\n");
162 if (dwFlags & MCI_OPEN_ELEMENT) {
163 lpstrElementName = (LPSTR)PTR_SEG_TO_LIN(lpParms->lpstrElementName);
164 dprintf_mciwave(stddeb,"WAVE_mciOpen // MCI_OPEN_ELEMENT '%s' !\n",
166 if ( lpstrElementName && (strlen(lpstrElementName) > 0)) {
167 strcpy(str, lpstrElementName);
169 MCIWavDev[wDevID].hFile = mmioOpen16(str, NULL,
170 MMIO_ALLOCBUF | MMIO_READWRITE | MMIO_EXCLUSIVE);
171 if (MCIWavDev[wDevID].hFile == 0) {
172 dprintf_mciwave(stddeb,"WAVE_mciOpen // can't find file='%s' !\n", str);
173 return MCIERR_FILE_NOT_FOUND;
177 MCIWavDev[wDevID].hFile = 0;
179 dprintf_mciwave(stddeb,"WAVE_mciOpen // hFile=%u\n", MCIWavDev[wDevID].hFile);
180 memcpy(&MCIWavDev[wDevID].openParms, lpParms, sizeof(MCI_WAVE_OPEN_PARMS16));
181 MCIWavDev[wDevID].wNotifyDeviceID = lpParms->wDeviceID;
182 lpWaveFormat = &MCIWavDev[wDevID].WaveFormat;
186 lpWaveFormat->wf.wFormatTag = WAVE_FORMAT_PCM;
187 lpWaveFormat->wBitsPerSample = 8;
188 lpWaveFormat->wf.nChannels = 1;
189 lpWaveFormat->wf.nSamplesPerSec = 11025;
190 lpWaveFormat->wf.nAvgBytesPerSec = 11025;
191 lpWaveFormat->wf.nBlockAlign = 1;
193 if (MCIWavDev[wDevID].hFile != 0) {
196 if (mmioDescend(MCIWavDev[wDevID].hFile, &ckMainRIFF, NULL, 0) != 0)
197 return MCIERR_INTERNAL;
198 dprintf_mciwave(stddeb,
199 "WAVE_mciOpen // ParentChunk ckid=%.4s fccType=%.4s cksize=%08lX \n",
200 (LPSTR)&ckMainRIFF.ckid, (LPSTR)&ckMainRIFF.fccType,
202 if ((ckMainRIFF.ckid != FOURCC_RIFF) ||
203 (ckMainRIFF.fccType != mmioFOURCC('W', 'A', 'V', 'E')))
204 return MCIERR_INTERNAL;
205 mmckInfo.ckid = mmioFOURCC('f', 'm', 't', ' ');
206 if (mmioDescend(MCIWavDev[wDevID].hFile, &mmckInfo, &ckMainRIFF, MMIO_FINDCHUNK) != 0)
207 return MCIERR_INTERNAL;
208 dprintf_mciwave(stddeb,
209 "WAVE_mciOpen // Chunk Found ckid=%.4s fccType=%.4s cksize=%08lX \n",
210 (LPSTR)&mmckInfo.ckid, (LPSTR)&mmckInfo.fccType,
212 if (mmioRead(MCIWavDev[wDevID].hFile, (HPSTR) lpWaveFormat,
213 (long) sizeof(PCMWAVEFORMAT)) != (long) sizeof(PCMWAVEFORMAT))
214 return MCIERR_INTERNAL;
215 mmckInfo.ckid = mmioFOURCC('d', 'a', 't', 'a');
216 if (mmioDescend(MCIWavDev[wDevID].hFile, &mmckInfo, &ckMainRIFF, MMIO_FINDCHUNK) != 0)
217 return MCIERR_INTERNAL;
218 dprintf_mciwave(stddeb,
219 "WAVE_mciOpen // Chunk Found ckid=%.4s fccType=%.4s cksize=%08lX \n",
220 (LPSTR)&mmckInfo.ckid, (LPSTR)&mmckInfo.fccType,
222 dprintf_mciwave(stddeb,
223 "WAVE_mciOpen // nChannels=%d nSamplesPerSec=%ld\n",
224 lpWaveFormat->wf.nChannels, lpWaveFormat->wf.nSamplesPerSec);
225 lpWaveFormat->wBitsPerSample = 0;
227 lpWaveFormat->wf.nAvgBytesPerSec =
228 lpWaveFormat->wf.nSamplesPerSec * lpWaveFormat->wf.nBlockAlign;
229 waveDesc.lpFormat = (LPWAVEFORMAT)lpWaveFormat;
232 By default the device will be opened for output, the MCI_CUE function is there to
233 change from output to input and back
236 dwRet=wodMessage(wDevID,WODM_OPEN,0,(DWORD)&waveDesc,CALLBACK_NULL);
240 /**************************************************************************
241 * WAVE_mciCue [internal]
244 static DWORD WAVE_mciCue(UINT16 wDevID, DWORD dwParam, LPMCI_GENERIC_PARMS lpParms)
249 This routine is far from complete. At the moment only a check is done on the
250 MCI_WAVE_INPUT flag. No explicit check on MCI_WAVE_OUTPUT is done since that
253 The flags MCI_NOTIFY (and the callback parameter in lpParms) and MCI_WAIT
258 WAVEOPENDESC waveDesc;
260 dprintf_mciwave(stddeb,"WAVE_mciCue(%u, %08lX, %p);\n", wDevID, dwParam, lpParms);
262 /* always close elements ? */
264 if (MCIWavDev[wDevID].hFile != 0) {
265 mmioClose(MCIWavDev[wDevID].hFile, 0);
266 MCIWavDev[wDevID].hFile = 0;
269 dwRet = MMSYSERR_NOERROR; /* assume success */
270 if ((dwParam & MCI_WAVE_INPUT) && !MCIWavDev[wDevID].fInput) {
271 /* FIXME this is just a hack WOutDev should be hidden here */
272 memcpy(&waveDesc,&WOutDev[wDevID].waveDesc,sizeof(WAVEOPENDESC));
274 dwRet = wodMessage(wDevID, WODM_CLOSE, 0, 0L, 0L);
275 if (dwRet != MMSYSERR_NOERROR) return MCIERR_INTERNAL;
276 dwRet = widMessage(wDevID, WIDM_OPEN, 0, (DWORD)&waveDesc, CALLBACK_NULL);
277 MCIWavDev[wDevID].fInput = TRUE;
279 else if (MCIWavDev[wDevID].fInput) {
280 /* FIXME this is just a hack WInDev should be hidden here */
281 memcpy(&waveDesc,&WInDev[wDevID].waveDesc,sizeof(WAVEOPENDESC));
283 dwRet = widMessage(wDevID, WIDM_CLOSE, 0, 0L, 0L);
284 if (dwRet != MMSYSERR_NOERROR) return MCIERR_INTERNAL;
285 dwRet = wodMessage(wDevID, WODM_OPEN, 0, (DWORD)&waveDesc, CALLBACK_NULL);
286 MCIWavDev[wDevID].fInput = FALSE;
291 /**************************************************************************
292 * WAVE_mciClose [internal]
294 static DWORD WAVE_mciClose(UINT16 wDevID, DWORD dwParam, LPMCI_GENERIC_PARMS lpParms)
298 dprintf_mciwave(stddeb,
299 "WAVE_mciClose(%u, %08lX, %p);\n", wDevID, dwParam, lpParms);
300 MCIWavDev[wDevID].nUseCount--;
301 if (MCIWavDev[wDevID].nUseCount == 0) {
302 if (MCIWavDev[wDevID].hFile != 0) {
303 mmioClose(MCIWavDev[wDevID].hFile, 0);
304 MCIWavDev[wDevID].hFile = 0;
306 if (MCIWavDev[wDevID].fInput)
307 dwRet = widMessage(wDevID, WIDM_CLOSE, 0, 0L, 0L);
309 dwRet = wodMessage(wDevID, WODM_CLOSE, 0, 0L, 0L);
311 if (dwRet != MMSYSERR_NOERROR) return MCIERR_INTERNAL;
317 /**************************************************************************
318 * WAVE_mciPlay [internal]
320 static DWORD WAVE_mciPlay(UINT16 wDevID, DWORD dwFlags, LPMCI_PLAY_PARMS lpParms)
328 dprintf_mciwave(stddeb,
329 "WAVE_mciPlay(%u, %08lX, %p);\n", wDevID, dwFlags, lpParms);
331 if (MCIWavDev[wDevID].fInput) {
332 dprintf_mciwave(stddeb,"WAVE_mciPlay // cannot play on input device\n");
333 return MCIERR_NONAPPLICABLE_FUNCTION;
336 if (MCIWavDev[wDevID].hFile == 0) {
337 dprintf_mciwave(stddeb,"WAVE_mciPlay // can't find file='%08lx' !\n",
338 MCIWavDev[wDevID].openParms.lpstrElementName);
339 return MCIERR_FILE_NOT_FOUND;
341 start = 1; end = 99999;
342 if (dwFlags & MCI_FROM) {
343 start = lpParms->dwFrom;
344 dprintf_mciwave(stddeb,
345 "WAVE_mciPlay // MCI_FROM=%d \n", start);
347 if (dwFlags & MCI_TO) {
349 dprintf_mciwave(stddeb,"WAVE_mciPlay // MCI_TO=%d \n", end);
352 if (dwFlags & MCI_NOTIFY) {
353 dprintf_mciwave(stddeb,
354 "WAVE_mciPlay // MCI_NOTIFY %08lX !\n", lpParms->dwCallback);
357 dprintf_mciwave(stddeb,
358 "WAVE_mciPlay // Can't 'fork' process !\n");
363 dprintf_mciwave(stddeb,"WAVE_mciPlay // process started ! return to caller...\n");
369 lpWaveHdr = &MCIWavDev[wDevID].WaveHdr;
370 hData = GlobalAlloc16(GMEM_MOVEABLE, bufsize);
371 lpWaveHdr->lpData = (LPSTR) GlobalLock16(hData);
372 lpWaveHdr->dwUser = 0L;
373 lpWaveHdr->dwFlags = 0L;
374 lpWaveHdr->dwLoops = 0L;
375 dwRet=wodMessage(wDevID,WODM_PREPARE,0,(DWORD)lpWaveHdr,sizeof(WAVEHDR));
377 count = mmioRead(MCIWavDev[wDevID].hFile, lpWaveHdr->lpData, bufsize);
378 dprintf_mciwave(stddeb,"WAVE_mciPlay // mmioRead bufsize=%ld count=%ld\n", bufsize, count);
379 if (count < 1) break;
380 lpWaveHdr->dwBufferLength = count;
381 /* lpWaveHdr->dwBytesRecorded = count; */
382 dprintf_mciwave(stddeb,"WAVE_mciPlay // before WODM_WRITE lpWaveHdr=%p dwBufferLength=%lu dwBytesRecorded=%lu\n",
383 lpWaveHdr, lpWaveHdr->dwBufferLength, lpWaveHdr->dwBytesRecorded);
384 dwRet=wodMessage(wDevID,WODM_WRITE,0,(DWORD)lpWaveHdr,sizeof(WAVEHDR));
386 dwRet = wodMessage(wDevID,WODM_UNPREPARE,0,(DWORD)lpWaveHdr,sizeof(WAVEHDR));
387 if (lpWaveHdr->lpData != NULL) {
388 GlobalUnlock16(hData);
390 lpWaveHdr->lpData = NULL;
392 if (dwFlags & MCI_NOTIFY) {
393 dprintf_mciwave(stddeb,"WAVE_mciPlay // MCI_NOTIFY_SUCCESSFUL %08lX !\n", lpParms->dwCallback);
394 mciDriverNotify((HWND16)LOWORD(lpParms->dwCallback),
395 MCIWavDev[wDevID].wNotifyDeviceID, MCI_NOTIFY_SUCCESSFUL);
401 /**************************************************************************
402 * WAVE_mciRecord [internal]
404 static DWORD WAVE_mciRecord(UINT16 wDevID, DWORD dwFlags, LPMCI_RECORD_PARMS lpParms)
412 dprintf_mciwave(stddeb,
413 "WAVE_mciRecord(%u, %08lX, %p);\n", wDevID, dwFlags, lpParms);
415 if (!MCIWavDev[wDevID].fInput) {
416 dprintf_mciwave(stddeb,"WAVE_mciPlay // cannot record on output device\n");
417 return MCIERR_NONAPPLICABLE_FUNCTION;
420 if (MCIWavDev[wDevID].hFile == 0) {
421 dprintf_mciwave(stddeb,"WAVE_mciRecord // can't find file='%08lx' !\n",
422 MCIWavDev[wDevID].openParms.lpstrElementName);
423 return MCIERR_FILE_NOT_FOUND;
425 start = 1; end = 99999;
426 if (dwFlags & MCI_FROM) {
427 start = lpParms->dwFrom;
428 dprintf_mciwave(stddeb,
429 "WAVE_mciRecord // MCI_FROM=%d \n", start);
431 if (dwFlags & MCI_TO) {
433 dprintf_mciwave(stddeb,"WAVE_mciRecord // MCI_TO=%d \n", end);
436 lpWaveHdr = &MCIWavDev[wDevID].WaveHdr;
437 hData = GlobalAlloc16(GMEM_MOVEABLE, bufsize);
438 lpWaveHdr->lpData = (LPSTR)GlobalLock16(hData);
439 lpWaveHdr->dwBufferLength = bufsize;
440 lpWaveHdr->dwUser = 0L;
441 lpWaveHdr->dwFlags = 0L;
442 lpWaveHdr->dwLoops = 0L;
443 dwRet=widMessage(wDevID,WIDM_PREPARE,0,(DWORD)lpWaveHdr,sizeof(WAVEHDR));
444 dprintf_mciwave(stddeb,"WAVE_mciRecord // after WIDM_PREPARE \n");
446 lpWaveHdr->dwBytesRecorded = 0;
447 dwRet = widMessage(wDevID, WIDM_START, 0, 0L, 0L);
448 dprintf_mciwave(stddeb,
449 "WAVE_mciRecord // after WIDM_START lpWaveHdr=%p dwBytesRecorded=%lu\n",
450 lpWaveHdr, lpWaveHdr->dwBytesRecorded);
451 if (lpWaveHdr->dwBytesRecorded == 0) break;
453 dprintf_mciwave(stddeb,"WAVE_mciRecord // before WIDM_UNPREPARE \n");
454 dwRet = widMessage(wDevID,WIDM_UNPREPARE,0,(DWORD)lpWaveHdr,sizeof(WAVEHDR));
455 dprintf_mciwave(stddeb,"WAVE_mciRecord // after WIDM_UNPREPARE \n");
456 if (lpWaveHdr->lpData != NULL) {
457 GlobalUnlock16(hData);
459 lpWaveHdr->lpData = NULL;
461 if (dwFlags & MCI_NOTIFY) {
462 dprintf_mciwave(stddeb,"WAVE_mciRecord // MCI_NOTIFY_SUCCESSFUL %08lX !\n", lpParms->dwCallback);
463 mciDriverNotify((HWND16)LOWORD(lpParms->dwCallback),
464 MCIWavDev[wDevID].wNotifyDeviceID, MCI_NOTIFY_SUCCESSFUL);
470 /**************************************************************************
471 * WAVE_mciStop [internal]
473 static DWORD WAVE_mciStop(UINT16 wDevID, DWORD dwFlags, LPMCI_GENERIC_PARMS lpParms)
477 dprintf_mciwave(stddeb,
478 "WAVE_mciStop(%u, %08lX, %p);\n", wDevID, dwFlags, lpParms);
479 if (lpParms == NULL) return MCIERR_INTERNAL;
480 if (MCIWavDev[wDevID].fInput)
481 dwRet = widMessage(wDevID, WIDM_STOP, 0, dwFlags, (DWORD)lpParms);
483 dwRet = wodMessage(wDevID, WODM_STOP, 0, dwFlags, (DWORD)lpParms);
489 /**************************************************************************
490 * WAVE_mciPause [internal]
492 static DWORD WAVE_mciPause(UINT16 wDevID, DWORD dwFlags, LPMCI_GENERIC_PARMS lpParms)
496 dprintf_mciwave(stddeb,
497 "WAVE_mciPause(%u, %08lX, %p);\n", wDevID, dwFlags, lpParms);
498 if (lpParms == NULL) return MCIERR_INTERNAL;
499 if (MCIWavDev[wDevID].fInput)
500 dwRet = widMessage(wDevID, WIDM_PAUSE, 0, dwFlags, (DWORD)lpParms);
502 dwRet = wodMessage(wDevID, WODM_PAUSE, 0, dwFlags, (DWORD)lpParms);
508 /**************************************************************************
509 * WAVE_mciResume [internal]
511 static DWORD WAVE_mciResume(UINT16 wDevID, DWORD dwFlags, LPMCI_GENERIC_PARMS lpParms)
513 dprintf_mciwave(stddeb,
514 "WAVE_mciResume(%u, %08lX, %p);\n", wDevID, dwFlags, lpParms);
515 if (lpParms == NULL) return MCIERR_INTERNAL;
520 /**************************************************************************
521 * WAVE_mciSet [internal]
523 static DWORD WAVE_mciSet(UINT16 wDevID, DWORD dwFlags, LPMCI_SET_PARMS lpParms)
525 dprintf_mciwave(stddeb,
526 "WAVE_mciSet(%u, %08lX, %p);\n", wDevID, dwFlags, lpParms);
527 if (lpParms == NULL) return MCIERR_INTERNAL;
528 dprintf_mciwave(stddeb,
529 "WAVE_mciSet // dwTimeFormat=%08lX\n", lpParms->dwTimeFormat);
530 dprintf_mciwave(stddeb,
531 "WAVE_mciSet // dwAudio=%08lX\n", lpParms->dwAudio);
532 if (dwFlags & MCI_SET_TIME_FORMAT) {
533 switch (lpParms->dwTimeFormat) {
534 case MCI_FORMAT_MILLISECONDS:
535 dprintf_mciwave(stddeb, "WAVE_mciSet // MCI_FORMAT_MILLISECONDS !\n");
537 case MCI_FORMAT_BYTES:
538 dprintf_mciwave(stddeb, "WAVE_mciSet // MCI_FORMAT_BYTES !\n");
540 case MCI_FORMAT_SAMPLES:
541 dprintf_mciwave(stddeb, "WAVE_mciSet // MCI_FORMAT_SAMPLES !\n");
544 dprintf_mciwave(stddeb, "WAVE_mciSet // bad time format !\n");
545 return MCIERR_BAD_TIME_FORMAT;
548 if (dwFlags & MCI_SET_VIDEO) return MCIERR_UNSUPPORTED_FUNCTION;
549 if (dwFlags & MCI_SET_DOOR_OPEN) return MCIERR_UNSUPPORTED_FUNCTION;
550 if (dwFlags & MCI_SET_DOOR_CLOSED) return MCIERR_UNSUPPORTED_FUNCTION;
551 if (dwFlags & MCI_SET_AUDIO)
552 dprintf_mciwave(stddeb,"WAVE_mciSet // MCI_SET_AUDIO !\n");
553 if (dwFlags && MCI_SET_ON) {
554 dprintf_mciwave(stddeb,"WAVE_mciSet // MCI_SET_ON !\n");
555 if (dwFlags && MCI_SET_AUDIO_LEFT)
556 dprintf_mciwave(stddeb,"WAVE_mciSet // MCI_SET_AUDIO_LEFT !\n");
557 if (dwFlags && MCI_SET_AUDIO_RIGHT)
558 dprintf_mciwave(stddeb,"WAVE_mciSet // MCI_SET_AUDIO_RIGHT !\n");
560 if (dwFlags & MCI_SET_OFF)
561 dprintf_mciwave(stddeb,"WAVE_mciSet // MCI_SET_OFF !\n");
562 if (dwFlags & MCI_WAVE_INPUT)
563 dprintf_mciwave(stddeb,"WAVE_mciSet // MCI_WAVE_INPUT !\n");
564 if (dwFlags & MCI_WAVE_OUTPUT)
565 dprintf_mciwave(stddeb,"WAVE_mciSet // MCI_WAVE_OUTPUT !\n");
566 if (dwFlags & MCI_WAVE_SET_ANYINPUT)
567 dprintf_mciwave(stddeb,"WAVE_mciSet // MCI_WAVE_SET_ANYINPUT !\n");
568 if (dwFlags & MCI_WAVE_SET_ANYOUTPUT)
569 dprintf_mciwave(stddeb,"WAVE_mciSet // MCI_WAVE_SET_ANYOUTPUT !\n");
570 if (dwFlags & MCI_WAVE_SET_AVGBYTESPERSEC)
571 dprintf_mciwave(stddeb,
572 "WAVE_mciSet // MCI_WAVE_SET_AVGBYTESPERSEC !\n");
573 if (dwFlags & MCI_WAVE_SET_BITSPERSAMPLE)
574 dprintf_mciwave(stddeb,
575 "WAVE_mciSet // MCI_WAVE_SET_BITSPERSAMPLE !\n");
576 if (dwFlags & MCI_WAVE_SET_BLOCKALIGN)
577 dprintf_mciwave(stddeb,"WAVE_mciSet // MCI_WAVE_SET_BLOCKALIGN !\n");
578 if (dwFlags & MCI_WAVE_SET_CHANNELS)
579 dprintf_mciwave(stddeb,"WAVE_mciSet // MCI_WAVE_SET_CHANNELS !\n");
580 if (dwFlags & MCI_WAVE_SET_FORMATTAG)
581 dprintf_mciwave(stddeb,"WAVE_mciSet // MCI_WAVE_SET_FORMATTAG !\n");
582 if (dwFlags & MCI_WAVE_SET_SAMPLESPERSEC)
583 dprintf_mciwave(stddeb,
584 "WAVE_mciSet // MCI_WAVE_SET_SAMPLESPERSEC !\n");
589 /**************************************************************************
590 * WAVE_mciStatus [internal]
592 static DWORD WAVE_mciStatus(UINT16 wDevID, DWORD dwFlags, LPMCI_STATUS_PARMS lpParms)
594 dprintf_mciwave(stddeb,
595 "WAVE_mciStatus(%u, %08lX, %p);\n", wDevID, dwFlags, lpParms);
596 if (lpParms == NULL) return MCIERR_INTERNAL;
597 if (dwFlags & MCI_STATUS_ITEM) {
598 switch(lpParms->dwItem) {
599 case MCI_STATUS_CURRENT_TRACK:
600 lpParms->dwReturn = 1;
602 case MCI_STATUS_LENGTH:
603 lpParms->dwReturn = 5555;
604 if (dwFlags & MCI_TRACK) {
605 lpParms->dwTrack = 1;
606 lpParms->dwReturn = 2222;
609 case MCI_STATUS_MODE:
610 lpParms->dwReturn = MCI_MODE_STOP;
612 case MCI_STATUS_MEDIA_PRESENT:
613 dprintf_mciwave(stddeb,"WAVE_mciStatus // MCI_STATUS_MEDIA_PRESENT !\n");
614 lpParms->dwReturn = TRUE;
616 case MCI_STATUS_NUMBER_OF_TRACKS:
617 lpParms->dwReturn = 1;
619 case MCI_STATUS_POSITION:
620 lpParms->dwReturn = 3333;
621 if (dwFlags & MCI_STATUS_START)
623 if (dwFlags & MCI_TRACK) {
624 lpParms->dwTrack = 1;
625 lpParms->dwReturn = 777;
628 case MCI_STATUS_READY:
629 dprintf_mciwave(stddeb,"WAVE_mciStatus // MCI_STATUS_READY !\n");
630 lpParms->dwReturn = TRUE;
632 case MCI_STATUS_TIME_FORMAT:
633 dprintf_mciwave(stddeb,"WAVE_mciStatus // MCI_STATUS_TIME_FORMAT !\n");
634 lpParms->dwReturn = MCI_FORMAT_MILLISECONDS;
637 dprintf_mciwave(stddeb,"WAVE_mciStatus // MCI_WAVE_INPUT !\n");
638 lpParms->dwReturn = 0;
640 case MCI_WAVE_OUTPUT:
641 dprintf_mciwave(stddeb,"WAVE_mciStatus // MCI_WAVE_OUTPUT !\n");
642 lpParms->dwReturn = 0;
644 case MCI_WAVE_STATUS_AVGBYTESPERSEC:
645 dprintf_mciwave(stddeb,"WAVE_mciStatus // MCI_WAVE_STATUS_AVGBYTESPERSEC !\n");
646 lpParms->dwReturn = 22050;
648 case MCI_WAVE_STATUS_BITSPERSAMPLE:
649 dprintf_mciwave(stddeb,"WAVE_mciStatus // MCI_WAVE_STATUS_BITSPERSAMPLE !\n");
650 lpParms->dwReturn = 8;
652 case MCI_WAVE_STATUS_BLOCKALIGN:
653 dprintf_mciwave(stddeb,"WAVE_mciStatus // MCI_WAVE_STATUS_BLOCKALIGN !\n");
654 lpParms->dwReturn = 1;
656 case MCI_WAVE_STATUS_CHANNELS:
657 dprintf_mciwave(stddeb,"WAVE_mciStatus // MCI_WAVE_STATUS_CHANNELS !\n");
658 lpParms->dwReturn = 1;
660 case MCI_WAVE_STATUS_FORMATTAG:
661 dprintf_mciwave(stddeb,"WAVE_mciStatus // MCI_WAVE_FORMATTAG !\n");
662 lpParms->dwReturn = WAVE_FORMAT_PCM;
664 case MCI_WAVE_STATUS_LEVEL:
665 dprintf_mciwave(stddeb,"WAVE_mciStatus // MCI_WAVE_STATUS_LEVEL !\n");
666 lpParms->dwReturn = 0xAAAA5555;
668 case MCI_WAVE_STATUS_SAMPLESPERSEC:
669 dprintf_mciwave(stddeb,"WAVE_mciStatus // MCI_WAVE_STATUS_SAMPLESPERSEC !\n");
670 lpParms->dwReturn = 22050;
673 dprintf_mciwave(stddeb,"WAVE_mciStatus // unknown command %08lX !\n", lpParms->dwItem);
674 return MCIERR_UNRECOGNIZED_COMMAND;
677 if (dwFlags & MCI_NOTIFY) {
678 dprintf_mciwave(stddeb,"WAVE_mciStatus // MCI_NOTIFY_SUCCESSFUL %08lX !\n", lpParms->dwCallback);
679 mciDriverNotify((HWND16)LOWORD(lpParms->dwCallback),
680 MCIWavDev[wDevID].wNotifyDeviceID, MCI_NOTIFY_SUCCESSFUL);
685 /**************************************************************************
686 * WAVE_mciGetDevCaps [internal]
688 static DWORD WAVE_mciGetDevCaps(UINT16 wDevID, DWORD dwFlags,
689 LPMCI_GETDEVCAPS_PARMS lpParms)
691 dprintf_mciwave(stddeb,
692 "WAVE_mciGetDevCaps(%u, %08lX, %p);\n", wDevID, dwFlags, lpParms);
693 if (lpParms == NULL) return MCIERR_INTERNAL;
694 if (dwFlags & MCI_GETDEVCAPS_ITEM) {
695 switch(lpParms->dwItem) {
696 case MCI_GETDEVCAPS_CAN_RECORD:
697 lpParms->dwReturn = TRUE;
699 case MCI_GETDEVCAPS_HAS_AUDIO:
700 lpParms->dwReturn = TRUE;
702 case MCI_GETDEVCAPS_HAS_VIDEO:
703 lpParms->dwReturn = FALSE;
705 case MCI_GETDEVCAPS_DEVICE_TYPE:
706 lpParms->dwReturn = MCI_DEVTYPE_WAVEFORM_AUDIO;
708 case MCI_GETDEVCAPS_USES_FILES:
709 lpParms->dwReturn = TRUE;
711 case MCI_GETDEVCAPS_COMPOUND_DEVICE:
712 lpParms->dwReturn = TRUE;
714 case MCI_GETDEVCAPS_CAN_EJECT:
715 lpParms->dwReturn = FALSE;
717 case MCI_GETDEVCAPS_CAN_PLAY:
718 lpParms->dwReturn = TRUE;
720 case MCI_GETDEVCAPS_CAN_SAVE:
721 lpParms->dwReturn = TRUE;
723 case MCI_WAVE_GETDEVCAPS_INPUTS:
724 lpParms->dwReturn = 1;
726 case MCI_WAVE_GETDEVCAPS_OUTPUTS:
727 lpParms->dwReturn = 1;
730 return MCIERR_UNRECOGNIZED_COMMAND;
736 /**************************************************************************
737 * WAVE_mciInfo [internal]
739 static DWORD WAVE_mciInfo(UINT16 wDevID, DWORD dwFlags, LPMCI_INFO_PARMS16 lpParms)
741 dprintf_mciwave(stddeb,
742 "WAVE_mciInfo(%u, %08lX, %p);\n", wDevID, dwFlags, lpParms);
743 if (lpParms == NULL) return MCIERR_INTERNAL;
744 lpParms->lpstrReturn = NULL;
746 case MCI_INFO_PRODUCT:
747 lpParms->lpstrReturn = "Open Sound System 0.5";
750 lpParms->lpstrReturn =
751 (LPSTR)MCIWavDev[wDevID].openParms.lpstrElementName;
754 lpParms->lpstrReturn = "Open Sound System 0.5";
756 case MCI_WAVE_OUTPUT:
757 lpParms->lpstrReturn = "Open Sound System 0.5";
760 return MCIERR_UNRECOGNIZED_COMMAND;
762 if (lpParms->lpstrReturn != NULL)
763 lpParms->dwRetSize = strlen(lpParms->lpstrReturn);
765 lpParms->dwRetSize = 0;
770 /*-----------------------------------------------------------------------*/
773 /**************************************************************************
774 * wodGetDevCaps [internal]
776 static DWORD wodGetDevCaps(WORD wDevID, LPWAVEOUTCAPS16 lpCaps, DWORD dwSize)
784 dprintf_mciwave(stddeb,
785 "wodGetDevCaps(%u, %p, %lu);\n", wDevID, lpCaps, dwSize);
786 if (lpCaps == NULL) return MMSYSERR_NOTENABLED;
787 if (access(SOUND_DEV,0) != 0) return MMSYSERR_NOTENABLED;
788 audio = open (SOUND_DEV, O_WRONLY, 0);
789 if (audio == -1) return MMSYSERR_ALLOCATED ;
791 lpCaps->wMid = 0x0002;
792 lpCaps->wPid = 0x0104;
793 strcpy(lpCaps->szPname, "SB16 Wave Out");
795 lpCaps->wMid = 0x00FF; /* Manufac ID */
796 lpCaps->wPid = 0x0001; /* Product ID */
797 strcpy(lpCaps->szPname, "OpenSoundSystem WAVOUT Driver");
799 lpCaps->vDriverVersion = 0x0100;
800 lpCaps->dwFormats = 0x00000000;
801 lpCaps->dwSupport = WAVECAPS_VOLUME;
802 lpCaps->wChannels = (IOCTL(audio, SNDCTL_DSP_STEREO, dsp_stereo) != 0) ? 1 : 2;
803 if (lpCaps->wChannels > 1) lpCaps->dwSupport |= WAVECAPS_LRVOLUME;
804 bytespersmpl = (IOCTL(audio, SNDCTL_DSP_SAMPLESIZE, samplesize) != 0) ? 1 : 2;
806 if (IOCTL(audio, SNDCTL_DSP_SPEED, smplrate) == 0) {
807 lpCaps->dwFormats |= WAVE_FORMAT_4M08;
808 if (lpCaps->wChannels > 1)
809 lpCaps->dwFormats |= WAVE_FORMAT_4S08;
810 if (bytespersmpl > 1) {
811 lpCaps->dwFormats |= WAVE_FORMAT_4M16;
812 if (lpCaps->wChannels > 1)
813 lpCaps->dwFormats |= WAVE_FORMAT_4S16;
817 if (IOCTL(audio, SNDCTL_DSP_SPEED, smplrate) == 0) {
818 lpCaps->dwFormats |= WAVE_FORMAT_2M08;
819 if (lpCaps->wChannels > 1)
820 lpCaps->dwFormats |= WAVE_FORMAT_2S08;
821 if (bytespersmpl > 1) {
822 lpCaps->dwFormats |= WAVE_FORMAT_2M16;
823 if (lpCaps->wChannels > 1)
824 lpCaps->dwFormats |= WAVE_FORMAT_2S16;
828 if (IOCTL(audio, SNDCTL_DSP_SPEED, smplrate) == 0) {
829 lpCaps->dwFormats |= WAVE_FORMAT_1M08;
830 if (lpCaps->wChannels > 1)
831 lpCaps->dwFormats |= WAVE_FORMAT_1S08;
832 if (bytespersmpl > 1) {
833 lpCaps->dwFormats |= WAVE_FORMAT_1M16;
834 if (lpCaps->wChannels > 1)
835 lpCaps->dwFormats |= WAVE_FORMAT_1S16;
839 dprintf_mciwave(stddeb,
840 "wodGetDevCaps // dwFormats = %08lX\n", lpCaps->dwFormats);
841 return MMSYSERR_NOERROR;
845 /**************************************************************************
848 static DWORD wodOpen(WORD wDevID, LPWAVEOPENDESC lpDesc, DWORD dwFlags)
850 int audio,abuf_size,smplrate,samplesize,dsp_stereo;
851 LPWAVEFORMAT lpFormat;
853 dprintf_mciwave(stddeb,
854 "wodOpen(%u, %p, %08lX);\n", wDevID, lpDesc, dwFlags);
855 if (lpDesc == NULL) {
856 dprintf_mciwave(stddeb,"Linux 'wodOpen' // Invalid Parameter !\n");
857 return MMSYSERR_INVALPARAM;
859 if (wDevID >= MAX_WAVOUTDRV) {
860 dprintf_mciwave(stddeb,"Linux 'wodOpen' // MAX_WAVOUTDRV reached !\n");
861 return MMSYSERR_ALLOCATED;
863 WOutDev[wDevID].unixdev = 0;
864 if (access(SOUND_DEV,0) != 0) return MMSYSERR_NOTENABLED;
865 audio = open (SOUND_DEV, O_WRONLY, 0);
867 dprintf_mciwave(stddeb,"Linux 'wodOpen' // can't open !\n");
868 return MMSYSERR_ALLOCATED ;
870 IOCTL(audio, SNDCTL_DSP_GETBLKSIZE, abuf_size);
871 if (abuf_size < 1024 || abuf_size > 65536) {
873 dprintf_mciwave(stddeb,"Linux 'wodOpen' // IOCTL can't 'SNDCTL_DSP_GETBLKSIZE' !\n");
875 dprintf_mciwave(stddeb,"Linux 'wodOpen' // SNDCTL_DSP_GETBLKSIZE Invalid bufsize !\n");
876 return MMSYSERR_NOTENABLED;
878 WOutDev[wDevID].wFlags = HIWORD(dwFlags & CALLBACK_TYPEMASK);
879 switch(WOutDev[wDevID].wFlags) {
881 dprintf_mciwave(stddeb, "Linux 'wodOpen' // CALLBACK_NULL !\n");
884 dprintf_mciwave(stddeb, "Linux 'wodOpen' // CALLBACK_WINDOW !\n");
887 dprintf_mciwave(stddeb, "Linux 'wodOpen' // CALLBACK_TASK !\n");
890 dprintf_mciwave(stddeb, "Linux 'wodOpen' // CALLBACK_FUNCTION !\n");
893 WOutDev[wDevID].lpQueueHdr = NULL;
894 WOutDev[wDevID].unixdev = audio;
895 WOutDev[wDevID].dwTotalPlayed = 0;
896 WOutDev[wDevID].bufsize = abuf_size;
897 /* FIXME: copy lpFormat too? */
898 memcpy(&WOutDev[wDevID].waveDesc, lpDesc, sizeof(WAVEOPENDESC));
899 dprintf_mciwave(stddeb,"Linux 'wodOpen' // lpDesc->lpFormat = %p\n",lpDesc->lpFormat);
900 lpFormat = lpDesc->lpFormat;
901 dprintf_mciwave(stddeb,"Linux 'wodOpen' // lpFormat = %p\n",lpFormat);
902 if (lpFormat->wFormatTag != WAVE_FORMAT_PCM) {
903 dprintf_mciwave(stddeb,"Linux 'wodOpen' // Bad format %04X !\n",
904 lpFormat->wFormatTag);
905 dprintf_mciwave(stddeb,"Linux 'wodOpen' // Bad nChannels %d !\n",
906 lpFormat->nChannels);
907 dprintf_mciwave(stddeb,"Linux 'wodOpen' // Bad nSamplesPerSec %ld !\n",
908 lpFormat->nSamplesPerSec);
909 return WAVERR_BADFORMAT;
911 memcpy(&WOutDev[wDevID].Format, lpFormat, sizeof(PCMWAVEFORMAT));
912 if (WOutDev[wDevID].Format.wf.nChannels == 0) return WAVERR_BADFORMAT;
913 if (WOutDev[wDevID].Format.wf.nSamplesPerSec == 0) return WAVERR_BADFORMAT;
914 dprintf_mciwave(stddeb,"Linux 'wodOpen' // wBitsPerSample=%u !\n",
915 WOutDev[wDevID].Format.wBitsPerSample);
916 if (WOutDev[wDevID].Format.wBitsPerSample == 0) {
917 WOutDev[wDevID].Format.wBitsPerSample = 8 *
918 (WOutDev[wDevID].Format.wf.nAvgBytesPerSec /
919 WOutDev[wDevID].Format.wf.nSamplesPerSec) /
920 WOutDev[wDevID].Format.wf.nChannels;
922 samplesize = WOutDev[wDevID].Format.wBitsPerSample;
923 smplrate = WOutDev[wDevID].Format.wf.nSamplesPerSec;
924 dsp_stereo = (WOutDev[wDevID].Format.wf.nChannels > 1) ? TRUE : FALSE;
925 IOCTL(audio, SNDCTL_DSP_SPEED, smplrate);
926 IOCTL(audio, SNDCTL_DSP_SAMPLESIZE, samplesize);
927 IOCTL(audio, SNDCTL_DSP_STEREO, dsp_stereo);
928 dprintf_mciwave(stddeb,"Linux 'wodOpen' // wBitsPerSample=%u !\n",
929 WOutDev[wDevID].Format.wBitsPerSample);
930 dprintf_mciwave(stddeb,"Linux 'wodOpen' // nAvgBytesPerSec=%lu !\n",
931 WOutDev[wDevID].Format.wf.nAvgBytesPerSec);
932 dprintf_mciwave(stddeb,"Linux 'wodOpen' // nSamplesPerSec=%lu !\n",
933 WOutDev[wDevID].Format.wf.nSamplesPerSec);
934 dprintf_mciwave(stddeb,"Linux 'wodOpen' // nChannels=%u !\n",
935 WOutDev[wDevID].Format.wf.nChannels);
936 if (WAVE_NotifyClient(wDevID, WOM_OPEN, 0L, 0L) != MMSYSERR_NOERROR) {
937 dprintf_mciwave(stddeb,"Linux 'wodOpen' // can't notify client !\n");
938 return MMSYSERR_INVALPARAM;
940 return MMSYSERR_NOERROR;
943 /**************************************************************************
944 * wodClose [internal]
946 static DWORD wodClose(WORD wDevID)
948 dprintf_mciwave(stddeb,"wodClose(%u);\n", wDevID);
949 if (wDevID > MAX_WAVOUTDRV) return MMSYSERR_INVALPARAM;
950 if (WOutDev[wDevID].unixdev == 0) {
951 dprintf_mciwave(stddeb,"Linux 'wodClose' // can't close !\n");
952 return MMSYSERR_NOTENABLED;
954 if (WOutDev[wDevID].lpQueueHdr != NULL) {
955 dprintf_mciwave(stddeb,"linux 'wodclose' // still buffers open !\n");
956 /* Don't care. Who needs those buffers anyway */
957 /*return WAVERR_STILLPLAYING; */
959 close(WOutDev[wDevID].unixdev);
960 WOutDev[wDevID].unixdev = 0;
961 WOutDev[wDevID].bufsize = 0;
962 WOutDev[wDevID].lpQueueHdr = NULL;
963 if (WAVE_NotifyClient(wDevID, WOM_CLOSE, 0L, 0L) != MMSYSERR_NOERROR) {
964 dprintf_mciwave(stddeb,"Linux 'wodClose' // can't notify client !\n");
965 return MMSYSERR_INVALPARAM;
967 return MMSYSERR_NOERROR;
970 /**************************************************************************
971 * wodWrite [internal]
972 * FIXME: this should _APPEND_ the lpWaveHdr to the output queue of the
973 * device, and initiate async playing.
975 static DWORD wodWrite(WORD wDevID, LPWAVEHDR lpWaveHdr, DWORD dwSize)
981 dprintf_mciwave(stddeb,"wodWrite(%u, %p, %08lX);\n", wDevID, lpWaveHdr, dwSize);
982 if (WOutDev[wDevID].unixdev == 0) {
983 dprintf_mciwave(stddeb,"Linux 'wodWrite' // can't play !\n");
984 return MMSYSERR_NOTENABLED;
986 if (lpWaveHdr->lpData == NULL) return WAVERR_UNPREPARED;
987 if (!(lpWaveHdr->dwFlags & WHDR_PREPARED)) return WAVERR_UNPREPARED;
988 if (lpWaveHdr->dwFlags & WHDR_INQUEUE) return WAVERR_STILLPLAYING;
989 lpWaveHdr->dwFlags &= ~WHDR_DONE;
990 lpWaveHdr->dwFlags |= WHDR_INQUEUE;
991 dprintf_mciwave(stddeb,
992 "wodWrite() // dwBufferLength %lu !\n", lpWaveHdr->dwBufferLength);
993 dprintf_mciwave(stddeb,
994 "wodWrite() // WOutDev[%u].unixdev %u !\n", wDevID, WOutDev[wDevID].unixdev);
995 lpData = lpWaveHdr->lpData;
996 count = write (WOutDev[wDevID].unixdev, lpData, lpWaveHdr->dwBufferLength);
997 dprintf_mciwave(stddeb,"wodWrite()//write returned count %u !\n",count);
998 if (count != lpWaveHdr->dwBufferLength) {
999 dprintf_mciwave(stddeb,"Linux 'wodWrite' // error writting !\n");
1000 return MMSYSERR_NOTENABLED;
1002 WOutDev[wDevID].dwTotalPlayed += count;
1003 lpWaveHdr->dwFlags &= ~WHDR_INQUEUE;
1004 lpWaveHdr->dwFlags |= WHDR_DONE;
1005 if ((DWORD)lpWaveHdr->lpData!=lpWaveHdr->reserved) {
1006 /* FIXME: what if it expects it's OWN lpwavehdr back? */
1007 xwavehdr = SEGPTR_NEW(WAVEHDR);
1008 memcpy(xwavehdr,lpWaveHdr,sizeof(WAVEHDR));
1009 xwavehdr->lpData = (LPBYTE)xwavehdr->reserved;
1010 if (WAVE_NotifyClient(wDevID, WOM_DONE, (DWORD)SEGPTR_GET(xwavehdr), count) != MMSYSERR_NOERROR) {
1011 dprintf_mciwave(stddeb,"Linux 'wodWrite' // can't notify client !\n");
1012 SEGPTR_FREE(xwavehdr);
1013 return MMSYSERR_INVALPARAM;
1015 SEGPTR_FREE(xwavehdr);
1017 if (WAVE_NotifyClient(wDevID, WOM_DONE, (DWORD)lpWaveHdr, count) != MMSYSERR_NOERROR) {
1018 dprintf_mciwave(stddeb,"Linux 'wodWrite' // can't notify client !\n");
1019 return MMSYSERR_INVALPARAM;
1022 return MMSYSERR_NOERROR;
1025 /**************************************************************************
1026 * wodPrepare [internal]
1028 static DWORD wodPrepare(WORD wDevID, LPWAVEHDR lpWaveHdr, DWORD dwSize)
1030 dprintf_mciwave(stddeb,
1031 "wodPrepare(%u, %p, %08lX);\n", wDevID, lpWaveHdr, dwSize);
1032 if (WOutDev[wDevID].unixdev == 0) {
1033 dprintf_mciwave(stddeb,"Linux 'wodPrepare' // can't prepare !\n");
1034 return MMSYSERR_NOTENABLED;
1036 /* don't append to queue, wodWrite does that */
1037 WOutDev[wDevID].dwTotalPlayed = 0;
1038 if (lpWaveHdr->dwFlags & WHDR_INQUEUE)
1039 return WAVERR_STILLPLAYING;
1040 lpWaveHdr->dwFlags |= WHDR_PREPARED;
1041 lpWaveHdr->dwFlags &= ~WHDR_DONE;
1042 return MMSYSERR_NOERROR;
1045 /**************************************************************************
1046 * wodUnprepare [internal]
1048 static DWORD wodUnprepare(WORD wDevID, LPWAVEHDR lpWaveHdr, DWORD dwSize)
1050 dprintf_mciwave(stddeb,
1051 "wodUnprepare(%u, %p, %08lX);\n", wDevID, lpWaveHdr, dwSize);
1052 if (WOutDev[wDevID].unixdev == 0) {
1053 dprintf_mciwave(stddeb,"Linux 'wodUnprepare' // can't unprepare !\n");
1054 return MMSYSERR_NOTENABLED;
1056 if (lpWaveHdr->dwFlags & WHDR_INQUEUE)
1057 return WAVERR_STILLPLAYING;
1059 lpWaveHdr->dwFlags &= ~WHDR_PREPARED;
1060 lpWaveHdr->dwFlags |= WHDR_DONE;
1061 dprintf_mciwave(stddeb,
1062 "Linux 'wodUnprepare' // all headers unprepared !\n");
1063 return MMSYSERR_NOERROR;
1066 /**************************************************************************
1067 * wodRestart [internal]
1069 static DWORD wodRestart(WORD wDevID)
1071 dprintf_mciwave(stddeb,"wodRestart(%u);\n", wDevID);
1072 if (WOutDev[wDevID].unixdev == 0) {
1073 dprintf_mciwave(stddeb,"Linux 'wodRestart' // can't restart !\n");
1074 return MMSYSERR_NOTENABLED;
1076 /* FIXME: is NotifyClient with WOM_DONE right ? (Comet Busters 1.3.3 needs this notification) */
1077 if (WAVE_NotifyClient(wDevID, WOM_DONE, 0L, 0L) != MMSYSERR_NOERROR) {
1078 dprintf_mciwave(stddeb,"Linux 'wodRestart' // can't notify client !\n");
1079 return MMSYSERR_INVALPARAM;
1082 return MMSYSERR_NOERROR;
1085 /**************************************************************************
1086 * wodReset [internal]
1088 static DWORD wodReset(WORD wDevID)
1090 dprintf_mciwave(stddeb,"wodReset(%u);\n", wDevID);
1091 if (WOutDev[wDevID].unixdev == 0) {
1092 dprintf_mciwave(stddeb,"Linux 'wodReset' // can't reset !\n");
1093 return MMSYSERR_NOTENABLED;
1095 return MMSYSERR_NOERROR;
1099 /**************************************************************************
1100 * wodGetPosition [internal]
1102 static DWORD wodGetPosition(WORD wDevID, LPMMTIME16 lpTime, DWORD uSize)
1105 dprintf_mciwave(stddeb,"wodGetPosition(%u, %p, %lu);\n", wDevID, lpTime, uSize);
1106 if (WOutDev[wDevID].unixdev == 0) {
1107 dprintf_mciwave(stddeb,"Linux 'wodGetPosition' // can't get pos !\n");
1108 return MMSYSERR_NOTENABLED;
1110 if (lpTime == NULL) return MMSYSERR_INVALPARAM;
1111 dprintf_mciwave(stddeb,"wodGetPosition // wType=%04X !\n",
1113 dprintf_mciwave(stddeb,"wodGetPosition // wBitsPerSample=%u\n",
1114 WOutDev[wDevID].Format.wBitsPerSample);
1115 dprintf_mciwave(stddeb,"wodGetPosition // nSamplesPerSec=%lu\n",
1116 WOutDev[wDevID].Format.wf.nSamplesPerSec);
1117 dprintf_mciwave(stddeb,"wodGetPosition // nChannels=%u\n",
1118 WOutDev[wDevID].Format.wf.nChannels);
1119 dprintf_mciwave(stddeb,"wodGetPosition // nAvgBytesPerSec=%lu\n",
1120 WOutDev[wDevID].Format.wf.nAvgBytesPerSec);
1121 switch(lpTime->wType) {
1123 lpTime->u.cb = WOutDev[wDevID].dwTotalPlayed;
1124 dprintf_mciwave(stddeb,"wodGetPosition // TIME_BYTES=%lu\n", lpTime->u.cb);
1127 dprintf_mciwave(stddeb,"wodGetPosition // dwTotalPlayed=%lu\n",
1128 WOutDev[wDevID].dwTotalPlayed);
1129 dprintf_mciwave(stddeb,"wodGetPosition // wBitsPerSample=%u\n",
1130 WOutDev[wDevID].Format.wBitsPerSample);
1131 lpTime->u.sample = WOutDev[wDevID].dwTotalPlayed * 8 /
1132 WOutDev[wDevID].Format.wBitsPerSample;
1133 dprintf_mciwave(stddeb,"wodGetPosition // TIME_SAMPLES=%lu\n", lpTime->u.sample);
1136 time = WOutDev[wDevID].dwTotalPlayed /
1137 (WOutDev[wDevID].Format.wf.nAvgBytesPerSec / 1000);
1138 lpTime->u.smpte.hour = time / 108000;
1139 time -= lpTime->u.smpte.hour * 108000;
1140 lpTime->u.smpte.min = time / 1800;
1141 time -= lpTime->u.smpte.min * 1800;
1142 lpTime->u.smpte.sec = time / 30;
1143 time -= lpTime->u.smpte.sec * 30;
1144 lpTime->u.smpte.frame = time;
1145 lpTime->u.smpte.fps = 30;
1146 dprintf_mciwave(stddeb,
1147 "wodGetPosition // TIME_SMPTE=%02u:%02u:%02u:%02u\n",
1148 lpTime->u.smpte.hour, lpTime->u.smpte.min,
1149 lpTime->u.smpte.sec, lpTime->u.smpte.frame);
1152 dprintf_mciwave(stddeb,"wodGetPosition() format not supported ! use TIME_MS !\n");
1153 lpTime->wType = TIME_MS;
1155 lpTime->u.ms = WOutDev[wDevID].dwTotalPlayed /
1156 (WOutDev[wDevID].Format.wf.nAvgBytesPerSec / 1000);
1157 dprintf_mciwave(stddeb,"wodGetPosition // TIME_MS=%lu\n", lpTime->u.ms);
1160 return MMSYSERR_NOERROR;
1163 /**************************************************************************
1164 * wodGetVolume [internal]
1166 static DWORD wodGetVolume(WORD wDevID, LPDWORD lpdwVol)
1169 int volume, left, right;
1170 dprintf_mciwave(stddeb,"wodGetVolume(%u, %p);\n", wDevID, lpdwVol);
1171 if (lpdwVol == NULL) return MMSYSERR_NOTENABLED;
1172 if ((mixer = open(MIXER_DEV, O_RDONLY)) < 0) {
1173 dprintf_mciwave(stddeb, "Linux 'wodGetVolume' // mixer device not available !\n");
1174 return MMSYSERR_NOTENABLED;
1176 if (ioctl(mixer, SOUND_MIXER_READ_PCM, &volume) == -1) {
1177 dprintf_mciwave(stddeb,"Linux 'wodGetVolume' // unable read mixer !\n");
1178 return MMSYSERR_NOTENABLED;
1181 left = volume & 0x7F;
1182 right = (volume >> 8) & 0x7F;
1183 dprintf_mciwave(stddeb,"Linux 'wodGetVolume' // left=%d right=%d !\n", left, right);
1184 *lpdwVol = MAKELONG(left << 9, right << 9);
1185 return MMSYSERR_NOERROR;
1189 /**************************************************************************
1190 * wodSetVolume [internal]
1192 static DWORD wodSetVolume(WORD wDevID, DWORD dwParam)
1196 dprintf_mciwave(stddeb,"wodSetVolume(%u, %08lX);\n", wDevID, dwParam);
1197 volume = (LOWORD(dwParam) >> 9 & 0x7F) +
1198 ((HIWORD(dwParam) >> 9 & 0x7F) << 8);
1199 if ((mixer = open(MIXER_DEV, O_WRONLY)) < 0) {
1200 dprintf_mciwave(stddeb, "Linux 'wodSetVolume' // mixer device not available !\n");
1201 return MMSYSERR_NOTENABLED;
1203 if (ioctl(mixer, SOUND_MIXER_WRITE_PCM, &volume) == -1) {
1204 dprintf_mciwave(stddeb,"Linux 'wodSetVolume' // unable set mixer !\n");
1205 return MMSYSERR_NOTENABLED;
1208 return MMSYSERR_NOERROR;
1211 /**************************************************************************
1212 * wodMessage [sample driver]
1214 DWORD wodMessage(WORD wDevID, WORD wMsg, DWORD dwUser,
1215 DWORD dwParam1, DWORD dwParam2)
1217 dprintf_mciwave(stddeb,"wodMessage(%u, %04X, %08lX, %08lX, %08lX);\n",
1218 wDevID, wMsg, dwUser, dwParam1, dwParam2);
1221 return wodOpen(wDevID, (LPWAVEOPENDESC)dwParam1, dwParam2);
1223 return wodClose(wDevID);
1225 return wodWrite(wDevID, (LPWAVEHDR)dwParam1, dwParam2);
1227 return MMSYSERR_NOTSUPPORTED;
1229 return MMSYSERR_NOTSUPPORTED;
1231 return wodGetPosition(wDevID, (LPMMTIME16)dwParam1, dwParam2);
1232 case WODM_BREAKLOOP:
1233 return MMSYSERR_NOTSUPPORTED;
1235 return wodPrepare(wDevID, (LPWAVEHDR)dwParam1, dwParam2);
1236 case WODM_UNPREPARE:
1237 return wodUnprepare(wDevID, (LPWAVEHDR)dwParam1, dwParam2);
1238 case WODM_GETDEVCAPS:
1239 return wodGetDevCaps(wDevID,(LPWAVEOUTCAPS16)dwParam1,dwParam2);
1240 case WODM_GETNUMDEVS:
1243 return MMSYSERR_NOTSUPPORTED;
1245 return MMSYSERR_NOTSUPPORTED;
1246 case WODM_GETPLAYBACKRATE:
1247 return MMSYSERR_NOTSUPPORTED;
1248 case WODM_SETPLAYBACKRATE:
1249 return MMSYSERR_NOTSUPPORTED;
1250 case WODM_GETVOLUME:
1251 return wodGetVolume(wDevID, (LPDWORD)dwParam1);
1252 case WODM_SETVOLUME:
1253 return wodSetVolume(wDevID, dwParam1);
1255 return wodRestart(wDevID);
1257 return wodReset(wDevID);
1259 dprintf_mciwave(stddeb,"wodMessage // unknown message !\n");
1261 return MMSYSERR_NOTSUPPORTED;
1265 /*-----------------------------------------------------------------------*/
1267 /**************************************************************************
1268 * widGetDevCaps [internal]
1270 static DWORD widGetDevCaps(WORD wDevID, LPWAVEINCAPS16 lpCaps, DWORD dwSize)
1272 int audio,smplrate,samplesize=16,dsp_stereo=1,bytespersmpl;
1274 dprintf_mciwave(stddeb,
1275 "widGetDevCaps(%u, %p, %lu);\n", wDevID, lpCaps, dwSize);
1276 if (lpCaps == NULL) return MMSYSERR_NOTENABLED;
1277 if (access(SOUND_DEV,0) != 0) return MMSYSERR_NOTENABLED;
1278 audio = open (SOUND_DEV, O_RDONLY, 0);
1279 if (audio == -1) return MMSYSERR_ALLOCATED ;
1281 lpCaps->wMid = 0x0002;
1282 lpCaps->wPid = 0x0004;
1283 strcpy(lpCaps->szPname, "SB16 Wave In");
1285 lpCaps->wMid = 0x00FF; /* Manufac ID */
1286 lpCaps->wPid = 0x0001; /* Product ID */
1287 strcpy(lpCaps->szPname, "OpenSoundSystem WAVIN Driver");
1289 lpCaps->dwFormats = 0x00000000;
1290 lpCaps->wChannels = (IOCTL(audio, SNDCTL_DSP_STEREO, dsp_stereo) != 0) ? 1 : 2;
1291 bytespersmpl = (IOCTL(audio, SNDCTL_DSP_SAMPLESIZE, samplesize) != 0) ? 1 : 2;
1293 if (IOCTL(audio, SNDCTL_DSP_SPEED, smplrate) == 0) {
1294 lpCaps->dwFormats |= WAVE_FORMAT_4M08;
1295 if (lpCaps->wChannels > 1)
1296 lpCaps->dwFormats |= WAVE_FORMAT_4S08;
1297 if (bytespersmpl > 1) {
1298 lpCaps->dwFormats |= WAVE_FORMAT_4M16;
1299 if (lpCaps->wChannels > 1)
1300 lpCaps->dwFormats |= WAVE_FORMAT_4S16;
1304 if (IOCTL(audio, SNDCTL_DSP_SPEED, smplrate) == 0) {
1305 lpCaps->dwFormats |= WAVE_FORMAT_2M08;
1306 if (lpCaps->wChannels > 1)
1307 lpCaps->dwFormats |= WAVE_FORMAT_2S08;
1308 if (bytespersmpl > 1) {
1309 lpCaps->dwFormats |= WAVE_FORMAT_2M16;
1310 if (lpCaps->wChannels > 1)
1311 lpCaps->dwFormats |= WAVE_FORMAT_2S16;
1315 if (IOCTL(audio, SNDCTL_DSP_SPEED, smplrate) == 0) {
1316 lpCaps->dwFormats |= WAVE_FORMAT_1M08;
1317 if (lpCaps->wChannels > 1)
1318 lpCaps->dwFormats |= WAVE_FORMAT_1S08;
1319 if (bytespersmpl > 1) {
1320 lpCaps->dwFormats |= WAVE_FORMAT_1M16;
1321 if (lpCaps->wChannels > 1)
1322 lpCaps->dwFormats |= WAVE_FORMAT_1S16;
1326 dprintf_mciwave(stddeb,
1327 "widGetDevCaps // dwFormats = %08lX\n", lpCaps->dwFormats);
1328 return MMSYSERR_NOERROR;
1332 /**************************************************************************
1333 * widOpen [internal]
1335 static DWORD widOpen(WORD wDevID, LPWAVEOPENDESC lpDesc, DWORD dwFlags)
1337 int audio,abuf_size,smplrate,samplesize,dsp_stereo;
1338 LPWAVEFORMAT lpFormat;
1340 dprintf_mciwave(stddeb, "widOpen(%u, %p, %08lX);\n", wDevID, lpDesc, dwFlags);
1341 if (lpDesc == NULL) {
1342 dprintf_mciwave(stddeb,"Linux 'widOpen' // Invalid Parameter !\n");
1343 return MMSYSERR_INVALPARAM;
1345 if (wDevID >= MAX_WAVINDRV) {
1346 dprintf_mciwave(stddeb,"Linux 'widOpen' // MAX_WAVINDRV reached !\n");
1347 return MMSYSERR_ALLOCATED;
1349 WInDev[wDevID].unixdev = 0;
1350 if (access(SOUND_DEV,0) != 0) return MMSYSERR_NOTENABLED;
1351 audio = open (SOUND_DEV, O_RDONLY, 0);
1353 dprintf_mciwave(stddeb,"Linux 'widOpen' // can't open !\n");
1354 return MMSYSERR_ALLOCATED;
1356 IOCTL(audio, SNDCTL_DSP_GETBLKSIZE, abuf_size);
1357 if (abuf_size < 1024 || abuf_size > 65536) {
1358 if (abuf_size == -1)
1359 dprintf_mciwave(stddeb,"Linux 'widOpen' // IOCTL can't 'SNDCTL_DSP_GETBLKSIZE' !\n");
1361 dprintf_mciwave(stddeb,"Linux 'widOpen' // SNDCTL_DSP_GETBLKSIZE Invalid bufsize !\n");
1362 return MMSYSERR_NOTENABLED;
1364 WInDev[wDevID].wFlags = HIWORD(dwFlags & CALLBACK_TYPEMASK);
1365 switch(WInDev[wDevID].wFlags) {
1367 dprintf_mciwave(stddeb,"Linux 'widOpen' // CALLBACK_NULL!\n");
1370 dprintf_mciwave(stddeb,"Linux 'widOpen' // CALLBACK_WINDOW!\n");
1373 dprintf_mciwave(stddeb,"Linux 'widOpen' // CALLBACK_TASK!\n");
1376 dprintf_mciwave(stddeb,"Linux 'widOpen' // CALLBACK_FUNCTION!\n");
1379 if (WInDev[wDevID].lpQueueHdr) {
1380 HeapFree(GetProcessHeap(),0,WInDev[wDevID].lpQueueHdr);
1381 WInDev[wDevID].lpQueueHdr = NULL;
1383 WInDev[wDevID].unixdev = audio;
1384 WInDev[wDevID].bufsize = abuf_size;
1385 WInDev[wDevID].dwTotalRecorded = 0;
1386 memcpy(&WInDev[wDevID].waveDesc, lpDesc, sizeof(WAVEOPENDESC));
1387 lpFormat = (LPWAVEFORMAT) lpDesc->lpFormat;
1388 if (lpFormat->wFormatTag != WAVE_FORMAT_PCM) {
1389 dprintf_mciwave(stddeb,"Linux 'widOpen' // Bad format %04X !\n",
1390 lpFormat->wFormatTag);
1391 return WAVERR_BADFORMAT;
1393 memcpy(&WInDev[wDevID].Format, lpFormat, sizeof(PCMWAVEFORMAT));
1394 WInDev[wDevID].Format.wBitsPerSample = 8; /* <-------------- */
1395 if (WInDev[wDevID].Format.wf.nChannels == 0) return WAVERR_BADFORMAT;
1396 if (WInDev[wDevID].Format.wf.nSamplesPerSec == 0) return WAVERR_BADFORMAT;
1397 if (WInDev[wDevID].Format.wBitsPerSample == 0) {
1398 WInDev[wDevID].Format.wBitsPerSample = 8 *
1399 (WInDev[wDevID].Format.wf.nAvgBytesPerSec /
1400 WInDev[wDevID].Format.wf.nSamplesPerSec) /
1401 WInDev[wDevID].Format.wf.nChannels;
1403 samplesize = WInDev[wDevID].Format.wBitsPerSample;
1404 smplrate = WInDev[wDevID].Format.wf.nSamplesPerSec;
1405 dsp_stereo = (WInDev[wDevID].Format.wf.nChannels > 1) ? TRUE : FALSE;
1406 IOCTL(audio, SNDCTL_DSP_SPEED, smplrate);
1407 IOCTL(audio, SNDCTL_DSP_SAMPLESIZE, samplesize);
1408 IOCTL(audio, SNDCTL_DSP_STEREO, dsp_stereo);
1409 dprintf_mciwave(stddeb,"Linux 'widOpen' // wBitsPerSample=%u !\n",
1410 WInDev[wDevID].Format.wBitsPerSample);
1411 dprintf_mciwave(stddeb,"Linux 'widOpen' // nSamplesPerSec=%lu !\n",
1412 WInDev[wDevID].Format.wf.nSamplesPerSec);
1413 dprintf_mciwave(stddeb,"Linux 'widOpen' // nChannels=%u !\n",
1414 WInDev[wDevID].Format.wf.nChannels);
1415 dprintf_mciwave(stddeb,"Linux 'widOpen' // nAvgBytesPerSec=%lu\n",
1416 WInDev[wDevID].Format.wf.nAvgBytesPerSec);
1417 if (WAVE_NotifyClient(wDevID, WIM_OPEN, 0L, 0L) != MMSYSERR_NOERROR) {
1418 dprintf_mciwave(stddeb,"Linux 'widOpen' // can't notify client !\n");
1419 return MMSYSERR_INVALPARAM;
1421 return MMSYSERR_NOERROR;
1424 /**************************************************************************
1425 * widClose [internal]
1427 static DWORD widClose(WORD wDevID)
1429 dprintf_mciwave(stddeb,"widClose(%u);\n", wDevID);
1430 if (wDevID > MAX_WAVINDRV) return MMSYSERR_INVALPARAM;
1431 if (WInDev[wDevID].unixdev == 0) {
1432 dprintf_mciwave(stddeb,"Linux 'widClose' // can't close !\n");
1433 return MMSYSERR_NOTENABLED;
1435 if (WInDev[wDevID].lpQueueHdr != NULL) {
1436 dprintf_mciwave(stddeb,"linux 'widclose' // still buffers open !\n");
1437 return WAVERR_STILLPLAYING;
1439 close(WInDev[wDevID].unixdev);
1440 WInDev[wDevID].unixdev = 0;
1441 WInDev[wDevID].bufsize = 0;
1442 if (WAVE_NotifyClient(wDevID, WIM_CLOSE, 0L, 0L) != MMSYSERR_NOERROR) {
1443 dprintf_mciwave(stddeb,"Linux 'widClose' // can't notify client !\n");
1444 return MMSYSERR_INVALPARAM;
1446 return MMSYSERR_NOERROR;
1449 /**************************************************************************
1450 * widAddBuffer [internal]
1452 static DWORD widAddBuffer(WORD wDevID, LPWAVEHDR lpWaveHdr, DWORD dwSize)
1457 dprintf_mciwave(stddeb,
1458 "widAddBuffer(%u, %p, %08lX);\n", wDevID, lpWaveHdr, dwSize);
1459 if (WInDev[wDevID].unixdev == 0) {
1460 dprintf_mciwave(stddeb,"Linux 'widAddBuffer' // can't do it !\n");
1461 return MMSYSERR_NOTENABLED;
1463 if (!(lpWaveHdr->dwFlags & WHDR_PREPARED)) {
1464 dprintf_mciwave(stddeb, "Linux 'widAddBuffer' // never been prepared !\n");
1465 return WAVERR_UNPREPARED;
1467 if (lpWaveHdr->dwFlags & WHDR_INQUEUE) {
1468 dprintf_mciwave(stddeb, "Linux 'widAddBuffer' // header already in use !\n");
1469 return WAVERR_STILLPLAYING;
1471 lpWaveHdr->dwFlags |= WHDR_PREPARED;
1472 lpWaveHdr->dwFlags |= WHDR_INQUEUE;
1473 lpWaveHdr->dwFlags &= ~WHDR_DONE;
1474 lpWaveHdr->dwBytesRecorded = 0;
1475 if (WInDev[wDevID].lpQueueHdr == NULL) {
1476 WInDev[wDevID].lpQueueHdr = lpWaveHdr;
1478 lpWIHdr = WInDev[wDevID].lpQueueHdr;
1479 while (lpWIHdr->lpNext != NULL) {
1480 lpWIHdr = lpWIHdr->lpNext;
1483 lpWIHdr->lpNext = lpWaveHdr;
1484 lpWaveHdr->lpNext = NULL;
1487 dprintf_mciwave(stddeb,
1488 "widAddBuffer // buffer added ! (now %u in queue)\n", count);
1489 return MMSYSERR_NOERROR;
1492 /**************************************************************************
1493 * widPrepare [internal]
1495 static DWORD widPrepare(WORD wDevID, LPWAVEHDR lpWaveHdr, DWORD dwSize)
1497 dprintf_mciwave(stddeb,
1498 "widPrepare(%u, %p, %08lX);\n", wDevID, lpWaveHdr, dwSize);
1499 if (WInDev[wDevID].unixdev == 0) {
1500 dprintf_mciwave(stddeb,"Linux 'widPrepare' // can't prepare !\n");
1501 return MMSYSERR_NOTENABLED;
1503 if (lpWaveHdr->dwFlags & WHDR_INQUEUE)
1504 return WAVERR_STILLPLAYING;
1505 lpWaveHdr->dwFlags |= WHDR_PREPARED;
1506 lpWaveHdr->dwFlags &= ~WHDR_INQUEUE;
1507 lpWaveHdr->dwFlags &= ~WHDR_DONE;
1508 lpWaveHdr->dwBytesRecorded = 0;
1509 dprintf_mciwave(stddeb,"Linux 'widPrepare' // header prepared !\n");
1510 return MMSYSERR_NOERROR;
1513 /**************************************************************************
1514 * widUnprepare [internal]
1516 static DWORD widUnprepare(WORD wDevID, LPWAVEHDR lpWaveHdr, DWORD dwSize)
1518 dprintf_mciwave(stddeb,
1519 "widUnprepare(%u, %p, %08lX);\n", wDevID, lpWaveHdr, dwSize);
1520 if (WInDev[wDevID].unixdev == 0) {
1521 dprintf_mciwave(stddeb,"Linux 'widUnprepare' // can't unprepare !\n");
1522 return MMSYSERR_NOTENABLED;
1524 lpWaveHdr->dwFlags &= ~WHDR_PREPARED;
1525 lpWaveHdr->dwFlags &= ~WHDR_INQUEUE;
1526 lpWaveHdr->dwFlags |= WHDR_DONE;
1528 dprintf_mciwave(stddeb, "Linux 'widUnprepare' // all headers unprepared !\n");
1529 return MMSYSERR_NOERROR;
1532 /**************************************************************************
1533 * widStart [internal]
1535 static DWORD widStart(WORD wDevID)
1540 LPWAVEHDR *lpWaveHdr;
1542 dprintf_mciwave(stddeb,"widStart(%u);\n", wDevID);
1543 if (WInDev[wDevID].unixdev == 0) {
1544 dprintf_mciwave(stddeb, "Linux 'widStart' // can't start recording !\n");
1545 return MMSYSERR_NOTENABLED;
1548 lpWaveHdr = &(WInDev[wDevID].lpQueueHdr);
1549 dprintf_mciwave(stddeb,"Linux 'widstart'// lpWaveHdr = %08lx\n",(DWORD)lpWaveHdr);
1550 if (!*lpWaveHdr || !(*lpWaveHdr)->lpData) {
1551 dprintf_mciwave(stddeb,"Linux 'widStart' // never been prepared !\n");
1552 return WAVERR_UNPREPARED;
1555 while(*lpWaveHdr != NULL) {
1556 lpWIHdr = *lpWaveHdr;
1557 dprintf_mciwave(stddeb,
1558 "widStart // recording buf#%u=%p size=%lu \n",
1559 count, lpWIHdr->lpData, lpWIHdr->dwBufferLength);
1561 bytesRead = read (WInDev[wDevID].unixdev,
1563 lpWIHdr->dwBufferLength);
1565 perror("read from audio device");
1566 fprintf(stderr,"bytesread = %d (%ld)\n",bytesRead,lpWIHdr->dwBufferLength);
1567 lpWIHdr->dwBytesRecorded = bytesRead;
1568 WInDev[wDevID].dwTotalRecorded += lpWIHdr->dwBytesRecorded;
1569 lpWIHdr->dwFlags &= ~WHDR_INQUEUE;
1570 lpWIHdr->dwFlags |= WHDR_DONE;
1572 /* FIXME: should pass segmented pointer here, do we need that?*/
1573 if (WAVE_NotifyClient(wDevID, WIM_DATA, (DWORD)lpWaveHdr, lpWIHdr->dwBytesRecorded) != MMSYSERR_NOERROR) {
1574 dprintf_mciwave(stddeb, "Linux 'widStart' // can't notify client !\n");
1575 return MMSYSERR_INVALPARAM;
1577 /* removes the current block from the queue */
1578 *lpWaveHdr = lpWIHdr->lpNext;
1581 dprintf_mciwave(stddeb,"widStart // end of recording !\n");
1583 return MMSYSERR_NOERROR;
1586 /**************************************************************************
1587 * widStop [internal]
1589 static DWORD widStop(WORD wDevID)
1591 dprintf_mciwave(stddeb,"widStop(%u);\n", wDevID);
1592 if (WInDev[wDevID].unixdev == 0) {
1593 dprintf_mciwave(stddeb,"Linux 'widStop' // can't stop !\n");
1594 return MMSYSERR_NOTENABLED;
1596 return MMSYSERR_NOERROR;
1599 /**************************************************************************
1600 * widReset [internal]
1602 static DWORD widReset(WORD wDevID)
1604 dprintf_mciwave(stddeb,"widReset(%u);\n", wDevID);
1605 if (WInDev[wDevID].unixdev == 0) {
1606 dprintf_mciwave(stddeb,"Linux 'widReset' // can't reset !\n");
1607 return MMSYSERR_NOTENABLED;
1609 return MMSYSERR_NOERROR;
1612 /**************************************************************************
1613 * widGetPosition [internal]
1615 static DWORD widGetPosition(WORD wDevID, LPMMTIME16 lpTime, DWORD uSize)
1619 dprintf_mciwave(stddeb,
1620 "widGetPosition(%u, %p, %lu);\n", wDevID, lpTime, uSize);
1621 if (WInDev[wDevID].unixdev == 0) {
1622 dprintf_mciwave(stddeb,"Linux 'widGetPosition' // can't get pos !\n");
1623 return MMSYSERR_NOTENABLED;
1625 if (lpTime == NULL) return MMSYSERR_INVALPARAM;
1626 dprintf_mciwave(stddeb,"widGetPosition // wType=%04X !\n",
1628 dprintf_mciwave(stddeb,"widGetPosition // wBitsPerSample=%u\n",
1629 WInDev[wDevID].Format.wBitsPerSample);
1630 dprintf_mciwave(stddeb,"widGetPosition // nSamplesPerSec=%lu\n",
1631 WInDev[wDevID].Format.wf.nSamplesPerSec);
1632 dprintf_mciwave(stddeb,"widGetPosition // nChannels=%u\n",
1633 WInDev[wDevID].Format.wf.nChannels);
1634 dprintf_mciwave(stddeb,"widGetPosition // nAvgBytesPerSec=%lu\n",
1635 WInDev[wDevID].Format.wf.nAvgBytesPerSec);
1637 switch(lpTime->wType) {
1639 lpTime->u.cb = WInDev[wDevID].dwTotalRecorded;
1640 dprintf_mciwave(stddeb,
1641 "widGetPosition // TIME_BYTES=%lu\n", lpTime->u.cb);
1644 lpTime->u.sample = WInDev[wDevID].dwTotalRecorded * 8 /
1645 WInDev[wDevID].Format.wBitsPerSample;
1646 dprintf_mciwave(stddeb,
1647 "widGetPosition // TIME_SAMPLES=%lu\n",
1651 time = WInDev[wDevID].dwTotalRecorded /
1652 (WInDev[wDevID].Format.wf.nAvgBytesPerSec / 1000);
1653 lpTime->u.smpte.hour = time / 108000;
1654 time -= lpTime->u.smpte.hour * 108000;
1655 lpTime->u.smpte.min = time / 1800;
1656 time -= lpTime->u.smpte.min * 1800;
1657 lpTime->u.smpte.sec = time / 30;
1658 time -= lpTime->u.smpte.sec * 30;
1659 lpTime->u.smpte.frame = time;
1660 lpTime->u.smpte.fps = 30;
1661 dprintf_mciwave(stddeb,"widGetPosition // TIME_SMPTE=%02u:%02u:%02u:%02u\n",
1662 lpTime->u.smpte.hour, lpTime->u.smpte.min,
1663 lpTime->u.smpte.sec, lpTime->u.smpte.frame);
1666 dprintf_mciwave(stddeb,"widGetPosition() format not supported ! use TIME_MS !\n");
1667 lpTime->wType = TIME_MS;
1669 lpTime->u.ms = WInDev[wDevID].dwTotalRecorded /
1670 (WInDev[wDevID].Format.wf.nAvgBytesPerSec / 1000);
1671 dprintf_mciwave(stddeb,
1672 "widGetPosition // TIME_MS=%lu\n", lpTime->u.ms);
1675 return MMSYSERR_NOERROR;
1678 /**************************************************************************
1679 * widMessage [sample driver]
1681 DWORD widMessage(WORD wDevID, WORD wMsg, DWORD dwUser,
1682 DWORD dwParam1, DWORD dwParam2)
1684 dprintf_mciwave(stddeb,"widMessage(%u, %04X, %08lX, %08lX, %08lX);\n",
1685 wDevID, wMsg, dwUser, dwParam1, dwParam2);
1688 return widOpen(wDevID, (LPWAVEOPENDESC)dwParam1, dwParam2);
1690 return widClose(wDevID);
1691 case WIDM_ADDBUFFER:
1692 return widAddBuffer(wDevID, (LPWAVEHDR)dwParam1, dwParam2);
1694 return widPrepare(wDevID, (LPWAVEHDR)dwParam1, dwParam2);
1695 case WIDM_UNPREPARE:
1696 return widUnprepare(wDevID, (LPWAVEHDR)dwParam1, dwParam2);
1697 case WIDM_GETDEVCAPS:
1698 return widGetDevCaps(wDevID, (LPWAVEINCAPS16)dwParam1,dwParam2);
1699 case WIDM_GETNUMDEVS:
1702 return widGetPosition(wDevID, (LPMMTIME16)dwParam1, dwParam2);
1704 return widReset(wDevID);
1706 return widStart(wDevID);
1708 return widStop(wDevID);
1710 return widStop(wDevID);
1712 dprintf_mciwave(stddeb,"widMessage // unknown message !\n");
1714 return MMSYSERR_NOTSUPPORTED;
1718 /**************************************************************************
1719 * AUDIO_DriverProc [sample driver]
1721 LONG WAVE_DriverProc(DWORD dwDevID, HDRVR16 hDriv, WORD wMsg,
1722 DWORD dwParam1, DWORD dwParam2)
1724 dprintf_mciwave(stddeb,"WAVE_DriverProc(%08lX, %04X, %04X, %08lX, %08lX)\n",
1725 dwDevID, hDriv, wMsg, dwParam1, dwParam2);
1739 case DRV_QUERYCONFIGURE:
1742 MessageBox16(0, "Sample MultiMedia Linux Driver !",
1743 "MMLinux Driver", MB_OK);
1746 return DRVCNF_RESTART;
1748 return DRVCNF_RESTART;
1749 case MCI_OPEN_DRIVER:
1751 return WAVE_mciOpen(dwDevID, dwParam1, (LPMCI_WAVE_OPEN_PARMS16)PTR_SEG_TO_LIN(dwParam2));
1753 return WAVE_mciCue(dwDevID, dwParam1, (LPMCI_GENERIC_PARMS)PTR_SEG_TO_LIN(dwParam2));
1754 case MCI_CLOSE_DRIVER:
1756 return WAVE_mciClose(dwDevID, dwParam1, (LPMCI_GENERIC_PARMS)PTR_SEG_TO_LIN(dwParam2));
1758 return WAVE_mciPlay(dwDevID, dwParam1, (LPMCI_PLAY_PARMS)PTR_SEG_TO_LIN(dwParam2));
1760 return WAVE_mciRecord(dwDevID, dwParam1, (LPMCI_RECORD_PARMS)PTR_SEG_TO_LIN(dwParam2));
1762 return WAVE_mciStop(dwDevID, dwParam1, (LPMCI_GENERIC_PARMS)PTR_SEG_TO_LIN(dwParam2));
1764 return WAVE_mciSet(dwDevID, dwParam1, (LPMCI_SET_PARMS)PTR_SEG_TO_LIN(dwParam2));
1766 return WAVE_mciPause(dwDevID, dwParam1, (LPMCI_GENERIC_PARMS)PTR_SEG_TO_LIN(dwParam2));
1768 return WAVE_mciResume(dwDevID, dwParam1, (LPMCI_GENERIC_PARMS)PTR_SEG_TO_LIN(dwParam2));
1770 return WAVE_mciStatus(dwDevID, dwParam1, (LPMCI_STATUS_PARMS)PTR_SEG_TO_LIN(dwParam2));
1771 case MCI_GETDEVCAPS:
1772 return WAVE_mciGetDevCaps(dwDevID, dwParam1, (LPMCI_GETDEVCAPS_PARMS)PTR_SEG_TO_LIN(dwParam2));
1774 return WAVE_mciInfo(dwDevID, dwParam1, (LPMCI_INFO_PARMS16)PTR_SEG_TO_LIN(dwParam2));
1777 return MMSYSERR_NOTSUPPORTED;
1779 return MMSYSERR_NOTSUPPORTED;
1781 return MMSYSERR_NOTSUPPORTED;
1783 return MMSYSERR_NOTSUPPORTED;
1785 return MMSYSERR_NOTSUPPORTED;
1787 return MMSYSERR_NOTSUPPORTED;
1789 return MMSYSERR_NOTSUPPORTED;
1791 return MMSYSERR_NOTSUPPORTED;
1793 return MMSYSERR_NOTSUPPORTED;
1795 return MMSYSERR_NOTSUPPORTED;
1797 return MMSYSERR_NOTSUPPORTED;
1799 return MMSYSERR_NOTSUPPORTED;
1801 return MMSYSERR_NOTSUPPORTED;
1803 return MMSYSERR_NOTSUPPORTED;
1805 return MMSYSERR_NOTSUPPORTED;
1807 return MMSYSERR_NOTSUPPORTED;
1809 return MMSYSERR_NOTSUPPORTED;
1812 return DefDriverProc(dwDevID, hDriv, wMsg, dwParam1, dwParam2);
1814 return MMSYSERR_NOTENABLED;
1817 #else /* !HAVE_OSS */
1819 /**************************************************************************
1820 * wodMessage [sample driver]
1822 DWORD wodMessage(WORD wDevID, WORD wMsg, DWORD dwUser,
1823 DWORD dwParam1, DWORD dwParam2)
1825 fprintf(stderr,"wodMessage(%u, %04X, %08lX, %08lX, %08lX);\n",
1826 wDevID, wMsg, dwUser, dwParam1, dwParam2);
1827 return MMSYSERR_NOTENABLED;
1830 /**************************************************************************
1831 * widMessage [sample driver]
1833 DWORD widMessage(WORD wDevID, WORD wMsg, DWORD dwUser,
1834 DWORD dwParam1, DWORD dwParam2)
1836 fprintf(stderr,"widMessage(%u, %04X, %08lX, %08lX, %08lX);\n",
1837 wDevID, wMsg, dwUser, dwParam1, dwParam2);
1838 return MMSYSERR_NOTENABLED;
1841 /**************************************************************************
1842 * AUDIO_DriverProc [sample driver]
1844 LONG WAVE_DriverProc(DWORD dwDevID, HDRVR16 hDriv, WORD wMsg,
1845 DWORD dwParam1, DWORD dwParam2)
1847 return MMSYSERR_NOTENABLED;
1849 #endif /* HAVE_OSS */