Release 970509
[wine/multimedia.git] / multimedia / audio.c
blob558466f2e526bb612bb92987041d2fab26fd613a
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 int MMSYSTEM_DevIDToIndex(UINT16);
31 #if defined(linux) || defined(__FreeBSD__)
32 #define SOUND_DEV "/dev/dsp"
34 #ifdef SOUND_VERSION
35 #define IOCTL(a,b,c) ((-1==ioctl(a,b,&c))&&(perror("ioctl:"#b":"#c),0))
36 #else
37 #define IOCTL(a,b,c) (c = ioctl(a,b,c) )
38 #endif
40 #define MAX_WAVOUTDRV 2
41 #define MAX_WAVINDRV 2
42 #define MAX_MCIWAVDRV 2
44 typedef struct {
45 int unixdev;
46 int state;
47 DWORD bufsize;
48 WAVEOPENDESC waveDesc;
49 WORD wFlags;
50 PCMWAVEFORMAT Format;
51 LPWAVEHDR lpQueueHdr;
52 DWORD dwTotalPlayed;
53 } LINUX_WAVEOUT;
55 typedef struct {
56 int unixdev;
57 int state;
58 DWORD bufsize; /* Linux '/dev/dsp' give us that size */
59 WAVEOPENDESC waveDesc;
60 WORD wFlags;
61 PCMWAVEFORMAT Format;
62 LPWAVEHDR lpQueueHdr;
63 DWORD dwTotalRecorded;
64 } LINUX_WAVEIN;
66 typedef struct {
67 int nUseCount; /* Incremented for each shared open */
68 BOOL16 fShareable; /* TRUE if first open was shareable */
69 WORD wNotifyDeviceID; /* MCI device ID with a pending notification */
70 HANDLE16 hCallback; /* Callback handle for pending notification */
71 HMMIO16 hFile; /* mmio file handle open as Element */
72 MCI_WAVE_OPEN_PARMS openParms;
73 PCMWAVEFORMAT WaveFormat;
74 WAVEHDR WaveHdr;
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 int index = MMSYSTEM_DevIDToIndex(wDevID);
90 if (WInDev[index].wFlags != DCB_NULL && !DriverCallback(
91 WInDev[index].waveDesc.dwCallBack, WInDev[index].wFlags,
92 WInDev[index].waveDesc.hWave, wMsg,
93 WInDev[index].waveDesc.dwInstance, dwParam1, dwParam2)) {
94 dprintf_mciwave(stddeb,"WAVE_NotifyClient // can't notify client !\n");
95 return MMSYSERR_NOERROR;
97 return 0;
101 /**************************************************************************
102 * WAVE_mciOpen */
103 static DWORD WAVE_mciOpen(UINT16 wDevID, DWORD dwFlags, LPMCI_WAVE_OPEN_PARMS lpParms)
105 int index = MMSYSTEM_DevIDToIndex(wDevID);
106 HLOCAL16 hFormat;
107 LPPCMWAVEFORMAT lpWaveFormat;
108 HLOCAL16 hDesc;
109 LPWAVEOPENDESC lpDesc;
110 LPSTR lpstrElementName;
111 DWORD dwRet;
112 char str[128];
114 dprintf_mciwave(stddeb,"WAVE_mciOpen(%04X, %08lX, %p)\n",
115 wDevID, dwFlags, lpParms);
116 if (lpParms == NULL) return MCIERR_INTERNAL;
118 wDevID = lpParms->wDeviceID;
119 index = MMSYSTEM_DevIDToIndex(wDevID);
121 if (MCIWavDev[index].nUseCount > 0) {
122 /* The driver already open on this channel */
123 /* If the driver was opened shareable before and this open specifies */
124 /* shareable then increment the use count */
125 if (MCIWavDev[index].fShareable && (dwFlags & MCI_OPEN_SHAREABLE))
126 ++MCIWavDev[index].nUseCount;
127 else
128 return MCIERR_MUST_USE_SHAREABLE;
130 else {
131 MCIWavDev[index].nUseCount = 1;
132 MCIWavDev[index].fShareable = dwFlags & MCI_OPEN_SHAREABLE;
134 lpParms->wDeviceID = wDevID;
135 dprintf_mciwave(stddeb,"WAVE_mciOpen // wDevID=%04X\n", wDevID);
136 dprintf_mciwave(stddeb,"WAVE_mciOpen // before OPEN_ELEMENT\n");
137 if (dwFlags & MCI_OPEN_ELEMENT) {
138 lpstrElementName = (LPSTR)PTR_SEG_TO_LIN(lpParms->lpstrElementName);
139 dprintf_mciwave(stddeb,"WAVE_mciOpen // MCI_OPEN_ELEMENT '%s' !\n",
140 lpstrElementName);
141 if (strlen(lpstrElementName) > 0) {
142 strcpy(str, lpstrElementName);
143 CharUpper32A(str);
144 MCIWavDev[index].hFile = mmioOpen(str, NULL,
145 MMIO_ALLOCBUF | MMIO_READWRITE | MMIO_EXCLUSIVE);
146 if (MCIWavDev[index].hFile == 0) {
147 dprintf_mciwave(stddeb,"WAVE_mciOpen // can't find file='%s' !\n", str);
148 return MCIERR_FILE_NOT_FOUND;
151 else
152 MCIWavDev[index].hFile = 0;
154 dprintf_mciwave(stddeb,"WAVE_mciOpen // hFile=%u\n", MCIWavDev[index].hFile);
155 memcpy(&MCIWavDev[index].openParms, lpParms, sizeof(MCI_WAVE_OPEN_PARMS));
156 MCIWavDev[index].wNotifyDeviceID = lpParms->wDeviceID;
157 lpWaveFormat = &MCIWavDev[index].WaveFormat;
158 hDesc = USER_HEAP_ALLOC(sizeof(WAVEOPENDESC));
159 lpDesc = (LPWAVEOPENDESC) USER_HEAP_LIN_ADDR(hDesc);
160 lpDesc->hWave = 0;
162 lpWaveFormat->wf.wFormatTag = WAVE_FORMAT_PCM;
163 lpWaveFormat->wBitsPerSample = 8;
164 lpWaveFormat->wf.nChannels = 1;
165 lpWaveFormat->wf.nSamplesPerSec = 11025;
166 lpWaveFormat->wf.nAvgBytesPerSec = 11025;
167 lpWaveFormat->wf.nBlockAlign = 1;
169 if (MCIWavDev[index].hFile != 0) {
170 MMCKINFO mmckInfo;
171 MMCKINFO ckMainRIFF;
172 if (mmioDescend(MCIWavDev[index].hFile, &ckMainRIFF, NULL, 0) != 0) {
173 return MCIERR_INTERNAL;
175 dprintf_mciwave(stddeb,
176 "WAVE_mciOpen // ParentChunk ckid=%.4s fccType=%.4s cksize=%08lX \n",
177 (LPSTR)&ckMainRIFF.ckid, (LPSTR)&ckMainRIFF.fccType,
178 ckMainRIFF.cksize);
179 if ((ckMainRIFF.ckid != FOURCC_RIFF) ||
180 (ckMainRIFF.fccType != mmioFOURCC('W', 'A', 'V', 'E'))) {
181 return MCIERR_INTERNAL;
183 mmckInfo.ckid = mmioFOURCC('f', 'm', 't', ' ');
184 if (mmioDescend(MCIWavDev[index].hFile, &mmckInfo, &ckMainRIFF, MMIO_FINDCHUNK) != 0) {
185 return MCIERR_INTERNAL;
187 dprintf_mciwave(stddeb,
188 "WAVE_mciOpen // Chunk Found ckid=%.4s fccType=%.4s cksize=%08lX \n",
189 (LPSTR)&mmckInfo.ckid, (LPSTR)&mmckInfo.fccType,
190 mmckInfo.cksize);
191 if (mmioRead(MCIWavDev[index].hFile, (HPSTR) lpWaveFormat,
192 (long) sizeof(PCMWAVEFORMAT)) != (long) sizeof(PCMWAVEFORMAT)) {
193 return MCIERR_INTERNAL;
195 mmckInfo.ckid = mmioFOURCC('d', 'a', 't', 'a');
196 if (mmioDescend(MCIWavDev[index].hFile, &mmckInfo, &ckMainRIFF, MMIO_FINDCHUNK) != 0) {
197 return MCIERR_INTERNAL;
199 dprintf_mciwave(stddeb,
200 "WAVE_mciOpen // Chunk Found ckid=%.4s fccType=%.4s cksize=%08lX \n",
201 (LPSTR)&mmckInfo.ckid, (LPSTR)&mmckInfo.fccType,
202 mmckInfo.cksize);
203 dprintf_mciwave(stddeb,
204 "WAVE_mciOpen // nChannels=%d nSamplesPerSec=%ld\n",
205 lpWaveFormat->wf.nChannels, lpWaveFormat->wf.nSamplesPerSec);
206 lpWaveFormat->wBitsPerSample = 0;
208 lpWaveFormat->wf.nAvgBytesPerSec =
209 lpWaveFormat->wf.nSamplesPerSec * lpWaveFormat->wf.nBlockAlign;
210 hFormat = USER_HEAP_ALLOC(sizeof(PCMWAVEFORMAT));
211 lpDesc->lpFormat = (LPWAVEFORMAT) USER_HEAP_LIN_ADDR(hFormat);
212 memcpy(lpDesc->lpFormat, lpWaveFormat, sizeof(PCMWAVEFORMAT));
213 lpDesc = (LPWAVEOPENDESC) USER_HEAP_SEG_ADDR(hDesc);
214 dwRet = wodMessage(index, WODM_OPEN, 0, (DWORD)lpDesc, CALLBACK_NULL);
215 dwRet = widMessage(index, WIDM_OPEN, 0, (DWORD)lpDesc, CALLBACK_NULL);
216 USER_HEAP_FREE(hFormat);
217 USER_HEAP_FREE(hDesc);
218 return 0;
221 /**************************************************************************
222 * WAVE_mciClose [internal]
224 static DWORD WAVE_mciClose(UINT16 wDevID, DWORD dwParam, LPMCI_GENERIC_PARMS lpParms)
226 int index = MMSYSTEM_DevIDToIndex(wDevID);
227 DWORD dwRet;
228 dprintf_mciwave(stddeb,
229 "WAVE_mciClose(%u, %08lX, %p);\n", wDevID, dwParam, lpParms);
230 MCIWavDev[index].nUseCount--;
231 if (MCIWavDev[index].nUseCount == 0) {
232 if (MCIWavDev[index].hFile != 0) {
233 mmioClose(MCIWavDev[index].hFile, 0);
234 MCIWavDev[index].hFile = 0;
236 dwRet = wodMessage(index, WODM_CLOSE, 0, 0L, 0L);
237 if (dwRet != MMSYSERR_NOERROR) return MCIERR_INTERNAL;
238 dwRet = widMessage(index, WIDM_CLOSE, 0, 0L, 0L);
239 if (dwRet != MMSYSERR_NOERROR) return MCIERR_INTERNAL;
241 return 0;
245 /**************************************************************************
246 * WAVE_mciPlay [internal]
248 static DWORD WAVE_mciPlay(UINT16 wDevID, DWORD dwFlags, LPMCI_PLAY_PARMS lpParms)
250 int index = MMSYSTEM_DevIDToIndex(wDevID);
251 int start, end;
252 LONG bufsize, count;
253 HGLOBAL16 hData;
254 HLOCAL16 hWaveHdr;
255 LPWAVEHDR lpWaveHdr;
256 LPWAVEHDR lp16WaveHdr;
257 DWORD dwRet;
258 dprintf_mciwave(stddeb,
259 "WAVE_mciPlay(%u, %08lX, %p);\n", wDevID, dwFlags, lpParms);
260 if (MCIWavDev[index].hFile == 0) {
261 dprintf_mciwave(stddeb,"WAVE_mciPlay // can't find file='%08lx' !\n",
262 MCIWavDev[index].openParms.lpstrElementName);
263 return MCIERR_FILE_NOT_FOUND;
265 start = 1; end = 99999;
266 if (dwFlags & MCI_FROM) {
267 start = lpParms->dwFrom;
268 dprintf_mciwave(stddeb,
269 "WAVE_mciPlay // MCI_FROM=%d \n", start);
271 if (dwFlags & MCI_TO) {
272 end = lpParms->dwTo;
273 dprintf_mciwave(stddeb,"WAVE_mciPlay // MCI_TO=%d \n", end);
275 #if 0
276 if (dwFlags & MCI_NOTIFY) {
277 dprintf_mciwave(stddeb,
278 "WAVE_mciPlay // MCI_NOTIFY %08lX !\n", lpParms->dwCallback);
279 switch(fork()) {
280 case -1:
281 dprintf_mciwave(stddeb,
282 "WAVE_mciPlay // Can't 'fork' process !\n");
283 break;
284 case 0:
285 break;
286 default:
287 dprintf_mciwave(stddeb,"WAVE_mciPlay // process started ! return to caller...\n");
288 return 0;
291 #endif
292 bufsize = 64000;
293 lpWaveHdr = &MCIWavDev[index].WaveHdr;
294 hData = GlobalAlloc16(GMEM_MOVEABLE, bufsize);
295 lpWaveHdr->lpData = (LPSTR) WIN16_GlobalLock16(hData);
296 lpWaveHdr->dwUser = 0L;
297 lpWaveHdr->dwFlags = 0L;
298 lpWaveHdr->dwLoops = 0L;
299 hWaveHdr = USER_HEAP_ALLOC(sizeof(WAVEHDR));
300 lp16WaveHdr = (LPWAVEHDR) USER_HEAP_SEG_ADDR(hWaveHdr);
301 memcpy(PTR_SEG_TO_LIN(lp16WaveHdr), lpWaveHdr, sizeof(WAVEHDR));
302 lpWaveHdr = PTR_SEG_TO_LIN(lp16WaveHdr);
303 dwRet = wodMessage(index, WODM_PREPARE, 0, (DWORD)lp16WaveHdr, sizeof(WAVEHDR));
304 while(TRUE) {
305 count = mmioRead(MCIWavDev[index].hFile,
306 PTR_SEG_TO_LIN(lpWaveHdr->lpData), bufsize);
307 dprintf_mciwave(stddeb,"WAVE_mciPlay // mmioRead bufsize=%ld count=%ld\n", bufsize, count);
308 if (count < 1) break;
309 lpWaveHdr->dwBufferLength = count;
310 /* lpWaveHdr->dwBytesRecorded = count; */
311 dprintf_mciwave(stddeb,"WAVE_mciPlay // before WODM_WRITE lpWaveHdr=%p dwBufferLength=%lu dwBytesRecorded=%lu\n",
312 lpWaveHdr, lpWaveHdr->dwBufferLength, lpWaveHdr->dwBytesRecorded);
313 dwRet = wodMessage(index, WODM_WRITE, 0, (DWORD)lp16WaveHdr, sizeof(WAVEHDR));
315 dwRet = wodMessage(index, WODM_UNPREPARE, 0, (DWORD)lp16WaveHdr, sizeof(WAVEHDR));
316 if (lpWaveHdr->lpData != NULL) {
317 GlobalUnlock16(hData);
318 GlobalFree16(hData);
319 lpWaveHdr->lpData = NULL;
321 USER_HEAP_FREE(hWaveHdr);
322 if (dwFlags & MCI_NOTIFY) {
323 dprintf_mciwave(stddeb,"WAVE_mciPlay // MCI_NOTIFY_SUCCESSFUL %08lX !\n", lpParms->dwCallback);
324 mciDriverNotify((HWND16)LOWORD(lpParms->dwCallback),
325 MCIWavDev[index].wNotifyDeviceID, MCI_NOTIFY_SUCCESSFUL);
327 return 0;
331 /**************************************************************************
332 * WAVE_mciRecord [internal]
334 static DWORD WAVE_mciRecord(UINT16 wDevID, DWORD dwFlags, LPMCI_RECORD_PARMS lpParms)
336 int index = MMSYSTEM_DevIDToIndex(wDevID);
337 int start, end;
338 LONG bufsize;
339 HGLOBAL16 hData;
340 HLOCAL16 hWaveHdr;
341 LPWAVEHDR lpWaveHdr;
342 LPWAVEHDR lp16WaveHdr;
343 DWORD dwRet;
345 dprintf_mciwave(stddeb,
346 "WAVE_mciRecord(%u, %08lX, %p);\n", wDevID, dwFlags, lpParms);
347 if (MCIWavDev[index].hFile == 0) {
348 dprintf_mciwave(stddeb,"WAVE_mciRecord // can't find file='%08lx' !\n",
349 MCIWavDev[index].openParms.lpstrElementName);
350 return MCIERR_FILE_NOT_FOUND;
352 start = 1; end = 99999;
353 if (dwFlags & MCI_FROM) {
354 start = lpParms->dwFrom;
355 dprintf_mciwave(stddeb,
356 "WAVE_mciRecord // MCI_FROM=%d \n", start);
358 if (dwFlags & MCI_TO) {
359 end = lpParms->dwTo;
360 dprintf_mciwave(stddeb,"WAVE_mciRecord // MCI_TO=%d \n", end);
362 bufsize = 64000;
363 lpWaveHdr = &MCIWavDev[index].WaveHdr;
364 hData = GlobalAlloc16(GMEM_MOVEABLE, bufsize);
365 lpWaveHdr->lpData = (LPSTR) WIN16_GlobalLock16(hData);
366 lpWaveHdr->dwBufferLength = bufsize;
367 lpWaveHdr->dwUser = 0L;
368 lpWaveHdr->dwFlags = 0L;
369 lpWaveHdr->dwLoops = 0L;
370 hWaveHdr = USER_HEAP_ALLOC(sizeof(WAVEHDR));
371 lp16WaveHdr = (LPWAVEHDR) USER_HEAP_SEG_ADDR(hWaveHdr);
372 memcpy(PTR_SEG_TO_LIN(lp16WaveHdr), lpWaveHdr, sizeof(WAVEHDR));
373 lpWaveHdr = PTR_SEG_TO_LIN(lp16WaveHdr);
374 dwRet = widMessage(index, WIDM_PREPARE, 0, (DWORD)lp16WaveHdr, sizeof(WAVEHDR));
375 dprintf_mciwave(stddeb,"WAVE_mciRecord // after WIDM_PREPARE \n");
376 while(TRUE) {
377 lpWaveHdr->dwBytesRecorded = 0;
378 dwRet = widMessage(index, WIDM_START, 0, 0L, 0L);
379 dprintf_mciwave(stddeb,
380 "WAVE_mciRecord // after WIDM_START lpWaveHdr=%p dwBytesRecorded=%lu\n",
381 lpWaveHdr, lpWaveHdr->dwBytesRecorded);
382 if (lpWaveHdr->dwBytesRecorded == 0) break;
384 dprintf_mciwave(stddeb,"WAVE_mciRecord // before WIDM_UNPREPARE \n");
385 dwRet = widMessage(index, WIDM_UNPREPARE, 0, (DWORD)lp16WaveHdr, sizeof(WAVEHDR));
386 dprintf_mciwave(stddeb,"WAVE_mciRecord // after WIDM_UNPREPARE \n");
387 if (lpWaveHdr->lpData != NULL) {
388 GlobalUnlock16(hData);
389 GlobalFree16(hData);
390 lpWaveHdr->lpData = NULL;
392 USER_HEAP_FREE(hWaveHdr);
393 if (dwFlags & MCI_NOTIFY) {
394 dprintf_mciwave(stddeb,"WAVE_mciRecord // MCI_NOTIFY_SUCCESSFUL %08lX !\n", lpParms->dwCallback);
395 mciDriverNotify((HWND16)LOWORD(lpParms->dwCallback),
396 MCIWavDev[index].wNotifyDeviceID, MCI_NOTIFY_SUCCESSFUL);
398 return 0;
402 /**************************************************************************
403 * WAVE_mciStop [internal]
405 static DWORD WAVE_mciStop(UINT16 wDevID, DWORD dwFlags, LPMCI_GENERIC_PARMS lpParms)
407 dprintf_mciwave(stddeb,
408 "WAVE_mciStop(%u, %08lX, %p);\n", wDevID, dwFlags, lpParms);
409 if (lpParms == NULL) return MCIERR_INTERNAL;
410 return 0;
414 /**************************************************************************
415 * WAVE_mciPause [internal]
417 static DWORD WAVE_mciPause(UINT16 wDevID, DWORD dwFlags, LPMCI_GENERIC_PARMS lpParms)
419 dprintf_mciwave(stddeb,
420 "WAVE_mciPause(%u, %08lX, %p);\n", wDevID, dwFlags, lpParms);
421 if (lpParms == NULL) return MCIERR_INTERNAL;
422 return 0;
426 /**************************************************************************
427 * WAVE_mciResume [internal]
429 static DWORD WAVE_mciResume(UINT16 wDevID, DWORD dwFlags, LPMCI_GENERIC_PARMS lpParms)
431 dprintf_mciwave(stddeb,
432 "WAVE_mciResume(%u, %08lX, %p);\n", wDevID, dwFlags, lpParms);
433 if (lpParms == NULL) return MCIERR_INTERNAL;
434 return 0;
438 /**************************************************************************
439 * WAVE_mciSet [internal]
441 static DWORD WAVE_mciSet(UINT16 wDevID, DWORD dwFlags, LPMCI_SET_PARMS lpParms)
443 dprintf_mciwave(stddeb,
444 "WAVE_mciSet(%u, %08lX, %p);\n", wDevID, dwFlags, lpParms);
445 if (lpParms == NULL) return MCIERR_INTERNAL;
446 dprintf_mciwave(stddeb,
447 "WAVE_mciSet // dwTimeFormat=%08lX\n", lpParms->dwTimeFormat);
448 dprintf_mciwave(stddeb,
449 "WAVE_mciSet // dwAudio=%08lX\n", lpParms->dwAudio);
450 if (dwFlags & MCI_SET_TIME_FORMAT) {
451 switch (lpParms->dwTimeFormat) {
452 case MCI_FORMAT_MILLISECONDS:
453 dprintf_mciwave(stddeb, "WAVE_mciSet // MCI_FORMAT_MILLISECONDS !\n");
454 break;
455 case MCI_FORMAT_BYTES:
456 dprintf_mciwave(stddeb, "WAVE_mciSet // MCI_FORMAT_BYTES !\n");
457 break;
458 case MCI_FORMAT_SAMPLES:
459 dprintf_mciwave(stddeb, "WAVE_mciSet // MCI_FORMAT_SAMPLES !\n");
460 break;
461 default:
462 dprintf_mciwave(stddeb, "WAVE_mciSet // bad time format !\n");
463 return MCIERR_BAD_TIME_FORMAT;
466 if (dwFlags & MCI_SET_VIDEO) return MCIERR_UNSUPPORTED_FUNCTION;
467 if (dwFlags & MCI_SET_DOOR_OPEN) return MCIERR_UNSUPPORTED_FUNCTION;
468 if (dwFlags & MCI_SET_DOOR_CLOSED) return MCIERR_UNSUPPORTED_FUNCTION;
469 if (dwFlags & MCI_SET_AUDIO)
470 dprintf_mciwave(stddeb,"WAVE_mciSet // MCI_SET_AUDIO !\n");
471 if (dwFlags && MCI_SET_ON) {
472 dprintf_mciwave(stddeb,"WAVE_mciSet // MCI_SET_ON !\n");
473 if (dwFlags && MCI_SET_AUDIO_LEFT)
474 dprintf_mciwave(stddeb,"WAVE_mciSet // MCI_SET_AUDIO_LEFT !\n");
475 if (dwFlags && MCI_SET_AUDIO_RIGHT)
476 dprintf_mciwave(stddeb,"WAVE_mciSet // MCI_SET_AUDIO_RIGHT !\n");
478 if (dwFlags & MCI_SET_OFF)
479 dprintf_mciwave(stddeb,"WAVE_mciSet // MCI_SET_OFF !\n");
480 if (dwFlags & MCI_WAVE_INPUT)
481 dprintf_mciwave(stddeb,"WAVE_mciSet // MCI_WAVE_INPUT !\n");
482 if (dwFlags & MCI_WAVE_OUTPUT)
483 dprintf_mciwave(stddeb,"WAVE_mciSet // MCI_WAVE_OUTPUT !\n");
484 if (dwFlags & MCI_WAVE_SET_ANYINPUT)
485 dprintf_mciwave(stddeb,"WAVE_mciSet // MCI_WAVE_SET_ANYINPUT !\n");
486 if (dwFlags & MCI_WAVE_SET_ANYOUTPUT)
487 dprintf_mciwave(stddeb,"WAVE_mciSet // MCI_WAVE_SET_ANYOUTPUT !\n");
488 if (dwFlags & MCI_WAVE_SET_AVGBYTESPERSEC)
489 dprintf_mciwave(stddeb,
490 "WAVE_mciSet // MCI_WAVE_SET_AVGBYTESPERSEC !\n");
491 if (dwFlags & MCI_WAVE_SET_BITSPERSAMPLE)
492 dprintf_mciwave(stddeb,
493 "WAVE_mciSet // MCI_WAVE_SET_BITSPERSAMPLE !\n");
494 if (dwFlags & MCI_WAVE_SET_BLOCKALIGN)
495 dprintf_mciwave(stddeb,"WAVE_mciSet // MCI_WAVE_SET_BLOCKALIGN !\n");
496 if (dwFlags & MCI_WAVE_SET_CHANNELS)
497 dprintf_mciwave(stddeb,"WAVE_mciSet // MCI_WAVE_SET_CHANNELS !\n");
498 if (dwFlags & MCI_WAVE_SET_FORMATTAG)
499 dprintf_mciwave(stddeb,"WAVE_mciSet // MCI_WAVE_SET_FORMATTAG !\n");
500 if (dwFlags & MCI_WAVE_SET_SAMPLESPERSEC)
501 dprintf_mciwave(stddeb,
502 "WAVE_mciSet // MCI_WAVE_SET_SAMPLESPERSEC !\n");
503 return 0;
507 /**************************************************************************
508 * WAVE_mciStatus [internal]
510 static DWORD WAVE_mciStatus(UINT16 wDevID, DWORD dwFlags, LPMCI_STATUS_PARMS lpParms)
512 int index = MMSYSTEM_DevIDToIndex(wDevID);
513 dprintf_mciwave(stddeb,
514 "WAVE_mciStatus(%u, %08lX, %p);\n", wDevID, dwFlags, lpParms);
515 if (lpParms == NULL) return MCIERR_INTERNAL;
516 if (dwFlags & MCI_STATUS_ITEM) {
517 switch(lpParms->dwItem) {
518 case MCI_STATUS_CURRENT_TRACK:
519 lpParms->dwReturn = 1;
520 break;
521 case MCI_STATUS_LENGTH:
522 lpParms->dwReturn = 5555;
523 if (dwFlags & MCI_TRACK) {
524 lpParms->dwTrack = 1;
525 lpParms->dwReturn = 2222;
527 break;
528 case MCI_STATUS_MODE:
529 lpParms->dwReturn = MCI_MODE_STOP;
530 break;
531 case MCI_STATUS_MEDIA_PRESENT:
532 dprintf_mciwave(stddeb,"WAVE_mciStatus // MCI_STATUS_MEDIA_PRESENT !\n");
533 lpParms->dwReturn = TRUE;
534 break;
535 case MCI_STATUS_NUMBER_OF_TRACKS:
536 lpParms->dwReturn = 1;
537 break;
538 case MCI_STATUS_POSITION:
539 lpParms->dwReturn = 3333;
540 if (dwFlags & MCI_STATUS_START) {
541 lpParms->dwItem = 1;
543 if (dwFlags & MCI_TRACK) {
544 lpParms->dwTrack = 1;
545 lpParms->dwReturn = 777;
547 break;
548 case MCI_STATUS_READY:
549 dprintf_mciwave(stddeb,"WAVE_mciStatus // MCI_STATUS_READY !\n");
550 lpParms->dwReturn = TRUE;
551 break;
552 case MCI_STATUS_TIME_FORMAT:
553 dprintf_mciwave(stddeb,"WAVE_mciStatus // MCI_STATUS_TIME_FORMAT !\n");
554 lpParms->dwReturn = MCI_FORMAT_MILLISECONDS;
555 break;
556 case MCI_WAVE_INPUT:
557 dprintf_mciwave(stddeb,"WAVE_mciStatus // MCI_WAVE_INPUT !\n");
558 lpParms->dwReturn = 0;
559 break;
560 case MCI_WAVE_OUTPUT:
561 dprintf_mciwave(stddeb,"WAVE_mciStatus // MCI_WAVE_OUTPUT !\n");
562 lpParms->dwReturn = 0;
563 break;
564 case MCI_WAVE_STATUS_AVGBYTESPERSEC:
565 dprintf_mciwave(stddeb,"WAVE_mciStatus // MCI_WAVE_STATUS_AVGBYTESPERSEC !\n");
566 lpParms->dwReturn = 22050;
567 break;
568 case MCI_WAVE_STATUS_BITSPERSAMPLE:
569 dprintf_mciwave(stddeb,"WAVE_mciStatus // MCI_WAVE_STATUS_BITSPERSAMPLE !\n");
570 lpParms->dwReturn = 8;
571 break;
572 case MCI_WAVE_STATUS_BLOCKALIGN:
573 dprintf_mciwave(stddeb,"WAVE_mciStatus // MCI_WAVE_STATUS_BLOCKALIGN !\n");
574 lpParms->dwReturn = 1;
575 break;
576 case MCI_WAVE_STATUS_CHANNELS:
577 dprintf_mciwave(stddeb,"WAVE_mciStatus // MCI_WAVE_STATUS_CHANNELS !\n");
578 lpParms->dwReturn = 1;
579 break;
580 case MCI_WAVE_STATUS_FORMATTAG:
581 dprintf_mciwave(stddeb,"WAVE_mciStatus // MCI_WAVE_FORMATTAG !\n");
582 lpParms->dwReturn = WAVE_FORMAT_PCM;
583 break;
584 case MCI_WAVE_STATUS_LEVEL:
585 dprintf_mciwave(stddeb,"WAVE_mciStatus // MCI_WAVE_STATUS_LEVEL !\n");
586 lpParms->dwReturn = 0xAAAA5555;
587 break;
588 case MCI_WAVE_STATUS_SAMPLESPERSEC:
589 dprintf_mciwave(stddeb,"WAVE_mciStatus // MCI_WAVE_STATUS_SAMPLESPERSEC !\n");
590 lpParms->dwReturn = 22050;
591 break;
592 default:
593 dprintf_mciwave(stddeb,"WAVE_mciStatus // unknown command %08lX !\n", lpParms->dwItem);
594 return MCIERR_UNRECOGNIZED_COMMAND;
597 if (dwFlags & MCI_NOTIFY) {
598 dprintf_mciwave(stddeb,"WAVE_mciStatus // MCI_NOTIFY_SUCCESSFUL %08lX !\n", lpParms->dwCallback);
599 mciDriverNotify((HWND16)LOWORD(lpParms->dwCallback),
600 MCIWavDev[index].wNotifyDeviceID, MCI_NOTIFY_SUCCESSFUL);
602 return 0;
605 /**************************************************************************
606 * WAVE_mciGetDevCaps [internal]
608 static DWORD WAVE_mciGetDevCaps(UINT16 wDevID, DWORD dwFlags,
609 LPMCI_GETDEVCAPS_PARMS lpParms)
611 dprintf_mciwave(stddeb,
612 "WAVE_mciGetDevCaps(%u, %08lX, %p);\n", wDevID, dwFlags, lpParms);
613 if (lpParms == NULL) return MCIERR_INTERNAL;
614 if (dwFlags & MCI_GETDEVCAPS_ITEM) {
615 switch(lpParms->dwItem) {
616 case MCI_GETDEVCAPS_CAN_RECORD:
617 lpParms->dwReturn = TRUE;
618 break;
619 case MCI_GETDEVCAPS_HAS_AUDIO:
620 lpParms->dwReturn = TRUE;
621 break;
622 case MCI_GETDEVCAPS_HAS_VIDEO:
623 lpParms->dwReturn = FALSE;
624 break;
625 case MCI_GETDEVCAPS_DEVICE_TYPE:
626 lpParms->dwReturn = MCI_DEVTYPE_WAVEFORM_AUDIO;
627 break;
628 case MCI_GETDEVCAPS_USES_FILES:
629 lpParms->dwReturn = TRUE;
630 break;
631 case MCI_GETDEVCAPS_COMPOUND_DEVICE:
632 lpParms->dwReturn = TRUE;
633 break;
634 case MCI_GETDEVCAPS_CAN_EJECT:
635 lpParms->dwReturn = FALSE;
636 break;
637 case MCI_GETDEVCAPS_CAN_PLAY:
638 lpParms->dwReturn = TRUE;
639 break;
640 case MCI_GETDEVCAPS_CAN_SAVE:
641 lpParms->dwReturn = TRUE;
642 break;
643 case MCI_WAVE_GETDEVCAPS_INPUTS:
644 lpParms->dwReturn = 1;
645 break;
646 case MCI_WAVE_GETDEVCAPS_OUTPUTS:
647 lpParms->dwReturn = 1;
648 break;
649 default:
650 return MCIERR_UNRECOGNIZED_COMMAND;
653 return 0;
656 /**************************************************************************
657 * WAVE_mciInfo [internal]
659 static DWORD WAVE_mciInfo(UINT16 wDevID, DWORD dwFlags, LPMCI_INFO_PARMS lpParms)
661 int index = MMSYSTEM_DevIDToIndex(wDevID);
662 dprintf_mciwave(stddeb,
663 "WAVE_mciInfo(%u, %08lX, %p);\n", wDevID, dwFlags, lpParms);
664 if (lpParms == NULL) return MCIERR_INTERNAL;
665 lpParms->lpstrReturn = NULL;
666 switch(dwFlags) {
667 case MCI_INFO_PRODUCT:
668 lpParms->lpstrReturn = "Linux Sound System 0.5";
669 break;
670 case MCI_INFO_FILE:
671 lpParms->lpstrReturn =
672 (LPSTR)MCIWavDev[index].openParms.lpstrElementName;
673 break;
674 case MCI_WAVE_INPUT:
675 lpParms->lpstrReturn = "Linux Sound System 0.5";
676 break;
677 case MCI_WAVE_OUTPUT:
678 lpParms->lpstrReturn = "Linux Sound System 0.5";
679 break;
680 default:
681 return MCIERR_UNRECOGNIZED_COMMAND;
683 if (lpParms->lpstrReturn != NULL)
684 lpParms->dwRetSize = strlen(lpParms->lpstrReturn);
685 else
686 lpParms->dwRetSize = 0;
687 return 0;
691 /*-----------------------------------------------------------------------*/
694 /**************************************************************************
695 * wodGetDevCaps [internal]
697 static DWORD wodGetDevCaps(WORD wDevID, LPWAVEOUTCAPS lpCaps, DWORD dwSize)
699 int audio;
700 int smplrate;
701 int samplesize = 16;
702 int dsp_stereo = 1;
703 int bytespersmpl;
704 dprintf_mciwave(stddeb,
705 "wodGetDevCaps(%u, %p, %lu);\n", wDevID, lpCaps, dwSize);
706 if (lpCaps == NULL) return MMSYSERR_NOTENABLED;
707 audio = open (SOUND_DEV, O_WRONLY, 0);
708 if (audio == -1) return MMSYSERR_NOTENABLED;
709 #ifdef EMULATE_SB16
710 lpCaps->wMid = 0x0002;
711 lpCaps->wPid = 0x0104;
712 strcpy(lpCaps->szPname, "SB16 Wave Out");
713 #else
714 lpCaps->wMid = 0x00FF; /* Manufac ID */
715 lpCaps->wPid = 0x0001; /* Product ID */
716 strcpy(lpCaps->szPname, "Linux WAVOUT Driver");
717 #endif
718 lpCaps->dwFormats = 0x00000000;
719 lpCaps->dwSupport = WAVECAPS_VOLUME;
720 lpCaps->wChannels = (IOCTL(audio, SNDCTL_DSP_STEREO, dsp_stereo) != 0) ? 1 : 2;
721 if (lpCaps->wChannels > 1) lpCaps->dwSupport |= WAVECAPS_LRVOLUME;
722 bytespersmpl = (IOCTL(audio, SNDCTL_DSP_SAMPLESIZE, samplesize) != 0) ? 1 : 2;
723 smplrate = 44100;
724 if (IOCTL(audio, SNDCTL_DSP_SPEED, smplrate) == 0) {
725 lpCaps->dwFormats |= WAVE_FORMAT_4M08;
726 if (lpCaps->wChannels > 1) lpCaps->dwFormats |= WAVE_FORMAT_4S08;
727 if (bytespersmpl > 1) {
728 lpCaps->dwFormats |= WAVE_FORMAT_4M16;
729 if (lpCaps->wChannels > 1) lpCaps->dwFormats |= WAVE_FORMAT_4S16;
732 smplrate = 22050;
733 if (IOCTL(audio, SNDCTL_DSP_SPEED, smplrate) == 0) {
734 lpCaps->dwFormats |= WAVE_FORMAT_2M08;
735 if (lpCaps->wChannels > 1) lpCaps->dwFormats |= WAVE_FORMAT_2S08;
736 if (bytespersmpl > 1) {
737 lpCaps->dwFormats |= WAVE_FORMAT_2M16;
738 if (lpCaps->wChannels > 1) lpCaps->dwFormats |= WAVE_FORMAT_2S16;
741 smplrate = 11025;
742 if (IOCTL(audio, SNDCTL_DSP_SPEED, smplrate) == 0) {
743 lpCaps->dwFormats |= WAVE_FORMAT_1M08;
744 if (lpCaps->wChannels > 1) lpCaps->dwFormats |= WAVE_FORMAT_1S08;
745 if (bytespersmpl > 1) {
746 lpCaps->dwFormats |= WAVE_FORMAT_1M16;
747 if (lpCaps->wChannels > 1) lpCaps->dwFormats |= WAVE_FORMAT_1S16;
750 close(audio);
751 dprintf_mciwave(stddeb,
752 "wodGetDevCaps // dwFormats = %08lX\n", lpCaps->dwFormats);
753 return MMSYSERR_NOERROR;
757 /**************************************************************************
758 * wodOpen [internal]
760 static DWORD wodOpen(WORD wDevID, LPWAVEOPENDESC lpDesc, DWORD dwFlags)
762 int audio;
763 int abuf_size;
764 int smplrate;
765 int samplesize;
766 int dsp_stereo;
767 LPWAVEFORMAT lpFormat;
769 dprintf_mciwave(stddeb,
770 "wodOpen(%u, %p, %08lX);\n", wDevID, lpDesc, dwFlags);
771 if (lpDesc == NULL) {
772 dprintf_mciwave(stddeb,"Linux 'wodOpen' // Invalid Parameter !\n");
773 return MMSYSERR_INVALPARAM;
775 if (wDevID >= MAX_WAVOUTDRV) {
776 dprintf_mciwave(stddeb,"Linux 'wodOpen' // MAX_WAVOUTDRV reached !\n");
777 return MMSYSERR_ALLOCATED;
779 WOutDev[wDevID].unixdev = 0;
780 audio = open (SOUND_DEV, O_WRONLY, 0);
781 if (audio == -1) {
782 dprintf_mciwave(stddeb,"Linux 'wodOpen' // can't open !\n");
783 return MMSYSERR_NOTENABLED;
785 IOCTL(audio, SNDCTL_DSP_GETBLKSIZE, abuf_size);
786 if (abuf_size < 1024 || abuf_size > 65536) {
787 if (abuf_size == -1)
788 dprintf_mciwave(stddeb,"Linux 'wodOpen' // IOCTL can't 'SNDCTL_DSP_GETBLKSIZE' !\n");
789 else
790 dprintf_mciwave(stddeb,"Linux 'wodOpen' // SNDCTL_DSP_GETBLKSIZE Invalid bufsize !\n");
791 return MMSYSERR_NOTENABLED;
793 WOutDev[wDevID].wFlags = HIWORD(dwFlags & CALLBACK_TYPEMASK);
794 switch(WOutDev[wDevID].wFlags) {
795 case DCB_NULL:
796 dprintf_mciwave(stddeb, "Linux 'wodOpen' // CALLBACK_NULL !\n");
797 break;
798 case DCB_WINDOW:
799 dprintf_mciwave(stddeb, "Linux 'wodOpen' // CALLBACK_WINDOW !\n");
800 break;
801 case DCB_TASK:
802 dprintf_mciwave(stddeb, "Linux 'wodOpen' // CALLBACK_TASK !\n");
803 break;
804 case DCB_FUNCTION:
805 dprintf_mciwave(stddeb, "Linux 'wodOpen' // CALLBACK_FUNCTION !\n");
806 break;
808 WOutDev[wDevID].lpQueueHdr = NULL;
809 WOutDev[wDevID].unixdev = audio;
810 WOutDev[wDevID].dwTotalPlayed = 0;
811 WOutDev[wDevID].bufsize = abuf_size;
812 memcpy(&WOutDev[wDevID].waveDesc, lpDesc, sizeof(WAVEOPENDESC));
813 lpFormat = (LPWAVEFORMAT) PTR_SEG_TO_LIN(lpDesc->lpFormat);
814 if (lpFormat->wFormatTag != WAVE_FORMAT_PCM) {
815 dprintf_mciwave(stddeb,"Linux 'wodOpen' // Bad format %04X !\n",
816 lpFormat->wFormatTag);
817 dprintf_mciwave(stddeb,"Linux 'wodOpen' // Bad nChannels %d !\n",
818 lpFormat->nChannels);
819 dprintf_mciwave(stddeb,"Linux 'wodOpen' // Bad nSamplesPerSec %ld !\n",
820 lpFormat->nSamplesPerSec);
821 return WAVERR_BADFORMAT;
823 memcpy(&WOutDev[wDevID].Format, lpFormat, sizeof(PCMWAVEFORMAT));
824 if (WOutDev[wDevID].Format.wf.nChannels == 0) return WAVERR_BADFORMAT;
825 if (WOutDev[wDevID].Format.wf.nSamplesPerSec == 0) return WAVERR_BADFORMAT;
826 dprintf_mciwave(stddeb,"Linux 'wodOpen' // wBitsPerSample=%u !\n",
827 WOutDev[wDevID].Format.wBitsPerSample);
828 if (WOutDev[wDevID].Format.wBitsPerSample == 0) {
829 WOutDev[wDevID].Format.wBitsPerSample = 8 *
830 (WOutDev[wDevID].Format.wf.nAvgBytesPerSec /
831 WOutDev[wDevID].Format.wf.nSamplesPerSec) /
832 WOutDev[wDevID].Format.wf.nChannels;
834 samplesize = WOutDev[wDevID].Format.wBitsPerSample;
835 smplrate = WOutDev[wDevID].Format.wf.nSamplesPerSec;
836 dsp_stereo = (WOutDev[wDevID].Format.wf.nChannels > 1) ? TRUE : FALSE;
837 IOCTL(audio, SNDCTL_DSP_SPEED, smplrate);
838 IOCTL(audio, SNDCTL_DSP_SAMPLESIZE, samplesize);
839 IOCTL(audio, SNDCTL_DSP_STEREO, dsp_stereo);
840 dprintf_mciwave(stddeb,"Linux 'wodOpen' // wBitsPerSample=%u !\n",
841 WOutDev[wDevID].Format.wBitsPerSample);
842 dprintf_mciwave(stddeb,"Linux 'wodOpen' // nAvgBytesPerSec=%lu !\n",
843 WOutDev[wDevID].Format.wf.nAvgBytesPerSec);
844 dprintf_mciwave(stddeb,"Linux 'wodOpen' // nSamplesPerSec=%lu !\n",
845 WOutDev[wDevID].Format.wf.nSamplesPerSec);
846 dprintf_mciwave(stddeb,"Linux 'wodOpen' // nChannels=%u !\n",
847 WOutDev[wDevID].Format.wf.nChannels);
848 if (WAVE_NotifyClient(wDevID, WOM_OPEN, 0L, 0L) != MMSYSERR_NOERROR) {
849 dprintf_mciwave(stddeb,"Linux 'wodOpen' // can't notify client !\n");
850 return MMSYSERR_INVALPARAM;
852 return MMSYSERR_NOERROR;
855 /**************************************************************************
856 * wodClose [internal]
858 static DWORD wodClose(WORD wDevID)
860 dprintf_mciwave(stddeb,"wodClose(%u);\n", wDevID);
861 if (WOutDev[wDevID].unixdev == 0) {
862 dprintf_mciwave(stddeb,"Linux 'wodClose' // can't close !\n");
863 return MMSYSERR_NOTENABLED;
865 close(WOutDev[wDevID].unixdev);
866 WOutDev[wDevID].unixdev = 0;
867 WOutDev[wDevID].bufsize = 0;
868 WOutDev[wDevID].lpQueueHdr = NULL;
869 if (WAVE_NotifyClient(wDevID, WOM_CLOSE, 0L, 0L) != MMSYSERR_NOERROR) {
870 dprintf_mciwave(stddeb,"Linux 'wodClose' // can't notify client !\n");
871 return MMSYSERR_INVALPARAM;
873 return MMSYSERR_NOERROR;
876 /**************************************************************************
877 * wodWrite [internal]
879 static DWORD wodWrite(WORD wDevID, LPWAVEHDR lpWaveHdr, DWORD dwSize)
881 int count;
882 LPSTR lpData;
883 dprintf_mciwave(stddeb,"wodWrite(%u, %p, %08lX);\n", wDevID, lpWaveHdr, dwSize);
884 if (WOutDev[wDevID].unixdev == 0) {
885 dprintf_mciwave(stddeb,"Linux 'wodWrite' // can't play !\n");
886 return MMSYSERR_NOTENABLED;
888 if (lpWaveHdr->lpData == NULL) return WAVERR_UNPREPARED;
889 if (!(lpWaveHdr->dwFlags & WHDR_PREPARED)) return WAVERR_UNPREPARED;
890 if (lpWaveHdr->dwFlags & WHDR_INQUEUE) return WAVERR_STILLPLAYING;
891 lpWaveHdr->dwFlags &= ~WHDR_DONE;
892 lpWaveHdr->dwFlags |= WHDR_INQUEUE;
893 dprintf_mciwave(stddeb,
894 "wodWrite() // dwBufferLength %lu !\n", lpWaveHdr->dwBufferLength);
895 dprintf_mciwave(stddeb,
896 "wodWrite() // WOutDev[%u].unixdev %u !\n", wDevID, WOutDev[wDevID].unixdev);
897 lpData = PTR_SEG_TO_LIN(lpWaveHdr->lpData);
898 count = write (WOutDev[wDevID].unixdev, lpData, lpWaveHdr->dwBufferLength);
899 dprintf_mciwave(stddeb,
900 "wodWrite() // write returned count %u !\n", count);
901 if (count != lpWaveHdr->dwBufferLength) {
902 dprintf_mciwave(stddeb,"Linux 'wodWrite' // error writting !\n");
903 return MMSYSERR_NOTENABLED;
905 WOutDev[wDevID].dwTotalPlayed += count;
906 lpWaveHdr->dwFlags &= ~WHDR_INQUEUE;
907 lpWaveHdr->dwFlags |= WHDR_DONE;
908 if (WAVE_NotifyClient(wDevID, WOM_DONE, 0L, 0L) != MMSYSERR_NOERROR) {
909 dprintf_mciwave(stddeb,"Linux 'wodWrite' // can't notify client !\n");
910 return MMSYSERR_INVALPARAM;
912 return MMSYSERR_NOERROR;
915 /**************************************************************************
916 * wodPrepare [internal]
918 static DWORD wodPrepare(WORD wDevID, LPWAVEHDR lpWaveHdr, DWORD dwSize)
920 dprintf_mciwave(stddeb,
921 "wodPrepare(%u, %p, %08lX);\n", wDevID, lpWaveHdr, dwSize);
922 if (WOutDev[wDevID].unixdev == 0) {
923 dprintf_mciwave(stddeb,"Linux 'wodPrepare' // can't prepare !\n");
924 return MMSYSERR_NOTENABLED;
926 /* the COOL waveeditor feels much better without this check...
927 * someone please have a look at available documentation
928 if (WOutDev[wDevID].lpQueueHdr != NULL) {
929 dprintf_mciwave(stddeb,"Linux 'wodPrepare' // already prepare !\n");
930 return MMSYSERR_NOTENABLED;
933 WOutDev[wDevID].dwTotalPlayed = 0;
934 WOutDev[wDevID].lpQueueHdr = lpWaveHdr;
935 if (lpWaveHdr->dwFlags & WHDR_INQUEUE) return WAVERR_STILLPLAYING;
936 lpWaveHdr->dwFlags |= WHDR_PREPARED;
937 lpWaveHdr->dwFlags &= ~WHDR_DONE;
938 return MMSYSERR_NOERROR;
941 /**************************************************************************
942 * wodUnprepare [internal]
944 static DWORD wodUnprepare(WORD wDevID, LPWAVEHDR lpWaveHdr, DWORD dwSize)
946 dprintf_mciwave(stddeb,
947 "wodUnprepare(%u, %p, %08lX);\n", wDevID, lpWaveHdr, dwSize);
948 if (WOutDev[wDevID].unixdev == 0) {
949 dprintf_mciwave(stddeb,"Linux 'wodUnprepare' // can't unprepare !\n");
950 return MMSYSERR_NOTENABLED;
952 return MMSYSERR_NOERROR;
955 /**************************************************************************
956 * wodRestart [internal]
958 static DWORD wodRestart(WORD wDevID)
960 dprintf_mciwave(stddeb,"wodRestart(%u);\n", wDevID);
961 if (WOutDev[wDevID].unixdev == 0) {
962 dprintf_mciwave(stddeb,"Linux 'wodRestart' // can't restart !\n");
963 return MMSYSERR_NOTENABLED;
965 return MMSYSERR_NOERROR;
968 /**************************************************************************
969 * wodReset [internal]
971 static DWORD wodReset(WORD wDevID)
973 dprintf_mciwave(stddeb,"wodReset(%u);\n", wDevID);
974 if (WOutDev[wDevID].unixdev == 0) {
975 dprintf_mciwave(stddeb,"Linux 'wodReset' // can't reset !\n");
976 return MMSYSERR_NOTENABLED;
978 return MMSYSERR_NOERROR;
982 /**************************************************************************
983 * wodGetPosition [internal]
985 static DWORD wodGetPosition(WORD wDevID, LPMMTIME lpTime, DWORD uSize)
987 int time;
988 dprintf_mciwave(stddeb,"wodGetPosition(%u, %p, %lu);\n", wDevID, lpTime, uSize);
989 if (WOutDev[wDevID].unixdev == 0) {
990 dprintf_mciwave(stddeb,"Linux 'wodGetPosition' // can't get pos !\n");
991 return MMSYSERR_NOTENABLED;
993 if (lpTime == NULL) return MMSYSERR_INVALPARAM;
994 switch(lpTime->wType) {
995 case TIME_BYTES:
996 lpTime->u.cb = WOutDev[wDevID].dwTotalPlayed;
997 dprintf_mciwave(stddeb,"wodGetPosition // TIME_BYTES=%lu\n", lpTime->u.cb);
998 break;
999 case TIME_SAMPLES:
1000 dprintf_mciwave(stddeb,"wodGetPosition // dwTotalPlayed=%lu\n",
1001 WOutDev[wDevID].dwTotalPlayed);
1002 dprintf_mciwave(stddeb,"wodGetPosition // wBitsPerSample=%u\n",
1003 WOutDev[wDevID].Format.wBitsPerSample);
1004 lpTime->u.sample = WOutDev[wDevID].dwTotalPlayed * 8 /
1005 WOutDev[wDevID].Format.wBitsPerSample;
1006 dprintf_mciwave(stddeb,"wodGetPosition // TIME_SAMPLES=%lu\n", lpTime->u.sample);
1007 break;
1008 case TIME_SMPTE:
1009 time = WOutDev[wDevID].dwTotalPlayed /
1010 (WOutDev[wDevID].Format.wf.nAvgBytesPerSec / 1000);
1011 lpTime->u.smpte.hour = time / 108000;
1012 time -= lpTime->u.smpte.hour * 108000;
1013 lpTime->u.smpte.min = time / 1800;
1014 time -= lpTime->u.smpte.min * 1800;
1015 lpTime->u.smpte.sec = time / 30;
1016 time -= lpTime->u.smpte.sec * 30;
1017 lpTime->u.smpte.frame = time;
1018 lpTime->u.smpte.fps = 30;
1019 dprintf_mciwave(stddeb,
1020 "wodGetPosition // TIME_SMPTE=%02u:%02u:%02u:%02u\n",
1021 lpTime->u.smpte.hour, lpTime->u.smpte.min,
1022 lpTime->u.smpte.sec, lpTime->u.smpte.frame);
1023 break;
1024 default:
1025 dprintf_mciwave(stddeb,"wodGetPosition() format not supported ! use TIME_MS !\n");
1026 lpTime->wType = TIME_MS;
1027 case TIME_MS:
1028 lpTime->u.ms = WOutDev[wDevID].dwTotalPlayed /
1029 (WOutDev[wDevID].Format.wf.nAvgBytesPerSec / 1000);
1030 dprintf_mciwave(stddeb,"wodGetPosition // TIME_MS=%lu\n", lpTime->u.ms);
1031 break;
1033 return MMSYSERR_NOERROR;
1036 /**************************************************************************
1037 * wodGetVolume [internal]
1039 static DWORD wodGetVolume(WORD wDevID, LPDWORD lpdwVol)
1041 int mixer;
1042 int volume, left, right;
1043 dprintf_mciwave(stddeb,"wodGetVolume(%u, %p);\n", wDevID, lpdwVol);
1044 if (lpdwVol == NULL) return MMSYSERR_NOTENABLED;
1045 if ((mixer = open("/dev/mixer", O_RDONLY)) < 0) {
1046 dprintf_mciwave(stddeb, "Linux 'wodGetVolume' // mixer device not available !\n");
1047 return MMSYSERR_NOTENABLED;
1049 if (ioctl(mixer, SOUND_MIXER_READ_PCM, &volume) == -1) {
1050 dprintf_mciwave(stddeb,"Linux 'wodGetVolume' // unable read mixer !\n");
1051 return MMSYSERR_NOTENABLED;
1053 close(mixer);
1054 left = volume & 0x7F;
1055 right = (volume >> 8) & 0x7F;
1056 printf("Linux 'AUX_GetVolume' // left=%d right=%d !\n", left, right);
1057 *lpdwVol = MAKELONG(left << 9, right << 9);
1058 return MMSYSERR_NOERROR;
1062 /**************************************************************************
1063 * wodSetVolume [internal]
1065 static DWORD wodSetVolume(WORD wDevID, DWORD dwParam)
1067 int mixer;
1068 int volume;
1069 dprintf_mciwave(stddeb,"wodSetVolume(%u, %08lX);\n", wDevID, dwParam);
1070 volume = (LOWORD(dwParam) >> 9 & 0x7F) +
1071 ((HIWORD(dwParam) >> 9 & 0x7F) << 8);
1072 if ((mixer = open("/dev/mixer", O_WRONLY)) < 0) {
1073 dprintf_mciwave(stddeb, "Linux 'wodSetVolume' // mixer device not available !\n");
1074 return MMSYSERR_NOTENABLED;
1076 if (ioctl(mixer, SOUND_MIXER_WRITE_PCM, &volume) == -1) {
1077 dprintf_mciwave(stddeb,"Linux 'wodSetVolume' // unable set mixer !\n");
1078 return MMSYSERR_NOTENABLED;
1080 close(mixer);
1081 return MMSYSERR_NOERROR;
1084 #endif /* linux || __FreeBSD__*/
1086 /**************************************************************************
1087 * wodMessage [sample driver]
1089 DWORD wodMessage(WORD wDevID, WORD wMsg, DWORD dwUser,
1090 DWORD dwParam1, DWORD dwParam2)
1092 dprintf_mciwave(stddeb,"wodMessage(%u, %04X, %08lX, %08lX, %08lX);\n",
1093 wDevID, wMsg, dwUser, dwParam1, dwParam2);
1094 #if defined(linux) || defined(__FreeBSD__)
1095 switch(wMsg) {
1096 case WODM_OPEN:
1097 return wodOpen(wDevID, (LPWAVEOPENDESC)PTR_SEG_TO_LIN(dwParam1), dwParam2);
1098 case WODM_CLOSE:
1099 return wodClose(wDevID);
1100 case WODM_WRITE:
1101 return wodWrite(wDevID, (LPWAVEHDR)PTR_SEG_TO_LIN(dwParam1), dwParam2);
1102 case WODM_PAUSE:
1103 return 0L;
1104 case WODM_GETPOS:
1105 return wodGetPosition(wDevID, (LPMMTIME)PTR_SEG_TO_LIN(dwParam1), dwParam2);
1106 case WODM_BREAKLOOP:
1107 return 0L;
1108 case WODM_PREPARE:
1109 return wodPrepare(wDevID, (LPWAVEHDR)PTR_SEG_TO_LIN(dwParam1), dwParam2);
1110 case WODM_UNPREPARE:
1111 return wodUnprepare(wDevID, (LPWAVEHDR)PTR_SEG_TO_LIN(dwParam1), dwParam2);
1112 case WODM_GETDEVCAPS:
1113 return wodGetDevCaps(wDevID, (LPWAVEOUTCAPS)PTR_SEG_TO_LIN(dwParam1), dwParam2);
1114 case WODM_GETNUMDEVS:
1115 return 1L;
1116 case WODM_GETPITCH:
1117 return 0L;
1118 case WODM_SETPITCH:
1119 return 0L;
1120 case WODM_GETPLAYBACKRATE:
1121 return 0L;
1122 case WODM_SETPLAYBACKRATE:
1123 return 0L;
1124 case WODM_GETVOLUME:
1125 return wodGetVolume(wDevID, (LPDWORD)PTR_SEG_TO_LIN(dwParam1));
1126 case WODM_SETVOLUME:
1127 return wodSetVolume(wDevID, dwParam1);
1128 case WODM_RESTART:
1129 return wodRestart(wDevID);
1130 case WODM_RESET:
1131 return wodReset(wDevID);
1132 default:
1133 dprintf_mciwave(stddeb,"wodMessage // unknown message !\n");
1135 return MMSYSERR_NOTSUPPORTED;
1136 #else
1137 return MMSYSERR_NOTENABLED;
1138 #endif
1142 /*-----------------------------------------------------------------------*/
1144 #if defined(linux) || defined(__FreeBSD__)
1146 /**************************************************************************
1147 * widGetDevCaps [internal]
1149 static DWORD widGetDevCaps(WORD wDevID, LPWAVEINCAPS lpCaps, DWORD dwSize)
1151 int audio;
1152 int smplrate;
1153 int samplesize = 16;
1154 int dsp_stereo = 1;
1155 int bytespersmpl;
1156 dprintf_mciwave(stddeb,
1157 "widGetDevCaps(%u, %p, %lu);\n", wDevID, lpCaps, dwSize);
1158 if (lpCaps == NULL) return MMSYSERR_NOTENABLED;
1159 audio = open (SOUND_DEV, O_RDONLY, 0);
1160 if (audio == -1) return MMSYSERR_NOTENABLED;
1161 #ifdef EMULATE_SB16
1162 lpCaps->wMid = 0x0002;
1163 lpCaps->wPid = 0x0004;
1164 strcpy(lpCaps->szPname, "SB16 Wave Out");
1165 #else
1166 lpCaps->wMid = 0x00FF; /* Manufac ID */
1167 lpCaps->wPid = 0x0001; /* Product ID */
1168 strcpy(lpCaps->szPname, "Linux WAVIN Driver");
1169 #endif
1170 lpCaps->dwFormats = 0x00000000;
1171 lpCaps->wChannels = (IOCTL(audio, SNDCTL_DSP_STEREO, dsp_stereo) != 0) ? 1 : 2;
1172 bytespersmpl = (IOCTL(audio, SNDCTL_DSP_SAMPLESIZE, samplesize) != 0) ? 1 : 2;
1173 smplrate = 44100;
1174 if (IOCTL(audio, SNDCTL_DSP_SPEED, smplrate) == 0) {
1175 lpCaps->dwFormats |= WAVE_FORMAT_4M08;
1176 if (lpCaps->wChannels > 1) lpCaps->dwFormats |= WAVE_FORMAT_4S08;
1177 if (bytespersmpl > 1) {
1178 lpCaps->dwFormats |= WAVE_FORMAT_4M16;
1179 if (lpCaps->wChannels > 1) lpCaps->dwFormats |= WAVE_FORMAT_4S16;
1182 smplrate = 22050;
1183 if (IOCTL(audio, SNDCTL_DSP_SPEED, smplrate) == 0) {
1184 lpCaps->dwFormats |= WAVE_FORMAT_2M08;
1185 if (lpCaps->wChannels > 1) lpCaps->dwFormats |= WAVE_FORMAT_2S08;
1186 if (bytespersmpl > 1) {
1187 lpCaps->dwFormats |= WAVE_FORMAT_2M16;
1188 if (lpCaps->wChannels > 1) lpCaps->dwFormats |= WAVE_FORMAT_2S16;
1191 smplrate = 11025;
1192 if (IOCTL(audio, SNDCTL_DSP_SPEED, smplrate) == 0) {
1193 lpCaps->dwFormats |= WAVE_FORMAT_1M08;
1194 if (lpCaps->wChannels > 1) lpCaps->dwFormats |= WAVE_FORMAT_1S08;
1195 if (bytespersmpl > 1) {
1196 lpCaps->dwFormats |= WAVE_FORMAT_1M16;
1197 if (lpCaps->wChannels > 1) lpCaps->dwFormats |= WAVE_FORMAT_1S16;
1200 close(audio);
1201 dprintf_mciwave(stddeb,
1202 "widGetDevCaps // dwFormats = %08lX\n", lpCaps->dwFormats);
1203 return MMSYSERR_NOERROR;
1207 /**************************************************************************
1208 * widOpen [internal]
1210 static DWORD widOpen(WORD wDevID, LPWAVEOPENDESC lpDesc, DWORD dwFlags)
1212 int audio;
1213 int abuf_size;
1214 int smplrate;
1215 int samplesize;
1216 int dsp_stereo;
1217 LPWAVEFORMAT lpFormat;
1218 dprintf_mciwave(stddeb, "widOpen(%u, %p, %08lX);\n", wDevID, lpDesc, dwFlags);
1219 if (lpDesc == NULL) {
1220 dprintf_mciwave(stddeb,"Linux 'widOpen' // Invalid Parameter !\n");
1221 return MMSYSERR_INVALPARAM;
1223 if (wDevID >= MAX_WAVINDRV) {
1224 dprintf_mciwave(stddeb,"Linux 'widOpen' // MAX_WAVINDRV reached !\n");
1225 return MMSYSERR_ALLOCATED;
1227 WInDev[wDevID].unixdev = 0;
1228 audio = open (SOUND_DEV, O_RDONLY, 0);
1229 if (audio == -1) {
1230 dprintf_mciwave(stddeb,"Linux 'widOpen' // can't open !\n");
1231 return MMSYSERR_NOTENABLED;
1233 IOCTL(audio, SNDCTL_DSP_GETBLKSIZE, abuf_size);
1234 if (abuf_size < 1024 || abuf_size > 65536) {
1235 if (abuf_size == -1)
1236 dprintf_mciwave(stddeb,"Linux 'widOpen' // IOCTL can't 'SNDCTL_DSP_GETBLKSIZE' !\n");
1237 else
1238 dprintf_mciwave(stddeb,"Linux 'widOpen' // SNDCTL_DSP_GETBLKSIZE Invalid bufsize !\n");
1239 return MMSYSERR_NOTENABLED;
1241 WInDev[wDevID].wFlags = HIWORD(dwFlags & CALLBACK_TYPEMASK);
1242 switch(WInDev[wDevID].wFlags) {
1243 case DCB_NULL:
1244 dprintf_mciwave(stddeb, "Linux 'widOpen' // CALLBACK_NULL !\n");
1245 break;
1246 case DCB_WINDOW:
1247 dprintf_mciwave(stddeb, "Linux 'widOpen' // CALLBACK_WINDOW !\n");
1248 break;
1249 case DCB_TASK:
1250 dprintf_mciwave(stddeb, "Linux 'widOpen' // CALLBACK_TASK !\n");
1251 break;
1252 case DCB_FUNCTION:
1253 dprintf_mciwave(stddeb, "Linux 'widOpen' // CALLBACK_FUNCTION !\n");
1254 break;
1256 WInDev[wDevID].lpQueueHdr = NULL;
1257 WInDev[wDevID].unixdev = audio;
1258 WInDev[wDevID].bufsize = abuf_size;
1259 WInDev[wDevID].dwTotalRecorded = 0;
1260 memcpy(&WInDev[wDevID].waveDesc, lpDesc, sizeof(WAVEOPENDESC));
1261 lpFormat = lpDesc->lpFormat;
1262 if (lpFormat->wFormatTag != WAVE_FORMAT_PCM) {
1263 dprintf_mciwave(stddeb,"Linux 'widOpen' // Bad format %04X !\n",
1264 lpFormat->wFormatTag);
1265 return WAVERR_BADFORMAT;
1267 memcpy(&WInDev[wDevID].Format, lpFormat, sizeof(PCMWAVEFORMAT));
1268 WInDev[wDevID].Format.wBitsPerSample = 8; /* <-------------- */
1269 if (WInDev[wDevID].Format.wf.nChannels == 0) return WAVERR_BADFORMAT;
1270 if (WInDev[wDevID].Format.wf.nSamplesPerSec == 0) return WAVERR_BADFORMAT;
1271 if (WInDev[wDevID].Format.wBitsPerSample == 0) {
1272 WInDev[wDevID].Format.wBitsPerSample = 8 *
1273 (WInDev[wDevID].Format.wf.nAvgBytesPerSec /
1274 WInDev[wDevID].Format.wf.nSamplesPerSec) /
1275 WInDev[wDevID].Format.wf.nChannels;
1277 samplesize = WInDev[wDevID].Format.wBitsPerSample;
1278 smplrate = WInDev[wDevID].Format.wf.nSamplesPerSec;
1279 dsp_stereo = (WInDev[wDevID].Format.wf.nChannels > 1) ? TRUE : FALSE;
1280 IOCTL(audio, SNDCTL_DSP_SPEED, smplrate);
1281 IOCTL(audio, SNDCTL_DSP_SAMPLESIZE, samplesize);
1282 IOCTL(audio, SNDCTL_DSP_STEREO, dsp_stereo);
1283 dprintf_mciwave(stddeb,"Linux 'widOpen' // wBitsPerSample=%u !\n",
1284 WInDev[wDevID].Format.wBitsPerSample);
1285 dprintf_mciwave(stddeb,"Linux 'widOpen' // nSamplesPerSec=%lu !\n",
1286 WInDev[wDevID].Format.wf.nSamplesPerSec);
1287 dprintf_mciwave(stddeb,"Linux 'widOpen' // nChannels=%u !\n",
1288 WInDev[wDevID].Format.wf.nChannels);
1289 dprintf_mciwave(stddeb,"Linux 'widOpen' // nAvgBytesPerSec=%lu\n",
1290 WInDev[wDevID].Format.wf.nAvgBytesPerSec);
1291 if (WAVE_NotifyClient(wDevID, WIM_OPEN, 0L, 0L) != MMSYSERR_NOERROR) {
1292 dprintf_mciwave(stddeb,"Linux 'widOpen' // can't notify client !\n");
1293 return MMSYSERR_INVALPARAM;
1295 return MMSYSERR_NOERROR;
1298 /**************************************************************************
1299 * widClose [internal]
1301 static DWORD widClose(WORD wDevID)
1303 dprintf_mciwave(stddeb,"widClose(%u);\n", wDevID);
1304 if (WInDev[wDevID].unixdev == 0) {
1305 dprintf_mciwave(stddeb,"Linux 'widClose' // can't close !\n");
1306 return MMSYSERR_NOTENABLED;
1308 close(WInDev[wDevID].unixdev);
1309 WInDev[wDevID].unixdev = 0;
1310 WInDev[wDevID].bufsize = 0;
1311 if (WAVE_NotifyClient(wDevID, WIM_CLOSE, 0L, 0L) != MMSYSERR_NOERROR) {
1312 dprintf_mciwave(stddeb,"Linux 'widClose' // can't notify client !\n");
1313 return MMSYSERR_INVALPARAM;
1315 return MMSYSERR_NOERROR;
1318 /**************************************************************************
1319 * widAddBuffer [internal]
1321 static DWORD widAddBuffer(WORD wDevID, LPWAVEHDR lpWaveHdr, DWORD dwSize)
1323 int count = 1;
1324 LPWAVEHDR lpWIHdr;
1325 dprintf_mciwave(stddeb,
1326 "widAddBuffer(%u, %p, %08lX);\n", wDevID, lpWaveHdr, dwSize);
1327 if (WInDev[wDevID].unixdev == 0) {
1328 dprintf_mciwave(stddeb,"Linux 'widAddBuffer' // can't do it !\n");
1329 return MMSYSERR_NOTENABLED;
1331 if (!(lpWaveHdr->dwFlags & WHDR_PREPARED)) {
1332 dprintf_mciwave(stddeb, "Linux 'widAddBuffer' // never been prepared !\n");
1333 return WAVERR_UNPREPARED;
1335 if (lpWaveHdr->dwFlags & WHDR_INQUEUE) {
1336 dprintf_mciwave(stddeb, "Linux 'widAddBuffer' // header already in use !\n");
1337 return WAVERR_STILLPLAYING;
1339 lpWaveHdr->dwFlags |= WHDR_PREPARED;
1340 lpWaveHdr->dwFlags |= WHDR_INQUEUE;
1341 lpWaveHdr->dwFlags &= ~WHDR_DONE;
1342 lpWaveHdr->dwBytesRecorded = 0;
1343 if (WInDev[wDevID].lpQueueHdr == NULL) {
1344 /* begin the queue with a first header ... */
1345 WInDev[wDevID].lpQueueHdr = lpWaveHdr;
1346 WInDev[wDevID].dwTotalRecorded = 0;
1348 else {
1349 /* added to the queue, except if it's the one just prepared ... */
1350 lpWIHdr = WInDev[wDevID].lpQueueHdr;
1351 while (lpWIHdr->lpNext != NULL) {
1352 lpWIHdr = lpWIHdr->lpNext;
1353 count++;
1355 lpWIHdr->lpNext = lpWaveHdr;
1356 count++;
1358 dprintf_mciwave(stddeb,
1359 "widAddBuffer // buffer added ! (now %u in queue)\n", count);
1360 return MMSYSERR_NOERROR;
1363 /**************************************************************************
1364 * widPrepare [internal]
1366 static DWORD widPrepare(WORD wDevID, LPWAVEHDR lpWaveHdr, DWORD dwSize)
1368 dprintf_mciwave(stddeb,
1369 "widPrepare(%u, %p, %08lX);\n", wDevID, lpWaveHdr, dwSize);
1370 if (WInDev[wDevID].unixdev == 0) {
1371 dprintf_mciwave(stddeb,"Linux 'widPrepare' // can't prepare !\n");
1372 return MMSYSERR_NOTENABLED;
1374 if (WInDev[wDevID].lpQueueHdr != NULL) {
1375 dprintf_mciwave(stddeb,"Linux 'widPrepare' // already prepare !\n");
1376 return WAVERR_BADFORMAT;
1378 if (lpWaveHdr->dwFlags & WHDR_INQUEUE) return WAVERR_STILLPLAYING;
1379 lpWaveHdr->dwFlags |= WHDR_PREPARED;
1380 lpWaveHdr->dwFlags &= ~WHDR_INQUEUE;
1381 lpWaveHdr->dwFlags &= ~WHDR_DONE;
1382 lpWaveHdr->dwBytesRecorded = 0;
1383 dprintf_mciwave(stddeb,"Linux 'widPrepare' // header prepared !\n");
1384 return MMSYSERR_NOERROR;
1387 /**************************************************************************
1388 * widUnprepare [internal]
1390 static DWORD widUnprepare(WORD wDevID, LPWAVEHDR lpWaveHdr, DWORD dwSize)
1392 dprintf_mciwave(stddeb,
1393 "widUnprepare(%u, %p, %08lX);\n", wDevID, lpWaveHdr, dwSize);
1394 if (WInDev[wDevID].unixdev == 0) {
1395 dprintf_mciwave(stddeb,"Linux 'widUnprepare' // can't unprepare !\n");
1396 return MMSYSERR_NOTENABLED;
1398 lpWaveHdr->dwFlags &= ~WHDR_PREPARED;
1399 lpWaveHdr->dwFlags &= ~WHDR_INQUEUE;
1400 lpWaveHdr->dwFlags |= WHDR_DONE;
1401 WInDev[wDevID].lpQueueHdr = NULL;
1402 dprintf_mciwave(stddeb,
1403 "Linux 'widUnprepare' // all headers unprepared !\n");
1404 return MMSYSERR_NOERROR;
1407 /**************************************************************************
1408 * widStart [internal]
1410 static DWORD widStart(WORD wDevID)
1412 int count = 1;
1413 LPWAVEHDR lpWIHdr;
1414 dprintf_mciwave(stddeb,"widStart(%u);\n", wDevID);
1415 if (WInDev[wDevID].unixdev == 0) {
1416 dprintf_mciwave(stddeb, "Linux 'widStart' // can't start recording !\n");
1417 return MMSYSERR_NOTENABLED;
1419 if (WInDev[wDevID].lpQueueHdr == NULL ||
1420 WInDev[wDevID].lpQueueHdr->lpData == NULL) {
1421 dprintf_mciwave(stddeb,"Linux 'widStart' // never been prepared !\n");
1422 return WAVERR_UNPREPARED;
1424 lpWIHdr = WInDev[wDevID].lpQueueHdr;
1425 while(lpWIHdr != NULL) {
1426 lpWIHdr->dwBufferLength &= 0xFFFF;
1427 dprintf_mciwave(stddeb,
1428 "widStart // recording buf#%u=%p size=%lu \n",
1429 count, lpWIHdr->lpData, lpWIHdr->dwBufferLength);
1430 fflush(stddeb);
1431 read (WInDev[wDevID].unixdev,
1432 PTR_SEG_TO_LIN(lpWIHdr->lpData),
1433 lpWIHdr->dwBufferLength);
1434 lpWIHdr->dwBytesRecorded = lpWIHdr->dwBufferLength;
1435 WInDev[wDevID].dwTotalRecorded += lpWIHdr->dwBytesRecorded;
1436 lpWIHdr->dwFlags &= ~WHDR_INQUEUE;
1437 lpWIHdr->dwFlags |= WHDR_DONE;
1438 if (WAVE_NotifyClient(wDevID, WIM_DATA, (DWORD)lpWIHdr, 0L) !=
1439 MMSYSERR_NOERROR) {
1440 dprintf_mciwave(stddeb, "Linux 'widStart' // can't notify client !\n");
1441 return MMSYSERR_INVALPARAM;
1443 lpWIHdr = lpWIHdr->lpNext;
1444 count++;
1446 dprintf_mciwave(stddeb,"widStart // end of recording !\n");
1447 fflush(stdout);
1448 return MMSYSERR_NOERROR;
1451 /**************************************************************************
1452 * widStop [internal]
1454 static DWORD widStop(WORD wDevID)
1456 dprintf_mciwave(stddeb,"widStop(%u);\n", wDevID);
1457 if (WInDev[wDevID].unixdev == 0) {
1458 dprintf_mciwave(stddeb,"Linux 'widStop' // can't stop !\n");
1459 return MMSYSERR_NOTENABLED;
1461 return MMSYSERR_NOERROR;
1464 /**************************************************************************
1465 * widReset [internal]
1467 static DWORD widReset(WORD wDevID)
1469 dprintf_mciwave(stddeb,"widReset(%u);\n", wDevID);
1470 if (WInDev[wDevID].unixdev == 0) {
1471 dprintf_mciwave(stddeb,"Linux 'widReset' // can't reset !\n");
1472 return MMSYSERR_NOTENABLED;
1474 return MMSYSERR_NOERROR;
1477 /**************************************************************************
1478 * widGetPosition [internal]
1480 static DWORD widGetPosition(WORD wDevID, LPMMTIME lpTime, DWORD uSize)
1482 int time;
1484 dprintf_mciwave(stddeb,
1485 "widGetPosition(%u, %p, %lu);\n", wDevID, lpTime, uSize);
1486 if (WInDev[wDevID].unixdev == 0) {
1487 dprintf_mciwave(stddeb,"Linux 'widGetPosition' // can't get pos !\n");
1488 return MMSYSERR_NOTENABLED;
1490 if (lpTime == NULL) return MMSYSERR_INVALPARAM;
1491 dprintf_mciwave(stddeb,"widGetPosition // wType=%04X !\n",
1492 lpTime->wType);
1493 dprintf_mciwave(stddeb,"widGetPosition // wBitsPerSample=%u\n",
1494 WInDev[wDevID].Format.wBitsPerSample);
1495 dprintf_mciwave(stddeb,"widGetPosition // nSamplesPerSec=%lu\n",
1496 WInDev[wDevID].Format.wf.nSamplesPerSec);
1497 dprintf_mciwave(stddeb,"widGetPosition // nChannels=%u\n",
1498 WInDev[wDevID].Format.wf.nChannels);
1499 dprintf_mciwave(stddeb,"widGetPosition // nAvgBytesPerSec=%lu\n",
1500 WInDev[wDevID].Format.wf.nAvgBytesPerSec);
1501 fflush(stddeb);
1502 switch(lpTime->wType) {
1503 case TIME_BYTES:
1504 lpTime->u.cb = WInDev[wDevID].dwTotalRecorded;
1505 dprintf_mciwave(stddeb,
1506 "widGetPosition // TIME_BYTES=%lu\n", lpTime->u.cb);
1507 break;
1508 case TIME_SAMPLES:
1509 lpTime->u.sample = WInDev[wDevID].dwTotalRecorded * 8 /
1510 WInDev[wDevID].Format.wBitsPerSample;
1511 dprintf_mciwave(stddeb,
1512 "widGetPosition // TIME_SAMPLES=%lu\n",
1513 lpTime->u.sample);
1514 break;
1515 case TIME_SMPTE:
1516 time = WInDev[wDevID].dwTotalRecorded /
1517 (WInDev[wDevID].Format.wf.nAvgBytesPerSec / 1000);
1518 lpTime->u.smpte.hour = time / 108000;
1519 time -= lpTime->u.smpte.hour * 108000;
1520 lpTime->u.smpte.min = time / 1800;
1521 time -= lpTime->u.smpte.min * 1800;
1522 lpTime->u.smpte.sec = time / 30;
1523 time -= lpTime->u.smpte.sec * 30;
1524 lpTime->u.smpte.frame = time;
1525 lpTime->u.smpte.fps = 30;
1526 dprintf_mciwave(stddeb,"widGetPosition // TIME_SMPTE=%02u:%02u:%02u:%02u\n",
1527 lpTime->u.smpte.hour, lpTime->u.smpte.min,
1528 lpTime->u.smpte.sec, lpTime->u.smpte.frame);
1529 break;
1530 default:
1531 dprintf_mciwave(stddeb,"widGetPosition() format not supported ! use TIME_MS !\n");
1532 lpTime->wType = TIME_MS;
1533 case TIME_MS:
1534 lpTime->u.ms = WInDev[wDevID].dwTotalRecorded /
1535 (WInDev[wDevID].Format.wf.nAvgBytesPerSec / 1000);
1536 dprintf_mciwave(stddeb,
1537 "widGetPosition // TIME_MS=%lu\n", lpTime->u.ms);
1538 break;
1540 return MMSYSERR_NOERROR;
1543 #endif /* linux || __FreeBSD__ */
1545 /**************************************************************************
1546 * widMessage [sample driver]
1548 DWORD widMessage(WORD wDevID, WORD wMsg, DWORD dwUser,
1549 DWORD dwParam1, DWORD dwParam2)
1551 dprintf_mciwave(stddeb,"widMessage(%u, %04X, %08lX, %08lX, %08lX);\n",
1552 wDevID, wMsg, dwUser, dwParam1, dwParam2);
1553 #if defined(linux) || defined(__FreeBSD__)
1554 switch(wMsg) {
1555 case WIDM_OPEN:
1556 return widOpen(wDevID, (LPWAVEOPENDESC)PTR_SEG_TO_LIN(dwParam1), dwParam2);
1557 case WIDM_CLOSE:
1558 return widClose(wDevID);
1559 case WIDM_ADDBUFFER:
1560 return widAddBuffer(wDevID, (LPWAVEHDR)PTR_SEG_TO_LIN(dwParam1), dwParam2);
1561 case WIDM_PREPARE:
1562 return widPrepare(wDevID, (LPWAVEHDR)PTR_SEG_TO_LIN(dwParam1), dwParam2);
1563 case WIDM_UNPREPARE:
1564 return widUnprepare(wDevID, (LPWAVEHDR)PTR_SEG_TO_LIN(dwParam1), dwParam2);
1565 case WIDM_GETDEVCAPS:
1566 return widGetDevCaps(wDevID, (LPWAVEINCAPS)PTR_SEG_TO_LIN(dwParam1), dwParam2);
1567 case WIDM_GETNUMDEVS:
1568 return 1;
1569 case WIDM_GETPOS:
1570 return widGetPosition(wDevID, (LPMMTIME)PTR_SEG_TO_LIN(dwParam1), dwParam2);
1571 case WIDM_RESET:
1572 return widReset(wDevID);
1573 case WIDM_START:
1574 return widStart(wDevID);
1575 case WIDM_STOP:
1576 return widStop(wDevID);
1577 default:
1578 dprintf_mciwave(stddeb,"widMessage // unknown message !\n");
1580 return MMSYSERR_NOTSUPPORTED;
1581 #else
1582 return MMSYSERR_NOTENABLED;
1583 #endif
1587 /**************************************************************************
1588 * AUDIO_DriverProc [sample driver]
1590 LONG WAVE_DriverProc(DWORD dwDevID, HDRVR16 hDriv, WORD wMsg,
1591 DWORD dwParam1, DWORD dwParam2)
1593 #if defined(linux) || defined(__FreeBSD__)
1594 dprintf_mciwave(stddeb,"WAVE_DriverProc(%08lX, %04X, %04X, %08lX, %08lX)\n",
1595 dwDevID, hDriv, wMsg, dwParam1, dwParam2);
1596 switch(wMsg) {
1597 case DRV_LOAD:
1598 return 1;
1599 case DRV_FREE:
1600 return 1;
1601 case DRV_OPEN:
1602 return 1;
1603 case DRV_CLOSE:
1604 return 1;
1605 case DRV_ENABLE:
1606 return 1;
1607 case DRV_DISABLE:
1608 return 1;
1609 case DRV_QUERYCONFIGURE:
1610 return 1;
1611 case DRV_CONFIGURE:
1612 MessageBox16(0, "Sample MultiMedia Linux Driver !",
1613 "MMLinux Driver", MB_OK);
1614 return 1;
1615 case DRV_INSTALL:
1616 return DRVCNF_RESTART;
1617 case DRV_REMOVE:
1618 return DRVCNF_RESTART;
1619 case MCI_OPEN_DRIVER:
1620 case MCI_OPEN:
1621 return WAVE_mciOpen(dwDevID, dwParam1, (LPMCI_WAVE_OPEN_PARMS)PTR_SEG_TO_LIN(dwParam2));
1622 case MCI_CLOSE_DRIVER:
1623 case MCI_CLOSE:
1624 return WAVE_mciClose(dwDevID, dwParam1, (LPMCI_GENERIC_PARMS)PTR_SEG_TO_LIN(dwParam2));
1625 case MCI_PLAY:
1626 return WAVE_mciPlay(dwDevID, dwParam1, (LPMCI_PLAY_PARMS)PTR_SEG_TO_LIN(dwParam2));
1627 case MCI_RECORD:
1628 return WAVE_mciRecord(dwDevID, dwParam1, (LPMCI_RECORD_PARMS)PTR_SEG_TO_LIN(dwParam2));
1629 case MCI_STOP:
1630 return WAVE_mciStop(dwDevID, dwParam1, (LPMCI_GENERIC_PARMS)PTR_SEG_TO_LIN(dwParam2));
1631 case MCI_SET:
1632 return WAVE_mciSet(dwDevID, dwParam1, (LPMCI_SET_PARMS)PTR_SEG_TO_LIN(dwParam2));
1633 case MCI_PAUSE:
1634 return WAVE_mciPause(dwDevID, dwParam1, (LPMCI_GENERIC_PARMS)PTR_SEG_TO_LIN(dwParam2));
1635 case MCI_RESUME:
1636 return WAVE_mciResume(dwDevID, dwParam1, (LPMCI_GENERIC_PARMS)PTR_SEG_TO_LIN(dwParam2));
1637 case MCI_STATUS:
1638 return WAVE_mciStatus(dwDevID, dwParam1, (LPMCI_STATUS_PARMS)PTR_SEG_TO_LIN(dwParam2));
1639 case MCI_GETDEVCAPS:
1640 return WAVE_mciGetDevCaps(dwDevID, dwParam1, (LPMCI_GETDEVCAPS_PARMS)PTR_SEG_TO_LIN(dwParam2));
1641 case MCI_INFO:
1642 return WAVE_mciInfo(dwDevID, dwParam1, (LPMCI_INFO_PARMS)PTR_SEG_TO_LIN(dwParam2));
1643 default:
1644 return DefDriverProc(dwDevID, hDriv, wMsg, dwParam1, dwParam2);
1646 #else
1647 return MMSYSERR_NOTENABLED;
1648 #endif