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