Release 960712
[wine/multimedia.git] / multimedia / audio.c
blob8f941e90c8f361cb11d01519acbef9fe6584c166
1 /*
2 * Sample Wine Driver for Linux
4 * Copyright 1994 Martin Ayotte
5 */
7 #ifndef WINELIB
8 #define BUILTIN_MMSYSTEM
9 #endif
11 #ifdef BUILTIN_MMSYSTEM
13 #define EMULATE_SB16
15 #include <stdio.h>
16 #include <stdlib.h>
17 #include <unistd.h>
18 #include <fcntl.h>
19 #include <sys/ioctl.h>
20 #include "windows.h"
21 #include "user.h"
22 #include "driver.h"
23 #include "mmsystem.h"
24 #include "ldt.h"
25 #include "stackframe.h"
27 #ifdef linux
28 #include <linux/soundcard.h>
29 #endif
31 #include "stddebug.h"
32 #include "debug.h"
34 #ifdef linux
35 #define SOUND_DEV "/dev/dsp"
37 #ifdef SOUND_VERSION
38 #define IOCTL(a,b,c) ((-1==ioctl(a,b,&c))&&(perror("ioctl:"#b":"#c),0))
39 #else
40 #define IOCTL(a,b,c) (c = ioctl(a,b,c) )
41 #endif
43 #define MAX_WAVOUTDRV 2
44 #define MAX_WAVINDRV 2
45 #define MAX_MCIWAVDRV 2
47 typedef struct {
48 int unixdev;
49 int state;
50 DWORD bufsize;
51 WAVEOPENDESC waveDesc;
52 WORD wFlags;
53 PCMWAVEFORMAT Format;
54 LPWAVEHDR lpQueueHdr;
55 DWORD dwTotalPlayed;
56 } LINUX_WAVEOUT;
58 typedef struct {
59 int unixdev;
60 int state;
61 DWORD bufsize; /* Linux '/dev/dsp' give us that size */
62 WAVEOPENDESC waveDesc;
63 WORD wFlags;
64 PCMWAVEFORMAT Format;
65 LPWAVEHDR lpQueueHdr;
66 DWORD dwTotalRecorded;
67 } LINUX_WAVEIN;
69 typedef struct {
70 int nUseCount; /* Incremented for each shared open */
71 BOOL fShareable; /* TRUE if first open was shareable */
72 WORD wNotifyDeviceID; /* MCI device ID with a pending notification */
73 HANDLE hCallback; /* Callback handle for pending notification */
74 HMMIO hFile; /* mmio file handle open as Element */
75 MCI_WAVE_OPEN_PARMS openParms;
76 PCMWAVEFORMAT WaveFormat;
77 WAVEHDR WaveHdr;
78 } LINUX_MCIWAVE;
80 static LINUX_WAVEOUT WOutDev[MAX_WAVOUTDRV];
81 static LINUX_WAVEIN WInDev[MAX_WAVOUTDRV];
82 static LINUX_MCIWAVE MCIWavDev[MAX_MCIWAVDRV];
85 /**************************************************************************
86 * WAVE_NotifyClient [internal]
88 static DWORD WAVE_NotifyClient(UINT wDevID, WORD wMsg,
89 DWORD dwParam1, DWORD dwParam2)
91 if (WInDev[wDevID].wFlags != DCB_NULL && !DriverCallback(
92 WInDev[wDevID].waveDesc.dwCallBack, WInDev[wDevID].wFlags,
93 WInDev[wDevID].waveDesc.hWave, wMsg,
94 WInDev[wDevID].waveDesc.dwInstance, dwParam1, dwParam2)) {
95 dprintf_mciwave(stddeb,"WAVE_NotifyClient // can't notify client !\n");
96 return MMSYSERR_NOERROR;
98 return 0;
102 /**************************************************************************
103 * WAVE_mciOpen */
104 static DWORD WAVE_mciOpen(UINT wDevID, DWORD dwFlags, LPMCI_WAVE_OPEN_PARMS lpParms)
106 HANDLE hFormat;
107 LPPCMWAVEFORMAT lpWaveFormat;
108 HANDLE 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;
117 dprintf_mciwave(stddeb,"WAVE_mciOpen // wDevID=%04X\n", wDevID);
118 if (MCIWavDev[wDevID].nUseCount > 0) {
119 /* The driver already open on this channel */
120 /* If the driver was opened shareable before and this open specifies */
121 /* shareable then increment the use count */
122 if (MCIWavDev[wDevID].fShareable && (dwFlags & MCI_OPEN_SHAREABLE))
123 ++MCIWavDev[wDevID].nUseCount;
124 else
125 return MCIERR_MUST_USE_SHAREABLE;
127 else {
128 MCIWavDev[wDevID].nUseCount = 1;
129 MCIWavDev[wDevID].fShareable = dwFlags & MCI_OPEN_SHAREABLE;
131 lpParms->wDeviceID = wDevID;
132 dprintf_mciwave(stddeb,"WAVE_mciOpen // wDevID=%04X\n", wDevID);
133 dprintf_mciwave(stddeb,"WAVE_mciOpen // before OPEN_ELEMENT\n");
134 if (dwFlags & MCI_OPEN_ELEMENT) {
135 lpstrElementName = (LPSTR)PTR_SEG_TO_LIN(lpParms->lpstrElementName);
136 dprintf_mciwave(stddeb,"WAVE_mciOpen // MCI_OPEN_ELEMENT '%s' !\n",
137 lpstrElementName);
138 if (strlen(lpstrElementName) > 0) {
139 strcpy(str, lpstrElementName);
140 AnsiUpper(str);
141 MCIWavDev[wDevID].hFile = mmioOpen(str, NULL,
142 MMIO_ALLOCBUF | MMIO_READWRITE | MMIO_EXCLUSIVE);
143 if (MCIWavDev[wDevID].hFile == 0) {
144 dprintf_mciwave(stddeb,"WAVE_mciOpen // can't find file='%s' !\n", str);
145 return MCIERR_FILE_NOT_FOUND;
148 else
149 MCIWavDev[wDevID].hFile = 0;
151 dprintf_mciwave(stddeb,"WAVE_mciOpen // hFile=%u\n", MCIWavDev[wDevID].hFile);
152 memcpy(&MCIWavDev[wDevID].openParms, lpParms, sizeof(MCI_WAVE_OPEN_PARMS));
153 MCIWavDev[wDevID].wNotifyDeviceID = lpParms->wDeviceID;
154 lpWaveFormat = &MCIWavDev[wDevID].WaveFormat;
155 hDesc = USER_HEAP_ALLOC(sizeof(WAVEOPENDESC));
156 lpDesc = (LPWAVEOPENDESC) USER_HEAP_LIN_ADDR(hDesc);
157 lpDesc->hWave = 0;
159 lpWaveFormat->wf.wFormatTag = WAVE_FORMAT_PCM;
160 lpWaveFormat->wBitsPerSample = 8;
161 lpWaveFormat->wf.nChannels = 1;
162 lpWaveFormat->wf.nSamplesPerSec = 11025;
163 lpWaveFormat->wf.nAvgBytesPerSec = 11025;
164 lpWaveFormat->wf.nBlockAlign = 1;
166 if (MCIWavDev[wDevID].hFile != 0) {
167 MMCKINFO mmckInfo;
168 MMCKINFO ckMainRIFF;
169 if (mmioDescend(MCIWavDev[wDevID].hFile, &ckMainRIFF, NULL, 0) != 0) {
170 return MCIERR_INTERNAL;
172 dprintf_mciwave(stddeb,
173 "WAVE_mciOpen // ParentChunk ckid=%.4s fccType=%.4s cksize=%08lX \n",
174 (LPSTR)&ckMainRIFF.ckid, (LPSTR)&ckMainRIFF.fccType,
175 ckMainRIFF.cksize);
176 if ((ckMainRIFF.ckid != FOURCC_RIFF) ||
177 (ckMainRIFF.fccType != mmioFOURCC('W', 'A', 'V', 'E'))) {
178 return MCIERR_INTERNAL;
180 mmckInfo.ckid = mmioFOURCC('f', 'm', 't', ' ');
181 if (mmioDescend(MCIWavDev[wDevID].hFile, &mmckInfo, &ckMainRIFF, MMIO_FINDCHUNK) != 0) {
182 return MCIERR_INTERNAL;
184 dprintf_mciwave(stddeb,
185 "WAVE_mciOpen // Chunk Found ckid=%.4s fccType=%.4s cksize=%08lX \n",
186 (LPSTR)&mmckInfo.ckid, (LPSTR)&mmckInfo.fccType,
187 mmckInfo.cksize);
188 if (mmioRead(MCIWavDev[wDevID].hFile, (HPSTR) lpWaveFormat,
189 (long) sizeof(PCMWAVEFORMAT)) != (long) sizeof(PCMWAVEFORMAT)) {
190 return MCIERR_INTERNAL;
192 mmckInfo.ckid = mmioFOURCC('d', 'a', 't', 'a');
193 if (mmioDescend(MCIWavDev[wDevID].hFile, &mmckInfo, &ckMainRIFF, MMIO_FINDCHUNK) != 0) {
194 return MCIERR_INTERNAL;
196 dprintf_mciwave(stddeb,
197 "WAVE_mciOpen // Chunk Found ckid=%.4s fccType=%.4s cksize=%08lX \n",
198 (LPSTR)&mmckInfo.ckid, (LPSTR)&mmckInfo.fccType,
199 mmckInfo.cksize);
200 dprintf_mciwave(stddeb,
201 "WAVE_mciOpen // nChannels=%d nSamplesPerSec=%ld\n",
202 lpWaveFormat->wf.nChannels, lpWaveFormat->wf.nSamplesPerSec);
203 lpWaveFormat->wBitsPerSample = 0;
205 lpWaveFormat->wf.nAvgBytesPerSec =
206 lpWaveFormat->wf.nSamplesPerSec * lpWaveFormat->wf.nBlockAlign;
207 hFormat = USER_HEAP_ALLOC(sizeof(PCMWAVEFORMAT));
208 lpDesc->lpFormat = (LPWAVEFORMAT) USER_HEAP_LIN_ADDR(hFormat);
209 memcpy(lpDesc->lpFormat, lpWaveFormat, sizeof(PCMWAVEFORMAT));
210 lpDesc = (LPWAVEOPENDESC) USER_HEAP_SEG_ADDR(hDesc);
211 dwRet = wodMessage(0, WODM_OPEN, 0, (DWORD)lpDesc, CALLBACK_NULL);
212 dwRet = widMessage(0, WIDM_OPEN, 0, (DWORD)lpDesc, CALLBACK_NULL);
213 USER_HEAP_FREE(hFormat);
214 USER_HEAP_FREE(hDesc);
215 return 0;
218 /**************************************************************************
219 * WAVE_mciClose [internal]
221 static DWORD WAVE_mciClose(UINT wDevID, DWORD dwParam, LPMCI_GENERIC_PARMS lpParms)
223 DWORD dwRet;
224 dprintf_mciwave(stddeb,
225 "WAVE_mciClose(%u, %08lX, %p);\n", wDevID, dwParam, lpParms);
226 MCIWavDev[wDevID].nUseCount--;
227 if (MCIWavDev[wDevID].nUseCount == 0) {
228 if (MCIWavDev[wDevID].hFile != 0) {
229 mmioClose(MCIWavDev[wDevID].hFile, 0);
230 MCIWavDev[wDevID].hFile = 0;
232 dwRet = wodMessage(0, WODM_CLOSE, 0, 0L, 0L);
233 if (dwRet != MMSYSERR_NOERROR) return MCIERR_INTERNAL;
234 dwRet = widMessage(0, WIDM_CLOSE, 0, 0L, 0L);
235 if (dwRet != MMSYSERR_NOERROR) return MCIERR_INTERNAL;
237 return 0;
241 /**************************************************************************
242 * WAVE_mciPlay [internal]
244 static DWORD WAVE_mciPlay(UINT wDevID, DWORD dwFlags, LPMCI_PLAY_PARMS lpParms)
246 int start, end;
247 LONG bufsize, count;
248 HANDLE hData;
249 HANDLE hWaveHdr;
250 LPWAVEHDR lpWaveHdr;
251 LPWAVEHDR lp16WaveHdr;
252 DWORD dwRet;
253 dprintf_mciwave(stddeb,
254 "WAVE_mciPlay(%u, %08lX, %p);\n", wDevID, dwFlags, lpParms);
255 if (MCIWavDev[wDevID].hFile == 0) {
256 dprintf_mciwave(stddeb,"WAVE_mciPlay // can't find file='%s' !\n",
257 MCIWavDev[wDevID].openParms.lpstrElementName);
258 return MCIERR_FILE_NOT_FOUND;
260 start = 1; end = 99999;
261 if (dwFlags & MCI_FROM) {
262 start = lpParms->dwFrom;
263 dprintf_mciwave(stddeb,
264 "WAVE_mciPlay // MCI_FROM=%d \n", start);
266 if (dwFlags & MCI_TO) {
267 end = lpParms->dwTo;
268 dprintf_mciwave(stddeb,"WAVE_mciPlay // MCI_TO=%d \n", end);
270 #if 0
271 if (dwFlags & MCI_NOTIFY) {
272 dprintf_mciwave(stddeb,
273 "WAVE_mciPlay // MCI_NOTIFY %08lX !\n", lpParms->dwCallback);
274 switch(fork()) {
275 case -1:
276 dprintf_mciwave(stddeb,
277 "WAVE_mciPlay // Can't 'fork' process !\n");
278 break;
279 case 0:
280 break;
281 default:
282 dprintf_mciwave(stddeb,"WAVE_mciPlay // process started ! return to caller...\n");
283 return 0;
286 #endif
287 bufsize = 64000;
288 lpWaveHdr = &MCIWavDev[wDevID].WaveHdr;
289 hData = GlobalAlloc16(GMEM_MOVEABLE, bufsize);
290 lpWaveHdr->lpData = (LPSTR) WIN16_GlobalLock16(hData);
291 lpWaveHdr->dwUser = 0L;
292 lpWaveHdr->dwFlags = 0L;
293 lpWaveHdr->dwLoops = 0L;
294 hWaveHdr = USER_HEAP_ALLOC(sizeof(WAVEHDR));
295 lp16WaveHdr = (LPWAVEHDR) USER_HEAP_SEG_ADDR(hWaveHdr);
296 memcpy(PTR_SEG_TO_LIN(lp16WaveHdr), lpWaveHdr, sizeof(WAVEHDR));
297 lpWaveHdr = PTR_SEG_TO_LIN(lp16WaveHdr);
298 dwRet = wodMessage(0, WODM_PREPARE, 0, (DWORD)lp16WaveHdr, sizeof(WAVEHDR));
299 while(TRUE) {
300 count = mmioRead(MCIWavDev[wDevID].hFile,
301 PTR_SEG_TO_LIN(lpWaveHdr->lpData), bufsize);
302 dprintf_mciwave(stddeb,"WAVE_mciPlay // mmioRead bufsize=%ld count=%ld\n", bufsize, count);
303 if (count < 1) break;
304 lpWaveHdr->dwBufferLength = count;
305 /* lpWaveHdr->dwBytesRecorded = count; */
306 dprintf_mciwave(stddeb,"WAVE_mciPlay // before WODM_WRITE lpWaveHdr=%p dwBufferLength=%lu dwBytesRecorded=%lu\n",
307 lpWaveHdr, lpWaveHdr->dwBufferLength, lpWaveHdr->dwBytesRecorded);
308 dwRet = wodMessage(0, WODM_WRITE, 0, (DWORD)lp16WaveHdr, sizeof(WAVEHDR));
310 dwRet = wodMessage(0, WODM_UNPREPARE, 0, (DWORD)lp16WaveHdr, sizeof(WAVEHDR));
311 if (lpWaveHdr->lpData != NULL) {
312 GlobalUnlock16(hData);
313 GlobalFree16(hData);
314 lpWaveHdr->lpData = NULL;
316 USER_HEAP_FREE(hWaveHdr);
317 if (dwFlags & MCI_NOTIFY) {
318 dprintf_mciwave(stddeb,"WAVE_mciPlay // MCI_NOTIFY_SUCCESSFUL %08lX !\n", lpParms->dwCallback);
319 mciDriverNotify((HWND)LOWORD(lpParms->dwCallback),
320 MCIWavDev[wDevID].wNotifyDeviceID, MCI_NOTIFY_SUCCESSFUL);
322 return 0;
326 /**************************************************************************
327 * WAVE_mciRecord [internal]
329 static DWORD WAVE_mciRecord(UINT wDevID, DWORD dwFlags, LPMCI_RECORD_PARMS lpParms)
331 int start, end;
332 LONG bufsize;
333 HANDLE hData;
334 HANDLE hWaveHdr;
335 LPWAVEHDR lpWaveHdr;
336 LPWAVEHDR lp16WaveHdr;
337 DWORD dwRet;
339 dprintf_mciwave(stddeb,
340 "WAVE_mciRecord(%u, %08lX, %p);\n", wDevID, dwFlags, lpParms);
341 if (MCIWavDev[wDevID].hFile == 0) {
342 dprintf_mciwave(stddeb,"WAVE_mciRecord // can't find file='%s' !\n",
343 MCIWavDev[wDevID].openParms.lpstrElementName);
344 return MCIERR_FILE_NOT_FOUND;
346 start = 1; end = 99999;
347 if (dwFlags & MCI_FROM) {
348 start = lpParms->dwFrom;
349 dprintf_mciwave(stddeb,
350 "WAVE_mciRecord // MCI_FROM=%d \n", start);
352 if (dwFlags & MCI_TO) {
353 end = lpParms->dwTo;
354 dprintf_mciwave(stddeb,"WAVE_mciRecord // MCI_TO=%d \n", end);
356 bufsize = 64000;
357 lpWaveHdr = &MCIWavDev[wDevID].WaveHdr;
358 hData = GlobalAlloc16(GMEM_MOVEABLE, bufsize);
359 lpWaveHdr->lpData = (LPSTR) WIN16_GlobalLock16(hData);
360 lpWaveHdr->dwBufferLength = bufsize;
361 lpWaveHdr->dwUser = 0L;
362 lpWaveHdr->dwFlags = 0L;
363 lpWaveHdr->dwLoops = 0L;
364 hWaveHdr = USER_HEAP_ALLOC(sizeof(WAVEHDR));
365 lp16WaveHdr = (LPWAVEHDR) USER_HEAP_SEG_ADDR(hWaveHdr);
366 memcpy(PTR_SEG_TO_LIN(lp16WaveHdr), lpWaveHdr, sizeof(WAVEHDR));
367 lpWaveHdr = PTR_SEG_TO_LIN(lp16WaveHdr);
368 dwRet = widMessage(0, WIDM_PREPARE, 0, (DWORD)lp16WaveHdr, sizeof(WAVEHDR));
369 dprintf_mciwave(stddeb,"WAVE_mciRecord // after WIDM_PREPARE \n");
370 while(TRUE) {
371 lpWaveHdr->dwBytesRecorded = 0;
372 dwRet = widMessage(0, WIDM_START, 0, 0L, 0L);
373 dprintf_mciwave(stddeb,
374 "WAVE_mciRecord // after WIDM_START lpWaveHdr=%p dwBytesRecorded=%lu\n",
375 lpWaveHdr, lpWaveHdr->dwBytesRecorded);
376 if (lpWaveHdr->dwBytesRecorded == 0) break;
378 dprintf_mciwave(stddeb,"WAVE_mciRecord // before WIDM_UNPREPARE \n");
379 dwRet = widMessage(0, WIDM_UNPREPARE, 0, (DWORD)lp16WaveHdr, sizeof(WAVEHDR));
380 dprintf_mciwave(stddeb,"WAVE_mciRecord // after WIDM_UNPREPARE \n");
381 if (lpWaveHdr->lpData != NULL) {
382 GlobalUnlock16(hData);
383 GlobalFree16(hData);
384 lpWaveHdr->lpData = NULL;
386 USER_HEAP_FREE(hWaveHdr);
387 if (dwFlags & MCI_NOTIFY) {
388 dprintf_mciwave(stddeb,"WAVE_mciRecord // MCI_NOTIFY_SUCCESSFUL %08lX !\n", lpParms->dwCallback);
389 mciDriverNotify((HWND)LOWORD(lpParms->dwCallback),
390 MCIWavDev[wDevID].wNotifyDeviceID, MCI_NOTIFY_SUCCESSFUL);
392 return 0;
396 /**************************************************************************
397 * WAVE_mciStop [internal]
399 static DWORD WAVE_mciStop(UINT wDevID, DWORD dwFlags, LPMCI_GENERIC_PARMS lpParms)
401 dprintf_mciwave(stddeb,
402 "WAVE_mciStop(%u, %08lX, %p);\n", wDevID, dwFlags, lpParms);
403 if (lpParms == NULL) return MCIERR_INTERNAL;
404 return 0;
408 /**************************************************************************
409 * WAVE_mciPause [internal]
411 static DWORD WAVE_mciPause(UINT wDevID, DWORD dwFlags, LPMCI_GENERIC_PARMS lpParms)
413 dprintf_mciwave(stddeb,
414 "WAVE_mciPause(%u, %08lX, %p);\n", wDevID, dwFlags, lpParms);
415 if (lpParms == NULL) return MCIERR_INTERNAL;
416 return 0;
420 /**************************************************************************
421 * WAVE_mciResume [internal]
423 static DWORD WAVE_mciResume(UINT wDevID, DWORD dwFlags, LPMCI_GENERIC_PARMS lpParms)
425 dprintf_mciwave(stddeb,
426 "WAVE_mciResume(%u, %08lX, %p);\n", wDevID, dwFlags, lpParms);
427 if (lpParms == NULL) return MCIERR_INTERNAL;
428 return 0;
432 /**************************************************************************
433 * WAVE_mciSet [internal]
435 static DWORD WAVE_mciSet(UINT wDevID, DWORD dwFlags, LPMCI_SET_PARMS lpParms)
437 dprintf_mciwave(stddeb,
438 "WAVE_mciSet(%u, %08lX, %p);\n", wDevID, dwFlags, lpParms);
439 if (lpParms == NULL) return MCIERR_INTERNAL;
440 dprintf_mciwave(stddeb,
441 "WAVE_mciSet // dwTimeFormat=%08lX\n", lpParms->dwTimeFormat);
442 dprintf_mciwave(stddeb,
443 "WAVE_mciSet // dwAudio=%08lX\n", lpParms->dwAudio);
444 if (dwFlags & MCI_SET_TIME_FORMAT) {
445 switch (lpParms->dwTimeFormat) {
446 case MCI_FORMAT_MILLISECONDS:
447 dprintf_mciwave(stddeb, "WAVE_mciSet // MCI_FORMAT_MILLISECONDS !\n");
448 break;
449 case MCI_FORMAT_BYTES:
450 dprintf_mciwave(stddeb, "WAVE_mciSet // MCI_FORMAT_BYTES !\n");
451 break;
452 case MCI_FORMAT_SAMPLES:
453 dprintf_mciwave(stddeb, "WAVE_mciSet // MCI_FORMAT_SAMPLES !\n");
454 break;
455 default:
456 dprintf_mciwave(stddeb, "WAVE_mciSet // bad time format !\n");
457 return MCIERR_BAD_TIME_FORMAT;
460 if (dwFlags & MCI_SET_VIDEO) return MCIERR_UNSUPPORTED_FUNCTION;
461 if (dwFlags & MCI_SET_DOOR_OPEN) return MCIERR_UNSUPPORTED_FUNCTION;
462 if (dwFlags & MCI_SET_DOOR_CLOSED) return MCIERR_UNSUPPORTED_FUNCTION;
463 if (dwFlags & MCI_SET_AUDIO)
464 dprintf_mciwave(stddeb,"WAVE_mciSet // MCI_SET_AUDIO !\n");
465 if (dwFlags && MCI_SET_ON) {
466 dprintf_mciwave(stddeb,"WAVE_mciSet // MCI_SET_ON !\n");
467 if (dwFlags && MCI_SET_AUDIO_LEFT)
468 dprintf_mciwave(stddeb,"WAVE_mciSet // MCI_SET_AUDIO_LEFT !\n");
469 if (dwFlags && MCI_SET_AUDIO_RIGHT)
470 dprintf_mciwave(stddeb,"WAVE_mciSet // MCI_SET_AUDIO_RIGHT !\n");
472 if (dwFlags & MCI_SET_OFF)
473 dprintf_mciwave(stddeb,"WAVE_mciSet // MCI_SET_OFF !\n");
474 if (dwFlags & MCI_WAVE_INPUT)
475 dprintf_mciwave(stddeb,"WAVE_mciSet // MCI_WAVE_INPUT !\n");
476 if (dwFlags & MCI_WAVE_OUTPUT)
477 dprintf_mciwave(stddeb,"WAVE_mciSet // MCI_WAVE_OUTPUT !\n");
478 if (dwFlags & MCI_WAVE_SET_ANYINPUT)
479 dprintf_mciwave(stddeb,"WAVE_mciSet // MCI_WAVE_SET_ANYINPUT !\n");
480 if (dwFlags & MCI_WAVE_SET_ANYOUTPUT)
481 dprintf_mciwave(stddeb,"WAVE_mciSet // MCI_WAVE_SET_ANYOUTPUT !\n");
482 if (dwFlags & MCI_WAVE_SET_AVGBYTESPERSEC)
483 dprintf_mciwave(stddeb,
484 "WAVE_mciSet // MCI_WAVE_SET_AVGBYTESPERSEC !\n");
485 if (dwFlags & MCI_WAVE_SET_BITSPERSAMPLE)
486 dprintf_mciwave(stddeb,
487 "WAVE_mciSet // MCI_WAVE_SET_BITSPERSAMPLE !\n");
488 if (dwFlags & MCI_WAVE_SET_BLOCKALIGN)
489 dprintf_mciwave(stddeb,"WAVE_mciSet // MCI_WAVE_SET_BLOCKALIGN !\n");
490 if (dwFlags & MCI_WAVE_SET_CHANNELS)
491 dprintf_mciwave(stddeb,"WAVE_mciSet // MCI_WAVE_SET_CHANNELS !\n");
492 if (dwFlags & MCI_WAVE_SET_FORMATTAG)
493 dprintf_mciwave(stddeb,"WAVE_mciSet // MCI_WAVE_SET_FORMATTAG !\n");
494 if (dwFlags & MCI_WAVE_SET_SAMPLESPERSEC)
495 dprintf_mciwave(stddeb,
496 "WAVE_mciSet // MCI_WAVE_SET_SAMPLESPERSEC !\n");
497 return 0;
501 /**************************************************************************
502 * WAVE_mciStatus [internal]
504 static DWORD WAVE_mciStatus(UINT wDevID, DWORD dwFlags, LPMCI_STATUS_PARMS lpParms)
506 dprintf_mciwave(stddeb,
507 "WAVE_mciStatus(%u, %08lX, %p);\n", wDevID, dwFlags, lpParms);
508 if (lpParms == NULL) return MCIERR_INTERNAL;
509 if (dwFlags & MCI_STATUS_ITEM) {
510 switch(lpParms->dwItem) {
511 case MCI_STATUS_CURRENT_TRACK:
512 lpParms->dwReturn = 1;
513 break;
514 case MCI_STATUS_LENGTH:
515 lpParms->dwReturn = 5555;
516 if (dwFlags & MCI_TRACK) {
517 lpParms->dwTrack = 1;
518 lpParms->dwReturn = 2222;
520 break;
521 case MCI_STATUS_MODE:
522 lpParms->dwReturn = MCI_MODE_STOP;
523 break;
524 case MCI_STATUS_MEDIA_PRESENT:
525 dprintf_mciwave(stddeb,"WAVE_mciStatus // MCI_STATUS_MEDIA_PRESENT !\n");
526 lpParms->dwReturn = TRUE;
527 break;
528 case MCI_STATUS_NUMBER_OF_TRACKS:
529 lpParms->dwReturn = 1;
530 break;
531 case MCI_STATUS_POSITION:
532 lpParms->dwReturn = 3333;
533 if (dwFlags & MCI_STATUS_START) {
534 lpParms->dwItem = 1;
536 if (dwFlags & MCI_TRACK) {
537 lpParms->dwTrack = 1;
538 lpParms->dwReturn = 777;
540 break;
541 case MCI_STATUS_READY:
542 dprintf_mciwave(stddeb,"WAVE_mciStatus // MCI_STATUS_READY !\n");
543 lpParms->dwReturn = TRUE;
544 break;
545 case MCI_STATUS_TIME_FORMAT:
546 dprintf_mciwave(stddeb,"WAVE_mciStatus // MCI_STATUS_TIME_FORMAT !\n");
547 lpParms->dwReturn = MCI_FORMAT_MILLISECONDS;
548 break;
549 case MCI_WAVE_INPUT:
550 dprintf_mciwave(stddeb,"WAVE_mciStatus // MCI_WAVE_INPUT !\n");
551 lpParms->dwReturn = 0;
552 break;
553 case MCI_WAVE_OUTPUT:
554 dprintf_mciwave(stddeb,"WAVE_mciStatus // MCI_WAVE_OUTPUT !\n");
555 lpParms->dwReturn = 0;
556 break;
557 case MCI_WAVE_STATUS_AVGBYTESPERSEC:
558 dprintf_mciwave(stddeb,"WAVE_mciStatus // MCI_WAVE_STATUS_AVGBYTESPERSEC !\n");
559 lpParms->dwReturn = 22050;
560 break;
561 case MCI_WAVE_STATUS_BITSPERSAMPLE:
562 dprintf_mciwave(stddeb,"WAVE_mciStatus // MCI_WAVE_STATUS_BITSPERSAMPLE !\n");
563 lpParms->dwReturn = 8;
564 break;
565 case MCI_WAVE_STATUS_BLOCKALIGN:
566 dprintf_mciwave(stddeb,"WAVE_mciStatus // MCI_WAVE_STATUS_BLOCKALIGN !\n");
567 lpParms->dwReturn = 1;
568 break;
569 case MCI_WAVE_STATUS_CHANNELS:
570 dprintf_mciwave(stddeb,"WAVE_mciStatus // MCI_WAVE_STATUS_CHANNELS !\n");
571 lpParms->dwReturn = 1;
572 break;
573 case MCI_WAVE_STATUS_FORMATTAG:
574 dprintf_mciwave(stddeb,"WAVE_mciStatus // MCI_WAVE_FORMATTAG !\n");
575 lpParms->dwReturn = WAVE_FORMAT_PCM;
576 break;
577 case MCI_WAVE_STATUS_LEVEL:
578 dprintf_mciwave(stddeb,"WAVE_mciStatus // MCI_WAVE_STATUS_LEVEL !\n");
579 lpParms->dwReturn = 0xAAAA5555;
580 break;
581 case MCI_WAVE_STATUS_SAMPLESPERSEC:
582 dprintf_mciwave(stddeb,"WAVE_mciStatus // MCI_WAVE_STATUS_SAMPLESPERSEC !\n");
583 lpParms->dwReturn = 22050;
584 break;
585 default:
586 dprintf_mciwave(stddeb,"WAVE_mciStatus // unknown command %08lX !\n", lpParms->dwItem);
587 return MCIERR_UNRECOGNIZED_COMMAND;
590 if (dwFlags & MCI_NOTIFY) {
591 dprintf_mciwave(stddeb,"WAVE_mciStatus // MCI_NOTIFY_SUCCESSFUL %08lX !\n", lpParms->dwCallback);
592 mciDriverNotify((HWND)LOWORD(lpParms->dwCallback),
593 MCIWavDev[wDevID].wNotifyDeviceID, MCI_NOTIFY_SUCCESSFUL);
595 return 0;
598 /**************************************************************************
599 * WAVE_mciGetDevCaps [internal]
601 static DWORD WAVE_mciGetDevCaps(UINT wDevID, DWORD dwFlags,
602 LPMCI_GETDEVCAPS_PARMS lpParms)
604 dprintf_mciwave(stddeb,
605 "WAVE_mciGetDevCaps(%u, %08lX, %p);\n", wDevID, dwFlags, lpParms);
606 if (lpParms == NULL) return MCIERR_INTERNAL;
607 if (dwFlags & MCI_GETDEVCAPS_ITEM) {
608 switch(lpParms->dwItem) {
609 case MCI_GETDEVCAPS_CAN_RECORD:
610 lpParms->dwReturn = TRUE;
611 break;
612 case MCI_GETDEVCAPS_HAS_AUDIO:
613 lpParms->dwReturn = TRUE;
614 break;
615 case MCI_GETDEVCAPS_HAS_VIDEO:
616 lpParms->dwReturn = FALSE;
617 break;
618 case MCI_GETDEVCAPS_DEVICE_TYPE:
619 lpParms->dwReturn = MCI_DEVTYPE_WAVEFORM_AUDIO;
620 break;
621 case MCI_GETDEVCAPS_USES_FILES:
622 lpParms->dwReturn = TRUE;
623 break;
624 case MCI_GETDEVCAPS_COMPOUND_DEVICE:
625 lpParms->dwReturn = TRUE;
626 break;
627 case MCI_GETDEVCAPS_CAN_EJECT:
628 lpParms->dwReturn = FALSE;
629 break;
630 case MCI_GETDEVCAPS_CAN_PLAY:
631 lpParms->dwReturn = TRUE;
632 break;
633 case MCI_GETDEVCAPS_CAN_SAVE:
634 lpParms->dwReturn = TRUE;
635 break;
636 case MCI_WAVE_GETDEVCAPS_INPUTS:
637 lpParms->dwReturn = 1;
638 break;
639 case MCI_WAVE_GETDEVCAPS_OUTPUTS:
640 lpParms->dwReturn = 1;
641 break;
642 default:
643 return MCIERR_UNRECOGNIZED_COMMAND;
646 return 0;
649 /**************************************************************************
650 * WAVE_mciInfo [internal]
652 static DWORD WAVE_mciInfo(UINT wDevID, DWORD dwFlags, LPMCI_INFO_PARMS lpParms)
654 dprintf_mciwave(stddeb,
655 "WAVE_mciInfo(%u, %08lX, %p);\n", wDevID, dwFlags, lpParms);
656 if (lpParms == NULL) return MCIERR_INTERNAL;
657 lpParms->lpstrReturn = NULL;
658 switch(dwFlags) {
659 case MCI_INFO_PRODUCT:
660 lpParms->lpstrReturn = "Linux Sound System 0.5";
661 break;
662 case MCI_INFO_FILE:
663 lpParms->lpstrReturn =
664 (LPSTR)MCIWavDev[wDevID].openParms.lpstrElementName;
665 break;
666 case MCI_WAVE_INPUT:
667 lpParms->lpstrReturn = "Linux Sound System 0.5";
668 break;
669 case MCI_WAVE_OUTPUT:
670 lpParms->lpstrReturn = "Linux Sound System 0.5";
671 break;
672 default:
673 return MCIERR_UNRECOGNIZED_COMMAND;
675 if (lpParms->lpstrReturn != NULL)
676 lpParms->dwRetSize = strlen(lpParms->lpstrReturn);
677 else
678 lpParms->dwRetSize = 0;
679 return 0;
683 /*-----------------------------------------------------------------------*/
686 /**************************************************************************
687 * wodGetDevCaps [internal]
689 static DWORD wodGetDevCaps(WORD wDevID, LPWAVEOUTCAPS lpCaps, DWORD dwSize)
691 int audio;
692 int smplrate;
693 int samplesize = 16;
694 int dsp_stereo = 1;
695 int bytespersmpl;
696 dprintf_mciwave(stddeb,
697 "wodGetDevCaps(%u, %p, %lu);\n", wDevID, lpCaps, dwSize);
698 if (lpCaps == NULL) return MMSYSERR_NOTENABLED;
699 audio = open (SOUND_DEV, O_WRONLY, 0);
700 if (audio == -1) return MMSYSERR_NOTENABLED;
701 #ifdef EMULATE_SB16
702 lpCaps->wMid = 0x0002;
703 lpCaps->wPid = 0x0104;
704 strcpy(lpCaps->szPname, "SB16 Wave Out");
705 #else
706 lpCaps->wMid = 0x00FF; /* Manufac ID */
707 lpCaps->wPid = 0x0001; /* Product ID */
708 strcpy(lpCaps->szPname, "Linux WAVOUT Driver");
709 #endif
710 lpCaps->dwFormats = 0x00000000;
711 lpCaps->dwSupport = WAVECAPS_VOLUME;
712 lpCaps->wChannels = (IOCTL(audio, SNDCTL_DSP_STEREO, dsp_stereo) != 0) ? 1 : 2;
713 if (lpCaps->wChannels > 1) lpCaps->dwSupport |= WAVECAPS_LRVOLUME;
714 bytespersmpl = (IOCTL(audio, SNDCTL_DSP_SAMPLESIZE, samplesize) != 0) ? 1 : 2;
715 smplrate = 44100;
716 if (IOCTL(audio, SNDCTL_DSP_SPEED, smplrate) == 0) {
717 lpCaps->dwFormats |= WAVE_FORMAT_4M08;
718 if (lpCaps->wChannels > 1) lpCaps->dwFormats |= WAVE_FORMAT_4S08;
719 if (bytespersmpl > 1) {
720 lpCaps->dwFormats |= WAVE_FORMAT_4M16;
721 if (lpCaps->wChannels > 1) lpCaps->dwFormats |= WAVE_FORMAT_4S16;
724 smplrate = 22050;
725 if (IOCTL(audio, SNDCTL_DSP_SPEED, smplrate) == 0) {
726 lpCaps->dwFormats |= WAVE_FORMAT_2M08;
727 if (lpCaps->wChannels > 1) lpCaps->dwFormats |= WAVE_FORMAT_2S08;
728 if (bytespersmpl > 1) {
729 lpCaps->dwFormats |= WAVE_FORMAT_2M16;
730 if (lpCaps->wChannels > 1) lpCaps->dwFormats |= WAVE_FORMAT_2S16;
733 smplrate = 11025;
734 if (IOCTL(audio, SNDCTL_DSP_SPEED, smplrate) == 0) {
735 lpCaps->dwFormats |= WAVE_FORMAT_1M08;
736 if (lpCaps->wChannels > 1) lpCaps->dwFormats |= WAVE_FORMAT_1S08;
737 if (bytespersmpl > 1) {
738 lpCaps->dwFormats |= WAVE_FORMAT_1M16;
739 if (lpCaps->wChannels > 1) lpCaps->dwFormats |= WAVE_FORMAT_1S16;
742 close(audio);
743 dprintf_mciwave(stddeb,
744 "wodGetDevCaps // dwFormats = %08lX\n", lpCaps->dwFormats);
745 return MMSYSERR_NOERROR;
749 /**************************************************************************
750 * wodOpen [internal]
752 static DWORD wodOpen(WORD wDevID, LPWAVEOPENDESC lpDesc, DWORD dwFlags)
754 int audio;
755 int abuf_size;
756 int smplrate;
757 int samplesize;
758 int dsp_stereo;
759 LPWAVEFORMAT lpFormat;
761 dprintf_mciwave(stddeb,
762 "wodOpen(%u, %p, %08lX);\n", wDevID, lpDesc, dwFlags);
763 if (lpDesc == NULL) {
764 dprintf_mciwave(stddeb,"Linux 'wodOpen' // Invalid Parameter !\n");
765 return MMSYSERR_INVALPARAM;
767 if (wDevID >= MAX_WAVOUTDRV) {
768 dprintf_mciwave(stddeb,"Linux 'wodOpen' // MAX_WAVOUTDRV reached !\n");
769 return MMSYSERR_ALLOCATED;
771 WOutDev[wDevID].unixdev = 0;
772 audio = open (SOUND_DEV, O_WRONLY, 0);
773 if (audio == -1) {
774 dprintf_mciwave(stddeb,"Linux 'wodOpen' // can't open !\n");
775 return MMSYSERR_NOTENABLED;
777 IOCTL(audio, SNDCTL_DSP_GETBLKSIZE, abuf_size);
778 if (abuf_size < 4096 || abuf_size > 65536) {
779 if (abuf_size == -1)
780 dprintf_mciwave(stddeb,"Linux 'wodOpen' // IOCTL can't 'SNDCTL_DSP_GETBLKSIZE' !\n");
781 else
782 dprintf_mciwave(stddeb,"Linux 'wodOpen' // SNDCTL_DSP_GETBLKSIZE Invalid bufsize !\n");
783 return MMSYSERR_NOTENABLED;
785 WOutDev[wDevID].wFlags = HIWORD(dwFlags & CALLBACK_TYPEMASK);
786 switch(WOutDev[wDevID].wFlags) {
787 case DCB_NULL:
788 dprintf_mciwave(stddeb, "Linux 'wodOpen' // CALLBACK_NULL !\n");
789 break;
790 case DCB_WINDOW:
791 dprintf_mciwave(stddeb, "Linux 'wodOpen' // CALLBACK_WINDOW !\n");
792 break;
793 case DCB_TASK:
794 dprintf_mciwave(stddeb, "Linux 'wodOpen' // CALLBACK_TASK !\n");
795 break;
796 case DCB_FUNCTION:
797 dprintf_mciwave(stddeb, "Linux 'wodOpen' // CALLBACK_FUNCTION !\n");
798 break;
800 WOutDev[wDevID].lpQueueHdr = NULL;
801 WOutDev[wDevID].unixdev = audio;
802 WOutDev[wDevID].dwTotalPlayed = 0;
803 WOutDev[wDevID].bufsize = abuf_size;
804 memcpy(&WOutDev[wDevID].waveDesc, lpDesc, sizeof(WAVEOPENDESC));
805 /* lpFormat = (LPWAVEFORMAT) PTR_SEG_TO_LIN(lpDesc->lpFormat); */
806 lpFormat = lpDesc->lpFormat;
807 if (lpFormat->wFormatTag != WAVE_FORMAT_PCM) {
808 dprintf_mciwave(stddeb,"Linux 'wodOpen' // Bad format %04X !\n",
809 lpFormat->wFormatTag);
810 dprintf_mciwave(stddeb,"Linux 'wodOpen' // Bad nChannels %d !\n",
811 lpFormat->nChannels);
812 dprintf_mciwave(stddeb,"Linux 'wodOpen' // Bad nSamplesPerSec %ld !\n",
813 lpFormat->nSamplesPerSec);
814 return WAVERR_BADFORMAT;
816 memcpy(&WOutDev[wDevID].Format, lpFormat, sizeof(PCMWAVEFORMAT));
817 if (WOutDev[wDevID].Format.wf.nChannels == 0) return WAVERR_BADFORMAT;
818 if (WOutDev[wDevID].Format.wf.nSamplesPerSec == 0) return WAVERR_BADFORMAT;
819 dprintf_mciwave(stddeb,"Linux 'wodOpen' // wBitsPerSample=%u !\n",
820 WOutDev[wDevID].Format.wBitsPerSample);
821 if (WOutDev[wDevID].Format.wBitsPerSample == 0) {
822 WOutDev[wDevID].Format.wBitsPerSample = 8 *
823 (WOutDev[wDevID].Format.wf.nAvgBytesPerSec /
824 WOutDev[wDevID].Format.wf.nSamplesPerSec) /
825 WOutDev[wDevID].Format.wf.nChannels;
827 samplesize = WOutDev[wDevID].Format.wBitsPerSample;
828 smplrate = WOutDev[wDevID].Format.wf.nSamplesPerSec;
829 dsp_stereo = (WOutDev[wDevID].Format.wf.nChannels > 1) ? TRUE : FALSE;
830 IOCTL(audio, SNDCTL_DSP_SPEED, smplrate);
831 IOCTL(audio, SNDCTL_DSP_SAMPLESIZE, samplesize);
832 IOCTL(audio, SNDCTL_DSP_STEREO, dsp_stereo);
833 dprintf_mciwave(stddeb,"Linux 'wodOpen' // wBitsPerSample=%u !\n",
834 WOutDev[wDevID].Format.wBitsPerSample);
835 dprintf_mciwave(stddeb,"Linux 'wodOpen' // nAvgBytesPerSec=%lu !\n",
836 WOutDev[wDevID].Format.wf.nAvgBytesPerSec);
837 dprintf_mciwave(stddeb,"Linux 'wodOpen' // nSamplesPerSec=%lu !\n",
838 WOutDev[wDevID].Format.wf.nSamplesPerSec);
839 dprintf_mciwave(stddeb,"Linux 'wodOpen' // nChannels=%u !\n",
840 WOutDev[wDevID].Format.wf.nChannels);
841 if (WAVE_NotifyClient(wDevID, WOM_OPEN, 0L, 0L) != MMSYSERR_NOERROR) {
842 dprintf_mciwave(stddeb,"Linux 'wodOpen' // can't notify client !\n");
843 return MMSYSERR_INVALPARAM;
845 return MMSYSERR_NOERROR;
848 /**************************************************************************
849 * wodClose [internal]
851 static DWORD wodClose(WORD wDevID)
853 dprintf_mciwave(stddeb,"wodClose(%u);\n", wDevID);
854 if (WOutDev[wDevID].unixdev == 0) {
855 dprintf_mciwave(stddeb,"Linux 'wodClose' // can't close !\n");
856 return MMSYSERR_NOTENABLED;
858 close(WOutDev[wDevID].unixdev);
859 WOutDev[wDevID].unixdev = 0;
860 WOutDev[wDevID].bufsize = 0;
861 WOutDev[wDevID].lpQueueHdr = NULL;
862 if (WAVE_NotifyClient(wDevID, WOM_CLOSE, 0L, 0L) != MMSYSERR_NOERROR) {
863 dprintf_mciwave(stddeb,"Linux 'wodClose' // can't notify client !\n");
864 return MMSYSERR_INVALPARAM;
866 return MMSYSERR_NOERROR;
869 /**************************************************************************
870 * wodWrite [internal]
872 static DWORD wodWrite(WORD wDevID, LPWAVEHDR lpWaveHdr, DWORD dwSize)
874 int count;
875 LPSTR lpData;
876 dprintf_mciwave(stddeb,"wodWrite(%u, %p, %08lX);\n", wDevID, lpWaveHdr, dwSize);
877 if (WOutDev[wDevID].unixdev == 0) {
878 dprintf_mciwave(stddeb,"Linux 'wodWrite' // can't play !\n");
879 return MMSYSERR_NOTENABLED;
881 if (lpWaveHdr->lpData == NULL) return WAVERR_UNPREPARED;
882 if (!(lpWaveHdr->dwFlags & WHDR_PREPARED)) return WAVERR_UNPREPARED;
883 if (lpWaveHdr->dwFlags & WHDR_INQUEUE) return WAVERR_STILLPLAYING;
884 lpWaveHdr->dwFlags &= ~WHDR_DONE;
885 lpWaveHdr->dwFlags |= WHDR_INQUEUE;
886 dprintf_mciwave(stddeb,
887 "wodWrite() // dwBufferLength %lu !\n", lpWaveHdr->dwBufferLength);
888 dprintf_mciwave(stddeb,
889 "wodWrite() // WOutDev[%u].unixdev %u !\n", wDevID, WOutDev[wDevID].unixdev);
890 lpData = PTR_SEG_TO_LIN(lpWaveHdr->lpData);
891 count = write (WOutDev[wDevID].unixdev, lpData, lpWaveHdr->dwBufferLength);
892 dprintf_mciwave(stddeb,
893 "wodWrite() // write returned count %u !\n", count);
894 if (count != lpWaveHdr->dwBufferLength) {
895 dprintf_mciwave(stddeb,"Linux 'wodWrite' // error writting !\n");
896 return MMSYSERR_NOTENABLED;
898 WOutDev[wDevID].dwTotalPlayed += count;
899 lpWaveHdr->dwFlags &= ~WHDR_INQUEUE;
900 lpWaveHdr->dwFlags |= WHDR_DONE;
901 if (WAVE_NotifyClient(wDevID, WOM_DONE, 0L, 0L) != MMSYSERR_NOERROR) {
902 dprintf_mciwave(stddeb,"Linux 'wodWrite' // can't notify client !\n");
903 return MMSYSERR_INVALPARAM;
905 return MMSYSERR_NOERROR;
908 /**************************************************************************
909 * wodPrepare [internal]
911 static DWORD wodPrepare(WORD wDevID, LPWAVEHDR lpWaveHdr, DWORD dwSize)
913 dprintf_mciwave(stddeb,
914 "wodPrepare(%u, %p, %08lX);\n", wDevID, lpWaveHdr, dwSize);
915 if (WOutDev[wDevID].unixdev == 0) {
916 dprintf_mciwave(stddeb,"Linux 'wodPrepare' // can't prepare !\n");
917 return MMSYSERR_NOTENABLED;
919 /* the COOL waveeditor feels much better without this check...
920 * someone please have a look at available documentation
921 if (WOutDev[wDevID].lpQueueHdr != NULL) {
922 dprintf_mciwave(stddeb,"Linux 'wodPrepare' // already prepare !\n");
923 return MMSYSERR_NOTENABLED;
926 WOutDev[wDevID].dwTotalPlayed = 0;
927 WOutDev[wDevID].lpQueueHdr = lpWaveHdr;
928 if (lpWaveHdr->dwFlags & WHDR_INQUEUE) return WAVERR_STILLPLAYING;
929 lpWaveHdr->dwFlags |= WHDR_PREPARED;
930 lpWaveHdr->dwFlags &= ~WHDR_DONE;
931 return MMSYSERR_NOERROR;
934 /**************************************************************************
935 * wodUnprepare [internal]
937 static DWORD wodUnprepare(WORD wDevID, LPWAVEHDR lpWaveHdr, DWORD dwSize)
939 dprintf_mciwave(stddeb,
940 "wodUnprepare(%u, %p, %08lX);\n", wDevID, lpWaveHdr, dwSize);
941 if (WOutDev[wDevID].unixdev == 0) {
942 dprintf_mciwave(stddeb,"Linux 'wodUnprepare' // can't unprepare !\n");
943 return MMSYSERR_NOTENABLED;
945 return MMSYSERR_NOERROR;
948 /**************************************************************************
949 * wodRestart [internal]
951 static DWORD wodRestart(WORD wDevID)
953 dprintf_mciwave(stddeb,"wodRestart(%u);\n", wDevID);
954 if (WOutDev[wDevID].unixdev == 0) {
955 dprintf_mciwave(stddeb,"Linux 'wodRestart' // can't restart !\n");
956 return MMSYSERR_NOTENABLED;
958 return MMSYSERR_NOERROR;
961 /**************************************************************************
962 * wodReset [internal]
964 static DWORD wodReset(WORD wDevID)
966 dprintf_mciwave(stddeb,"wodReset(%u);\n", wDevID);
967 if (WOutDev[wDevID].unixdev == 0) {
968 dprintf_mciwave(stddeb,"Linux 'wodReset' // can't reset !\n");
969 return MMSYSERR_NOTENABLED;
971 return MMSYSERR_NOERROR;
975 /**************************************************************************
976 * wodGetPosition [internal]
978 static DWORD wodGetPosition(WORD wDevID, LPMMTIME lpTime, DWORD uSize)
980 int time;
981 dprintf_mciwave(stddeb,"wodGetPosition(%u, %p, %lu);\n", wDevID, lpTime, uSize);
982 if (WOutDev[wDevID].unixdev == 0) {
983 dprintf_mciwave(stddeb,"Linux 'wodGetPosition' // can't get pos !\n");
984 return MMSYSERR_NOTENABLED;
986 if (lpTime == NULL) return MMSYSERR_INVALPARAM;
987 switch(lpTime->wType) {
988 case TIME_BYTES:
989 lpTime->u.cb = WOutDev[wDevID].dwTotalPlayed;
990 dprintf_mciwave(stddeb,"wodGetPosition // TIME_BYTES=%lu\n", lpTime->u.cb);
991 break;
992 case TIME_SAMPLES:
993 dprintf_mciwave(stddeb,"wodGetPosition // dwTotalPlayed=%lu\n",
994 WOutDev[wDevID].dwTotalPlayed);
995 dprintf_mciwave(stddeb,"wodGetPosition // wBitsPerSample=%u\n",
996 WOutDev[wDevID].Format.wBitsPerSample);
997 lpTime->u.sample = WOutDev[wDevID].dwTotalPlayed * 8 /
998 WOutDev[wDevID].Format.wBitsPerSample;
999 dprintf_mciwave(stddeb,"wodGetPosition // TIME_SAMPLES=%lu\n", lpTime->u.sample);
1000 break;
1001 case TIME_SMPTE:
1002 time = WOutDev[wDevID].dwTotalPlayed /
1003 (WOutDev[wDevID].Format.wf.nAvgBytesPerSec / 1000);
1004 lpTime->u.smpte.hour = time / 108000;
1005 time -= lpTime->u.smpte.hour * 108000;
1006 lpTime->u.smpte.min = time / 1800;
1007 time -= lpTime->u.smpte.min * 1800;
1008 lpTime->u.smpte.sec = time / 30;
1009 time -= lpTime->u.smpte.sec * 30;
1010 lpTime->u.smpte.frame = time;
1011 lpTime->u.smpte.fps = 30;
1012 dprintf_mciwave(stddeb,
1013 "wodGetPosition // TIME_SMPTE=%02u:%02u:%02u:%02u\n",
1014 lpTime->u.smpte.hour, lpTime->u.smpte.min,
1015 lpTime->u.smpte.sec, lpTime->u.smpte.frame);
1016 break;
1017 default:
1018 dprintf_mciwave(stddeb,"wodGetPosition() format not supported ! use TIME_MS !\n");
1019 lpTime->wType = TIME_MS;
1020 case TIME_MS:
1021 lpTime->u.ms = WOutDev[wDevID].dwTotalPlayed /
1022 (WOutDev[wDevID].Format.wf.nAvgBytesPerSec / 1000);
1023 dprintf_mciwave(stddeb,"wodGetPosition // TIME_MS=%lu\n", lpTime->u.ms);
1024 break;
1026 return MMSYSERR_NOERROR;
1029 /**************************************************************************
1030 * wodGetVolume [internal]
1032 static DWORD wodGetVolume(WORD wDevID, LPDWORD lpdwVol)
1034 int mixer;
1035 int volume, left, right;
1036 dprintf_mciwave(stddeb,"wodGetVolume(%u, %p);\n", wDevID, lpdwVol);
1037 if (lpdwVol == NULL) return MMSYSERR_NOTENABLED;
1038 if ((mixer = open("/dev/mixer", O_RDONLY)) < 0) {
1039 dprintf_mciwave(stddeb, "Linux 'wodGetVolume' // mixer device not available !\n");
1040 return MMSYSERR_NOTENABLED;
1042 if (ioctl(mixer, SOUND_MIXER_READ_PCM, &volume) == -1) {
1043 dprintf_mciwave(stddeb,"Linux 'wodGetVolume' // unable read mixer !\n");
1044 return MMSYSERR_NOTENABLED;
1046 close(mixer);
1047 left = volume & 0x7F;
1048 right = (volume >> 8) & 0x7F;
1049 printf("Linux 'AUX_GetVolume' // left=%d right=%d !\n", left, right);
1050 *lpdwVol = MAKELONG(left << 9, right << 9);
1051 return MMSYSERR_NOERROR;
1055 /**************************************************************************
1056 * wodSetVolume [internal]
1058 static DWORD wodSetVolume(WORD wDevID, DWORD dwParam)
1060 int mixer;
1061 int volume;
1062 dprintf_mciwave(stddeb,"wodSetVolume(%u, %08lX);\n", wDevID, dwParam);
1063 volume = (LOWORD(dwParam) >> 9 & 0x7F) +
1064 ((HIWORD(dwParam) >> 9 & 0x7F) << 8);
1065 if ((mixer = open("/dev/mixer", O_WRONLY)) < 0) {
1066 dprintf_mciwave(stddeb, "Linux 'wodSetVolume' // mixer device not available !\n");
1067 return MMSYSERR_NOTENABLED;
1069 if (ioctl(mixer, SOUND_MIXER_WRITE_PCM, &volume) == -1) {
1070 dprintf_mciwave(stddeb,"Linux 'wodSetVolume' // unable set mixer !\n");
1071 return MMSYSERR_NOTENABLED;
1073 close(mixer);
1074 return MMSYSERR_NOERROR;
1077 #endif /* linux */
1079 /**************************************************************************
1080 * wodMessage [sample driver]
1082 DWORD wodMessage(WORD wDevID, WORD wMsg, DWORD dwUser,
1083 DWORD dwParam1, DWORD dwParam2)
1085 dprintf_mciwave(stddeb,"wodMessage(%u, %04X, %08lX, %08lX, %08lX);\n",
1086 wDevID, wMsg, dwUser, dwParam1, dwParam2);
1087 #ifdef linux
1088 switch(wMsg) {
1089 case WODM_OPEN:
1090 return wodOpen(wDevID, (LPWAVEOPENDESC)PTR_SEG_TO_LIN(dwParam1), dwParam2);
1091 case WODM_CLOSE:
1092 return wodClose(wDevID);
1093 case WODM_WRITE:
1094 return wodWrite(wDevID, (LPWAVEHDR)PTR_SEG_TO_LIN(dwParam1), dwParam2);
1095 case WODM_PAUSE:
1096 return 0L;
1097 case WODM_GETPOS:
1098 return wodGetPosition(wDevID, (LPMMTIME)PTR_SEG_TO_LIN(dwParam1), dwParam2);
1099 case WODM_BREAKLOOP:
1100 return 0L;
1101 case WODM_PREPARE:
1102 return wodPrepare(wDevID, (LPWAVEHDR)PTR_SEG_TO_LIN(dwParam1), dwParam2);
1103 case WODM_UNPREPARE:
1104 return wodUnprepare(wDevID, (LPWAVEHDR)PTR_SEG_TO_LIN(dwParam1), dwParam2);
1105 case WODM_GETDEVCAPS:
1106 return wodGetDevCaps(wDevID, (LPWAVEOUTCAPS)PTR_SEG_TO_LIN(dwParam1), dwParam2);
1107 case WODM_GETNUMDEVS:
1108 return 1L;
1109 case WODM_GETPITCH:
1110 return 0L;
1111 case WODM_SETPITCH:
1112 return 0L;
1113 case WODM_GETPLAYBACKRATE:
1114 return 0L;
1115 case WODM_SETPLAYBACKRATE:
1116 return 0L;
1117 case WODM_GETVOLUME:
1118 return wodGetVolume(wDevID, (LPDWORD)PTR_SEG_TO_LIN(dwParam1));
1119 case WODM_SETVOLUME:
1120 return wodSetVolume(wDevID, dwParam1);
1121 case WODM_RESTART:
1122 return wodRestart(wDevID);
1123 case WODM_RESET:
1124 return wodReset(wDevID);
1125 default:
1126 dprintf_mciwave(stddeb,"wodMessage // unknown message !\n");
1128 return MMSYSERR_NOTSUPPORTED;
1129 #else
1130 return MMSYSERR_NOTENABLED;
1131 #endif
1135 /*-----------------------------------------------------------------------*/
1137 #ifdef linux
1139 /**************************************************************************
1140 * widGetDevCaps [internal]
1142 static DWORD widGetDevCaps(WORD wDevID, LPWAVEINCAPS lpCaps, DWORD dwSize)
1144 int audio;
1145 int smplrate;
1146 int samplesize = 16;
1147 int dsp_stereo = 1;
1148 int bytespersmpl;
1149 dprintf_mciwave(stddeb,
1150 "widGetDevCaps(%u, %p, %lu);\n", wDevID, lpCaps, dwSize);
1151 if (lpCaps == NULL) return MMSYSERR_NOTENABLED;
1152 audio = open (SOUND_DEV, O_RDONLY, 0);
1153 if (audio == -1) return MMSYSERR_NOTENABLED;
1154 #ifdef EMULATE_SB16
1155 lpCaps->wMid = 0x0002;
1156 lpCaps->wPid = 0x0004;
1157 strcpy(lpCaps->szPname, "SB16 Wave Out");
1158 #else
1159 lpCaps->wMid = 0x00FF; /* Manufac ID */
1160 lpCaps->wPid = 0x0001; /* Product ID */
1161 strcpy(lpCaps->szPname, "Linux WAVIN Driver");
1162 #endif
1163 lpCaps->dwFormats = 0x00000000;
1164 lpCaps->wChannels = (IOCTL(audio, SNDCTL_DSP_STEREO, dsp_stereo) != 0) ? 1 : 2;
1165 bytespersmpl = (IOCTL(audio, SNDCTL_DSP_SAMPLESIZE, samplesize) != 0) ? 1 : 2;
1166 smplrate = 44100;
1167 if (IOCTL(audio, SNDCTL_DSP_SPEED, smplrate) == 0) {
1168 lpCaps->dwFormats |= WAVE_FORMAT_4M08;
1169 if (lpCaps->wChannels > 1) lpCaps->dwFormats |= WAVE_FORMAT_4S08;
1170 if (bytespersmpl > 1) {
1171 lpCaps->dwFormats |= WAVE_FORMAT_4M16;
1172 if (lpCaps->wChannels > 1) lpCaps->dwFormats |= WAVE_FORMAT_4S16;
1175 smplrate = 22050;
1176 if (IOCTL(audio, SNDCTL_DSP_SPEED, smplrate) == 0) {
1177 lpCaps->dwFormats |= WAVE_FORMAT_2M08;
1178 if (lpCaps->wChannels > 1) lpCaps->dwFormats |= WAVE_FORMAT_2S08;
1179 if (bytespersmpl > 1) {
1180 lpCaps->dwFormats |= WAVE_FORMAT_2M16;
1181 if (lpCaps->wChannels > 1) lpCaps->dwFormats |= WAVE_FORMAT_2S16;
1184 smplrate = 11025;
1185 if (IOCTL(audio, SNDCTL_DSP_SPEED, smplrate) == 0) {
1186 lpCaps->dwFormats |= WAVE_FORMAT_1M08;
1187 if (lpCaps->wChannels > 1) lpCaps->dwFormats |= WAVE_FORMAT_1S08;
1188 if (bytespersmpl > 1) {
1189 lpCaps->dwFormats |= WAVE_FORMAT_1M16;
1190 if (lpCaps->wChannels > 1) lpCaps->dwFormats |= WAVE_FORMAT_1S16;
1193 close(audio);
1194 dprintf_mciwave(stddeb,
1195 "widGetDevCaps // dwFormats = %08lX\n", lpCaps->dwFormats);
1196 return MMSYSERR_NOERROR;
1200 /**************************************************************************
1201 * widOpen [internal]
1203 static DWORD widOpen(WORD wDevID, LPWAVEOPENDESC lpDesc, DWORD dwFlags)
1205 int audio;
1206 int abuf_size;
1207 int smplrate;
1208 int samplesize;
1209 int dsp_stereo;
1210 LPWAVEFORMAT lpFormat;
1211 dprintf_mciwave(stddeb, "widOpen(%u, %p, %08lX);\n", wDevID, lpDesc, dwFlags);
1212 if (lpDesc == NULL) {
1213 dprintf_mciwave(stddeb,"Linux 'widOpen' // Invalid Parameter !\n");
1214 return MMSYSERR_INVALPARAM;
1216 if (wDevID >= MAX_WAVINDRV) {
1217 dprintf_mciwave(stddeb,"Linux 'widOpen' // MAX_WAVINDRV reached !\n");
1218 return MMSYSERR_ALLOCATED;
1220 WInDev[wDevID].unixdev = 0;
1221 audio = open (SOUND_DEV, O_RDONLY, 0);
1222 if (audio == -1) {
1223 dprintf_mciwave(stddeb,"Linux 'widOpen' // can't open !\n");
1224 return MMSYSERR_NOTENABLED;
1226 IOCTL(audio, SNDCTL_DSP_GETBLKSIZE, abuf_size);
1227 if (abuf_size < 4096 || abuf_size > 65536) {
1228 if (abuf_size == -1)
1229 dprintf_mciwave(stddeb,"Linux 'widOpen' // IOCTL can't 'SNDCTL_DSP_GETBLKSIZE' !\n");
1230 else
1231 dprintf_mciwave(stddeb,"Linux 'widOpen' // SNDCTL_DSP_GETBLKSIZE Invalid bufsize !\n");
1232 return MMSYSERR_NOTENABLED;
1234 WInDev[wDevID].wFlags = HIWORD(dwFlags & CALLBACK_TYPEMASK);
1235 switch(WInDev[wDevID].wFlags) {
1236 case DCB_NULL:
1237 dprintf_mciwave(stddeb, "Linux 'widOpen' // CALLBACK_NULL !\n");
1238 break;
1239 case DCB_WINDOW:
1240 dprintf_mciwave(stddeb, "Linux 'widOpen' // CALLBACK_WINDOW !\n");
1241 break;
1242 case DCB_TASK:
1243 dprintf_mciwave(stddeb, "Linux 'widOpen' // CALLBACK_TASK !\n");
1244 break;
1245 case DCB_FUNCTION:
1246 dprintf_mciwave(stddeb, "Linux 'widOpen' // CALLBACK_FUNCTION !\n");
1247 break;
1249 WInDev[wDevID].lpQueueHdr = NULL;
1250 WInDev[wDevID].unixdev = audio;
1251 WInDev[wDevID].bufsize = abuf_size;
1252 WInDev[wDevID].dwTotalRecorded = 0;
1253 memcpy(&WInDev[wDevID].waveDesc, lpDesc, sizeof(WAVEOPENDESC));
1254 lpFormat = lpDesc->lpFormat;
1255 if (lpFormat->wFormatTag != WAVE_FORMAT_PCM) {
1256 dprintf_mciwave(stddeb,"Linux 'widOpen' // Bad format %04X !\n",
1257 lpFormat->wFormatTag);
1258 return WAVERR_BADFORMAT;
1260 memcpy(&WInDev[wDevID].Format, lpFormat, sizeof(PCMWAVEFORMAT));
1261 WInDev[wDevID].Format.wBitsPerSample = 8; /* <-------------- */
1262 if (WInDev[wDevID].Format.wf.nChannels == 0) return WAVERR_BADFORMAT;
1263 if (WInDev[wDevID].Format.wf.nSamplesPerSec == 0) return WAVERR_BADFORMAT;
1264 if (WInDev[wDevID].Format.wBitsPerSample == 0) {
1265 WInDev[wDevID].Format.wBitsPerSample = 8 *
1266 (WInDev[wDevID].Format.wf.nAvgBytesPerSec /
1267 WInDev[wDevID].Format.wf.nSamplesPerSec) /
1268 WInDev[wDevID].Format.wf.nChannels;
1270 samplesize = WInDev[wDevID].Format.wBitsPerSample;
1271 smplrate = WInDev[wDevID].Format.wf.nSamplesPerSec;
1272 dsp_stereo = (WInDev[wDevID].Format.wf.nChannels > 1) ? TRUE : FALSE;
1273 IOCTL(audio, SNDCTL_DSP_SPEED, smplrate);
1274 IOCTL(audio, SNDCTL_DSP_SAMPLESIZE, samplesize);
1275 IOCTL(audio, SNDCTL_DSP_STEREO, dsp_stereo);
1276 dprintf_mciwave(stddeb,"Linux 'widOpen' // wBitsPerSample=%u !\n",
1277 WInDev[wDevID].Format.wBitsPerSample);
1278 dprintf_mciwave(stddeb,"Linux 'widOpen' // nSamplesPerSec=%lu !\n",
1279 WInDev[wDevID].Format.wf.nSamplesPerSec);
1280 dprintf_mciwave(stddeb,"Linux 'widOpen' // nChannels=%u !\n",
1281 WInDev[wDevID].Format.wf.nChannels);
1282 dprintf_mciwave(stddeb,"Linux 'widOpen' // nAvgBytesPerSec=%lu\n",
1283 WInDev[wDevID].Format.wf.nAvgBytesPerSec);
1284 if (WAVE_NotifyClient(wDevID, WIM_OPEN, 0L, 0L) != MMSYSERR_NOERROR) {
1285 dprintf_mciwave(stddeb,"Linux 'widOpen' // can't notify client !\n");
1286 return MMSYSERR_INVALPARAM;
1288 return MMSYSERR_NOERROR;
1291 /**************************************************************************
1292 * widClose [internal]
1294 static DWORD widClose(WORD wDevID)
1296 dprintf_mciwave(stddeb,"widClose(%u);\n", wDevID);
1297 if (WInDev[wDevID].unixdev == 0) {
1298 dprintf_mciwave(stddeb,"Linux 'widClose' // can't close !\n");
1299 return MMSYSERR_NOTENABLED;
1301 close(WInDev[wDevID].unixdev);
1302 WInDev[wDevID].unixdev = 0;
1303 WInDev[wDevID].bufsize = 0;
1304 if (WAVE_NotifyClient(wDevID, WIM_CLOSE, 0L, 0L) != MMSYSERR_NOERROR) {
1305 dprintf_mciwave(stddeb,"Linux 'widClose' // can't notify client !\n");
1306 return MMSYSERR_INVALPARAM;
1308 return MMSYSERR_NOERROR;
1311 /**************************************************************************
1312 * widAddBuffer [internal]
1314 static DWORD widAddBuffer(WORD wDevID, LPWAVEHDR lpWaveHdr, DWORD dwSize)
1316 int count = 1;
1317 LPWAVEHDR lpWIHdr;
1318 dprintf_mciwave(stddeb,
1319 "widAddBuffer(%u, %p, %08lX);\n", wDevID, lpWaveHdr, dwSize);
1320 if (WInDev[wDevID].unixdev == 0) {
1321 dprintf_mciwave(stddeb,"Linux 'widAddBuffer' // can't do it !\n");
1322 return MMSYSERR_NOTENABLED;
1324 if (!(lpWaveHdr->dwFlags & WHDR_PREPARED)) {
1325 dprintf_mciwave(stddeb, "Linux 'widAddBuffer' // never been prepared !\n");
1326 return WAVERR_UNPREPARED;
1328 if (lpWaveHdr->dwFlags & WHDR_INQUEUE) {
1329 dprintf_mciwave(stddeb, "Linux 'widAddBuffer' // header already in use !\n");
1330 return WAVERR_STILLPLAYING;
1332 lpWaveHdr->dwFlags |= WHDR_PREPARED;
1333 lpWaveHdr->dwFlags |= WHDR_INQUEUE;
1334 lpWaveHdr->dwFlags &= ~WHDR_DONE;
1335 lpWaveHdr->dwBytesRecorded = 0;
1336 if (WInDev[wDevID].lpQueueHdr == NULL) {
1337 /* begin the queue with a first header ... */
1338 WInDev[wDevID].lpQueueHdr = lpWaveHdr;
1339 WInDev[wDevID].dwTotalRecorded = 0;
1341 else {
1342 /* added to the queue, except if it's the one just prepared ... */
1343 lpWIHdr = WInDev[wDevID].lpQueueHdr;
1344 while (lpWIHdr->lpNext != NULL) {
1345 lpWIHdr = lpWIHdr->lpNext;
1346 count++;
1348 lpWIHdr->lpNext = lpWaveHdr;
1349 count++;
1351 dprintf_mciwave(stddeb,
1352 "widAddBuffer // buffer added ! (now %u in queue)\n", count);
1353 return MMSYSERR_NOERROR;
1356 /**************************************************************************
1357 * widPrepare [internal]
1359 static DWORD widPrepare(WORD wDevID, LPWAVEHDR lpWaveHdr, DWORD dwSize)
1361 dprintf_mciwave(stddeb,
1362 "widPrepare(%u, %p, %08lX);\n", wDevID, lpWaveHdr, dwSize);
1363 if (WInDev[wDevID].unixdev == 0) {
1364 dprintf_mciwave(stddeb,"Linux 'widPrepare' // can't prepare !\n");
1365 return MMSYSERR_NOTENABLED;
1367 if (WInDev[wDevID].lpQueueHdr != NULL) {
1368 dprintf_mciwave(stddeb,"Linux 'widPrepare' // already prepare !\n");
1369 return WAVERR_BADFORMAT;
1371 if (lpWaveHdr->dwFlags & WHDR_INQUEUE) return WAVERR_STILLPLAYING;
1372 lpWaveHdr->dwFlags |= WHDR_PREPARED;
1373 lpWaveHdr->dwFlags &= ~WHDR_INQUEUE;
1374 lpWaveHdr->dwFlags &= ~WHDR_DONE;
1375 lpWaveHdr->dwBytesRecorded = 0;
1376 dprintf_mciwave(stddeb,"Linux 'widPrepare' // header prepared !\n");
1377 return MMSYSERR_NOERROR;
1380 /**************************************************************************
1381 * widUnprepare [internal]
1383 static DWORD widUnprepare(WORD wDevID, LPWAVEHDR lpWaveHdr, DWORD dwSize)
1385 dprintf_mciwave(stddeb,
1386 "widUnprepare(%u, %p, %08lX);\n", wDevID, lpWaveHdr, dwSize);
1387 if (WInDev[wDevID].unixdev == 0) {
1388 dprintf_mciwave(stddeb,"Linux 'widUnprepare' // can't unprepare !\n");
1389 return MMSYSERR_NOTENABLED;
1391 lpWaveHdr->dwFlags &= ~WHDR_PREPARED;
1392 lpWaveHdr->dwFlags &= ~WHDR_INQUEUE;
1393 lpWaveHdr->dwFlags |= WHDR_DONE;
1394 WInDev[wDevID].lpQueueHdr = NULL;
1395 dprintf_mciwave(stddeb,
1396 "Linux 'widUnprepare' // all headers unprepared !\n");
1397 return MMSYSERR_NOERROR;
1400 /**************************************************************************
1401 * widStart [internal]
1403 static DWORD widStart(WORD wDevID)
1405 int count = 1;
1406 LPWAVEHDR lpWIHdr;
1407 dprintf_mciwave(stddeb,"widStart(%u);\n", wDevID);
1408 if (WInDev[wDevID].unixdev == 0) {
1409 dprintf_mciwave(stddeb, "Linux 'widStart' // can't start recording !\n");
1410 return MMSYSERR_NOTENABLED;
1412 if (WInDev[wDevID].lpQueueHdr == NULL ||
1413 WInDev[wDevID].lpQueueHdr->lpData == NULL) {
1414 dprintf_mciwave(stddeb,"Linux 'widStart' // never been prepared !\n");
1415 return WAVERR_UNPREPARED;
1417 lpWIHdr = WInDev[wDevID].lpQueueHdr;
1418 while(lpWIHdr != NULL) {
1419 lpWIHdr->dwBufferLength &= 0xFFFF;
1420 dprintf_mciwave(stddeb,
1421 "widStart // recording buf#%u=%p size=%lu \n",
1422 count, lpWIHdr->lpData, lpWIHdr->dwBufferLength);
1423 fflush(stddeb);
1424 read (WInDev[wDevID].unixdev,
1425 PTR_SEG_TO_LIN(lpWIHdr->lpData),
1426 lpWIHdr->dwBufferLength);
1427 lpWIHdr->dwBytesRecorded = lpWIHdr->dwBufferLength;
1428 WInDev[wDevID].dwTotalRecorded += lpWIHdr->dwBytesRecorded;
1429 lpWIHdr->dwFlags &= ~WHDR_INQUEUE;
1430 lpWIHdr->dwFlags |= WHDR_DONE;
1431 if (WAVE_NotifyClient(wDevID, WIM_DATA, (DWORD)lpWIHdr, 0L) !=
1432 MMSYSERR_NOERROR) {
1433 dprintf_mciwave(stddeb, "Linux 'widStart' // can't notify client !\n");
1434 return MMSYSERR_INVALPARAM;
1436 lpWIHdr = lpWIHdr->lpNext;
1437 count++;
1439 dprintf_mciwave(stddeb,"widStart // end of recording !\n");
1440 fflush(stdout);
1441 return MMSYSERR_NOERROR;
1444 /**************************************************************************
1445 * widStop [internal]
1447 static DWORD widStop(WORD wDevID)
1449 dprintf_mciwave(stddeb,"widStop(%u);\n", wDevID);
1450 if (WInDev[wDevID].unixdev == 0) {
1451 dprintf_mciwave(stddeb,"Linux 'widStop' // can't stop !\n");
1452 return MMSYSERR_NOTENABLED;
1454 return MMSYSERR_NOERROR;
1457 /**************************************************************************
1458 * widReset [internal]
1460 static DWORD widReset(WORD wDevID)
1462 dprintf_mciwave(stddeb,"widReset(%u);\n", wDevID);
1463 if (WInDev[wDevID].unixdev == 0) {
1464 dprintf_mciwave(stddeb,"Linux 'widReset' // can't reset !\n");
1465 return MMSYSERR_NOTENABLED;
1467 return MMSYSERR_NOERROR;
1470 /**************************************************************************
1471 * widGetPosition [internal]
1473 static DWORD widGetPosition(WORD wDevID, LPMMTIME lpTime, DWORD uSize)
1475 int time;
1477 dprintf_mciwave(stddeb,
1478 "widGetPosition(%u, %p, %lu);\n", wDevID, lpTime, uSize);
1479 if (WInDev[wDevID].unixdev == 0) {
1480 dprintf_mciwave(stddeb,"Linux 'widGetPosition' // can't get pos !\n");
1481 return MMSYSERR_NOTENABLED;
1483 if (lpTime == NULL) return MMSYSERR_INVALPARAM;
1484 dprintf_mciwave(stddeb,"widGetPosition // wType=%04X !\n",
1485 lpTime->wType);
1486 dprintf_mciwave(stddeb,"widGetPosition // wBitsPerSample=%u\n",
1487 WInDev[wDevID].Format.wBitsPerSample);
1488 dprintf_mciwave(stddeb,"widGetPosition // nSamplesPerSec=%lu\n",
1489 WInDev[wDevID].Format.wf.nSamplesPerSec);
1490 dprintf_mciwave(stddeb,"widGetPosition // nChannels=%u\n",
1491 WInDev[wDevID].Format.wf.nChannels);
1492 dprintf_mciwave(stddeb,"widGetPosition // nAvgBytesPerSec=%lu\n",
1493 WInDev[wDevID].Format.wf.nAvgBytesPerSec);
1494 fflush(stddeb);
1495 switch(lpTime->wType) {
1496 case TIME_BYTES:
1497 lpTime->u.cb = WInDev[wDevID].dwTotalRecorded;
1498 dprintf_mciwave(stddeb,
1499 "widGetPosition // TIME_BYTES=%lu\n", lpTime->u.cb);
1500 break;
1501 case TIME_SAMPLES:
1502 lpTime->u.sample = WInDev[wDevID].dwTotalRecorded * 8 /
1503 WInDev[wDevID].Format.wBitsPerSample;
1504 dprintf_mciwave(stddeb,
1505 "widGetPosition // TIME_SAMPLES=%lu\n",
1506 lpTime->u.sample);
1507 break;
1508 case TIME_SMPTE:
1509 time = WInDev[wDevID].dwTotalRecorded /
1510 (WInDev[wDevID].Format.wf.nAvgBytesPerSec / 1000);
1511 lpTime->u.smpte.hour = time / 108000;
1512 time -= lpTime->u.smpte.hour * 108000;
1513 lpTime->u.smpte.min = time / 1800;
1514 time -= lpTime->u.smpte.min * 1800;
1515 lpTime->u.smpte.sec = time / 30;
1516 time -= lpTime->u.smpte.sec * 30;
1517 lpTime->u.smpte.frame = time;
1518 lpTime->u.smpte.fps = 30;
1519 dprintf_mciwave(stddeb,"widGetPosition // TIME_SMPTE=%02u:%02u:%02u:%02u\n",
1520 lpTime->u.smpte.hour, lpTime->u.smpte.min,
1521 lpTime->u.smpte.sec, lpTime->u.smpte.frame);
1522 break;
1523 default:
1524 dprintf_mciwave(stddeb,"widGetPosition() format not supported ! use TIME_MS !\n");
1525 lpTime->wType = TIME_MS;
1526 case TIME_MS:
1527 lpTime->u.ms = WInDev[wDevID].dwTotalRecorded /
1528 (WInDev[wDevID].Format.wf.nAvgBytesPerSec / 1000);
1529 dprintf_mciwave(stddeb,
1530 "widGetPosition // TIME_MS=%lu\n", lpTime->u.ms);
1531 break;
1533 return MMSYSERR_NOERROR;
1536 #endif /* linux */
1538 /**************************************************************************
1539 * widMessage [sample driver]
1541 DWORD widMessage(WORD wDevID, WORD wMsg, DWORD dwUser,
1542 DWORD dwParam1, DWORD dwParam2)
1544 dprintf_mciwave(stddeb,"widMessage(%u, %04X, %08lX, %08lX, %08lX);\n",
1545 wDevID, wMsg, dwUser, dwParam1, dwParam2);
1546 #ifdef linux
1547 switch(wMsg) {
1548 case WIDM_OPEN:
1549 return widOpen(wDevID, (LPWAVEOPENDESC)PTR_SEG_TO_LIN(dwParam1), dwParam2);
1550 case WIDM_CLOSE:
1551 return widClose(wDevID);
1552 case WIDM_ADDBUFFER:
1553 return widAddBuffer(wDevID, (LPWAVEHDR)PTR_SEG_TO_LIN(dwParam1), dwParam2);
1554 case WIDM_PREPARE:
1555 return widPrepare(wDevID, (LPWAVEHDR)PTR_SEG_TO_LIN(dwParam1), dwParam2);
1556 case WIDM_UNPREPARE:
1557 return widUnprepare(wDevID, (LPWAVEHDR)PTR_SEG_TO_LIN(dwParam1), dwParam2);
1558 case WIDM_GETDEVCAPS:
1559 return widGetDevCaps(wDevID, (LPWAVEINCAPS)PTR_SEG_TO_LIN(dwParam1), dwParam2);
1560 case WIDM_GETNUMDEVS:
1561 return 1;
1562 case WIDM_GETPOS:
1563 return widGetPosition(wDevID, (LPMMTIME)PTR_SEG_TO_LIN(dwParam1), dwParam2);
1564 case WIDM_RESET:
1565 return widReset(wDevID);
1566 case WIDM_START:
1567 return widStart(wDevID);
1568 case WIDM_STOP:
1569 return widStop(wDevID);
1570 default:
1571 dprintf_mciwave(stddeb,"widMessage // unknown message !\n");
1573 return MMSYSERR_NOTSUPPORTED;
1574 #else
1575 return MMSYSERR_NOTENABLED;
1576 #endif
1580 /**************************************************************************
1581 * AUDIO_DriverProc [sample driver]
1583 LONG WAVE_DriverProc(DWORD dwDevID, HDRVR hDriv, WORD wMsg,
1584 DWORD dwParam1, DWORD dwParam2)
1586 #ifdef linux
1587 dprintf_mciwave(stddeb,"WAVE_DriverProc(%08lX, %04X, %04X, %08lX, %08lX)\n",
1588 dwDevID, hDriv, wMsg, dwParam1, dwParam2);
1589 switch(wMsg) {
1590 case DRV_LOAD:
1591 return 1;
1592 case DRV_FREE:
1593 return 1;
1594 case DRV_OPEN:
1595 return 1;
1596 case DRV_CLOSE:
1597 return 1;
1598 case DRV_ENABLE:
1599 return 1;
1600 case DRV_DISABLE:
1601 return 1;
1602 case DRV_QUERYCONFIGURE:
1603 return 1;
1604 case DRV_CONFIGURE:
1605 MessageBox((HWND)NULL, "Sample MultiMedia Linux Driver !",
1606 "MMLinux Driver", MB_OK);
1607 return 1;
1608 case DRV_INSTALL:
1609 return DRVCNF_RESTART;
1610 case DRV_REMOVE:
1611 return DRVCNF_RESTART;
1612 case MCI_OPEN_DRIVER:
1613 case MCI_OPEN:
1614 return WAVE_mciOpen(dwDevID, dwParam1, (LPMCI_WAVE_OPEN_PARMS)PTR_SEG_TO_LIN(dwParam2));
1615 case MCI_CLOSE_DRIVER:
1616 case MCI_CLOSE:
1617 return WAVE_mciClose(dwDevID, dwParam1, (LPMCI_GENERIC_PARMS)PTR_SEG_TO_LIN(dwParam2));
1618 case MCI_PLAY:
1619 return WAVE_mciPlay(dwDevID, dwParam1, (LPMCI_PLAY_PARMS)PTR_SEG_TO_LIN(dwParam2));
1620 case MCI_RECORD:
1621 return WAVE_mciRecord(dwDevID, dwParam1, (LPMCI_RECORD_PARMS)PTR_SEG_TO_LIN(dwParam2));
1622 case MCI_STOP:
1623 return WAVE_mciStop(dwDevID, dwParam1, (LPMCI_GENERIC_PARMS)PTR_SEG_TO_LIN(dwParam2));
1624 case MCI_SET:
1625 return WAVE_mciSet(dwDevID, dwParam1, (LPMCI_SET_PARMS)PTR_SEG_TO_LIN(dwParam2));
1626 case MCI_PAUSE:
1627 return WAVE_mciPause(dwDevID, dwParam1, (LPMCI_GENERIC_PARMS)PTR_SEG_TO_LIN(dwParam2));
1628 case MCI_RESUME:
1629 return WAVE_mciResume(dwDevID, dwParam1, (LPMCI_GENERIC_PARMS)PTR_SEG_TO_LIN(dwParam2));
1630 case MCI_STATUS:
1631 return WAVE_mciStatus(dwDevID, dwParam1, (LPMCI_STATUS_PARMS)PTR_SEG_TO_LIN(dwParam2));
1632 case MCI_GETDEVCAPS:
1633 return WAVE_mciGetDevCaps(dwDevID, dwParam1, (LPMCI_GETDEVCAPS_PARMS)PTR_SEG_TO_LIN(dwParam2));
1634 case MCI_INFO:
1635 return WAVE_mciInfo(dwDevID, dwParam1, (LPMCI_INFO_PARMS)PTR_SEG_TO_LIN(dwParam2));
1636 default:
1637 return DefDriverProc(dwDevID, hDriv, wMsg, dwParam1, dwParam2);
1639 #else
1640 return MMSYSERR_NOTENABLED;
1641 #endif
1645 #endif /* #ifdef BUILTIN_MMSYSTEM */