Release 970525
[wine/multimedia.git] / multimedia / audio.c
blob31af3189617be851f54aa9e89ff03cd9c67eccce
1 /*
2 * Sample Wine Driver for Linux
4 * Copyright 1994 Martin Ayotte
5 */
7 #define EMULATE_SB16
9 #include <stdio.h>
10 #include <stdlib.h>
11 #include <unistd.h>
12 #include <fcntl.h>
13 #include <sys/ioctl.h>
14 #include "windows.h"
15 #include "user.h"
16 #include "driver.h"
17 #include "mmsystem.h"
18 #include "ldt.h"
20 #ifdef linux
21 #include <linux/soundcard.h>
22 #elif __FreeBSD__
23 #include <machine/soundcard.h>
24 #endif
26 #include "stddebug.h"
27 #include "debug.h"
29 #if defined(linux) || defined(__FreeBSD__)
30 #define SOUND_DEV "/dev/dsp"
31 #define MIXER_DEV "/dev/mixer"
33 #ifdef SOUND_VERSION
34 #define IOCTL(a,b,c) ((-1==ioctl(a,b,&c))&&(perror("ioctl:"#b":"#c),0))
35 #else
36 #define IOCTL(a,b,c) (c = ioctl(a,b,c) )
37 #endif
39 #define MAX_WAVOUTDRV (1)
40 #define MAX_WAVINDRV (1)
41 #define MAX_MCIWAVDRV (1)
43 typedef struct {
44 int unixdev;
45 int state;
46 DWORD bufsize;
47 WAVEOPENDESC waveDesc;
48 WORD wFlags;
49 PCMWAVEFORMAT Format;
50 LPWAVEHDR lpQueueHdr;
51 DWORD dwTotalPlayed;
52 } LINUX_WAVEOUT;
54 typedef struct {
55 int unixdev;
56 int state;
57 DWORD bufsize; /* Linux '/dev/dsp' give us that size */
58 WAVEOPENDESC waveDesc;
59 WORD wFlags;
60 PCMWAVEFORMAT Format;
61 LPWAVEHDR lpQueueHdr;
62 DWORD dwTotalRecorded;
63 } LINUX_WAVEIN;
65 typedef struct {
66 int nUseCount; /* Incremented for each shared open */
67 BOOL16 fShareable; /* TRUE if first open was shareable */
68 WORD wNotifyDeviceID; /* MCI device ID with a pending notification */
69 HANDLE16 hCallback; /* Callback handle for pending notification */
70 HMMIO16 hFile; /* mmio file handle open as Element */
71 MCI_WAVE_OPEN_PARMS openParms;
72 PCMWAVEFORMAT WaveFormat;
73 WAVEHDR WaveHdr;
74 BOOL16 fInput; /* FALSE = Output, TRUE = Input */
75 } LINUX_MCIWAVE;
77 static LINUX_WAVEOUT WOutDev[MAX_WAVOUTDRV];
78 static LINUX_WAVEIN WInDev[MAX_WAVOUTDRV];
79 static LINUX_MCIWAVE MCIWavDev[MAX_MCIWAVDRV];
82 /**************************************************************************
83 * WAVE_NotifyClient [internal]
85 static DWORD WAVE_NotifyClient(UINT16 wDevID, WORD wMsg,
86 DWORD dwParam1, DWORD dwParam2)
88 dprintf_mciwave(stddeb,"WAVE_NotifyClient // wDevID = %04X wMsg = %d dwParm1 = %04lX dwParam2 = %04lX\n",wDevID, wMsg, dwParam1, dwParam2);
90 if (wDevID > MAX_WAVOUTDRV) return MCIERR_INTERNAL;
92 if (WInDev[wDevID].wFlags != DCB_NULL && !DriverCallback(
93 WInDev[wDevID].waveDesc.dwCallBack, WInDev[wDevID].wFlags,
94 WInDev[wDevID].waveDesc.hWave, wMsg,
95 WInDev[wDevID].waveDesc.dwInstance, dwParam1, dwParam2)) {
96 dprintf_mciwave(stddeb,"WAVE_NotifyClient // can't notify client !\n");
97 return MMSYSERR_NOERROR;
99 return 0;
103 /**************************************************************************
104 * WAVE_mciOpen [internal]*/
105 static DWORD WAVE_mciOpen(UINT16 wDevID, DWORD dwFlags, LPMCI_WAVE_OPEN_PARMS lpParms)
107 HLOCAL16 hFormat;
108 LPWAVEFORMAT lpFormat;
109 LPPCMWAVEFORMAT lpWaveFormat;
110 HLOCAL16 hDesc;
111 LPWAVEOPENDESC lpDesc;
112 LPSTR lpstrElementName;
113 DWORD dwRet;
114 char str[128];
116 dprintf_mciwave(stddeb,"WAVE_mciOpen(%04X, %08lX, %p)\n",
117 wDevID, dwFlags, lpParms);
118 if (lpParms == NULL) return MCIERR_INTERNAL;
120 if (MCIWavDev[wDevID].nUseCount > 0) {
121 /* The driver already open on this channel */
122 /* If the driver was opened shareable before and this open specifies */
123 /* shareable then increment the use count */
124 if (MCIWavDev[wDevID].fShareable && (dwFlags & MCI_OPEN_SHAREABLE))
125 ++MCIWavDev[wDevID].nUseCount;
126 else
127 return MCIERR_MUST_USE_SHAREABLE;
129 else {
130 MCIWavDev[wDevID].nUseCount = 1;
131 MCIWavDev[wDevID].fShareable = dwFlags & MCI_OPEN_SHAREABLE;
134 MCIWavDev[wDevID].fInput = FALSE;
136 dprintf_mciwave(stddeb,"WAVE_mciOpen // wDevID=%04X\n", wDevID);
137 dprintf_mciwave(stddeb,"WAVE_mciOpen // before OPEN_ELEMENT\n");
138 if (dwFlags & MCI_OPEN_ELEMENT) {
139 lpstrElementName = (LPSTR)PTR_SEG_TO_LIN(lpParms->lpstrElementName);
140 dprintf_mciwave(stddeb,"WAVE_mciOpen // MCI_OPEN_ELEMENT '%s' !\n",
141 lpstrElementName);
142 if (strlen(lpstrElementName) > 0) {
143 strcpy(str, lpstrElementName);
144 CharUpper32A(str);
145 MCIWavDev[wDevID].hFile = mmioOpen(str, NULL,
146 MMIO_ALLOCBUF | MMIO_READWRITE | MMIO_EXCLUSIVE);
147 if (MCIWavDev[wDevID].hFile == 0) {
148 dprintf_mciwave(stddeb,"WAVE_mciOpen // can't find file='%s' !\n", str);
149 return MCIERR_FILE_NOT_FOUND;
152 else
153 MCIWavDev[wDevID].hFile = 0;
155 dprintf_mciwave(stddeb,"WAVE_mciOpen // hFile=%u\n", MCIWavDev[wDevID].hFile);
156 memcpy(&MCIWavDev[wDevID].openParms, lpParms, sizeof(MCI_WAVE_OPEN_PARMS));
157 MCIWavDev[wDevID].wNotifyDeviceID = lpParms->wDeviceID;
158 lpWaveFormat = &MCIWavDev[wDevID].WaveFormat;
159 hDesc = USER_HEAP_ALLOC(sizeof(WAVEOPENDESC));
160 lpDesc = (LPWAVEOPENDESC) USER_HEAP_LIN_ADDR(hDesc);
161 lpDesc->hWave = 0;
163 lpWaveFormat->wf.wFormatTag = WAVE_FORMAT_PCM;
164 lpWaveFormat->wBitsPerSample = 8;
165 lpWaveFormat->wf.nChannels = 1;
166 lpWaveFormat->wf.nSamplesPerSec = 11025;
167 lpWaveFormat->wf.nAvgBytesPerSec = 11025;
168 lpWaveFormat->wf.nBlockAlign = 1;
170 if (MCIWavDev[wDevID].hFile != 0) {
171 MMCKINFO mmckInfo;
172 MMCKINFO ckMainRIFF;
173 if (mmioDescend(MCIWavDev[wDevID].hFile, &ckMainRIFF, NULL, 0) != 0) {
174 return MCIERR_INTERNAL;
176 dprintf_mciwave(stddeb,
177 "WAVE_mciOpen // ParentChunk ckid=%.4s fccType=%.4s cksize=%08lX \n",
178 (LPSTR)&ckMainRIFF.ckid, (LPSTR)&ckMainRIFF.fccType,
179 ckMainRIFF.cksize);
180 if ((ckMainRIFF.ckid != FOURCC_RIFF) ||
181 (ckMainRIFF.fccType != mmioFOURCC('W', 'A', 'V', 'E'))) {
182 return MCIERR_INTERNAL;
184 mmckInfo.ckid = mmioFOURCC('f', 'm', 't', ' ');
185 if (mmioDescend(MCIWavDev[wDevID].hFile, &mmckInfo, &ckMainRIFF, MMIO_FINDCHUNK) != 0) {
186 return MCIERR_INTERNAL;
188 dprintf_mciwave(stddeb,
189 "WAVE_mciOpen // Chunk Found ckid=%.4s fccType=%.4s cksize=%08lX \n",
190 (LPSTR)&mmckInfo.ckid, (LPSTR)&mmckInfo.fccType,
191 mmckInfo.cksize);
192 if (mmioRead(MCIWavDev[wDevID].hFile, (HPSTR) lpWaveFormat,
193 (long) sizeof(PCMWAVEFORMAT)) != (long) sizeof(PCMWAVEFORMAT)) {
194 return MCIERR_INTERNAL;
196 mmckInfo.ckid = mmioFOURCC('d', 'a', 't', 'a');
197 if (mmioDescend(MCIWavDev[wDevID].hFile, &mmckInfo, &ckMainRIFF, MMIO_FINDCHUNK) != 0) {
198 return MCIERR_INTERNAL;
200 dprintf_mciwave(stddeb,
201 "WAVE_mciOpen // Chunk Found ckid=%.4s fccType=%.4s cksize=%08lX \n",
202 (LPSTR)&mmckInfo.ckid, (LPSTR)&mmckInfo.fccType,
203 mmckInfo.cksize);
204 dprintf_mciwave(stddeb,
205 "WAVE_mciOpen // nChannels=%d nSamplesPerSec=%ld\n",
206 lpWaveFormat->wf.nChannels, lpWaveFormat->wf.nSamplesPerSec);
207 lpWaveFormat->wBitsPerSample = 0;
210 lpWaveFormat->wf.nAvgBytesPerSec =
211 lpWaveFormat->wf.nSamplesPerSec * lpWaveFormat->wf.nBlockAlign;
212 hFormat = USER_HEAP_ALLOC(sizeof(PCMWAVEFORMAT));
213 lpFormat = (LPWAVEFORMAT) USER_HEAP_LIN_ADDR(hFormat);
214 memcpy(lpFormat, lpWaveFormat, sizeof(PCMWAVEFORMAT));
215 lpDesc->lpFormat = (LPWAVEFORMAT)USER_HEAP_SEG_ADDR(hFormat);
216 lpDesc = (LPWAVEOPENDESC) USER_HEAP_SEG_ADDR(hDesc);
219 By default the device will be opened for output, the MCI_CUE function is there to
220 change from output to input and back
223 dwRet = wodMessage(wDevID, WODM_OPEN, 0, (DWORD)lpDesc, CALLBACK_NULL);
225 USER_HEAP_FREE(hFormat);
226 USER_HEAP_FREE(hDesc);
227 return 0;
230 /**************************************************************************
231 * WAVE_mciCue [internal]
234 static DWORD WAVE_mciCue(UINT16 wDevID, DWORD dwParam, LPMCI_GENERIC_PARMS lpParms)
237 FIXME
239 This routine is far from complete. At the moment only a check is done on the
240 MCI_WAVE_INPUT flag. No explicit check on MCI_WAVE_OUTPUT is done since that
241 is the default.
243 The flags MCI_NOTIFY (and the callback parameter in lpParms) and MCI_WAIT are
244 ignored
247 DWORD dwRet;
248 HLOCAL16 hDesc;
249 LPWAVEOPENDESC lpDesc;
251 dprintf_mciwave(stddeb,"WAVE_mciCue(%u, %08lX, %p);\n", wDevID, dwParam, lpParms);
253 /* always close elements ? */
255 if (MCIWavDev[wDevID].hFile != 0) {
256 mmioClose(MCIWavDev[wDevID].hFile, 0);
257 MCIWavDev[wDevID].hFile = 0;
260 hDesc = USER_HEAP_ALLOC(sizeof(WAVEOPENDESC));
261 lpDesc = (LPWAVEOPENDESC) USER_HEAP_LIN_ADDR(hDesc);
263 dwRet = MMSYSERR_NOERROR; /* assume success */
265 if ((dwParam & MCI_WAVE_INPUT) && !MCIWavDev[wDevID].fInput) {
267 /* FIXME this is just a hack WOutDev should be hidden here */
268 memcpy(lpDesc,&WOutDev[wDevID].waveDesc,sizeof(WAVEOPENDESC));
270 dwRet = wodMessage(wDevID, WODM_CLOSE, 0, 0L, 0L);
271 if (dwRet != MMSYSERR_NOERROR) return MCIERR_INTERNAL;
272 dwRet = widMessage(wDevID, WIDM_OPEN, 0, (DWORD)lpDesc, CALLBACK_NULL);
274 else if (MCIWavDev[wDevID].fInput) {
275 /* FIXME this is just a hack WInDev should be hidden here */
276 memcpy(lpDesc,&WInDev[wDevID].waveDesc,sizeof(WAVEOPENDESC));
278 dwRet = widMessage(wDevID, WIDM_CLOSE, 0, 0L, 0L);
279 if (dwRet != MMSYSERR_NOERROR) return MCIERR_INTERNAL;
280 dwRet = wodMessage(wDevID, WODM_OPEN, 0, (DWORD)lpDesc, CALLBACK_NULL);
283 USER_HEAP_FREE(hDesc);
285 return dwRet;
288 /**************************************************************************
289 * WAVE_mciClose [internal]
291 static DWORD WAVE_mciClose(UINT16 wDevID, DWORD dwParam, LPMCI_GENERIC_PARMS lpParms)
293 DWORD dwRet;
295 dprintf_mciwave(stddeb,
296 "WAVE_mciClose(%u, %08lX, %p);\n", wDevID, dwParam, lpParms);
297 MCIWavDev[wDevID].nUseCount--;
298 if (MCIWavDev[wDevID].nUseCount == 0) {
299 if (MCIWavDev[wDevID].hFile != 0) {
300 mmioClose(MCIWavDev[wDevID].hFile, 0);
301 MCIWavDev[wDevID].hFile = 0;
303 if (MCIWavDev[wDevID].fInput)
304 dwRet = widMessage(wDevID, WIDM_CLOSE, 0, 0L, 0L);
305 else
306 dwRet = wodMessage(wDevID, WODM_CLOSE, 0, 0L, 0L);
308 if (dwRet != MMSYSERR_NOERROR) return MCIERR_INTERNAL;
310 return 0;
314 /**************************************************************************
315 * WAVE_mciPlay [internal]
317 static DWORD WAVE_mciPlay(UINT16 wDevID, DWORD dwFlags, LPMCI_PLAY_PARMS lpParms)
319 int start, end;
320 LONG bufsize, count;
321 HGLOBAL16 hData;
322 HLOCAL16 hWaveHdr;
323 LPWAVEHDR lpWaveHdr;
324 LPWAVEHDR lp16WaveHdr;
325 DWORD dwRet;
327 dprintf_mciwave(stddeb,
328 "WAVE_mciPlay(%u, %08lX, %p);\n", wDevID, dwFlags, lpParms);
330 if (MCIWavDev[wDevID].fInput) {
331 dprintf_mciwave(stddeb,"WAVE_mciPlay // cannot play on input device\n");
332 return MCIERR_NONAPPLICABLE_FUNCTION;
335 if (MCIWavDev[wDevID].hFile == 0) {
336 dprintf_mciwave(stddeb,"WAVE_mciPlay // can't find file='%08lx' !\n",
337 MCIWavDev[wDevID].openParms.lpstrElementName);
338 return MCIERR_FILE_NOT_FOUND;
340 start = 1; end = 99999;
341 if (dwFlags & MCI_FROM) {
342 start = lpParms->dwFrom;
343 dprintf_mciwave(stddeb,
344 "WAVE_mciPlay // MCI_FROM=%d \n", start);
346 if (dwFlags & MCI_TO) {
347 end = lpParms->dwTo;
348 dprintf_mciwave(stddeb,"WAVE_mciPlay // MCI_TO=%d \n", end);
350 #if 0
351 if (dwFlags & MCI_NOTIFY) {
352 dprintf_mciwave(stddeb,
353 "WAVE_mciPlay // MCI_NOTIFY %08lX !\n", lpParms->dwCallback);
354 switch(fork()) {
355 case -1:
356 dprintf_mciwave(stddeb,
357 "WAVE_mciPlay // Can't 'fork' process !\n");
358 break;
359 case 0:
360 break;
361 default:
362 dprintf_mciwave(stddeb,"WAVE_mciPlay // process started ! return to caller...\n");
363 return 0;
366 #endif
367 bufsize = 64000;
368 lpWaveHdr = &MCIWavDev[wDevID].WaveHdr;
369 hData = GlobalAlloc16(GMEM_MOVEABLE, bufsize);
370 lpWaveHdr->lpData = (LPSTR) WIN16_GlobalLock16(hData);
371 lpWaveHdr->dwUser = 0L;
372 lpWaveHdr->dwFlags = 0L;
373 lpWaveHdr->dwLoops = 0L;
374 hWaveHdr = USER_HEAP_ALLOC(sizeof(WAVEHDR));
375 lp16WaveHdr = (LPWAVEHDR) USER_HEAP_SEG_ADDR(hWaveHdr);
376 memcpy(PTR_SEG_TO_LIN(lp16WaveHdr), lpWaveHdr, sizeof(WAVEHDR));
377 lpWaveHdr = PTR_SEG_TO_LIN(lp16WaveHdr);
378 dwRet = wodMessage(wDevID, WODM_PREPARE, 0, (DWORD)lp16WaveHdr, sizeof(WAVEHDR));
379 while(TRUE) {
380 count = mmioRead(MCIWavDev[wDevID].hFile,
381 PTR_SEG_TO_LIN(lpWaveHdr->lpData), bufsize);
382 dprintf_mciwave(stddeb,"WAVE_mciPlay // mmioRead bufsize=%ld count=%ld\n", bufsize, count);
383 if (count < 1) break;
384 lpWaveHdr->dwBufferLength = count;
385 /* lpWaveHdr->dwBytesRecorded = count; */
386 dprintf_mciwave(stddeb,"WAVE_mciPlay // before WODM_WRITE lpWaveHdr=%p dwBufferLength=%lu dwBytesRecorded=%lu\n",
387 lpWaveHdr, lpWaveHdr->dwBufferLength, lpWaveHdr->dwBytesRecorded);
388 dwRet = wodMessage(wDevID, WODM_WRITE, 0, (DWORD)lp16WaveHdr, sizeof(WAVEHDR));
390 dwRet = wodMessage(wDevID, WODM_UNPREPARE, 0, (DWORD)lp16WaveHdr, sizeof(WAVEHDR));
391 if (lpWaveHdr->lpData != NULL) {
392 GlobalUnlock16(hData);
393 GlobalFree16(hData);
394 lpWaveHdr->lpData = NULL;
396 USER_HEAP_FREE(hWaveHdr);
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);
402 return 0;
406 /**************************************************************************
407 * WAVE_mciRecord [internal]
409 static DWORD WAVE_mciRecord(UINT16 wDevID, DWORD dwFlags, LPMCI_RECORD_PARMS lpParms)
411 int start, end;
412 LONG bufsize;
413 HGLOBAL16 hData;
414 HLOCAL16 hWaveHdr;
415 LPWAVEHDR lpWaveHdr;
416 LPWAVEHDR lp16WaveHdr;
417 DWORD dwRet;
419 dprintf_mciwave(stddeb,
420 "WAVE_mciRecord(%u, %08lX, %p);\n", wDevID, dwFlags, lpParms);
422 if (!MCIWavDev[wDevID].fInput) {
423 dprintf_mciwave(stddeb,"WAVE_mciPlay // cannot record on output device\n");
424 return MCIERR_NONAPPLICABLE_FUNCTION;
427 if (MCIWavDev[wDevID].hFile == 0) {
428 dprintf_mciwave(stddeb,"WAVE_mciRecord // can't find file='%08lx' !\n",
429 MCIWavDev[wDevID].openParms.lpstrElementName);
430 return MCIERR_FILE_NOT_FOUND;
432 start = 1; end = 99999;
433 if (dwFlags & MCI_FROM) {
434 start = lpParms->dwFrom;
435 dprintf_mciwave(stddeb,
436 "WAVE_mciRecord // MCI_FROM=%d \n", start);
438 if (dwFlags & MCI_TO) {
439 end = lpParms->dwTo;
440 dprintf_mciwave(stddeb,"WAVE_mciRecord // MCI_TO=%d \n", end);
442 bufsize = 64000;
443 lpWaveHdr = &MCIWavDev[wDevID].WaveHdr;
444 hData = GlobalAlloc16(GMEM_MOVEABLE, bufsize);
445 lpWaveHdr->lpData = (LPSTR) WIN16_GlobalLock16(hData);
446 lpWaveHdr->dwBufferLength = bufsize;
447 lpWaveHdr->dwUser = 0L;
448 lpWaveHdr->dwFlags = 0L;
449 lpWaveHdr->dwLoops = 0L;
450 hWaveHdr = USER_HEAP_ALLOC(sizeof(WAVEHDR));
451 lp16WaveHdr = (LPWAVEHDR) USER_HEAP_SEG_ADDR(hWaveHdr);
452 memcpy(PTR_SEG_TO_LIN(lp16WaveHdr), lpWaveHdr, sizeof(WAVEHDR));
453 lpWaveHdr = PTR_SEG_TO_LIN(lp16WaveHdr);
454 dwRet = widMessage(wDevID, WIDM_PREPARE, 0, (DWORD)lp16WaveHdr, sizeof(WAVEHDR));
455 dprintf_mciwave(stddeb,"WAVE_mciRecord // after WIDM_PREPARE \n");
456 while(TRUE) {
457 lpWaveHdr->dwBytesRecorded = 0;
458 dwRet = widMessage(wDevID, WIDM_START, 0, 0L, 0L);
459 dprintf_mciwave(stddeb,
460 "WAVE_mciRecord // after WIDM_START lpWaveHdr=%p dwBytesRecorded=%lu\n",
461 lpWaveHdr, lpWaveHdr->dwBytesRecorded);
462 if (lpWaveHdr->dwBytesRecorded == 0) break;
464 dprintf_mciwave(stddeb,"WAVE_mciRecord // before WIDM_UNPREPARE \n");
465 dwRet = widMessage(wDevID, WIDM_UNPREPARE, 0, (DWORD)lp16WaveHdr, sizeof(WAVEHDR));
466 dprintf_mciwave(stddeb,"WAVE_mciRecord // after WIDM_UNPREPARE \n");
467 if (lpWaveHdr->lpData != NULL) {
468 GlobalUnlock16(hData);
469 GlobalFree16(hData);
470 lpWaveHdr->lpData = NULL;
472 USER_HEAP_FREE(hWaveHdr);
473 if (dwFlags & MCI_NOTIFY) {
474 dprintf_mciwave(stddeb,"WAVE_mciRecord // MCI_NOTIFY_SUCCESSFUL %08lX !\n", lpParms->dwCallback);
475 mciDriverNotify((HWND16)LOWORD(lpParms->dwCallback),
476 MCIWavDev[wDevID].wNotifyDeviceID, MCI_NOTIFY_SUCCESSFUL);
478 return 0;
482 /**************************************************************************
483 * WAVE_mciStop [internal]
485 static DWORD WAVE_mciStop(UINT16 wDevID, DWORD dwFlags, LPMCI_GENERIC_PARMS lpParms)
487 dprintf_mciwave(stddeb,
488 "WAVE_mciStop(%u, %08lX, %p);\n", wDevID, dwFlags, lpParms);
489 if (lpParms == NULL) return MCIERR_INTERNAL;
490 return 0;
494 /**************************************************************************
495 * WAVE_mciPause [internal]
497 static DWORD WAVE_mciPause(UINT16 wDevID, DWORD dwFlags, LPMCI_GENERIC_PARMS lpParms)
499 dprintf_mciwave(stddeb,
500 "WAVE_mciPause(%u, %08lX, %p);\n", wDevID, dwFlags, lpParms);
501 if (lpParms == NULL) return MCIERR_INTERNAL;
502 return 0;
506 /**************************************************************************
507 * WAVE_mciResume [internal]
509 static DWORD WAVE_mciResume(UINT16 wDevID, DWORD dwFlags, LPMCI_GENERIC_PARMS lpParms)
511 dprintf_mciwave(stddeb,
512 "WAVE_mciResume(%u, %08lX, %p);\n", wDevID, dwFlags, lpParms);
513 if (lpParms == NULL) return MCIERR_INTERNAL;
514 return 0;
518 /**************************************************************************
519 * WAVE_mciSet [internal]
521 static DWORD WAVE_mciSet(UINT16 wDevID, DWORD dwFlags, LPMCI_SET_PARMS lpParms)
523 dprintf_mciwave(stddeb,
524 "WAVE_mciSet(%u, %08lX, %p);\n", wDevID, dwFlags, lpParms);
525 if (lpParms == NULL) return MCIERR_INTERNAL;
526 dprintf_mciwave(stddeb,
527 "WAVE_mciSet // dwTimeFormat=%08lX\n", lpParms->dwTimeFormat);
528 dprintf_mciwave(stddeb,
529 "WAVE_mciSet // dwAudio=%08lX\n", lpParms->dwAudio);
530 if (dwFlags & MCI_SET_TIME_FORMAT) {
531 switch (lpParms->dwTimeFormat) {
532 case MCI_FORMAT_MILLISECONDS:
533 dprintf_mciwave(stddeb, "WAVE_mciSet // MCI_FORMAT_MILLISECONDS !\n");
534 break;
535 case MCI_FORMAT_BYTES:
536 dprintf_mciwave(stddeb, "WAVE_mciSet // MCI_FORMAT_BYTES !\n");
537 break;
538 case MCI_FORMAT_SAMPLES:
539 dprintf_mciwave(stddeb, "WAVE_mciSet // MCI_FORMAT_SAMPLES !\n");
540 break;
541 default:
542 dprintf_mciwave(stddeb, "WAVE_mciSet // bad time format !\n");
543 return MCIERR_BAD_TIME_FORMAT;
546 if (dwFlags & MCI_SET_VIDEO) return MCIERR_UNSUPPORTED_FUNCTION;
547 if (dwFlags & MCI_SET_DOOR_OPEN) return MCIERR_UNSUPPORTED_FUNCTION;
548 if (dwFlags & MCI_SET_DOOR_CLOSED) return MCIERR_UNSUPPORTED_FUNCTION;
549 if (dwFlags & MCI_SET_AUDIO)
550 dprintf_mciwave(stddeb,"WAVE_mciSet // MCI_SET_AUDIO !\n");
551 if (dwFlags && MCI_SET_ON) {
552 dprintf_mciwave(stddeb,"WAVE_mciSet // MCI_SET_ON !\n");
553 if (dwFlags && MCI_SET_AUDIO_LEFT)
554 dprintf_mciwave(stddeb,"WAVE_mciSet // MCI_SET_AUDIO_LEFT !\n");
555 if (dwFlags && MCI_SET_AUDIO_RIGHT)
556 dprintf_mciwave(stddeb,"WAVE_mciSet // MCI_SET_AUDIO_RIGHT !\n");
558 if (dwFlags & MCI_SET_OFF)
559 dprintf_mciwave(stddeb,"WAVE_mciSet // MCI_SET_OFF !\n");
560 if (dwFlags & MCI_WAVE_INPUT)
561 dprintf_mciwave(stddeb,"WAVE_mciSet // MCI_WAVE_INPUT !\n");
562 if (dwFlags & MCI_WAVE_OUTPUT)
563 dprintf_mciwave(stddeb,"WAVE_mciSet // MCI_WAVE_OUTPUT !\n");
564 if (dwFlags & MCI_WAVE_SET_ANYINPUT)
565 dprintf_mciwave(stddeb,"WAVE_mciSet // MCI_WAVE_SET_ANYINPUT !\n");
566 if (dwFlags & MCI_WAVE_SET_ANYOUTPUT)
567 dprintf_mciwave(stddeb,"WAVE_mciSet // MCI_WAVE_SET_ANYOUTPUT !\n");
568 if (dwFlags & MCI_WAVE_SET_AVGBYTESPERSEC)
569 dprintf_mciwave(stddeb,
570 "WAVE_mciSet // MCI_WAVE_SET_AVGBYTESPERSEC !\n");
571 if (dwFlags & MCI_WAVE_SET_BITSPERSAMPLE)
572 dprintf_mciwave(stddeb,
573 "WAVE_mciSet // MCI_WAVE_SET_BITSPERSAMPLE !\n");
574 if (dwFlags & MCI_WAVE_SET_BLOCKALIGN)
575 dprintf_mciwave(stddeb,"WAVE_mciSet // MCI_WAVE_SET_BLOCKALIGN !\n");
576 if (dwFlags & MCI_WAVE_SET_CHANNELS)
577 dprintf_mciwave(stddeb,"WAVE_mciSet // MCI_WAVE_SET_CHANNELS !\n");
578 if (dwFlags & MCI_WAVE_SET_FORMATTAG)
579 dprintf_mciwave(stddeb,"WAVE_mciSet // MCI_WAVE_SET_FORMATTAG !\n");
580 if (dwFlags & MCI_WAVE_SET_SAMPLESPERSEC)
581 dprintf_mciwave(stddeb,
582 "WAVE_mciSet // MCI_WAVE_SET_SAMPLESPERSEC !\n");
583 return 0;
587 /**************************************************************************
588 * WAVE_mciStatus [internal]
590 static DWORD WAVE_mciStatus(UINT16 wDevID, DWORD dwFlags, LPMCI_STATUS_PARMS lpParms)
592 dprintf_mciwave(stddeb,
593 "WAVE_mciStatus(%u, %08lX, %p);\n", wDevID, dwFlags, lpParms);
594 if (lpParms == NULL) return MCIERR_INTERNAL;
595 if (dwFlags & MCI_STATUS_ITEM) {
596 switch(lpParms->dwItem) {
597 case MCI_STATUS_CURRENT_TRACK:
598 lpParms->dwReturn = 1;
599 break;
600 case MCI_STATUS_LENGTH:
601 lpParms->dwReturn = 5555;
602 if (dwFlags & MCI_TRACK) {
603 lpParms->dwTrack = 1;
604 lpParms->dwReturn = 2222;
606 break;
607 case MCI_STATUS_MODE:
608 lpParms->dwReturn = MCI_MODE_STOP;
609 break;
610 case MCI_STATUS_MEDIA_PRESENT:
611 dprintf_mciwave(stddeb,"WAVE_mciStatus // MCI_STATUS_MEDIA_PRESENT !\n");
612 lpParms->dwReturn = TRUE;
613 break;
614 case MCI_STATUS_NUMBER_OF_TRACKS:
615 lpParms->dwReturn = 1;
616 break;
617 case MCI_STATUS_POSITION:
618 lpParms->dwReturn = 3333;
619 if (dwFlags & MCI_STATUS_START) {
620 lpParms->dwItem = 1;
622 if (dwFlags & MCI_TRACK) {
623 lpParms->dwTrack = 1;
624 lpParms->dwReturn = 777;
626 break;
627 case MCI_STATUS_READY:
628 dprintf_mciwave(stddeb,"WAVE_mciStatus // MCI_STATUS_READY !\n");
629 lpParms->dwReturn = TRUE;
630 break;
631 case MCI_STATUS_TIME_FORMAT:
632 dprintf_mciwave(stddeb,"WAVE_mciStatus // MCI_STATUS_TIME_FORMAT !\n");
633 lpParms->dwReturn = MCI_FORMAT_MILLISECONDS;
634 break;
635 case MCI_WAVE_INPUT:
636 dprintf_mciwave(stddeb,"WAVE_mciStatus // MCI_WAVE_INPUT !\n");
637 lpParms->dwReturn = 0;
638 break;
639 case MCI_WAVE_OUTPUT:
640 dprintf_mciwave(stddeb,"WAVE_mciStatus // MCI_WAVE_OUTPUT !\n");
641 lpParms->dwReturn = 0;
642 break;
643 case MCI_WAVE_STATUS_AVGBYTESPERSEC:
644 dprintf_mciwave(stddeb,"WAVE_mciStatus // MCI_WAVE_STATUS_AVGBYTESPERSEC !\n");
645 lpParms->dwReturn = 22050;
646 break;
647 case MCI_WAVE_STATUS_BITSPERSAMPLE:
648 dprintf_mciwave(stddeb,"WAVE_mciStatus // MCI_WAVE_STATUS_BITSPERSAMPLE !\n");
649 lpParms->dwReturn = 8;
650 break;
651 case MCI_WAVE_STATUS_BLOCKALIGN:
652 dprintf_mciwave(stddeb,"WAVE_mciStatus // MCI_WAVE_STATUS_BLOCKALIGN !\n");
653 lpParms->dwReturn = 1;
654 break;
655 case MCI_WAVE_STATUS_CHANNELS:
656 dprintf_mciwave(stddeb,"WAVE_mciStatus // MCI_WAVE_STATUS_CHANNELS !\n");
657 lpParms->dwReturn = 1;
658 break;
659 case MCI_WAVE_STATUS_FORMATTAG:
660 dprintf_mciwave(stddeb,"WAVE_mciStatus // MCI_WAVE_FORMATTAG !\n");
661 lpParms->dwReturn = WAVE_FORMAT_PCM;
662 break;
663 case MCI_WAVE_STATUS_LEVEL:
664 dprintf_mciwave(stddeb,"WAVE_mciStatus // MCI_WAVE_STATUS_LEVEL !\n");
665 lpParms->dwReturn = 0xAAAA5555;
666 break;
667 case MCI_WAVE_STATUS_SAMPLESPERSEC:
668 dprintf_mciwave(stddeb,"WAVE_mciStatus // MCI_WAVE_STATUS_SAMPLESPERSEC !\n");
669 lpParms->dwReturn = 22050;
670 break;
671 default:
672 dprintf_mciwave(stddeb,"WAVE_mciStatus // unknown command %08lX !\n", lpParms->dwItem);
673 return MCIERR_UNRECOGNIZED_COMMAND;
676 if (dwFlags & MCI_NOTIFY) {
677 dprintf_mciwave(stddeb,"WAVE_mciStatus // MCI_NOTIFY_SUCCESSFUL %08lX !\n", lpParms->dwCallback);
678 mciDriverNotify((HWND16)LOWORD(lpParms->dwCallback),
679 MCIWavDev[wDevID].wNotifyDeviceID, MCI_NOTIFY_SUCCESSFUL);
681 return 0;
684 /**************************************************************************
685 * WAVE_mciGetDevCaps [internal]
687 static DWORD WAVE_mciGetDevCaps(UINT16 wDevID, DWORD dwFlags,
688 LPMCI_GETDEVCAPS_PARMS lpParms)
690 dprintf_mciwave(stddeb,
691 "WAVE_mciGetDevCaps(%u, %08lX, %p);\n", wDevID, dwFlags, lpParms);
692 if (lpParms == NULL) return MCIERR_INTERNAL;
693 if (dwFlags & MCI_GETDEVCAPS_ITEM) {
694 switch(lpParms->dwItem) {
695 case MCI_GETDEVCAPS_CAN_RECORD:
696 lpParms->dwReturn = TRUE;
697 break;
698 case MCI_GETDEVCAPS_HAS_AUDIO:
699 lpParms->dwReturn = TRUE;
700 break;
701 case MCI_GETDEVCAPS_HAS_VIDEO:
702 lpParms->dwReturn = FALSE;
703 break;
704 case MCI_GETDEVCAPS_DEVICE_TYPE:
705 lpParms->dwReturn = MCI_DEVTYPE_WAVEFORM_AUDIO;
706 break;
707 case MCI_GETDEVCAPS_USES_FILES:
708 lpParms->dwReturn = TRUE;
709 break;
710 case MCI_GETDEVCAPS_COMPOUND_DEVICE:
711 lpParms->dwReturn = TRUE;
712 break;
713 case MCI_GETDEVCAPS_CAN_EJECT:
714 lpParms->dwReturn = FALSE;
715 break;
716 case MCI_GETDEVCAPS_CAN_PLAY:
717 lpParms->dwReturn = TRUE;
718 break;
719 case MCI_GETDEVCAPS_CAN_SAVE:
720 lpParms->dwReturn = TRUE;
721 break;
722 case MCI_WAVE_GETDEVCAPS_INPUTS:
723 lpParms->dwReturn = 1;
724 break;
725 case MCI_WAVE_GETDEVCAPS_OUTPUTS:
726 lpParms->dwReturn = 1;
727 break;
728 default:
729 return MCIERR_UNRECOGNIZED_COMMAND;
732 return 0;
735 /**************************************************************************
736 * WAVE_mciInfo [internal]
738 static DWORD WAVE_mciInfo(UINT16 wDevID, DWORD dwFlags, LPMCI_INFO_PARMS lpParms)
740 dprintf_mciwave(stddeb,
741 "WAVE_mciInfo(%u, %08lX, %p);\n", wDevID, dwFlags, lpParms);
742 if (lpParms == NULL) return MCIERR_INTERNAL;
743 lpParms->lpstrReturn = NULL;
744 switch(dwFlags) {
745 case MCI_INFO_PRODUCT:
746 lpParms->lpstrReturn = "Linux Sound System 0.5";
747 break;
748 case MCI_INFO_FILE:
749 lpParms->lpstrReturn =
750 (LPSTR)MCIWavDev[wDevID].openParms.lpstrElementName;
751 break;
752 case MCI_WAVE_INPUT:
753 lpParms->lpstrReturn = "Linux Sound System 0.5";
754 break;
755 case MCI_WAVE_OUTPUT:
756 lpParms->lpstrReturn = "Linux Sound System 0.5";
757 break;
758 default:
759 return MCIERR_UNRECOGNIZED_COMMAND;
761 if (lpParms->lpstrReturn != NULL)
762 lpParms->dwRetSize = strlen(lpParms->lpstrReturn);
763 else
764 lpParms->dwRetSize = 0;
765 return 0;
769 /*-----------------------------------------------------------------------*/
772 /**************************************************************************
773 * wodGetDevCaps [internal]
775 static DWORD wodGetDevCaps(WORD wDevID, LPWAVEOUTCAPS lpCaps, DWORD dwSize)
777 int audio;
778 int smplrate;
779 int samplesize = 16;
780 int dsp_stereo = 1;
781 int bytespersmpl;
782 dprintf_mciwave(stddeb,
783 "wodGetDevCaps(%u, %p, %lu);\n", wDevID, lpCaps, dwSize);
784 if (lpCaps == NULL) return MMSYSERR_NOTENABLED;
785 if (access(SOUND_DEV,0) != 0) return MMSYSERR_NOTENABLED;
786 audio = open (SOUND_DEV, O_WRONLY, 0);
787 if (audio == -1) return MMSYSERR_ALLOCATED ;
788 #ifdef EMULATE_SB16
789 lpCaps->wMid = 0x0002;
790 lpCaps->wPid = 0x0104;
791 strcpy(lpCaps->szPname, "SB16 Wave Out");
792 #else
793 lpCaps->wMid = 0x00FF; /* Manufac ID */
794 lpCaps->wPid = 0x0001; /* Product ID */
795 strcpy(lpCaps->szPname, "Linux WAVOUT Driver");
796 #endif
797 lpCaps->dwFormats = 0x00000000;
798 lpCaps->dwSupport = WAVECAPS_VOLUME;
799 lpCaps->wChannels = (IOCTL(audio, SNDCTL_DSP_STEREO, dsp_stereo) != 0) ? 1 : 2;
800 if (lpCaps->wChannels > 1) lpCaps->dwSupport |= WAVECAPS_LRVOLUME;
801 bytespersmpl = (IOCTL(audio, SNDCTL_DSP_SAMPLESIZE, samplesize) != 0) ? 1 : 2;
802 smplrate = 44100;
803 if (IOCTL(audio, SNDCTL_DSP_SPEED, smplrate) == 0) {
804 lpCaps->dwFormats |= WAVE_FORMAT_4M08;
805 if (lpCaps->wChannels > 1) lpCaps->dwFormats |= WAVE_FORMAT_4S08;
806 if (bytespersmpl > 1) {
807 lpCaps->dwFormats |= WAVE_FORMAT_4M16;
808 if (lpCaps->wChannels > 1) lpCaps->dwFormats |= WAVE_FORMAT_4S16;
811 smplrate = 22050;
812 if (IOCTL(audio, SNDCTL_DSP_SPEED, smplrate) == 0) {
813 lpCaps->dwFormats |= WAVE_FORMAT_2M08;
814 if (lpCaps->wChannels > 1) lpCaps->dwFormats |= WAVE_FORMAT_2S08;
815 if (bytespersmpl > 1) {
816 lpCaps->dwFormats |= WAVE_FORMAT_2M16;
817 if (lpCaps->wChannels > 1) lpCaps->dwFormats |= WAVE_FORMAT_2S16;
820 smplrate = 11025;
821 if (IOCTL(audio, SNDCTL_DSP_SPEED, smplrate) == 0) {
822 lpCaps->dwFormats |= WAVE_FORMAT_1M08;
823 if (lpCaps->wChannels > 1) lpCaps->dwFormats |= WAVE_FORMAT_1S08;
824 if (bytespersmpl > 1) {
825 lpCaps->dwFormats |= WAVE_FORMAT_1M16;
826 if (lpCaps->wChannels > 1) lpCaps->dwFormats |= WAVE_FORMAT_1S16;
829 close(audio);
830 dprintf_mciwave(stddeb,
831 "wodGetDevCaps // dwFormats = %08lX\n", lpCaps->dwFormats);
832 return MMSYSERR_NOERROR;
836 /**************************************************************************
837 * wodOpen [internal]
839 static DWORD wodOpen(WORD wDevID, LPWAVEOPENDESC lpDesc, DWORD dwFlags)
841 int audio;
842 int abuf_size;
843 int smplrate;
844 int samplesize;
845 int dsp_stereo;
846 LPWAVEFORMAT lpFormat;
848 dprintf_mciwave(stddeb,
849 "wodOpen(%u, %p, %08lX);\n", wDevID, lpDesc, dwFlags);
850 if (lpDesc == NULL) {
851 dprintf_mciwave(stddeb,"Linux 'wodOpen' // Invalid Parameter !\n");
852 return MMSYSERR_INVALPARAM;
854 if (wDevID >= MAX_WAVOUTDRV) {
855 dprintf_mciwave(stddeb,"Linux 'wodOpen' // MAX_WAVOUTDRV reached !\n");
856 return MMSYSERR_ALLOCATED;
858 WOutDev[wDevID].unixdev = 0;
859 if (access(SOUND_DEV,0) != 0) return MMSYSERR_NOTENABLED;
860 audio = open (SOUND_DEV, O_WRONLY, 0);
861 if (audio == -1) {
862 dprintf_mciwave(stddeb,"Linux 'wodOpen' // can't open !\n");
863 return MMSYSERR_ALLOCATED ;
865 IOCTL(audio, SNDCTL_DSP_GETBLKSIZE, abuf_size);
866 if (abuf_size < 1024 || abuf_size > 65536) {
867 if (abuf_size == -1)
868 dprintf_mciwave(stddeb,"Linux 'wodOpen' // IOCTL can't 'SNDCTL_DSP_GETBLKSIZE' !\n");
869 else
870 dprintf_mciwave(stddeb,"Linux 'wodOpen' // SNDCTL_DSP_GETBLKSIZE Invalid bufsize !\n");
871 return MMSYSERR_NOTENABLED;
873 WOutDev[wDevID].wFlags = HIWORD(dwFlags & CALLBACK_TYPEMASK);
874 switch(WOutDev[wDevID].wFlags) {
875 case DCB_NULL:
876 dprintf_mciwave(stddeb, "Linux 'wodOpen' // CALLBACK_NULL !\n");
877 break;
878 case DCB_WINDOW:
879 dprintf_mciwave(stddeb, "Linux 'wodOpen' // CALLBACK_WINDOW !\n");
880 break;
881 case DCB_TASK:
882 dprintf_mciwave(stddeb, "Linux 'wodOpen' // CALLBACK_TASK !\n");
883 break;
884 case DCB_FUNCTION:
885 dprintf_mciwave(stddeb, "Linux 'wodOpen' // CALLBACK_FUNCTION !\n");
886 break;
888 WOutDev[wDevID].lpQueueHdr = NULL;
889 WOutDev[wDevID].unixdev = audio;
890 WOutDev[wDevID].dwTotalPlayed = 0;
891 WOutDev[wDevID].bufsize = abuf_size;
892 memcpy(&WOutDev[wDevID].waveDesc, lpDesc, sizeof(WAVEOPENDESC));
893 dprintf_mciwave(stddeb,"Linux 'wodOpen' // lpDesc->lpFormat = %p\n",lpDesc->lpFormat);
894 lpFormat = (LPWAVEFORMAT) PTR_SEG_TO_LIN(lpDesc->lpFormat);
895 /* lpFormat = lpDesc->lpFormat; */
896 dprintf_mciwave(stddeb,"Linux 'wodOpen' // lpFormat = %p\n",lpFormat);
897 if (lpFormat->wFormatTag != WAVE_FORMAT_PCM) {
898 dprintf_mciwave(stddeb,"Linux 'wodOpen' // Bad format %04X !\n",
899 lpFormat->wFormatTag);
900 dprintf_mciwave(stddeb,"Linux 'wodOpen' // Bad nChannels %d !\n",
901 lpFormat->nChannels);
902 dprintf_mciwave(stddeb,"Linux 'wodOpen' // Bad nSamplesPerSec %ld !\n",
903 lpFormat->nSamplesPerSec);
904 return WAVERR_BADFORMAT;
906 memcpy(&WOutDev[wDevID].Format, lpFormat, sizeof(PCMWAVEFORMAT));
907 if (WOutDev[wDevID].Format.wf.nChannels == 0) return WAVERR_BADFORMAT;
908 if (WOutDev[wDevID].Format.wf.nSamplesPerSec == 0) return WAVERR_BADFORMAT;
909 dprintf_mciwave(stddeb,"Linux 'wodOpen' // wBitsPerSample=%u !\n",
910 WOutDev[wDevID].Format.wBitsPerSample);
911 if (WOutDev[wDevID].Format.wBitsPerSample == 0) {
912 WOutDev[wDevID].Format.wBitsPerSample = 8 *
913 (WOutDev[wDevID].Format.wf.nAvgBytesPerSec /
914 WOutDev[wDevID].Format.wf.nSamplesPerSec) /
915 WOutDev[wDevID].Format.wf.nChannels;
917 samplesize = WOutDev[wDevID].Format.wBitsPerSample;
918 smplrate = WOutDev[wDevID].Format.wf.nSamplesPerSec;
919 dsp_stereo = (WOutDev[wDevID].Format.wf.nChannels > 1) ? TRUE : FALSE;
920 IOCTL(audio, SNDCTL_DSP_SPEED, smplrate);
921 IOCTL(audio, SNDCTL_DSP_SAMPLESIZE, samplesize);
922 IOCTL(audio, SNDCTL_DSP_STEREO, dsp_stereo);
923 dprintf_mciwave(stddeb,"Linux 'wodOpen' // wBitsPerSample=%u !\n",
924 WOutDev[wDevID].Format.wBitsPerSample);
925 dprintf_mciwave(stddeb,"Linux 'wodOpen' // nAvgBytesPerSec=%lu !\n",
926 WOutDev[wDevID].Format.wf.nAvgBytesPerSec);
927 dprintf_mciwave(stddeb,"Linux 'wodOpen' // nSamplesPerSec=%lu !\n",
928 WOutDev[wDevID].Format.wf.nSamplesPerSec);
929 dprintf_mciwave(stddeb,"Linux 'wodOpen' // nChannels=%u !\n",
930 WOutDev[wDevID].Format.wf.nChannels);
931 if (WAVE_NotifyClient(wDevID, WOM_OPEN, 0L, 0L) != MMSYSERR_NOERROR) {
932 dprintf_mciwave(stddeb,"Linux 'wodOpen' // can't notify client !\n");
933 return MMSYSERR_INVALPARAM;
935 return MMSYSERR_NOERROR;
938 /**************************************************************************
939 * wodClose [internal]
941 static DWORD wodClose(WORD wDevID)
943 dprintf_mciwave(stddeb,"wodClose(%u);\n", wDevID);
944 if (WOutDev[wDevID].unixdev == 0) {
945 dprintf_mciwave(stddeb,"Linux 'wodClose' // can't close !\n");
946 return MMSYSERR_NOTENABLED;
948 close(WOutDev[wDevID].unixdev);
949 WOutDev[wDevID].unixdev = 0;
950 WOutDev[wDevID].bufsize = 0;
951 WOutDev[wDevID].lpQueueHdr = NULL;
952 if (WAVE_NotifyClient(wDevID, WOM_CLOSE, 0L, 0L) != MMSYSERR_NOERROR) {
953 dprintf_mciwave(stddeb,"Linux 'wodClose' // can't notify client !\n");
954 return MMSYSERR_INVALPARAM;
956 return MMSYSERR_NOERROR;
959 /**************************************************************************
960 * wodWrite [internal]
962 static DWORD wodWrite(WORD wDevID, LPWAVEHDR lpWaveHdr, DWORD dwSize)
964 int count;
965 LPSTR lpData;
966 dprintf_mciwave(stddeb,"wodWrite(%u, %p, %08lX);\n", wDevID, lpWaveHdr, dwSize);
967 if (WOutDev[wDevID].unixdev == 0) {
968 dprintf_mciwave(stddeb,"Linux 'wodWrite' // can't play !\n");
969 return MMSYSERR_NOTENABLED;
971 if (lpWaveHdr->lpData == NULL) return WAVERR_UNPREPARED;
972 if (!(lpWaveHdr->dwFlags & WHDR_PREPARED)) return WAVERR_UNPREPARED;
973 if (lpWaveHdr->dwFlags & WHDR_INQUEUE) return WAVERR_STILLPLAYING;
974 lpWaveHdr->dwFlags &= ~WHDR_DONE;
975 lpWaveHdr->dwFlags |= WHDR_INQUEUE;
976 dprintf_mciwave(stddeb,
977 "wodWrite() // dwBufferLength %lu !\n", lpWaveHdr->dwBufferLength);
978 dprintf_mciwave(stddeb,
979 "wodWrite() // WOutDev[%u].unixdev %u !\n", wDevID, WOutDev[wDevID].unixdev);
980 lpData = PTR_SEG_TO_LIN(lpWaveHdr->lpData);
981 count = write (WOutDev[wDevID].unixdev, lpData, lpWaveHdr->dwBufferLength);
982 dprintf_mciwave(stddeb,
983 "wodWrite() // write returned count %u !\n", count);
984 if (count != lpWaveHdr->dwBufferLength) {
985 dprintf_mciwave(stddeb,"Linux 'wodWrite' // error writting !\n");
986 return MMSYSERR_NOTENABLED;
988 WOutDev[wDevID].dwTotalPlayed += count;
989 lpWaveHdr->dwFlags &= ~WHDR_INQUEUE;
990 lpWaveHdr->dwFlags |= WHDR_DONE;
991 if (WAVE_NotifyClient(wDevID, WOM_DONE, 0L, 0L) != MMSYSERR_NOERROR) {
992 dprintf_mciwave(stddeb,"Linux 'wodWrite' // can't notify client !\n");
993 return MMSYSERR_INVALPARAM;
995 return MMSYSERR_NOERROR;
998 /**************************************************************************
999 * wodPrepare [internal]
1001 static DWORD wodPrepare(WORD wDevID, LPWAVEHDR lpWaveHdr, DWORD dwSize)
1003 dprintf_mciwave(stddeb,
1004 "wodPrepare(%u, %p, %08lX);\n", wDevID, lpWaveHdr, dwSize);
1005 if (WOutDev[wDevID].unixdev == 0) {
1006 dprintf_mciwave(stddeb,"Linux 'wodPrepare' // can't prepare !\n");
1007 return MMSYSERR_NOTENABLED;
1009 /* the COOL waveeditor feels much better without this check...
1010 * someone please have a look at available documentation
1011 if (WOutDev[wDevID].lpQueueHdr != NULL) {
1012 dprintf_mciwave(stddeb,"Linux 'wodPrepare' // already prepare !\n");
1013 return MMSYSERR_NOTENABLED;
1016 WOutDev[wDevID].dwTotalPlayed = 0;
1017 WOutDev[wDevID].lpQueueHdr = lpWaveHdr;
1018 if (lpWaveHdr->dwFlags & WHDR_INQUEUE) return WAVERR_STILLPLAYING;
1019 lpWaveHdr->dwFlags |= WHDR_PREPARED;
1020 lpWaveHdr->dwFlags &= ~WHDR_DONE;
1021 return MMSYSERR_NOERROR;
1024 /**************************************************************************
1025 * wodUnprepare [internal]
1027 static DWORD wodUnprepare(WORD wDevID, LPWAVEHDR lpWaveHdr, DWORD dwSize)
1029 dprintf_mciwave(stddeb,
1030 "wodUnprepare(%u, %p, %08lX);\n", wDevID, lpWaveHdr, dwSize);
1031 if (WOutDev[wDevID].unixdev == 0) {
1032 dprintf_mciwave(stddeb,"Linux 'wodUnprepare' // can't unprepare !\n");
1033 return MMSYSERR_NOTENABLED;
1035 return MMSYSERR_NOERROR;
1038 /**************************************************************************
1039 * wodRestart [internal]
1041 static DWORD wodRestart(WORD wDevID)
1043 dprintf_mciwave(stddeb,"wodRestart(%u);\n", wDevID);
1044 if (WOutDev[wDevID].unixdev == 0) {
1045 dprintf_mciwave(stddeb,"Linux 'wodRestart' // can't restart !\n");
1046 return MMSYSERR_NOTENABLED;
1048 return MMSYSERR_NOERROR;
1051 /**************************************************************************
1052 * wodReset [internal]
1054 static DWORD wodReset(WORD wDevID)
1056 dprintf_mciwave(stddeb,"wodReset(%u);\n", wDevID);
1057 if (WOutDev[wDevID].unixdev == 0) {
1058 dprintf_mciwave(stddeb,"Linux 'wodReset' // can't reset !\n");
1059 return MMSYSERR_NOTENABLED;
1061 return MMSYSERR_NOERROR;
1065 /**************************************************************************
1066 * wodGetPosition [internal]
1068 static DWORD wodGetPosition(WORD wDevID, LPMMTIME lpTime, DWORD uSize)
1070 int time;
1071 dprintf_mciwave(stddeb,"wodGetPosition(%u, %p, %lu);\n", wDevID, lpTime, uSize);
1072 if (WOutDev[wDevID].unixdev == 0) {
1073 dprintf_mciwave(stddeb,"Linux 'wodGetPosition' // can't get pos !\n");
1074 return MMSYSERR_NOTENABLED;
1076 if (lpTime == NULL) return MMSYSERR_INVALPARAM;
1077 switch(lpTime->wType) {
1078 case TIME_BYTES:
1079 lpTime->u.cb = WOutDev[wDevID].dwTotalPlayed;
1080 dprintf_mciwave(stddeb,"wodGetPosition // TIME_BYTES=%lu\n", lpTime->u.cb);
1081 break;
1082 case TIME_SAMPLES:
1083 dprintf_mciwave(stddeb,"wodGetPosition // dwTotalPlayed=%lu\n",
1084 WOutDev[wDevID].dwTotalPlayed);
1085 dprintf_mciwave(stddeb,"wodGetPosition // wBitsPerSample=%u\n",
1086 WOutDev[wDevID].Format.wBitsPerSample);
1087 lpTime->u.sample = WOutDev[wDevID].dwTotalPlayed * 8 /
1088 WOutDev[wDevID].Format.wBitsPerSample;
1089 dprintf_mciwave(stddeb,"wodGetPosition // TIME_SAMPLES=%lu\n", lpTime->u.sample);
1090 break;
1091 case TIME_SMPTE:
1092 time = WOutDev[wDevID].dwTotalPlayed /
1093 (WOutDev[wDevID].Format.wf.nAvgBytesPerSec / 1000);
1094 lpTime->u.smpte.hour = time / 108000;
1095 time -= lpTime->u.smpte.hour * 108000;
1096 lpTime->u.smpte.min = time / 1800;
1097 time -= lpTime->u.smpte.min * 1800;
1098 lpTime->u.smpte.sec = time / 30;
1099 time -= lpTime->u.smpte.sec * 30;
1100 lpTime->u.smpte.frame = time;
1101 lpTime->u.smpte.fps = 30;
1102 dprintf_mciwave(stddeb,
1103 "wodGetPosition // TIME_SMPTE=%02u:%02u:%02u:%02u\n",
1104 lpTime->u.smpte.hour, lpTime->u.smpte.min,
1105 lpTime->u.smpte.sec, lpTime->u.smpte.frame);
1106 break;
1107 default:
1108 dprintf_mciwave(stddeb,"wodGetPosition() format not supported ! use TIME_MS !\n");
1109 lpTime->wType = TIME_MS;
1110 case TIME_MS:
1111 lpTime->u.ms = WOutDev[wDevID].dwTotalPlayed /
1112 (WOutDev[wDevID].Format.wf.nAvgBytesPerSec / 1000);
1113 dprintf_mciwave(stddeb,"wodGetPosition // TIME_MS=%lu\n", lpTime->u.ms);
1114 break;
1116 return MMSYSERR_NOERROR;
1119 /**************************************************************************
1120 * wodGetVolume [internal]
1122 static DWORD wodGetVolume(WORD wDevID, LPDWORD lpdwVol)
1124 int mixer;
1125 int volume, left, right;
1126 dprintf_mciwave(stddeb,"wodGetVolume(%u, %p);\n", wDevID, lpdwVol);
1127 if (lpdwVol == NULL) return MMSYSERR_NOTENABLED;
1128 if ((mixer = open(MIXER_DEV, O_RDONLY)) < 0) {
1129 dprintf_mciwave(stddeb, "Linux 'wodGetVolume' // mixer device not available !\n");
1130 return MMSYSERR_NOTENABLED;
1132 if (ioctl(mixer, SOUND_MIXER_READ_PCM, &volume) == -1) {
1133 dprintf_mciwave(stddeb,"Linux 'wodGetVolume' // unable read mixer !\n");
1134 return MMSYSERR_NOTENABLED;
1136 close(mixer);
1137 left = volume & 0x7F;
1138 right = (volume >> 8) & 0x7F;
1139 dprintf_mciwave(stddeb,"Linux 'wodGetVolume' // left=%d right=%d !\n", left, right);
1140 *lpdwVol = MAKELONG(left << 9, right << 9);
1141 return MMSYSERR_NOERROR;
1145 /**************************************************************************
1146 * wodSetVolume [internal]
1148 static DWORD wodSetVolume(WORD wDevID, DWORD dwParam)
1150 int mixer;
1151 int volume;
1152 dprintf_mciwave(stddeb,"wodSetVolume(%u, %08lX);\n", wDevID, dwParam);
1153 volume = (LOWORD(dwParam) >> 9 & 0x7F) +
1154 ((HIWORD(dwParam) >> 9 & 0x7F) << 8);
1155 if ((mixer = open(MIXER_DEV, O_WRONLY)) < 0) {
1156 dprintf_mciwave(stddeb, "Linux 'wodSetVolume' // mixer device not available !\n");
1157 return MMSYSERR_NOTENABLED;
1159 if (ioctl(mixer, SOUND_MIXER_WRITE_PCM, &volume) == -1) {
1160 dprintf_mciwave(stddeb,"Linux 'wodSetVolume' // unable set mixer !\n");
1161 return MMSYSERR_NOTENABLED;
1163 close(mixer);
1164 return MMSYSERR_NOERROR;
1167 #endif /* linux || __FreeBSD__*/
1169 /**************************************************************************
1170 * wodMessage [sample driver]
1172 DWORD wodMessage(WORD wDevID, WORD wMsg, DWORD dwUser,
1173 DWORD dwParam1, DWORD dwParam2)
1175 dprintf_mciwave(stddeb,"wodMessage(%u, %04X, %08lX, %08lX, %08lX);\n",
1176 wDevID, wMsg, dwUser, dwParam1, dwParam2);
1177 #if defined(linux) || defined(__FreeBSD__)
1178 switch(wMsg) {
1179 case WODM_OPEN:
1180 return wodOpen(wDevID, (LPWAVEOPENDESC)PTR_SEG_TO_LIN(dwParam1), dwParam2);
1181 case WODM_CLOSE:
1182 return wodClose(wDevID);
1183 case WODM_WRITE:
1184 return wodWrite(wDevID, (LPWAVEHDR)PTR_SEG_TO_LIN(dwParam1), dwParam2);
1185 case WODM_PAUSE:
1186 return 0L;
1187 case WODM_GETPOS:
1188 return wodGetPosition(wDevID, (LPMMTIME)PTR_SEG_TO_LIN(dwParam1), dwParam2);
1189 case WODM_BREAKLOOP:
1190 return 0L;
1191 case WODM_PREPARE:
1192 return wodPrepare(wDevID, (LPWAVEHDR)PTR_SEG_TO_LIN(dwParam1), dwParam2);
1193 case WODM_UNPREPARE:
1194 return wodUnprepare(wDevID, (LPWAVEHDR)PTR_SEG_TO_LIN(dwParam1), dwParam2);
1195 case WODM_GETDEVCAPS:
1196 return wodGetDevCaps(wDevID, (LPWAVEOUTCAPS)PTR_SEG_TO_LIN(dwParam1), dwParam2);
1197 case WODM_GETNUMDEVS:
1198 return 1L;
1199 case WODM_GETPITCH:
1200 return MMSYSERR_NOTSUPPORTED;
1201 case WODM_SETPITCH:
1202 return MMSYSERR_NOTSUPPORTED;
1203 case WODM_GETPLAYBACKRATE:
1204 return MMSYSERR_NOTSUPPORTED;
1205 case WODM_SETPLAYBACKRATE:
1206 return MMSYSERR_NOTSUPPORTED;
1207 case WODM_GETVOLUME:
1208 return wodGetVolume(wDevID, (LPDWORD)PTR_SEG_TO_LIN(dwParam1));
1209 case WODM_SETVOLUME:
1210 return wodSetVolume(wDevID, dwParam1);
1211 case WODM_RESTART:
1212 return wodRestart(wDevID);
1213 case WODM_RESET:
1214 return wodReset(wDevID);
1215 default:
1216 dprintf_mciwave(stddeb,"wodMessage // unknown message !\n");
1218 return MMSYSERR_NOTSUPPORTED;
1219 #else
1220 return MMSYSERR_NOTENABLED;
1221 #endif
1225 /*-----------------------------------------------------------------------*/
1227 #if defined(linux) || defined(__FreeBSD__)
1229 /**************************************************************************
1230 * widGetDevCaps [internal]
1232 static DWORD widGetDevCaps(WORD wDevID, LPWAVEINCAPS lpCaps, DWORD dwSize)
1234 int audio;
1235 int smplrate;
1236 int samplesize = 16;
1237 int dsp_stereo = 1;
1238 int bytespersmpl;
1239 dprintf_mciwave(stddeb,
1240 "widGetDevCaps(%u, %p, %lu);\n", wDevID, lpCaps, dwSize);
1241 if (lpCaps == NULL) return MMSYSERR_NOTENABLED;
1242 if (access(SOUND_DEV,0) != 0) return MMSYSERR_NOTENABLED;
1243 audio = open (SOUND_DEV, O_RDONLY, 0);
1244 if (audio == -1) return MMSYSERR_ALLOCATED ;
1245 #ifdef EMULATE_SB16
1246 lpCaps->wMid = 0x0002;
1247 lpCaps->wPid = 0x0004;
1248 strcpy(lpCaps->szPname, "SB16 Wave In");
1249 #else
1250 lpCaps->wMid = 0x00FF; /* Manufac ID */
1251 lpCaps->wPid = 0x0001; /* Product ID */
1252 strcpy(lpCaps->szPname, "Linux WAVIN Driver");
1253 #endif
1254 lpCaps->dwFormats = 0x00000000;
1255 lpCaps->wChannels = (IOCTL(audio, SNDCTL_DSP_STEREO, dsp_stereo) != 0) ? 1 : 2;
1256 bytespersmpl = (IOCTL(audio, SNDCTL_DSP_SAMPLESIZE, samplesize) != 0) ? 1 : 2;
1257 smplrate = 44100;
1258 if (IOCTL(audio, SNDCTL_DSP_SPEED, smplrate) == 0) {
1259 lpCaps->dwFormats |= WAVE_FORMAT_4M08;
1260 if (lpCaps->wChannels > 1) lpCaps->dwFormats |= WAVE_FORMAT_4S08;
1261 if (bytespersmpl > 1) {
1262 lpCaps->dwFormats |= WAVE_FORMAT_4M16;
1263 if (lpCaps->wChannels > 1) lpCaps->dwFormats |= WAVE_FORMAT_4S16;
1266 smplrate = 22050;
1267 if (IOCTL(audio, SNDCTL_DSP_SPEED, smplrate) == 0) {
1268 lpCaps->dwFormats |= WAVE_FORMAT_2M08;
1269 if (lpCaps->wChannels > 1) lpCaps->dwFormats |= WAVE_FORMAT_2S08;
1270 if (bytespersmpl > 1) {
1271 lpCaps->dwFormats |= WAVE_FORMAT_2M16;
1272 if (lpCaps->wChannels > 1) lpCaps->dwFormats |= WAVE_FORMAT_2S16;
1275 smplrate = 11025;
1276 if (IOCTL(audio, SNDCTL_DSP_SPEED, smplrate) == 0) {
1277 lpCaps->dwFormats |= WAVE_FORMAT_1M08;
1278 if (lpCaps->wChannels > 1) lpCaps->dwFormats |= WAVE_FORMAT_1S08;
1279 if (bytespersmpl > 1) {
1280 lpCaps->dwFormats |= WAVE_FORMAT_1M16;
1281 if (lpCaps->wChannels > 1) lpCaps->dwFormats |= WAVE_FORMAT_1S16;
1284 close(audio);
1285 dprintf_mciwave(stddeb,
1286 "widGetDevCaps // dwFormats = %08lX\n", lpCaps->dwFormats);
1287 return MMSYSERR_NOERROR;
1291 /**************************************************************************
1292 * widOpen [internal]
1294 static DWORD widOpen(WORD wDevID, LPWAVEOPENDESC lpDesc, DWORD dwFlags)
1296 int audio;
1297 int abuf_size;
1298 int smplrate;
1299 int samplesize;
1300 int dsp_stereo;
1301 LPWAVEFORMAT lpFormat;
1302 dprintf_mciwave(stddeb, "widOpen(%u, %p, %08lX);\n", wDevID, lpDesc, dwFlags);
1303 if (lpDesc == NULL) {
1304 dprintf_mciwave(stddeb,"Linux 'widOpen' // Invalid Parameter !\n");
1305 return MMSYSERR_INVALPARAM;
1307 if (wDevID >= MAX_WAVINDRV) {
1308 dprintf_mciwave(stddeb,"Linux 'widOpen' // MAX_WAVINDRV reached !\n");
1309 return MMSYSERR_ALLOCATED;
1311 WInDev[wDevID].unixdev = 0;
1312 if (access(SOUND_DEV,0) != 0) return MMSYSERR_NOTENABLED;
1313 audio = open (SOUND_DEV, O_RDONLY, 0);
1314 if (audio == -1) {
1315 dprintf_mciwave(stddeb,"Linux 'widOpen' // can't open !\n");
1316 return MMSYSERR_ALLOCATED;
1318 IOCTL(audio, SNDCTL_DSP_GETBLKSIZE, abuf_size);
1319 if (abuf_size < 1024 || abuf_size > 65536) {
1320 if (abuf_size == -1)
1321 dprintf_mciwave(stddeb,"Linux 'widOpen' // IOCTL can't 'SNDCTL_DSP_GETBLKSIZE' !\n");
1322 else
1323 dprintf_mciwave(stddeb,"Linux 'widOpen' // SNDCTL_DSP_GETBLKSIZE Invalid bufsize !\n");
1324 return MMSYSERR_NOTENABLED;
1326 WInDev[wDevID].wFlags = HIWORD(dwFlags & CALLBACK_TYPEMASK);
1327 switch(WInDev[wDevID].wFlags) {
1328 case DCB_NULL:
1329 dprintf_mciwave(stddeb, "Linux 'widOpen' // CALLBACK_NULL !\n");
1330 break;
1331 case DCB_WINDOW:
1332 dprintf_mciwave(stddeb, "Linux 'widOpen' // CALLBACK_WINDOW !\n");
1333 break;
1334 case DCB_TASK:
1335 dprintf_mciwave(stddeb, "Linux 'widOpen' // CALLBACK_TASK !\n");
1336 break;
1337 case DCB_FUNCTION:
1338 dprintf_mciwave(stddeb, "Linux 'widOpen' // CALLBACK_FUNCTION !\n");
1339 break;
1341 WInDev[wDevID].lpQueueHdr = NULL;
1342 WInDev[wDevID].unixdev = audio;
1343 WInDev[wDevID].bufsize = abuf_size;
1344 WInDev[wDevID].dwTotalRecorded = 0;
1345 memcpy(&WInDev[wDevID].waveDesc, lpDesc, sizeof(WAVEOPENDESC));
1346 lpFormat = (LPWAVEFORMAT) PTR_SEG_TO_LIN(lpDesc->lpFormat);
1347 /* lpFormat = lpDesc->lpFormat; */
1348 if (lpFormat->wFormatTag != WAVE_FORMAT_PCM) {
1349 dprintf_mciwave(stddeb,"Linux 'widOpen' // Bad format %04X !\n",
1350 lpFormat->wFormatTag);
1351 return WAVERR_BADFORMAT;
1353 memcpy(&WInDev[wDevID].Format, lpFormat, sizeof(PCMWAVEFORMAT));
1354 WInDev[wDevID].Format.wBitsPerSample = 8; /* <-------------- */
1355 if (WInDev[wDevID].Format.wf.nChannels == 0) return WAVERR_BADFORMAT;
1356 if (WInDev[wDevID].Format.wf.nSamplesPerSec == 0) return WAVERR_BADFORMAT;
1357 if (WInDev[wDevID].Format.wBitsPerSample == 0) {
1358 WInDev[wDevID].Format.wBitsPerSample = 8 *
1359 (WInDev[wDevID].Format.wf.nAvgBytesPerSec /
1360 WInDev[wDevID].Format.wf.nSamplesPerSec) /
1361 WInDev[wDevID].Format.wf.nChannels;
1363 samplesize = WInDev[wDevID].Format.wBitsPerSample;
1364 smplrate = WInDev[wDevID].Format.wf.nSamplesPerSec;
1365 dsp_stereo = (WInDev[wDevID].Format.wf.nChannels > 1) ? TRUE : FALSE;
1366 IOCTL(audio, SNDCTL_DSP_SPEED, smplrate);
1367 IOCTL(audio, SNDCTL_DSP_SAMPLESIZE, samplesize);
1368 IOCTL(audio, SNDCTL_DSP_STEREO, dsp_stereo);
1369 dprintf_mciwave(stddeb,"Linux 'widOpen' // wBitsPerSample=%u !\n",
1370 WInDev[wDevID].Format.wBitsPerSample);
1371 dprintf_mciwave(stddeb,"Linux 'widOpen' // nSamplesPerSec=%lu !\n",
1372 WInDev[wDevID].Format.wf.nSamplesPerSec);
1373 dprintf_mciwave(stddeb,"Linux 'widOpen' // nChannels=%u !\n",
1374 WInDev[wDevID].Format.wf.nChannels);
1375 dprintf_mciwave(stddeb,"Linux 'widOpen' // nAvgBytesPerSec=%lu\n",
1376 WInDev[wDevID].Format.wf.nAvgBytesPerSec);
1377 if (WAVE_NotifyClient(wDevID, WIM_OPEN, 0L, 0L) != MMSYSERR_NOERROR) {
1378 dprintf_mciwave(stddeb,"Linux 'widOpen' // can't notify client !\n");
1379 return MMSYSERR_INVALPARAM;
1381 return MMSYSERR_NOERROR;
1384 /**************************************************************************
1385 * widClose [internal]
1387 static DWORD widClose(WORD wDevID)
1389 dprintf_mciwave(stddeb,"widClose(%u);\n", wDevID);
1390 if (WInDev[wDevID].unixdev == 0) {
1391 dprintf_mciwave(stddeb,"Linux 'widClose' // can't close !\n");
1392 return MMSYSERR_NOTENABLED;
1394 close(WInDev[wDevID].unixdev);
1395 WInDev[wDevID].unixdev = 0;
1396 WInDev[wDevID].bufsize = 0;
1397 if (WAVE_NotifyClient(wDevID, WIM_CLOSE, 0L, 0L) != MMSYSERR_NOERROR) {
1398 dprintf_mciwave(stddeb,"Linux 'widClose' // can't notify client !\n");
1399 return MMSYSERR_INVALPARAM;
1401 return MMSYSERR_NOERROR;
1404 /**************************************************************************
1405 * widAddBuffer [internal]
1407 static DWORD widAddBuffer(WORD wDevID, LPWAVEHDR lpWaveHdr, DWORD dwSize)
1409 int count = 1;
1410 LPWAVEHDR lpWIHdr;
1411 dprintf_mciwave(stddeb,
1412 "widAddBuffer(%u, %p, %08lX);\n", wDevID, lpWaveHdr, dwSize);
1413 if (WInDev[wDevID].unixdev == 0) {
1414 dprintf_mciwave(stddeb,"Linux 'widAddBuffer' // can't do it !\n");
1415 return MMSYSERR_NOTENABLED;
1417 if (!(lpWaveHdr->dwFlags & WHDR_PREPARED)) {
1418 dprintf_mciwave(stddeb, "Linux 'widAddBuffer' // never been prepared !\n");
1419 return WAVERR_UNPREPARED;
1421 if (lpWaveHdr->dwFlags & WHDR_INQUEUE) {
1422 dprintf_mciwave(stddeb, "Linux 'widAddBuffer' // header already in use !\n");
1423 return WAVERR_STILLPLAYING;
1425 lpWaveHdr->dwFlags |= WHDR_PREPARED;
1426 lpWaveHdr->dwFlags |= WHDR_INQUEUE;
1427 lpWaveHdr->dwFlags &= ~WHDR_DONE;
1428 lpWaveHdr->dwBytesRecorded = 0;
1429 if (WInDev[wDevID].lpQueueHdr == NULL) {
1430 /* begin the queue with a first header ... */
1431 WInDev[wDevID].lpQueueHdr = lpWaveHdr;
1432 WInDev[wDevID].dwTotalRecorded = 0;
1434 else {
1435 /* added to the queue, except if it's the one just prepared ... */
1436 lpWIHdr = WInDev[wDevID].lpQueueHdr;
1437 while (lpWIHdr->lpNext != NULL) {
1438 lpWIHdr = lpWIHdr->lpNext;
1439 count++;
1441 lpWIHdr->lpNext = lpWaveHdr;
1442 count++;
1444 dprintf_mciwave(stddeb,
1445 "widAddBuffer // buffer added ! (now %u in queue)\n", count);
1446 return MMSYSERR_NOERROR;
1449 /**************************************************************************
1450 * widPrepare [internal]
1452 static DWORD widPrepare(WORD wDevID, LPWAVEHDR lpWaveHdr, DWORD dwSize)
1454 dprintf_mciwave(stddeb,
1455 "widPrepare(%u, %p, %08lX);\n", wDevID, lpWaveHdr, dwSize);
1456 if (WInDev[wDevID].unixdev == 0) {
1457 dprintf_mciwave(stddeb,"Linux 'widPrepare' // can't prepare !\n");
1458 return MMSYSERR_NOTENABLED;
1460 if (WInDev[wDevID].lpQueueHdr != NULL) {
1461 dprintf_mciwave(stddeb,"Linux 'widPrepare' // already prepare !\n");
1462 return WAVERR_BADFORMAT;
1464 if (lpWaveHdr->dwFlags & WHDR_INQUEUE) return WAVERR_STILLPLAYING;
1465 lpWaveHdr->dwFlags |= WHDR_PREPARED;
1466 lpWaveHdr->dwFlags &= ~WHDR_INQUEUE;
1467 lpWaveHdr->dwFlags &= ~WHDR_DONE;
1468 lpWaveHdr->dwBytesRecorded = 0;
1469 dprintf_mciwave(stddeb,"Linux 'widPrepare' // header prepared !\n");
1470 return MMSYSERR_NOERROR;
1473 /**************************************************************************
1474 * widUnprepare [internal]
1476 static DWORD widUnprepare(WORD wDevID, LPWAVEHDR lpWaveHdr, DWORD dwSize)
1478 dprintf_mciwave(stddeb,
1479 "widUnprepare(%u, %p, %08lX);\n", wDevID, lpWaveHdr, dwSize);
1480 if (WInDev[wDevID].unixdev == 0) {
1481 dprintf_mciwave(stddeb,"Linux 'widUnprepare' // can't unprepare !\n");
1482 return MMSYSERR_NOTENABLED;
1484 lpWaveHdr->dwFlags &= ~WHDR_PREPARED;
1485 lpWaveHdr->dwFlags &= ~WHDR_INQUEUE;
1486 lpWaveHdr->dwFlags |= WHDR_DONE;
1487 WInDev[wDevID].lpQueueHdr = NULL;
1488 dprintf_mciwave(stddeb,
1489 "Linux 'widUnprepare' // all headers unprepared !\n");
1490 return MMSYSERR_NOERROR;
1493 /**************************************************************************
1494 * widStart [internal]
1496 static DWORD widStart(WORD wDevID)
1498 int count = 1;
1499 LPWAVEHDR lpWIHdr;
1500 dprintf_mciwave(stddeb,"widStart(%u);\n", wDevID);
1501 if (WInDev[wDevID].unixdev == 0) {
1502 dprintf_mciwave(stddeb, "Linux 'widStart' // can't start recording !\n");
1503 return MMSYSERR_NOTENABLED;
1505 if (WInDev[wDevID].lpQueueHdr == NULL ||
1506 WInDev[wDevID].lpQueueHdr->lpData == NULL) {
1507 dprintf_mciwave(stddeb,"Linux 'widStart' // never been prepared !\n");
1508 return WAVERR_UNPREPARED;
1510 lpWIHdr = WInDev[wDevID].lpQueueHdr;
1511 while(lpWIHdr != NULL) {
1512 lpWIHdr->dwBufferLength &= 0xFFFF;
1513 dprintf_mciwave(stddeb,
1514 "widStart // recording buf#%u=%p size=%lu \n",
1515 count, lpWIHdr->lpData, lpWIHdr->dwBufferLength);
1516 fflush(stddeb);
1517 read (WInDev[wDevID].unixdev,
1518 PTR_SEG_TO_LIN(lpWIHdr->lpData),
1519 lpWIHdr->dwBufferLength);
1520 lpWIHdr->dwBytesRecorded = lpWIHdr->dwBufferLength;
1521 WInDev[wDevID].dwTotalRecorded += lpWIHdr->dwBytesRecorded;
1522 lpWIHdr->dwFlags &= ~WHDR_INQUEUE;
1523 lpWIHdr->dwFlags |= WHDR_DONE;
1524 if (WAVE_NotifyClient(wDevID, WIM_DATA, (DWORD)lpWIHdr, 0L) !=
1525 MMSYSERR_NOERROR) {
1526 dprintf_mciwave(stddeb, "Linux 'widStart' // can't notify client !\n");
1527 return MMSYSERR_INVALPARAM;
1529 lpWIHdr = lpWIHdr->lpNext;
1530 count++;
1532 dprintf_mciwave(stddeb,"widStart // end of recording !\n");
1533 fflush(stdout);
1534 return MMSYSERR_NOERROR;
1537 /**************************************************************************
1538 * widStop [internal]
1540 static DWORD widStop(WORD wDevID)
1542 dprintf_mciwave(stddeb,"widStop(%u);\n", wDevID);
1543 if (WInDev[wDevID].unixdev == 0) {
1544 dprintf_mciwave(stddeb,"Linux 'widStop' // can't stop !\n");
1545 return MMSYSERR_NOTENABLED;
1547 return MMSYSERR_NOERROR;
1550 /**************************************************************************
1551 * widReset [internal]
1553 static DWORD widReset(WORD wDevID)
1555 dprintf_mciwave(stddeb,"widReset(%u);\n", wDevID);
1556 if (WInDev[wDevID].unixdev == 0) {
1557 dprintf_mciwave(stddeb,"Linux 'widReset' // can't reset !\n");
1558 return MMSYSERR_NOTENABLED;
1560 return MMSYSERR_NOERROR;
1563 /**************************************************************************
1564 * widGetPosition [internal]
1566 static DWORD widGetPosition(WORD wDevID, LPMMTIME lpTime, DWORD uSize)
1568 int time;
1570 dprintf_mciwave(stddeb,
1571 "widGetPosition(%u, %p, %lu);\n", wDevID, lpTime, uSize);
1572 if (WInDev[wDevID].unixdev == 0) {
1573 dprintf_mciwave(stddeb,"Linux 'widGetPosition' // can't get pos !\n");
1574 return MMSYSERR_NOTENABLED;
1576 if (lpTime == NULL) return MMSYSERR_INVALPARAM;
1577 dprintf_mciwave(stddeb,"widGetPosition // wType=%04X !\n",
1578 lpTime->wType);
1579 dprintf_mciwave(stddeb,"widGetPosition // wBitsPerSample=%u\n",
1580 WInDev[wDevID].Format.wBitsPerSample);
1581 dprintf_mciwave(stddeb,"widGetPosition // nSamplesPerSec=%lu\n",
1582 WInDev[wDevID].Format.wf.nSamplesPerSec);
1583 dprintf_mciwave(stddeb,"widGetPosition // nChannels=%u\n",
1584 WInDev[wDevID].Format.wf.nChannels);
1585 dprintf_mciwave(stddeb,"widGetPosition // nAvgBytesPerSec=%lu\n",
1586 WInDev[wDevID].Format.wf.nAvgBytesPerSec);
1587 fflush(stddeb);
1588 switch(lpTime->wType) {
1589 case TIME_BYTES:
1590 lpTime->u.cb = WInDev[wDevID].dwTotalRecorded;
1591 dprintf_mciwave(stddeb,
1592 "widGetPosition // TIME_BYTES=%lu\n", lpTime->u.cb);
1593 break;
1594 case TIME_SAMPLES:
1595 lpTime->u.sample = WInDev[wDevID].dwTotalRecorded * 8 /
1596 WInDev[wDevID].Format.wBitsPerSample;
1597 dprintf_mciwave(stddeb,
1598 "widGetPosition // TIME_SAMPLES=%lu\n",
1599 lpTime->u.sample);
1600 break;
1601 case TIME_SMPTE:
1602 time = WInDev[wDevID].dwTotalRecorded /
1603 (WInDev[wDevID].Format.wf.nAvgBytesPerSec / 1000);
1604 lpTime->u.smpte.hour = time / 108000;
1605 time -= lpTime->u.smpte.hour * 108000;
1606 lpTime->u.smpte.min = time / 1800;
1607 time -= lpTime->u.smpte.min * 1800;
1608 lpTime->u.smpte.sec = time / 30;
1609 time -= lpTime->u.smpte.sec * 30;
1610 lpTime->u.smpte.frame = time;
1611 lpTime->u.smpte.fps = 30;
1612 dprintf_mciwave(stddeb,"widGetPosition // TIME_SMPTE=%02u:%02u:%02u:%02u\n",
1613 lpTime->u.smpte.hour, lpTime->u.smpte.min,
1614 lpTime->u.smpte.sec, lpTime->u.smpte.frame);
1615 break;
1616 default:
1617 dprintf_mciwave(stddeb,"widGetPosition() format not supported ! use TIME_MS !\n");
1618 lpTime->wType = TIME_MS;
1619 case TIME_MS:
1620 lpTime->u.ms = WInDev[wDevID].dwTotalRecorded /
1621 (WInDev[wDevID].Format.wf.nAvgBytesPerSec / 1000);
1622 dprintf_mciwave(stddeb,
1623 "widGetPosition // TIME_MS=%lu\n", lpTime->u.ms);
1624 break;
1626 return MMSYSERR_NOERROR;
1629 #endif /* linux || __FreeBSD__ */
1631 /**************************************************************************
1632 * widMessage [sample driver]
1634 DWORD widMessage(WORD wDevID, WORD wMsg, DWORD dwUser,
1635 DWORD dwParam1, DWORD dwParam2)
1637 dprintf_mciwave(stddeb,"widMessage(%u, %04X, %08lX, %08lX, %08lX);\n",
1638 wDevID, wMsg, dwUser, dwParam1, dwParam2);
1639 #if defined(linux) || defined(__FreeBSD__)
1640 switch(wMsg) {
1641 case WIDM_OPEN:
1642 return widOpen(wDevID, (LPWAVEOPENDESC)PTR_SEG_TO_LIN(dwParam1), dwParam2);
1643 case WIDM_CLOSE:
1644 return widClose(wDevID);
1645 case WIDM_ADDBUFFER:
1646 return widAddBuffer(wDevID, (LPWAVEHDR)PTR_SEG_TO_LIN(dwParam1), dwParam2);
1647 case WIDM_PREPARE:
1648 return widPrepare(wDevID, (LPWAVEHDR)PTR_SEG_TO_LIN(dwParam1), dwParam2);
1649 case WIDM_UNPREPARE:
1650 return widUnprepare(wDevID, (LPWAVEHDR)PTR_SEG_TO_LIN(dwParam1), dwParam2);
1651 case WIDM_GETDEVCAPS:
1652 return widGetDevCaps(wDevID, (LPWAVEINCAPS)PTR_SEG_TO_LIN(dwParam1), dwParam2);
1653 case WIDM_GETNUMDEVS:
1654 return 1;
1655 case WIDM_GETPOS:
1656 return widGetPosition(wDevID, (LPMMTIME)PTR_SEG_TO_LIN(dwParam1), dwParam2);
1657 case WIDM_RESET:
1658 return widReset(wDevID);
1659 case WIDM_START:
1660 return widStart(wDevID);
1661 case WIDM_STOP:
1662 return widStop(wDevID);
1663 default:
1664 dprintf_mciwave(stddeb,"widMessage // unknown message !\n");
1666 return MMSYSERR_NOTSUPPORTED;
1667 #else
1668 return MMSYSERR_NOTENABLED;
1669 #endif
1673 /**************************************************************************
1674 * AUDIO_DriverProc [sample driver]
1676 LONG WAVE_DriverProc(DWORD dwDevID, HDRVR16 hDriv, WORD wMsg,
1677 DWORD dwParam1, DWORD dwParam2)
1679 #if defined(linux) || defined(__FreeBSD__)
1680 dprintf_mciwave(stddeb,"WAVE_DriverProc(%08lX, %04X, %04X, %08lX, %08lX)\n",
1681 dwDevID, hDriv, wMsg, dwParam1, dwParam2);
1682 switch(wMsg) {
1683 case DRV_LOAD:
1684 return 1;
1685 case DRV_FREE:
1686 return 1;
1687 case DRV_OPEN:
1688 return 1;
1689 case DRV_CLOSE:
1690 return 1;
1691 case DRV_ENABLE:
1692 return 1;
1693 case DRV_DISABLE:
1694 return 1;
1695 case DRV_QUERYCONFIGURE:
1696 return 1;
1697 case DRV_CONFIGURE:
1698 MessageBox16(0, "Sample MultiMedia Linux Driver !",
1699 "MMLinux Driver", MB_OK);
1700 return 1;
1701 case DRV_INSTALL:
1702 return DRVCNF_RESTART;
1703 case DRV_REMOVE:
1704 return DRVCNF_RESTART;
1705 case MCI_OPEN_DRIVER:
1706 case MCI_OPEN:
1707 return WAVE_mciOpen(dwDevID, dwParam1, (LPMCI_WAVE_OPEN_PARMS)PTR_SEG_TO_LIN(dwParam2));
1708 case MCI_CUE:
1709 return WAVE_mciCue(dwDevID, dwParam1, (LPMCI_GENERIC_PARMS)PTR_SEG_TO_LIN(dwParam2));
1710 case MCI_CLOSE_DRIVER:
1711 case MCI_CLOSE:
1712 return WAVE_mciClose(dwDevID, dwParam1, (LPMCI_GENERIC_PARMS)PTR_SEG_TO_LIN(dwParam2));
1713 case MCI_PLAY:
1714 return WAVE_mciPlay(dwDevID, dwParam1, (LPMCI_PLAY_PARMS)PTR_SEG_TO_LIN(dwParam2));
1715 case MCI_RECORD:
1716 return WAVE_mciRecord(dwDevID, dwParam1, (LPMCI_RECORD_PARMS)PTR_SEG_TO_LIN(dwParam2));
1717 case MCI_STOP:
1718 return WAVE_mciStop(dwDevID, dwParam1, (LPMCI_GENERIC_PARMS)PTR_SEG_TO_LIN(dwParam2));
1719 case MCI_SET:
1720 return WAVE_mciSet(dwDevID, dwParam1, (LPMCI_SET_PARMS)PTR_SEG_TO_LIN(dwParam2));
1721 case MCI_PAUSE:
1722 return WAVE_mciPause(dwDevID, dwParam1, (LPMCI_GENERIC_PARMS)PTR_SEG_TO_LIN(dwParam2));
1723 case MCI_RESUME:
1724 return WAVE_mciResume(dwDevID, dwParam1, (LPMCI_GENERIC_PARMS)PTR_SEG_TO_LIN(dwParam2));
1725 case MCI_STATUS:
1726 return WAVE_mciStatus(dwDevID, dwParam1, (LPMCI_STATUS_PARMS)PTR_SEG_TO_LIN(dwParam2));
1727 case MCI_GETDEVCAPS:
1728 return WAVE_mciGetDevCaps(dwDevID, dwParam1, (LPMCI_GETDEVCAPS_PARMS)PTR_SEG_TO_LIN(dwParam2));
1729 case MCI_INFO:
1730 return WAVE_mciInfo(dwDevID, dwParam1, (LPMCI_INFO_PARMS)PTR_SEG_TO_LIN(dwParam2));
1731 default:
1732 return DefDriverProc(dwDevID, hDriv, wMsg, dwParam1, dwParam2);
1734 #else
1735 return MMSYSERR_NOTENABLED;
1736 #endif