2 * Sample Wine Driver for Linux
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>
29 #include <linux/soundcard.h>
31 #include <machine/soundcard.h>
37 #if defined(linux) || defined(__FreeBSD__)
38 #define SOUND_DEV "/dev/dsp"
39 #define MIXER_DEV "/dev/mixer"
42 #define IOCTL(a,b,c) ((-1==ioctl(a,b,&c))&&(perror("ioctl:"#b":"#c),0))
44 #define IOCTL(a,b,c) (c = ioctl(a,b,c) )
47 #define MAX_WAVOUTDRV (1)
48 #define MAX_WAVINDRV (1)
49 #define MAX_MCIWAVDRV (1)
55 WAVEOPENDESC waveDesc;
65 DWORD bufsize; /* Linux '/dev/dsp' give us that size */
66 WAVEOPENDESC waveDesc;
70 DWORD dwTotalRecorded;
74 int nUseCount; /* Incremented for each shared open */
75 BOOL16 fShareable; /* TRUE if first open was shareable */
76 WORD wNotifyDeviceID;/* MCI device ID with a pending notification */
77 HANDLE16 hCallback; /* Callback handle for pending notification */
78 HMMIO16 hFile; /* mmio file handle open as Element */
79 MCI_WAVE_OPEN_PARMS16 openParms;
80 PCMWAVEFORMAT WaveFormat;
82 BOOL16 fInput; /* FALSE = Output, TRUE = Input */
85 static LINUX_WAVEOUT WOutDev[MAX_WAVOUTDRV];
86 static LINUX_WAVEIN WInDev[MAX_WAVOUTDRV];
87 static LINUX_MCIWAVE MCIWavDev[MAX_MCIWAVDRV];
90 /**************************************************************************
91 * WAVE_NotifyClient [internal]
93 static DWORD WAVE_NotifyClient(UINT16 wDevID, WORD wMsg,
94 DWORD dwParam1, DWORD dwParam2)
96 dprintf_mciwave(stddeb,"WAVE_NotifyClient // wDevID = %04X wMsg = %d dwParm1 = %04lX dwParam2 = %04lX\n",wDevID, wMsg, dwParam1, dwParam2);
102 if (wDevID > MAX_WAVOUTDRV) return MCIERR_INTERNAL;
104 if (WOutDev[wDevID].wFlags != DCB_NULL && !DriverCallback(
105 WOutDev[wDevID].waveDesc.dwCallBack,
106 WOutDev[wDevID].wFlags,
107 WOutDev[wDevID].waveDesc.hWave,
109 WOutDev[wDevID].waveDesc.dwInstance,
112 dprintf_mciwave(stddeb,"WAVE_NotifyClient // can't notify client !\n");
113 return MMSYSERR_NOERROR;
120 if (wDevID > MAX_WAVINDRV) return MCIERR_INTERNAL;
122 if (WInDev[wDevID].wFlags != DCB_NULL && !DriverCallback(
123 WInDev[wDevID].waveDesc.dwCallBack, WInDev[wDevID].wFlags,
124 WInDev[wDevID].waveDesc.hWave, wMsg,
125 WInDev[wDevID].waveDesc.dwInstance, dwParam1, dwParam2)) {
126 dprintf_mciwave(stddeb,"WAVE_NotifyClient // can't notify client !\n");
127 return MMSYSERR_NOERROR;
135 /**************************************************************************
136 * WAVE_mciOpen [internal]
138 static DWORD WAVE_mciOpen(UINT16 wDevID, DWORD dwFlags, LPMCI_WAVE_OPEN_PARMS16 lpParms)
140 LPPCMWAVEFORMAT lpWaveFormat;
141 WAVEOPENDESC waveDesc;
142 LPSTR lpstrElementName;
146 dprintf_mciwave(stddeb,"WAVE_mciOpen(%04X, %08lX, %p)\n",
147 wDevID, dwFlags, lpParms);
148 if (lpParms == NULL) return MCIERR_INTERNAL;
150 if (MCIWavDev[wDevID].nUseCount > 0) {
151 /* The driver already open on this channel */
152 /* If the driver was opened shareable before and this open specifies */
153 /* shareable then increment the use count */
154 if (MCIWavDev[wDevID].fShareable && (dwFlags & MCI_OPEN_SHAREABLE))
155 ++MCIWavDev[wDevID].nUseCount;
157 return MCIERR_MUST_USE_SHAREABLE;
159 MCIWavDev[wDevID].nUseCount = 1;
160 MCIWavDev[wDevID].fShareable = dwFlags & MCI_OPEN_SHAREABLE;
163 MCIWavDev[wDevID].fInput = FALSE;
165 dprintf_mciwave(stddeb,"WAVE_mciOpen // wDevID=%04X\n", wDevID);
166 dprintf_mciwave(stddeb,"WAVE_mciOpen // before OPEN_ELEMENT\n");
167 if (dwFlags & MCI_OPEN_ELEMENT) {
168 lpstrElementName = (LPSTR)PTR_SEG_TO_LIN(lpParms->lpstrElementName);
169 dprintf_mciwave(stddeb,"WAVE_mciOpen // MCI_OPEN_ELEMENT '%s' !\n",
171 if ( lpstrElementName && (strlen(lpstrElementName) > 0)) {
172 strcpy(str, lpstrElementName);
174 MCIWavDev[wDevID].hFile = mmioOpen16(str, NULL,
175 MMIO_ALLOCBUF | MMIO_READWRITE | MMIO_EXCLUSIVE);
176 if (MCIWavDev[wDevID].hFile == 0) {
177 dprintf_mciwave(stddeb,"WAVE_mciOpen // can't find file='%s' !\n", str);
178 return MCIERR_FILE_NOT_FOUND;
182 MCIWavDev[wDevID].hFile = 0;
184 dprintf_mciwave(stddeb,"WAVE_mciOpen // hFile=%u\n", MCIWavDev[wDevID].hFile);
185 memcpy(&MCIWavDev[wDevID].openParms, lpParms, sizeof(MCI_WAVE_OPEN_PARMS16));
186 MCIWavDev[wDevID].wNotifyDeviceID = lpParms->wDeviceID;
187 lpWaveFormat = &MCIWavDev[wDevID].WaveFormat;
191 lpWaveFormat->wf.wFormatTag = WAVE_FORMAT_PCM;
192 lpWaveFormat->wBitsPerSample = 8;
193 lpWaveFormat->wf.nChannels = 1;
194 lpWaveFormat->wf.nSamplesPerSec = 11025;
195 lpWaveFormat->wf.nAvgBytesPerSec = 11025;
196 lpWaveFormat->wf.nBlockAlign = 1;
198 if (MCIWavDev[wDevID].hFile != 0) {
201 if (mmioDescend(MCIWavDev[wDevID].hFile, &ckMainRIFF, NULL, 0) != 0)
202 return MCIERR_INTERNAL;
203 dprintf_mciwave(stddeb,
204 "WAVE_mciOpen // ParentChunk ckid=%.4s fccType=%.4s cksize=%08lX \n",
205 (LPSTR)&ckMainRIFF.ckid, (LPSTR)&ckMainRIFF.fccType,
207 if ((ckMainRIFF.ckid != FOURCC_RIFF) ||
208 (ckMainRIFF.fccType != mmioFOURCC('W', 'A', 'V', 'E')))
209 return MCIERR_INTERNAL;
210 mmckInfo.ckid = mmioFOURCC('f', 'm', 't', ' ');
211 if (mmioDescend(MCIWavDev[wDevID].hFile, &mmckInfo, &ckMainRIFF, MMIO_FINDCHUNK) != 0)
212 return MCIERR_INTERNAL;
213 dprintf_mciwave(stddeb,
214 "WAVE_mciOpen // Chunk Found ckid=%.4s fccType=%.4s cksize=%08lX \n",
215 (LPSTR)&mmckInfo.ckid, (LPSTR)&mmckInfo.fccType,
217 if (mmioRead(MCIWavDev[wDevID].hFile, (HPSTR) lpWaveFormat,
218 (long) sizeof(PCMWAVEFORMAT)) != (long) sizeof(PCMWAVEFORMAT))
219 return MCIERR_INTERNAL;
220 mmckInfo.ckid = mmioFOURCC('d', 'a', 't', 'a');
221 if (mmioDescend(MCIWavDev[wDevID].hFile, &mmckInfo, &ckMainRIFF, MMIO_FINDCHUNK) != 0)
222 return MCIERR_INTERNAL;
223 dprintf_mciwave(stddeb,
224 "WAVE_mciOpen // Chunk Found ckid=%.4s fccType=%.4s cksize=%08lX \n",
225 (LPSTR)&mmckInfo.ckid, (LPSTR)&mmckInfo.fccType,
227 dprintf_mciwave(stddeb,
228 "WAVE_mciOpen // nChannels=%d nSamplesPerSec=%ld\n",
229 lpWaveFormat->wf.nChannels, lpWaveFormat->wf.nSamplesPerSec);
230 lpWaveFormat->wBitsPerSample = 0;
232 lpWaveFormat->wf.nAvgBytesPerSec =
233 lpWaveFormat->wf.nSamplesPerSec * lpWaveFormat->wf.nBlockAlign;
234 waveDesc.lpFormat = (LPWAVEFORMAT)lpWaveFormat;
237 By default the device will be opened for output, the MCI_CUE function is there to
238 change from output to input and back
241 dwRet=wodMessage(wDevID,WODM_OPEN,0,(DWORD)&waveDesc,CALLBACK_NULL);
245 /**************************************************************************
246 * WAVE_mciCue [internal]
249 static DWORD WAVE_mciCue(UINT16 wDevID, DWORD dwParam, LPMCI_GENERIC_PARMS lpParms)
254 This routine is far from complete. At the moment only a check is done on the
255 MCI_WAVE_INPUT flag. No explicit check on MCI_WAVE_OUTPUT is done since that
258 The flags MCI_NOTIFY (and the callback parameter in lpParms) and MCI_WAIT
263 WAVEOPENDESC waveDesc;
265 dprintf_mciwave(stddeb,"WAVE_mciCue(%u, %08lX, %p);\n", wDevID, dwParam, lpParms);
267 /* always close elements ? */
269 if (MCIWavDev[wDevID].hFile != 0) {
270 mmioClose(MCIWavDev[wDevID].hFile, 0);
271 MCIWavDev[wDevID].hFile = 0;
274 dwRet = MMSYSERR_NOERROR; /* assume success */
275 if ((dwParam & MCI_WAVE_INPUT) && !MCIWavDev[wDevID].fInput) {
276 /* FIXME this is just a hack WOutDev should be hidden here */
277 memcpy(&waveDesc,&WOutDev[wDevID].waveDesc,sizeof(WAVEOPENDESC));
279 dwRet = wodMessage(wDevID, WODM_CLOSE, 0, 0L, 0L);
280 if (dwRet != MMSYSERR_NOERROR) return MCIERR_INTERNAL;
281 dwRet = widMessage(wDevID, WIDM_OPEN, 0, (DWORD)&waveDesc, CALLBACK_NULL);
282 MCIWavDev[wDevID].fInput = TRUE;
284 else if (MCIWavDev[wDevID].fInput) {
285 /* FIXME this is just a hack WInDev should be hidden here */
286 memcpy(&waveDesc,&WInDev[wDevID].waveDesc,sizeof(WAVEOPENDESC));
288 dwRet = widMessage(wDevID, WIDM_CLOSE, 0, 0L, 0L);
289 if (dwRet != MMSYSERR_NOERROR) return MCIERR_INTERNAL;
290 dwRet = wodMessage(wDevID, WODM_OPEN, 0, (DWORD)&waveDesc, CALLBACK_NULL);
291 MCIWavDev[wDevID].fInput = FALSE;
296 /**************************************************************************
297 * WAVE_mciClose [internal]
299 static DWORD WAVE_mciClose(UINT16 wDevID, DWORD dwParam, LPMCI_GENERIC_PARMS lpParms)
303 dprintf_mciwave(stddeb,
304 "WAVE_mciClose(%u, %08lX, %p);\n", wDevID, dwParam, lpParms);
305 MCIWavDev[wDevID].nUseCount--;
306 if (MCIWavDev[wDevID].nUseCount == 0) {
307 if (MCIWavDev[wDevID].hFile != 0) {
308 mmioClose(MCIWavDev[wDevID].hFile, 0);
309 MCIWavDev[wDevID].hFile = 0;
311 if (MCIWavDev[wDevID].fInput)
312 dwRet = widMessage(wDevID, WIDM_CLOSE, 0, 0L, 0L);
314 dwRet = wodMessage(wDevID, WODM_CLOSE, 0, 0L, 0L);
316 if (dwRet != MMSYSERR_NOERROR) return MCIERR_INTERNAL;
322 /**************************************************************************
323 * WAVE_mciPlay [internal]
325 static DWORD WAVE_mciPlay(UINT16 wDevID, DWORD dwFlags, LPMCI_PLAY_PARMS lpParms)
333 dprintf_mciwave(stddeb,
334 "WAVE_mciPlay(%u, %08lX, %p);\n", wDevID, dwFlags, lpParms);
336 if (MCIWavDev[wDevID].fInput) {
337 dprintf_mciwave(stddeb,"WAVE_mciPlay // cannot play on input device\n");
338 return MCIERR_NONAPPLICABLE_FUNCTION;
341 if (MCIWavDev[wDevID].hFile == 0) {
342 dprintf_mciwave(stddeb,"WAVE_mciPlay // can't find file='%08lx' !\n",
343 MCIWavDev[wDevID].openParms.lpstrElementName);
344 return MCIERR_FILE_NOT_FOUND;
346 start = 1; end = 99999;
347 if (dwFlags & MCI_FROM) {
348 start = lpParms->dwFrom;
349 dprintf_mciwave(stddeb,
350 "WAVE_mciPlay // MCI_FROM=%d \n", start);
352 if (dwFlags & MCI_TO) {
354 dprintf_mciwave(stddeb,"WAVE_mciPlay // MCI_TO=%d \n", end);
357 if (dwFlags & MCI_NOTIFY) {
358 dprintf_mciwave(stddeb,
359 "WAVE_mciPlay // MCI_NOTIFY %08lX !\n", lpParms->dwCallback);
362 dprintf_mciwave(stddeb,
363 "WAVE_mciPlay // Can't 'fork' process !\n");
368 dprintf_mciwave(stddeb,"WAVE_mciPlay // process started ! return to caller...\n");
374 lpWaveHdr = &MCIWavDev[wDevID].WaveHdr;
375 hData = GlobalAlloc16(GMEM_MOVEABLE, bufsize);
376 lpWaveHdr->lpData = (LPSTR) GlobalLock16(hData);
377 lpWaveHdr->dwUser = 0L;
378 lpWaveHdr->dwFlags = 0L;
379 lpWaveHdr->dwLoops = 0L;
380 dwRet=wodMessage(wDevID,WODM_PREPARE,0,(DWORD)lpWaveHdr,sizeof(WAVEHDR));
382 count = mmioRead(MCIWavDev[wDevID].hFile, lpWaveHdr->lpData, bufsize);
383 dprintf_mciwave(stddeb,"WAVE_mciPlay // mmioRead bufsize=%ld count=%ld\n", bufsize, count);
384 if (count < 1) break;
385 lpWaveHdr->dwBufferLength = count;
386 /* lpWaveHdr->dwBytesRecorded = count; */
387 dprintf_mciwave(stddeb,"WAVE_mciPlay // before WODM_WRITE lpWaveHdr=%p dwBufferLength=%lu dwBytesRecorded=%lu\n",
388 lpWaveHdr, lpWaveHdr->dwBufferLength, lpWaveHdr->dwBytesRecorded);
389 dwRet=wodMessage(wDevID,WODM_WRITE,0,(DWORD)lpWaveHdr,sizeof(WAVEHDR));
391 dwRet = wodMessage(wDevID,WODM_UNPREPARE,0,(DWORD)lpWaveHdr,sizeof(WAVEHDR));
392 if (lpWaveHdr->lpData != NULL) {
393 GlobalUnlock16(hData);
395 lpWaveHdr->lpData = NULL;
397 if (dwFlags & MCI_NOTIFY) {
398 dprintf_mciwave(stddeb,"WAVE_mciPlay // MCI_NOTIFY_SUCCESSFUL %08lX !\n", lpParms->dwCallback);
399 mciDriverNotify((HWND16)LOWORD(lpParms->dwCallback),
400 MCIWavDev[wDevID].wNotifyDeviceID, MCI_NOTIFY_SUCCESSFUL);
406 /**************************************************************************
407 * WAVE_mciRecord [internal]
409 static DWORD WAVE_mciRecord(UINT16 wDevID, DWORD dwFlags, LPMCI_RECORD_PARMS lpParms)
417 dprintf_mciwave(stddeb,
418 "WAVE_mciRecord(%u, %08lX, %p);\n", wDevID, dwFlags, lpParms);
420 if (!MCIWavDev[wDevID].fInput) {
421 dprintf_mciwave(stddeb,"WAVE_mciPlay // cannot record on output device\n");
422 return MCIERR_NONAPPLICABLE_FUNCTION;
425 if (MCIWavDev[wDevID].hFile == 0) {
426 dprintf_mciwave(stddeb,"WAVE_mciRecord // can't find file='%08lx' !\n",
427 MCIWavDev[wDevID].openParms.lpstrElementName);
428 return MCIERR_FILE_NOT_FOUND;
430 start = 1; end = 99999;
431 if (dwFlags & MCI_FROM) {
432 start = lpParms->dwFrom;
433 dprintf_mciwave(stddeb,
434 "WAVE_mciRecord // MCI_FROM=%d \n", start);
436 if (dwFlags & MCI_TO) {
438 dprintf_mciwave(stddeb,"WAVE_mciRecord // MCI_TO=%d \n", end);
441 lpWaveHdr = &MCIWavDev[wDevID].WaveHdr;
442 hData = GlobalAlloc16(GMEM_MOVEABLE, bufsize);
443 lpWaveHdr->lpData = (LPSTR)GlobalLock16(hData);
444 lpWaveHdr->dwBufferLength = bufsize;
445 lpWaveHdr->dwUser = 0L;
446 lpWaveHdr->dwFlags = 0L;
447 lpWaveHdr->dwLoops = 0L;
448 dwRet=widMessage(wDevID,WIDM_PREPARE,0,(DWORD)lpWaveHdr,sizeof(WAVEHDR));
449 dprintf_mciwave(stddeb,"WAVE_mciRecord // after WIDM_PREPARE \n");
451 lpWaveHdr->dwBytesRecorded = 0;
452 dwRet = widMessage(wDevID, WIDM_START, 0, 0L, 0L);
453 dprintf_mciwave(stddeb,
454 "WAVE_mciRecord // after WIDM_START lpWaveHdr=%p dwBytesRecorded=%lu\n",
455 lpWaveHdr, lpWaveHdr->dwBytesRecorded);
456 if (lpWaveHdr->dwBytesRecorded == 0) break;
458 dprintf_mciwave(stddeb,"WAVE_mciRecord // before WIDM_UNPREPARE \n");
459 dwRet = widMessage(wDevID,WIDM_UNPREPARE,0,(DWORD)lpWaveHdr,sizeof(WAVEHDR));
460 dprintf_mciwave(stddeb,"WAVE_mciRecord // after WIDM_UNPREPARE \n");
461 if (lpWaveHdr->lpData != NULL) {
462 GlobalUnlock16(hData);
464 lpWaveHdr->lpData = NULL;
466 if (dwFlags & MCI_NOTIFY) {
467 dprintf_mciwave(stddeb,"WAVE_mciRecord // MCI_NOTIFY_SUCCESSFUL %08lX !\n", lpParms->dwCallback);
468 mciDriverNotify((HWND16)LOWORD(lpParms->dwCallback),
469 MCIWavDev[wDevID].wNotifyDeviceID, MCI_NOTIFY_SUCCESSFUL);
475 /**************************************************************************
476 * WAVE_mciStop [internal]
478 static DWORD WAVE_mciStop(UINT16 wDevID, DWORD dwFlags, LPMCI_GENERIC_PARMS lpParms)
482 dprintf_mciwave(stddeb,
483 "WAVE_mciStop(%u, %08lX, %p);\n", wDevID, dwFlags, lpParms);
484 if (lpParms == NULL) return MCIERR_INTERNAL;
485 if (MCIWavDev[wDevID].fInput)
486 dwRet = widMessage(wDevID, WIDM_STOP, 0, dwFlags, (DWORD)lpParms);
488 dwRet = wodMessage(wDevID, WODM_STOP, 0, dwFlags, (DWORD)lpParms);
494 /**************************************************************************
495 * WAVE_mciPause [internal]
497 static DWORD WAVE_mciPause(UINT16 wDevID, DWORD dwFlags, LPMCI_GENERIC_PARMS lpParms)
501 dprintf_mciwave(stddeb,
502 "WAVE_mciPause(%u, %08lX, %p);\n", wDevID, dwFlags, lpParms);
503 if (lpParms == NULL) return MCIERR_INTERNAL;
504 if (MCIWavDev[wDevID].fInput)
505 dwRet = widMessage(wDevID, WIDM_PAUSE, 0, dwFlags, (DWORD)lpParms);
507 dwRet = wodMessage(wDevID, WODM_PAUSE, 0, dwFlags, (DWORD)lpParms);
513 /**************************************************************************
514 * WAVE_mciResume [internal]
516 static DWORD WAVE_mciResume(UINT16 wDevID, DWORD dwFlags, LPMCI_GENERIC_PARMS lpParms)
518 dprintf_mciwave(stddeb,
519 "WAVE_mciResume(%u, %08lX, %p);\n", wDevID, dwFlags, lpParms);
520 if (lpParms == NULL) return MCIERR_INTERNAL;
525 /**************************************************************************
526 * WAVE_mciSet [internal]
528 static DWORD WAVE_mciSet(UINT16 wDevID, DWORD dwFlags, LPMCI_SET_PARMS lpParms)
530 dprintf_mciwave(stddeb,
531 "WAVE_mciSet(%u, %08lX, %p);\n", wDevID, dwFlags, lpParms);
532 if (lpParms == NULL) return MCIERR_INTERNAL;
533 dprintf_mciwave(stddeb,
534 "WAVE_mciSet // dwTimeFormat=%08lX\n", lpParms->dwTimeFormat);
535 dprintf_mciwave(stddeb,
536 "WAVE_mciSet // dwAudio=%08lX\n", lpParms->dwAudio);
537 if (dwFlags & MCI_SET_TIME_FORMAT) {
538 switch (lpParms->dwTimeFormat) {
539 case MCI_FORMAT_MILLISECONDS:
540 dprintf_mciwave(stddeb, "WAVE_mciSet // MCI_FORMAT_MILLISECONDS !\n");
542 case MCI_FORMAT_BYTES:
543 dprintf_mciwave(stddeb, "WAVE_mciSet // MCI_FORMAT_BYTES !\n");
545 case MCI_FORMAT_SAMPLES:
546 dprintf_mciwave(stddeb, "WAVE_mciSet // MCI_FORMAT_SAMPLES !\n");
549 dprintf_mciwave(stddeb, "WAVE_mciSet // bad time format !\n");
550 return MCIERR_BAD_TIME_FORMAT;
553 if (dwFlags & MCI_SET_VIDEO) return MCIERR_UNSUPPORTED_FUNCTION;
554 if (dwFlags & MCI_SET_DOOR_OPEN) return MCIERR_UNSUPPORTED_FUNCTION;
555 if (dwFlags & MCI_SET_DOOR_CLOSED) return MCIERR_UNSUPPORTED_FUNCTION;
556 if (dwFlags & MCI_SET_AUDIO)
557 dprintf_mciwave(stddeb,"WAVE_mciSet // MCI_SET_AUDIO !\n");
558 if (dwFlags && MCI_SET_ON) {
559 dprintf_mciwave(stddeb,"WAVE_mciSet // MCI_SET_ON !\n");
560 if (dwFlags && MCI_SET_AUDIO_LEFT)
561 dprintf_mciwave(stddeb,"WAVE_mciSet // MCI_SET_AUDIO_LEFT !\n");
562 if (dwFlags && MCI_SET_AUDIO_RIGHT)
563 dprintf_mciwave(stddeb,"WAVE_mciSet // MCI_SET_AUDIO_RIGHT !\n");
565 if (dwFlags & MCI_SET_OFF)
566 dprintf_mciwave(stddeb,"WAVE_mciSet // MCI_SET_OFF !\n");
567 if (dwFlags & MCI_WAVE_INPUT)
568 dprintf_mciwave(stddeb,"WAVE_mciSet // MCI_WAVE_INPUT !\n");
569 if (dwFlags & MCI_WAVE_OUTPUT)
570 dprintf_mciwave(stddeb,"WAVE_mciSet // MCI_WAVE_OUTPUT !\n");
571 if (dwFlags & MCI_WAVE_SET_ANYINPUT)
572 dprintf_mciwave(stddeb,"WAVE_mciSet // MCI_WAVE_SET_ANYINPUT !\n");
573 if (dwFlags & MCI_WAVE_SET_ANYOUTPUT)
574 dprintf_mciwave(stddeb,"WAVE_mciSet // MCI_WAVE_SET_ANYOUTPUT !\n");
575 if (dwFlags & MCI_WAVE_SET_AVGBYTESPERSEC)
576 dprintf_mciwave(stddeb,
577 "WAVE_mciSet // MCI_WAVE_SET_AVGBYTESPERSEC !\n");
578 if (dwFlags & MCI_WAVE_SET_BITSPERSAMPLE)
579 dprintf_mciwave(stddeb,
580 "WAVE_mciSet // MCI_WAVE_SET_BITSPERSAMPLE !\n");
581 if (dwFlags & MCI_WAVE_SET_BLOCKALIGN)
582 dprintf_mciwave(stddeb,"WAVE_mciSet // MCI_WAVE_SET_BLOCKALIGN !\n");
583 if (dwFlags & MCI_WAVE_SET_CHANNELS)
584 dprintf_mciwave(stddeb,"WAVE_mciSet // MCI_WAVE_SET_CHANNELS !\n");
585 if (dwFlags & MCI_WAVE_SET_FORMATTAG)
586 dprintf_mciwave(stddeb,"WAVE_mciSet // MCI_WAVE_SET_FORMATTAG !\n");
587 if (dwFlags & MCI_WAVE_SET_SAMPLESPERSEC)
588 dprintf_mciwave(stddeb,
589 "WAVE_mciSet // MCI_WAVE_SET_SAMPLESPERSEC !\n");
594 /**************************************************************************
595 * WAVE_mciStatus [internal]
597 static DWORD WAVE_mciStatus(UINT16 wDevID, DWORD dwFlags, LPMCI_STATUS_PARMS lpParms)
599 dprintf_mciwave(stddeb,
600 "WAVE_mciStatus(%u, %08lX, %p);\n", wDevID, dwFlags, lpParms);
601 if (lpParms == NULL) return MCIERR_INTERNAL;
602 if (dwFlags & MCI_STATUS_ITEM) {
603 switch(lpParms->dwItem) {
604 case MCI_STATUS_CURRENT_TRACK:
605 lpParms->dwReturn = 1;
607 case MCI_STATUS_LENGTH:
608 lpParms->dwReturn = 5555;
609 if (dwFlags & MCI_TRACK) {
610 lpParms->dwTrack = 1;
611 lpParms->dwReturn = 2222;
614 case MCI_STATUS_MODE:
615 lpParms->dwReturn = MCI_MODE_STOP;
617 case MCI_STATUS_MEDIA_PRESENT:
618 dprintf_mciwave(stddeb,"WAVE_mciStatus // MCI_STATUS_MEDIA_PRESENT !\n");
619 lpParms->dwReturn = TRUE;
621 case MCI_STATUS_NUMBER_OF_TRACKS:
622 lpParms->dwReturn = 1;
624 case MCI_STATUS_POSITION:
625 lpParms->dwReturn = 3333;
626 if (dwFlags & MCI_STATUS_START)
628 if (dwFlags & MCI_TRACK) {
629 lpParms->dwTrack = 1;
630 lpParms->dwReturn = 777;
633 case MCI_STATUS_READY:
634 dprintf_mciwave(stddeb,"WAVE_mciStatus // MCI_STATUS_READY !\n");
635 lpParms->dwReturn = TRUE;
637 case MCI_STATUS_TIME_FORMAT:
638 dprintf_mciwave(stddeb,"WAVE_mciStatus // MCI_STATUS_TIME_FORMAT !\n");
639 lpParms->dwReturn = MCI_FORMAT_MILLISECONDS;
642 dprintf_mciwave(stddeb,"WAVE_mciStatus // MCI_WAVE_INPUT !\n");
643 lpParms->dwReturn = 0;
645 case MCI_WAVE_OUTPUT:
646 dprintf_mciwave(stddeb,"WAVE_mciStatus // MCI_WAVE_OUTPUT !\n");
647 lpParms->dwReturn = 0;
649 case MCI_WAVE_STATUS_AVGBYTESPERSEC:
650 dprintf_mciwave(stddeb,"WAVE_mciStatus // MCI_WAVE_STATUS_AVGBYTESPERSEC !\n");
651 lpParms->dwReturn = 22050;
653 case MCI_WAVE_STATUS_BITSPERSAMPLE:
654 dprintf_mciwave(stddeb,"WAVE_mciStatus // MCI_WAVE_STATUS_BITSPERSAMPLE !\n");
655 lpParms->dwReturn = 8;
657 case MCI_WAVE_STATUS_BLOCKALIGN:
658 dprintf_mciwave(stddeb,"WAVE_mciStatus // MCI_WAVE_STATUS_BLOCKALIGN !\n");
659 lpParms->dwReturn = 1;
661 case MCI_WAVE_STATUS_CHANNELS:
662 dprintf_mciwave(stddeb,"WAVE_mciStatus // MCI_WAVE_STATUS_CHANNELS !\n");
663 lpParms->dwReturn = 1;
665 case MCI_WAVE_STATUS_FORMATTAG:
666 dprintf_mciwave(stddeb,"WAVE_mciStatus // MCI_WAVE_FORMATTAG !\n");
667 lpParms->dwReturn = WAVE_FORMAT_PCM;
669 case MCI_WAVE_STATUS_LEVEL:
670 dprintf_mciwave(stddeb,"WAVE_mciStatus // MCI_WAVE_STATUS_LEVEL !\n");
671 lpParms->dwReturn = 0xAAAA5555;
673 case MCI_WAVE_STATUS_SAMPLESPERSEC:
674 dprintf_mciwave(stddeb,"WAVE_mciStatus // MCI_WAVE_STATUS_SAMPLESPERSEC !\n");
675 lpParms->dwReturn = 22050;
678 dprintf_mciwave(stddeb,"WAVE_mciStatus // unknown command %08lX !\n", lpParms->dwItem);
679 return MCIERR_UNRECOGNIZED_COMMAND;
682 if (dwFlags & MCI_NOTIFY) {
683 dprintf_mciwave(stddeb,"WAVE_mciStatus // MCI_NOTIFY_SUCCESSFUL %08lX !\n", lpParms->dwCallback);
684 mciDriverNotify((HWND16)LOWORD(lpParms->dwCallback),
685 MCIWavDev[wDevID].wNotifyDeviceID, MCI_NOTIFY_SUCCESSFUL);
690 /**************************************************************************
691 * WAVE_mciGetDevCaps [internal]
693 static DWORD WAVE_mciGetDevCaps(UINT16 wDevID, DWORD dwFlags,
694 LPMCI_GETDEVCAPS_PARMS lpParms)
696 dprintf_mciwave(stddeb,
697 "WAVE_mciGetDevCaps(%u, %08lX, %p);\n", wDevID, dwFlags, lpParms);
698 if (lpParms == NULL) return MCIERR_INTERNAL;
699 if (dwFlags & MCI_GETDEVCAPS_ITEM) {
700 switch(lpParms->dwItem) {
701 case MCI_GETDEVCAPS_CAN_RECORD:
702 lpParms->dwReturn = TRUE;
704 case MCI_GETDEVCAPS_HAS_AUDIO:
705 lpParms->dwReturn = TRUE;
707 case MCI_GETDEVCAPS_HAS_VIDEO:
708 lpParms->dwReturn = FALSE;
710 case MCI_GETDEVCAPS_DEVICE_TYPE:
711 lpParms->dwReturn = MCI_DEVTYPE_WAVEFORM_AUDIO;
713 case MCI_GETDEVCAPS_USES_FILES:
714 lpParms->dwReturn = TRUE;
716 case MCI_GETDEVCAPS_COMPOUND_DEVICE:
717 lpParms->dwReturn = TRUE;
719 case MCI_GETDEVCAPS_CAN_EJECT:
720 lpParms->dwReturn = FALSE;
722 case MCI_GETDEVCAPS_CAN_PLAY:
723 lpParms->dwReturn = TRUE;
725 case MCI_GETDEVCAPS_CAN_SAVE:
726 lpParms->dwReturn = TRUE;
728 case MCI_WAVE_GETDEVCAPS_INPUTS:
729 lpParms->dwReturn = 1;
731 case MCI_WAVE_GETDEVCAPS_OUTPUTS:
732 lpParms->dwReturn = 1;
735 return MCIERR_UNRECOGNIZED_COMMAND;
741 /**************************************************************************
742 * WAVE_mciInfo [internal]
744 static DWORD WAVE_mciInfo(UINT16 wDevID, DWORD dwFlags, LPMCI_INFO_PARMS16 lpParms)
746 dprintf_mciwave(stddeb,
747 "WAVE_mciInfo(%u, %08lX, %p);\n", wDevID, dwFlags, lpParms);
748 if (lpParms == NULL) return MCIERR_INTERNAL;
749 lpParms->lpstrReturn = NULL;
751 case MCI_INFO_PRODUCT:
752 lpParms->lpstrReturn = "Linux Sound System 0.5";
755 lpParms->lpstrReturn =
756 (LPSTR)MCIWavDev[wDevID].openParms.lpstrElementName;
759 lpParms->lpstrReturn = "Linux Sound System 0.5";
761 case MCI_WAVE_OUTPUT:
762 lpParms->lpstrReturn = "Linux Sound System 0.5";
765 return MCIERR_UNRECOGNIZED_COMMAND;
767 if (lpParms->lpstrReturn != NULL)
768 lpParms->dwRetSize = strlen(lpParms->lpstrReturn);
770 lpParms->dwRetSize = 0;
775 /*-----------------------------------------------------------------------*/
778 /**************************************************************************
779 * wodGetDevCaps [internal]
781 static DWORD wodGetDevCaps(WORD wDevID, LPWAVEOUTCAPS16 lpCaps, DWORD dwSize)
789 dprintf_mciwave(stddeb,
790 "wodGetDevCaps(%u, %p, %lu);\n", wDevID, lpCaps, dwSize);
791 if (lpCaps == NULL) return MMSYSERR_NOTENABLED;
792 if (access(SOUND_DEV,0) != 0) return MMSYSERR_NOTENABLED;
793 audio = open (SOUND_DEV, O_WRONLY, 0);
794 if (audio == -1) return MMSYSERR_ALLOCATED ;
796 lpCaps->wMid = 0x0002;
797 lpCaps->wPid = 0x0104;
798 strcpy(lpCaps->szPname, "SB16 Wave Out");
800 lpCaps->wMid = 0x00FF; /* Manufac ID */
801 lpCaps->wPid = 0x0001; /* Product ID */
802 strcpy(lpCaps->szPname, "Linux WAVOUT Driver");
804 lpCaps->vDriverVersion = 0x0100;
805 lpCaps->dwFormats = 0x00000000;
806 lpCaps->dwSupport = WAVECAPS_VOLUME;
807 lpCaps->wChannels = (IOCTL(audio, SNDCTL_DSP_STEREO, dsp_stereo) != 0) ? 1 : 2;
808 if (lpCaps->wChannels > 1) lpCaps->dwSupport |= WAVECAPS_LRVOLUME;
809 bytespersmpl = (IOCTL(audio, SNDCTL_DSP_SAMPLESIZE, samplesize) != 0) ? 1 : 2;
811 if (IOCTL(audio, SNDCTL_DSP_SPEED, smplrate) == 0) {
812 lpCaps->dwFormats |= WAVE_FORMAT_4M08;
813 if (lpCaps->wChannels > 1)
814 lpCaps->dwFormats |= WAVE_FORMAT_4S08;
815 if (bytespersmpl > 1) {
816 lpCaps->dwFormats |= WAVE_FORMAT_4M16;
817 if (lpCaps->wChannels > 1)
818 lpCaps->dwFormats |= WAVE_FORMAT_4S16;
822 if (IOCTL(audio, SNDCTL_DSP_SPEED, smplrate) == 0) {
823 lpCaps->dwFormats |= WAVE_FORMAT_2M08;
824 if (lpCaps->wChannels > 1)
825 lpCaps->dwFormats |= WAVE_FORMAT_2S08;
826 if (bytespersmpl > 1) {
827 lpCaps->dwFormats |= WAVE_FORMAT_2M16;
828 if (lpCaps->wChannels > 1)
829 lpCaps->dwFormats |= WAVE_FORMAT_2S16;
833 if (IOCTL(audio, SNDCTL_DSP_SPEED, smplrate) == 0) {
834 lpCaps->dwFormats |= WAVE_FORMAT_1M08;
835 if (lpCaps->wChannels > 1)
836 lpCaps->dwFormats |= WAVE_FORMAT_1S08;
837 if (bytespersmpl > 1) {
838 lpCaps->dwFormats |= WAVE_FORMAT_1M16;
839 if (lpCaps->wChannels > 1)
840 lpCaps->dwFormats |= WAVE_FORMAT_1S16;
844 dprintf_mciwave(stddeb,
845 "wodGetDevCaps // dwFormats = %08lX\n", lpCaps->dwFormats);
846 return MMSYSERR_NOERROR;
850 /**************************************************************************
853 static DWORD wodOpen(WORD wDevID, LPWAVEOPENDESC lpDesc, DWORD dwFlags)
855 int audio,abuf_size,smplrate,samplesize,dsp_stereo;
856 LPWAVEFORMAT lpFormat;
858 dprintf_mciwave(stddeb,
859 "wodOpen(%u, %p, %08lX);\n", wDevID, lpDesc, dwFlags);
860 if (lpDesc == NULL) {
861 dprintf_mciwave(stddeb,"Linux 'wodOpen' // Invalid Parameter !\n");
862 return MMSYSERR_INVALPARAM;
864 if (wDevID >= MAX_WAVOUTDRV) {
865 dprintf_mciwave(stddeb,"Linux 'wodOpen' // MAX_WAVOUTDRV reached !\n");
866 return MMSYSERR_ALLOCATED;
868 WOutDev[wDevID].unixdev = 0;
869 if (access(SOUND_DEV,0) != 0) return MMSYSERR_NOTENABLED;
870 audio = open (SOUND_DEV, O_WRONLY, 0);
872 dprintf_mciwave(stddeb,"Linux 'wodOpen' // can't open !\n");
873 return MMSYSERR_ALLOCATED ;
875 IOCTL(audio, SNDCTL_DSP_GETBLKSIZE, abuf_size);
876 if (abuf_size < 1024 || abuf_size > 65536) {
878 dprintf_mciwave(stddeb,"Linux 'wodOpen' // IOCTL can't 'SNDCTL_DSP_GETBLKSIZE' !\n");
880 dprintf_mciwave(stddeb,"Linux 'wodOpen' // SNDCTL_DSP_GETBLKSIZE Invalid bufsize !\n");
881 return MMSYSERR_NOTENABLED;
883 WOutDev[wDevID].wFlags = HIWORD(dwFlags & CALLBACK_TYPEMASK);
884 switch(WOutDev[wDevID].wFlags) {
886 dprintf_mciwave(stddeb, "Linux 'wodOpen' // CALLBACK_NULL !\n");
889 dprintf_mciwave(stddeb, "Linux 'wodOpen' // CALLBACK_WINDOW !\n");
892 dprintf_mciwave(stddeb, "Linux 'wodOpen' // CALLBACK_TASK !\n");
895 dprintf_mciwave(stddeb, "Linux 'wodOpen' // CALLBACK_FUNCTION !\n");
898 WOutDev[wDevID].lpQueueHdr = NULL;
899 WOutDev[wDevID].unixdev = audio;
900 WOutDev[wDevID].dwTotalPlayed = 0;
901 WOutDev[wDevID].bufsize = abuf_size;
902 /* FIXME: copy lpFormat too? */
903 memcpy(&WOutDev[wDevID].waveDesc, lpDesc, sizeof(WAVEOPENDESC));
904 dprintf_mciwave(stddeb,"Linux 'wodOpen' // lpDesc->lpFormat = %p\n",lpDesc->lpFormat);
905 lpFormat = lpDesc->lpFormat;
906 dprintf_mciwave(stddeb,"Linux 'wodOpen' // lpFormat = %p\n",lpFormat);
907 if (lpFormat->wFormatTag != WAVE_FORMAT_PCM) {
908 dprintf_mciwave(stddeb,"Linux 'wodOpen' // Bad format %04X !\n",
909 lpFormat->wFormatTag);
910 dprintf_mciwave(stddeb,"Linux 'wodOpen' // Bad nChannels %d !\n",
911 lpFormat->nChannels);
912 dprintf_mciwave(stddeb,"Linux 'wodOpen' // Bad nSamplesPerSec %ld !\n",
913 lpFormat->nSamplesPerSec);
914 return WAVERR_BADFORMAT;
916 memcpy(&WOutDev[wDevID].Format, lpFormat, sizeof(PCMWAVEFORMAT));
917 if (WOutDev[wDevID].Format.wf.nChannels == 0) return WAVERR_BADFORMAT;
918 if (WOutDev[wDevID].Format.wf.nSamplesPerSec == 0) return WAVERR_BADFORMAT;
919 dprintf_mciwave(stddeb,"Linux 'wodOpen' // wBitsPerSample=%u !\n",
920 WOutDev[wDevID].Format.wBitsPerSample);
921 if (WOutDev[wDevID].Format.wBitsPerSample == 0) {
922 WOutDev[wDevID].Format.wBitsPerSample = 8 *
923 (WOutDev[wDevID].Format.wf.nAvgBytesPerSec /
924 WOutDev[wDevID].Format.wf.nSamplesPerSec) /
925 WOutDev[wDevID].Format.wf.nChannels;
927 samplesize = WOutDev[wDevID].Format.wBitsPerSample;
928 smplrate = WOutDev[wDevID].Format.wf.nSamplesPerSec;
929 dsp_stereo = (WOutDev[wDevID].Format.wf.nChannels > 1) ? TRUE : FALSE;
930 IOCTL(audio, SNDCTL_DSP_SPEED, smplrate);
931 IOCTL(audio, SNDCTL_DSP_SAMPLESIZE, samplesize);
932 IOCTL(audio, SNDCTL_DSP_STEREO, dsp_stereo);
933 dprintf_mciwave(stddeb,"Linux 'wodOpen' // wBitsPerSample=%u !\n",
934 WOutDev[wDevID].Format.wBitsPerSample);
935 dprintf_mciwave(stddeb,"Linux 'wodOpen' // nAvgBytesPerSec=%lu !\n",
936 WOutDev[wDevID].Format.wf.nAvgBytesPerSec);
937 dprintf_mciwave(stddeb,"Linux 'wodOpen' // nSamplesPerSec=%lu !\n",
938 WOutDev[wDevID].Format.wf.nSamplesPerSec);
939 dprintf_mciwave(stddeb,"Linux 'wodOpen' // nChannels=%u !\n",
940 WOutDev[wDevID].Format.wf.nChannels);
941 if (WAVE_NotifyClient(wDevID, WOM_OPEN, 0L, 0L) != MMSYSERR_NOERROR) {
942 dprintf_mciwave(stddeb,"Linux 'wodOpen' // can't notify client !\n");
943 return MMSYSERR_INVALPARAM;
945 return MMSYSERR_NOERROR;
948 /**************************************************************************
949 * wodClose [internal]
951 static DWORD wodClose(WORD wDevID)
953 dprintf_mciwave(stddeb,"wodClose(%u);\n", wDevID);
954 if (wDevID > MAX_WAVOUTDRV) return MMSYSERR_INVALPARAM;
955 if (WOutDev[wDevID].unixdev == 0) {
956 dprintf_mciwave(stddeb,"Linux 'wodClose' // can't close !\n");
957 return MMSYSERR_NOTENABLED;
959 if (WOutDev[wDevID].lpQueueHdr != NULL) {
960 dprintf_mciwave(stddeb,"linux 'wodclose' // still buffers open !\n");
961 /* Don't care. Who needs those buffers anyway */
962 /*return WAVERR_STILLPLAYING; */
964 close(WOutDev[wDevID].unixdev);
965 WOutDev[wDevID].unixdev = 0;
966 WOutDev[wDevID].bufsize = 0;
967 WOutDev[wDevID].lpQueueHdr = NULL;
968 if (WAVE_NotifyClient(wDevID, WOM_CLOSE, 0L, 0L) != MMSYSERR_NOERROR) {
969 dprintf_mciwave(stddeb,"Linux 'wodClose' // can't notify client !\n");
970 return MMSYSERR_INVALPARAM;
972 return MMSYSERR_NOERROR;
975 /**************************************************************************
976 * wodWrite [internal]
977 * FIXME: this should _APPEND_ the lpWaveHdr to the output queue of the
978 * device, and initiate async playing.
980 static DWORD wodWrite(WORD wDevID, LPWAVEHDR lpWaveHdr, DWORD dwSize)
986 dprintf_mciwave(stddeb,"wodWrite(%u, %p, %08lX);\n", wDevID, lpWaveHdr, dwSize);
987 if (WOutDev[wDevID].unixdev == 0) {
988 dprintf_mciwave(stddeb,"Linux 'wodWrite' // can't play !\n");
989 return MMSYSERR_NOTENABLED;
991 if (lpWaveHdr->lpData == NULL) return WAVERR_UNPREPARED;
992 if (!(lpWaveHdr->dwFlags & WHDR_PREPARED)) return WAVERR_UNPREPARED;
993 if (lpWaveHdr->dwFlags & WHDR_INQUEUE) return WAVERR_STILLPLAYING;
994 lpWaveHdr->dwFlags &= ~WHDR_DONE;
995 lpWaveHdr->dwFlags |= WHDR_INQUEUE;
996 dprintf_mciwave(stddeb,
997 "wodWrite() // dwBufferLength %lu !\n", lpWaveHdr->dwBufferLength);
998 dprintf_mciwave(stddeb,
999 "wodWrite() // WOutDev[%u].unixdev %u !\n", wDevID, WOutDev[wDevID].unixdev);
1000 lpData = lpWaveHdr->lpData;
1001 count = write (WOutDev[wDevID].unixdev, lpData, lpWaveHdr->dwBufferLength);
1002 dprintf_mciwave(stddeb,"wodWrite()//write returned count %u !\n",count);
1003 if (count != lpWaveHdr->dwBufferLength) {
1004 dprintf_mciwave(stddeb,"Linux 'wodWrite' // error writting !\n");
1005 return MMSYSERR_NOTENABLED;
1007 WOutDev[wDevID].dwTotalPlayed += count;
1008 lpWaveHdr->dwFlags &= ~WHDR_INQUEUE;
1009 lpWaveHdr->dwFlags |= WHDR_DONE;
1010 if ((DWORD)lpWaveHdr->lpData!=lpWaveHdr->reserved) {
1011 /* FIXME: what if it expects it's OWN lpwavehdr back? */
1012 xwavehdr = SEGPTR_NEW(WAVEHDR);
1013 memcpy(xwavehdr,lpWaveHdr,sizeof(WAVEHDR));
1014 xwavehdr->lpData = (LPBYTE)xwavehdr->reserved;
1015 if (WAVE_NotifyClient(wDevID, WOM_DONE, (DWORD)SEGPTR_GET(xwavehdr), count) != MMSYSERR_NOERROR) {
1016 dprintf_mciwave(stddeb,"Linux 'wodWrite' // can't notify client !\n");
1017 SEGPTR_FREE(xwavehdr);
1018 return MMSYSERR_INVALPARAM;
1020 SEGPTR_FREE(xwavehdr);
1022 if (WAVE_NotifyClient(wDevID, WOM_DONE, (DWORD)lpWaveHdr, count) != MMSYSERR_NOERROR) {
1023 dprintf_mciwave(stddeb,"Linux 'wodWrite' // can't notify client !\n");
1024 return MMSYSERR_INVALPARAM;
1027 return MMSYSERR_NOERROR;
1030 /**************************************************************************
1031 * wodPrepare [internal]
1033 static DWORD wodPrepare(WORD wDevID, LPWAVEHDR lpWaveHdr, DWORD dwSize)
1035 dprintf_mciwave(stddeb,
1036 "wodPrepare(%u, %p, %08lX);\n", wDevID, lpWaveHdr, dwSize);
1037 if (WOutDev[wDevID].unixdev == 0) {
1038 dprintf_mciwave(stddeb,"Linux 'wodPrepare' // can't prepare !\n");
1039 return MMSYSERR_NOTENABLED;
1041 /* don't append to queue, wodWrite does that */
1042 WOutDev[wDevID].dwTotalPlayed = 0;
1043 if (lpWaveHdr->dwFlags & WHDR_INQUEUE)
1044 return WAVERR_STILLPLAYING;
1045 lpWaveHdr->dwFlags |= WHDR_PREPARED;
1046 lpWaveHdr->dwFlags &= ~WHDR_DONE;
1047 return MMSYSERR_NOERROR;
1050 /**************************************************************************
1051 * wodUnprepare [internal]
1053 static DWORD wodUnprepare(WORD wDevID, LPWAVEHDR lpWaveHdr, DWORD dwSize)
1055 dprintf_mciwave(stddeb,
1056 "wodUnprepare(%u, %p, %08lX);\n", wDevID, lpWaveHdr, dwSize);
1057 if (WOutDev[wDevID].unixdev == 0) {
1058 dprintf_mciwave(stddeb,"Linux 'wodUnprepare' // can't unprepare !\n");
1059 return MMSYSERR_NOTENABLED;
1061 if (lpWaveHdr->dwFlags & WHDR_INQUEUE)
1062 return WAVERR_STILLPLAYING;
1064 lpWaveHdr->dwFlags &= ~WHDR_PREPARED;
1065 lpWaveHdr->dwFlags |= WHDR_DONE;
1066 dprintf_mciwave(stddeb,
1067 "Linux 'wodUnprepare' // all headers unprepared !\n");
1068 return MMSYSERR_NOERROR;
1071 /**************************************************************************
1072 * wodRestart [internal]
1074 static DWORD wodRestart(WORD wDevID)
1076 dprintf_mciwave(stddeb,"wodRestart(%u);\n", wDevID);
1077 if (WOutDev[wDevID].unixdev == 0) {
1078 dprintf_mciwave(stddeb,"Linux 'wodRestart' // can't restart !\n");
1079 return MMSYSERR_NOTENABLED;
1081 /* FIXME: is NotifyClient with WOM_DONE right ? (Comet Busters 1.3.3 needs this notification) */
1082 if (WAVE_NotifyClient(wDevID, WOM_DONE, 0L, 0L) != MMSYSERR_NOERROR) {
1083 dprintf_mciwave(stddeb,"Linux 'wodRestart' // can't notify client !\n");
1084 return MMSYSERR_INVALPARAM;
1087 return MMSYSERR_NOERROR;
1090 /**************************************************************************
1091 * wodReset [internal]
1093 static DWORD wodReset(WORD wDevID)
1095 dprintf_mciwave(stddeb,"wodReset(%u);\n", wDevID);
1096 if (WOutDev[wDevID].unixdev == 0) {
1097 dprintf_mciwave(stddeb,"Linux 'wodReset' // can't reset !\n");
1098 return MMSYSERR_NOTENABLED;
1100 return MMSYSERR_NOERROR;
1104 /**************************************************************************
1105 * wodGetPosition [internal]
1107 static DWORD wodGetPosition(WORD wDevID, LPMMTIME16 lpTime, DWORD uSize)
1110 dprintf_mciwave(stddeb,"wodGetPosition(%u, %p, %lu);\n", wDevID, lpTime, uSize);
1111 if (WOutDev[wDevID].unixdev == 0) {
1112 dprintf_mciwave(stddeb,"Linux 'wodGetPosition' // can't get pos !\n");
1113 return MMSYSERR_NOTENABLED;
1115 if (lpTime == NULL) return MMSYSERR_INVALPARAM;
1116 dprintf_mciwave(stddeb,"wodGetPosition // wType=%04X !\n",
1118 dprintf_mciwave(stddeb,"wodGetPosition // wBitsPerSample=%u\n",
1119 WOutDev[wDevID].Format.wBitsPerSample);
1120 dprintf_mciwave(stddeb,"wodGetPosition // nSamplesPerSec=%lu\n",
1121 WOutDev[wDevID].Format.wf.nSamplesPerSec);
1122 dprintf_mciwave(stddeb,"wodGetPosition // nChannels=%u\n",
1123 WOutDev[wDevID].Format.wf.nChannels);
1124 dprintf_mciwave(stddeb,"wodGetPosition // nAvgBytesPerSec=%lu\n",
1125 WOutDev[wDevID].Format.wf.nAvgBytesPerSec);
1126 switch(lpTime->wType) {
1128 lpTime->u.cb = WOutDev[wDevID].dwTotalPlayed;
1129 dprintf_mciwave(stddeb,"wodGetPosition // TIME_BYTES=%lu\n", lpTime->u.cb);
1132 dprintf_mciwave(stddeb,"wodGetPosition // dwTotalPlayed=%lu\n",
1133 WOutDev[wDevID].dwTotalPlayed);
1134 dprintf_mciwave(stddeb,"wodGetPosition // wBitsPerSample=%u\n",
1135 WOutDev[wDevID].Format.wBitsPerSample);
1136 lpTime->u.sample = WOutDev[wDevID].dwTotalPlayed * 8 /
1137 WOutDev[wDevID].Format.wBitsPerSample;
1138 dprintf_mciwave(stddeb,"wodGetPosition // TIME_SAMPLES=%lu\n", lpTime->u.sample);
1141 time = WOutDev[wDevID].dwTotalPlayed /
1142 (WOutDev[wDevID].Format.wf.nAvgBytesPerSec / 1000);
1143 lpTime->u.smpte.hour = time / 108000;
1144 time -= lpTime->u.smpte.hour * 108000;
1145 lpTime->u.smpte.min = time / 1800;
1146 time -= lpTime->u.smpte.min * 1800;
1147 lpTime->u.smpte.sec = time / 30;
1148 time -= lpTime->u.smpte.sec * 30;
1149 lpTime->u.smpte.frame = time;
1150 lpTime->u.smpte.fps = 30;
1151 dprintf_mciwave(stddeb,
1152 "wodGetPosition // TIME_SMPTE=%02u:%02u:%02u:%02u\n",
1153 lpTime->u.smpte.hour, lpTime->u.smpte.min,
1154 lpTime->u.smpte.sec, lpTime->u.smpte.frame);
1157 dprintf_mciwave(stddeb,"wodGetPosition() format not supported ! use TIME_MS !\n");
1158 lpTime->wType = TIME_MS;
1160 lpTime->u.ms = WOutDev[wDevID].dwTotalPlayed /
1161 (WOutDev[wDevID].Format.wf.nAvgBytesPerSec / 1000);
1162 dprintf_mciwave(stddeb,"wodGetPosition // TIME_MS=%lu\n", lpTime->u.ms);
1165 return MMSYSERR_NOERROR;
1168 /**************************************************************************
1169 * wodGetVolume [internal]
1171 static DWORD wodGetVolume(WORD wDevID, LPDWORD lpdwVol)
1174 int volume, left, right;
1175 dprintf_mciwave(stddeb,"wodGetVolume(%u, %p);\n", wDevID, lpdwVol);
1176 if (lpdwVol == NULL) return MMSYSERR_NOTENABLED;
1177 if ((mixer = open(MIXER_DEV, O_RDONLY)) < 0) {
1178 dprintf_mciwave(stddeb, "Linux 'wodGetVolume' // mixer device not available !\n");
1179 return MMSYSERR_NOTENABLED;
1181 if (ioctl(mixer, SOUND_MIXER_READ_PCM, &volume) == -1) {
1182 dprintf_mciwave(stddeb,"Linux 'wodGetVolume' // unable read mixer !\n");
1183 return MMSYSERR_NOTENABLED;
1186 left = volume & 0x7F;
1187 right = (volume >> 8) & 0x7F;
1188 dprintf_mciwave(stddeb,"Linux 'wodGetVolume' // left=%d right=%d !\n", left, right);
1189 *lpdwVol = MAKELONG(left << 9, right << 9);
1190 return MMSYSERR_NOERROR;
1194 /**************************************************************************
1195 * wodSetVolume [internal]
1197 static DWORD wodSetVolume(WORD wDevID, DWORD dwParam)
1201 dprintf_mciwave(stddeb,"wodSetVolume(%u, %08lX);\n", wDevID, dwParam);
1202 volume = (LOWORD(dwParam) >> 9 & 0x7F) +
1203 ((HIWORD(dwParam) >> 9 & 0x7F) << 8);
1204 if ((mixer = open(MIXER_DEV, O_WRONLY)) < 0) {
1205 dprintf_mciwave(stddeb, "Linux 'wodSetVolume' // mixer device not available !\n");
1206 return MMSYSERR_NOTENABLED;
1208 if (ioctl(mixer, SOUND_MIXER_WRITE_PCM, &volume) == -1) {
1209 dprintf_mciwave(stddeb,"Linux 'wodSetVolume' // unable set mixer !\n");
1210 return MMSYSERR_NOTENABLED;
1213 return MMSYSERR_NOERROR;
1216 #endif /* linux || __FreeBSD__*/
1218 /**************************************************************************
1219 * wodMessage [sample driver]
1221 DWORD wodMessage(WORD wDevID, WORD wMsg, DWORD dwUser,
1222 DWORD dwParam1, DWORD dwParam2)
1224 dprintf_mciwave(stddeb,"wodMessage(%u, %04X, %08lX, %08lX, %08lX);\n",
1225 wDevID, wMsg, dwUser, dwParam1, dwParam2);
1226 #if defined(linux) || defined(__FreeBSD__)
1229 return wodOpen(wDevID, (LPWAVEOPENDESC)dwParam1, dwParam2);
1231 return wodClose(wDevID);
1233 return wodWrite(wDevID, (LPWAVEHDR)dwParam1, dwParam2);
1235 return MMSYSERR_NOTSUPPORTED;
1237 return MMSYSERR_NOTSUPPORTED;
1239 return wodGetPosition(wDevID, (LPMMTIME16)dwParam1, dwParam2);
1240 case WODM_BREAKLOOP:
1241 return MMSYSERR_NOTSUPPORTED;
1243 return wodPrepare(wDevID, (LPWAVEHDR)dwParam1, dwParam2);
1244 case WODM_UNPREPARE:
1245 return wodUnprepare(wDevID, (LPWAVEHDR)dwParam1, dwParam2);
1246 case WODM_GETDEVCAPS:
1247 return wodGetDevCaps(wDevID,(LPWAVEOUTCAPS16)dwParam1,dwParam2);
1248 case WODM_GETNUMDEVS:
1251 return MMSYSERR_NOTSUPPORTED;
1253 return MMSYSERR_NOTSUPPORTED;
1254 case WODM_GETPLAYBACKRATE:
1255 return MMSYSERR_NOTSUPPORTED;
1256 case WODM_SETPLAYBACKRATE:
1257 return MMSYSERR_NOTSUPPORTED;
1258 case WODM_GETVOLUME:
1259 return wodGetVolume(wDevID, (LPDWORD)dwParam1);
1260 case WODM_SETVOLUME:
1261 return wodSetVolume(wDevID, dwParam1);
1263 return wodRestart(wDevID);
1265 return wodReset(wDevID);
1267 dprintf_mciwave(stddeb,"wodMessage // unknown message !\n");
1269 return MMSYSERR_NOTSUPPORTED;
1271 return MMSYSERR_NOTENABLED;
1276 /*-----------------------------------------------------------------------*/
1278 #if defined(linux) || defined(__FreeBSD__)
1280 /**************************************************************************
1281 * widGetDevCaps [internal]
1283 static DWORD widGetDevCaps(WORD wDevID, LPWAVEINCAPS16 lpCaps, DWORD dwSize)
1285 int audio,smplrate,samplesize=16,dsp_stereo=1,bytespersmpl;
1287 dprintf_mciwave(stddeb,
1288 "widGetDevCaps(%u, %p, %lu);\n", wDevID, lpCaps, dwSize);
1289 if (lpCaps == NULL) return MMSYSERR_NOTENABLED;
1290 if (access(SOUND_DEV,0) != 0) return MMSYSERR_NOTENABLED;
1291 audio = open (SOUND_DEV, O_RDONLY, 0);
1292 if (audio == -1) return MMSYSERR_ALLOCATED ;
1294 lpCaps->wMid = 0x0002;
1295 lpCaps->wPid = 0x0004;
1296 strcpy(lpCaps->szPname, "SB16 Wave In");
1298 lpCaps->wMid = 0x00FF; /* Manufac ID */
1299 lpCaps->wPid = 0x0001; /* Product ID */
1300 strcpy(lpCaps->szPname, "Linux WAVIN Driver");
1302 lpCaps->dwFormats = 0x00000000;
1303 lpCaps->wChannels = (IOCTL(audio, SNDCTL_DSP_STEREO, dsp_stereo) != 0) ? 1 : 2;
1304 bytespersmpl = (IOCTL(audio, SNDCTL_DSP_SAMPLESIZE, samplesize) != 0) ? 1 : 2;
1306 if (IOCTL(audio, SNDCTL_DSP_SPEED, smplrate) == 0) {
1307 lpCaps->dwFormats |= WAVE_FORMAT_4M08;
1308 if (lpCaps->wChannels > 1)
1309 lpCaps->dwFormats |= WAVE_FORMAT_4S08;
1310 if (bytespersmpl > 1) {
1311 lpCaps->dwFormats |= WAVE_FORMAT_4M16;
1312 if (lpCaps->wChannels > 1)
1313 lpCaps->dwFormats |= WAVE_FORMAT_4S16;
1317 if (IOCTL(audio, SNDCTL_DSP_SPEED, smplrate) == 0) {
1318 lpCaps->dwFormats |= WAVE_FORMAT_2M08;
1319 if (lpCaps->wChannels > 1)
1320 lpCaps->dwFormats |= WAVE_FORMAT_2S08;
1321 if (bytespersmpl > 1) {
1322 lpCaps->dwFormats |= WAVE_FORMAT_2M16;
1323 if (lpCaps->wChannels > 1)
1324 lpCaps->dwFormats |= WAVE_FORMAT_2S16;
1328 if (IOCTL(audio, SNDCTL_DSP_SPEED, smplrate) == 0) {
1329 lpCaps->dwFormats |= WAVE_FORMAT_1M08;
1330 if (lpCaps->wChannels > 1)
1331 lpCaps->dwFormats |= WAVE_FORMAT_1S08;
1332 if (bytespersmpl > 1) {
1333 lpCaps->dwFormats |= WAVE_FORMAT_1M16;
1334 if (lpCaps->wChannels > 1)
1335 lpCaps->dwFormats |= WAVE_FORMAT_1S16;
1339 dprintf_mciwave(stddeb,
1340 "widGetDevCaps // dwFormats = %08lX\n", lpCaps->dwFormats);
1341 return MMSYSERR_NOERROR;
1345 /**************************************************************************
1346 * widOpen [internal]
1348 static DWORD widOpen(WORD wDevID, LPWAVEOPENDESC lpDesc, DWORD dwFlags)
1350 int audio,abuf_size,smplrate,samplesize,dsp_stereo;
1351 LPWAVEFORMAT lpFormat;
1353 dprintf_mciwave(stddeb, "widOpen(%u, %p, %08lX);\n", wDevID, lpDesc, dwFlags);
1354 if (lpDesc == NULL) {
1355 dprintf_mciwave(stddeb,"Linux 'widOpen' // Invalid Parameter !\n");
1356 return MMSYSERR_INVALPARAM;
1358 if (wDevID >= MAX_WAVINDRV) {
1359 dprintf_mciwave(stddeb,"Linux 'widOpen' // MAX_WAVINDRV reached !\n");
1360 return MMSYSERR_ALLOCATED;
1362 WInDev[wDevID].unixdev = 0;
1363 if (access(SOUND_DEV,0) != 0) return MMSYSERR_NOTENABLED;
1364 audio = open (SOUND_DEV, O_RDONLY, 0);
1366 dprintf_mciwave(stddeb,"Linux 'widOpen' // can't open !\n");
1367 return MMSYSERR_ALLOCATED;
1369 IOCTL(audio, SNDCTL_DSP_GETBLKSIZE, abuf_size);
1370 if (abuf_size < 1024 || abuf_size > 65536) {
1371 if (abuf_size == -1)
1372 dprintf_mciwave(stddeb,"Linux 'widOpen' // IOCTL can't 'SNDCTL_DSP_GETBLKSIZE' !\n");
1374 dprintf_mciwave(stddeb,"Linux 'widOpen' // SNDCTL_DSP_GETBLKSIZE Invalid bufsize !\n");
1375 return MMSYSERR_NOTENABLED;
1377 WInDev[wDevID].wFlags = HIWORD(dwFlags & CALLBACK_TYPEMASK);
1378 switch(WInDev[wDevID].wFlags) {
1380 dprintf_mciwave(stddeb,"Linux 'widOpen' // CALLBACK_NULL!\n");
1383 dprintf_mciwave(stddeb,"Linux 'widOpen' // CALLBACK_WINDOW!\n");
1386 dprintf_mciwave(stddeb,"Linux 'widOpen' // CALLBACK_TASK!\n");
1389 dprintf_mciwave(stddeb,"Linux 'widOpen' // CALLBACK_FUNCTION!\n");
1392 if (WInDev[wDevID].lpQueueHdr) {
1393 HeapFree(GetProcessHeap(),0,WInDev[wDevID].lpQueueHdr);
1394 WInDev[wDevID].lpQueueHdr = NULL;
1396 WInDev[wDevID].unixdev = audio;
1397 WInDev[wDevID].bufsize = abuf_size;
1398 WInDev[wDevID].dwTotalRecorded = 0;
1399 memcpy(&WInDev[wDevID].waveDesc, lpDesc, sizeof(WAVEOPENDESC));
1400 lpFormat = (LPWAVEFORMAT) lpDesc->lpFormat;
1401 if (lpFormat->wFormatTag != WAVE_FORMAT_PCM) {
1402 dprintf_mciwave(stddeb,"Linux 'widOpen' // Bad format %04X !\n",
1403 lpFormat->wFormatTag);
1404 return WAVERR_BADFORMAT;
1406 memcpy(&WInDev[wDevID].Format, lpFormat, sizeof(PCMWAVEFORMAT));
1407 WInDev[wDevID].Format.wBitsPerSample = 8; /* <-------------- */
1408 if (WInDev[wDevID].Format.wf.nChannels == 0) return WAVERR_BADFORMAT;
1409 if (WInDev[wDevID].Format.wf.nSamplesPerSec == 0) return WAVERR_BADFORMAT;
1410 if (WInDev[wDevID].Format.wBitsPerSample == 0) {
1411 WInDev[wDevID].Format.wBitsPerSample = 8 *
1412 (WInDev[wDevID].Format.wf.nAvgBytesPerSec /
1413 WInDev[wDevID].Format.wf.nSamplesPerSec) /
1414 WInDev[wDevID].Format.wf.nChannels;
1416 samplesize = WInDev[wDevID].Format.wBitsPerSample;
1417 smplrate = WInDev[wDevID].Format.wf.nSamplesPerSec;
1418 dsp_stereo = (WInDev[wDevID].Format.wf.nChannels > 1) ? TRUE : FALSE;
1419 IOCTL(audio, SNDCTL_DSP_SPEED, smplrate);
1420 IOCTL(audio, SNDCTL_DSP_SAMPLESIZE, samplesize);
1421 IOCTL(audio, SNDCTL_DSP_STEREO, dsp_stereo);
1422 dprintf_mciwave(stddeb,"Linux 'widOpen' // wBitsPerSample=%u !\n",
1423 WInDev[wDevID].Format.wBitsPerSample);
1424 dprintf_mciwave(stddeb,"Linux 'widOpen' // nSamplesPerSec=%lu !\n",
1425 WInDev[wDevID].Format.wf.nSamplesPerSec);
1426 dprintf_mciwave(stddeb,"Linux 'widOpen' // nChannels=%u !\n",
1427 WInDev[wDevID].Format.wf.nChannels);
1428 dprintf_mciwave(stddeb,"Linux 'widOpen' // nAvgBytesPerSec=%lu\n",
1429 WInDev[wDevID].Format.wf.nAvgBytesPerSec);
1430 if (WAVE_NotifyClient(wDevID, WIM_OPEN, 0L, 0L) != MMSYSERR_NOERROR) {
1431 dprintf_mciwave(stddeb,"Linux 'widOpen' // can't notify client !\n");
1432 return MMSYSERR_INVALPARAM;
1434 return MMSYSERR_NOERROR;
1437 /**************************************************************************
1438 * widClose [internal]
1440 static DWORD widClose(WORD wDevID)
1442 dprintf_mciwave(stddeb,"widClose(%u);\n", wDevID);
1443 if (wDevID > MAX_WAVINDRV) return MMSYSERR_INVALPARAM;
1444 if (WInDev[wDevID].unixdev == 0) {
1445 dprintf_mciwave(stddeb,"Linux 'widClose' // can't close !\n");
1446 return MMSYSERR_NOTENABLED;
1448 if (WInDev[wDevID].lpQueueHdr != NULL) {
1449 dprintf_mciwave(stddeb,"linux 'widclose' // still buffers open !\n");
1450 return WAVERR_STILLPLAYING;
1452 close(WInDev[wDevID].unixdev);
1453 WInDev[wDevID].unixdev = 0;
1454 WInDev[wDevID].bufsize = 0;
1455 if (WAVE_NotifyClient(wDevID, WIM_CLOSE, 0L, 0L) != MMSYSERR_NOERROR) {
1456 dprintf_mciwave(stddeb,"Linux 'widClose' // can't notify client !\n");
1457 return MMSYSERR_INVALPARAM;
1459 return MMSYSERR_NOERROR;
1462 /**************************************************************************
1463 * widAddBuffer [internal]
1465 static DWORD widAddBuffer(WORD wDevID, LPWAVEHDR lpWaveHdr, DWORD dwSize)
1470 dprintf_mciwave(stddeb,
1471 "widAddBuffer(%u, %p, %08lX);\n", wDevID, lpWaveHdr, dwSize);
1472 if (WInDev[wDevID].unixdev == 0) {
1473 dprintf_mciwave(stddeb,"Linux 'widAddBuffer' // can't do it !\n");
1474 return MMSYSERR_NOTENABLED;
1476 if (!(lpWaveHdr->dwFlags & WHDR_PREPARED)) {
1477 dprintf_mciwave(stddeb, "Linux 'widAddBuffer' // never been prepared !\n");
1478 return WAVERR_UNPREPARED;
1480 if (lpWaveHdr->dwFlags & WHDR_INQUEUE) {
1481 dprintf_mciwave(stddeb, "Linux 'widAddBuffer' // header already in use !\n");
1482 return WAVERR_STILLPLAYING;
1484 lpWaveHdr->dwFlags |= WHDR_PREPARED;
1485 lpWaveHdr->dwFlags |= WHDR_INQUEUE;
1486 lpWaveHdr->dwFlags &= ~WHDR_DONE;
1487 lpWaveHdr->dwBytesRecorded = 0;
1488 if (WInDev[wDevID].lpQueueHdr == NULL) {
1489 WInDev[wDevID].lpQueueHdr = lpWaveHdr;
1491 lpWIHdr = WInDev[wDevID].lpQueueHdr;
1492 while (lpWIHdr->lpNext != NULL) {
1493 lpWIHdr = lpWIHdr->lpNext;
1496 lpWIHdr->lpNext = lpWaveHdr;
1497 lpWaveHdr->lpNext = NULL;
1500 dprintf_mciwave(stddeb,
1501 "widAddBuffer // buffer added ! (now %u in queue)\n", count);
1502 return MMSYSERR_NOERROR;
1505 /**************************************************************************
1506 * widPrepare [internal]
1508 static DWORD widPrepare(WORD wDevID, LPWAVEHDR lpWaveHdr, DWORD dwSize)
1510 dprintf_mciwave(stddeb,
1511 "widPrepare(%u, %p, %08lX);\n", wDevID, lpWaveHdr, dwSize);
1512 if (WInDev[wDevID].unixdev == 0) {
1513 dprintf_mciwave(stddeb,"Linux 'widPrepare' // can't prepare !\n");
1514 return MMSYSERR_NOTENABLED;
1516 if (lpWaveHdr->dwFlags & WHDR_INQUEUE)
1517 return WAVERR_STILLPLAYING;
1518 lpWaveHdr->dwFlags |= WHDR_PREPARED;
1519 lpWaveHdr->dwFlags &= ~WHDR_INQUEUE;
1520 lpWaveHdr->dwFlags &= ~WHDR_DONE;
1521 lpWaveHdr->dwBytesRecorded = 0;
1522 dprintf_mciwave(stddeb,"Linux 'widPrepare' // header prepared !\n");
1523 return MMSYSERR_NOERROR;
1526 /**************************************************************************
1527 * widUnprepare [internal]
1529 static DWORD widUnprepare(WORD wDevID, LPWAVEHDR lpWaveHdr, DWORD dwSize)
1531 dprintf_mciwave(stddeb,
1532 "widUnprepare(%u, %p, %08lX);\n", wDevID, lpWaveHdr, dwSize);
1533 if (WInDev[wDevID].unixdev == 0) {
1534 dprintf_mciwave(stddeb,"Linux 'widUnprepare' // can't unprepare !\n");
1535 return MMSYSERR_NOTENABLED;
1537 lpWaveHdr->dwFlags &= ~WHDR_PREPARED;
1538 lpWaveHdr->dwFlags &= ~WHDR_INQUEUE;
1539 lpWaveHdr->dwFlags |= WHDR_DONE;
1541 dprintf_mciwave(stddeb, "Linux 'widUnprepare' // all headers unprepared !\n");
1542 return MMSYSERR_NOERROR;
1545 /**************************************************************************
1546 * widStart [internal]
1548 static DWORD widStart(WORD wDevID)
1553 LPWAVEHDR *lpWaveHdr;
1555 dprintf_mciwave(stddeb,"widStart(%u);\n", wDevID);
1556 if (WInDev[wDevID].unixdev == 0) {
1557 dprintf_mciwave(stddeb, "Linux 'widStart' // can't start recording !\n");
1558 return MMSYSERR_NOTENABLED;
1561 lpWaveHdr = &(WInDev[wDevID].lpQueueHdr);
1562 dprintf_mciwave(stddeb,"Linux 'widstart'// lpWaveHdr = %08lx\n",(DWORD)lpWaveHdr);
1563 if (!*lpWaveHdr || !(*lpWaveHdr)->lpData) {
1564 dprintf_mciwave(stddeb,"Linux 'widStart' // never been prepared !\n");
1565 return WAVERR_UNPREPARED;
1568 while(*lpWaveHdr != NULL) {
1569 lpWIHdr = *lpWaveHdr;
1570 dprintf_mciwave(stddeb,
1571 "widStart // recording buf#%u=%p size=%lu \n",
1572 count, lpWIHdr->lpData, lpWIHdr->dwBufferLength);
1574 bytesRead = read (WInDev[wDevID].unixdev,
1576 lpWIHdr->dwBufferLength);
1578 perror("read from audio device");
1579 fprintf(stderr,"bytesread = %d (%ld)\n",bytesRead,lpWIHdr->dwBufferLength);
1580 lpWIHdr->dwBytesRecorded = bytesRead;
1581 WInDev[wDevID].dwTotalRecorded += lpWIHdr->dwBytesRecorded;
1582 lpWIHdr->dwFlags &= ~WHDR_INQUEUE;
1583 lpWIHdr->dwFlags |= WHDR_DONE;
1585 /* FIXME: should pass segmented pointer here, do we need that?*/
1586 if (WAVE_NotifyClient(wDevID, WIM_DATA, (DWORD)lpWaveHdr, lpWIHdr->dwBytesRecorded) != MMSYSERR_NOERROR) {
1587 dprintf_mciwave(stddeb, "Linux 'widStart' // can't notify client !\n");
1588 return MMSYSERR_INVALPARAM;
1590 /* removes the current block from the queue */
1591 *lpWaveHdr = lpWIHdr->lpNext;
1594 dprintf_mciwave(stddeb,"widStart // end of recording !\n");
1596 return MMSYSERR_NOERROR;
1599 /**************************************************************************
1600 * widStop [internal]
1602 static DWORD widStop(WORD wDevID)
1604 dprintf_mciwave(stddeb,"widStop(%u);\n", wDevID);
1605 if (WInDev[wDevID].unixdev == 0) {
1606 dprintf_mciwave(stddeb,"Linux 'widStop' // can't stop !\n");
1607 return MMSYSERR_NOTENABLED;
1609 return MMSYSERR_NOERROR;
1612 /**************************************************************************
1613 * widReset [internal]
1615 static DWORD widReset(WORD wDevID)
1617 dprintf_mciwave(stddeb,"widReset(%u);\n", wDevID);
1618 if (WInDev[wDevID].unixdev == 0) {
1619 dprintf_mciwave(stddeb,"Linux 'widReset' // can't reset !\n");
1620 return MMSYSERR_NOTENABLED;
1622 return MMSYSERR_NOERROR;
1625 /**************************************************************************
1626 * widGetPosition [internal]
1628 static DWORD widGetPosition(WORD wDevID, LPMMTIME16 lpTime, DWORD uSize)
1632 dprintf_mciwave(stddeb,
1633 "widGetPosition(%u, %p, %lu);\n", wDevID, lpTime, uSize);
1634 if (WInDev[wDevID].unixdev == 0) {
1635 dprintf_mciwave(stddeb,"Linux 'widGetPosition' // can't get pos !\n");
1636 return MMSYSERR_NOTENABLED;
1638 if (lpTime == NULL) return MMSYSERR_INVALPARAM;
1639 dprintf_mciwave(stddeb,"widGetPosition // wType=%04X !\n",
1641 dprintf_mciwave(stddeb,"widGetPosition // wBitsPerSample=%u\n",
1642 WInDev[wDevID].Format.wBitsPerSample);
1643 dprintf_mciwave(stddeb,"widGetPosition // nSamplesPerSec=%lu\n",
1644 WInDev[wDevID].Format.wf.nSamplesPerSec);
1645 dprintf_mciwave(stddeb,"widGetPosition // nChannels=%u\n",
1646 WInDev[wDevID].Format.wf.nChannels);
1647 dprintf_mciwave(stddeb,"widGetPosition // nAvgBytesPerSec=%lu\n",
1648 WInDev[wDevID].Format.wf.nAvgBytesPerSec);
1650 switch(lpTime->wType) {
1652 lpTime->u.cb = WInDev[wDevID].dwTotalRecorded;
1653 dprintf_mciwave(stddeb,
1654 "widGetPosition // TIME_BYTES=%lu\n", lpTime->u.cb);
1657 lpTime->u.sample = WInDev[wDevID].dwTotalRecorded * 8 /
1658 WInDev[wDevID].Format.wBitsPerSample;
1659 dprintf_mciwave(stddeb,
1660 "widGetPosition // TIME_SAMPLES=%lu\n",
1664 time = WInDev[wDevID].dwTotalRecorded /
1665 (WInDev[wDevID].Format.wf.nAvgBytesPerSec / 1000);
1666 lpTime->u.smpte.hour = time / 108000;
1667 time -= lpTime->u.smpte.hour * 108000;
1668 lpTime->u.smpte.min = time / 1800;
1669 time -= lpTime->u.smpte.min * 1800;
1670 lpTime->u.smpte.sec = time / 30;
1671 time -= lpTime->u.smpte.sec * 30;
1672 lpTime->u.smpte.frame = time;
1673 lpTime->u.smpte.fps = 30;
1674 dprintf_mciwave(stddeb,"widGetPosition // TIME_SMPTE=%02u:%02u:%02u:%02u\n",
1675 lpTime->u.smpte.hour, lpTime->u.smpte.min,
1676 lpTime->u.smpte.sec, lpTime->u.smpte.frame);
1679 dprintf_mciwave(stddeb,"widGetPosition() format not supported ! use TIME_MS !\n");
1680 lpTime->wType = TIME_MS;
1682 lpTime->u.ms = WInDev[wDevID].dwTotalRecorded /
1683 (WInDev[wDevID].Format.wf.nAvgBytesPerSec / 1000);
1684 dprintf_mciwave(stddeb,
1685 "widGetPosition // TIME_MS=%lu\n", lpTime->u.ms);
1688 return MMSYSERR_NOERROR;
1691 #endif /* linux || __FreeBSD__ */
1693 /**************************************************************************
1694 * widMessage [sample driver]
1696 DWORD widMessage(WORD wDevID, WORD wMsg, DWORD dwUser,
1697 DWORD dwParam1, DWORD dwParam2)
1699 dprintf_mciwave(stddeb,"widMessage(%u, %04X, %08lX, %08lX, %08lX);\n",
1700 wDevID, wMsg, dwUser, dwParam1, dwParam2);
1701 #if defined(linux) || defined(__FreeBSD__)
1704 return widOpen(wDevID, (LPWAVEOPENDESC)dwParam1, dwParam2);
1706 return widClose(wDevID);
1707 case WIDM_ADDBUFFER:
1708 return widAddBuffer(wDevID, (LPWAVEHDR)dwParam1, dwParam2);
1710 return widPrepare(wDevID, (LPWAVEHDR)dwParam1, dwParam2);
1711 case WIDM_UNPREPARE:
1712 return widUnprepare(wDevID, (LPWAVEHDR)dwParam1, dwParam2);
1713 case WIDM_GETDEVCAPS:
1714 return widGetDevCaps(wDevID, (LPWAVEINCAPS16)dwParam1,dwParam2);
1715 case WIDM_GETNUMDEVS:
1718 return widGetPosition(wDevID, (LPMMTIME16)dwParam1, dwParam2);
1720 return widReset(wDevID);
1722 return widStart(wDevID);
1724 return widStop(wDevID);
1726 return widStop(wDevID);
1728 dprintf_mciwave(stddeb,"widMessage // unknown message !\n");
1730 return MMSYSERR_NOTSUPPORTED;
1732 return MMSYSERR_NOTENABLED;
1737 /**************************************************************************
1738 * AUDIO_DriverProc [sample driver]
1740 LONG WAVE_DriverProc(DWORD dwDevID, HDRVR16 hDriv, WORD wMsg,
1741 DWORD dwParam1, DWORD dwParam2)
1743 #if defined(linux) || defined(__FreeBSD__)
1744 dprintf_mciwave(stddeb,"WAVE_DriverProc(%08lX, %04X, %04X, %08lX, %08lX)\n",
1745 dwDevID, hDriv, wMsg, dwParam1, dwParam2);
1759 case DRV_QUERYCONFIGURE:
1762 MessageBox16(0, "Sample MultiMedia Linux Driver !",
1763 "MMLinux Driver", MB_OK);
1766 return DRVCNF_RESTART;
1768 return DRVCNF_RESTART;
1769 case MCI_OPEN_DRIVER:
1771 return WAVE_mciOpen(dwDevID, dwParam1, (LPMCI_WAVE_OPEN_PARMS16)PTR_SEG_TO_LIN(dwParam2));
1773 return WAVE_mciCue(dwDevID, dwParam1, (LPMCI_GENERIC_PARMS)PTR_SEG_TO_LIN(dwParam2));
1774 case MCI_CLOSE_DRIVER:
1776 return WAVE_mciClose(dwDevID, dwParam1, (LPMCI_GENERIC_PARMS)PTR_SEG_TO_LIN(dwParam2));
1778 return WAVE_mciPlay(dwDevID, dwParam1, (LPMCI_PLAY_PARMS)PTR_SEG_TO_LIN(dwParam2));
1780 return WAVE_mciRecord(dwDevID, dwParam1, (LPMCI_RECORD_PARMS)PTR_SEG_TO_LIN(dwParam2));
1782 return WAVE_mciStop(dwDevID, dwParam1, (LPMCI_GENERIC_PARMS)PTR_SEG_TO_LIN(dwParam2));
1784 return WAVE_mciSet(dwDevID, dwParam1, (LPMCI_SET_PARMS)PTR_SEG_TO_LIN(dwParam2));
1786 return WAVE_mciPause(dwDevID, dwParam1, (LPMCI_GENERIC_PARMS)PTR_SEG_TO_LIN(dwParam2));
1788 return WAVE_mciResume(dwDevID, dwParam1, (LPMCI_GENERIC_PARMS)PTR_SEG_TO_LIN(dwParam2));
1790 return WAVE_mciStatus(dwDevID, dwParam1, (LPMCI_STATUS_PARMS)PTR_SEG_TO_LIN(dwParam2));
1791 case MCI_GETDEVCAPS:
1792 return WAVE_mciGetDevCaps(dwDevID, dwParam1, (LPMCI_GETDEVCAPS_PARMS)PTR_SEG_TO_LIN(dwParam2));
1794 return WAVE_mciInfo(dwDevID, dwParam1, (LPMCI_INFO_PARMS16)PTR_SEG_TO_LIN(dwParam2));
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;
1811 return MMSYSERR_NOTSUPPORTED;
1813 return MMSYSERR_NOTSUPPORTED;
1815 return MMSYSERR_NOTSUPPORTED;
1817 return MMSYSERR_NOTSUPPORTED;
1819 return MMSYSERR_NOTSUPPORTED;
1821 return MMSYSERR_NOTSUPPORTED;
1823 return MMSYSERR_NOTSUPPORTED;
1825 return MMSYSERR_NOTSUPPORTED;
1827 return MMSYSERR_NOTSUPPORTED;
1829 return MMSYSERR_NOTSUPPORTED;
1832 return DefDriverProc(dwDevID, hDriv, wMsg, dwParam1, dwParam2);
1835 return MMSYSERR_NOTENABLED;