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