Release 961013
[wine/multimedia.git] / multimedia / audio.c
blobf92a6b7df099ac95b2267015a8d07d4c8f2d3e1d
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"
26 #ifdef linux
27 #include <linux/soundcard.h>
28 #elif __FreeBSD__
29 #include <machine/soundcard.h>
30 #endif
32 #include "stddebug.h"
33 #include "debug.h"
35 #if defined(linux) || defined(__FreeBSD__)
36 #define SOUND_DEV "/dev/dsp"
38 #ifdef SOUND_VERSION
39 #define IOCTL(a,b,c) ((-1==ioctl(a,b,&c))&&(perror("ioctl:"#b":"#c),0))
40 #else
41 #define IOCTL(a,b,c) (c = ioctl(a,b,c) )
42 #endif
44 #define MAX_WAVOUTDRV 2
45 #define MAX_WAVINDRV 2
46 #define MAX_MCIWAVDRV 2
48 typedef struct {
49 int unixdev;
50 int state;
51 DWORD bufsize;
52 WAVEOPENDESC waveDesc;
53 WORD wFlags;
54 PCMWAVEFORMAT Format;
55 LPWAVEHDR lpQueueHdr;
56 DWORD dwTotalPlayed;
57 } LINUX_WAVEOUT;
59 typedef struct {
60 int unixdev;
61 int state;
62 DWORD bufsize; /* Linux '/dev/dsp' give us that size */
63 WAVEOPENDESC waveDesc;
64 WORD wFlags;
65 PCMWAVEFORMAT Format;
66 LPWAVEHDR lpQueueHdr;
67 DWORD dwTotalRecorded;
68 } LINUX_WAVEIN;
70 typedef struct {
71 int nUseCount; /* Incremented for each shared open */
72 BOOL fShareable; /* TRUE if first open was shareable */
73 WORD wNotifyDeviceID; /* MCI device ID with a pending notification */
74 HANDLE16 hCallback; /* Callback handle for pending notification */
75 HMMIO16 hFile; /* mmio file handle open as Element */
76 MCI_WAVE_OPEN_PARMS openParms;
77 PCMWAVEFORMAT WaveFormat;
78 WAVEHDR WaveHdr;
79 } LINUX_MCIWAVE;
81 static LINUX_WAVEOUT WOutDev[MAX_WAVOUTDRV];
82 static LINUX_WAVEIN WInDev[MAX_WAVOUTDRV];
83 static LINUX_MCIWAVE MCIWavDev[MAX_MCIWAVDRV];
86 /**************************************************************************
87 * WAVE_NotifyClient [internal]
89 static DWORD WAVE_NotifyClient(UINT wDevID, WORD wMsg,
90 DWORD dwParam1, DWORD dwParam2)
92 if (WInDev[wDevID].wFlags != DCB_NULL && !DriverCallback(
93 WInDev[wDevID].waveDesc.dwCallBack, WInDev[wDevID].wFlags,
94 WInDev[wDevID].waveDesc.hWave, wMsg,
95 WInDev[wDevID].waveDesc.dwInstance, dwParam1, dwParam2)) {
96 dprintf_mciwave(stddeb,"WAVE_NotifyClient // can't notify client !\n");
97 return MMSYSERR_NOERROR;
99 return 0;
103 /**************************************************************************
104 * WAVE_mciOpen */
105 static DWORD WAVE_mciOpen(UINT wDevID, DWORD dwFlags, LPMCI_WAVE_OPEN_PARMS lpParms)
107 HLOCAL16 hFormat;
108 LPPCMWAVEFORMAT lpWaveFormat;
109 HLOCAL16 hDesc;
110 LPWAVEOPENDESC lpDesc;
111 LPSTR lpstrElementName;
112 DWORD dwRet;
113 char str[128];
115 dprintf_mciwave(stddeb,"WAVE_mciOpen(%04X, %08lX, %p)\n",
116 wDevID, dwFlags, lpParms);
117 if (lpParms == NULL) return MCIERR_INTERNAL;
118 dprintf_mciwave(stddeb,"WAVE_mciOpen // wDevID=%04X\n", wDevID);
119 if (MCIWavDev[wDevID].nUseCount > 0) {
120 /* The driver already open on this channel */
121 /* If the driver was opened shareable before and this open specifies */
122 /* shareable then increment the use count */
123 if (MCIWavDev[wDevID].fShareable && (dwFlags & MCI_OPEN_SHAREABLE))
124 ++MCIWavDev[wDevID].nUseCount;
125 else
126 return MCIERR_MUST_USE_SHAREABLE;
128 else {
129 MCIWavDev[wDevID].nUseCount = 1;
130 MCIWavDev[wDevID].fShareable = dwFlags & MCI_OPEN_SHAREABLE;
132 lpParms->wDeviceID = wDevID;
133 dprintf_mciwave(stddeb,"WAVE_mciOpen // wDevID=%04X\n", wDevID);
134 dprintf_mciwave(stddeb,"WAVE_mciOpen // before OPEN_ELEMENT\n");
135 if (dwFlags & MCI_OPEN_ELEMENT) {
136 lpstrElementName = (LPSTR)PTR_SEG_TO_LIN(lpParms->lpstrElementName);
137 dprintf_mciwave(stddeb,"WAVE_mciOpen // MCI_OPEN_ELEMENT '%s' !\n",
138 lpstrElementName);
139 if (strlen(lpstrElementName) > 0) {
140 strcpy(str, lpstrElementName);
141 AnsiUpper(str);
142 MCIWavDev[wDevID].hFile = mmioOpen(str, NULL,
143 MMIO_ALLOCBUF | MMIO_READWRITE | MMIO_EXCLUSIVE);
144 if (MCIWavDev[wDevID].hFile == 0) {
145 dprintf_mciwave(stddeb,"WAVE_mciOpen // can't find file='%s' !\n", str);
146 return MCIERR_FILE_NOT_FOUND;
149 else
150 MCIWavDev[wDevID].hFile = 0;
152 dprintf_mciwave(stddeb,"WAVE_mciOpen // hFile=%u\n", MCIWavDev[wDevID].hFile);
153 memcpy(&MCIWavDev[wDevID].openParms, lpParms, sizeof(MCI_WAVE_OPEN_PARMS));
154 MCIWavDev[wDevID].wNotifyDeviceID = lpParms->wDeviceID;
155 lpWaveFormat = &MCIWavDev[wDevID].WaveFormat;
156 hDesc = USER_HEAP_ALLOC(sizeof(WAVEOPENDESC));
157 lpDesc = (LPWAVEOPENDESC) USER_HEAP_LIN_ADDR(hDesc);
158 lpDesc->hWave = 0;
160 lpWaveFormat->wf.wFormatTag = WAVE_FORMAT_PCM;
161 lpWaveFormat->wBitsPerSample = 8;
162 lpWaveFormat->wf.nChannels = 1;
163 lpWaveFormat->wf.nSamplesPerSec = 11025;
164 lpWaveFormat->wf.nAvgBytesPerSec = 11025;
165 lpWaveFormat->wf.nBlockAlign = 1;
167 if (MCIWavDev[wDevID].hFile != 0) {
168 MMCKINFO mmckInfo;
169 MMCKINFO ckMainRIFF;
170 if (mmioDescend(MCIWavDev[wDevID].hFile, &ckMainRIFF, NULL, 0) != 0) {
171 return MCIERR_INTERNAL;
173 dprintf_mciwave(stddeb,
174 "WAVE_mciOpen // ParentChunk ckid=%.4s fccType=%.4s cksize=%08lX \n",
175 (LPSTR)&ckMainRIFF.ckid, (LPSTR)&ckMainRIFF.fccType,
176 ckMainRIFF.cksize);
177 if ((ckMainRIFF.ckid != FOURCC_RIFF) ||
178 (ckMainRIFF.fccType != mmioFOURCC('W', 'A', 'V', 'E'))) {
179 return MCIERR_INTERNAL;
181 mmckInfo.ckid = mmioFOURCC('f', 'm', 't', ' ');
182 if (mmioDescend(MCIWavDev[wDevID].hFile, &mmckInfo, &ckMainRIFF, MMIO_FINDCHUNK) != 0) {
183 return MCIERR_INTERNAL;
185 dprintf_mciwave(stddeb,
186 "WAVE_mciOpen // Chunk Found ckid=%.4s fccType=%.4s cksize=%08lX \n",
187 (LPSTR)&mmckInfo.ckid, (LPSTR)&mmckInfo.fccType,
188 mmckInfo.cksize);
189 if (mmioRead(MCIWavDev[wDevID].hFile, (HPSTR) lpWaveFormat,
190 (long) sizeof(PCMWAVEFORMAT)) != (long) sizeof(PCMWAVEFORMAT)) {
191 return MCIERR_INTERNAL;
193 mmckInfo.ckid = mmioFOURCC('d', 'a', 't', 'a');
194 if (mmioDescend(MCIWavDev[wDevID].hFile, &mmckInfo, &ckMainRIFF, MMIO_FINDCHUNK) != 0) {
195 return MCIERR_INTERNAL;
197 dprintf_mciwave(stddeb,
198 "WAVE_mciOpen // Chunk Found ckid=%.4s fccType=%.4s cksize=%08lX \n",
199 (LPSTR)&mmckInfo.ckid, (LPSTR)&mmckInfo.fccType,
200 mmckInfo.cksize);
201 dprintf_mciwave(stddeb,
202 "WAVE_mciOpen // nChannels=%d nSamplesPerSec=%ld\n",
203 lpWaveFormat->wf.nChannels, lpWaveFormat->wf.nSamplesPerSec);
204 lpWaveFormat->wBitsPerSample = 0;
206 lpWaveFormat->wf.nAvgBytesPerSec =
207 lpWaveFormat->wf.nSamplesPerSec * lpWaveFormat->wf.nBlockAlign;
208 hFormat = USER_HEAP_ALLOC(sizeof(PCMWAVEFORMAT));
209 lpDesc->lpFormat = (LPWAVEFORMAT) USER_HEAP_LIN_ADDR(hFormat);
210 memcpy(lpDesc->lpFormat, lpWaveFormat, sizeof(PCMWAVEFORMAT));
211 lpDesc = (LPWAVEOPENDESC) USER_HEAP_SEG_ADDR(hDesc);
212 dwRet = wodMessage(0, WODM_OPEN, 0, (DWORD)lpDesc, CALLBACK_NULL);
213 dwRet = widMessage(0, WIDM_OPEN, 0, (DWORD)lpDesc, CALLBACK_NULL);
214 USER_HEAP_FREE(hFormat);
215 USER_HEAP_FREE(hDesc);
216 return 0;
219 /**************************************************************************
220 * WAVE_mciClose [internal]
222 static DWORD WAVE_mciClose(UINT wDevID, DWORD dwParam, LPMCI_GENERIC_PARMS lpParms)
224 DWORD dwRet;
225 dprintf_mciwave(stddeb,
226 "WAVE_mciClose(%u, %08lX, %p);\n", wDevID, dwParam, lpParms);
227 MCIWavDev[wDevID].nUseCount--;
228 if (MCIWavDev[wDevID].nUseCount == 0) {
229 if (MCIWavDev[wDevID].hFile != 0) {
230 mmioClose(MCIWavDev[wDevID].hFile, 0);
231 MCIWavDev[wDevID].hFile = 0;
233 dwRet = wodMessage(0, WODM_CLOSE, 0, 0L, 0L);
234 if (dwRet != MMSYSERR_NOERROR) return MCIERR_INTERNAL;
235 dwRet = widMessage(0, WIDM_CLOSE, 0, 0L, 0L);
236 if (dwRet != MMSYSERR_NOERROR) return MCIERR_INTERNAL;
238 return 0;
242 /**************************************************************************
243 * WAVE_mciPlay [internal]
245 static DWORD WAVE_mciPlay(UINT wDevID, DWORD dwFlags, LPMCI_PLAY_PARMS lpParms)
247 int start, end;
248 LONG bufsize, count;
249 HGLOBAL16 hData;
250 HLOCAL16 hWaveHdr;
251 LPWAVEHDR lpWaveHdr;
252 LPWAVEHDR lp16WaveHdr;
253 DWORD dwRet;
254 dprintf_mciwave(stddeb,
255 "WAVE_mciPlay(%u, %08lX, %p);\n", wDevID, dwFlags, lpParms);
256 if (MCIWavDev[wDevID].hFile == 0) {
257 dprintf_mciwave(stddeb,"WAVE_mciPlay // can't find file='%s' !\n",
258 MCIWavDev[wDevID].openParms.lpstrElementName);
259 return MCIERR_FILE_NOT_FOUND;
261 start = 1; end = 99999;
262 if (dwFlags & MCI_FROM) {
263 start = lpParms->dwFrom;
264 dprintf_mciwave(stddeb,
265 "WAVE_mciPlay // MCI_FROM=%d \n", start);
267 if (dwFlags & MCI_TO) {
268 end = lpParms->dwTo;
269 dprintf_mciwave(stddeb,"WAVE_mciPlay // MCI_TO=%d \n", end);
271 #if 0
272 if (dwFlags & MCI_NOTIFY) {
273 dprintf_mciwave(stddeb,
274 "WAVE_mciPlay // MCI_NOTIFY %08lX !\n", lpParms->dwCallback);
275 switch(fork()) {
276 case -1:
277 dprintf_mciwave(stddeb,
278 "WAVE_mciPlay // Can't 'fork' process !\n");
279 break;
280 case 0:
281 break;
282 default:
283 dprintf_mciwave(stddeb,"WAVE_mciPlay // process started ! return to caller...\n");
284 return 0;
287 #endif
288 bufsize = 64000;
289 lpWaveHdr = &MCIWavDev[wDevID].WaveHdr;
290 hData = GlobalAlloc16(GMEM_MOVEABLE, bufsize);
291 lpWaveHdr->lpData = (LPSTR) WIN16_GlobalLock16(hData);
292 lpWaveHdr->dwUser = 0L;
293 lpWaveHdr->dwFlags = 0L;
294 lpWaveHdr->dwLoops = 0L;
295 hWaveHdr = USER_HEAP_ALLOC(sizeof(WAVEHDR));
296 lp16WaveHdr = (LPWAVEHDR) USER_HEAP_SEG_ADDR(hWaveHdr);
297 memcpy(PTR_SEG_TO_LIN(lp16WaveHdr), lpWaveHdr, sizeof(WAVEHDR));
298 lpWaveHdr = PTR_SEG_TO_LIN(lp16WaveHdr);
299 dwRet = wodMessage(0, WODM_PREPARE, 0, (DWORD)lp16WaveHdr, sizeof(WAVEHDR));
300 while(TRUE) {
301 count = mmioRead(MCIWavDev[wDevID].hFile,
302 PTR_SEG_TO_LIN(lpWaveHdr->lpData), bufsize);
303 dprintf_mciwave(stddeb,"WAVE_mciPlay // mmioRead bufsize=%ld count=%ld\n", bufsize, count);
304 if (count < 1) break;
305 lpWaveHdr->dwBufferLength = count;
306 /* lpWaveHdr->dwBytesRecorded = count; */
307 dprintf_mciwave(stddeb,"WAVE_mciPlay // before WODM_WRITE lpWaveHdr=%p dwBufferLength=%lu dwBytesRecorded=%lu\n",
308 lpWaveHdr, lpWaveHdr->dwBufferLength, lpWaveHdr->dwBytesRecorded);
309 dwRet = wodMessage(0, WODM_WRITE, 0, (DWORD)lp16WaveHdr, sizeof(WAVEHDR));
311 dwRet = wodMessage(0, WODM_UNPREPARE, 0, (DWORD)lp16WaveHdr, sizeof(WAVEHDR));
312 if (lpWaveHdr->lpData != NULL) {
313 GlobalUnlock16(hData);
314 GlobalFree16(hData);
315 lpWaveHdr->lpData = NULL;
317 USER_HEAP_FREE(hWaveHdr);
318 if (dwFlags & MCI_NOTIFY) {
319 dprintf_mciwave(stddeb,"WAVE_mciPlay // MCI_NOTIFY_SUCCESSFUL %08lX !\n", lpParms->dwCallback);
320 mciDriverNotify((HWND)LOWORD(lpParms->dwCallback),
321 MCIWavDev[wDevID].wNotifyDeviceID, MCI_NOTIFY_SUCCESSFUL);
323 return 0;
327 /**************************************************************************
328 * WAVE_mciRecord [internal]
330 static DWORD WAVE_mciRecord(UINT wDevID, DWORD dwFlags, LPMCI_RECORD_PARMS lpParms)
332 int start, end;
333 LONG bufsize;
334 HGLOBAL16 hData;
335 HLOCAL16 hWaveHdr;
336 LPWAVEHDR lpWaveHdr;
337 LPWAVEHDR lp16WaveHdr;
338 DWORD dwRet;
340 dprintf_mciwave(stddeb,
341 "WAVE_mciRecord(%u, %08lX, %p);\n", wDevID, dwFlags, lpParms);
342 if (MCIWavDev[wDevID].hFile == 0) {
343 dprintf_mciwave(stddeb,"WAVE_mciRecord // can't find file='%s' !\n",
344 MCIWavDev[wDevID].openParms.lpstrElementName);
345 return MCIERR_FILE_NOT_FOUND;
347 start = 1; end = 99999;
348 if (dwFlags & MCI_FROM) {
349 start = lpParms->dwFrom;
350 dprintf_mciwave(stddeb,
351 "WAVE_mciRecord // MCI_FROM=%d \n", start);
353 if (dwFlags & MCI_TO) {
354 end = lpParms->dwTo;
355 dprintf_mciwave(stddeb,"WAVE_mciRecord // MCI_TO=%d \n", end);
357 bufsize = 64000;
358 lpWaveHdr = &MCIWavDev[wDevID].WaveHdr;
359 hData = GlobalAlloc16(GMEM_MOVEABLE, bufsize);
360 lpWaveHdr->lpData = (LPSTR) WIN16_GlobalLock16(hData);
361 lpWaveHdr->dwBufferLength = bufsize;
362 lpWaveHdr->dwUser = 0L;
363 lpWaveHdr->dwFlags = 0L;
364 lpWaveHdr->dwLoops = 0L;
365 hWaveHdr = USER_HEAP_ALLOC(sizeof(WAVEHDR));
366 lp16WaveHdr = (LPWAVEHDR) USER_HEAP_SEG_ADDR(hWaveHdr);
367 memcpy(PTR_SEG_TO_LIN(lp16WaveHdr), lpWaveHdr, sizeof(WAVEHDR));
368 lpWaveHdr = PTR_SEG_TO_LIN(lp16WaveHdr);
369 dwRet = widMessage(0, WIDM_PREPARE, 0, (DWORD)lp16WaveHdr, sizeof(WAVEHDR));
370 dprintf_mciwave(stddeb,"WAVE_mciRecord // after WIDM_PREPARE \n");
371 while(TRUE) {
372 lpWaveHdr->dwBytesRecorded = 0;
373 dwRet = widMessage(0, WIDM_START, 0, 0L, 0L);
374 dprintf_mciwave(stddeb,
375 "WAVE_mciRecord // after WIDM_START lpWaveHdr=%p dwBytesRecorded=%lu\n",
376 lpWaveHdr, lpWaveHdr->dwBytesRecorded);
377 if (lpWaveHdr->dwBytesRecorded == 0) break;
379 dprintf_mciwave(stddeb,"WAVE_mciRecord // before WIDM_UNPREPARE \n");
380 dwRet = widMessage(0, WIDM_UNPREPARE, 0, (DWORD)lp16WaveHdr, sizeof(WAVEHDR));
381 dprintf_mciwave(stddeb,"WAVE_mciRecord // after WIDM_UNPREPARE \n");
382 if (lpWaveHdr->lpData != NULL) {
383 GlobalUnlock16(hData);
384 GlobalFree16(hData);
385 lpWaveHdr->lpData = NULL;
387 USER_HEAP_FREE(hWaveHdr);
388 if (dwFlags & MCI_NOTIFY) {
389 dprintf_mciwave(stddeb,"WAVE_mciRecord // MCI_NOTIFY_SUCCESSFUL %08lX !\n", lpParms->dwCallback);
390 mciDriverNotify((HWND)LOWORD(lpParms->dwCallback),
391 MCIWavDev[wDevID].wNotifyDeviceID, MCI_NOTIFY_SUCCESSFUL);
393 return 0;
397 /**************************************************************************
398 * WAVE_mciStop [internal]
400 static DWORD WAVE_mciStop(UINT wDevID, DWORD dwFlags, LPMCI_GENERIC_PARMS lpParms)
402 dprintf_mciwave(stddeb,
403 "WAVE_mciStop(%u, %08lX, %p);\n", wDevID, dwFlags, lpParms);
404 if (lpParms == NULL) return MCIERR_INTERNAL;
405 return 0;
409 /**************************************************************************
410 * WAVE_mciPause [internal]
412 static DWORD WAVE_mciPause(UINT wDevID, DWORD dwFlags, LPMCI_GENERIC_PARMS lpParms)
414 dprintf_mciwave(stddeb,
415 "WAVE_mciPause(%u, %08lX, %p);\n", wDevID, dwFlags, lpParms);
416 if (lpParms == NULL) return MCIERR_INTERNAL;
417 return 0;
421 /**************************************************************************
422 * WAVE_mciResume [internal]
424 static DWORD WAVE_mciResume(UINT wDevID, DWORD dwFlags, LPMCI_GENERIC_PARMS lpParms)
426 dprintf_mciwave(stddeb,
427 "WAVE_mciResume(%u, %08lX, %p);\n", wDevID, dwFlags, lpParms);
428 if (lpParms == NULL) return MCIERR_INTERNAL;
429 return 0;
433 /**************************************************************************
434 * WAVE_mciSet [internal]
436 static DWORD WAVE_mciSet(UINT wDevID, DWORD dwFlags, LPMCI_SET_PARMS lpParms)
438 dprintf_mciwave(stddeb,
439 "WAVE_mciSet(%u, %08lX, %p);\n", wDevID, dwFlags, lpParms);
440 if (lpParms == NULL) return MCIERR_INTERNAL;
441 dprintf_mciwave(stddeb,
442 "WAVE_mciSet // dwTimeFormat=%08lX\n", lpParms->dwTimeFormat);
443 dprintf_mciwave(stddeb,
444 "WAVE_mciSet // dwAudio=%08lX\n", lpParms->dwAudio);
445 if (dwFlags & MCI_SET_TIME_FORMAT) {
446 switch (lpParms->dwTimeFormat) {
447 case MCI_FORMAT_MILLISECONDS:
448 dprintf_mciwave(stddeb, "WAVE_mciSet // MCI_FORMAT_MILLISECONDS !\n");
449 break;
450 case MCI_FORMAT_BYTES:
451 dprintf_mciwave(stddeb, "WAVE_mciSet // MCI_FORMAT_BYTES !\n");
452 break;
453 case MCI_FORMAT_SAMPLES:
454 dprintf_mciwave(stddeb, "WAVE_mciSet // MCI_FORMAT_SAMPLES !\n");
455 break;
456 default:
457 dprintf_mciwave(stddeb, "WAVE_mciSet // bad time format !\n");
458 return MCIERR_BAD_TIME_FORMAT;
461 if (dwFlags & MCI_SET_VIDEO) return MCIERR_UNSUPPORTED_FUNCTION;
462 if (dwFlags & MCI_SET_DOOR_OPEN) return MCIERR_UNSUPPORTED_FUNCTION;
463 if (dwFlags & MCI_SET_DOOR_CLOSED) return MCIERR_UNSUPPORTED_FUNCTION;
464 if (dwFlags & MCI_SET_AUDIO)
465 dprintf_mciwave(stddeb,"WAVE_mciSet // MCI_SET_AUDIO !\n");
466 if (dwFlags && MCI_SET_ON) {
467 dprintf_mciwave(stddeb,"WAVE_mciSet // MCI_SET_ON !\n");
468 if (dwFlags && MCI_SET_AUDIO_LEFT)
469 dprintf_mciwave(stddeb,"WAVE_mciSet // MCI_SET_AUDIO_LEFT !\n");
470 if (dwFlags && MCI_SET_AUDIO_RIGHT)
471 dprintf_mciwave(stddeb,"WAVE_mciSet // MCI_SET_AUDIO_RIGHT !\n");
473 if (dwFlags & MCI_SET_OFF)
474 dprintf_mciwave(stddeb,"WAVE_mciSet // MCI_SET_OFF !\n");
475 if (dwFlags & MCI_WAVE_INPUT)
476 dprintf_mciwave(stddeb,"WAVE_mciSet // MCI_WAVE_INPUT !\n");
477 if (dwFlags & MCI_WAVE_OUTPUT)
478 dprintf_mciwave(stddeb,"WAVE_mciSet // MCI_WAVE_OUTPUT !\n");
479 if (dwFlags & MCI_WAVE_SET_ANYINPUT)
480 dprintf_mciwave(stddeb,"WAVE_mciSet // MCI_WAVE_SET_ANYINPUT !\n");
481 if (dwFlags & MCI_WAVE_SET_ANYOUTPUT)
482 dprintf_mciwave(stddeb,"WAVE_mciSet // MCI_WAVE_SET_ANYOUTPUT !\n");
483 if (dwFlags & MCI_WAVE_SET_AVGBYTESPERSEC)
484 dprintf_mciwave(stddeb,
485 "WAVE_mciSet // MCI_WAVE_SET_AVGBYTESPERSEC !\n");
486 if (dwFlags & MCI_WAVE_SET_BITSPERSAMPLE)
487 dprintf_mciwave(stddeb,
488 "WAVE_mciSet // MCI_WAVE_SET_BITSPERSAMPLE !\n");
489 if (dwFlags & MCI_WAVE_SET_BLOCKALIGN)
490 dprintf_mciwave(stddeb,"WAVE_mciSet // MCI_WAVE_SET_BLOCKALIGN !\n");
491 if (dwFlags & MCI_WAVE_SET_CHANNELS)
492 dprintf_mciwave(stddeb,"WAVE_mciSet // MCI_WAVE_SET_CHANNELS !\n");
493 if (dwFlags & MCI_WAVE_SET_FORMATTAG)
494 dprintf_mciwave(stddeb,"WAVE_mciSet // MCI_WAVE_SET_FORMATTAG !\n");
495 if (dwFlags & MCI_WAVE_SET_SAMPLESPERSEC)
496 dprintf_mciwave(stddeb,
497 "WAVE_mciSet // MCI_WAVE_SET_SAMPLESPERSEC !\n");
498 return 0;
502 /**************************************************************************
503 * WAVE_mciStatus [internal]
505 static DWORD WAVE_mciStatus(UINT wDevID, DWORD dwFlags, LPMCI_STATUS_PARMS lpParms)
507 dprintf_mciwave(stddeb,
508 "WAVE_mciStatus(%u, %08lX, %p);\n", wDevID, dwFlags, lpParms);
509 if (lpParms == NULL) return MCIERR_INTERNAL;
510 if (dwFlags & MCI_STATUS_ITEM) {
511 switch(lpParms->dwItem) {
512 case MCI_STATUS_CURRENT_TRACK:
513 lpParms->dwReturn = 1;
514 break;
515 case MCI_STATUS_LENGTH:
516 lpParms->dwReturn = 5555;
517 if (dwFlags & MCI_TRACK) {
518 lpParms->dwTrack = 1;
519 lpParms->dwReturn = 2222;
521 break;
522 case MCI_STATUS_MODE:
523 lpParms->dwReturn = MCI_MODE_STOP;
524 break;
525 case MCI_STATUS_MEDIA_PRESENT:
526 dprintf_mciwave(stddeb,"WAVE_mciStatus // MCI_STATUS_MEDIA_PRESENT !\n");
527 lpParms->dwReturn = TRUE;
528 break;
529 case MCI_STATUS_NUMBER_OF_TRACKS:
530 lpParms->dwReturn = 1;
531 break;
532 case MCI_STATUS_POSITION:
533 lpParms->dwReturn = 3333;
534 if (dwFlags & MCI_STATUS_START) {
535 lpParms->dwItem = 1;
537 if (dwFlags & MCI_TRACK) {
538 lpParms->dwTrack = 1;
539 lpParms->dwReturn = 777;
541 break;
542 case MCI_STATUS_READY:
543 dprintf_mciwave(stddeb,"WAVE_mciStatus // MCI_STATUS_READY !\n");
544 lpParms->dwReturn = TRUE;
545 break;
546 case MCI_STATUS_TIME_FORMAT:
547 dprintf_mciwave(stddeb,"WAVE_mciStatus // MCI_STATUS_TIME_FORMAT !\n");
548 lpParms->dwReturn = MCI_FORMAT_MILLISECONDS;
549 break;
550 case MCI_WAVE_INPUT:
551 dprintf_mciwave(stddeb,"WAVE_mciStatus // MCI_WAVE_INPUT !\n");
552 lpParms->dwReturn = 0;
553 break;
554 case MCI_WAVE_OUTPUT:
555 dprintf_mciwave(stddeb,"WAVE_mciStatus // MCI_WAVE_OUTPUT !\n");
556 lpParms->dwReturn = 0;
557 break;
558 case MCI_WAVE_STATUS_AVGBYTESPERSEC:
559 dprintf_mciwave(stddeb,"WAVE_mciStatus // MCI_WAVE_STATUS_AVGBYTESPERSEC !\n");
560 lpParms->dwReturn = 22050;
561 break;
562 case MCI_WAVE_STATUS_BITSPERSAMPLE:
563 dprintf_mciwave(stddeb,"WAVE_mciStatus // MCI_WAVE_STATUS_BITSPERSAMPLE !\n");
564 lpParms->dwReturn = 8;
565 break;
566 case MCI_WAVE_STATUS_BLOCKALIGN:
567 dprintf_mciwave(stddeb,"WAVE_mciStatus // MCI_WAVE_STATUS_BLOCKALIGN !\n");
568 lpParms->dwReturn = 1;
569 break;
570 case MCI_WAVE_STATUS_CHANNELS:
571 dprintf_mciwave(stddeb,"WAVE_mciStatus // MCI_WAVE_STATUS_CHANNELS !\n");
572 lpParms->dwReturn = 1;
573 break;
574 case MCI_WAVE_STATUS_FORMATTAG:
575 dprintf_mciwave(stddeb,"WAVE_mciStatus // MCI_WAVE_FORMATTAG !\n");
576 lpParms->dwReturn = WAVE_FORMAT_PCM;
577 break;
578 case MCI_WAVE_STATUS_LEVEL:
579 dprintf_mciwave(stddeb,"WAVE_mciStatus // MCI_WAVE_STATUS_LEVEL !\n");
580 lpParms->dwReturn = 0xAAAA5555;
581 break;
582 case MCI_WAVE_STATUS_SAMPLESPERSEC:
583 dprintf_mciwave(stddeb,"WAVE_mciStatus // MCI_WAVE_STATUS_SAMPLESPERSEC !\n");
584 lpParms->dwReturn = 22050;
585 break;
586 default:
587 dprintf_mciwave(stddeb,"WAVE_mciStatus // unknown command %08lX !\n", lpParms->dwItem);
588 return MCIERR_UNRECOGNIZED_COMMAND;
591 if (dwFlags & MCI_NOTIFY) {
592 dprintf_mciwave(stddeb,"WAVE_mciStatus // MCI_NOTIFY_SUCCESSFUL %08lX !\n", lpParms->dwCallback);
593 mciDriverNotify((HWND)LOWORD(lpParms->dwCallback),
594 MCIWavDev[wDevID].wNotifyDeviceID, MCI_NOTIFY_SUCCESSFUL);
596 return 0;
599 /**************************************************************************
600 * WAVE_mciGetDevCaps [internal]
602 static DWORD WAVE_mciGetDevCaps(UINT wDevID, DWORD dwFlags,
603 LPMCI_GETDEVCAPS_PARMS lpParms)
605 dprintf_mciwave(stddeb,
606 "WAVE_mciGetDevCaps(%u, %08lX, %p);\n", wDevID, dwFlags, lpParms);
607 if (lpParms == NULL) return MCIERR_INTERNAL;
608 if (dwFlags & MCI_GETDEVCAPS_ITEM) {
609 switch(lpParms->dwItem) {
610 case MCI_GETDEVCAPS_CAN_RECORD:
611 lpParms->dwReturn = TRUE;
612 break;
613 case MCI_GETDEVCAPS_HAS_AUDIO:
614 lpParms->dwReturn = TRUE;
615 break;
616 case MCI_GETDEVCAPS_HAS_VIDEO:
617 lpParms->dwReturn = FALSE;
618 break;
619 case MCI_GETDEVCAPS_DEVICE_TYPE:
620 lpParms->dwReturn = MCI_DEVTYPE_WAVEFORM_AUDIO;
621 break;
622 case MCI_GETDEVCAPS_USES_FILES:
623 lpParms->dwReturn = TRUE;
624 break;
625 case MCI_GETDEVCAPS_COMPOUND_DEVICE:
626 lpParms->dwReturn = TRUE;
627 break;
628 case MCI_GETDEVCAPS_CAN_EJECT:
629 lpParms->dwReturn = FALSE;
630 break;
631 case MCI_GETDEVCAPS_CAN_PLAY:
632 lpParms->dwReturn = TRUE;
633 break;
634 case MCI_GETDEVCAPS_CAN_SAVE:
635 lpParms->dwReturn = TRUE;
636 break;
637 case MCI_WAVE_GETDEVCAPS_INPUTS:
638 lpParms->dwReturn = 1;
639 break;
640 case MCI_WAVE_GETDEVCAPS_OUTPUTS:
641 lpParms->dwReturn = 1;
642 break;
643 default:
644 return MCIERR_UNRECOGNIZED_COMMAND;
647 return 0;
650 /**************************************************************************
651 * WAVE_mciInfo [internal]
653 static DWORD WAVE_mciInfo(UINT wDevID, DWORD dwFlags, LPMCI_INFO_PARMS lpParms)
655 dprintf_mciwave(stddeb,
656 "WAVE_mciInfo(%u, %08lX, %p);\n", wDevID, dwFlags, lpParms);
657 if (lpParms == NULL) return MCIERR_INTERNAL;
658 lpParms->lpstrReturn = NULL;
659 switch(dwFlags) {
660 case MCI_INFO_PRODUCT:
661 lpParms->lpstrReturn = "Linux Sound System 0.5";
662 break;
663 case MCI_INFO_FILE:
664 lpParms->lpstrReturn =
665 (LPSTR)MCIWavDev[wDevID].openParms.lpstrElementName;
666 break;
667 case MCI_WAVE_INPUT:
668 lpParms->lpstrReturn = "Linux Sound System 0.5";
669 break;
670 case MCI_WAVE_OUTPUT:
671 lpParms->lpstrReturn = "Linux Sound System 0.5";
672 break;
673 default:
674 return MCIERR_UNRECOGNIZED_COMMAND;
676 if (lpParms->lpstrReturn != NULL)
677 lpParms->dwRetSize = strlen(lpParms->lpstrReturn);
678 else
679 lpParms->dwRetSize = 0;
680 return 0;
684 /*-----------------------------------------------------------------------*/
687 /**************************************************************************
688 * wodGetDevCaps [internal]
690 static DWORD wodGetDevCaps(WORD wDevID, LPWAVEOUTCAPS lpCaps, DWORD dwSize)
692 int audio;
693 int smplrate;
694 int samplesize = 16;
695 int dsp_stereo = 1;
696 int bytespersmpl;
697 dprintf_mciwave(stddeb,
698 "wodGetDevCaps(%u, %p, %lu);\n", wDevID, lpCaps, dwSize);
699 if (lpCaps == NULL) return MMSYSERR_NOTENABLED;
700 audio = open (SOUND_DEV, O_WRONLY, 0);
701 if (audio == -1) return MMSYSERR_NOTENABLED;
702 #ifdef EMULATE_SB16
703 lpCaps->wMid = 0x0002;
704 lpCaps->wPid = 0x0104;
705 strcpy(lpCaps->szPname, "SB16 Wave Out");
706 #else
707 lpCaps->wMid = 0x00FF; /* Manufac ID */
708 lpCaps->wPid = 0x0001; /* Product ID */
709 strcpy(lpCaps->szPname, "Linux WAVOUT Driver");
710 #endif
711 lpCaps->dwFormats = 0x00000000;
712 lpCaps->dwSupport = WAVECAPS_VOLUME;
713 lpCaps->wChannels = (IOCTL(audio, SNDCTL_DSP_STEREO, dsp_stereo) != 0) ? 1 : 2;
714 if (lpCaps->wChannels > 1) lpCaps->dwSupport |= WAVECAPS_LRVOLUME;
715 bytespersmpl = (IOCTL(audio, SNDCTL_DSP_SAMPLESIZE, samplesize) != 0) ? 1 : 2;
716 smplrate = 44100;
717 if (IOCTL(audio, SNDCTL_DSP_SPEED, smplrate) == 0) {
718 lpCaps->dwFormats |= WAVE_FORMAT_4M08;
719 if (lpCaps->wChannels > 1) lpCaps->dwFormats |= WAVE_FORMAT_4S08;
720 if (bytespersmpl > 1) {
721 lpCaps->dwFormats |= WAVE_FORMAT_4M16;
722 if (lpCaps->wChannels > 1) lpCaps->dwFormats |= WAVE_FORMAT_4S16;
725 smplrate = 22050;
726 if (IOCTL(audio, SNDCTL_DSP_SPEED, smplrate) == 0) {
727 lpCaps->dwFormats |= WAVE_FORMAT_2M08;
728 if (lpCaps->wChannels > 1) lpCaps->dwFormats |= WAVE_FORMAT_2S08;
729 if (bytespersmpl > 1) {
730 lpCaps->dwFormats |= WAVE_FORMAT_2M16;
731 if (lpCaps->wChannels > 1) lpCaps->dwFormats |= WAVE_FORMAT_2S16;
734 smplrate = 11025;
735 if (IOCTL(audio, SNDCTL_DSP_SPEED, smplrate) == 0) {
736 lpCaps->dwFormats |= WAVE_FORMAT_1M08;
737 if (lpCaps->wChannels > 1) lpCaps->dwFormats |= WAVE_FORMAT_1S08;
738 if (bytespersmpl > 1) {
739 lpCaps->dwFormats |= WAVE_FORMAT_1M16;
740 if (lpCaps->wChannels > 1) lpCaps->dwFormats |= WAVE_FORMAT_1S16;
743 close(audio);
744 dprintf_mciwave(stddeb,
745 "wodGetDevCaps // dwFormats = %08lX\n", lpCaps->dwFormats);
746 return MMSYSERR_NOERROR;
750 /**************************************************************************
751 * wodOpen [internal]
753 static DWORD wodOpen(WORD wDevID, LPWAVEOPENDESC lpDesc, DWORD dwFlags)
755 int audio;
756 int abuf_size;
757 int smplrate;
758 int samplesize;
759 int dsp_stereo;
760 LPWAVEFORMAT lpFormat;
762 dprintf_mciwave(stddeb,
763 "wodOpen(%u, %p, %08lX);\n", wDevID, lpDesc, dwFlags);
764 if (lpDesc == NULL) {
765 dprintf_mciwave(stddeb,"Linux 'wodOpen' // Invalid Parameter !\n");
766 return MMSYSERR_INVALPARAM;
768 if (wDevID >= MAX_WAVOUTDRV) {
769 dprintf_mciwave(stddeb,"Linux 'wodOpen' // MAX_WAVOUTDRV reached !\n");
770 return MMSYSERR_ALLOCATED;
772 WOutDev[wDevID].unixdev = 0;
773 audio = open (SOUND_DEV, O_WRONLY, 0);
774 if (audio == -1) {
775 dprintf_mciwave(stddeb,"Linux 'wodOpen' // can't open !\n");
776 return MMSYSERR_NOTENABLED;
778 IOCTL(audio, SNDCTL_DSP_GETBLKSIZE, abuf_size);
779 if (abuf_size < 1024 || abuf_size > 65536) {
780 if (abuf_size == -1)
781 dprintf_mciwave(stddeb,"Linux 'wodOpen' // IOCTL can't 'SNDCTL_DSP_GETBLKSIZE' !\n");
782 else
783 dprintf_mciwave(stddeb,"Linux 'wodOpen' // SNDCTL_DSP_GETBLKSIZE Invalid bufsize !\n");
784 return MMSYSERR_NOTENABLED;
786 WOutDev[wDevID].wFlags = HIWORD(dwFlags & CALLBACK_TYPEMASK);
787 switch(WOutDev[wDevID].wFlags) {
788 case DCB_NULL:
789 dprintf_mciwave(stddeb, "Linux 'wodOpen' // CALLBACK_NULL !\n");
790 break;
791 case DCB_WINDOW:
792 dprintf_mciwave(stddeb, "Linux 'wodOpen' // CALLBACK_WINDOW !\n");
793 break;
794 case DCB_TASK:
795 dprintf_mciwave(stddeb, "Linux 'wodOpen' // CALLBACK_TASK !\n");
796 break;
797 case DCB_FUNCTION:
798 dprintf_mciwave(stddeb, "Linux 'wodOpen' // CALLBACK_FUNCTION !\n");
799 break;
801 WOutDev[wDevID].lpQueueHdr = NULL;
802 WOutDev[wDevID].unixdev = audio;
803 WOutDev[wDevID].dwTotalPlayed = 0;
804 WOutDev[wDevID].bufsize = abuf_size;
805 memcpy(&WOutDev[wDevID].waveDesc, lpDesc, sizeof(WAVEOPENDESC));
806 /* lpFormat = (LPWAVEFORMAT) PTR_SEG_TO_LIN(lpDesc->lpFormat); */
807 lpFormat = lpDesc->lpFormat;
808 if (lpFormat->wFormatTag != WAVE_FORMAT_PCM) {
809 dprintf_mciwave(stddeb,"Linux 'wodOpen' // Bad format %04X !\n",
810 lpFormat->wFormatTag);
811 dprintf_mciwave(stddeb,"Linux 'wodOpen' // Bad nChannels %d !\n",
812 lpFormat->nChannels);
813 dprintf_mciwave(stddeb,"Linux 'wodOpen' // Bad nSamplesPerSec %ld !\n",
814 lpFormat->nSamplesPerSec);
815 return WAVERR_BADFORMAT;
817 memcpy(&WOutDev[wDevID].Format, lpFormat, sizeof(PCMWAVEFORMAT));
818 if (WOutDev[wDevID].Format.wf.nChannels == 0) return WAVERR_BADFORMAT;
819 if (WOutDev[wDevID].Format.wf.nSamplesPerSec == 0) return WAVERR_BADFORMAT;
820 dprintf_mciwave(stddeb,"Linux 'wodOpen' // wBitsPerSample=%u !\n",
821 WOutDev[wDevID].Format.wBitsPerSample);
822 if (WOutDev[wDevID].Format.wBitsPerSample == 0) {
823 WOutDev[wDevID].Format.wBitsPerSample = 8 *
824 (WOutDev[wDevID].Format.wf.nAvgBytesPerSec /
825 WOutDev[wDevID].Format.wf.nSamplesPerSec) /
826 WOutDev[wDevID].Format.wf.nChannels;
828 samplesize = WOutDev[wDevID].Format.wBitsPerSample;
829 smplrate = WOutDev[wDevID].Format.wf.nSamplesPerSec;
830 dsp_stereo = (WOutDev[wDevID].Format.wf.nChannels > 1) ? TRUE : FALSE;
831 IOCTL(audio, SNDCTL_DSP_SPEED, smplrate);
832 IOCTL(audio, SNDCTL_DSP_SAMPLESIZE, samplesize);
833 IOCTL(audio, SNDCTL_DSP_STEREO, dsp_stereo);
834 dprintf_mciwave(stddeb,"Linux 'wodOpen' // wBitsPerSample=%u !\n",
835 WOutDev[wDevID].Format.wBitsPerSample);
836 dprintf_mciwave(stddeb,"Linux 'wodOpen' // nAvgBytesPerSec=%lu !\n",
837 WOutDev[wDevID].Format.wf.nAvgBytesPerSec);
838 dprintf_mciwave(stddeb,"Linux 'wodOpen' // nSamplesPerSec=%lu !\n",
839 WOutDev[wDevID].Format.wf.nSamplesPerSec);
840 dprintf_mciwave(stddeb,"Linux 'wodOpen' // nChannels=%u !\n",
841 WOutDev[wDevID].Format.wf.nChannels);
842 if (WAVE_NotifyClient(wDevID, WOM_OPEN, 0L, 0L) != MMSYSERR_NOERROR) {
843 dprintf_mciwave(stddeb,"Linux 'wodOpen' // can't notify client !\n");
844 return MMSYSERR_INVALPARAM;
846 return MMSYSERR_NOERROR;
849 /**************************************************************************
850 * wodClose [internal]
852 static DWORD wodClose(WORD wDevID)
854 dprintf_mciwave(stddeb,"wodClose(%u);\n", wDevID);
855 if (WOutDev[wDevID].unixdev == 0) {
856 dprintf_mciwave(stddeb,"Linux 'wodClose' // can't close !\n");
857 return MMSYSERR_NOTENABLED;
859 close(WOutDev[wDevID].unixdev);
860 WOutDev[wDevID].unixdev = 0;
861 WOutDev[wDevID].bufsize = 0;
862 WOutDev[wDevID].lpQueueHdr = NULL;
863 if (WAVE_NotifyClient(wDevID, WOM_CLOSE, 0L, 0L) != MMSYSERR_NOERROR) {
864 dprintf_mciwave(stddeb,"Linux 'wodClose' // can't notify client !\n");
865 return MMSYSERR_INVALPARAM;
867 return MMSYSERR_NOERROR;
870 /**************************************************************************
871 * wodWrite [internal]
873 static DWORD wodWrite(WORD wDevID, LPWAVEHDR lpWaveHdr, DWORD dwSize)
875 int count;
876 LPSTR lpData;
877 dprintf_mciwave(stddeb,"wodWrite(%u, %p, %08lX);\n", wDevID, lpWaveHdr, dwSize);
878 if (WOutDev[wDevID].unixdev == 0) {
879 dprintf_mciwave(stddeb,"Linux 'wodWrite' // can't play !\n");
880 return MMSYSERR_NOTENABLED;
882 if (lpWaveHdr->lpData == NULL) return WAVERR_UNPREPARED;
883 if (!(lpWaveHdr->dwFlags & WHDR_PREPARED)) return WAVERR_UNPREPARED;
884 if (lpWaveHdr->dwFlags & WHDR_INQUEUE) return WAVERR_STILLPLAYING;
885 lpWaveHdr->dwFlags &= ~WHDR_DONE;
886 lpWaveHdr->dwFlags |= WHDR_INQUEUE;
887 dprintf_mciwave(stddeb,
888 "wodWrite() // dwBufferLength %lu !\n", lpWaveHdr->dwBufferLength);
889 dprintf_mciwave(stddeb,
890 "wodWrite() // WOutDev[%u].unixdev %u !\n", wDevID, WOutDev[wDevID].unixdev);
891 lpData = PTR_SEG_TO_LIN(lpWaveHdr->lpData);
892 count = write (WOutDev[wDevID].unixdev, lpData, lpWaveHdr->dwBufferLength);
893 dprintf_mciwave(stddeb,
894 "wodWrite() // write returned count %u !\n", count);
895 if (count != lpWaveHdr->dwBufferLength) {
896 dprintf_mciwave(stddeb,"Linux 'wodWrite' // error writting !\n");
897 return MMSYSERR_NOTENABLED;
899 WOutDev[wDevID].dwTotalPlayed += count;
900 lpWaveHdr->dwFlags &= ~WHDR_INQUEUE;
901 lpWaveHdr->dwFlags |= WHDR_DONE;
902 if (WAVE_NotifyClient(wDevID, WOM_DONE, 0L, 0L) != MMSYSERR_NOERROR) {
903 dprintf_mciwave(stddeb,"Linux 'wodWrite' // can't notify client !\n");
904 return MMSYSERR_INVALPARAM;
906 return MMSYSERR_NOERROR;
909 /**************************************************************************
910 * wodPrepare [internal]
912 static DWORD wodPrepare(WORD wDevID, LPWAVEHDR lpWaveHdr, DWORD dwSize)
914 dprintf_mciwave(stddeb,
915 "wodPrepare(%u, %p, %08lX);\n", wDevID, lpWaveHdr, dwSize);
916 if (WOutDev[wDevID].unixdev == 0) {
917 dprintf_mciwave(stddeb,"Linux 'wodPrepare' // can't prepare !\n");
918 return MMSYSERR_NOTENABLED;
920 /* the COOL waveeditor feels much better without this check...
921 * someone please have a look at available documentation
922 if (WOutDev[wDevID].lpQueueHdr != NULL) {
923 dprintf_mciwave(stddeb,"Linux 'wodPrepare' // already prepare !\n");
924 return MMSYSERR_NOTENABLED;
927 WOutDev[wDevID].dwTotalPlayed = 0;
928 WOutDev[wDevID].lpQueueHdr = lpWaveHdr;
929 if (lpWaveHdr->dwFlags & WHDR_INQUEUE) return WAVERR_STILLPLAYING;
930 lpWaveHdr->dwFlags |= WHDR_PREPARED;
931 lpWaveHdr->dwFlags &= ~WHDR_DONE;
932 return MMSYSERR_NOERROR;
935 /**************************************************************************
936 * wodUnprepare [internal]
938 static DWORD wodUnprepare(WORD wDevID, LPWAVEHDR lpWaveHdr, DWORD dwSize)
940 dprintf_mciwave(stddeb,
941 "wodUnprepare(%u, %p, %08lX);\n", wDevID, lpWaveHdr, dwSize);
942 if (WOutDev[wDevID].unixdev == 0) {
943 dprintf_mciwave(stddeb,"Linux 'wodUnprepare' // can't unprepare !\n");
944 return MMSYSERR_NOTENABLED;
946 return MMSYSERR_NOERROR;
949 /**************************************************************************
950 * wodRestart [internal]
952 static DWORD wodRestart(WORD wDevID)
954 dprintf_mciwave(stddeb,"wodRestart(%u);\n", wDevID);
955 if (WOutDev[wDevID].unixdev == 0) {
956 dprintf_mciwave(stddeb,"Linux 'wodRestart' // can't restart !\n");
957 return MMSYSERR_NOTENABLED;
959 return MMSYSERR_NOERROR;
962 /**************************************************************************
963 * wodReset [internal]
965 static DWORD wodReset(WORD wDevID)
967 dprintf_mciwave(stddeb,"wodReset(%u);\n", wDevID);
968 if (WOutDev[wDevID].unixdev == 0) {
969 dprintf_mciwave(stddeb,"Linux 'wodReset' // can't reset !\n");
970 return MMSYSERR_NOTENABLED;
972 return MMSYSERR_NOERROR;
976 /**************************************************************************
977 * wodGetPosition [internal]
979 static DWORD wodGetPosition(WORD wDevID, LPMMTIME lpTime, DWORD uSize)
981 int time;
982 dprintf_mciwave(stddeb,"wodGetPosition(%u, %p, %lu);\n", wDevID, lpTime, uSize);
983 if (WOutDev[wDevID].unixdev == 0) {
984 dprintf_mciwave(stddeb,"Linux 'wodGetPosition' // can't get pos !\n");
985 return MMSYSERR_NOTENABLED;
987 if (lpTime == NULL) return MMSYSERR_INVALPARAM;
988 switch(lpTime->wType) {
989 case TIME_BYTES:
990 lpTime->u.cb = WOutDev[wDevID].dwTotalPlayed;
991 dprintf_mciwave(stddeb,"wodGetPosition // TIME_BYTES=%lu\n", lpTime->u.cb);
992 break;
993 case TIME_SAMPLES:
994 dprintf_mciwave(stddeb,"wodGetPosition // dwTotalPlayed=%lu\n",
995 WOutDev[wDevID].dwTotalPlayed);
996 dprintf_mciwave(stddeb,"wodGetPosition // wBitsPerSample=%u\n",
997 WOutDev[wDevID].Format.wBitsPerSample);
998 lpTime->u.sample = WOutDev[wDevID].dwTotalPlayed * 8 /
999 WOutDev[wDevID].Format.wBitsPerSample;
1000 dprintf_mciwave(stddeb,"wodGetPosition // TIME_SAMPLES=%lu\n", lpTime->u.sample);
1001 break;
1002 case TIME_SMPTE:
1003 time = WOutDev[wDevID].dwTotalPlayed /
1004 (WOutDev[wDevID].Format.wf.nAvgBytesPerSec / 1000);
1005 lpTime->u.smpte.hour = time / 108000;
1006 time -= lpTime->u.smpte.hour * 108000;
1007 lpTime->u.smpte.min = time / 1800;
1008 time -= lpTime->u.smpte.min * 1800;
1009 lpTime->u.smpte.sec = time / 30;
1010 time -= lpTime->u.smpte.sec * 30;
1011 lpTime->u.smpte.frame = time;
1012 lpTime->u.smpte.fps = 30;
1013 dprintf_mciwave(stddeb,
1014 "wodGetPosition // TIME_SMPTE=%02u:%02u:%02u:%02u\n",
1015 lpTime->u.smpte.hour, lpTime->u.smpte.min,
1016 lpTime->u.smpte.sec, lpTime->u.smpte.frame);
1017 break;
1018 default:
1019 dprintf_mciwave(stddeb,"wodGetPosition() format not supported ! use TIME_MS !\n");
1020 lpTime->wType = TIME_MS;
1021 case TIME_MS:
1022 lpTime->u.ms = WOutDev[wDevID].dwTotalPlayed /
1023 (WOutDev[wDevID].Format.wf.nAvgBytesPerSec / 1000);
1024 dprintf_mciwave(stddeb,"wodGetPosition // TIME_MS=%lu\n", lpTime->u.ms);
1025 break;
1027 return MMSYSERR_NOERROR;
1030 /**************************************************************************
1031 * wodGetVolume [internal]
1033 static DWORD wodGetVolume(WORD wDevID, LPDWORD lpdwVol)
1035 int mixer;
1036 int volume, left, right;
1037 dprintf_mciwave(stddeb,"wodGetVolume(%u, %p);\n", wDevID, lpdwVol);
1038 if (lpdwVol == NULL) return MMSYSERR_NOTENABLED;
1039 if ((mixer = open("/dev/mixer", O_RDONLY)) < 0) {
1040 dprintf_mciwave(stddeb, "Linux 'wodGetVolume' // mixer device not available !\n");
1041 return MMSYSERR_NOTENABLED;
1043 if (ioctl(mixer, SOUND_MIXER_READ_PCM, &volume) == -1) {
1044 dprintf_mciwave(stddeb,"Linux 'wodGetVolume' // unable read mixer !\n");
1045 return MMSYSERR_NOTENABLED;
1047 close(mixer);
1048 left = volume & 0x7F;
1049 right = (volume >> 8) & 0x7F;
1050 printf("Linux 'AUX_GetVolume' // left=%d right=%d !\n", left, right);
1051 *lpdwVol = MAKELONG(left << 9, right << 9);
1052 return MMSYSERR_NOERROR;
1056 /**************************************************************************
1057 * wodSetVolume [internal]
1059 static DWORD wodSetVolume(WORD wDevID, DWORD dwParam)
1061 int mixer;
1062 int volume;
1063 dprintf_mciwave(stddeb,"wodSetVolume(%u, %08lX);\n", wDevID, dwParam);
1064 volume = (LOWORD(dwParam) >> 9 & 0x7F) +
1065 ((HIWORD(dwParam) >> 9 & 0x7F) << 8);
1066 if ((mixer = open("/dev/mixer", O_WRONLY)) < 0) {
1067 dprintf_mciwave(stddeb, "Linux 'wodSetVolume' // mixer device not available !\n");
1068 return MMSYSERR_NOTENABLED;
1070 if (ioctl(mixer, SOUND_MIXER_WRITE_PCM, &volume) == -1) {
1071 dprintf_mciwave(stddeb,"Linux 'wodSetVolume' // unable set mixer !\n");
1072 return MMSYSERR_NOTENABLED;
1074 close(mixer);
1075 return MMSYSERR_NOERROR;
1078 #endif /* linux || __FreeBSD__*/
1080 /**************************************************************************
1081 * wodMessage [sample driver]
1083 DWORD wodMessage(WORD wDevID, WORD wMsg, DWORD dwUser,
1084 DWORD dwParam1, DWORD dwParam2)
1086 dprintf_mciwave(stddeb,"wodMessage(%u, %04X, %08lX, %08lX, %08lX);\n",
1087 wDevID, wMsg, dwUser, dwParam1, dwParam2);
1088 #if defined(linux) || defined(__FreeBSD__)
1089 switch(wMsg) {
1090 case WODM_OPEN:
1091 return wodOpen(wDevID, (LPWAVEOPENDESC)PTR_SEG_TO_LIN(dwParam1), dwParam2);
1092 case WODM_CLOSE:
1093 return wodClose(wDevID);
1094 case WODM_WRITE:
1095 return wodWrite(wDevID, (LPWAVEHDR)PTR_SEG_TO_LIN(dwParam1), dwParam2);
1096 case WODM_PAUSE:
1097 return 0L;
1098 case WODM_GETPOS:
1099 return wodGetPosition(wDevID, (LPMMTIME)PTR_SEG_TO_LIN(dwParam1), dwParam2);
1100 case WODM_BREAKLOOP:
1101 return 0L;
1102 case WODM_PREPARE:
1103 return wodPrepare(wDevID, (LPWAVEHDR)PTR_SEG_TO_LIN(dwParam1), dwParam2);
1104 case WODM_UNPREPARE:
1105 return wodUnprepare(wDevID, (LPWAVEHDR)PTR_SEG_TO_LIN(dwParam1), dwParam2);
1106 case WODM_GETDEVCAPS:
1107 return wodGetDevCaps(wDevID, (LPWAVEOUTCAPS)PTR_SEG_TO_LIN(dwParam1), dwParam2);
1108 case WODM_GETNUMDEVS:
1109 return 1L;
1110 case WODM_GETPITCH:
1111 return 0L;
1112 case WODM_SETPITCH:
1113 return 0L;
1114 case WODM_GETPLAYBACKRATE:
1115 return 0L;
1116 case WODM_SETPLAYBACKRATE:
1117 return 0L;
1118 case WODM_GETVOLUME:
1119 return wodGetVolume(wDevID, (LPDWORD)PTR_SEG_TO_LIN(dwParam1));
1120 case WODM_SETVOLUME:
1121 return wodSetVolume(wDevID, dwParam1);
1122 case WODM_RESTART:
1123 return wodRestart(wDevID);
1124 case WODM_RESET:
1125 return wodReset(wDevID);
1126 default:
1127 dprintf_mciwave(stddeb,"wodMessage // unknown message !\n");
1129 return MMSYSERR_NOTSUPPORTED;
1130 #else
1131 return MMSYSERR_NOTENABLED;
1132 #endif
1136 /*-----------------------------------------------------------------------*/
1138 #if defined(linux) || defined(__FreeBSD__)
1140 /**************************************************************************
1141 * widGetDevCaps [internal]
1143 static DWORD widGetDevCaps(WORD wDevID, LPWAVEINCAPS lpCaps, DWORD dwSize)
1145 int audio;
1146 int smplrate;
1147 int samplesize = 16;
1148 int dsp_stereo = 1;
1149 int bytespersmpl;
1150 dprintf_mciwave(stddeb,
1151 "widGetDevCaps(%u, %p, %lu);\n", wDevID, lpCaps, dwSize);
1152 if (lpCaps == NULL) return MMSYSERR_NOTENABLED;
1153 audio = open (SOUND_DEV, O_RDONLY, 0);
1154 if (audio == -1) return MMSYSERR_NOTENABLED;
1155 #ifdef EMULATE_SB16
1156 lpCaps->wMid = 0x0002;
1157 lpCaps->wPid = 0x0004;
1158 strcpy(lpCaps->szPname, "SB16 Wave Out");
1159 #else
1160 lpCaps->wMid = 0x00FF; /* Manufac ID */
1161 lpCaps->wPid = 0x0001; /* Product ID */
1162 strcpy(lpCaps->szPname, "Linux WAVIN Driver");
1163 #endif
1164 lpCaps->dwFormats = 0x00000000;
1165 lpCaps->wChannels = (IOCTL(audio, SNDCTL_DSP_STEREO, dsp_stereo) != 0) ? 1 : 2;
1166 bytespersmpl = (IOCTL(audio, SNDCTL_DSP_SAMPLESIZE, samplesize) != 0) ? 1 : 2;
1167 smplrate = 44100;
1168 if (IOCTL(audio, SNDCTL_DSP_SPEED, smplrate) == 0) {
1169 lpCaps->dwFormats |= WAVE_FORMAT_4M08;
1170 if (lpCaps->wChannels > 1) lpCaps->dwFormats |= WAVE_FORMAT_4S08;
1171 if (bytespersmpl > 1) {
1172 lpCaps->dwFormats |= WAVE_FORMAT_4M16;
1173 if (lpCaps->wChannels > 1) lpCaps->dwFormats |= WAVE_FORMAT_4S16;
1176 smplrate = 22050;
1177 if (IOCTL(audio, SNDCTL_DSP_SPEED, smplrate) == 0) {
1178 lpCaps->dwFormats |= WAVE_FORMAT_2M08;
1179 if (lpCaps->wChannels > 1) lpCaps->dwFormats |= WAVE_FORMAT_2S08;
1180 if (bytespersmpl > 1) {
1181 lpCaps->dwFormats |= WAVE_FORMAT_2M16;
1182 if (lpCaps->wChannels > 1) lpCaps->dwFormats |= WAVE_FORMAT_2S16;
1185 smplrate = 11025;
1186 if (IOCTL(audio, SNDCTL_DSP_SPEED, smplrate) == 0) {
1187 lpCaps->dwFormats |= WAVE_FORMAT_1M08;
1188 if (lpCaps->wChannels > 1) lpCaps->dwFormats |= WAVE_FORMAT_1S08;
1189 if (bytespersmpl > 1) {
1190 lpCaps->dwFormats |= WAVE_FORMAT_1M16;
1191 if (lpCaps->wChannels > 1) lpCaps->dwFormats |= WAVE_FORMAT_1S16;
1194 close(audio);
1195 dprintf_mciwave(stddeb,
1196 "widGetDevCaps // dwFormats = %08lX\n", lpCaps->dwFormats);
1197 return MMSYSERR_NOERROR;
1201 /**************************************************************************
1202 * widOpen [internal]
1204 static DWORD widOpen(WORD wDevID, LPWAVEOPENDESC lpDesc, DWORD dwFlags)
1206 int audio;
1207 int abuf_size;
1208 int smplrate;
1209 int samplesize;
1210 int dsp_stereo;
1211 LPWAVEFORMAT lpFormat;
1212 dprintf_mciwave(stddeb, "widOpen(%u, %p, %08lX);\n", wDevID, lpDesc, dwFlags);
1213 if (lpDesc == NULL) {
1214 dprintf_mciwave(stddeb,"Linux 'widOpen' // Invalid Parameter !\n");
1215 return MMSYSERR_INVALPARAM;
1217 if (wDevID >= MAX_WAVINDRV) {
1218 dprintf_mciwave(stddeb,"Linux 'widOpen' // MAX_WAVINDRV reached !\n");
1219 return MMSYSERR_ALLOCATED;
1221 WInDev[wDevID].unixdev = 0;
1222 audio = open (SOUND_DEV, O_RDONLY, 0);
1223 if (audio == -1) {
1224 dprintf_mciwave(stddeb,"Linux 'widOpen' // can't open !\n");
1225 return MMSYSERR_NOTENABLED;
1227 IOCTL(audio, SNDCTL_DSP_GETBLKSIZE, abuf_size);
1228 if (abuf_size < 1024 || abuf_size > 65536) {
1229 if (abuf_size == -1)
1230 dprintf_mciwave(stddeb,"Linux 'widOpen' // IOCTL can't 'SNDCTL_DSP_GETBLKSIZE' !\n");
1231 else
1232 dprintf_mciwave(stddeb,"Linux 'widOpen' // SNDCTL_DSP_GETBLKSIZE Invalid bufsize !\n");
1233 return MMSYSERR_NOTENABLED;
1235 WInDev[wDevID].wFlags = HIWORD(dwFlags & CALLBACK_TYPEMASK);
1236 switch(WInDev[wDevID].wFlags) {
1237 case DCB_NULL:
1238 dprintf_mciwave(stddeb, "Linux 'widOpen' // CALLBACK_NULL !\n");
1239 break;
1240 case DCB_WINDOW:
1241 dprintf_mciwave(stddeb, "Linux 'widOpen' // CALLBACK_WINDOW !\n");
1242 break;
1243 case DCB_TASK:
1244 dprintf_mciwave(stddeb, "Linux 'widOpen' // CALLBACK_TASK !\n");
1245 break;
1246 case DCB_FUNCTION:
1247 dprintf_mciwave(stddeb, "Linux 'widOpen' // CALLBACK_FUNCTION !\n");
1248 break;
1250 WInDev[wDevID].lpQueueHdr = NULL;
1251 WInDev[wDevID].unixdev = audio;
1252 WInDev[wDevID].bufsize = abuf_size;
1253 WInDev[wDevID].dwTotalRecorded = 0;
1254 memcpy(&WInDev[wDevID].waveDesc, lpDesc, sizeof(WAVEOPENDESC));
1255 lpFormat = lpDesc->lpFormat;
1256 if (lpFormat->wFormatTag != WAVE_FORMAT_PCM) {
1257 dprintf_mciwave(stddeb,"Linux 'widOpen' // Bad format %04X !\n",
1258 lpFormat->wFormatTag);
1259 return WAVERR_BADFORMAT;
1261 memcpy(&WInDev[wDevID].Format, lpFormat, sizeof(PCMWAVEFORMAT));
1262 WInDev[wDevID].Format.wBitsPerSample = 8; /* <-------------- */
1263 if (WInDev[wDevID].Format.wf.nChannels == 0) return WAVERR_BADFORMAT;
1264 if (WInDev[wDevID].Format.wf.nSamplesPerSec == 0) return WAVERR_BADFORMAT;
1265 if (WInDev[wDevID].Format.wBitsPerSample == 0) {
1266 WInDev[wDevID].Format.wBitsPerSample = 8 *
1267 (WInDev[wDevID].Format.wf.nAvgBytesPerSec /
1268 WInDev[wDevID].Format.wf.nSamplesPerSec) /
1269 WInDev[wDevID].Format.wf.nChannels;
1271 samplesize = WInDev[wDevID].Format.wBitsPerSample;
1272 smplrate = WInDev[wDevID].Format.wf.nSamplesPerSec;
1273 dsp_stereo = (WInDev[wDevID].Format.wf.nChannels > 1) ? TRUE : FALSE;
1274 IOCTL(audio, SNDCTL_DSP_SPEED, smplrate);
1275 IOCTL(audio, SNDCTL_DSP_SAMPLESIZE, samplesize);
1276 IOCTL(audio, SNDCTL_DSP_STEREO, dsp_stereo);
1277 dprintf_mciwave(stddeb,"Linux 'widOpen' // wBitsPerSample=%u !\n",
1278 WInDev[wDevID].Format.wBitsPerSample);
1279 dprintf_mciwave(stddeb,"Linux 'widOpen' // nSamplesPerSec=%lu !\n",
1280 WInDev[wDevID].Format.wf.nSamplesPerSec);
1281 dprintf_mciwave(stddeb,"Linux 'widOpen' // nChannels=%u !\n",
1282 WInDev[wDevID].Format.wf.nChannels);
1283 dprintf_mciwave(stddeb,"Linux 'widOpen' // nAvgBytesPerSec=%lu\n",
1284 WInDev[wDevID].Format.wf.nAvgBytesPerSec);
1285 if (WAVE_NotifyClient(wDevID, WIM_OPEN, 0L, 0L) != MMSYSERR_NOERROR) {
1286 dprintf_mciwave(stddeb,"Linux 'widOpen' // can't notify client !\n");
1287 return MMSYSERR_INVALPARAM;
1289 return MMSYSERR_NOERROR;
1292 /**************************************************************************
1293 * widClose [internal]
1295 static DWORD widClose(WORD wDevID)
1297 dprintf_mciwave(stddeb,"widClose(%u);\n", wDevID);
1298 if (WInDev[wDevID].unixdev == 0) {
1299 dprintf_mciwave(stddeb,"Linux 'widClose' // can't close !\n");
1300 return MMSYSERR_NOTENABLED;
1302 close(WInDev[wDevID].unixdev);
1303 WInDev[wDevID].unixdev = 0;
1304 WInDev[wDevID].bufsize = 0;
1305 if (WAVE_NotifyClient(wDevID, WIM_CLOSE, 0L, 0L) != MMSYSERR_NOERROR) {
1306 dprintf_mciwave(stddeb,"Linux 'widClose' // can't notify client !\n");
1307 return MMSYSERR_INVALPARAM;
1309 return MMSYSERR_NOERROR;
1312 /**************************************************************************
1313 * widAddBuffer [internal]
1315 static DWORD widAddBuffer(WORD wDevID, LPWAVEHDR lpWaveHdr, DWORD dwSize)
1317 int count = 1;
1318 LPWAVEHDR lpWIHdr;
1319 dprintf_mciwave(stddeb,
1320 "widAddBuffer(%u, %p, %08lX);\n", wDevID, lpWaveHdr, dwSize);
1321 if (WInDev[wDevID].unixdev == 0) {
1322 dprintf_mciwave(stddeb,"Linux 'widAddBuffer' // can't do it !\n");
1323 return MMSYSERR_NOTENABLED;
1325 if (!(lpWaveHdr->dwFlags & WHDR_PREPARED)) {
1326 dprintf_mciwave(stddeb, "Linux 'widAddBuffer' // never been prepared !\n");
1327 return WAVERR_UNPREPARED;
1329 if (lpWaveHdr->dwFlags & WHDR_INQUEUE) {
1330 dprintf_mciwave(stddeb, "Linux 'widAddBuffer' // header already in use !\n");
1331 return WAVERR_STILLPLAYING;
1333 lpWaveHdr->dwFlags |= WHDR_PREPARED;
1334 lpWaveHdr->dwFlags |= WHDR_INQUEUE;
1335 lpWaveHdr->dwFlags &= ~WHDR_DONE;
1336 lpWaveHdr->dwBytesRecorded = 0;
1337 if (WInDev[wDevID].lpQueueHdr == NULL) {
1338 /* begin the queue with a first header ... */
1339 WInDev[wDevID].lpQueueHdr = lpWaveHdr;
1340 WInDev[wDevID].dwTotalRecorded = 0;
1342 else {
1343 /* added to the queue, except if it's the one just prepared ... */
1344 lpWIHdr = WInDev[wDevID].lpQueueHdr;
1345 while (lpWIHdr->lpNext != NULL) {
1346 lpWIHdr = lpWIHdr->lpNext;
1347 count++;
1349 lpWIHdr->lpNext = lpWaveHdr;
1350 count++;
1352 dprintf_mciwave(stddeb,
1353 "widAddBuffer // buffer added ! (now %u in queue)\n", count);
1354 return MMSYSERR_NOERROR;
1357 /**************************************************************************
1358 * widPrepare [internal]
1360 static DWORD widPrepare(WORD wDevID, LPWAVEHDR lpWaveHdr, DWORD dwSize)
1362 dprintf_mciwave(stddeb,
1363 "widPrepare(%u, %p, %08lX);\n", wDevID, lpWaveHdr, dwSize);
1364 if (WInDev[wDevID].unixdev == 0) {
1365 dprintf_mciwave(stddeb,"Linux 'widPrepare' // can't prepare !\n");
1366 return MMSYSERR_NOTENABLED;
1368 if (WInDev[wDevID].lpQueueHdr != NULL) {
1369 dprintf_mciwave(stddeb,"Linux 'widPrepare' // already prepare !\n");
1370 return WAVERR_BADFORMAT;
1372 if (lpWaveHdr->dwFlags & WHDR_INQUEUE) return WAVERR_STILLPLAYING;
1373 lpWaveHdr->dwFlags |= WHDR_PREPARED;
1374 lpWaveHdr->dwFlags &= ~WHDR_INQUEUE;
1375 lpWaveHdr->dwFlags &= ~WHDR_DONE;
1376 lpWaveHdr->dwBytesRecorded = 0;
1377 dprintf_mciwave(stddeb,"Linux 'widPrepare' // header prepared !\n");
1378 return MMSYSERR_NOERROR;
1381 /**************************************************************************
1382 * widUnprepare [internal]
1384 static DWORD widUnprepare(WORD wDevID, LPWAVEHDR lpWaveHdr, DWORD dwSize)
1386 dprintf_mciwave(stddeb,
1387 "widUnprepare(%u, %p, %08lX);\n", wDevID, lpWaveHdr, dwSize);
1388 if (WInDev[wDevID].unixdev == 0) {
1389 dprintf_mciwave(stddeb,"Linux 'widUnprepare' // can't unprepare !\n");
1390 return MMSYSERR_NOTENABLED;
1392 lpWaveHdr->dwFlags &= ~WHDR_PREPARED;
1393 lpWaveHdr->dwFlags &= ~WHDR_INQUEUE;
1394 lpWaveHdr->dwFlags |= WHDR_DONE;
1395 WInDev[wDevID].lpQueueHdr = NULL;
1396 dprintf_mciwave(stddeb,
1397 "Linux 'widUnprepare' // all headers unprepared !\n");
1398 return MMSYSERR_NOERROR;
1401 /**************************************************************************
1402 * widStart [internal]
1404 static DWORD widStart(WORD wDevID)
1406 int count = 1;
1407 LPWAVEHDR lpWIHdr;
1408 dprintf_mciwave(stddeb,"widStart(%u);\n", wDevID);
1409 if (WInDev[wDevID].unixdev == 0) {
1410 dprintf_mciwave(stddeb, "Linux 'widStart' // can't start recording !\n");
1411 return MMSYSERR_NOTENABLED;
1413 if (WInDev[wDevID].lpQueueHdr == NULL ||
1414 WInDev[wDevID].lpQueueHdr->lpData == NULL) {
1415 dprintf_mciwave(stddeb,"Linux 'widStart' // never been prepared !\n");
1416 return WAVERR_UNPREPARED;
1418 lpWIHdr = WInDev[wDevID].lpQueueHdr;
1419 while(lpWIHdr != NULL) {
1420 lpWIHdr->dwBufferLength &= 0xFFFF;
1421 dprintf_mciwave(stddeb,
1422 "widStart // recording buf#%u=%p size=%lu \n",
1423 count, lpWIHdr->lpData, lpWIHdr->dwBufferLength);
1424 fflush(stddeb);
1425 read (WInDev[wDevID].unixdev,
1426 PTR_SEG_TO_LIN(lpWIHdr->lpData),
1427 lpWIHdr->dwBufferLength);
1428 lpWIHdr->dwBytesRecorded = lpWIHdr->dwBufferLength;
1429 WInDev[wDevID].dwTotalRecorded += lpWIHdr->dwBytesRecorded;
1430 lpWIHdr->dwFlags &= ~WHDR_INQUEUE;
1431 lpWIHdr->dwFlags |= WHDR_DONE;
1432 if (WAVE_NotifyClient(wDevID, WIM_DATA, (DWORD)lpWIHdr, 0L) !=
1433 MMSYSERR_NOERROR) {
1434 dprintf_mciwave(stddeb, "Linux 'widStart' // can't notify client !\n");
1435 return MMSYSERR_INVALPARAM;
1437 lpWIHdr = lpWIHdr->lpNext;
1438 count++;
1440 dprintf_mciwave(stddeb,"widStart // end of recording !\n");
1441 fflush(stdout);
1442 return MMSYSERR_NOERROR;
1445 /**************************************************************************
1446 * widStop [internal]
1448 static DWORD widStop(WORD wDevID)
1450 dprintf_mciwave(stddeb,"widStop(%u);\n", wDevID);
1451 if (WInDev[wDevID].unixdev == 0) {
1452 dprintf_mciwave(stddeb,"Linux 'widStop' // can't stop !\n");
1453 return MMSYSERR_NOTENABLED;
1455 return MMSYSERR_NOERROR;
1458 /**************************************************************************
1459 * widReset [internal]
1461 static DWORD widReset(WORD wDevID)
1463 dprintf_mciwave(stddeb,"widReset(%u);\n", wDevID);
1464 if (WInDev[wDevID].unixdev == 0) {
1465 dprintf_mciwave(stddeb,"Linux 'widReset' // can't reset !\n");
1466 return MMSYSERR_NOTENABLED;
1468 return MMSYSERR_NOERROR;
1471 /**************************************************************************
1472 * widGetPosition [internal]
1474 static DWORD widGetPosition(WORD wDevID, LPMMTIME lpTime, DWORD uSize)
1476 int time;
1478 dprintf_mciwave(stddeb,
1479 "widGetPosition(%u, %p, %lu);\n", wDevID, lpTime, uSize);
1480 if (WInDev[wDevID].unixdev == 0) {
1481 dprintf_mciwave(stddeb,"Linux 'widGetPosition' // can't get pos !\n");
1482 return MMSYSERR_NOTENABLED;
1484 if (lpTime == NULL) return MMSYSERR_INVALPARAM;
1485 dprintf_mciwave(stddeb,"widGetPosition // wType=%04X !\n",
1486 lpTime->wType);
1487 dprintf_mciwave(stddeb,"widGetPosition // wBitsPerSample=%u\n",
1488 WInDev[wDevID].Format.wBitsPerSample);
1489 dprintf_mciwave(stddeb,"widGetPosition // nSamplesPerSec=%lu\n",
1490 WInDev[wDevID].Format.wf.nSamplesPerSec);
1491 dprintf_mciwave(stddeb,"widGetPosition // nChannels=%u\n",
1492 WInDev[wDevID].Format.wf.nChannels);
1493 dprintf_mciwave(stddeb,"widGetPosition // nAvgBytesPerSec=%lu\n",
1494 WInDev[wDevID].Format.wf.nAvgBytesPerSec);
1495 fflush(stddeb);
1496 switch(lpTime->wType) {
1497 case TIME_BYTES:
1498 lpTime->u.cb = WInDev[wDevID].dwTotalRecorded;
1499 dprintf_mciwave(stddeb,
1500 "widGetPosition // TIME_BYTES=%lu\n", lpTime->u.cb);
1501 break;
1502 case TIME_SAMPLES:
1503 lpTime->u.sample = WInDev[wDevID].dwTotalRecorded * 8 /
1504 WInDev[wDevID].Format.wBitsPerSample;
1505 dprintf_mciwave(stddeb,
1506 "widGetPosition // TIME_SAMPLES=%lu\n",
1507 lpTime->u.sample);
1508 break;
1509 case TIME_SMPTE:
1510 time = WInDev[wDevID].dwTotalRecorded /
1511 (WInDev[wDevID].Format.wf.nAvgBytesPerSec / 1000);
1512 lpTime->u.smpte.hour = time / 108000;
1513 time -= lpTime->u.smpte.hour * 108000;
1514 lpTime->u.smpte.min = time / 1800;
1515 time -= lpTime->u.smpte.min * 1800;
1516 lpTime->u.smpte.sec = time / 30;
1517 time -= lpTime->u.smpte.sec * 30;
1518 lpTime->u.smpte.frame = time;
1519 lpTime->u.smpte.fps = 30;
1520 dprintf_mciwave(stddeb,"widGetPosition // TIME_SMPTE=%02u:%02u:%02u:%02u\n",
1521 lpTime->u.smpte.hour, lpTime->u.smpte.min,
1522 lpTime->u.smpte.sec, lpTime->u.smpte.frame);
1523 break;
1524 default:
1525 dprintf_mciwave(stddeb,"widGetPosition() format not supported ! use TIME_MS !\n");
1526 lpTime->wType = TIME_MS;
1527 case TIME_MS:
1528 lpTime->u.ms = WInDev[wDevID].dwTotalRecorded /
1529 (WInDev[wDevID].Format.wf.nAvgBytesPerSec / 1000);
1530 dprintf_mciwave(stddeb,
1531 "widGetPosition // TIME_MS=%lu\n", lpTime->u.ms);
1532 break;
1534 return MMSYSERR_NOERROR;
1537 #endif /* linux || __FreeBSD__ */
1539 /**************************************************************************
1540 * widMessage [sample driver]
1542 DWORD widMessage(WORD wDevID, WORD wMsg, DWORD dwUser,
1543 DWORD dwParam1, DWORD dwParam2)
1545 dprintf_mciwave(stddeb,"widMessage(%u, %04X, %08lX, %08lX, %08lX);\n",
1546 wDevID, wMsg, dwUser, dwParam1, dwParam2);
1547 #if defined(linux) || defined(__FreeBSD__)
1548 switch(wMsg) {
1549 case WIDM_OPEN:
1550 return widOpen(wDevID, (LPWAVEOPENDESC)PTR_SEG_TO_LIN(dwParam1), dwParam2);
1551 case WIDM_CLOSE:
1552 return widClose(wDevID);
1553 case WIDM_ADDBUFFER:
1554 return widAddBuffer(wDevID, (LPWAVEHDR)PTR_SEG_TO_LIN(dwParam1), dwParam2);
1555 case WIDM_PREPARE:
1556 return widPrepare(wDevID, (LPWAVEHDR)PTR_SEG_TO_LIN(dwParam1), dwParam2);
1557 case WIDM_UNPREPARE:
1558 return widUnprepare(wDevID, (LPWAVEHDR)PTR_SEG_TO_LIN(dwParam1), dwParam2);
1559 case WIDM_GETDEVCAPS:
1560 return widGetDevCaps(wDevID, (LPWAVEINCAPS)PTR_SEG_TO_LIN(dwParam1), dwParam2);
1561 case WIDM_GETNUMDEVS:
1562 return 1;
1563 case WIDM_GETPOS:
1564 return widGetPosition(wDevID, (LPMMTIME)PTR_SEG_TO_LIN(dwParam1), dwParam2);
1565 case WIDM_RESET:
1566 return widReset(wDevID);
1567 case WIDM_START:
1568 return widStart(wDevID);
1569 case WIDM_STOP:
1570 return widStop(wDevID);
1571 default:
1572 dprintf_mciwave(stddeb,"widMessage // unknown message !\n");
1574 return MMSYSERR_NOTSUPPORTED;
1575 #else
1576 return MMSYSERR_NOTENABLED;
1577 #endif
1581 /**************************************************************************
1582 * AUDIO_DriverProc [sample driver]
1584 LONG WAVE_DriverProc(DWORD dwDevID, HDRVR16 hDriv, WORD wMsg,
1585 DWORD dwParam1, DWORD dwParam2)
1587 #if defined(linux) || defined(__FreeBSD__)
1588 dprintf_mciwave(stddeb,"WAVE_DriverProc(%08lX, %04X, %04X, %08lX, %08lX)\n",
1589 dwDevID, hDriv, wMsg, dwParam1, dwParam2);
1590 switch(wMsg) {
1591 case DRV_LOAD:
1592 return 1;
1593 case DRV_FREE:
1594 return 1;
1595 case DRV_OPEN:
1596 return 1;
1597 case DRV_CLOSE:
1598 return 1;
1599 case DRV_ENABLE:
1600 return 1;
1601 case DRV_DISABLE:
1602 return 1;
1603 case DRV_QUERYCONFIGURE:
1604 return 1;
1605 case DRV_CONFIGURE:
1606 MessageBox((HWND)NULL, "Sample MultiMedia Linux Driver !",
1607 "MMLinux Driver", MB_OK);
1608 return 1;
1609 case DRV_INSTALL:
1610 return DRVCNF_RESTART;
1611 case DRV_REMOVE:
1612 return DRVCNF_RESTART;
1613 case MCI_OPEN_DRIVER:
1614 case MCI_OPEN:
1615 return WAVE_mciOpen(dwDevID, dwParam1, (LPMCI_WAVE_OPEN_PARMS)PTR_SEG_TO_LIN(dwParam2));
1616 case MCI_CLOSE_DRIVER:
1617 case MCI_CLOSE:
1618 return WAVE_mciClose(dwDevID, dwParam1, (LPMCI_GENERIC_PARMS)PTR_SEG_TO_LIN(dwParam2));
1619 case MCI_PLAY:
1620 return WAVE_mciPlay(dwDevID, dwParam1, (LPMCI_PLAY_PARMS)PTR_SEG_TO_LIN(dwParam2));
1621 case MCI_RECORD:
1622 return WAVE_mciRecord(dwDevID, dwParam1, (LPMCI_RECORD_PARMS)PTR_SEG_TO_LIN(dwParam2));
1623 case MCI_STOP:
1624 return WAVE_mciStop(dwDevID, dwParam1, (LPMCI_GENERIC_PARMS)PTR_SEG_TO_LIN(dwParam2));
1625 case MCI_SET:
1626 return WAVE_mciSet(dwDevID, dwParam1, (LPMCI_SET_PARMS)PTR_SEG_TO_LIN(dwParam2));
1627 case MCI_PAUSE:
1628 return WAVE_mciPause(dwDevID, dwParam1, (LPMCI_GENERIC_PARMS)PTR_SEG_TO_LIN(dwParam2));
1629 case MCI_RESUME:
1630 return WAVE_mciResume(dwDevID, dwParam1, (LPMCI_GENERIC_PARMS)PTR_SEG_TO_LIN(dwParam2));
1631 case MCI_STATUS:
1632 return WAVE_mciStatus(dwDevID, dwParam1, (LPMCI_STATUS_PARMS)PTR_SEG_TO_LIN(dwParam2));
1633 case MCI_GETDEVCAPS:
1634 return WAVE_mciGetDevCaps(dwDevID, dwParam1, (LPMCI_GETDEVCAPS_PARMS)PTR_SEG_TO_LIN(dwParam2));
1635 case MCI_INFO:
1636 return WAVE_mciInfo(dwDevID, dwParam1, (LPMCI_INFO_PARMS)PTR_SEG_TO_LIN(dwParam2));
1637 default:
1638 return DefDriverProc(dwDevID, hDriv, wMsg, dwParam1, dwParam2);
1640 #else
1641 return MMSYSERR_NOTENABLED;
1642 #endif
1646 #endif /* #ifdef BUILTIN_MMSYSTEM */